r349862 - [analyzer] RetainCount: Suppress retain detection heuristic on some CM methods.

Artem Dergachev via cfe-commits cfe-commits at lists.llvm.org
Thu Dec 20 16:18:58 PST 2018


Author: dergachev
Date: Thu Dec 20 16:18:58 2018
New Revision: 349862

URL: http://llvm.org/viewvc/llvm-project?rev=349862&view=rev
Log:
[analyzer] RetainCount: Suppress retain detection heuristic on some CM methods.

If it ends with "Retain" like CFRetain and returns a CFTypeRef like CFRetain,
then it is not necessarily a CFRetain. But it is indeed true that these two
return something retained.

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

rdar://problem/39390714

Modified:
    cfe/trunk/lib/StaticAnalyzer/Core/RetainSummaryManager.cpp
    cfe/trunk/test/Analysis/retain-release.m

Modified: cfe/trunk/lib/StaticAnalyzer/Core/RetainSummaryManager.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/RetainSummaryManager.cpp?rev=349862&r1=349861&r2=349862&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/RetainSummaryManager.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/RetainSummaryManager.cpp Thu Dec 20 16:18:58 2018
@@ -204,6 +204,11 @@ const RetainSummary *RetainSummaryManage
     AllowAnnotations = false;
     return RetTy->isObjCIdType() ? getUnarySummary(FT, cfmakecollectable)
                                  : getPersistentStopSummary();
+  } else if (FName == "CMBufferQueueDequeueAndRetain" ||
+             FName == "CMBufferQueueDequeueIfDataReadyAndRetain") {
+    // Part of: <rdar://problem/39390714>.
+    return getPersistentSummary(RetEffect::MakeOwned(RetEffect::CF), DoNothing,
+                                DoNothing);
   } else if (FName == "CFPlugInInstanceCreate") {
     return getPersistentSummary(RetEffect::MakeNoRet());
   } else if (FName == "IORegistryEntrySearchCFProperty" ||
@@ -591,6 +596,12 @@ RetainSummaryManager::canEval(const Call
     // Handle: (CF|CG|CV)Retain
     //         CFAutorelease
     // It's okay to be a little sloppy here.
+    if (FName == "CMBufferQueueDequeueAndRetain" ||
+        FName == "CMBufferQueueDequeueIfDataReadyAndRetain") {
+      // Part of: <rdar://problem/39390714>.
+      // These are not retain. They just return something and retain it.
+      return None;
+    }
     if (cocoa::isRefType(ResultTy, "CF", FName) ||
         cocoa::isRefType(ResultTy, "CG", FName) ||
         cocoa::isRefType(ResultTy, "CV", FName))

Modified: cfe/trunk/test/Analysis/retain-release.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/retain-release.m?rev=349862&r1=349861&r2=349862&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/retain-release.m (original)
+++ cfe/trunk/test/Analysis/retain-release.m Thu Dec 20 16:18:58 2018
@@ -1,9 +1,20 @@
 // RUN: rm -f %t.objc.plist %t.objcpp.plist
-// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin10 -analyzer-checker=core,osx.coreFoundation.CFRetainRelease,osx.cocoa.ClassRelease,osx.cocoa.RetainCount -analyzer-store=region -fblocks -verify -Wno-objc-root-class %s -analyzer-output=plist -o %t.objc.plist
-// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin10 -analyzer-checker=core,osx.coreFoundation.CFRetainRelease,osx.cocoa.ClassRelease,osx.cocoa.RetainCount -analyzer-store=region -fblocks -verify -x objective-c++ -std=gnu++98 -Wno-objc-root-class %s -analyzer-output=plist -o %t.objcpp.plist
+// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin10\
+// RUN:     -analyzer-checker=core,osx.coreFoundation.CFRetainRelease\
+// RUN:     -analyzer-checker=osx.cocoa.ClassRelease,osx.cocoa.RetainCount\
+// RUN:     -analyzer-checker=debug.ExprInspection -fblocks -verify %s\
+// RUN:     -Wno-objc-root-class -analyzer-output=plist -o %t.objcpp.plist
+// RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin10\
+// RUN:     -analyzer-checker=core,osx.coreFoundation.CFRetainRelease\
+// RUN:     -analyzer-checker=osx.cocoa.ClassRelease,osx.cocoa.RetainCount\
+// RUN:     -analyzer-checker=debug.ExprInspection -fblocks -verify %s\
+// RUN:     -Wno-objc-root-class -analyzer-output=plist -o %t.objcpp.plist\
+// RUN:     -x objective-c++ -std=gnu++98
 // FIXLATER: cat %t.objc.plist ; FileCheck --input-file=%t.objc.plist %s
 // FIXLATER: cat %t.objcpp.plist ; FileCheck --input-file=%t.objcpp.plist %s
 
+void clang_analyzer_eval(int);
+
 #if __has_feature(attribute_ns_returns_retained)
 #define NS_RETURNS_RETAINED __attribute__((ns_returns_retained))
 #endif
@@ -495,6 +506,21 @@ void testLeakWithReturnsRetainedOutParam
   // status is returned.
 }
 
+typedef CFTypeRef CMBufferRef;
+
+typedef CFTypeRef *CMBufferQueueRef;
+
+CMBufferRef CMBufferQueueDequeueAndRetain(CMBufferQueueRef);
+
+void testCMBufferQueueDequeueAndRetain(CMBufferQueueRef queue) {
+  CMBufferRef buffer = CMBufferQueueDequeueAndRetain(queue); // expected-warning{{Potential leak of an object stored into 'buffer'}}
+  // There's a state split due to the eagerly-assume behavior.
+  // The point here is that we don't treat CMBufferQueueDequeueAndRetain
+  // as some sort of CFRetain() that returns its argument.
+  clang_analyzer_eval((CMFooRef)buffer == (CMFooRef)queue); // expected-warning{{TRUE}}
+                                                            // expected-warning at -1{{FALSE}}
+}
+
 // Test retain/release checker with CFString and CFMutableArray.
 void f11() {
   // Create the array.




More information about the cfe-commits mailing list