[cfe-commits] r62106 - in /cfe/trunk: lib/Analysis/CFRefCount.cpp test/Analysis/CFDate.m test/Analysis/CFDateGC.m test/Analysis/CFString.c test/Analysis/retain-release.m

Ted Kremenek kremenek at apple.com
Mon Jan 12 13:45:02 PST 2009


Author: kremenek
Date: Mon Jan 12 15:45:02 2009
New Revision: 62106

URL: http://llvm.org/viewvc/llvm-project?rev=62106&view=rev
Log:
retain/release checker:
- Refactor a bunch of logic in the retain/release checker, making it more
  condense and easier to read.
- Add support for "Create" methods in the DiskArbitration framework

retain/release tests:
- Rename CFDate.m to retain-release.m, and move test from CFString.c to
  retain-release.m
- Add DiskArbitration framework tests cases.
- Add/refine and few more retain/release GC test cases.

Added:
    cfe/trunk/test/Analysis/retain-release.m
Removed:
    cfe/trunk/test/Analysis/CFDate.m
    cfe/trunk/test/Analysis/CFString.c
Modified:
    cfe/trunk/lib/Analysis/CFRefCount.cpp
    cfe/trunk/test/Analysis/CFDateGC.m

Modified: cfe/trunk/lib/Analysis/CFRefCount.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/CFRefCount.cpp?rev=62106&r1=62105&r2=62106&view=diff

==============================================================================
--- cfe/trunk/lib/Analysis/CFRefCount.cpp (original)
+++ cfe/trunk/lib/Analysis/CFRefCount.cpp Mon Jan 12 15:45:02 2009
@@ -83,50 +83,45 @@
 // Type querying functions.
 //===----------------------------------------------------------------------===//
 
-static bool isCFRefType(QualType T) {
-  
-  if (!T->isPointerType())
-    return false;
-  
-  // Check the typedef for the name "CF" and the substring "Ref".  
-  TypedefType* TD = dyn_cast<TypedefType>(T.getTypePtr());
-  
-  if (!TD)
-    return false;
-  
-  const char* TDName = TD->getDecl()->getIdentifier()->getName();
-  assert (TDName);
+static bool hasPrefix(const char* s, const char* prefix) {
+  if (!prefix)
+    return true;
   
-  if (TDName[0] != 'C' || TDName[1] != 'F')
-    return false;
+  char c = *s;
+  char cP = *prefix;
   
-  if (strstr(TDName, "Ref") == 0)
-    return false;
+  while (c != '\0' && cP != '\0') {
+    if (c != cP) break;
+    c = *(++s);
+    cP = *(++prefix);
+  }
   
-  return true;
+  return cP == '\0';
 }
 
-static bool isCGRefType(QualType T) {
-  
-  if (!T->isPointerType())
-    return false;
-  
-  // Check the typedef for the name "CG" and the substring "Ref".  
-  TypedefType* TD = dyn_cast<TypedefType>(T.getTypePtr());
-  
-  if (!TD)
-    return false;
-  
-  const char* TDName = TD->getDecl()->getIdentifier()->getName();
-  assert (TDName);
+static bool hasSuffix(const char* s, const char* suffix) {
+  const char* loc = strstr(s, suffix);
+  return loc && strcmp(suffix, loc) == 0;
+}
+
+static bool isRefType(QualType RetTy, const char* prefix,
+                      ASTContext* Ctx = 0, const char* name = 0) {
   
-  if (TDName[0] != 'C' || TDName[1] != 'G')
+  if (TypedefType* TD = dyn_cast<TypedefType>(RetTy.getTypePtr())) {
+    const char* TDName = TD->getDecl()->getIdentifier()->getName();
+    return hasPrefix(TDName, prefix) && hasSuffix(TDName, "Ref");
+  }
+
+  if (!Ctx || !name)
     return false;
-  
-  if (strstr(TDName, "Ref") == 0)
+
+  // Is the type void*?
+  const PointerType* PT = RetTy->getAsPointerType();
+  if (!(PT->getPointeeType().getUnqualifiedType() == Ctx->VoidTy))
     return false;
-  
-  return true;
+
+  // Does the name start with the prefix?
+  return hasPrefix(name, prefix);
 }
 
 //===----------------------------------------------------------------------===//
@@ -507,15 +502,11 @@
   enum UnaryFuncKind { cfretain, cfrelease, cfmakecollectable };  
   
 public:
-  RetainSummary* getUnarySummary(FunctionDecl* FD, UnaryFuncKind func);
-  
-  RetainSummary* getNSSummary(FunctionDecl* FD, const char* FName);
-  RetainSummary* getCFSummary(FunctionDecl* FD, const char* FName);
-  RetainSummary* getCGSummary(FunctionDecl* FD, const char* FName);
+  RetainSummary* getUnarySummary(FunctionType* FT, UnaryFuncKind func);
   
   RetainSummary* getCFSummaryCreateRule(FunctionDecl* FD);
   RetainSummary* getCFSummaryGetRule(FunctionDecl* FD);  
-  RetainSummary* getCFCreateGetRuleSummary(FunctionDecl* FD, const char* FName);  
+  RetainSummary* getCFCreateGetRuleSummary(FunctionDecl* FD, const char* FName);
   
   RetainSummary* getPersistentSummary(ArgEffects* AE, RetEffect RetEff,
                                       ArgEffect ReceiverEff = DoNothing,
@@ -713,6 +704,16 @@
 // Summary creation for functions (largely uses of Core Foundation).
 //===----------------------------------------------------------------------===//
 
+static bool isRetain(FunctionDecl* FD, const char* FName) {
+  const char* loc = strstr(FName, "Retain");
+  return loc && loc[sizeof("Retain")-1] == '\0';
+}
+
+static bool isRelease(FunctionDecl* FD, const char* FName) {
+  const char* loc = strstr(FName, "Release");
+  return loc && loc[sizeof("Release")-1] == '\0';
+}
+
 RetainSummary* RetainSummaryManager::getSummary(FunctionDecl* FD) {
 
   SourceLocation Loc = FD->getLocation();
@@ -727,50 +728,90 @@
     return I->second;
 
   // No summary.  Generate one.
-  const char* FName = FD->getIdentifier()->getName();
+  RetainSummary *S = 0;
   
-  RetainSummary *S = 0;  
-  FunctionType* FT = dyn_cast<FunctionType>(FD->getType());
-
   do {
-    if (FT) {
-      
-      QualType T = FT->getResultType();
-      
-      if (isCFRefType(T)) {
-        S = getCFSummary(FD, FName);
+    // We generate "stop" summaries for implicitly defined functions.
+    if (FD->isImplicit()) {
+      S = getPersistentStopSummary();
+      break;
+    }
+    
+    FunctionType* FT = cast<FunctionType>(FD->getType());
+    const char* FName = FD->getIdentifier()->getName();
+    
+    // Inspect the result type.
+    QualType RetTy = FT->getResultType();
+    
+    // FIXME: This should all be refactored into a chain of "summary lookup"
+    //  filters.
+    if (strcmp(FName, "IOServiceGetMatchingServices") == 0) {
+      // FIXES: <rdar://problem/6326900>
+      // This should be addressed using a API table.  This strcmp is also
+      // a little gross, but there is no need to super optimize here.
+      assert (ScratchArgs.empty());
+      ScratchArgs.push_back(std::make_pair(1, DecRef));
+      S = getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, DoNothing);
+      break;
+    }
+    
+    // Handle: id NSMakeCollectable(CFTypeRef)
+    if (strcmp(FName, "NSMakeCollectable") == 0) {
+      S = (RetTy == Ctx.getObjCIdType())
+          ? getUnarySummary(FT, cfmakecollectable)
+          : getPersistentStopSummary();
+        
+      break;
+    }
+
+    if (RetTy->isPointerType()) {
+      // For CoreFoundation ('CF') types.
+      if (isRefType(RetTy, "CF", &Ctx, FName)) {
+        if (isRetain(FD, FName))
+          S = getUnarySummary(FT, cfretain);
+        else if (strstr(FName, "MakeCollectable"))
+          S = getUnarySummary(FT, cfmakecollectable);
+        else 
+          S = getCFCreateGetRuleSummary(FD, FName);
+
         break;
       }
-      
-      if (isCGRefType(T)) {
-        S = getCGSummary(FD, FName );
+
+      // For CoreGraphics ('CG') types.
+      if (isRefType(RetTy, "CG", &Ctx, FName)) {
+        if (isRetain(FD, FName))
+          S = getUnarySummary(FT, cfretain);
+        else
+          S = getCFCreateGetRuleSummary(FD, FName);
+
         break;
       }
-      
-      // FIXME: This should all be refactored into a chain of "summary lookup"
-      //  filters.
-      if (strcmp(FName, "IOServiceGetMatchingServices") == 0) {
-        // FIXES: <rdar://problem/6326900>
-        // This should be addressed using a API table.  This strcmp is also
-        // a little gross, but there is no need to super optimize here.
-        assert (ScratchArgs.empty());
-        ScratchArgs.push_back(std::make_pair(1, DecRef));
-        S = getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, DoNothing);
+
+      // For the Disk Arbitration API (DiskArbitration/DADisk.h)
+      if (isRefType(RetTy, "DADisk") ||
+          isRefType(RetTy, "DADissenter") ||
+          isRefType(RetTy, "DASessionRef")) {
+        S = getCFCreateGetRuleSummary(FD, FName);
         break;
       }
+      
+      break;
     }
-    
-    // Ignore the prefix '_'
-    while (*FName == '_') ++FName;
 
-    if (FName[0] == 'C') {
-      if (FName[1] == 'F')
-        S = getCFSummary(FD, FName);  
-      else if (FName[1] == 'G')
-        S = getCGSummary(FD, FName);
+    // Check for release functions, the only kind of functions that we care
+    // about that don't return a pointer type.
+    if (FName[0] == 'C' && (FName[1] == 'F' || FName[1] == 'G')) {
+      if (isRelease(FD, FName+2))
+        S = getUnarySummary(FT, cfrelease);
+      else {
+        // For CoreFoundation and CoreGraphics functions we assume they
+        // follow the ownership idiom strictly and thus do not cause
+        // ownership to "escape".
+        assert (ScratchArgs.empty());  
+        S = getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, 
+                                 DoNothing);
+      }
     }
-    else if (FName[0] == 'N' && FName[1] == 'S')
-      S = getNSSummary(FD, FName);
   }
   while (0);
 
@@ -778,58 +819,6 @@
   return S;  
 }
 
-RetainSummary* RetainSummaryManager::getNSSummary(FunctionDecl* FD,
-                                                  const char* FName) {
-  FName += 2;
-  
-  if (strcmp(FName, "MakeCollectable") == 0)
-    return getUnarySummary(FD, cfmakecollectable);
-
-  return 0;  
-}
-
-static bool isRetain(FunctionDecl* FD, const char* FName) {
-  const char* loc = strstr(FName, "Retain");
-  return loc && loc[sizeof("Retain")-1] == '\0';
-}
-
-static bool isRelease(FunctionDecl* FD, const char* FName) {
-  const char* loc = strstr(FName, "Release");
-  return loc && loc[sizeof("Release")-1] == '\0';
-}
-
-RetainSummary* RetainSummaryManager::getCFSummary(FunctionDecl* FD,
-                                                  const char* FName) {
-  if (FName[0] == 'C' && FName[1] == 'F')
-    FName += 2;
-  
-  if (isRetain(FD, FName))
-    return getUnarySummary(FD, cfretain);
-  
-  if (isRelease(FD, FName))
-    return getUnarySummary(FD, cfrelease);
-  
-  if (strcmp(FName, "MakeCollectable") == 0)
-    return getUnarySummary(FD, cfmakecollectable);
-
-  return getCFCreateGetRuleSummary(FD, FName);
-}
-
-RetainSummary* RetainSummaryManager::getCGSummary(FunctionDecl* FD,
-                                                  const char* FName) {
-  
-  if (FName[0] == 'C' && FName[1] == 'G')
-    FName += 2;
-  
-  if (isRelease(FD, FName))
-    return getUnarySummary(FD, cfrelease);
-  
-  if (isRetain(FD, FName))
-    return getUnarySummary(FD, cfretain);
-  
-  return getCFCreateGetRuleSummary(FD, FName);
-}
-
 RetainSummary*
 RetainSummaryManager::getCFCreateGetRuleSummary(FunctionDecl* FD,
                                                 const char* FName) {
@@ -844,29 +833,17 @@
 }
 
 RetainSummary*
-RetainSummaryManager::getUnarySummary(FunctionDecl* FD, UnaryFuncKind func) {
-  
-  FunctionTypeProto* FT =
-    dyn_cast<FunctionTypeProto>(FD->getType().getTypePtr());
-  
-  if (FT) {
-    
-    if (FT->getNumArgs() != 1)
-      return 0;
-  
-    TypedefType* ArgT = dyn_cast<TypedefType>(FT->getArgType(0).getTypePtr());
-  
-    if (!ArgT)
-      return 0;
-
-    if (!ArgT->isPointerType())
-      return NULL;
-  }
+RetainSummaryManager::getUnarySummary(FunctionType* FT, UnaryFuncKind func) {
+  // Sanity check that this is *really* a unary function.  This can
+  // happen if people do weird things.
+  FunctionTypeProto* FTP = dyn_cast<FunctionTypeProto>(FT);
+  if (!FTP || FTP->getNumArgs() != 1)
+    return getPersistentStopSummary();
   
   assert (ScratchArgs.empty());
   
   switch (func) {
-    case cfretain: {
+    case cfretain: {      
       ScratchArgs.push_back(std::make_pair(0, IncRef));
       return getPersistentSummary(RetEffect::MakeAlias(0),
                                   DoNothing, DoNothing);
@@ -893,17 +870,6 @@
 }
 
 RetainSummary* RetainSummaryManager::getCFSummaryCreateRule(FunctionDecl* FD) {
- 
-  FunctionType* FT =
-    dyn_cast<FunctionType>(FD->getType().getTypePtr());
-
-  if (FT) {
-    QualType ResTy = FT->getResultType();
-    
-    if (!isCFRefType(ResTy) && !isCGRefType(ResTy))
-      return getPersistentSummary(RetEffect::MakeNoRet());
-  }
-  
   assert (ScratchArgs.empty());
   
   if (FD->getIdentifier() == CFDictionaryCreateII) {
@@ -915,26 +881,6 @@
 }
 
 RetainSummary* RetainSummaryManager::getCFSummaryGetRule(FunctionDecl* FD) {
-  
-  FunctionType* FT =
-    dyn_cast<FunctionType>(FD->getType().getTypePtr());
-  
-  if (FT) {
-    QualType RetTy = FT->getResultType();
-  
-    // FIXME: For now we assume that all pointer types returned are referenced
-    // counted.  Since this is the "Get" rule, we assume non-ownership, which
-    // works fine for things that are not reference counted.  We do this because
-    // some generic data structures return "void*".  We need something better
-    // in the future.
-  
-    if (!isCFRefType(RetTy) && !RetTy->isPointerType())
-      return getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, DoNothing);
-  }
-  
-  // FIXME: Add special-cases for functions that retain/release.  For now
-  //  just handle the default case.
-  
   assert (ScratchArgs.empty());  
   return getPersistentSummary(RetEffect::MakeNotOwned(), DoNothing, DoNothing);
 }

Removed: cfe/trunk/test/Analysis/CFDate.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/CFDate.m?rev=62105&view=auto

==============================================================================
--- cfe/trunk/test/Analysis/CFDate.m (original)
+++ cfe/trunk/test/Analysis/CFDate.m (removed)
@@ -1,143 +0,0 @@
-// RUN: clang -checker-cfref -verify %s
-
-//===----------------------------------------------------------------------===//
-// The following code is reduced using delta-debugging from
-// Foundation.h (Mac OS X).
-//
-// It includes the basic definitions for the test cases below.
-// Not including Foundation.h directly makes this test case both svelte and
-// portable to non-Mac platforms.
-//===----------------------------------------------------------------------===//
-
-typedef const struct __CFAllocator * CFAllocatorRef;
-typedef double CFTimeInterval;
-typedef CFTimeInterval CFAbsoluteTime;
-typedef const struct __CFDate * CFDateRef;
-extern CFDateRef CFDateCreate(CFAllocatorRef allocator, CFAbsoluteTime at);
-typedef struct objc_object {} *id;
-typedef signed char BOOL;
-typedef unsigned int NSUInteger;
-typedef struct _NSZone NSZone;
- at class NSInvocation, NSMethodSignature, NSCoder, NSString, NSEnumerator;
- at protocol NSObject  - (BOOL)isEqual:(id)object; - (id)retain; - (oneway void)release; @end
- at protocol NSCopying  - (id)copyWithZone:(NSZone *)zone; @end
- at protocol NSCoding  - (void)encodeWithCoder:(NSCoder *)aCoder; @end
- at interface NSObject <NSObject> {} @end
-extern id NSAllocateObject(Class aClass, NSUInteger extraBytes, NSZone *zone);
-typedef double NSTimeInterval;
- at interface NSDate : NSObject <NSCopying, NSCoding>  - (NSTimeInterval)timeIntervalSinceReferenceDate; @end
- at class NSString, NSArray, NSTimeZone;
-
-//===----------------------------------------------------------------------===//
-// Test cases.
-//===----------------------------------------------------------------------===//
-
-CFAbsoluteTime f1() {
-  CFAbsoluteTime t = CFAbsoluteTimeGetCurrent();
-  CFDateRef date = CFDateCreate(0, t);
-  CFRetain(date);
-  CFRelease(date);
-  CFDateGetAbsoluteTime(date); // no-warning
-  CFRelease(date);
-  t = CFDateGetAbsoluteTime(date);   // expected-warning{{Reference-counted object is used after it is released.}}
-  return t;
-}
-
-CFAbsoluteTime f2() {
-  CFAbsoluteTime t = CFAbsoluteTimeGetCurrent();
-  CFDateRef date = CFDateCreate(0, t);  
-  [((NSDate*) date) retain];
-  CFRelease(date);
-  CFDateGetAbsoluteTime(date); // no-warning
-  [((NSDate*) date) release];
-  t = CFDateGetAbsoluteTime(date);   // expected-warning{{Reference-counted object is used after it is released.}}
-  return t;
-}
-
-
-NSDate* global_x;
-
-  // Test to see if we supresss an error when we store the pointer
-  // to a global.
-  
-CFAbsoluteTime f3() {
-  CFAbsoluteTime t = CFAbsoluteTimeGetCurrent();
-  CFDateRef date = CFDateCreate(0, t);  
-  [((NSDate*) date) retain];
-  CFRelease(date);
-  CFDateGetAbsoluteTime(date); // no-warning
-  global_x = (NSDate*) date;  
-  [((NSDate*) date) release];
-  t = CFDateGetAbsoluteTime(date);   // no-warning
-  return t;
-}
-
-// Test to see if we supresss an error when we store the pointer
-// to a struct.
-
-struct foo {
-  NSDate* f;
-};
-
-CFAbsoluteTime f4() {
-  struct foo x;
-  
-  CFAbsoluteTime t = CFAbsoluteTimeGetCurrent();
-  CFDateRef date = CFDateCreate(0, t);  
-  [((NSDate*) date) retain];
-  CFRelease(date);
-  CFDateGetAbsoluteTime(date); // no-warning
-  x.f = (NSDate*) date;  
-  [((NSDate*) date) release];
-  t = CFDateGetAbsoluteTime(date);   // no-warning
-  return t;
-}
-
-// Test a leak.
-
-CFAbsoluteTime f5(int x) {  
-  CFAbsoluteTime t = CFAbsoluteTimeGetCurrent();
-  CFDateRef date = CFDateCreate(0, t);
-  
-  if (x)
-    CFRelease(date);
-
-  return t; // expected-warning{{leak}}
-}
-
-// Test a leak involving the return.
-
-CFDateRef f6(int x) {  
-  CFDateRef date = CFDateCreate(0, CFAbsoluteTimeGetCurrent());
-  CFRetain(date);
-  return date; // expected-warning{{leak}}
-}
-
-// Test a leak involving an overwrite.
-
-CFDateRef f7() {
-  CFDateRef date = CFDateCreate(0, CFAbsoluteTimeGetCurrent());
-  CFRetain(date); //expected-warning{{leak}}
-  date = CFDateCreate(0, CFAbsoluteTimeGetCurrent()); 
-  return date;
-}
-
-// Generalization of Create rule.  MyDateCreate returns a CFXXXTypeRef, and
-// has the word create.
-
-CFDateRef MyDateCreate();
-
-CFDateRef f8() {
-  CFDateRef date = MyDateCreate();
-  CFRetain(date);  
-  return date; // expected-warning{{leak}}
-}
-
-CFDateRef f9() {
-  CFDateRef date = CFDateCreate(0, CFAbsoluteTimeGetCurrent());
-  int *p = 0;
-  // test that the checker assumes that CFDateCreate returns a non-null
-  // pointer
-  if (!date) *p = 1; // no-warning
-  return date;
-}

Modified: cfe/trunk/test/Analysis/CFDateGC.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/CFDateGC.m?rev=62106&r1=62105&r2=62106&view=diff

==============================================================================
--- cfe/trunk/test/Analysis/CFDateGC.m (original)
+++ cfe/trunk/test/Analysis/CFDateGC.m Mon Jan 12 15:45:02 2009
@@ -10,24 +10,28 @@
 //===----------------------------------------------------------------------===//
 
 typedef const void * CFTypeRef;
+void CFRelease(CFTypeRef cf);
+CFTypeRef CFRetain(CFTypeRef cf);
+CFTypeRef CFMakeCollectable(CFTypeRef cf);
 typedef const struct __CFAllocator * CFAllocatorRef;
 typedef double CFTimeInterval;
 typedef CFTimeInterval CFAbsoluteTime;
 typedef const struct __CFDate * CFDateRef;
 extern CFDateRef CFDateCreate(CFAllocatorRef allocator, CFAbsoluteTime at);
+extern CFAbsoluteTime CFDateGetAbsoluteTime(CFDateRef theDate);
+typedef struct objc_object {} *id;
 typedef signed char BOOL;
-typedef unsigned int NSUInteger;
-typedef struct _NSZone NSZone;
 static __inline__ __attribute__((always_inline)) id NSMakeCollectable(CFTypeRef cf) {}
- at protocol NSObject  - (BOOL)isEqual:(id)object; - (oneway void)release; @end
-extern id NSAllocateObject(Class aClass, NSUInteger extraBytes, NSZone *zone);
-CFTypeRef CFMakeCollectable(CFTypeRef cf);
+ at protocol NSObject  - (BOOL)isEqual:(id)object;
+- (oneway void)release;
+ at end
+ at class NSArray;
 
 //===----------------------------------------------------------------------===//
 // Test cases.
 //===----------------------------------------------------------------------===//
 
-CFAbsoluteTime f1() {
+CFAbsoluteTime f1_use_after_release() {
   CFAbsoluteTime t = CFAbsoluteTimeGetCurrent();
   CFDateRef date = CFDateCreate(0, t);
   CFRetain(date);
@@ -38,7 +42,20 @@
   return t;
 }
 
-CFAbsoluteTime f1b() {
+// The following two test cases verifies that CFMakeCollectable is a no-op
+// in non-GC mode and a "release" in GC mode.
+CFAbsoluteTime f2_leak() {
+  CFAbsoluteTime t = CFAbsoluteTimeGetCurrent();
+  CFDateRef date = CFDateCreate(0, t);
+  CFRetain(date);
+  [(id) CFMakeCollectable(date) release];
+  CFDateGetAbsoluteTime(date); // no-warning
+  CFRelease(date);
+  t = CFDateGetAbsoluteTime(date);   // expected-warning{{Reference-counted object is used after it is released.}}
+  return t;
+}
+
+CFAbsoluteTime f2_noleak() {
   CFAbsoluteTime t = CFAbsoluteTimeGetCurrent();
   CFDateRef date = CFDateCreate(0, t);
   CFRetain(date);
@@ -49,4 +66,12 @@
   return t;
 }
 
-
+// The following test case verifies that we "stop tracking" a retained object
+// when it is passed as an argument to an implicitly defined function.
+CFAbsoluteTime f4() {
+  CFAbsoluteTime t = CFAbsoluteTimeGetCurrent();
+  CFDateRef date = CFDateCreate(0, t);
+  CFRetain(date);
+  some_implicitly_defined_function_stop_tracking(date); // no-warning
+  return t;
+}

Removed: cfe/trunk/test/Analysis/CFString.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/CFString.c?rev=62105&view=auto

==============================================================================
--- cfe/trunk/test/Analysis/CFString.c (original)
+++ cfe/trunk/test/Analysis/CFString.c (removed)
@@ -1,60 +0,0 @@
-// RUN: clang -checker-cfref -pedantic -verify %s
-
-//===----------------------------------------------------------------------===//
-// The following code is reduced using delta-debugging from
-// CoreFoundation.h (Mac OS X).
-//
-// It includes the basic definitions for the test cases below.
-// Not directly including CoreFoundation.h directly makes this test case 
-// both svelte and portable to non-Mac platforms.
-//===----------------------------------------------------------------------===//
-
-typedef unsigned long UInt32;
-typedef unsigned char Boolean;
-typedef signed long CFIndex;
-typedef const void * CFTypeRef;
-typedef const struct __CFString * CFStringRef;
-typedef struct { CFIndex location; } CFRange;
-typedef const struct __CFAllocator * CFAllocatorRef;
-extern void CFRelease(CFTypeRef cf);
-typedef Boolean (*CFArrayEqualCallBack)(const void *value1, const void *value2);
-typedef struct { CFArrayEqualCallBack equal; } CFArrayCallBacks;
-extern const CFArrayCallBacks kCFTypeArrayCallBacks;
-typedef const struct __CFArray * CFArrayRef;
-typedef struct __CFArray * CFMutableArrayRef;
-extern CFMutableArrayRef CFArrayCreateMutable(CFAllocatorRef allocator, CFIndex capacity, const CFArrayCallBacks *callBacks);
-extern const void *CFArrayGetValueAtIndex(CFArrayRef theArray, CFIndex idx);
-extern void CFArrayAppendValue(CFMutableArrayRef theArray, const void *value);
-typedef UInt32 CFStringEncoding;
-enum { kCFStringEncodingMacRoman = 0,     kCFStringEncodingWindowsLatin1 = 0x0500,     kCFStringEncodingISOLatin1 = 0x0201,     kCFStringEncodingNextStepLatin = 0x0B01,     kCFStringEncodingASCII = 0x0600,     kCFStringEncodingUnicode = 0x0100,     kCFStringEncodingUTF8 = 0x08000100,     kCFStringEncodingNonLossyASCII = 0x0BFF      ,     kCFStringEncodingUTF16 = 0x0100,     kCFStringEncodingUTF16BE = 0x10000100,     kCFStringEncodingUTF16LE = 0x14000100,      kCFStringEncodingUTF32 = 0x0c000100,     kCFStringEncodingUTF32BE = 0x18000100,     kCFStringEncodingUTF32LE = 0x1c000100  };
-extern CFStringRef CFStringCreateWithCString(CFAllocatorRef alloc, const char *cStr, CFStringEncoding encoding);
-
-//===----------------------------------------------------------------------===//
-// Test cases.
-//===----------------------------------------------------------------------===//
-
-void f1() {
-  
-  // Create the array.
-  CFMutableArrayRef A = CFArrayCreateMutable(0, 10, &kCFTypeArrayCallBacks);
-
-  // Create a string.
-  CFStringRef s1 = CFStringCreateWithCString(0, "hello world",
-                                             kCFStringEncodingUTF8);
-
-  // Add the string to the array.
-  CFArrayAppendValue(A, s1);
-  
-  // Decrement the reference count.
-  CFRelease(s1); // no-warning
-  
-  // Get the string.  We don't own it.
-  s1 = (CFStringRef) CFArrayGetValueAtIndex(A, 0);
-  
-  // Release the array.
-  CFRelease(A); // no-warning
-  
-  // Release the string.  This is a bug.
-  CFRelease(s1); // expected-warning{{Incorrect decrement of the reference count}}
-}
-

Added: cfe/trunk/test/Analysis/retain-release.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/retain-release.m?rev=62106&view=auto

==============================================================================
--- cfe/trunk/test/Analysis/retain-release.m (added)
+++ cfe/trunk/test/Analysis/retain-release.m Mon Jan 12 15:45:02 2009
@@ -0,0 +1,239 @@
+// RUN: clang -checker-cfref -verify %s
+
+//===----------------------------------------------------------------------===//
+// The following code is reduced using delta-debugging from
+// Foundation.h (Mac OS X).
+//
+// It includes the basic definitions for the test cases below.
+// Not including Foundation.h directly makes this test case both svelte and
+// portable to non-Mac platforms.
+//===----------------------------------------------------------------------===//
+
+typedef unsigned int __darwin_natural_t;
+typedef unsigned long UInt32;
+typedef signed long CFIndex;
+typedef const void * CFTypeRef;
+typedef const struct __CFString * CFStringRef;
+typedef const struct __CFAllocator * CFAllocatorRef;
+extern const CFAllocatorRef kCFAllocatorDefault;
+extern CFTypeRef CFRetain(CFTypeRef cf);
+extern void CFRelease(CFTypeRef cf);
+typedef struct {
+}
+CFArrayCallBacks;
+extern const CFArrayCallBacks kCFTypeArrayCallBacks;
+typedef const struct __CFArray * CFArrayRef;
+typedef struct __CFArray * CFMutableArrayRef;
+extern CFMutableArrayRef CFArrayCreateMutable(CFAllocatorRef allocator, CFIndex capacity, const CFArrayCallBacks *callBacks);
+extern const void *CFArrayGetValueAtIndex(CFArrayRef theArray, CFIndex idx);
+typedef const struct __CFDictionary * CFDictionaryRef;
+typedef UInt32 CFStringEncoding;
+enum {
+kCFStringEncodingMacRoman = 0,     kCFStringEncodingWindowsLatin1 = 0x0500,     kCFStringEncodingISOLatin1 = 0x0201,     kCFStringEncodingNextStepLatin = 0x0B01,     kCFStringEncodingASCII = 0x0600,     kCFStringEncodingUnicode = 0x0100,     kCFStringEncodingUTF8 = 0x08000100,     kCFStringEncodingNonLossyASCII = 0x0BFF      ,     kCFStringEncodingUTF16 = 0x0100,     kCFStringEncodingUTF16BE = 0x10000100,     kCFStringEncodingUTF16LE = 0x14000100,      kCFStringEncodingUTF32 = 0x0c000100,     kCFStringEncodingUTF32BE = 0x18000100,     kCFStringEncodingUTF32LE = 0x1c000100  };
+extern CFStringRef CFStringCreateWithCString(CFAllocatorRef alloc, const char *cStr, CFStringEncoding encoding);
+typedef double CFTimeInterval;
+typedef CFTimeInterval CFAbsoluteTime;
+typedef const struct __CFDate * CFDateRef;
+extern CFDateRef CFDateCreate(CFAllocatorRef allocator, CFAbsoluteTime at);
+extern CFAbsoluteTime CFDateGetAbsoluteTime(CFDateRef theDate);
+typedef __darwin_natural_t natural_t;
+typedef natural_t mach_port_name_t;
+typedef mach_port_name_t mach_port_t;
+typedef signed char BOOL;
+typedef struct _NSZone NSZone;
+ at class NSInvocation, NSMethodSignature, NSCoder, NSString, NSEnumerator;
+ at protocol NSObject  - (BOOL)isEqual:(id)object;
+- (id)retain;
+- (oneway void)release;
+ at end  @protocol NSCopying  - (id)copyWithZone:(NSZone *)zone;
+ at end  @protocol NSCoding  - (void)encodeWithCoder:(NSCoder *)aCoder;
+ at end    @interface NSObject <NSObject> {
+}
+ at end  typedef float CGFloat;
+typedef double NSTimeInterval;
+ at interface NSDate : NSObject <NSCopying, NSCoding>  - (NSTimeInterval)timeIntervalSinceReferenceDate;
+ at end      enum {
+NSObjCNoType = 0,     NSObjCVoidType = 'v',     NSObjCCharType = 'c',     NSObjCShortType = 's',     NSObjCLongType = 'l',     NSObjCLonglongType = 'q',     NSObjCFloatType = 'f',     NSObjCDoubleType = 'd',      NSObjCBoolType = 'B',      NSObjCSelectorType = ':',     NSObjCObjectType = '@',     NSObjCStructType = '{',     NSObjCPointerType = '^',     NSObjCStringType = '*',     NSObjCArrayType = '[',     NSObjCUnionType = '(',     NSObjCBitfield = 'b' }
+__attribute__((deprecated));
+typedef int kern_return_t;
+typedef kern_return_t mach_error_t;
+typedef mach_port_t io_object_t;
+typedef io_object_t io_service_t;
+typedef struct __DASession * DASessionRef;
+extern DASessionRef DASessionCreate( CFAllocatorRef allocator );
+typedef struct __DADisk * DADiskRef;
+extern DADiskRef DADiskCreateFromBSDName( CFAllocatorRef allocator, DASessionRef session, const char * name );
+extern DADiskRef DADiskCreateFromIOMedia( CFAllocatorRef allocator, DASessionRef session, io_service_t media );
+extern CFDictionaryRef DADiskCopyDescription( DADiskRef disk );
+extern DADiskRef DADiskCopyWholeDisk( DADiskRef disk );
+ at interface NSAppleEventManager : NSObject {
+}
+ at end enum {
+kDAReturnSuccess = 0,     kDAReturnError = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x01,     kDAReturnBusy = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x02,     kDAReturnBadArgument = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x03,     kDAReturnExclusiveAccess = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x04,     kDAReturnNoResources = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x05,     kDAReturnNotFound = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x06,     kDAReturnNotMounted = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x07,     kDAReturnNotPermitted = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x08,     kDAReturnNotPrivileged = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x09,     kDAReturnNotReady = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x0A,     kDAReturnNotWritable = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x0B,     kDAReturnUnsupported = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x0C };
+typedef mach_error_t DAReturn;
+typedef const struct __DADissenter * DADissenterRef;
+extern DADissenterRef DADissenterCreate( CFAllocatorRef allocator, DAReturn status, CFStringRef string );
+
+//===----------------------------------------------------------------------===//
+// Test cases.
+//===----------------------------------------------------------------------===//
+
+CFAbsoluteTime f1() {
+  CFAbsoluteTime t = CFAbsoluteTimeGetCurrent();
+  CFDateRef date = CFDateCreate(0, t);
+  CFRetain(date);
+  CFRelease(date);
+  CFDateGetAbsoluteTime(date); // no-warning
+  CFRelease(date);
+  t = CFDateGetAbsoluteTime(date);   // expected-warning{{Reference-counted object is used after it is released.}}
+  return t;
+}
+
+CFAbsoluteTime f2() {
+  CFAbsoluteTime t = CFAbsoluteTimeGetCurrent();
+  CFDateRef date = CFDateCreate(0, t);  
+  [((NSDate*) date) retain];
+  CFRelease(date);
+  CFDateGetAbsoluteTime(date); // no-warning
+  [((NSDate*) date) release];
+  t = CFDateGetAbsoluteTime(date);   // expected-warning{{Reference-counted object is used after it is released.}}
+  return t;
+}
+
+
+NSDate* global_x;
+
+// Test to see if we supresss an error when we store the pointer
+// to a global.
+
+CFAbsoluteTime f3() {
+  CFAbsoluteTime t = CFAbsoluteTimeGetCurrent();
+  CFDateRef date = CFDateCreate(0, t);  
+  [((NSDate*) date) retain];
+  CFRelease(date);
+  CFDateGetAbsoluteTime(date); // no-warning
+  global_x = (NSDate*) date;  
+  [((NSDate*) date) release];
+  t = CFDateGetAbsoluteTime(date);   // no-warning
+  return t;
+}
+
+// Test to see if we supresss an error when we store the pointer
+// to a struct.
+
+struct foo {
+  NSDate* f;
+};
+
+CFAbsoluteTime f4() {
+  struct foo x;
+  
+  CFAbsoluteTime t = CFAbsoluteTimeGetCurrent();
+  CFDateRef date = CFDateCreate(0, t);  
+  [((NSDate*) date) retain];
+  CFRelease(date);
+  CFDateGetAbsoluteTime(date); // no-warning
+  x.f = (NSDate*) date;  
+  [((NSDate*) date) release];
+  t = CFDateGetAbsoluteTime(date);   // no-warning
+  return t;
+}
+
+// Test a leak.
+
+CFAbsoluteTime f5(int x) {  
+  CFAbsoluteTime t = CFAbsoluteTimeGetCurrent();
+  CFDateRef date = CFDateCreate(0, t);
+  
+  if (x)
+    CFRelease(date);
+  
+  return t; // expected-warning{{leak}}
+}
+
+// Test a leak involving the return.
+
+CFDateRef f6(int x) {  
+  CFDateRef date = CFDateCreate(0, CFAbsoluteTimeGetCurrent());
+  CFRetain(date);
+  return date; // expected-warning{{leak}}
+}
+
+// Test a leak involving an overwrite.
+
+CFDateRef f7() {
+  CFDateRef date = CFDateCreate(0, CFAbsoluteTimeGetCurrent());
+  CFRetain(date); //expected-warning{{leak}}
+  date = CFDateCreate(0, CFAbsoluteTimeGetCurrent()); 
+  return date;
+}
+
+// Generalization of Create rule.  MyDateCreate returns a CFXXXTypeRef, and
+// has the word create.
+CFDateRef MyDateCreate();
+
+CFDateRef f8() {
+  CFDateRef date = MyDateCreate();
+  CFRetain(date);  
+  return date; // expected-warning{{leak}}
+}
+
+CFDateRef f9() {
+  CFDateRef date = CFDateCreate(0, CFAbsoluteTimeGetCurrent());
+  int *p = 0;
+  // test that the checker assumes that CFDateCreate returns a non-null
+  // pointer
+  if (!date) *p = 1; // no-warning
+  return date;
+}
+
+// Handle DiskArbitration API:
+//
+// http://developer.apple.com/DOCUMENTATION/DARWIN/Reference/DiscArbitrationFramework/
+//
+void f10(io_service_t media, DADiskRef d, CFStringRef s) {
+  DADiskRef disk = DADiskCreateFromBSDName(kCFAllocatorDefault, 0, "hello");
+  if (disk) NSLog(@"ok"); // expected-warning{{leak}}
+  
+  disk = DADiskCreateFromIOMedia(kCFAllocatorDefault, 0, media);
+  if (disk) NSLog(@"ok"); // expected-warning{{leak}}
+
+  CFDictionaryRef dict = DADiskCopyDescription(d); 
+  if (dict) NSLog(@"ok"); // expected-warning{{leak}}
+  
+  disk = DADiskCopyWholeDisk(d);
+  if (disk) NSLog(@"ok"); // expected-warning{{leak}}
+    
+  DADissenterRef dissenter = DADissenterCreate(kCFAllocatorDefault,
+                                                kDAReturnSuccess, s);
+  if (dissenter) NSLog(@"ok"); // expected-warning{{leak}}
+  
+  DASessionRef session = DASessionCreate(kCFAllocatorDefault);
+  if (session) NSLog(@"ok"); // expected-warning{{leak}}
+}
+
+// Test retain/release checker with CFString and CFMutableArray.
+void f11() {
+  // Create the array.
+  CFMutableArrayRef A = CFArrayCreateMutable(0, 10, &kCFTypeArrayCallBacks);
+
+  // Create a string.
+  CFStringRef s1 = CFStringCreateWithCString(0, "hello world",
+                                             kCFStringEncodingUTF8);
+
+  // Add the string to the array.
+  CFArrayAppendValue(A, s1);
+  
+  // Decrement the reference count.
+  CFRelease(s1); // no-warning
+  
+  // Get the string.  We don't own it.
+  s1 = (CFStringRef) CFArrayGetValueAtIndex(A, 0);
+  
+  // Release the array.
+  CFRelease(A); // no-warning
+  
+  // Release the string.  This is a bug.
+  CFRelease(s1); // expected-warning{{Incorrect decrement of the reference count}}
+}
+





More information about the cfe-commits mailing list