r330375 - [analyzer] RetainCount: Accept more "safe" CFRetain wrappers.

Artem Dergachev via cfe-commits cfe-commits at lists.llvm.org
Thu Apr 19 16:00:22 PDT 2018


Author: dergachev
Date: Thu Apr 19 16:00:22 2018
New Revision: 330375

URL: http://llvm.org/viewvc/llvm-project?rev=330375&view=rev
Log:
[analyzer] RetainCount: Accept more "safe" CFRetain wrappers.

r315736 added support for the misplaced CF_RETURNS_RETAINED annotation on
CFRetain() wrappers. It works by trusting the function's name (seeing if it
confirms to the CoreFoundation naming convention) rather than the annotation.

There are more false positives caused by users using a different naming
convention, namely starting the function name with "retain" or "release"
rather than suffixing it with "retain" or "release" respectively.

Because this isn't according to the naming convention, these functions
are usually inlined and the annotation is therefore ignored, which is correct.
But sometimes we run out of inlining stack depth and the function is
evaluated conservatively and then the annotation is trusted.

Add support for the "alternative" naming convention and test the situation when
we're running out of inlining stack depth.

rdar://problem/18270122

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

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

Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp?rev=330375&r1=330374&r2=330375&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp Thu Apr 19 16:00:22 2018
@@ -883,21 +883,22 @@ RetainSummaryManager::getPersistentSumma
 //===----------------------------------------------------------------------===//
 
 static bool isRetain(const FunctionDecl *FD, StringRef FName) {
-  return FName.endswith("Retain");
+  return FName.startswith_lower("retain") || FName.endswith_lower("retain");
 }
 
 static bool isRelease(const FunctionDecl *FD, StringRef FName) {
-  return FName.endswith("Release");
+  return FName.startswith_lower("release") || FName.endswith_lower("release");
 }
 
 static bool isAutorelease(const FunctionDecl *FD, StringRef FName) {
-  return FName.endswith("Autorelease");
+  return FName.startswith_lower("autorelease") ||
+         FName.endswith_lower("autorelease");
 }
 
 static bool isMakeCollectable(const FunctionDecl *FD, StringRef FName) {
   // FIXME: Remove FunctionDecl parameter.
   // FIXME: Is it really okay if MakeCollectable isn't a suffix?
-  return FName.find("MakeCollectable") != StringRef::npos;
+  return FName.find_lower("MakeCollectable") != StringRef::npos;
 }
 
 static ArgEffect getStopTrackingHardEquivalent(ArgEffect E) {

Modified: cfe/trunk/test/Analysis/retain-release-safe.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/retain-release-safe.c?rev=330375&r1=330374&r2=330375&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/retain-release-safe.c (original)
+++ cfe/trunk/test/Analysis/retain-release-safe.c Thu Apr 19 16:00:22 2018
@@ -1,4 +1,5 @@
 // RUN: %clang_analyze_cc1 -analyzer-checker=core,osx.coreFoundation.CFRetainRelease,osx.cocoa.RetainCount -verify %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,osx.coreFoundation.CFRetainRelease,osx.cocoa.RetainCount -analyzer-inline-max-stack-depth=0 -verify %s
 
 #pragma clang arc_cf_code_audited begin
 typedef const void * CFTypeRef;
@@ -35,6 +36,19 @@ void SafeCFRelease(CFTypeRef CF_CONSUMED
     CFRelease(cf); // no-warning (when inlined)
 }
 
+// The same thing, just with a different naming style.
+CFTypeRef retainCFType(CFTypeRef cf) CF_RETURNS_RETAINED {
+  if (cf) {
+    return CFRetain(cf);
+  }
+  return cf;
+}
+
+void releaseCFType(CFTypeRef CF_CONSUMED cf) {
+  if (cf)
+    CFRelease(cf); // no-warning (when inlined)
+}
+
 void escape(CFTypeRef cf);
 
 void makeSureTestsWork() {
@@ -70,3 +84,10 @@ void falseReleaseNotOwned(CFTypeRef cf)
   SafeCFRelease(cf);
   SafeCFRelease(cf); // no-warning after inlining this.
 }
+
+void testTheOtherNamingConvention(CFTypeRef cf) {
+  retainCFType(cf);
+  retainCFType(cf);
+  releaseCFType(cf);
+  releaseCFType(cf); // no-warning
+}




More information about the cfe-commits mailing list