vsavchenko updated this revision to Diff 338835.
vsavchenko added a comment.
Update comments
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D100839/new/
https://reviews.llvm.org/D100839
Files:
clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountDiagnostics.cpp
clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountDiagnostics.h
clang/test/Analysis/Inputs/expected-plists/edges-new.mm.plist
clang/test/Analysis/Inputs/expected-plists/retain-release-path-notes.m.plist
clang/test/Analysis/Inputs/expected-plists/retain-release.m.objc.plist
clang/test/Analysis/Inputs/expected-plists/retain-release.m.objcpp.plist
clang/test/Analysis/osobject-retain-release.cpp
clang/test/Analysis/retain-release-path-notes.m
clang/test/Analysis/retain-release.m
Index: clang/test/Analysis/retain-release.m
===================================================================
--- clang/test/Analysis/retain-release.m
+++ clang/test/Analysis/retain-release.m
@@ -2282,7 +2282,7 @@
void testAutoreleaseReturnsInput() {
extern CFTypeRef CFCreateSomething();
- CFTypeRef obj = CFCreateSomething(); // expected-warning{{Potential leak of an object stored into 'obj'}}
+ CFTypeRef obj = CFCreateSomething(); // expected-warning{{Potential leak of an object stored into 'second'}}
CFTypeRef second = CFAutorelease(obj);
CFRetain(second);
}
@@ -2302,7 +2302,7 @@
}
void autoreleaseReturningTypedObject() {
- CFArrayRef arr = CFArrayCreateMutable(0, 10, &kCFTypeArrayCallBacks); // expected-warning{{Potential leak of an object stored into 'arr'}}
+ CFArrayRef arr = CFArrayCreateMutable(0, 10, &kCFTypeArrayCallBacks); // expected-warning{{Potential leak of an object stored into 'alias'}}
CFArrayRef alias = (CFArrayRef)CFAutorelease((CFTypeRef)arr);
CFRetain(alias);
}
Index: clang/test/Analysis/retain-release-path-notes.m
===================================================================
--- clang/test/Analysis/retain-release-path-notes.m
+++ clang/test/Analysis/retain-release-path-notes.m
@@ -212,7 +212,7 @@
}
-(id)initY {
- self = [super init]; //expected-note {{Method returns an instance of MyObj with a +1 retain count}}
+ self = [super init]; // expected-note 4 {{Method returns an instance of MyObj with a +1 retain count}}
return self;
}
@@ -327,5 +327,54 @@
@end
+int seed();
+@interface LeakReassignmentTests : MyObj
+@end
+
+@implementation LeakReassignmentTests
++(void)testLeakAliasSimple {
+ id Original = [[MyObj alloc] initY]; // expected-note {{Calling 'initY'}}
+ // expected-note@-1 {{Returning from 'initY'}}
+ id New = Original;
+ Original = [[MyObj alloc] initZ];
+ (void)New;
+ [Original release]; // expected-warning {{Potential leak of an object stored into 'New'}}
+ // expected-note@-1 {{Object leaked: object allocated and stored into 'New' is not referenced later in this execution path and has a retain count of +1}}
+}
+
++(void)testLeakAliasChain {
+ id Original = [[MyObj alloc] initY]; // expected-note {{Calling 'initY'}}
+ // expected-note@-1 {{Returning from 'initY'}}
+ id Intermediate = Original;
+ id New = Intermediate;
+ Original = [[MyObj alloc] initZ];
+ (void)New;
+ [Original release]; // expected-warning {{Potential leak of an object stored into 'New'}}
+ // expected-note@-1 {{Object leaked: object allocated and stored into 'New' is not referenced later in this execution path and has a retain count of +1}}
+}
+
++(void)log:(id)Obj with:(int)Num {
+ Num *= 42;
+ if (Obj )
+ Num /= 2;
+}
+
++(int)calculate {
+ int x = 10;
+ int y = 25;
+ x += y * x + seed();
+ return y - x * y;
+}
++(void)testLeakAliasDeathInExpr {
+ id Original = [[MyObj alloc] initY]; // expected-note {{Calling 'initY'}}
+ // expected-note@-1 {{Returning from 'initY'}}
+ id New = Original;
+ Original = [[MyObj alloc] initZ];
+ [self log:New with:[self calculate]];
+ [Original release]; // expected-warning {{Potential leak of an object stored into 'New'}}
+ // expected-note@-1 {{Object leaked: object allocated and stored into 'New' is not referenced later in this execution path and has a retain count of +1}}
+}
+
+@end
Index: clang/test/Analysis/osobject-retain-release.cpp
===================================================================
--- clang/test/Analysis/osobject-retain-release.cpp
+++ clang/test/Analysis/osobject-retain-release.cpp
@@ -641,7 +641,7 @@
OSObject *obj = new OSObject; // expected-note{{Operator 'new' returns an OSObject of type 'OSObject' with a +1 retain count}}
{
OSObjectPtr p(obj); // expected-note{{Calling constructor for 'smart_ptr<OSObject>'}}
- // expected-note@-1{{Returning from constructor for 'smart_ptr<OSObject>'}}
+ // expected-note@-1{{Returning from constructor for 'smart_ptr<OSObject>'}}
// expected-note@os_smart_ptr.h:13{{Field 'pointer' is non-null}}
// expected-note@os_smart_ptr.h:13{{Taking true branch}}
// expected-note@os_smart_ptr.h:14{{Calling 'smart_ptr::_retain'}}
@@ -653,9 +653,9 @@
// expected-note@os_smart_ptr.h:36{{Calling 'smart_ptr::_release'}}
// expected-note@os_smart_ptr.h:76{{Reference count decremented. The object now has a +1 retain count}}
// expected-note@os_smart_ptr.h:36{{Returning from 'smart_ptr::_release'}}
- // expected-note@-6{{Returning from '~smart_ptr'}}
-} // expected-warning{{Potential leak of an object stored into 'obj'}}
-// expected-note@-1{{Object leaked: object allocated and stored into 'obj' is not referenced later in this execution path and has a retain count of +1}}
+ // expected-note@-6{{Returning from '~smart_ptr'}}
+} // expected-warning{{Potential leak of an object stored into 'p'}}
+// expected-note@-1{{Object leaked: object allocated and stored into 'p' is not referenced later in this execution path and has a retain count of +1}}
void test_smart_ptr_no_leak() {
OSObject *obj = new OSObject;
Index: clang/test/Analysis/Inputs/expected-plists/retain-release.m.objcpp.plist
===================================================================
--- clang/test/Analysis/Inputs/expected-plists/retain-release.m.objcpp.plist
+++ clang/test/Analysis/Inputs/expected-plists/retain-release.m.objcpp.plist
@@ -25476,12 +25476,12 @@
</dict>
<key>depth</key><integer>0</integer>
<key>extended_message</key>
- <string>Object leaked: object allocated and stored into 'obj' is not referenced later in this execution path and has a retain count of +1</string>
+ <string>Object leaked: object allocated and stored into 'second' is not referenced later in this execution path and has a retain count of +1</string>
<key>message</key>
- <string>Object leaked: object allocated and stored into 'obj' is not referenced later in this execution path and has a retain count of +1</string>
+ <string>Object leaked: object allocated and stored into 'second' is not referenced later in this execution path and has a retain count of +1</string>
</dict>
</array>
- <key>description</key><string>Potential leak of an object stored into 'obj'</string>
+ <key>description</key><string>Potential leak of an object stored into 'second'</string>
<key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
<key>type</key><string>Leak</string>
<key>check_name</key><string>osx.cocoa.RetainCount</string>
@@ -25734,12 +25734,12 @@
</dict>
<key>depth</key><integer>0</integer>
<key>extended_message</key>
- <string>Object leaked: object allocated and stored into 'arr' is not referenced later in this execution path and has a retain count of +1</string>
+ <string>Object leaked: object allocated and stored into 'alias' is not referenced later in this execution path and has a retain count of +1</string>
<key>message</key>
- <string>Object leaked: object allocated and stored into 'arr' is not referenced later in this execution path and has a retain count of +1</string>
+ <string>Object leaked: object allocated and stored into 'alias' is not referenced later in this execution path and has a retain count of +1</string>
</dict>
</array>
- <key>description</key><string>Potential leak of an object stored into 'arr'</string>
+ <key>description</key><string>Potential leak of an object stored into 'alias'</string>
<key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
<key>type</key><string>Leak</string>
<key>check_name</key><string>osx.cocoa.RetainCount</string>
Index: clang/test/Analysis/Inputs/expected-plists/retain-release.m.objc.plist
===================================================================
--- clang/test/Analysis/Inputs/expected-plists/retain-release.m.objc.plist
+++ clang/test/Analysis/Inputs/expected-plists/retain-release.m.objc.plist
@@ -25407,12 +25407,12 @@
</dict>
<key>depth</key><integer>0</integer>
<key>extended_message</key>
- <string>Object leaked: object allocated and stored into 'obj' is not referenced later in this execution path and has a retain count of +1</string>
+ <string>Object leaked: object allocated and stored into 'second' is not referenced later in this execution path and has a retain count of +1</string>
<key>message</key>
- <string>Object leaked: object allocated and stored into 'obj' is not referenced later in this execution path and has a retain count of +1</string>
+ <string>Object leaked: object allocated and stored into 'second' is not referenced later in this execution path and has a retain count of +1</string>
</dict>
</array>
- <key>description</key><string>Potential leak of an object stored into 'obj'</string>
+ <key>description</key><string>Potential leak of an object stored into 'second'</string>
<key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
<key>type</key><string>Leak</string>
<key>check_name</key><string>osx.cocoa.RetainCount</string>
@@ -25665,12 +25665,12 @@
</dict>
<key>depth</key><integer>0</integer>
<key>extended_message</key>
- <string>Object leaked: object allocated and stored into 'arr' is not referenced later in this execution path and has a retain count of +1</string>
+ <string>Object leaked: object allocated and stored into 'alias' is not referenced later in this execution path and has a retain count of +1</string>
<key>message</key>
- <string>Object leaked: object allocated and stored into 'arr' is not referenced later in this execution path and has a retain count of +1</string>
+ <string>Object leaked: object allocated and stored into 'alias' is not referenced later in this execution path and has a retain count of +1</string>
</dict>
</array>
- <key>description</key><string>Potential leak of an object stored into 'arr'</string>
+ <key>description</key><string>Potential leak of an object stored into 'alias'</string>
<key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
<key>type</key><string>Leak</string>
<key>check_name</key><string>osx.cocoa.RetainCount</string>
Index: clang/test/Analysis/Inputs/expected-plists/retain-release-path-notes.m.plist
===================================================================
--- clang/test/Analysis/Inputs/expected-plists/retain-release-path-notes.m.plist
+++ clang/test/Analysis/Inputs/expected-plists/retain-release-path-notes.m.plist
@@ -5012,6 +5012,1030 @@
</array>
</dict>
</dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>337</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>337</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>337</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>337</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>337</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>337</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>337</integer>
+ <key>col</key><integer>37</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Calling 'initY'</string>
+ <key>message</key>
+ <string>Calling 'initY'</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>214</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Entered call from 'testLeakAliasSimple'</string>
+ <key>message</key>
+ <string>Entered call from 'testLeakAliasSimple'</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>214</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>214</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>215</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>215</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>215</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>215</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>215</integer>
+ <key>col</key><integer>21</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Method returns an instance of MyObj with a +1 retain count</string>
+ <key>message</key>
+ <string>Method returns an instance of MyObj with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>215</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>215</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>216</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>216</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>337</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>337</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>337</integer>
+ <key>col</key><integer>37</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Returning from 'initY'</string>
+ <key>message</key>
+ <string>Returning from 'initY'</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>337</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>337</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>337</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>337</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>337</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>337</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>342</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>342</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>342</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>342</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>342</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: object allocated and stored into 'New' is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: object allocated and stored into 'New' is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object stored into 'New'</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>c6578d694dd90a2f586f52c9b53042c3</string>
+ <key>issue_context_kind</key><string>Objective-C method</string>
+ <key>issue_context</key><string>testLeakAliasSimple</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>342</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>214</integer>
+ <integer>215</integer>
+ <integer>216</integer>
+ <integer>219</integer>
+ <integer>220</integer>
+ <integer>221</integer>
+ <integer>336</integer>
+ <integer>337</integer>
+ <integer>339</integer>
+ <integer>340</integer>
+ <integer>341</integer>
+ <integer>342</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>347</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>347</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>347</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>347</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>347</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>347</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>347</integer>
+ <key>col</key><integer>37</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Calling 'initY'</string>
+ <key>message</key>
+ <string>Calling 'initY'</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>214</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Entered call from 'testLeakAliasChain'</string>
+ <key>message</key>
+ <string>Entered call from 'testLeakAliasChain'</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>214</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>214</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>215</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>215</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>215</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>215</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>215</integer>
+ <key>col</key><integer>21</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Method returns an instance of MyObj with a +1 retain count</string>
+ <key>message</key>
+ <string>Method returns an instance of MyObj with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>215</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>215</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>216</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>216</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>347</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>347</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>347</integer>
+ <key>col</key><integer>37</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Returning from 'initY'</string>
+ <key>message</key>
+ <string>Returning from 'initY'</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>347</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>347</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>347</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>347</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>347</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>347</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>353</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>353</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>353</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>353</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>353</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: object allocated and stored into 'New' is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: object allocated and stored into 'New' is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object stored into 'New'</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>076457f7cf482449386f129554f48f68</string>
+ <key>issue_context_kind</key><string>Objective-C method</string>
+ <key>issue_context</key><string>testLeakAliasChain</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>353</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>214</integer>
+ <integer>215</integer>
+ <integer>216</integer>
+ <integer>219</integer>
+ <integer>220</integer>
+ <integer>221</integer>
+ <integer>346</integer>
+ <integer>347</integer>
+ <integer>349</integer>
+ <integer>350</integer>
+ <integer>351</integer>
+ <integer>352</integer>
+ <integer>353</integer>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>path</key>
+ <array>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>371</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>371</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>371</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>371</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>371</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>371</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>371</integer>
+ <key>col</key><integer>37</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Calling 'initY'</string>
+ <key>message</key>
+ <string>Calling 'initY'</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>214</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Entered call from 'testLeakAliasDeathInExpr'</string>
+ <key>message</key>
+ <string>Entered call from 'testLeakAliasDeathInExpr'</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>214</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>214</integer>
+ <key>col</key><integer>1</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>215</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>215</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>215</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>215</integer>
+ <key>col</key><integer>10</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>215</integer>
+ <key>col</key><integer>21</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>1</integer>
+ <key>extended_message</key>
+ <string>Method returns an instance of MyObj with a +1 retain count</string>
+ <key>message</key>
+ <string>Method returns an instance of MyObj with a +1 retain count</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>215</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>215</integer>
+ <key>col</key><integer>6</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>216</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>216</integer>
+ <key>col</key><integer>8</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>371</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>371</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>371</integer>
+ <key>col</key><integer>37</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Returning from 'initY'</string>
+ <key>message</key>
+ <string>Returning from 'initY'</string>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>371</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>371</integer>
+ <key>col</key><integer>17</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>371</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>371</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>control</string>
+ <key>edges</key>
+ <array>
+ <dict>
+ <key>start</key>
+ <array>
+ <dict>
+ <key>line</key><integer>371</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>371</integer>
+ <key>col</key><integer>4</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ <key>end</key>
+ <array>
+ <dict>
+ <key>line</key><integer>376</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>376</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </dict>
+ </array>
+ </dict>
+ <dict>
+ <key>kind</key><string>event</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>376</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ranges</key>
+ <array>
+ <array>
+ <dict>
+ <key>line</key><integer>376</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <dict>
+ <key>line</key><integer>376</integer>
+ <key>col</key><integer>20</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ </array>
+ </array>
+ <key>depth</key><integer>0</integer>
+ <key>extended_message</key>
+ <string>Object leaked: object allocated and stored into 'New' is not referenced later in this execution path and has a retain count of +1</string>
+ <key>message</key>
+ <string>Object leaked: object allocated and stored into 'New' is not referenced later in this execution path and has a retain count of +1</string>
+ </dict>
+ </array>
+ <key>description</key><string>Potential leak of an object stored into 'New'</string>
+ <key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
+ <key>type</key><string>Leak</string>
+ <key>check_name</key><string>osx.cocoa.RetainCount</string>
+ <!-- This hash is experimental and going to change! -->
+ <key>issue_hash_content_of_line_in_context</key><string>1ead75ff85eb09fa93374d0083f531e5</string>
+ <key>issue_context_kind</key><string>Objective-C method</string>
+ <key>issue_context</key><string>testLeakAliasDeathInExpr</string>
+ <key>issue_hash_function_offset</key><string>1</string>
+ <key>location</key>
+ <dict>
+ <key>line</key><integer>376</integer>
+ <key>col</key><integer>3</integer>
+ <key>file</key><integer>0</integer>
+ </dict>
+ <key>ExecutedLines</key>
+ <dict>
+ <key>0</key>
+ <array>
+ <integer>214</integer>
+ <integer>215</integer>
+ <integer>216</integer>
+ <integer>219</integer>
+ <integer>220</integer>
+ <integer>221</integer>
+ <integer>357</integer>
+ <integer>358</integer>
+ <integer>359</integer>
+ <integer>360</integer>
+ <integer>363</integer>
+ <integer>364</integer>
+ <integer>365</integer>
+ <integer>366</integer>
+ <integer>367</integer>
+ <integer>370</integer>
+ <integer>371</integer>
+ <integer>373</integer>
+ <integer>374</integer>
+ <integer>375</integer>
+ <integer>376</integer>
+ </array>
+ </dict>
+ </dict>
</array>
<key>files</key>
<array>
Index: clang/test/Analysis/Inputs/expected-plists/edges-new.mm.plist
===================================================================
--- clang/test/Analysis/Inputs/expected-plists/edges-new.mm.plist
+++ clang/test/Analysis/Inputs/expected-plists/edges-new.mm.plist
@@ -21946,12 +21946,12 @@
</dict>
<key>depth</key><integer>0</integer>
<key>extended_message</key>
- <string>Object leaked: object allocated and stored into 'foo' is not referenced later in this execution path and has a retain count of +1</string>
+ <string>Object leaked: object allocated and stored into 'garply' is not referenced later in this execution path and has a retain count of +1</string>
<key>message</key>
- <string>Object leaked: object allocated and stored into 'foo' is not referenced later in this execution path and has a retain count of +1</string>
+ <string>Object leaked: object allocated and stored into 'garply' is not referenced later in this execution path and has a retain count of +1</string>
</dict>
</array>
- <key>description</key><string>Potential leak of an object stored into 'foo'</string>
+ <key>description</key><string>Potential leak of an object stored into 'garply'</string>
<key>category</key><string>Memory (Core Foundation/Objective-C/OSObject)</string>
<key>type</key><string>Leak</string>
<key>check_name</key><string>osx.cocoa.RetainCount</string>
Index: clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountDiagnostics.h
===================================================================
--- clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountDiagnostics.h
+++ clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountDiagnostics.h
@@ -68,17 +68,20 @@
};
class RefLeakReport : public RefCountReport {
- const MemRegion* AllocBinding;
- const Stmt *AllocStmt;
+ const MemRegion *AllocFirstBinding = nullptr;
+ const MemRegion *AllocBindingToReport = nullptr;
+ const Stmt *AllocStmt = nullptr;
PathDiagnosticLocation Location;
// Finds the function declaration where a leak warning for the parameter
// 'sym' should be raised.
- void deriveParamLocation(CheckerContext &Ctx, SymbolRef sym);
- // Finds the location where a leak warning for 'sym' should be raised.
- void deriveAllocLocation(CheckerContext &Ctx, SymbolRef sym);
+ void deriveParamLocation(CheckerContext &Ctx);
+ // Finds the location where the leaking object is allocated.
+ void deriveAllocLocation(CheckerContext &Ctx);
// Produces description of a leak warning which is printed on the console.
void createDescription(CheckerContext &Ctx);
+ // Finds the binding that we should use in a leak warning.
+ void findBindingToReport(CheckerContext &Ctx, ExplodedNode *Node);
public:
RefLeakReport(const RefCountBug &D, const LangOptions &LOpts, ExplodedNode *n,
Index: clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountDiagnostics.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountDiagnostics.cpp
+++ clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountDiagnostics.cpp
@@ -13,6 +13,8 @@
#include "RetainCountDiagnostics.h"
#include "RetainCountChecker.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallVector.h"
using namespace clang;
using namespace ento;
@@ -337,15 +339,15 @@
class RefLeakReportVisitor : public RefCountReportVisitor {
public:
- RefLeakReportVisitor(SymbolRef Sym, const MemRegion *FirstBinding)
- : RefCountReportVisitor(Sym), FirstBinding(FirstBinding) {}
+ RefLeakReportVisitor(SymbolRef Sym, const MemRegion *LastBinding)
+ : RefCountReportVisitor(Sym), LastBinding(LastBinding) {}
PathDiagnosticPieceRef getEndPath(BugReporterContext &BRC,
const ExplodedNode *N,
PathSensitiveBugReport &BR) override;
private:
- const MemRegion *FirstBinding;
+ const MemRegion *LastBinding;
};
} // end namespace retaincountchecker
@@ -614,6 +616,41 @@
return None;
}
+using Bindings = llvm::SmallVector<const MemRegion *, 4>;
+
+class VarBindingsCollector : public StoreManager::BindingsHandler {
+ SymbolRef Sym;
+ Bindings &Result;
+
+public:
+ VarBindingsCollector(SymbolRef Sym, Bindings &ToFill)
+ : Sym(Sym), Result(ToFill) {}
+
+ bool HandleBinding(StoreManager &SMgr, Store Store, const MemRegion *R,
+ SVal Val) override {
+ SymbolRef SymV = Val.getAsLocSymbol();
+ if (!SymV || SymV != Sym)
+ return true;
+
+ if (isa<NonParamVarRegion>(R))
+ Result.push_back(R);
+
+ return true;
+ }
+};
+
+Bindings getAllVarBindingsForSymbol(ProgramStateManager &Manager,
+ const ExplodedNode *Node, SymbolRef Sym) {
+ Bindings Result;
+ VarBindingsCollector Collector{Sym, Result};
+ while (Result.empty() && Node) {
+ Manager.iterBindings(Node->getState(), Collector);
+ Node = Node->getFirstPred();
+ }
+
+ return Result;
+}
+
namespace {
// Find the first node in the current function context that referred to the
// tracked symbol and the memory location that value was stored to. Note, the
@@ -740,7 +777,7 @@
os << "Object leaked: ";
- Optional<std::string> RegionDescription = describeRegion(FirstBinding);
+ Optional<std::string> RegionDescription = describeRegion(LastBinding);
if (RegionDescription) {
os << "object allocated and stored into '" << *RegionDescription << '\'';
} else {
@@ -749,7 +786,7 @@
}
// Get the retain count.
- const RefVal* RV = getRefBinding(EndN->getState(), Sym);
+ const RefVal *RV = getRefBinding(EndN->getState(), Sym);
assert(RV);
if (RV->getKind() == RefVal::ErrorLeakReturned) {
@@ -790,14 +827,15 @@
" Foundation";
} else if (RV->getObjKind() == ObjKind::OS) {
std::string FuncName = FD->getNameAsString();
- os << "whose name ('" << FuncName
- << "') starts with '" << StringRef(FuncName).substr(0, 3) << "'";
+ os << "whose name ('" << FuncName << "') starts with '"
+ << StringRef(FuncName).substr(0, 3) << "'";
}
}
}
} else {
os << " is not referenced later in this execution path and has a retain "
- "count of +" << RV->getCount();
+ "count of +"
+ << RV->getCount();
}
return std::make_shared<PathDiagnosticEventPiece>(L, os.str());
@@ -819,16 +857,16 @@
addVisitor(std::make_unique<RefCountReportVisitor>(sym));
}
-void RefLeakReport::deriveParamLocation(CheckerContext &Ctx, SymbolRef sym) {
- const SourceManager& SMgr = Ctx.getSourceManager();
+void RefLeakReport::deriveParamLocation(CheckerContext &Ctx) {
+ const SourceManager &SMgr = Ctx.getSourceManager();
- if (!sym->getOriginRegion())
+ if (!Sym->getOriginRegion())
return;
- auto *Region = dyn_cast<DeclRegion>(sym->getOriginRegion());
+ auto *Region = dyn_cast<DeclRegion>(Sym->getOriginRegion());
if (Region) {
const Decl *PDecl = Region->getDecl();
- if (PDecl && isa<ParmVarDecl>(PDecl)) {
+ if (isa_and_nonnull<ParmVarDecl>(PDecl)) {
PathDiagnosticLocation ParamLocation =
PathDiagnosticLocation::create(PDecl, SMgr);
Location = ParamLocation;
@@ -838,8 +876,7 @@
}
}
-void RefLeakReport::deriveAllocLocation(CheckerContext &Ctx,
- SymbolRef sym) {
+void RefLeakReport::deriveAllocLocation(CheckerContext &Ctx) {
// Most bug reports are cached at the location where they occurred.
// With leaks, we want to unique them by the location where they were
// allocated, and only report a single path. To do this, we need to find
@@ -850,13 +887,13 @@
// same SourceLocation.
const ExplodedNode *AllocNode = nullptr;
- const SourceManager& SMgr = Ctx.getSourceManager();
+ const SourceManager &SMgr = Ctx.getSourceManager();
AllocationInfo AllocI =
- GetAllocationSite(Ctx.getStateManager(), getErrorNode(), sym);
+ GetAllocationSite(Ctx.getStateManager(), getErrorNode(), Sym);
AllocNode = AllocI.N;
- AllocBinding = AllocI.R;
+ AllocFirstBinding = AllocI.R;
markInteresting(AllocI.InterestingMethodContext);
// Get the SourceLocation for the allocation site.
@@ -866,13 +903,12 @@
AllocStmt = AllocNode->getStmtForDiagnostics();
if (!AllocStmt) {
- AllocBinding = nullptr;
+ AllocFirstBinding = nullptr;
return;
}
- PathDiagnosticLocation AllocLocation =
- PathDiagnosticLocation::createBegin(AllocStmt, SMgr,
- AllocNode->getLocationContext());
+ PathDiagnosticLocation AllocLocation = PathDiagnosticLocation::createBegin(
+ AllocStmt, SMgr, AllocNode->getLocationContext());
Location = AllocLocation;
// Set uniqieing info, which will be used for unique the bug reports. The
@@ -887,7 +923,8 @@
llvm::raw_string_ostream os(Description);
os << "Potential leak of an object";
- Optional<std::string> RegionDescription = describeRegion(AllocBinding);
+ Optional<std::string> RegionDescription =
+ describeRegion(AllocBindingToReport);
if (RegionDescription) {
os << " stored into '" << *RegionDescription << '\'';
} else {
@@ -897,16 +934,59 @@
}
}
+void RefLeakReport::findBindingToReport(CheckerContext &Ctx,
+ ExplodedNode *Node) {
+ if (!AllocFirstBinding)
+ // If we don't have any bindings, we won't be able to find any
+ // better binding to report.
+ return;
+
+ // If the original region still contains the leaking symbol...
+ if (Node->getState()->getSVal(AllocFirstBinding).getAsSymbol() == Sym) {
+ // ...it is the best binding to report.
+ AllocBindingToReport = AllocFirstBinding;
+ return;
+ }
+
+ // At this point, we know that the original region doesn't contain the leaking
+ // when the actual leak happens. It means that it can be confusing for the
+ // user to see such description in the message.
+ //
+ // Let's consider the following example:
+ // Object *Original = allocate(...);
+ // Object *New = Original;
+ // Original = allocate(...);
+ // Original->release();
+ //
+ // Complaining about a leaking object "stored into Original" might cause a
+ // rightful confusion because 'Original' is actually released.
+ // We should complain about 'New' instead.
+ Bindings AllVarBindings =
+ getAllVarBindingsForSymbol(Ctx.getStateManager(), Node, Sym);
+
+ // While looking for the last var bindings, we can still find
+ // `AllocFirstBinding` to be one of them. In situations like this,
+ // it would still be the easiest case to explain to our users.
+ if (!AllVarBindings.empty() &&
+ llvm::count(AllVarBindings, AllocFirstBinding) == 0)
+ // Let's pick one of them at random (if there is something to pick from).
+ AllocBindingToReport = AllVarBindings[0];
+ else
+ AllocBindingToReport = AllocFirstBinding;
+}
+
RefLeakReport::RefLeakReport(const RefCountBug &D, const LangOptions &LOpts,
ExplodedNode *N, SymbolRef Sym,
CheckerContext &Ctx)
: RefCountReport(D, LOpts, N, Sym, /*isLeak=*/true) {
- deriveAllocLocation(Ctx, Sym);
- if (!AllocBinding)
- deriveParamLocation(Ctx, Sym);
+ deriveAllocLocation(Ctx);
+ findBindingToReport(Ctx, N);
+
+ if (!AllocFirstBinding)
+ deriveParamLocation(Ctx);
createDescription(Ctx);
- addVisitor(std::make_unique<RefLeakReportVisitor>(Sym, AllocBinding));
+ addVisitor(std::make_unique<RefLeakReportVisitor>(Sym, AllocBindingToReport));
}
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits