[cfe-commits] r50653 - in /cfe/trunk: lib/Analysis/CFRefCount.cpp test/Analysis-Apple/CFDateGC.m

Ted Kremenek kremenek at apple.com
Mon May 5 09:51:50 PDT 2008


Author: kremenek
Date: Mon May  5 11:51:50 2008
New Revision: 50653

URL: http://llvm.org/viewvc/llvm-project?rev=50653&view=rev
Log:
Minor refactorings/cleanups in CF retain checker and added support for NSMakeCollectable.
Added test case for NSMakeCollectable.

Added:
    cfe/trunk/test/Analysis-Apple/CFDateGC.m
Modified:
    cfe/trunk/lib/Analysis/CFRefCount.cpp

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

==============================================================================
--- cfe/trunk/lib/Analysis/CFRefCount.cpp (original)
+++ cfe/trunk/lib/Analysis/CFRefCount.cpp Mon May  5 11:51:50 2008
@@ -159,13 +159,14 @@
   
   ArgEffects*   getArgEffects();
 
-  enum CFUnaryFunc { cfretain, cfrelease, cfmakecollectable };  
-  CFRefSummary* getUnaryCFSummary(FunctionTypeProto* FT, CFUnaryFunc func);
+  enum UnaryFuncKind { cfretain, cfrelease, cfmakecollectable };  
+  CFRefSummary* getUnarySummary(FunctionDecl* FD, UnaryFuncKind func);
   
+  CFRefSummary* getNSSummary(FunctionDecl* FD, const char* FName);
   CFRefSummary* getCFSummary(FunctionDecl* FD, const char* FName);
   
-  CFRefSummary* getCFSummaryCreateRule(FunctionTypeProto* FT);
-  CFRefSummary* getCFSummaryGetRule(FunctionTypeProto* FT);  
+  CFRefSummary* getCFSummaryCreateRule(FunctionDecl* FD);
+  CFRefSummary* getCFSummaryGetRule(FunctionDecl* FD);  
   
   CFRefSummary* getPersistentSummary(ArgEffects* AE, RetEffect RE);
     
@@ -257,7 +258,6 @@
   if (!Loc.isFileID())
     return NULL;
   
-
   // Look up a summary in our cache of FunctionDecls -> Summaries.
   SummaryMapTy::iterator I = SummaryMap.find(FD);
 
@@ -267,125 +267,92 @@
   // No summary.  Generate one.
   const char* FName = FD->getIdentifier()->getName();
     
-  if (FName[0] == 'C' && FName[1] == 'F') {
-    CFRefSummary* S = getCFSummary(FD, FName);
-    SummaryMap[FD] = S;
-    return S;
-  }
+  CFRefSummary *S = 0;
+  
+  if (FName[0] == 'C' && FName[1] == 'F')
+    S = getCFSummary(FD, FName);
+  else if (FName[0] == 'N' && FName[1] == 'S')
+    S = getNSSummary(FD, FName);
 
-  // Function has no ref-count effects.  Return the NULL summary.
-  return NULL;  
+  SummaryMap[FD] = S;
+  return S;  
 }
 
-CFRefSummary* CFRefSummaryManager::getCFSummary(FunctionDecl* FD,
+CFRefSummary* CFRefSummaryManager::getNSSummary(FunctionDecl* FD,
                                                 const char* FName) {
+  FName += 2;
   
-  // For now, only generate summaries for functions that have a prototype.
-  
-  FunctionTypeProto* FT =
-    dyn_cast<FunctionTypeProto>(FD->getType().getTypePtr());
-  
-  if (!FT)
-    return NULL;
+  if (strcmp(FName, "MakeCollectable") == 0)
+    return getUnarySummary(FD, cfmakecollectable);
+
+  return 0;  
+}
   
+CFRefSummary* CFRefSummaryManager::getCFSummary(FunctionDecl* FD,
+                                                const char* FName) {
+
   FName += 2;
 
   if (strcmp(FName, "Retain") == 0)
-    return getUnaryCFSummary(FT, cfretain);
+    return getUnarySummary(FD, cfretain);
   
   if (strcmp(FName, "Release") == 0)
-    return getUnaryCFSummary(FT, cfrelease);
+    return getUnarySummary(FD, cfrelease);
 
   if (strcmp(FName, "MakeCollectable") == 0)
-    return getUnaryCFSummary(FT, cfmakecollectable);
-  
-  assert (ScratchArgs.empty());
-  bool usesCreateRule = false;
-  
-  if (strstr(FName, "Create"))
-    usesCreateRule = true;
-  
-  if (!usesCreateRule && strstr(FName, "Copy"))
-    usesCreateRule = true;
-  
-  if (usesCreateRule)
-    return getCFSummaryCreateRule(FT);
+    return getUnarySummary(FD, cfmakecollectable);
+    
+  if (strstr(FName, "Create") || strstr(FName, "Copy"))
+    return getCFSummaryCreateRule(FD);
 
   if (strstr(FName, "Get"))
-    return getCFSummaryGetRule(FT);
+    return getCFSummaryGetRule(FD);
   
-  return NULL;
+  return 0;
 }
 
 CFRefSummary*
-CFRefSummaryManager::getUnaryCFSummary(FunctionTypeProto* FT, CFUnaryFunc func) {
+CFRefSummaryManager::getUnarySummary(FunctionDecl* FD, UnaryFuncKind func) {
   
-  if (FT->getNumArgs() != 1)
-    return NULL;
-  
-  TypedefType* ArgT = dyn_cast<TypedefType>(FT->getArgType(0).getTypePtr());
-  
-  if (!ArgT)
-    return NULL;
-  
-  // For CFRetain/CFRelease, the first (and only) argument is of type 
-  // "CFTypeRef".
+  FunctionTypeProto* FT =
+    dyn_cast<FunctionTypeProto>(FD->getType().getTypePtr());
   
-  const char* TDName = ArgT->getDecl()->getIdentifier()->getName();
-  assert (TDName);
+  if (FT) {
+    
+    if (FT->getNumArgs() != 1)
+      return 0;
   
-  if (strcmp("CFTypeRef", TDName) != 0)
-    return NULL;
+    TypedefType* ArgT = dyn_cast<TypedefType>(FT->getArgType(0).getTypePtr());
   
-  if (!ArgT->isPointerType())
-    return NULL;
+    if (!ArgT)
+      return 0;
+
+    if (!ArgT->isPointerType())
+      return NULL;
+  }
 
-  QualType RetTy = FT->getResultType();
+  assert (ScratchArgs.empty());
   
   switch (func) {
     case cfretain: {
-      
-      // CFRetain: the return type should also be "CFTypeRef".
-      if (RetTy.getTypePtr() != ArgT)
-        return NULL;
-      
-      // The function's interface checks out.  Generate a canned summary.    
-      assert (ScratchArgs.empty());
       ScratchArgs.push_back(std::make_pair(0, IncRef));
       return getPersistentSummary(getArgEffects(), RetEffect::MakeAlias(0));
     }
       
     case cfrelease: {
-
-      // CFRelease: the return type should be void.
-      
-      if (RetTy != Ctx.VoidTy)
-        return NULL;
-      
-      assert (ScratchArgs.empty());
       ScratchArgs.push_back(std::make_pair(0, DecRef));
       return getPersistentSummary(getArgEffects(), RetEffect::MakeNoRet());
     }
       
     case cfmakecollectable: {
-      
-      // CFRetain: the return type should also be "CFTypeRef".
-      if (RetTy.getTypePtr() != ArgT)
-        return NULL;
-      
-      // The function's interface checks out.  Generate a canned summary.    
-      assert (ScratchArgs.empty());
-      
       if (GCEnabled)
         ScratchArgs.push_back(std::make_pair(0, DecRef));
       
-      return getPersistentSummary(getArgEffects(), RetEffect::MakeAlias(0));
-      
-      
+      return getPersistentSummary(getArgEffects(), RetEffect::MakeAlias(0));    
     }
       
     default:
-      assert (false && "Not a support unary function.");
+      assert (false && "Not a supported unary function.");
   }
 }
 
@@ -414,10 +381,13 @@
 }
 
 CFRefSummary*
-CFRefSummaryManager::getCFSummaryCreateRule(FunctionTypeProto* FT) {
+CFRefSummaryManager::getCFSummaryCreateRule(FunctionDecl* FD) {
  
-  if (!isCFRefType(FT->getResultType()))
-    return NULL;
+  FunctionTypeProto* FT =
+    dyn_cast<FunctionTypeProto>(FD->getType().getTypePtr());
+  
+  if (FT && !isCFRefType(FT->getResultType()))
+    return 0;
 
   // FIXME: Add special-cases for functions that retain/release.  For now
   //  just handle the default case.
@@ -427,18 +397,23 @@
 }
 
 CFRefSummary*
-CFRefSummaryManager::getCFSummaryGetRule(FunctionTypeProto* FT) {
+CFRefSummaryManager::getCFSummaryGetRule(FunctionDecl* FD) {
   
-  QualType RetTy = FT->getResultType();
+  FunctionTypeProto* FT =
+    dyn_cast<FunctionTypeProto>(FD->getType().getTypePtr());
   
-  // 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 (FT) {
+    QualType RetTy = FT->getResultType();
   
-  if (!isCFRefType(RetTy) && !RetTy->isPointerType())
-    return NULL;
+    // 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 0;
+  }
   
   // FIXME: Add special-cases for functions that retain/release.  For now
   //  just handle the default case.

Added: cfe/trunk/test/Analysis-Apple/CFDateGC.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis-Apple/CFDateGC.m?rev=50653&view=auto

==============================================================================
--- cfe/trunk/test/Analysis-Apple/CFDateGC.m (added)
+++ cfe/trunk/test/Analysis-Apple/CFDateGC.m Mon May  5 11:51:50 2008
@@ -0,0 +1,17 @@
+// RUN: clang -checker-cfref -verify -fobjc-gc %s
+
+#include <CoreFoundation/CFDate.h>
+#include <Foundation/NSDate.h>
+#include <Foundation/NSZone.h>
+
+CFAbsoluteTime f1() {
+  CFAbsoluteTime t = CFAbsoluteTimeGetCurrent();
+  CFDateRef date = CFDateCreate(NULL, t);
+  CFRetain(date);
+  [NSMakeCollectable(date) release];
+  CFDateGetAbsoluteTime(date); // no-warning
+  CFRelease(date);
+  t = CFDateGetAbsoluteTime(date);   // expected-warning{{Reference-counted object is used after it is released.}}
+  return t;
+}
+





More information about the cfe-commits mailing list