GRState:
- Remove ConstNotEq from GRState/GRStateManager (!= tracking uses GDM instead).
- GRStateManager now can book-keep "contexts" (e.g., factory objects) for uses
  with data elements stored into the GDM.
- Refactor pretty-printing of states to use GRState::Printer objects
  exclusively. This removed a huge amount of pretty-printing logic from
  GRExprEngine.

CFRefCount
- Simplified some API calls based on refinements to the GDM api.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@54835 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Analysis/CFRefCount.cpp b/lib/Analysis/CFRefCount.cpp
index 9a76998..2fdd029 100644
--- a/lib/Analysis/CFRefCount.cpp
+++ b/lib/Analysis/CFRefCount.cpp
@@ -1264,7 +1264,6 @@
   UseAfterReleasesTy   UseAfterReleases;
   ReleasesNotOwnedTy   ReleasesNotOwned;
   LeaksTy              Leaks;
-  BindingsPrinter      Printer;  
   
   RefBindings Update(RefBindings B, SymbolID sym, RefVal V, ArgEffect E,
                      RefVal::Kind& hasErr);
@@ -1301,8 +1300,8 @@
   
   virtual void RegisterChecks(GRExprEngine& Eng);
  
-  virtual void getStatePrinters(std::vector<GRState::Printer*>& Printers) {
-    Printers.push_back(&Printer);
+  virtual void RegisterPrinters(std::vector<GRState::Printer*>& Printers) {
+    Printers.push_back(new BindingsPrinter());
   }
   
   bool isGCEnabled() const { return Summaries.isGCEnabled(); }
@@ -1598,7 +1597,7 @@
                ? cast<RVal>(lval::SymbolVal(Sym)) 
                : cast<RVal>(nonlval::SymbolVal(Sym));
         
-        state = state.SetRVal(Ex, X, Eng.getCFG().isBlkExpr(Ex), false);
+        state = state.SetRVal(Ex, X, false);
       }      
       
       break;
@@ -1608,14 +1607,14 @@
       assert (arg_end >= arg_beg);
       assert (idx < (unsigned) (arg_end - arg_beg));
       RVal V = state.GetRVal(*(arg_beg+idx));
-      state = state.SetRVal(Ex, V, Eng.getCFG().isBlkExpr(Ex), false);
+      state = state.SetRVal(Ex, V, false);
       break;
     }
       
     case RetEffect::ReceiverAlias: {
       assert (Receiver);
       RVal V = state.GetRVal(Receiver);
-      state = state.SetRVal(Ex, V, Eng.getCFG().isBlkExpr(Ex), false);
+      state = state.SetRVal(Ex, V, false);
       break;
     }
       
@@ -1626,15 +1625,13 @@
       QualType RetT = GetReturnType(Ex, Eng.getContext());
       
       state = state.set<RefBindings>(Sym, RefVal::makeOwned(RetT), RefBFactory);
-      state = state.SetRVal(Ex, lval::SymbolVal(Sym),
-                            Eng.getCFG().isBlkExpr(Ex), false);
+      state = state.SetRVal(Ex, lval::SymbolVal(Sym), false);
 
 #if 0
       RefBindings B = GetRefBindings(StImpl);
       SetRefBindings(StImpl, RefBFactory.Add(B, Sym, RefVal::makeOwned(RetT)));
 #endif 
 
-      
       // FIXME: Add a flag to the checker where allocations are allowed to fail.      
       if (RE.getKind() == RetEffect::OwnedAllocatedSymbol)
         state = state.AddNE(Sym, Eng.getBasicVals().getZeroWithPtrWidth());
@@ -1648,8 +1645,7 @@
       QualType RetT = GetReturnType(Ex, Eng.getContext());
       
       state = state.set<RefBindings>(Sym, RefVal::makeNotOwned(RetT), RefBFactory);
-      state = state.SetRVal(Ex, lval::SymbolVal(Sym),
-                            Eng.getCFG().isBlkExpr(Ex), false);
+      state = state.SetRVal(Ex, lval::SymbolVal(Sym), false);
       break;
     }
   }
diff --git a/lib/Analysis/GRExprEngine.cpp b/lib/Analysis/GRExprEngine.cpp
index f4ffcb1..896f473 100644
--- a/lib/Analysis/GRExprEngine.cpp
+++ b/lib/Analysis/GRExprEngine.cpp
@@ -177,7 +177,8 @@
 
 void GRExprEngine::setTransferFunctions(GRTransferFuncs* tf) {
   StateMgr.TF = tf;
-  getTF().RegisterChecks(*this);
+  tf->RegisterChecks(*this);
+  tf->RegisterPrinters(getStateManager().Printers);
 }
 
 void GRExprEngine::AddCheck(GRSimpleAPICheck* A, Stmt::StmtClass C) {
@@ -2266,109 +2267,12 @@
 #ifndef NDEBUG
 static GRExprEngine* GraphPrintCheckerState;
 static SourceManager* GraphPrintSourceManager;
-static GRState::Printer **GraphStatePrinterBeg, **GraphStatePrinterEnd;
 
 namespace llvm {
 template<>
 struct VISIBILITY_HIDDEN DOTGraphTraits<GRExprEngine::NodeTy*> :
   public DefaultDOTGraphTraits {
     
-  static void PrintVarBindings(std::ostream& Out, GRState* St) {
-
-    Out << "Variables:\\l";
-    
-    bool isFirst = true;
-    
-    for (GRState::vb_iterator I=St->vb_begin(), E=St->vb_end(); I!=E;++I) {        
-
-      if (isFirst)
-        isFirst = false;
-      else
-        Out << "\\l";
-      
-      Out << ' ' << I.getKey()->getName() << " : ";
-      I.getData().print(Out);
-    }
-    
-  }
-    
-    
-  static void PrintSubExprBindings(std::ostream& Out, GRState* St){
-    
-    bool isFirst = true;
-    
-    for (GRState::seb_iterator I=St->seb_begin(), E=St->seb_end();I!=E;++I) {        
-      
-      if (isFirst) {
-        Out << "\\l\\lSub-Expressions:\\l";
-        isFirst = false;
-      }
-      else
-        Out << "\\l";
-      
-      Out << " (" << (void*) I.getKey() << ") ";
-      I.getKey()->printPretty(Out);
-      Out << " : ";
-      I.getData().print(Out);
-    }
-  }
-    
-  static void PrintBlkExprBindings(std::ostream& Out, GRState* St){
-        
-    bool isFirst = true;
-
-    for (GRState::beb_iterator I=St->beb_begin(), E=St->beb_end(); I!=E;++I){      
-      if (isFirst) {
-        Out << "\\l\\lBlock-level Expressions:\\l";
-        isFirst = false;
-      }
-      else
-        Out << "\\l";
-
-      Out << " (" << (void*) I.getKey() << ") ";
-      I.getKey()->printPretty(Out);
-      Out << " : ";
-      I.getData().print(Out);
-    }
-  }
-    
-  static void PrintEQ(std::ostream& Out, GRState* St) {
-    GRState::ConstEqTy CE = St->ConstEq;
-    
-    if (CE.isEmpty())
-      return;
-    
-    Out << "\\l\\|'==' constraints:";
-
-    for (GRState::ConstEqTy::iterator I=CE.begin(), E=CE.end(); I!=E;++I)
-      Out << "\\l $" << I.getKey() << " : " << I.getData()->toString();
-  }
-    
-  static void PrintNE(std::ostream& Out, GRState* St) {
-    GRState::ConstNotEqTy NE = St->ConstNotEq;
-    
-    if (NE.isEmpty())
-      return;
-    
-    Out << "\\l\\|'!=' constraints:";
-    
-    for (GRState::ConstNotEqTy::iterator I=NE.begin(), EI=NE.end();
-         I != EI; ++I){
-      
-      Out << "\\l $" << I.getKey() << " : ";
-      bool isFirst = true;
-      
-      GRState::IntSetTy::iterator J=I.getData().begin(),
-                                    EJ=I.getData().end();      
-      for ( ; J != EJ; ++J) {        
-        if (isFirst) isFirst = false;
-        else Out << ", ";
-        
-        Out << (*J)->toString();
-      }    
-    }
-  }
-    
   static std::string getNodeAttributes(const GRExprEngine::NodeTy* N, void*) {
     
     if (GraphPrintCheckerState->isImplicitNullDeref(N) ||
@@ -2509,7 +2413,8 @@
     
     Out << "\\|StateID: " << (void*) N->getState() << "\\|";
 
-    N->getState()->printDOT(Out, GraphStatePrinterBeg, GraphStatePrinterEnd);
+    GRStateRef state(N->getState(), GraphPrintCheckerState->getStateManager());
+    state.printDOT(Out);
       
     Out << "\\l";
     return Out.str();
@@ -2575,19 +2480,10 @@
     GraphPrintCheckerState = this;
     GraphPrintSourceManager = &getContext().getSourceManager();
 
-    // Get the state printers.
-    std::vector<GRState::Printer*> Printers;
-    getTF().getStatePrinters(Printers);   
-    GraphStatePrinterBeg = Printers.empty() ? 0 : &Printers[0];
-    GraphStatePrinterEnd = Printers.empty() ? 0 : &Printers[0]+Printers.size();
-    
-
     llvm::ViewGraph(*G.roots_begin(), "GRExprEngine");
     
     GraphPrintCheckerState = NULL;
     GraphPrintSourceManager = NULL;
-    GraphStatePrinterBeg = NULL;
-    GraphStatePrinterEnd = NULL;
   }
 #endif
 }
@@ -2596,13 +2492,7 @@
 #ifndef NDEBUG
   GraphPrintCheckerState = this;
   GraphPrintSourceManager = &getContext().getSourceManager();
-  
-  // Get the state printers.
-  std::vector<GRState::Printer*> Printers;
-  getTF().getStatePrinters(Printers);
-  GraphStatePrinterBeg = Printers.empty() ? 0 : &Printers[0];
-  GraphStatePrinterEnd = Printers.empty() ? 0 : &Printers[0]+Printers.size();
-  
+    
   GRExprEngine::GraphTy* TrimmedG = G.Trim(Beg, End);
 
   if (!TrimmedG)
@@ -2614,7 +2504,5 @@
   
   GraphPrintCheckerState = NULL;
   GraphPrintSourceManager = NULL;
-  GraphStatePrinterBeg = NULL;
-  GraphStatePrinterEnd = NULL;
 #endif
 }
diff --git a/lib/Analysis/GRState.cpp b/lib/Analysis/GRState.cpp
index b945803..5522600 100644
--- a/lib/Analysis/GRState.cpp
+++ b/lib/Analysis/GRState.cpp
@@ -17,10 +17,71 @@
 
 using namespace clang;
 
+GRStateManager::~GRStateManager() {
+  for (std::vector<GRState::Printer*>::iterator I=Printers.begin(),
+        E=Printers.end(); I!=E; ++I)
+    delete *I;
+  
+  for (GDMContextsTy::iterator I=GDMContexts.begin(), E=GDMContexts.end();
+       I!=E; ++I)
+    I->second.second(I->second.first);
+}
+
+//===----------------------------------------------------------------------===//
+//  Basic symbolic analysis.  This will eventually be refactored into a
+//  separate component.
+//===----------------------------------------------------------------------===//
+
+typedef llvm::ImmutableMap<SymbolID,GRState::IntSetTy> ConstNotEqTy;
+
+static int ConstNotEqTyIndex = 0;
+
+namespace clang {
+  template<> struct GRStateTrait<ConstNotEqTy> {
+    typedef ConstNotEqTy             data_type;
+    typedef ConstNotEqTy::Factory&   context_type;  
+    typedef SymbolID                 key_type;
+    typedef GRState::IntSetTy        value_type;
+    typedef const GRState::IntSetTy* lookup_type;
+    
+    static data_type MakeData(void* const* p) {
+      return p ? ConstNotEqTy((ConstNotEqTy::TreeTy*) *p) : ConstNotEqTy(0);
+    }  
+    static void* MakeVoidPtr(ConstNotEqTy B) {
+      return B.getRoot();
+    }  
+    static void* GDMIndex() {
+      return &ConstNotEqTyIndex;
+    }  
+    static lookup_type Lookup(ConstNotEqTy B, SymbolID K) {
+      return B.lookup(K);
+    }  
+    static data_type Set(data_type B, key_type K, value_type E,context_type F){
+      return F.Add(B, K, E);
+    }
+    
+    static data_type Remove(ConstNotEqTy B, SymbolID K, context_type F) {
+      return F.Remove(B, K);
+    }
+    
+    static context_type MakeContext(void* p) {
+      return *((ConstNotEqTy::Factory*) p);
+    }
+    
+    static void* CreateContext(llvm::BumpPtrAllocator& Alloc) {
+      return new ConstNotEqTy::Factory(Alloc);      
+    }
+    
+    static void DeleteContext(void* Ctx) {
+      delete (ConstNotEqTy::Factory*) Ctx;
+    }      
+  };
+}
+
 bool GRState::isNotEqual(SymbolID sym, const llvm::APSInt& V) const {
 
   // Retrieve the NE-set associated with the given symbol.
-  const ConstNotEqTy::data_type* T = ConstNotEq.lookup(sym);
+  const ConstNotEqTy::data_type* T = get<ConstNotEqTy>(sym);
 
   // See if V is present in the NE-set.
   return T ? T->contains(&V) : false;
@@ -42,8 +103,8 @@
 
 const GRState*
 GRStateManager::RemoveDeadBindings(const GRState* St, Stmt* Loc,
-                                      const LiveVariables& Liveness,
-                                      DeadSymbolsTy& DSymbols) {  
+                                   const LiveVariables& Liveness,
+                                   DeadSymbolsTy& DSymbols) {  
   
   // This code essentially performs a "mark-and-sweep" of the VariableBindings.
   // The roots are any Block-level exprs and Decls that our liveness algorithm
@@ -97,7 +158,9 @@
                                        LSymbols, DSymbols);
   
   // Remove the dead symbols from the symbol tracker.
-  for (GRState::ce_iterator I = St->ce_begin(), E=St->ce_end(); I!=E; ++I) {
+  // FIXME: Refactor into something else that manages symbol values.
+  for (GRState::ConstEqTy::iterator I = St->ConstEq.begin(),
+       E=St->ConstEq.end(); I!=E; ++I) {
 
     SymbolID sym = I.getKey();    
     
@@ -107,17 +170,19 @@
     }
   }
   
-  for (GRState::cne_iterator I = St->cne_begin(), E=St->cne_end(); I!=E;++I){
-    
-    SymbolID sym = I.getKey();
-    
+  GRStateRef state(getPersistentState(NewSt), *this);
+  ConstNotEqTy CNE = state.get<ConstNotEqTy>();
+  ConstNotEqTy::Factory& CNEFactory = state.get_context<ConstNotEqTy>();
+
+  for (ConstNotEqTy::iterator I = CNE.begin(), E = CNE.end(); I != E; ++I) {
+    SymbolID sym = I.getKey();    
     if (!LSymbols.count(sym)) {
       DSymbols.insert(sym);
-      NewSt.ConstNotEq = CNEFactory.Remove(NewSt.ConstNotEq, sym);
+      CNE = CNEFactory.Remove(CNE, sym);
     }
   }
   
-  return getPersistentState(NewSt);
+  return state.set<ConstNotEqTy>(CNE);
 }
 
 const GRState* GRStateManager::SetRVal(const GRState* St, LVal LV,
@@ -148,21 +213,19 @@
 
 
 const GRState* GRStateManager::AddNE(const GRState* St, SymbolID sym,
-                                           const llvm::APSInt& V) {
+                                     const llvm::APSInt& V) {
+  
+  GRStateRef state(St, *this);
 
   // First, retrieve the NE-set associated with the given symbol.
-  GRState::ConstNotEqTy::data_type* T = St->ConstNotEq.lookup(sym);  
+  ConstNotEqTy::data_type* T = state.get<ConstNotEqTy>(sym);  
   GRState::IntSetTy S = T ? *T : ISetFactory.GetEmptySet();
   
   // Now add V to the NE set.
   S = ISetFactory.Add(S, &V);
   
   // Create a new state with the old binding replaced.
-  GRState NewSt = *St;
-  NewSt.ConstNotEq = CNEFactory.Add(NewSt.ConstNotEq, sym, S);
-    
-  // Get the persistent copy.
-  return getPersistentState(NewSt);
+  return state.set<ConstNotEqTy>(sym, S);
 }
 
 const GRState* GRStateManager::AddEQ(const GRState* St, SymbolID sym,
@@ -179,7 +242,7 @@
 const GRState* GRStateManager::getInitialState() {
 
   GRState StateImpl(EnvMgr.getInitialEnvironment(), StMgr->getInitialStore(),
-                    GDMFactory.GetEmptyMap(), CNEFactory.GetEmptyMap(),
+                    GDMFactory.GetEmptyMap(),
                     CEFactory.GetEmptyMap());
   
   return getPersistentState(StateImpl);
@@ -200,14 +263,10 @@
   return I;
 }
 
-void GRState::printDOT(std::ostream& Out,
-                       Printer** Beg, Printer** End) const {
-  print(Out, Beg, End, "\\l", "\\|");
-}
 
-void GRState::printStdErr(Printer** Beg, Printer** End) const {
-  print(*llvm::cerr, Beg, End);
-}  
+//===----------------------------------------------------------------------===//
+//  State pretty-printing.
+//===----------------------------------------------------------------------===//
 
 void GRState::print(std::ostream& Out, Printer** Beg, Printer** End,
                     const char* nl, const char* sep) const {
@@ -279,14 +338,14 @@
 
   // Print != constraints.
   // FIXME: Make just another printer do this.
-    
-  if (!ConstNotEq.isEmpty()) {
+  
+  ConstNotEqTy CNE = get<ConstNotEqTy>();
+  
+  if (!CNE.isEmpty()) {
   
     Out << nl << sep << "'!=' constraints:";
   
-    for (ConstNotEqTy::iterator I  = ConstNotEq.begin(),
-                                EI = ConstNotEq.end();   I != EI; ++I) {
-    
+    for (ConstNotEqTy::iterator I = CNE.begin(), EI = CNE.end(); I!=EI; ++I) {
       Out << nl << " $" << I.getKey() << " : ";
       isFirst = true;
     
@@ -305,6 +364,20 @@
   for ( ; Beg != End ; ++Beg) (*Beg)->Print(Out, this, nl, sep);
 }
 
+void GRStateRef::printDOT(std::ostream& Out) const {
+  print(Out, "\\l", "\\|");
+}
+
+void GRStateRef::printStdErr() const {
+  print(*llvm::cerr);
+}  
+
+void GRStateRef::print(std::ostream& Out, const char* nl, const char* sep)const{
+  GRState::Printer **beg = Mgr->Printers.empty() ? 0 : &Mgr->Printers[0];
+  GRState::Printer **end = !beg ? 0 : beg + Mgr->Printers.size();  
+  St->print(Out, beg, end, nl, sep);
+}
+
 //===----------------------------------------------------------------------===//
 // Generic Data Map.
 //===----------------------------------------------------------------------===//
@@ -313,6 +386,20 @@
   return GDM.lookup(K);
 }
 
+void*
+GRStateManager::FindGDMContext(void* K,
+                               void* (*CreateContext)(llvm::BumpPtrAllocator&),
+                               void (*DeleteContext)(void*)) {
+  
+  std::pair<void*, void (*)(void*)>& p = GDMContexts[K];
+  if (!p.first) {
+    p.first = CreateContext(Alloc);
+    p.second = DeleteContext;
+  }
+  
+  return p.first;
+}
+
 const GRState* GRStateManager::addGDM(const GRState* St, void* Key, void* Data){  
   GRState::GenericDataMap M1 = St->getGDM();
   GRState::GenericDataMap M2 = GDMFactory.Add(M1, Key, Data);
@@ -330,7 +417,8 @@
 //===----------------------------------------------------------------------===//
 
 bool GRStateManager::isEqual(const GRState* state, Expr* Ex,
-                                const llvm::APSInt& Y) {
+                             const llvm::APSInt& Y) {
+  
   RVal V = GetRVal(state, Ex);
   
   if (lval::ConcreteInt* X = dyn_cast<lval::ConcreteInt>(&V))
@@ -348,8 +436,7 @@
   return false;
 }
   
-bool GRStateManager::isEqual(const GRState* state, Expr* Ex,
-                                uint64_t x) {
+bool GRStateManager::isEqual(const GRState* state, Expr* Ex, uint64_t x) {
   return isEqual(state, Ex, BasicVals.getValue(x, Ex->getType()));
 }
 
@@ -382,7 +469,6 @@
         return AssumeSymEQ(St, cast<lval::SymbolVal>(Cond).getSymbol(),
                            BasicVals.getZeroWithPtrWidth(), isFeasible);
       
-      
     case lval::DeclValKind:
     case lval::FuncValKind:
     case lval::GotoLabelKind: