Prototype (pre-alpha) implementation of CFRef checker.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@48272 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/Analysis/CFRefCount.cpp b/Analysis/CFRefCount.cpp
index ea9c8bf..a1f63b1 100644
--- a/Analysis/CFRefCount.cpp
+++ b/Analysis/CFRefCount.cpp
@@ -86,6 +86,10 @@
     return (*Args)[idx];
   }
   
+  RetEffect getRet() const {
+    return Ret;
+  }
+  
   typedef ArgEffects::const_iterator arg_iterator;
   
   arg_iterator begin_args() const { return Args->begin(); }
@@ -113,12 +117,24 @@
   llvm::BumpPtrAllocator BPAlloc;
   
   ArgEffects             ScratchArgs;
+  
+  
+  ArgEffects*   getArgEffects();
 
+  CFRefSummary* getCannedCFSummary(FunctionTypeProto* FT, bool isRetain);
+
+  CFRefSummary* getCFSummary(FunctionDecl* FD, const char* FName);
+  
+  CFRefSummary* getCFSummaryCreateRule(FunctionTypeProto* FT);
+  CFRefSummary* getCFSummaryGetRule(FunctionTypeProto* FT);  
+  
+  CFRefSummary* getPersistentSummary(ArgEffects* AE, RetEffect RE);
+  
 public:
   CFRefSummaryManager() {}
   ~CFRefSummaryManager();
   
-  CFRefSummary* getSummary(FunctionDecl* FD);
+  CFRefSummary* getSummary(FunctionDecl* FD, ASTContext& Ctx);
 };
   
 } // end anonymous namespace
@@ -137,7 +153,59 @@
     I->getValue().~ArgEffects();
 }
 
-CFRefSummary* CFRefSummaryManager::getSummary(FunctionDecl* FD) {
+ArgEffects* CFRefSummaryManager::getArgEffects() {
+
+  assert (!ScratchArgs.empty());
+  
+  llvm::FoldingSetNodeID profile;
+  profile.Add(ScratchArgs);
+  void* InsertPos;
+  
+  llvm::FoldingSetNodeWrapper<ArgEffects>* E =
+    AESet.FindNodeOrInsertPos(profile, InsertPos);
+  
+  if (E) {    
+    ScratchArgs.clear();
+    return &E->getValue();
+  }
+  
+  E = (llvm::FoldingSetNodeWrapper<ArgEffects>*)
+      BPAlloc.Allocate<llvm::FoldingSetNodeWrapper<ArgEffects> >();
+                       
+  new (E) llvm::FoldingSetNodeWrapper<ArgEffects>(ScratchArgs);
+  AESet.InsertNode(E, InsertPos);
+
+  ScratchArgs.clear();
+  return &E->getValue();
+}
+
+CFRefSummary* CFRefSummaryManager::getPersistentSummary(ArgEffects* AE,
+                                                        RetEffect RE) {
+  
+  llvm::FoldingSetNodeID profile;
+  CFRefSummary::Profile(profile, AE, RE);
+  void* InsertPos;
+  
+  CFRefSummary* Summ = SummarySet.FindNodeOrInsertPos(profile, InsertPos);
+  
+  if (Summ)
+    return Summ;
+  
+  Summ = (CFRefSummary*) BPAlloc.Allocate<CFRefSummary>();
+  new (Summ) CFRefSummary(AE, RE);
+  SummarySet.InsertNode(Summ, InsertPos);
+  
+  return Summ;
+}
+
+
+CFRefSummary* CFRefSummaryManager::getSummary(FunctionDecl* FD,
+                                              ASTContext& Ctx) {
+
+  SourceLocation Loc = FD->getLocation();
+  
+  if (!Loc.isFileID())
+    return NULL;
   
   { // Look into our cache of summaries to see if we have already computed
     // a summary for this FunctionDecl.
@@ -148,12 +216,169 @@
       return I->second;
   }
   
-  //
+#if 0
+  SourceManager& SrcMgr = Ctx.getSourceManager();
+  unsigned fid = Loc.getFileID();
+  const FileEntry* FE = SrcMgr.getFileEntryForID(fid);
   
+  if (!FE)
+    return NULL;
+  
+  const char* DirName = FE->getDir()->getName();  
+  assert (DirName);
+  assert (strlen(DirName) > 0);
+  
+  if (!strstr(DirName, "CoreFoundation")) {
+    SummaryMap[FD] = NULL;
+    return NULL;
+  }
+#endif
+  
+  const char* FName = FD->getIdentifier()->getName();
+    
+  if (FName[0] == 'C' && FName[1] == 'F') {
+    CFRefSummary* S = getCFSummary(FD, FName);
+    SummaryMap[FD] = S;
+    return S;
+  }
   
   return NULL;  
 }
 
+CFRefSummary* CFRefSummaryManager::getCFSummary(FunctionDecl* FD,
+                                                const char* FName) {
+  
+  // For now, only generate summaries for functions that have a prototype.
+  
+  FunctionTypeProto* FT =
+    dyn_cast<FunctionTypeProto>(FD->getType().getTypePtr());
+  
+  if (!FT)
+    return NULL;
+  
+  FName += 2;
+
+  if (strcmp(FName, "Retain") == 0)
+    return getCannedCFSummary(FT, true);
+  
+  if (strcmp(FName, "Release") == 0)
+    return getCannedCFSummary(FT, false);
+  
+  assert (ScratchArgs.empty());
+  bool usesCreateRule = false;
+  
+  if (strstr(FName, "Create"))
+    usesCreateRule = true;
+  
+  if (!usesCreateRule && strstr(FName, "Copy"))
+    usesCreateRule = true;
+  
+  if (usesCreateRule)
+    return getCFSummaryCreateRule(FT);
+
+  if (strstr(FName, "Get"))
+    return getCFSummaryGetRule(FT);
+  
+  return NULL;
+}
+
+CFRefSummary* CFRefSummaryManager::getCannedCFSummary(FunctionTypeProto* FT,
+                                                      bool isRetain) {
+  
+  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".
+  
+  const char* TDName = ArgT->getDecl()->getIdentifier()->getName();
+  assert (TDName);
+  
+  if (strcmp("CFTypeRef", TDName) == 0)
+    return NULL;
+  
+  if (!ArgT->isPointerType())
+    return NULL;
+  
+  // Check the return type.  It should also be "CFTypeRef".
+  
+  QualType RetTy = FT->getResultType();
+  
+  if (RetTy.getTypePtr() != ArgT)
+    return NULL;
+  
+  // The function's interface checks out.  Generate a canned summary.
+  
+  assert (ScratchArgs.empty());
+  ScratchArgs.push_back(isRetain ? IncRef : DecRef);
+  
+  return getPersistentSummary(getArgEffects(), RetEffect::MakeAlias(0));
+}
+
+static bool isCFRefType(QualType T) {
+  
+  if (!T->isPointerType())
+    return false;
+  
+  // Check the typedef for the name "CF" and the substring "Ref".
+  
+  TypedefType* TD = dyn_cast<TypedefType>(T.getTypePtr());
+  
+  if (!TD)
+    return false;
+  
+  const char* TDName = TD->getDecl()->getIdentifier()->getName();
+  assert (TDName);
+  
+  if (TDName[0] != 'C' || TDName[1] != 'F')
+    return false;
+  
+  if (strstr(TDName, "Ref") == 0)
+    return false;
+  
+  return true;
+}
+  
+
+CFRefSummary*
+CFRefSummaryManager::getCFSummaryCreateRule(FunctionTypeProto* FT) {
+ 
+  if (!isCFRefType(FT->getResultType()))
+    return NULL;
+
+  assert (ScratchArgs.empty());
+  
+  // FIXME: Add special-cases for functions that retain/release.  For now
+  //  just handle the default case.
+  
+  for (unsigned i = 0, n = FT->getNumArgs(); i != n; ++i)
+    ScratchArgs.push_back(DoNothing);
+  
+  return getPersistentSummary(getArgEffects(), RetEffect::MakeOwned());
+}
+
+CFRefSummary*
+CFRefSummaryManager::getCFSummaryGetRule(FunctionTypeProto* FT) {
+  
+  if (!isCFRefType(FT->getResultType()))
+    return NULL;
+  
+  assert (ScratchArgs.empty());
+  
+  // FIXME: Add special-cases for functions that retain/release.  For now
+  //  just handle the default case.
+  
+  for (unsigned i = 0, n = FT->getNumArgs(); i != n; ++i)
+    ScratchArgs.push_back(DoNothing);
+  
+  return getPersistentSummary(getArgEffects(), RetEffect::MakeNotOwned());
+}
+
 //===----------------------------------------------------------------------===//
 // Transfer functions.
 //===----------------------------------------------------------------------===//
@@ -246,8 +471,8 @@
   // Instance variables.
   
   CFRefSummaryManager Summaries;
-  RefBFactoryTy  RefBFactory;
-  
+  RefBFactoryTy       RefBFactory;
+     
   UseAfterReleasesTy UseAfterReleases;
   ReleasesNotOwnedTy ReleasesNotOwned;
   
@@ -282,9 +507,8 @@
   // Calls.
   
   virtual void EvalCall(ExplodedNodeSet<ValueState>& Dst,
-                        ValueStateManager& StateMgr,
+                        GRExprEngine& Engine,
                         GRStmtNodeBuilder<ValueState>& Builder,
-                        BasicValueFactory& BasicVals,
                         CallExpr* CE, LVal L,
                         ExplodedNode<ValueState>* Pred);  
 };
@@ -307,11 +531,12 @@
 }
 
 void CFRefCount::EvalCall(ExplodedNodeSet<ValueState>& Dst,
-                            ValueStateManager& StateMgr,
-                            GRStmtNodeBuilder<ValueState>& Builder,
-                            BasicValueFactory& BasicVals,
-                            CallExpr* CE, LVal L,
-                            ExplodedNode<ValueState>* Pred) {
+                          GRExprEngine& Engine,
+                          GRStmtNodeBuilder<ValueState>& Builder,
+                          CallExpr* CE, LVal L,
+                          ExplodedNode<ValueState>* Pred) {
+  
+  ValueStateManager& StateMgr = Engine.getStateManager();
   
   // FIXME: Support calls to things other than lval::FuncVal.  At the very
   //  least we should stop tracking ref-state for ref-counted objects passed
@@ -323,7 +548,7 @@
 
   lval::FuncVal FV = cast<lval::FuncVal>(L);
   FunctionDecl* FD = FV.getDecl();
-  CFRefSummary* Summ = Summaries.getSummary(FD);
+  CFRefSummary* Summ = Summaries.getSummary(FD, Engine.getContext());
 
   // Get the state.
   
@@ -355,35 +580,36 @@
             
       if (isa<LVal>(V))
         StateMgr.Unbind(StVals, cast<LVal>(V));
-    }    
+    }
+    
+    St = StateMgr.getPersistentState(StVals);
+    Builder.Nodify(Dst, CE, Pred, St);
+    return;
   }
-  else {
+  
+  // This function has a summary.  Evaluate the effect of the arguments.
+  
+  unsigned idx = 0;
+  
+  for (CallExpr::arg_iterator I=CE->arg_begin(), E=CE->arg_end();
+        I!=E; ++I, ++idx) {
     
-    // This function has a summary.  Evaluate the effect of the arguments.
+    RVal V = StateMgr.GetRVal(St, *I);
     
-    unsigned idx = 0;
-    
-    for (CallExpr::arg_iterator I=CE->arg_begin(), E=CE->arg_end();
-          I!=E; ++I, ++idx) {
-      
-      RVal V = StateMgr.GetRVal(St, *I);
-      
-      if (isa<lval::SymbolVal>(V)) {
-        SymbolID Sym = cast<lval::SymbolVal>(V).getSymbol();
-        RefBindings B = GetRefBindings(StVals);
+    if (isa<lval::SymbolVal>(V)) {
+      SymbolID Sym = cast<lval::SymbolVal>(V).getSymbol();
+      RefBindings B = GetRefBindings(StVals);
 
-        if (RefBindings::TreeTy* T = B.SlimFind(Sym)) {
-          B = Update(B, Sym, T->getValue().second, Summ->getArg(idx), hasError);
-          SetRefBindings(StVals, B);
-          if (hasError) break;
-        }
+      if (RefBindings::TreeTy* T = B.SlimFind(Sym)) {
+        B = Update(B, Sym, T->getValue().second, Summ->getArg(idx), hasError);
+        SetRefBindings(StVals, B);
+        if (hasError) break;
       }
-    }    
-  }
-  
-  St = StateMgr.getPersistentState(StVals);
-  
+    }
+  }    
+    
   if (hasError) {
+    St = StateMgr.getPersistentState(StVals);
     GRExprEngine::NodeTy* N = Builder.generateNode(CE, St, Pred);
 
     if (N) {
@@ -399,10 +625,61 @@
           ReleasesNotOwned.insert(N);
           break;
       }
-    }    
+    }
+    
+    return;
   }
-  else
-    Builder.Nodify(Dst, CE, Pred, St);
+
+  // Finally, consult the summary for the return value.
+  
+  RetEffect RE = Summ->getRet();
+  St = StateMgr.getPersistentState(StVals);
+
+  
+  switch (RE.getKind()) {
+    default:
+      assert (false && "Unhandled RetEffect."); break;
+    
+    case RetEffect::Alias: {
+      unsigned idx = RE.getValue();
+      assert (idx < CE->getNumArgs());
+      RVal V = StateMgr.GetRVal(St, CE->getArg(idx));
+      St = StateMgr.SetRVal(St, CE, V, Engine.getCFG().isBlkExpr(CE), false);
+      break;
+    }
+      
+    case RetEffect::OwnedSymbol: {
+      unsigned Count = Builder.getCurrentBlockCount();
+      SymbolID Sym = Engine.getSymbolManager().getCallRetValSymbol(CE, Count);
+
+      ValueState StImpl = *St;
+      RefBindings B = GetRefBindings(StImpl);
+      SetRefBindings(StImpl, RefBFactory.Add(B, Sym, RefVal::makeOwned(1)));
+      
+      St = StateMgr.SetRVal(StateMgr.getPersistentState(StImpl),
+                            CE, lval::SymbolVal(Sym),
+                            Engine.getCFG().isBlkExpr(CE), false);
+      
+      break;
+    }
+      
+    case RetEffect::NotOwnedSymbol: {
+      unsigned Count = Builder.getCurrentBlockCount();
+      SymbolID Sym = Engine.getSymbolManager().getCallRetValSymbol(CE, Count);
+      
+      ValueState StImpl = *St;
+      RefBindings B = GetRefBindings(StImpl);
+      SetRefBindings(StImpl, RefBFactory.Add(B, Sym, RefVal::makeNotOwned()));
+      
+      St = StateMgr.SetRVal(StateMgr.getPersistentState(StImpl),
+                            CE, lval::SymbolVal(Sym),
+                            Engine.getCFG().isBlkExpr(CE), false);
+      
+      break;
+    }
+  }
+      
+  Builder.Nodify(Dst, CE, Pred, St);
 }
 
 
@@ -418,6 +695,12 @@
       assert (false && "Unhandled CFRef transition.");
       
     case DoNothing:
+      if (V.getKind() == RefVal::Released) {
+        V = RefVal::makeUseAfterRelease();        
+        hasError = V.getKind();
+        break;
+      }
+      
       return B;
       
     case IncRef:      
diff --git a/Analysis/GRSimpleVals.cpp b/Analysis/GRSimpleVals.cpp
index ae06917..16cd674 100644
--- a/Analysis/GRSimpleVals.cpp
+++ b/Analysis/GRSimpleVals.cpp
@@ -95,13 +95,13 @@
   if (Diag.hasErrorOccurred())
     return 0;
   
-  GRCoreEngine<GRExprEngine> Engine(cfg, FD, Ctx);
-  GRExprEngine* CheckerState = &Engine.getCheckerState();
+  GRCoreEngine<GRExprEngine> Eng(cfg, FD, Ctx);
+  GRExprEngine* CheckerState = &Eng.getCheckerState();
   GRSimpleVals GRSV;
   CheckerState->setTransferFunctions(GRSV);
   
   // Execute the worklist algorithm.
-  Engine.ExecuteWorkList(50000);
+  Eng.ExecuteWorkList(50000);
   
   SourceManager& SrcMgr = Ctx.getSourceManager();  
 
@@ -144,7 +144,7 @@
   if (Visualize) CheckerState->ViewGraph(TrimGraph);
 #endif
   
-  return Engine.getGraph().size();
+  return Eng.getGraph().size();
 }
   
 } // end clang namespace
@@ -153,14 +153,16 @@
 // Transfer function for Casts.
 //===----------------------------------------------------------------------===//
 
-RVal GRSimpleVals::EvalCast(BasicValueFactory& BasicVals, NonLVal X, QualType T) {
+RVal GRSimpleVals::EvalCast(GRExprEngine& Eng, NonLVal X, QualType T) {
   
   if (!isa<nonlval::ConcreteInt>(X))
     return UnknownVal();
+
+  BasicValueFactory& BasicVals = Eng.getBasicVals();
   
   llvm::APSInt V = cast<nonlval::ConcreteInt>(X).getValue();
   V.setIsUnsigned(T->isUnsignedIntegerType() || T->isPointerType());
-  V.extOrTrunc(BasicVals.getContext().getTypeSize(T));
+  V.extOrTrunc(Eng.getContext().getTypeSize(T));
   
   if (T->isPointerType())
     return lval::ConcreteInt(BasicVals.getValue(V));
@@ -170,7 +172,7 @@
 
 // Casts.
 
-RVal GRSimpleVals::EvalCast(BasicValueFactory& BasicVals, LVal X, QualType T) {
+RVal GRSimpleVals::EvalCast(GRExprEngine& Eng, LVal X, QualType T) {
   
   if (T->isPointerType() || T->isReferenceType())
     return X;
@@ -180,33 +182,35 @@
   if (!isa<lval::ConcreteInt>(X))
     return UnknownVal();
   
+  BasicValueFactory& BasicVals = Eng.getBasicVals();
+  
   llvm::APSInt V = cast<lval::ConcreteInt>(X).getValue();
   V.setIsUnsigned(T->isUnsignedIntegerType() || T->isPointerType());
-  V.extOrTrunc(BasicVals.getContext().getTypeSize(T));
+  V.extOrTrunc(Eng.getContext().getTypeSize(T));
 
   return nonlval::ConcreteInt(BasicVals.getValue(V));
 }
 
 // Unary operators.
 
-RVal GRSimpleVals::EvalMinus(BasicValueFactory& BasicVals, UnaryOperator* U, NonLVal X){
+RVal GRSimpleVals::EvalMinus(GRExprEngine& Eng, UnaryOperator* U, NonLVal X){
   
   switch (X.getSubKind()) {
       
     case nonlval::ConcreteIntKind:
-      return cast<nonlval::ConcreteInt>(X).EvalMinus(BasicVals, U);
+      return cast<nonlval::ConcreteInt>(X).EvalMinus(Eng.getBasicVals(), U);
       
     default:
       return UnknownVal();
   }
 }
 
-RVal GRSimpleVals::EvalComplement(BasicValueFactory& BasicVals, NonLVal X) {
+RVal GRSimpleVals::EvalComplement(GRExprEngine& Eng, NonLVal X) {
 
   switch (X.getSubKind()) {
       
     case nonlval::ConcreteIntKind:
-      return cast<nonlval::ConcreteInt>(X).EvalComplement(BasicVals);
+      return cast<nonlval::ConcreteInt>(X).EvalComplement(Eng.getBasicVals());
       
     default:
       return UnknownVal();
@@ -215,8 +219,11 @@
 
 // Binary operators.
 
-RVal GRSimpleVals::EvalBinOp(BasicValueFactory& BasicVals, BinaryOperator::Opcode Op,
-                             NonLVal L, NonLVal R)  {  
+RVal GRSimpleVals::EvalBinOp(GRExprEngine& Eng, BinaryOperator::Opcode Op,
+                             NonLVal L, NonLVal R)  {
+  
+  BasicValueFactory& BasicVals = Eng.getBasicVals();
+  
   while (1) {
     
     switch (L.getSubKind()) {
@@ -242,7 +249,7 @@
         if (isa<nonlval::ConcreteInt>(R)) {
           const SymIntConstraint& C =
             BasicVals.getConstraint(cast<nonlval::SymbolVal>(L).getSymbol(), Op,
-                                 cast<nonlval::ConcreteInt>(R).getValue());
+                                    cast<nonlval::ConcreteInt>(R).getValue());
           
           return nonlval::SymIntConstraintVal(C);
         }
@@ -256,7 +263,7 @@
 
 // Binary Operators (except assignments and comma).
 
-RVal GRSimpleVals::EvalBinOp(BasicValueFactory& BasicVals, BinaryOperator::Opcode Op,
+RVal GRSimpleVals::EvalBinOp(GRExprEngine& Eng, BinaryOperator::Opcode Op,
                              LVal L, LVal R) {
   
   switch (Op) {
@@ -265,23 +272,25 @@
       return UnknownVal();
       
     case BinaryOperator::EQ:
-      return EvalEQ(BasicVals, L, R);
+      return EvalEQ(Eng, L, R);
       
     case BinaryOperator::NE:
-      return EvalNE(BasicVals, L, R);      
+      return EvalNE(Eng, L, R);      
   }
 }
 
 // Pointer arithmetic.
 
-RVal GRSimpleVals::EvalBinOp(BasicValueFactory& BasicVals, BinaryOperator::Opcode Op,
+RVal GRSimpleVals::EvalBinOp(GRExprEngine& Eng, BinaryOperator::Opcode Op,
                              LVal L, NonLVal R) {  
   return UnknownVal();
 }
 
 // Equality operators for LVals.
 
-RVal GRSimpleVals::EvalEQ(BasicValueFactory& BasicVals, LVal L, LVal R) {
+RVal GRSimpleVals::EvalEQ(GRExprEngine& Eng, LVal L, LVal R) {
+  
+  BasicValueFactory& BasicVals = Eng.getBasicVals();
   
   switch (L.getSubKind()) {
 
@@ -337,8 +346,10 @@
   return NonLVal::MakeIntTruthVal(BasicVals, false);
 }
 
-RVal GRSimpleVals::EvalNE(BasicValueFactory& BasicVals, LVal L, LVal R) {
+RVal GRSimpleVals::EvalNE(GRExprEngine& Eng, LVal L, LVal R) {
   
+  BasicValueFactory& BasicVals = Eng.getBasicVals();
+
   switch (L.getSubKind()) {
 
     default:
@@ -356,8 +367,8 @@
       else if (isa<lval::SymbolVal>(R)) {        
         const SymIntConstraint& C =
           BasicVals.getConstraint(cast<lval::SymbolVal>(R).getSymbol(),
-                               BinaryOperator::NE,
-                               cast<lval::ConcreteInt>(L).getValue());
+                                  BinaryOperator::NE,
+                                  cast<lval::ConcreteInt>(L).getValue());
         
         return nonlval::SymIntConstraintVal(C);
       }
@@ -368,8 +379,8 @@
       if (isa<lval::ConcreteInt>(R)) {          
         const SymIntConstraint& C =
           BasicVals.getConstraint(cast<lval::SymbolVal>(L).getSymbol(),
-                               BinaryOperator::NE,
-                               cast<lval::ConcreteInt>(R).getValue());
+                                  BinaryOperator::NE,
+                                  cast<lval::ConcreteInt>(R).getValue());
         
         return nonlval::SymIntConstraintVal(C);
       }
@@ -398,9 +409,8 @@
 //===----------------------------------------------------------------------===//
 
 void GRSimpleVals::EvalCall(ExplodedNodeSet<ValueState>& Dst,
-                            ValueStateManager& StateMgr,
+                            GRExprEngine& Eng,
                             GRStmtNodeBuilder<ValueState>& Builder,
-                            BasicValueFactory& BasicVals,
                             CallExpr* CE, LVal L,
                             ExplodedNode<ValueState>* Pred) {
   
@@ -411,10 +421,10 @@
   for (CallExpr::arg_iterator I = CE->arg_begin(), E = CE->arg_end();
         I != E; ++I) {
 
-    RVal V = StateMgr.GetRVal(St, *I);
+    RVal V = Eng.getStateManager().GetRVal(St, *I);
     
     if (isa<LVal>(V))
-      St = StateMgr.SetRVal(St, cast<LVal>(V), UnknownVal());
+      St = Eng.getStateManager().SetRVal(St, cast<LVal>(V), UnknownVal());
   }
     
   Builder.Nodify(Dst, CE, Pred, St);
diff --git a/Analysis/GRSimpleVals.h b/Analysis/GRSimpleVals.h
index 33ccd26..2b3d0fd 100644
--- a/Analysis/GRSimpleVals.h
+++ b/Analysis/GRSimpleVals.h
@@ -28,34 +28,33 @@
   
   // Casts.
   
-  virtual RVal EvalCast(BasicValueFactory& BasicVals, NonLVal V, QualType CastT);
-  virtual RVal EvalCast(BasicValueFactory& BasicVals, LVal V, QualType CastT);
+  virtual RVal EvalCast(GRExprEngine& Engine, NonLVal V, QualType CastT);
+  virtual RVal EvalCast(GRExprEngine& Engine, LVal V, QualType CastT);
   
   // Unary Operators.
   
-  virtual RVal EvalMinus(BasicValueFactory& BasicVals, UnaryOperator* U, NonLVal X);
+  virtual RVal EvalMinus(GRExprEngine& Engine, UnaryOperator* U, NonLVal X);
 
-  virtual RVal EvalComplement(BasicValueFactory& BasicVals, NonLVal X);
+  virtual RVal EvalComplement(GRExprEngine& Engine, NonLVal X);
   
   // Binary Operators.
   
-  virtual RVal EvalBinOp(BasicValueFactory& BasicVals, BinaryOperator::Opcode Op,
+  virtual RVal EvalBinOp(GRExprEngine& Engine, BinaryOperator::Opcode Op,
                          NonLVal L, NonLVal R);
   
-  virtual RVal EvalBinOp(BasicValueFactory& BasicVals, BinaryOperator::Opcode Op,
+  virtual RVal EvalBinOp(GRExprEngine& Engine, BinaryOperator::Opcode Op,
                          LVal L, LVal R);
   
   // Pointer arithmetic.
   
-  virtual RVal EvalBinOp(BasicValueFactory& BasicVals, BinaryOperator::Opcode Op,
+  virtual RVal EvalBinOp(GRExprEngine& Engine, BinaryOperator::Opcode Op,
                          LVal L, NonLVal R);  
   
   // Calls.
   
   virtual void EvalCall(ExplodedNodeSet<ValueState>& Dst,
-                        ValueStateManager& StateMgr,
+                        GRExprEngine& Engine,
                         GRStmtNodeBuilder<ValueState>& Builder,
-                        BasicValueFactory& BasicVals,
                         CallExpr* CE, LVal L,
                         ExplodedNode<ValueState>* Pred);
   
@@ -63,8 +62,8 @@
   
   // Equality operators for LVals.
   
-  RVal EvalEQ(BasicValueFactory& BasicVals, LVal L, LVal R);
-  RVal EvalNE(BasicValueFactory& BasicVals, LVal L, LVal R);
+  RVal EvalEQ(GRExprEngine& Engine, LVal L, LVal R);
+  RVal EvalNE(GRExprEngine& Engine, LVal L, LVal R);
 };
   
 } // end clang namespace
diff --git a/Analysis/SymbolManager.cpp b/Analysis/SymbolManager.cpp
index 95fbbb9..5454649 100644
--- a/Analysis/SymbolManager.cpp
+++ b/Analysis/SymbolManager.cpp
@@ -20,30 +20,84 @@
 
   assert (isa<ParmVarDecl>(D) || D->hasGlobalStorage());
   
-  SymbolID& X = DataToSymbol[getKey(D)];
+  llvm::FoldingSetNodeID profile;
   
-  if (!X.isInitialized()) {
-    X = SymbolToData.size();
-    
-    if (ParmVarDecl* VD = dyn_cast<ParmVarDecl>(D))
-      SymbolToData.push_back(SymbolDataParmVar(VD));
-    else
-      SymbolToData.push_back(SymbolDataGlobalVar(D));
+  ParmVarDecl* PD = dyn_cast<ParmVarDecl>(D);
+  
+  if (PD)
+    SymbolDataParmVar::Profile(profile, PD);
+  else
+    SymbolDataGlobalVar::Profile(profile, D);
+  
+  void* InsertPos;
+  
+  SymbolData* SD = DataSet.FindNodeOrInsertPos(profile, InsertPos);
+
+  if (SD)
+    return SD->getSymbol();
+  
+  if (PD) {
+    SD = (SymbolData*) BPAlloc.Allocate<SymbolDataParmVar>();
+    new (SD) SymbolDataParmVar(SymbolCounter, PD);
+  }
+  else {
+    SD = (SymbolData*) BPAlloc.Allocate<SymbolDataGlobalVar>();
+    new (SD) SymbolDataGlobalVar(SymbolCounter, D);
   }
   
-  return X;
+  DataSet.InsertNode(SD, InsertPos);
+  
+  DataMap[SymbolCounter] = SD;
+  return SymbolCounter++;
 }  
  
 SymbolID SymbolManager::getContentsOfSymbol(SymbolID sym) {
-  SymbolID& X = DataToSymbol[getKey(sym)];
   
-  if (!X.isInitialized()) {
-    X = SymbolToData.size();
-    SymbolToData.push_back(SymbolDataContentsOf(sym));
-  }
+  llvm::FoldingSetNodeID profile;
+  SymbolDataContentsOf::Profile(profile, sym);
+  void* InsertPos;
   
-  return X;  
+  SymbolData* SD = DataSet.FindNodeOrInsertPos(profile, InsertPos);
+  
+  if (SD)
+    return SD->getSymbol();
+
+  SD = (SymbolData*) BPAlloc.Allocate<SymbolDataContentsOf>();
+  new (SD) SymbolDataContentsOf(SymbolCounter, sym);
+
+
+  DataSet.InsertNode(SD, InsertPos);  
+  DataMap[SymbolCounter] = SD;
+  
+  return SymbolCounter++;
 }
+  
+SymbolID SymbolManager::getCallRetValSymbol(CallExpr* CE, unsigned Count) {
+  
+  llvm::FoldingSetNodeID profile;
+  SymbolDataCallRetVal::Profile(profile, CE, Count);
+  void* InsertPos;
+  
+  SymbolData* SD = DataSet.FindNodeOrInsertPos(profile, InsertPos);
+  
+  if (SD)
+    return SD->getSymbol();
+  
+  SD = (SymbolData*) BPAlloc.Allocate<SymbolDataCallRetVal>();
+  new (SD) SymbolDataCallRetVal(SymbolCounter, CE, Count);
+  
+  DataSet.InsertNode(SD, InsertPos);  
+  DataMap[SymbolCounter] = SD;
+  
+  return SymbolCounter++;
+}
+
+const SymbolData& SymbolManager::getSymbolData(SymbolID Sym) const {  
+  DataMapTy::const_iterator I = DataMap.find(Sym);
+  assert (I != DataMap.end());  
+  return *I->second;
+}
+
 
 QualType SymbolData::getType(const SymbolManager& SymMgr) const {
   switch (getKind()) {
@@ -57,12 +111,14 @@
       return cast<SymbolDataGlobalVar>(this)->getDecl()->getType();
       
     case ContentsOfKind: {
-      SymbolID x = cast<SymbolDataContentsOf>(this)->getSymbol();
+      SymbolID x = cast<SymbolDataContentsOf>(this)->getContainerSymbol();
       QualType T = SymMgr.getSymbolData(x).getType(SymMgr);
       return T->getAsPointerType()->getPointeeType();
     }
+      
+    case CallRetValKind:
+      return cast<SymbolDataCallRetVal>(this)->getCallExpr()->getType();
   }
 }
 
-SymbolManager::SymbolManager() {}
 SymbolManager::~SymbolManager() {}