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@-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@-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@-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@-1{{Calling 'generateArray'}} + // expected-note@-2{{Returning from 'generateArray'}} + // expected-note@-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@-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@-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@-1 {{Method returns an instance of MyObj with a +1 retain count}} // expected-note@-2 {{Calling 'initX'}} // expected-note@-3 {{Returning from 'initX'}} - // expected-note@-4 {{Object leaked: allocated object is not referenced later in this execution path and has a retain count of +1}} + // expected-note@-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@-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}} }; } _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits