[cfe-commits] r51433 - /cfe/trunk/lib/Analysis/CFRefCount.cpp

Ted Kremenek kremenek at apple.com
Thu May 22 10:31:13 PDT 2008


Author: kremenek
Date: Thu May 22 12:31:13 2008
New Revision: 51433

URL: http://llvm.org/viewvc/llvm-project?rev=51433&view=rev
Log:
Expand retain/release checker to consider methods/function calls that cause a
tracked object to "escape": it's reference count might be incremented by the
called function, thus causing an object's lifetime to extend beyond when the
local reference count is decremented to 0.

This addresses: <rdar://problem/5933215>

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=51433&r1=51432&r2=51433&view=diff

==============================================================================
--- cfe/trunk/lib/Analysis/CFRefCount.cpp (original)
+++ cfe/trunk/lib/Analysis/CFRefCount.cpp Thu May 22 12:31:13 2008
@@ -94,7 +94,7 @@
 //===----------------------------------------------------------------------===//
 
 namespace {  
-  enum ArgEffect { IncRef, DecRef, DoNothing, StopTracking };
+  enum ArgEffect { IncRef, DecRef, DoNothing, StopTracking, MayEscape };
   typedef std::vector<std::pair<unsigned,ArgEffect> > ArgEffects;
 }
 
@@ -286,12 +286,12 @@
   
   RetainSummary* getPersistentSummary(ArgEffects* AE, RetEffect RetEff,
                                       ArgEffect ReceiverEff = DoNothing,
-                                      ArgEffect DefaultEff = DoNothing);
+                                      ArgEffect DefaultEff = MayEscape);
                  
 
   RetainSummary* getPersistentSummary(RetEffect RE,
                                       ArgEffect ReceiverEff = DoNothing,
-                                      ArgEffect DefaultEff = DoNothing) {
+                                      ArgEffect DefaultEff = MayEscape) {
     return getPersistentSummary(getArgEffects(), RE, ReceiverEff, DefaultEff);
   }
   
@@ -499,19 +499,22 @@
   switch (func) {
     case cfretain: {
       ScratchArgs.push_back(std::make_pair(0, IncRef));
-      return getPersistentSummary(RetEffect::MakeAlias(0));
+      return getPersistentSummary(RetEffect::MakeAlias(0),
+                                  DoNothing, DoNothing);
     }
       
     case cfrelease: {
       ScratchArgs.push_back(std::make_pair(0, DecRef));
-      return getPersistentSummary(RetEffect::MakeNoRet());
+      return getPersistentSummary(RetEffect::MakeNoRet(),
+                                  DoNothing, DoNothing);
     }
       
     case cfmakecollectable: {
       if (GCEnabled)
         ScratchArgs.push_back(std::make_pair(0, DecRef));
       
-      return getPersistentSummary(RetEffect::MakeAlias(0));    
+      return getPersistentSummary(RetEffect::MakeAlias(0),
+                                  DoNothing, DoNothing);    
     }
       
     default:
@@ -525,7 +528,7 @@
     dyn_cast<FunctionType>(FD->getType().getTypePtr());
   
   if (FT && !isCFRefType(FT->getResultType()))
-    return 0;
+    return getPersistentSummary(RetEffect::MakeNoRet());
 
   // FIXME: Add special-cases for functions that retain/release.  For now
   //  just handle the default case.
@@ -549,14 +552,14 @@
     // in the future.
   
     if (!isCFRefType(RetTy) && !RetTy->isPointerType())
-      return 0;
+      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());
+  return getPersistentSummary(RetEffect::MakeNotOwned(), DoNothing, DoNothing);
 }
 
 //===----------------------------------------------------------------------===//
@@ -801,7 +804,7 @@
   
   // State creation: normal state.
   
-  static RefVal makeOwned(unsigned Count = 0) {
+  static RefVal makeOwned(unsigned Count = 1) {
     return RefVal(Owned, Count);
   }
   
@@ -887,16 +890,6 @@
   }
 }
   
-static inline unsigned GetCount(RefVal V) {
-  switch (V.getKind()) {
-    default:
-      return V.getCount();
-
-    case RefVal::Owned:
-      return V.getCount()+1;
-  }
-}
-  
 //===----------------------------------------------------------------------===//
 // Transfer functions.
 //===----------------------------------------------------------------------===//
@@ -1096,7 +1089,7 @@
 }
 
 static inline ArgEffect GetArgE(RetainSummary* Summ, unsigned idx) {
-  return Summ ? Summ->getArg(idx) : DoNothing;
+  return Summ ? Summ->getArg(idx) : MayEscape;
 }
 
 static inline RetEffect GetRetEffect(RetainSummary* Summ) {
@@ -1396,7 +1389,7 @@
   ValueState StImpl = *St;  
 
   StImpl.CheckerState =
-    RefBFactory.Add(B, sid, RefVal::makeLeak(GetCount(V))).getRoot();
+    RefBFactory.Add(B, sid, RefVal::makeLeak(V.getCount())).getRoot();
   
   return VMgr.getPersistentState(StImpl);
 }
@@ -1517,7 +1510,8 @@
       
     case RefVal::Owned: { 
       unsigned cnt = X.getCount();
-      X = RefVal::makeReturnedOwned(cnt);
+      assert (cnt > 0);
+      X = RefVal::makeReturnedOwned(cnt - 1);
       break;
     }
       
@@ -1588,6 +1582,14 @@
   switch (E) {
     default:
       assert (false && "Unhandled CFRef transition.");
+
+    case MayEscape:
+      if (V.getKind() == RefVal::Owned) {
+        V = RefVal::makeNotOwned(V.getCount());
+        break;
+      }
+
+      // Fall-through.
       
     case DoNothing:
       if (!isGCEnabled() && V.getKind() == RefVal::Released) {
@@ -1634,7 +1636,7 @@
           
         case RefVal::Owned: {
           unsigned Count = V.getCount();
-          V = Count > 0 ? RefVal::makeOwned(Count - 1) : RefVal::makeReleased();
+          V = Count > 1 ? RefVal::makeOwned(Count - 1) : RefVal::makeReleased();
           break;
         }
           
@@ -1907,14 +1909,16 @@
   switch (CurrV.getKind()) {
     case RefVal::Owned:
     case RefVal::NotOwned:
-      assert (PrevV.getKind() == CurrV.getKind());
+
+      if (PrevV.getCount() == CurrV.getCount())
+        return 0;
       
       if (PrevV.getCount() > CurrV.getCount())
         os << "Reference count decremented.";
       else
         os << "Reference count incremented.";
       
-      if (unsigned Count = GetCount(CurrV)) {
+      if (unsigned Count = CurrV.getCount()) {
 
         os << " Object has +" << Count;
         
@@ -2027,7 +2031,7 @@
     RefBindings B = RefBindings((RefBindings::TreeTy*) St->CheckerState);
     RefBindings::TreeTy* T = B.SlimFind(Sym);
     assert (T);
-    RetCount = GetCount(T->getValue().second);
+    RetCount = T->getValue().second.getCount();
   }
 
   // We are a leak.  Walk up the graph to get to the first node where the





More information about the cfe-commits mailing list