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

Ted Kremenek kremenek at apple.com
Tue Feb 24 11:15:11 PST 2009


Author: kremenek
Date: Tue Feb 24 13:15:11 2009
New Revision: 65384

URL: http://llvm.org/viewvc/llvm-project?rev=65384&view=rev
Log:
retain/release checker:
- For autorelease pool tracking, keep information about the stack of pools
  separate from their contents. Also, keep track of the number of times an
  autorelease pool will send the "release" message to an object when the pool is
  destroyed.
- Update CFRefCount::Update to return a new state instead of a reference count
  binding. This will allow us to implement more complicated semantics with
  autorelease pools.

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=65384&r1=65383&r2=65384&view=diff

==============================================================================
--- cfe/trunk/lib/Analysis/CFRefCount.cpp (original)
+++ cfe/trunk/lib/Analysis/CFRefCount.cpp Tue Feb 24 13:15:11 2009
@@ -1358,56 +1358,30 @@
 }
 
 //===----------------------------------------------------------------------===//
-// ARBindings - State used to track objects in autorelease pools.
+// AutoreleaseBindings - State used to track objects in autorelease pools.
 //===----------------------------------------------------------------------===//
 
+typedef llvm::ImmutableMap<SymbolRef, unsigned> ARCounts;
+typedef llvm::ImmutableMap<SymbolRef, ARCounts> ARPoolContents;
+typedef llvm::ImmutableList<SymbolRef> ARStack;
 
-namespace {
-class VISIBILITY_HIDDEN AutoreleasePoolID {
-  unsigned short PoolLevel;
-  SymbolRef Sym;
-
-public:
-  AutoreleasePoolID() : PoolLevel(0) {}
-  AutoreleasePoolID(unsigned short poolLevel, SymbolRef sym)
-    : PoolLevel(poolLevel), Sym(Sym) {}
-  
-  bool operator<(const AutoreleasePoolID &X) const {
-    assert(!(PoolLevel == X.PoolLevel) || Sym == X.Sym);
-    return PoolLevel < X.PoolLevel;
-  }
-  
-  bool operator==(const AutoreleasePoolID &X) const {
-    assert(!(PoolLevel == X.PoolLevel) || Sym == X.Sym);
-    return PoolLevel == X.PoolLevel;
-  }
-  
-  bool matches(SymbolRef sym) {
-    return Sym.isInitialized() ? Sym == sym : false;
-  }
-  
-  static void Profile(llvm::FoldingSetNodeID& ID, const AutoreleasePoolID& AI) {
-    ID.AddInteger(AI.PoolLevel);
-    if (AI.Sym.isInitialized()) ID.Add(AI.Sym);
-  }
-};
-}
-
-typedef llvm::ImmutableSet<SymbolRef> AutoreleasePoolContents;
-typedef llvm::ImmutableMap<AutoreleasePoolID, AutoreleasePoolContents>
-        AutoreleaseBindings;
-
+static int AutoRCIndex = 0;
 static int AutoRBIndex = 0;
 
-// We can use 'AutoreleaseBindings' directly as the tag class into the GDM sinc
-// it is an ImmutableMap based on two types private to this source file.
+namespace { class VISIBILITY_HIDDEN AutoreleasePoolContents {}; }
+namespace { class VISIBILITY_HIDDEN AutoreleaseBindings {}; }
+
 namespace clang {
-  template<>
-  struct GRStateTrait<AutoreleaseBindings>
-    : public GRStatePartialTrait<AutoreleaseBindings> {
-    static inline void* GDMIndex() { return &AutoRBIndex; }  
-  };
-}
+template<> struct GRStateTrait<AutoreleaseBindings>
+  : public GRStatePartialTrait<ARStack> {
+  static inline void* GDMIndex() { return &AutoRBIndex; }  
+};
+
+template<> struct GRStateTrait<AutoreleasePoolContents>
+  : public GRStatePartialTrait<ARPoolContents> {
+  static inline void* GDMIndex() { return &AutoRCIndex; }  
+};
+} // end clang namespace
 
 //===----------------------------------------------------------------------===//
 // Transfer functions.
@@ -1430,23 +1404,15 @@
   RetainSummaryManager Summaries;  
   SummaryLogTy SummaryLog;
   const LangOptions&   LOpts;
+  ARCounts::Factory    ARCountFactory;
 
   BugType *useAfterRelease, *releaseNotOwned;
   BugType *leakWithinFunction, *leakAtReturn;
   BugReporter *BR;
   
-  RefBindings Update(RefBindings B, SymbolRef sym, RefVal V, ArgEffect E,
-                     RefVal::Kind& hasErr, RefBindings::Factory& RefBFactory);
-  
-  RefVal::Kind& Update(GRStateRef& state, SymbolRef sym, RefVal V,
-                       ArgEffect E, RefVal::Kind& hasErr) {
-    
-    state = state.set<RefBindings>(Update(state.get<RefBindings>(), sym, V, 
-                                          E, hasErr,
-                                          state.get_context<RefBindings>()));
-    return hasErr;
-  }
-  
+  GRStateRef Update(GRStateRef state, SymbolRef sym, RefVal V, ArgEffect E,
+                    RefVal::Kind& hasErr);
+
   void ProcessNonLeakError(ExplodedNodeSet<GRState>& Dst,
                            GRStmtNodeBuilder<GRState>& Builder,
                            Expr* NodeExpr, Expr* ErrorExpr,                        
@@ -1458,8 +1424,7 @@
   HandleSymbolDeath(GRStateManager& VMgr, const GRState* St,
                     const Decl* CD, SymbolRef sid, RefVal V, bool& hasLeak);
   
-public:
-  
+public:  
   CFRefCount(ASTContext& Ctx, bool gcenabled, const LangOptions& lopts)
     : Summaries(Ctx, gcenabled),
       LOpts(lopts), useAfterRelease(0), releaseNotOwned(0), 
@@ -1633,12 +1598,14 @@
     
     if (isa<loc::SymbolVal>(V)) {
       SymbolRef Sym = cast<loc::SymbolVal>(V).getSymbol();
-      if (RefBindings::data_type* T = state.get<RefBindings>(Sym))
-        if (Update(state, Sym, *T, GetArgE(Summ, idx), hasErr)) {
+      if (RefBindings::data_type* T = state.get<RefBindings>(Sym)) {
+        state = Update(state, Sym, *T, GetArgE(Summ, idx), hasErr);
+        if (hasErr) {
           ErrorExpr = *I;
           ErrorSym = Sym;
           break;
         }
+      }
     }  
     else if (isa<Loc>(V)) {
       if (loc::MemRegionVal* MR = dyn_cast<loc::MemRegionVal>(&V)) {
@@ -1711,11 +1678,13 @@
     SVal V = state.GetSVal(Receiver);
     if (isa<loc::SymbolVal>(V)) {
       SymbolRef Sym = cast<loc::SymbolVal>(V).getSymbol();
-      if (const RefVal* T = state.get<RefBindings>(Sym))
-        if (Update(state, Sym, *T, GetReceiverE(Summ), hasErr)) {
+      if (const RefVal* T = state.get<RefBindings>(Sym)) {
+        state = Update(state, Sym, *T, GetReceiverE(Summ), hasErr);
+        if (hasErr) {
           ErrorExpr = Receiver;
           ErrorSym = Sym;
         }
+      }
     }
   }
   
@@ -2073,10 +2042,9 @@
   return state;
 }
 
-RefBindings CFRefCount::Update(RefBindings B, SymbolRef sym,
-                               RefVal V, ArgEffect E,
-                               RefVal::Kind& hasErr,
-                               RefBindings::Factory& RefBFactory) {
+GRStateRef CFRefCount::Update(GRStateRef state, SymbolRef sym,
+                              RefVal V, ArgEffect E,
+                              RefVal::Kind& hasErr) {
 
   // In GC mode [... release] and [... retain] do nothing.
   switch (E) {
@@ -2107,13 +2075,13 @@
         hasErr = V.getKind();
         break;
       }      
-      return B;
+      return state;
 
     case Autorelease:
-      if (isGCEnabled()) return B;      
+      if (isGCEnabled()) return state;
       // Fall-through.      
     case StopTracking:
-      return RefBFactory.Remove(B, sym);
+      return state.remove<RefBindings>(sym);
 
     case IncRef:      
       switch (V.getKind()) {
@@ -2165,7 +2133,7 @@
       }      
       break;
   }
-  return RefBFactory.Add(B, sym, V);
+  return state.set<RefBindings>(sym, V);
 }
 
 //===----------------------------------------------------------------------===//





More information about the cfe-commits mailing list