[cfe-commits] r138370 - /cfe/trunk/lib/StaticAnalyzer/Core/CFRefCount.cpp

Jordy Rose jediknil at belkadan.com
Tue Aug 23 13:27:17 PDT 2011


Author: jrose
Date: Tue Aug 23 15:27:16 2011
New Revision: 138370

URL: http://llvm.org/viewvc/llvm-project?rev=138370&view=rev
Log:
[analyzer] Move helper method Update from CFRefCount to RetainReleaseChecker. No functionality change.

Modified:
    cfe/trunk/lib/StaticAnalyzer/Core/CFRefCount.cpp

Modified: cfe/trunk/lib/StaticAnalyzer/Core/CFRefCount.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/CFRefCount.cpp?rev=138370&r1=138369&r2=138370&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/CFRefCount.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/CFRefCount.cpp Tue Aug 23 15:27:16 2011
@@ -1641,7 +1641,6 @@
   RetainSummaryManager Summaries;
   SummaryLogTy SummaryLog;
   const LangOptions&   LOpts;
-  ARCounts::Factory    ARCountFactory;
 
   BugType *useAfterRelease, *releaseNotOwned;
   BugType *deallocGC, *deallocNotOwned;
@@ -2631,144 +2630,6 @@
                     /* Callee = */ 0, Pred, state);
 }
 
-const ProgramState * CFRefCount::Update(const ProgramState * state,
-                                        SymbolRef sym,
-                                        RefVal V,
-                                        ArgEffect E,
-                                        RefVal::Kind& hasErr) {
-
-  // In GC mode [... release] and [... retain] do nothing.
-  switch (E) {
-    default: break;
-    case IncRefMsg: E = isARCorGCEnabled() ? DoNothing : IncRef; break;
-    case DecRefMsg: E = isARCorGCEnabled() ? DoNothing : DecRef; break;
-    case MakeCollectable: E = isGCEnabled() ? DecRef : DoNothing; break;
-    case NewAutoreleasePool: E = isGCEnabled() ? DoNothing :
-                                                 NewAutoreleasePool; break;
-  }
-
-  // Handle all use-after-releases.
-  if (!isGCEnabled() && V.getKind() == RefVal::Released) {
-    V = V ^ RefVal::ErrorUseAfterRelease;
-    hasErr = V.getKind();
-    return state->set<RefBindings>(sym, V);
-  }
-
-  switch (E) {
-    case DecRefMsg:
-    case IncRefMsg:
-    case MakeCollectable:
-      assert(false &&
-             "DecRefMsg/IncRefMsg/MakeCollectable already transformed");
-      return state;
-      
-    case Dealloc:
-      // Any use of -dealloc in GC is *bad*.
-      if (isGCEnabled()) {
-        V = V ^ RefVal::ErrorDeallocGC;
-        hasErr = V.getKind();
-        break;
-      }
-
-      switch (V.getKind()) {
-        default:
-          assert(false && "Invalid case.");
-        case RefVal::Owned:
-          // The object immediately transitions to the released state.
-          V = V ^ RefVal::Released;
-          V.clearCounts();
-          return state->set<RefBindings>(sym, V);
-        case RefVal::NotOwned:
-          V = V ^ RefVal::ErrorDeallocNotOwned;
-          hasErr = V.getKind();
-          break;
-      }
-      break;
-
-    case NewAutoreleasePool:
-      assert(!isGCEnabled());
-      return state->add<AutoreleaseStack>(sym);
-
-    case MayEscape:
-      if (V.getKind() == RefVal::Owned) {
-        V = V ^ RefVal::NotOwned;
-        break;
-      }
-
-      // Fall-through.
-
-    case DoNothingByRef:
-    case DoNothing:
-      return state;
-
-    case Autorelease:
-      if (isGCEnabled())
-        return state;
-
-      // Update the autorelease counts.
-      state = SendAutorelease(state, ARCountFactory, sym);
-      V = V.autorelease();
-      break;
-
-    case StopTracking:
-      return state->remove<RefBindings>(sym);
-
-    case IncRef:
-      switch (V.getKind()) {
-        default:
-          assert(false);
-
-        case RefVal::Owned:
-        case RefVal::NotOwned:
-          V = V + 1;
-          break;
-        case RefVal::Released:
-          // Non-GC cases are handled above.
-          assert(isGCEnabled());
-          V = (V ^ RefVal::Owned) + 1;
-          break;
-      }
-      break;
-
-    case SelfOwn:
-      V = V ^ RefVal::NotOwned;
-      // Fall-through.
-    case DecRef:
-    case DecRefBridgedTransfered:
-      switch (V.getKind()) {
-        default:
-          // case 'RefVal::Released' handled above.
-          assert (false);
-
-        case RefVal::Owned:
-          assert(V.getCount() > 0);
-          if (V.getCount() == 1)
-            V = V ^ (E == DecRefBridgedTransfered ? 
-                      RefVal::NotOwned : RefVal::Released);
-          V = V - 1;
-          break;
-
-        case RefVal::NotOwned:
-          if (V.getCount() > 0)
-            V = V - 1;
-          else {
-            V = V ^ RefVal::ErrorReleaseNotOwned;
-            hasErr = V.getKind();
-          }
-          break;
-
-        case RefVal::Released:
-          // Non-GC cases are handled above.
-          assert(isGCEnabled());
-          V = V ^ RefVal::ErrorUseAfterRelease;
-          hasErr = V.getKind();
-          break;
-      }
-      break;
-  }
-  return state->set<RefBindings>(sym, V);
-}
-
 //===----------------------------------------------------------------------===//
 // Pieces of the retain/release checker implemented using a CheckerVisitor.
 // More pieces of the retain/release checker will be migrated to this interface
@@ -2794,6 +2655,8 @@
   // This map is only used to ensure proper deletion of any allocated tags.
   mutable SymbolTagMap DeadSymbolTags;
 
+  mutable ARCounts::Factory ARCountFactory;
+
 public:  
 
   virtual ~RetainReleaseChecker() {
@@ -2831,6 +2694,10 @@
   void checkDeadSymbols(SymbolReaper &SymReaper, CheckerContext &C) const;
   void checkEndPath(EndOfFunctionNodeBuilder &Builder, ExprEngine &Eng) const;
 
+  const ProgramState *updateSymbol(const ProgramState *state, SymbolRef sym,
+                                   RefVal V, ArgEffect E,
+                                   RefVal::Kind &hasErr) const;
+
   void processNonLeakError(const ProgramState *St, SourceRange ErrorRange,
                            RefVal::Kind ErrorKind, SymbolRef Sym,
                            CheckerContext &C) const;
@@ -3026,14 +2893,12 @@
   if (!T)
     return;
 
-  // This is gross.  Once the checker and CFRefCount are unified,
-  // this will go away.
-  CFRefCount &cf = static_cast<CFRefCount&>(C.getEngine().getTF());
   RefVal::Kind hasErr = (RefVal::Kind) 0;
-  state = cf.Update(state, Sym, *T, AE, hasErr);
+  state = updateSymbol(state, Sym, *T, AE, hasErr);
   
   if (hasErr) {
-    
+    // FIXME: If we get an error during a bridge cast, should we report it?
+    // Should we assert that there is no error?
     return;
   }
 
@@ -3101,7 +2966,7 @@
                                         const CallOrObjCMessage &CallOrMsg,
                                         InstanceReceiver Receiver,
                                         CheckerContext &C) const {
-  // FIXME: This goes away once the Update() method moves to the checker.
+  // FIXME: This goes away when the RetainSummaryManager moves to the checker.
   CFRefCount &TF = static_cast<CFRefCount&>(C.getEngine().getTF());
 
   const ProgramState *state = C.getState();
@@ -3116,7 +2981,7 @@
 
     if (SymbolRef Sym = V.getAsLocSymbol()) {
       if (RefBindings::data_type *T = state->get<RefBindings>(Sym)) {
-        state = TF.Update(state, Sym, *T, Summ.getArg(idx), hasErr);
+        state = updateSymbol(state, Sym, *T, Summ.getArg(idx), hasErr);
         if (hasErr) {
           ErrorRange = CallOrMsg.getArgSourceRange(idx);
           ErrorSym = Sym;
@@ -3132,7 +2997,7 @@
     if (SymbolRef Sym = Receiver.getSValAsScalarOrLoc(state).getAsLocSymbol()) {
       if (const RefVal *T = state->get<RefBindings>(Sym)) {
         ReceiverIsTracked = true;
-        state = TF.Update(state, Sym, *T, Summ.getReceiverEffect(), hasErr);
+        state = updateSymbol(state, Sym, *T, Summ.getReceiverEffect(), hasErr);
         if (hasErr) {
           ErrorRange = Receiver.getSourceRange();
           ErrorSym = Sym;
@@ -3221,6 +3086,149 @@
   if (NewNode) TF.SummaryLog[NewNode] = &Summ;
 }
 
+
+const ProgramState *
+RetainReleaseChecker::updateSymbol(const ProgramState *state, SymbolRef sym,
+                                   RefVal V, ArgEffect E,
+                                   RefVal::Kind &hasErr) const {
+  // FIXME: This will go away when the ARC/GC state moves to the checker.
+  ExprEngine *Eng = 
+    static_cast<ExprEngine*>(state->getStateManager().getOwningEngine());
+  CFRefCount &TF = static_cast<CFRefCount&>(Eng->getTF());
+
+  // In GC mode [... release] and [... retain] do nothing.
+  switch (E) {
+    default: break;
+    case IncRefMsg: E = TF.isARCorGCEnabled() ? DoNothing : IncRef; break;
+    case DecRefMsg: E = TF.isARCorGCEnabled() ? DoNothing : DecRef; break;
+    case MakeCollectable: E = TF.isGCEnabled() ? DecRef : DoNothing; break;
+    case NewAutoreleasePool: E = TF.isGCEnabled() ? DoNothing :
+                                                    NewAutoreleasePool; break;
+  }
+
+  // Handle all use-after-releases.
+  if (!TF.isGCEnabled() && V.getKind() == RefVal::Released) {
+    V = V ^ RefVal::ErrorUseAfterRelease;
+    hasErr = V.getKind();
+    return state->set<RefBindings>(sym, V);
+  }
+
+  switch (E) {
+    case DecRefMsg:
+    case IncRefMsg:
+    case MakeCollectable:
+      llvm_unreachable("DecRefMsg/IncRefMsg/MakeCollectable already converted");
+      return state;
+
+    case Dealloc:
+      // Any use of -dealloc in GC is *bad*.
+      if (TF.isGCEnabled()) {
+        V = V ^ RefVal::ErrorDeallocGC;
+        hasErr = V.getKind();
+        break;
+      }
+
+      switch (V.getKind()) {
+        default:
+          llvm_unreachable("Invalid RefVal state for an explicit dealloc.");
+          break;
+        case RefVal::Owned:
+          // The object immediately transitions to the released state.
+          V = V ^ RefVal::Released;
+          V.clearCounts();
+          return state->set<RefBindings>(sym, V);
+        case RefVal::NotOwned:
+          V = V ^ RefVal::ErrorDeallocNotOwned;
+          hasErr = V.getKind();
+          break;
+      }
+      break;
+
+    case NewAutoreleasePool:
+      assert(!TF.isGCEnabled());
+      return state->add<AutoreleaseStack>(sym);
+
+    case MayEscape:
+      if (V.getKind() == RefVal::Owned) {
+        V = V ^ RefVal::NotOwned;
+        break;
+      }
+
+      // Fall-through.
+
+    case DoNothingByRef:
+    case DoNothing:
+      return state;
+
+    case Autorelease:
+      if (TF.isGCEnabled())
+        return state;
+
+      // Update the autorelease counts.
+      state = SendAutorelease(state, ARCountFactory, sym);
+      V = V.autorelease();
+      break;
+
+    case StopTracking:
+      return state->remove<RefBindings>(sym);
+
+    case IncRef:
+      switch (V.getKind()) {
+        default:
+          llvm_unreachable("Invalid RefVal state for a retain.");
+          break;
+        case RefVal::Owned:
+        case RefVal::NotOwned:
+          V = V + 1;
+          break;
+        case RefVal::Released:
+          // Non-GC cases are handled above.
+          assert(TF.isGCEnabled());
+          V = (V ^ RefVal::Owned) + 1;
+          break;
+      }
+      break;
+
+    case SelfOwn:
+      V = V ^ RefVal::NotOwned;
+      // Fall-through.
+    case DecRef:
+    case DecRefBridgedTransfered:
+      switch (V.getKind()) {
+        default:
+          // case 'RefVal::Released' handled above.
+          llvm_unreachable("Invalid RefVal state for a release.");
+          break;
+
+        case RefVal::Owned:
+          assert(V.getCount() > 0);
+          if (V.getCount() == 1)
+            V = V ^ (E == DecRefBridgedTransfered ? 
+                      RefVal::NotOwned : RefVal::Released);
+          V = V - 1;
+          break;
+
+        case RefVal::NotOwned:
+          if (V.getCount() > 0)
+            V = V - 1;
+          else {
+            V = V ^ RefVal::ErrorReleaseNotOwned;
+            hasErr = V.getKind();
+          }
+          break;
+
+        case RefVal::Released:
+          // Non-GC cases are handled above.
+          assert(TF.isGCEnabled());
+          V = V ^ RefVal::ErrorUseAfterRelease;
+          hasErr = V.getKind();
+          break;
+      }
+      break;
+  }
+  return state->set<RefBindings>(sym, V);
+}
+
 void RetainReleaseChecker::processNonLeakError(const ProgramState *St,
                                                SourceRange ErrorRange,
                                                RefVal::Kind ErrorKind,





More information about the cfe-commits mailing list