r347944 - [analyzer] Print a fully qualified name for functions in RetainCountChecker diagnostics

George Karpenkov via cfe-commits cfe-commits at lists.llvm.org
Thu Nov 29 18:17:57 PST 2018


Author: george.karpenkov
Date: Thu Nov 29 18:17:57 2018
New Revision: 347944

URL: http://llvm.org/viewvc/llvm-project?rev=347944&view=rev
Log:
[analyzer] Print a fully qualified name for functions in RetainCountChecker diagnostics

Attempt to get a fully qualified name from AST if an SVal corresponding
to the object is not available.

Differential Revision: https://reviews.llvm.org/D55034

Modified:
    cfe/trunk/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountDiagnostics.cpp
    cfe/trunk/test/Analysis/osobject-retain-release.cpp

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=347944&r1=347943&r2=347944&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountDiagnostics.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountDiagnostics.cpp Thu Nov 29 18:17:57 2018
@@ -173,10 +173,19 @@ CFRefReportVisitor::VisitNode(const Expl
       os << "Object loaded from instance variable";
     } else {
       if (const CallExpr *CE = dyn_cast<CallExpr>(S)) {
-        // Get the name of the callee (if it is available).
+        // Get the name of the callee (if it is available)
+        // from the tracked SVal.
         SVal X = CurrSt->getSValAsScalarOrLoc(CE->getCallee(), LCtx);
-        if (const FunctionDecl *FD = X.getAsFunctionDecl()) {
-          os << "Call to function '" << *FD << '\'';
+        const FunctionDecl *FD = X.getAsFunctionDecl();
+
+        // If failed, try to get it from AST.
+        if (!FD)
+          FD = dyn_cast<FunctionDecl>(CE->getCalleeDecl());
+
+        if (const auto *MD = dyn_cast<CXXMethodDecl>(CE->getCalleeDecl())) {
+          os << "Call to method '" << MD->getQualifiedNameAsString() << '\'';
+        } else if (FD) {
+          os << "Call to function '" << FD->getQualifiedNameAsString() << '\'';
         } else {
           os << "function call";
         }

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=347944&r1=347943&r2=347944&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/osobject-retain-release.cpp (original)
+++ cfe/trunk/test/Analysis/osobject-retain-release.cpp Thu Nov 29 18:17:57 2018
@@ -60,14 +60,19 @@ void check_custom_iterator_rule(OSArray
   it->release();
 }
 
+void check_iterator_leak(OSArray *arr) {
+  arr->getIterator(); // expected-note{{Call to method 'OSArray::getIterator' returns an OSObject of type struct OSIterator * with a +1 retain count}}
+} // expected-note{{Object leaked: allocated object of type struct OSIterator * is not referenced later}}
+  // expected-warning at -1{{Potential leak of an object of type struct OSIterator *}}n this execution path and has a retain count of +1}}
+
 void check_no_invalidation() {
-  OSArray *arr = OSArray::withCapacity(10); // expected-note{{Call to function 'withCapacity' returns an OSObject of type OSArray with a +1 retain count}}
+  OSArray *arr = OSArray::withCapacity(10); // expected-note{{Call to method 'OSArray::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 OSArray with a +1 retain count}}
+  OSArray *arr = OSArray::withCapacity(10); // expected-note{{Call to method 'OSArray::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,8 +99,8 @@ struct ArrayOwner : public OSObject {
 };
 
 OSArray *generateArray() {
-  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}}
+  return OSArray::withCapacity(10); // expected-note{{Call to method 'withCapacity' returns an OSObject of type OSArray with a +1 retain count}}
+                                    // expected-note at -1{{Call to method 'withCapacity' returns an OSObject of type OSArray with a +1 retain count}}
 }
 
 unsigned int check_leak_good_error_message() {
@@ -164,7 +169,7 @@ unsigned int check_dynamic_cast_no_null_
 }
 
 void check_dynamic_cast_null_branch(OSObject *obj) {
-  OSArray *arr1 = OSArray::withCapacity(10); // expected-note{{Call to function 'withCapacity' returns an OSObject}}
+  OSArray *arr1 = OSArray::withCapacity(10); // expected-note{{Call to method 'OSArray::withCapacity' returns an OSObject}}
   OSArray *arr = OSDynamicCast(OSArray, obj);
   if (!arr) // expected-note{{Taking true branch}}
     return; // expected-warning{{Potential leak of an object stored into 'arr1'}}
@@ -173,7 +178,7 @@ void check_dynamic_cast_null_branch(OSOb
 }
 
 void check_dynamic_cast_null_check() {
-  OSArray *arr = OSDynamicCast(OSArray, OSObject::generateObject(1)); // expected-note{{Call to function 'generateObject' returns an OSObject}}
+  OSArray *arr = OSDynamicCast(OSArray, OSObject::generateObject(1)); // expected-note{{Call to method 'OSObject::generateObject' returns an OSObject}}
     // expected-warning at -1{{Potential leak of an object}}
     // expected-note at -2{{Object leaked}}
   if (!arr)
@@ -182,14 +187,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 OSArray with a +1 retain count}}
+  OSArray *arr = OSArray::withCapacity(10); // expected-note{{Call to method '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 OSArray with a +1 retain count}}
+  OSArray *arr = OSArray::withCapacity(10); // expected-note{{Call to method '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();
@@ -240,7 +245,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 OSArray with a +0 retain count}}
+  OSArray *arr = owner->getArraySourceUnknown(); // expected-note{{Call to method 'ArrayOwner::getArraySourceUnknown' 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();




More information about the cfe-commits mailing list