[analyzer] Don't let cf_audited_transfer override CFRetain semantics.
authorJordan Rose <jordan_rose@apple.com>
Mon, 4 Mar 2013 23:21:32 +0000 (23:21 +0000)
committerJordan Rose <jordan_rose@apple.com>
Mon, 4 Mar 2013 23:21:32 +0000 (23:21 +0000)
We weren't treating a cf_audited_transfer CFRetain as returning +1 because
its name doesn't contain "Create" or "Copy". Oops! Fortunately, the
standard definitions of these functions are not marked audited.

<rdar://problem/13339601>

llvm-svn: 176463

clang/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp
clang/test/Analysis/retain-release-cf-audited.m [new file with mode: 0644]

index 3edc997..856463a 100644 (file)
@@ -1133,12 +1133,7 @@ RetainSummaryManager::getFunctionSummary(const FunctionDecl *FD) {
     if (S)
       break;
 
-    if (RetTy->isPointerType()) {
-      if (FD->getAttr<CFAuditedTransferAttr>()) {
-        S = getCFCreateGetRuleSummary(FD);
-        break;
-      }
-      
+    if (RetTy->isPointerType()) {      
       // For CoreFoundation ('CF') types.
       if (cocoa::isRefType(RetTy, "CF", FName)) {
         if (isRetain(FD, FName))
@@ -1169,6 +1164,11 @@ RetainSummaryManager::getFunctionSummary(const FunctionDecl *FD) {
         break;
       }
 
+      if (FD->getAttr<CFAuditedTransferAttr>()) {
+        S = getCFCreateGetRuleSummary(FD);
+        break;
+      }
+
       break;
     }
 
diff --git a/clang/test/Analysis/retain-release-cf-audited.m b/clang/test/Analysis/retain-release-cf-audited.m
new file mode 100644 (file)
index 0000000..c89172f
--- /dev/null
@@ -0,0 +1,33 @@
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -analyze -analyzer-checker=core,osx.cocoa.RetainCount -verify %s
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -analyze -analyzer-checker=core,osx.cocoa.RetainCount -verify %s -x objective-c++
+
+// The special thing about this file is that CFRetain and CFRelease are marked
+// as cf_audited_transfer.
+
+#pragma clang arc_cf_code_audited begin
+typedef const void * CFTypeRef;
+extern CFTypeRef CFRetain(CFTypeRef cf);
+extern void CFRelease(CFTypeRef cf);
+
+extern CFTypeRef CFCreateSomethingAudited();
+#pragma clang arc_cf_code_audited end
+
+extern CFTypeRef CFCreateSomethingUnaudited();
+
+void testAudited() {
+  CFTypeRef obj = CFCreateSomethingAudited(); // no-warning
+  CFRelease(obj); // no-warning
+
+  CFTypeRef obj2 = CFCreateSomethingAudited(); // expected-warning{{leak}}
+  CFRetain(obj2); // no-warning
+  CFRelease(obj2); // no-warning
+}
+
+void testUnaudited() {
+  CFTypeRef obj = CFCreateSomethingUnaudited(); // no-warning
+  CFRelease(obj); // no-warning
+
+  CFTypeRef obj2 = CFCreateSomethingUnaudited(); // expected-warning{{leak}}
+  CFRetain(obj2); // no-warning
+  CFRelease(obj2); // no-warning
+}