r347943 - [analyzer] Add the type of the leaked object to the diagnostic message
George Karpenkov via cfe-commits
cfe-commits at lists.llvm.org
Thu Nov 29 18:17:44 PST 2018
Author: george.karpenkov
Date: Thu Nov 29 18:17:44 2018
New Revision: 347943
URL: http://llvm.org/viewvc/llvm-project?rev=347943&view=rev
Log:
[analyzer] Add the type of the leaked object to the diagnostic message
If the object is a temporary, and there is no variable it binds to,
let's at least print out the object name in order to help differentiate
it from other temporaries.
rdar://45175098
Differential Revision: https://reviews.llvm.org/D55033
Modified:
cfe/trunk/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountDiagnostics.cpp
cfe/trunk/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountDiagnostics.h
cfe/trunk/test/Analysis/Inputs/expected-plists/objc-arc.m.plist
cfe/trunk/test/Analysis/Inputs/expected-plists/retain-release-path-notes.m.plist
cfe/trunk/test/Analysis/objc-radar17039661.m
cfe/trunk/test/Analysis/osobject-retain-release.cpp
cfe/trunk/test/Analysis/retain-release-path-notes.m
cfe/trunk/test/Analysis/retaincountchecker-compoundregion.m
Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountDiagnostics.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountDiagnostics.cpp?rev=347943&r1=347942&r2=347943&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountDiagnostics.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountDiagnostics.cpp Thu Nov 29 18:17:44 2018
@@ -28,6 +28,17 @@ static bool isNumericLiteralExpression(c
isa<CXXBoolLiteralExpr>(E);
}
+/// If type represents a pointer to CXXRecordDecl,
+/// and is not a typedef, return the decl name.
+/// Otherwise, return the serialization of type.
+static StringRef getPrettyTypeName(QualType QT) {
+ QualType PT = QT->getPointeeType();
+ if (!PT.isNull() && !QT->getAs<TypedefType>())
+ if (const auto *RD = PT->getAsCXXRecordDecl())
+ return RD->getName();
+ return QT.getAsString();
+}
+
/// Write information about the type state change to {@code os},
/// return whether the note should be generated.
static bool shouldGenerateNote(llvm::raw_string_ostream &os,
@@ -193,7 +204,7 @@ CFRefReportVisitor::VisitNode(const Expl
<< Sym->getType().getAsString() << " with a ";
} else if (CurrV.getObjKind() == RetEffect::OS) {
os << " returns an OSObject of type "
- << Sym->getType().getAsString() << " with a ";
+ << getPrettyTypeName(Sym->getType()) << " with a ";
} else if (CurrV.getObjKind() == RetEffect::Generalized) {
os << " returns an object of type " << Sym->getType().getAsString()
<< " with a ";
@@ -432,7 +443,7 @@ CFRefLeakReportVisitor::getEndPath(BugRe
if (RegionDescription) {
os << "object allocated and stored into '" << *RegionDescription << '\'';
} else {
- os << "allocated object";
+ os << "allocated object of type " << getPrettyTypeName(Sym->getType());
}
// Get the retain count.
@@ -472,10 +483,10 @@ CFRefLeakReportVisitor::getEndPath(BugRe
" Foundation";
}
}
- }
- else
+ } else {
os << " is not referenced later in this execution path and has a retain "
"count of +" << RV->getCount();
+ }
return std::make_shared<PathDiagnosticEventPiece>(L, os.str());
}
@@ -555,6 +566,10 @@ void CFRefLeakReport::createDescription(
FullSourceLoc SL(AllocStmt->getBeginLoc(), Ctx.getSourceManager());
os << " (allocated on line " << SL.getSpellingLineNumber() << ")";
}
+ } else {
+
+ // If we can't figure out the name, just supply the type information.
+ os << " of type " << getPrettyTypeName(Sym->getType());
}
}
Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountDiagnostics.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountDiagnostics.h?rev=347943&r1=347942&r2=347943&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountDiagnostics.h (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountDiagnostics.h Thu Nov 29 18:17:44 2018
@@ -141,12 +141,14 @@ public:
};
class CFRefReport : public BugReport {
+protected:
+ SymbolRef Sym;
public:
CFRefReport(CFRefBug &D, const LangOptions &LOpts,
const SummaryLogTy &Log, ExplodedNode *n, SymbolRef sym,
bool registerVisitor = true)
- : BugReport(D, D.getDescription(), n) {
+ : BugReport(D, D.getDescription(), n), Sym(sym) {
if (registerVisitor)
addVisitor(llvm::make_unique<CFRefReportVisitor>(sym, Log));
}
Modified: cfe/trunk/test/Analysis/Inputs/expected-plists/objc-arc.m.plist
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/Inputs/expected-plists/objc-arc.m.plist?rev=347943&r1=347942&r2=347943&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/Inputs/expected-plists/objc-arc.m.plist (original)
+++ cfe/trunk/test/Analysis/Inputs/expected-plists/objc-arc.m.plist Thu Nov 29 18:17:44 2018
@@ -1727,12 +1727,12 @@
</dict>
<key>depth</key><integer>0</integer>
<key>extended_message</key>
- <string>Object leaked: allocated object is not referenced later in this execution path and has a retain count of +1</string>
+ <string>Object leaked: allocated object of type CFStringRef is not referenced later in this execution path and has a retain count of +1</string>
<key>message</key>
- <string>Object leaked: allocated object is not referenced later in this execution path and has a retain count of +1</string>
+ <string>Object leaked: allocated object of type CFStringRef 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</string>
+ <key>description</key><string>Potential leak of an object of type CFStringRef</string>
<key>category</key><string>Memory (Core Foundation/Objective-C)</string>
<key>type</key><string>Leak</string>
<key>check_name</key><string>osx.cocoa.RetainCount</string>
Modified: cfe/trunk/test/Analysis/Inputs/expected-plists/retain-release-path-notes.m.plist
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/Inputs/expected-plists/retain-release-path-notes.m.plist?rev=347943&r1=347942&r2=347943&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/Inputs/expected-plists/retain-release-path-notes.m.plist (original)
+++ cfe/trunk/test/Analysis/Inputs/expected-plists/retain-release-path-notes.m.plist Thu Nov 29 18:17:44 2018
@@ -3834,12 +3834,12 @@
</array>
<key>depth</key><integer>0</integer>
<key>extended_message</key>
- <string>Object leaked: allocated object is not referenced later in this execution path and has a retain count of +1</string>
+ <string>Object leaked: allocated object of type MyObj * is not referenced later in this execution path and has a retain count of +1</string>
<key>message</key>
- <string>Object leaked: allocated object is not referenced later in this execution path and has a retain count of +1</string>
+ <string>Object leaked: allocated object of type MyObj * 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</string>
+ <key>description</key><string>Potential leak of an object of type MyObj *</string>
<key>category</key><string>Memory (Core Foundation/Objective-C)</string>
<key>type</key><string>Leak</string>
<key>check_name</key><string>osx.cocoa.RetainCount</string>
Modified: cfe/trunk/test/Analysis/objc-radar17039661.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/objc-radar17039661.m?rev=347943&r1=347942&r2=347943&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/objc-radar17039661.m (original)
+++ cfe/trunk/test/Analysis/objc-radar17039661.m Thu Nov 29 18:17:44 2018
@@ -1315,12 +1315,12 @@ void runTest() {
// CHECK: </array>
// CHECK: <key>depth</key><integer>4</integer>
// CHECK: <key>extended_message</key>
-// CHECK: <string>Object leaked: allocated object is not referenced later in this execution path and has a retain count of +1</string>
+// CHECK: <string>Object leaked: allocated object of type NSNumber * is not referenced later in this execution path and has a retain count of +1</string>
// CHECK: <key>message</key>
-// CHECK: <string>Object leaked: allocated object is not referenced later in this execution path and has a retain count of +1</string>
+// CHECK: <string>Object leaked: allocated object of type NSNumber * is not referenced later in this execution path and has a retain count of +1</string>
// CHECK: </dict>
// CHECK: </array>
-// CHECK: <key>description</key><string>Potential leak of an object</string>
+// CHECK: <key>description</key><string>Potential leak of an object of type NSNumber *</string>
// CHECK: <key>category</key><string>Memory (Core Foundation/Objective-C)</string>
// CHECK: <key>type</key><string>Leak</string>
// CHECK: <key>location</key>
Modified: cfe/trunk/test/Analysis/osobject-retain-release.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/osobject-retain-release.cpp?rev=347943&r1=347942&r2=347943&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/osobject-retain-release.cpp (original)
+++ cfe/trunk/test/Analysis/osobject-retain-release.cpp Thu Nov 29 18:17:44 2018
@@ -61,13 +61,13 @@ void check_custom_iterator_rule(OSArray
}
void check_no_invalidation() {
- OSArray *arr = OSArray::withCapacity(10); // expected-note{{Call to function 'withCapacity' returns an OSObject of type struct OSArray * with a +1 retain count}}
+ OSArray *arr = OSArray::withCapacity(10); // expected-note{{Call to function 'withCapacity' returns an OSObject of type OSArray with a +1 retain count}}
OtherStruct::doNothingToArray(arr);
} // expected-warning{{Potential leak of an object stored into 'arr'}}
// expected-note at -1{{Object leaked}}
void check_no_invalidation_other_struct() {
- OSArray *arr = OSArray::withCapacity(10); // expected-note{{Call to function 'withCapacity' returns an OSObject of type struct OSArray * with a +1 retain count}}
+ OSArray *arr = OSArray::withCapacity(10); // expected-note{{Call to function 'withCapacity' returns an OSObject of type OSArray with a +1 retain count}}
OtherStruct other(arr); // expected-warning{{Potential leak}}
// expected-note at -1{{Object leaked}}
}
@@ -94,7 +94,8 @@ struct ArrayOwner : public OSObject {
};
OSArray *generateArray() {
- return OSArray::withCapacity(10); // expected-note{{Call to function 'withCapacity' returns an OSObject of type struct OSArray * with a +1 retain count}}
+ return OSArray::withCapacity(10); // expected-note{{Call to function 'withCapacity' returns an OSObject of type OSArray with a +1 retain count}}
+ // expected-note at -1{{Call to function 'withCapacity' returns an OSObject of type OSArray with a +1 retain count}}
}
unsigned int check_leak_good_error_message() {
@@ -109,7 +110,10 @@ unsigned int check_leak_good_error_messa
}
unsigned int check_leak_msg_temporary() {
- return generateArray()->getCount();
+ return generateArray()->getCount(); // expected-warning{{Potential leak of an object}}
+ // expected-note at -1{{Calling 'generateArray'}}
+ // expected-note at -2{{Returning from 'generateArray'}}
+ // expected-note at -3{{Object leaked: allocated object of type OSArray is not referenced later in this execution path and has a retain count of +1}}
}
void check_confusing_getters() {
@@ -178,14 +182,14 @@ void check_dynamic_cast_null_check() {
}
void use_after_release() {
- OSArray *arr = OSArray::withCapacity(10); // expected-note{{Call to function 'withCapacity' returns an OSObject of type struct OSArray * with a +1 retain count}}
+ OSArray *arr = OSArray::withCapacity(10); // expected-note{{Call to function 'withCapacity' returns an OSObject of type OSArray with a +1 retain count}}
arr->release(); // expected-note{{Object released}}
arr->getCount(); // expected-warning{{Reference-counted object is used after it is released}}
// expected-note at -1{{Reference-counted object is used after it is released}}
}
void potential_leak() {
- OSArray *arr = OSArray::withCapacity(10); // expected-note{{Call to function 'withCapacity' returns an OSObject of type struct OSArray * with a +1 retain count}}
+ OSArray *arr = OSArray::withCapacity(10); // expected-note{{Call to function 'withCapacity' returns an OSObject of type OSArray with a +1 retain count}}
arr->retain(); // expected-note{{Reference count incremented. The object now has a +2 retain count}}
arr->release(); // expected-note{{Reference count decremented. The object now has a +1 retain count}}
arr->getCount();
@@ -236,7 +240,7 @@ unsigned int no_warn_ok_release(ArrayOwn
}
unsigned int warn_on_overrelease_with_unknown_source(ArrayOwner *owner) {
- OSArray *arr = owner->getArraySourceUnknown(); // expected-note{{function call returns an OSObject of type struct OSArray * with a +0 retain count}}
+ OSArray *arr = owner->getArraySourceUnknown(); // expected-note{{function call returns an OSObject of type OSArray with a +0 retain count}}
arr->release(); // expected-warning{{Incorrect decrement of the reference count of an object that is not owned at this point by the caller}}
// expected-note at -1{{Incorrect decrement of the reference count of an object that is not owned at this point by the caller}}
return arr->getCount();
Modified: cfe/trunk/test/Analysis/retain-release-path-notes.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/retain-release-path-notes.m?rev=347943&r1=347942&r2=347943&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/retain-release-path-notes.m (original)
+++ cfe/trunk/test/Analysis/retain-release-path-notes.m Thu Nov 29 18:17:44 2018
@@ -227,7 +227,7 @@ static int Cond;
// expected-note at -1 {{Method returns an instance of MyObj with a +1 retain count}}
// expected-note at -2 {{Calling 'initX'}}
// expected-note at -3 {{Returning from 'initX'}}
- // expected-note at -4 {{Object leaked: allocated object is not referenced later in this execution path and has a retain count of +1}}
+ // expected-note at -4 {{Object leaked: allocated object of type MyObj * is not referenced later in this execution path and has a retain count of +1}}
// initI is inlined because the allocation happens within initY
id y = [[MyObj alloc] initY];
// expected-note at -1 {{Calling 'initY'}}
Modified: cfe/trunk/test/Analysis/retaincountchecker-compoundregion.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/retaincountchecker-compoundregion.m?rev=347943&r1=347942&r2=347943&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/retaincountchecker-compoundregion.m (original)
+++ cfe/trunk/test/Analysis/retaincountchecker-compoundregion.m Thu Nov 29 18:17:44 2018
@@ -19,7 +19,7 @@ void foo(CFAllocatorRef allocator) {
int width = 0;
int height = 0;
CFTypeRef* values = (CFTypeRef[]){
- CFNumberCreate(allocator, kCFNumberSInt32Type, &width), //expected-warning-re{{Potential leak of an object{{$}}}}
- CFNumberCreate(allocator, kCFNumberSInt32Type, &height), //expected-warning-re{{Potential leak of an object{{$}}}}
+ CFNumberCreate(allocator, kCFNumberSInt32Type, &width), //expected-warning{{Potential leak of an object of type CFNumberRef}}
+ CFNumberCreate(allocator, kCFNumberSInt32Type, &height), //expected-warning{{Potential leak of an object of type CFNumberRef}}
};
}
More information about the cfe-commits
mailing list