From 50b73317314e889cf39c7b1d6cbf419fa7502f22 Mon Sep 17 00:00:00 2001
From: dim <dim@FreeBSD.org>
Date: Sat, 14 Apr 2012 14:01:31 +0000
Subject: Vendor import of clang trunk r154661:
 http://llvm.org/svn/llvm-project/cfe/trunk@r154661

---
 lib/StaticAnalyzer/Core/ExprEngine.cpp | 1215 ++++++++++++++++++--------------
 1 file changed, 700 insertions(+), 515 deletions(-)

(limited to 'lib/StaticAnalyzer/Core/ExprEngine.cpp')

diff --git a/lib/StaticAnalyzer/Core/ExprEngine.cpp b/lib/StaticAnalyzer/Core/ExprEngine.cpp
index ac9cf0b..d2da9aa 100644
--- a/lib/StaticAnalyzer/Core/ExprEngine.cpp
+++ b/lib/StaticAnalyzer/Core/ExprEngine.cpp
@@ -13,22 +13,24 @@
 //
 //===----------------------------------------------------------------------===//
 
+#define DEBUG_TYPE "ExprEngine"
+
 #include "clang/StaticAnalyzer/Core/CheckerManager.h"
 #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngineBuilders.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.h"
 #include "clang/AST/CharUnits.h"
 #include "clang/AST/ParentMap.h"
 #include "clang/AST/StmtObjC.h"
+#include "clang/AST/StmtCXX.h"
 #include "clang/AST/DeclCXX.h"
 #include "clang/Basic/Builtins.h"
 #include "clang/Basic/SourceManager.h"
-#include "clang/Basic/SourceManager.h"
 #include "clang/Basic/PrettyStackTrace.h"
 #include "llvm/Support/raw_ostream.h"
 #include "llvm/ADT/ImmutableList.h"
+#include "llvm/ADT/Statistic.h"
 
 #ifndef NDEBUG
 #include "llvm/Support/GraphWriter.h"
@@ -38,6 +40,19 @@ using namespace clang;
 using namespace ento;
 using llvm::APSInt;
 
+STATISTIC(NumRemoveDeadBindings,
+            "The # of times RemoveDeadBindings is called");
+STATISTIC(NumRemoveDeadBindingsSkipped,
+            "The # of times RemoveDeadBindings is skipped");
+STATISTIC(NumMaxBlockCountReached,
+            "The # of aborted paths due to reaching the maximum block count in "
+            "a top level function");
+STATISTIC(NumMaxBlockCountReachedInInlined,
+            "The # of aborted paths due to reaching the maximum block count in "
+            "an inlined function");
+STATISTIC(NumTimesRetriedWithoutInlining,
+            "The # of times we re-evaluated a call without inlining");
+
 //===----------------------------------------------------------------------===//
 // Utility functions.
 //===----------------------------------------------------------------------===//
@@ -51,17 +66,20 @@ static inline Selector GetNullarySelector(const char* name, ASTContext &Ctx) {
 // Engine construction and deletion.
 //===----------------------------------------------------------------------===//
 
-ExprEngine::ExprEngine(AnalysisManager &mgr, bool gcEnabled)
+ExprEngine::ExprEngine(AnalysisManager &mgr, bool gcEnabled,
+                       SetOfConstDecls *VisitedCallees,
+                       FunctionSummariesTy *FS)
   : AMgr(mgr),
-    Engine(*this),
+    AnalysisDeclContexts(mgr.getAnalysisDeclContextManager()),
+    Engine(*this, VisitedCallees, FS),
     G(Engine.getGraph()),
-    Builder(NULL),
     StateMgr(getContext(), mgr.getStoreManagerCreator(),
              mgr.getConstraintManagerCreator(), G.getAllocator(),
              *this),
     SymMgr(StateMgr.getSymbolManager()),
     svalBuilder(StateMgr.getSValBuilder()),
-    EntryNode(NULL), currentStmt(NULL),
+    EntryNode(NULL),
+    currentStmt(NULL), currentStmtIdx(0), currentBuilderContext(0),
     NSExceptionII(NULL), NSExceptionInstanceRaiseSelectors(NULL),
     RaiseSel(GetNullarySelector("raise", getContext())),
     ObjCGCEnabled(gcEnabled), BR(mgr, *this) {
@@ -81,15 +99,15 @@ ExprEngine::~ExprEngine() {
 // Utility methods.
 //===----------------------------------------------------------------------===//
 
-const ProgramState *ExprEngine::getInitialState(const LocationContext *InitLoc) {
-  const ProgramState *state = StateMgr.getInitialState(InitLoc);
+ProgramStateRef ExprEngine::getInitialState(const LocationContext *InitLoc) {
+  ProgramStateRef state = StateMgr.getInitialState(InitLoc);
+  const Decl *D = InitLoc->getDecl();
 
   // Preconditions.
-
   // FIXME: It would be nice if we had a more general mechanism to add
   // such preconditions.  Some day.
   do {
-    const Decl *D = InitLoc->getDecl();
+
     if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
       // Precondition: the first argument of 'main' is an integer guaranteed
       //  to be > 0.
@@ -117,49 +135,45 @@ const ProgramState *ExprEngine::getInitialState(const LocationContext *InitLoc)
       if (!Constraint)
         break;
 
-      if (const ProgramState *newState = state->assume(*Constraint, true))
+      if (ProgramStateRef newState = state->assume(*Constraint, true))
         state = newState;
-
-      break;
     }
-
-    if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
-      // Precondition: 'self' is always non-null upon entry to an Objective-C
-      // method.
-      const ImplicitParamDecl *SelfD = MD->getSelfDecl();
-      const MemRegion *R = state->getRegion(SelfD, InitLoc);
-      SVal V = state->getSVal(loc::MemRegionVal(R));
-
-      if (const Loc *LV = dyn_cast<Loc>(&V)) {
-        // Assume that the pointer value in 'self' is non-null.
-        state = state->assume(*LV, true);
-        assert(state && "'self' cannot be null");
-      }
+    break;
+  }
+  while (0);
+
+  if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
+    // Precondition: 'self' is always non-null upon entry to an Objective-C
+    // method.
+    const ImplicitParamDecl *SelfD = MD->getSelfDecl();
+    const MemRegion *R = state->getRegion(SelfD, InitLoc);
+    SVal V = state->getSVal(loc::MemRegionVal(R));
+
+    if (const Loc *LV = dyn_cast<Loc>(&V)) {
+      // Assume that the pointer value in 'self' is non-null.
+      state = state->assume(*LV, true);
+      assert(state && "'self' cannot be null");
     }
-  } while (0);
-
-  return state;
-}
+  }
 
-bool
-ExprEngine::doesInvalidateGlobals(const CallOrObjCMessage &callOrMessage) const
-{
-  if (callOrMessage.isFunctionCall() && !callOrMessage.isCXXCall()) {
-    SVal calleeV = callOrMessage.getFunctionCallee();
-    if (const FunctionTextRegion *codeR =
-          dyn_cast_or_null<FunctionTextRegion>(calleeV.getAsRegion())) {
-      
-      const FunctionDecl *fd = codeR->getDecl();
-      if (const IdentifierInfo *ii = fd->getIdentifier()) {
-        StringRef fname = ii->getName();
-        if (fname == "strlen")
-          return false;
+  if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) {
+    if (!MD->isStatic()) {
+      // Precondition: 'this' is always non-null upon entry to the
+      // top-level function.  This is our starting assumption for
+      // analyzing an "open" program.
+      const StackFrameContext *SFC = InitLoc->getCurrentStackFrame();
+      if (SFC->getParent() == 0) {
+        loc::MemRegionVal L(getCXXThisRegion(MD, SFC));
+        SVal V = state->getSVal(L);
+        if (const Loc *LV = dyn_cast<Loc>(&V)) {
+          state = state->assume(*LV, true);
+          assert(state && "'this' cannot be null");
+        }
       }
     }
   }
-  
-  // The conservative answer: invalidates globals.
-  return true;
+    
+  return state;
 }
 
 //===----------------------------------------------------------------------===//
@@ -168,25 +182,26 @@ ExprEngine::doesInvalidateGlobals(const CallOrObjCMessage &callOrMessage) const
 
 /// evalAssume - Called by ConstraintManager. Used to call checker-specific
 ///  logic for handling assumptions on symbolic values.
-const ProgramState *ExprEngine::processAssume(const ProgramState *state,
+ProgramStateRef ExprEngine::processAssume(ProgramStateRef state,
                                               SVal cond, bool assumption) {
   return getCheckerManager().runCheckersForEvalAssume(state, cond, assumption);
 }
 
-bool ExprEngine::wantsRegionChangeUpdate(const ProgramState *state) {
+bool ExprEngine::wantsRegionChangeUpdate(ProgramStateRef state) {
   return getCheckerManager().wantsRegionChangeUpdate(state);
 }
 
-const ProgramState *
-ExprEngine::processRegionChanges(const ProgramState *state,
+ProgramStateRef 
+ExprEngine::processRegionChanges(ProgramStateRef state,
                             const StoreManager::InvalidatedSymbols *invalidated,
                                  ArrayRef<const MemRegion *> Explicits,
-                                 ArrayRef<const MemRegion *> Regions) {
+                                 ArrayRef<const MemRegion *> Regions,
+                                 const CallOrObjCMessage *Call) {
   return getCheckerManager().runCheckersForRegionChanges(state, invalidated,
-                                                         Explicits, Regions);
+                                                      Explicits, Regions, Call);
 }
 
-void ExprEngine::printState(raw_ostream &Out, const ProgramState *State,
+void ExprEngine::printState(raw_ostream &Out, ProgramStateRef State,
                             const char *NL, const char *Sep) {
   getCheckerManager().runCheckersForPrintState(Out, State, NL, Sep);
 }
@@ -195,54 +210,77 @@ void ExprEngine::processEndWorklist(bool hasWorkRemaining) {
   getCheckerManager().runCheckersForEndAnalysis(G, BR, *this);
 }
 
-void ExprEngine::processCFGElement(const CFGElement E, 
-                                  StmtNodeBuilder& builder) {
+void ExprEngine::processCFGElement(const CFGElement E, ExplodedNode *Pred,
+                                   unsigned StmtIdx, NodeBuilderContext *Ctx) {
+  currentStmtIdx = StmtIdx;
+  currentBuilderContext = Ctx;
+
   switch (E.getKind()) {
     case CFGElement::Invalid:
       llvm_unreachable("Unexpected CFGElement kind.");
     case CFGElement::Statement:
-      ProcessStmt(const_cast<Stmt*>(E.getAs<CFGStmt>()->getStmt()), builder);
+      ProcessStmt(const_cast<Stmt*>(E.getAs<CFGStmt>()->getStmt()), Pred);
       return;
     case CFGElement::Initializer:
-      ProcessInitializer(E.getAs<CFGInitializer>()->getInitializer(), builder);
+      ProcessInitializer(E.getAs<CFGInitializer>()->getInitializer(), Pred);
       return;
     case CFGElement::AutomaticObjectDtor:
     case CFGElement::BaseDtor:
     case CFGElement::MemberDtor:
     case CFGElement::TemporaryDtor:
-      ProcessImplicitDtor(*E.getAs<CFGImplicitDtor>(), builder);
+      ProcessImplicitDtor(*E.getAs<CFGImplicitDtor>(), Pred);
       return;
   }
 }
 
-void ExprEngine::ProcessStmt(const CFGStmt S, StmtNodeBuilder& builder) {
-  // TODO: Use RAII to remove the unnecessary, tagged nodes.
-  //RegisterCreatedNodes registerCreatedNodes(getGraph());
+static bool shouldRemoveDeadBindings(AnalysisManager &AMgr,
+                                     const CFGStmt S,
+                                     const ExplodedNode *Pred,
+                                     const LocationContext *LC) {
+  
+  // Are we never purging state values?
+  if (AMgr.getPurgeMode() == PurgeNone)
+    return false;
+
+  // Is this the beginning of a basic block?
+  if (isa<BlockEntrance>(Pred->getLocation()))
+    return true;
 
+  // Is this on a non-expression?
+  if (!isa<Expr>(S.getStmt()))
+    return true;
+    
+  // Run before processing a call.
+  if (isa<CallExpr>(S.getStmt()))
+    return true;
+
+  // Is this an expression that is consumed by another expression?  If so,
+  // postpone cleaning out the state.
+  ParentMap &PM = LC->getAnalysisDeclContext()->getParentMap();
+  return !PM.isConsumedExpr(cast<Expr>(S.getStmt()));
+}
+
+void ExprEngine::ProcessStmt(const CFGStmt S,
+                             ExplodedNode *Pred) {
   // Reclaim any unnecessary nodes in the ExplodedGraph.
   G.reclaimRecentlyAllocatedNodes();
-  // Recycle any unused states in the ProgramStateManager.
-  StateMgr.recycleUnusedStates();
   
   currentStmt = S.getStmt();
   PrettyStackTraceLoc CrashInfo(getContext().getSourceManager(),
                                 currentStmt->getLocStart(),
                                 "Error evaluating statement");
 
-  // A tag to track convenience transitions, which can be removed at cleanup.
-  static SimpleProgramPointTag cleanupTag("ExprEngine : Clean Node");
-  Builder = &builder;
-  EntryNode = builder.getPredecessor();
+  EntryNode = Pred;
 
-  const ProgramState *EntryState = EntryNode->getState();
+  ProgramStateRef EntryState = EntryNode->getState();
   CleanedState = EntryState;
-  ExplodedNode *CleanedNode = 0;
 
   // Create the cleaned state.
   const LocationContext *LC = EntryNode->getLocationContext();
   SymbolReaper SymReaper(LC, currentStmt, SymMgr, getStoreManager());
 
-  if (AMgr.getPurgeMode() != PurgeNone) {
+  if (shouldRemoveDeadBindings(AMgr, S, Pred, LC)) {
+    NumRemoveDeadBindings++;
     getCheckerManager().runCheckersForLiveSymbols(CleanedState, SymReaper);
 
     const StackFrameContext *SFC = LC->getCurrentStackFrame();
@@ -251,25 +289,23 @@ void ExprEngine::ProcessStmt(const CFGStmt S, StmtNodeBuilder& builder) {
     // and the store. TODO: The function should just return new env and store,
     // not a new state.
     CleanedState = StateMgr.removeDeadBindings(CleanedState, SFC, SymReaper);
+  } else {
+    NumRemoveDeadBindingsSkipped++;
   }
 
   // Process any special transfer function for dead symbols.
   ExplodedNodeSet Tmp;
+  // A tag to track convenience transitions, which can be removed at cleanup.
+  static SimpleProgramPointTag cleanupTag("ExprEngine : Clean Node");
+
   if (!SymReaper.hasDeadSymbols()) {
     // Generate a CleanedNode that has the environment and store cleaned
     // up. Since no symbols are dead, we can optimize and not clean out
     // the constraint manager.
-    CleanedNode =
-      Builder->generateNode(currentStmt, CleanedState, EntryNode, &cleanupTag);
-    Tmp.Add(CleanedNode);
+    StmtNodeBuilder Bldr(Pred, Tmp, *currentBuilderContext);
+    Bldr.generateNode(currentStmt, EntryNode, CleanedState, false, &cleanupTag);
 
   } else {
-    SaveAndRestore<bool> OldSink(Builder->BuildSinks);
-    SaveOr OldHasGen(Builder->hasGeneratedNode);
-
-    SaveAndRestore<bool> OldPurgeDeadSymbols(Builder->PurgingDeadSymbols);
-    Builder->PurgingDeadSymbols = true;
-
     // Call checkers with the non-cleaned state so that they could query the
     // values of the soon to be dead symbols.
     ExplodedNodeSet CheckedSet;
@@ -279,9 +315,10 @@ void ExprEngine::ProcessStmt(const CFGStmt S, StmtNodeBuilder& builder) {
     // For each node in CheckedSet, generate CleanedNodes that have the
     // environment, the store, and the constraints cleaned up but have the
     // user-supplied states as the predecessors.
+    StmtNodeBuilder Bldr(CheckedSet, Tmp, *currentBuilderContext);
     for (ExplodedNodeSet::const_iterator
           I = CheckedSet.begin(), E = CheckedSet.end(); I != E; ++I) {
-      const ProgramState *CheckerState = (*I)->getState();
+      ProgramStateRef CheckerState = (*I)->getState();
 
       // The constraint manager has not been cleaned up yet, so clean up now.
       CheckerState = getConstraintManager().removeDeadBindings(CheckerState,
@@ -296,109 +333,109 @@ void ExprEngine::ProcessStmt(const CFGStmt S, StmtNodeBuilder& builder) {
 
       // Create a state based on CleanedState with CheckerState GDM and
       // generate a transition to that state.
-      const ProgramState *CleanedCheckerSt =
+      ProgramStateRef CleanedCheckerSt =
         StateMgr.getPersistentStateWithGDM(CleanedState, CheckerState);
-      ExplodedNode *CleanedNode = Builder->generateNode(currentStmt,
-                                                        CleanedCheckerSt, *I,
-                                                        &cleanupTag);
-      Tmp.Add(CleanedNode);
+      Bldr.generateNode(currentStmt, *I, CleanedCheckerSt, false, &cleanupTag,
+                        ProgramPoint::PostPurgeDeadSymbolsKind);
     }
   }
 
+  ExplodedNodeSet Dst;
   for (ExplodedNodeSet::iterator I=Tmp.begin(), E=Tmp.end(); I!=E; ++I) {
-    // TODO: Remove Dest set, it's no longer needed.
-    ExplodedNodeSet Dst;
+    ExplodedNodeSet DstI;
     // Visit the statement.
-    Visit(currentStmt, *I, Dst);
+    Visit(currentStmt, *I, DstI);
+    Dst.insert(DstI);
   }
 
+  // Enqueue the new nodes onto the work list.
+  Engine.enqueue(Dst, currentBuilderContext->getBlock(), currentStmtIdx);
+
   // NULL out these variables to cleanup.
   CleanedState = NULL;
   EntryNode = NULL;
   currentStmt = 0;
-  Builder = NULL;
 }
 
 void ExprEngine::ProcessInitializer(const CFGInitializer Init,
-                                    StmtNodeBuilder &builder) {
+                                    ExplodedNode *Pred) {
+  ExplodedNodeSet Dst;
+
   // We don't set EntryNode and currentStmt. And we don't clean up state.
   const CXXCtorInitializer *BMI = Init.getInitializer();
-
-  ExplodedNode *pred = builder.getPredecessor();
-
-  const StackFrameContext *stackFrame = cast<StackFrameContext>(pred->getLocationContext());
-  const CXXConstructorDecl *decl = cast<CXXConstructorDecl>(stackFrame->getDecl());
+  const StackFrameContext *stackFrame =
+                           cast<StackFrameContext>(Pred->getLocationContext());
+  const CXXConstructorDecl *decl =
+                           cast<CXXConstructorDecl>(stackFrame->getDecl());
   const CXXThisRegion *thisReg = getCXXThisRegion(decl, stackFrame);
 
-  SVal thisVal = pred->getState()->getSVal(thisReg);
+  SVal thisVal = Pred->getState()->getSVal(thisReg);
 
   if (BMI->isAnyMemberInitializer()) {
-    ExplodedNodeSet Dst;
-
     // Evaluate the initializer.
-    Visit(BMI->getInit(), pred, Dst);
 
-    for (ExplodedNodeSet::iterator I = Dst.begin(), E = Dst.end(); I != E; ++I){
-      ExplodedNode *Pred = *I;
-      const ProgramState *state = Pred->getState();
+    StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext);
+    ProgramStateRef state = Pred->getState();
 
-      const FieldDecl *FD = BMI->getAnyMember();
+    const FieldDecl *FD = BMI->getAnyMember();
 
-      SVal FieldLoc = state->getLValue(FD, thisVal);
-      SVal InitVal = state->getSVal(BMI->getInit());
-      state = state->bindLoc(FieldLoc, InitVal);
+    SVal FieldLoc = state->getLValue(FD, thisVal);
+    SVal InitVal = state->getSVal(BMI->getInit(), Pred->getLocationContext());
+    state = state->bindLoc(FieldLoc, InitVal);
 
-      // Use a custom node building process.
-      PostInitializer PP(BMI, stackFrame);
-      // Builder automatically add the generated node to the deferred set,
-      // which are processed in the builder's dtor.
-      builder.generateNode(PP, state, Pred);
-    }
-    return;
-  }
+    // Use a custom node building process.
+    PostInitializer PP(BMI, stackFrame);
+    // Builder automatically add the generated node to the deferred set,
+    // which are processed in the builder's dtor.
+    Bldr.generateNode(PP, Pred, state);
+  } else {
+    assert(BMI->isBaseInitializer());
 
-  assert(BMI->isBaseInitializer());
+    // Get the base class declaration.
+    const CXXConstructExpr *ctorExpr = cast<CXXConstructExpr>(BMI->getInit());
 
-  // Get the base class declaration.
-  const CXXConstructExpr *ctorExpr = cast<CXXConstructExpr>(BMI->getInit());
+    // Create the base object region.
+    SVal baseVal =
+        getStoreManager().evalDerivedToBase(thisVal, ctorExpr->getType());
+    const MemRegion *baseReg = baseVal.getAsRegion();
+    assert(baseReg);
+
+    VisitCXXConstructExpr(ctorExpr, baseReg, Pred, Dst);
+  }
 
-  // Create the base object region.
-  SVal baseVal = 
-    getStoreManager().evalDerivedToBase(thisVal, ctorExpr->getType());
-  const MemRegion *baseReg = baseVal.getAsRegion();
-  assert(baseReg);
-  Builder = &builder;
-  ExplodedNodeSet dst;
-  VisitCXXConstructExpr(ctorExpr, baseReg, pred, dst);
+  // Enqueue the new nodes onto the work list.
+  Engine.enqueue(Dst, currentBuilderContext->getBlock(), currentStmtIdx);
 }
 
 void ExprEngine::ProcessImplicitDtor(const CFGImplicitDtor D,
-                                       StmtNodeBuilder &builder) {
-  Builder = &builder;
-
+                                     ExplodedNode *Pred) {
+  ExplodedNodeSet Dst;
   switch (D.getKind()) {
   case CFGElement::AutomaticObjectDtor:
-    ProcessAutomaticObjDtor(cast<CFGAutomaticObjDtor>(D), builder);
+    ProcessAutomaticObjDtor(cast<CFGAutomaticObjDtor>(D), Pred, Dst);
     break;
   case CFGElement::BaseDtor:
-    ProcessBaseDtor(cast<CFGBaseDtor>(D), builder);
+    ProcessBaseDtor(cast<CFGBaseDtor>(D), Pred, Dst);
     break;
   case CFGElement::MemberDtor:
-    ProcessMemberDtor(cast<CFGMemberDtor>(D), builder);
+    ProcessMemberDtor(cast<CFGMemberDtor>(D), Pred, Dst);
     break;
   case CFGElement::TemporaryDtor:
-    ProcessTemporaryDtor(cast<CFGTemporaryDtor>(D), builder);
+    ProcessTemporaryDtor(cast<CFGTemporaryDtor>(D), Pred, Dst);
     break;
   default:
     llvm_unreachable("Unexpected dtor kind.");
   }
+
+  // Enqueue the new nodes onto the work list.
+  Engine.enqueue(Dst, currentBuilderContext->getBlock(), currentStmtIdx);
 }
 
-void ExprEngine::ProcessAutomaticObjDtor(const CFGAutomaticObjDtor dtor,
-                                           StmtNodeBuilder &builder) {
-  ExplodedNode *pred = builder.getPredecessor();
-  const ProgramState *state = pred->getState();
-  const VarDecl *varDecl = dtor.getVarDecl();
+void ExprEngine::ProcessAutomaticObjDtor(const CFGAutomaticObjDtor Dtor,
+                                         ExplodedNode *Pred,
+                                         ExplodedNodeSet &Dst) {
+  ProgramStateRef state = Pred->getState();
+  const VarDecl *varDecl = Dtor.getVarDecl();
 
   QualType varType = varDecl->getType();
 
@@ -409,30 +446,29 @@ void ExprEngine::ProcessAutomaticObjDtor(const CFGAutomaticObjDtor dtor,
   assert(recordDecl && "get CXXRecordDecl fail");
   const CXXDestructorDecl *dtorDecl = recordDecl->getDestructor();
 
-  Loc dest = state->getLValue(varDecl, pred->getLocationContext());
+  Loc dest = state->getLValue(varDecl, Pred->getLocationContext());
 
-  ExplodedNodeSet dstSet;
   VisitCXXDestructor(dtorDecl, cast<loc::MemRegionVal>(dest).getRegion(),
-                     dtor.getTriggerStmt(), pred, dstSet);
+                     Dtor.getTriggerStmt(), Pred, Dst);
 }
 
 void ExprEngine::ProcessBaseDtor(const CFGBaseDtor D,
-                                   StmtNodeBuilder &builder) {
-}
+                                 ExplodedNode *Pred, ExplodedNodeSet &Dst) {}
 
 void ExprEngine::ProcessMemberDtor(const CFGMemberDtor D,
-                                     StmtNodeBuilder &builder) {
-}
+                                   ExplodedNode *Pred, ExplodedNodeSet &Dst) {}
 
 void ExprEngine::ProcessTemporaryDtor(const CFGTemporaryDtor D,
-                                        StmtNodeBuilder &builder) {
-}
+                                      ExplodedNode *Pred,
+                                      ExplodedNodeSet &Dst) {}
 
 void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred, 
-                         ExplodedNodeSet &Dst) {
+                       ExplodedNodeSet &DstTop) {
   PrettyStackTraceLoc CrashInfo(getContext().getSourceManager(),
                                 S->getLocStart(),
                                 "Error evaluating statement");
+  ExplodedNodeSet Dst;
+  StmtNodeBuilder Bldr(Pred, DstTop, *currentBuilderContext);
 
   // Expressions to ignore.
   if (const Expr *Ex = dyn_cast<Expr>(S))
@@ -442,19 +478,14 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
   //  this check when we KNOW that there is no block-level subexpression.
   //  The motivation is that this check requires a hashtable lookup.
 
-  if (S != currentStmt && Pred->getLocationContext()->getCFG()->isBlkExpr(S)) {
-    Dst.Add(Pred);
+  if (S != currentStmt && Pred->getLocationContext()->getCFG()->isBlkExpr(S))
     return;
-  }
 
   switch (S->getStmtClass()) {
     // C++ and ARC stuff we don't support yet.
     case Expr::ObjCIndirectCopyRestoreExprClass:
-    case Stmt::CXXBindTemporaryExprClass:
-    case Stmt::CXXCatchStmtClass:
     case Stmt::CXXDependentScopeMemberExprClass:
     case Stmt::CXXPseudoDestructorExprClass:
-    case Stmt::CXXThrowExprClass:
     case Stmt::CXXTryStmtClass:
     case Stmt::CXXTypeidExprClass:
     case Stmt::CXXUuidofExprClass:
@@ -463,6 +494,7 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
     case Stmt::DependentScopeDeclRefExprClass:
     case Stmt::UnaryTypeTraitExprClass:
     case Stmt::BinaryTypeTraitExprClass:
+    case Stmt::TypeTraitExprClass:
     case Stmt::ArrayTypeTraitExprClass:
     case Stmt::ExpressionTraitExprClass:
     case Stmt::UnresolvedLookupExprClass:
@@ -472,22 +504,19 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
     case Stmt::SubstNonTypeTemplateParmPackExprClass:
     case Stmt::SEHTryStmtClass:
     case Stmt::SEHExceptStmtClass:
-    case Stmt::SEHFinallyStmtClass:
-    {
-      SaveAndRestore<bool> OldSink(Builder->BuildSinks);
-      Builder->BuildSinks = true;
-      const ExplodedNode *node = MakeNode(Dst, S, Pred, Pred->getState());
-      Engine.addAbortedBlock(node, Builder->getBlock());
+    case Stmt::LambdaExprClass:
+    case Stmt::SEHFinallyStmtClass: {
+      const ExplodedNode *node = Bldr.generateNode(S, Pred, Pred->getState(),
+                                                   /* sink */ true);
+      Engine.addAbortedBlock(node, currentBuilderContext->getBlock());
       break;
     }
     
     // We don't handle default arguments either yet, but we can fake it
     // for now by just skipping them.
     case Stmt::SubstNonTypeTemplateParmExprClass:
-    case Stmt::CXXDefaultArgExprClass: {
-      Dst.Add(Pred);
+    case Stmt::CXXDefaultArgExprClass:
       break;
-    }
 
     case Stmt::ParenExprClass:
       llvm_unreachable("ParenExprs already handled.");
@@ -511,38 +540,44 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
     case Stmt::NullStmtClass:
     case Stmt::SwitchStmtClass:
     case Stmt::WhileStmtClass:
+    case Expr::MSDependentExistsStmtClass:
       llvm_unreachable("Stmt should not be in analyzer evaluation loop");
-      break;
 
     case Stmt::GNUNullExprClass: {
       // GNU __null is a pointer-width integer, not an actual pointer.
-      const ProgramState *state = Pred->getState();
-      state = state->BindExpr(S, svalBuilder.makeIntValWithPtrWidth(0, false));
-      MakeNode(Dst, S, Pred, state);
+      ProgramStateRef state = Pred->getState();
+      state = state->BindExpr(S, Pred->getLocationContext(),
+                              svalBuilder.makeIntValWithPtrWidth(0, false));
+      Bldr.generateNode(S, Pred, state);
       break;
     }
 
     case Stmt::ObjCAtSynchronizedStmtClass:
+      Bldr.takeNodes(Pred);
       VisitObjCAtSynchronizedStmt(cast<ObjCAtSynchronizedStmt>(S), Pred, Dst);
+      Bldr.addNodes(Dst);
       break;
 
+    // FIXME.
+    case Stmt::ObjCSubscriptRefExprClass:
+      break;
+      
     case Stmt::ObjCPropertyRefExprClass:
       // Implicitly handled by Environment::getSVal().
-      Dst.Add(Pred);
       break;
 
     case Stmt::ImplicitValueInitExprClass: {
-      const ProgramState *state = Pred->getState();
+      ProgramStateRef state = Pred->getState();
       QualType ty = cast<ImplicitValueInitExpr>(S)->getType();
       SVal val = svalBuilder.makeZeroVal(ty);
-      MakeNode(Dst, S, Pred, state->BindExpr(S, val));
+      Bldr.generateNode(S, Pred, state->BindExpr(S, Pred->getLocationContext(),
+                                                 val));
       break;
     }
       
-    case Stmt::ExprWithCleanupsClass: {
-      Visit(cast<ExprWithCleanups>(S)->getSubExpr(), Pred, Dst);
+    case Stmt::ExprWithCleanupsClass:
+      // Handled due to fully linearised CFG.
       break;
-    }
 
     // Cases not handled yet; but will handle some day.
     case Stmt::DesignatedInitExprClass:
@@ -556,7 +591,7 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
     case Stmt::ObjCIsaExprClass:
     case Stmt::ObjCProtocolExprClass:
     case Stmt::ObjCSelectorExprClass:
-    case Stmt::ObjCStringLiteralClass:
+    case Expr::ObjCNumericLiteralClass:
     case Stmt::ParenListExprClass:
     case Stmt::PredefinedExprClass:
     case Stmt::ShuffleVectorExprClass:
@@ -565,50 +600,101 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
     case Stmt::OpaqueValueExprClass:
     case Stmt::AsTypeExprClass:
     case Stmt::AtomicExprClass:
-        // Fall through.
+      // Fall through.
 
+    // Currently all handling of 'throw' just falls to the CFG.  We
+    // can consider doing more if necessary.
+    case Stmt::CXXThrowExprClass:
+      // Fall through.
+      
     // Cases we intentionally don't evaluate, since they don't need
     // to be explicitly evaluated.
     case Stmt::AddrLabelExprClass:
     case Stmt::IntegerLiteralClass:
     case Stmt::CharacterLiteralClass:
     case Stmt::CXXBoolLiteralExprClass:
+    case Stmt::ObjCBoolLiteralExprClass:
     case Stmt::FloatingLiteralClass:
     case Stmt::SizeOfPackExprClass:
-    case Stmt::CXXNullPtrLiteralExprClass:
-      Dst.Add(Pred); // No-op. Simply propagate the current state unchanged.
+    case Stmt::StringLiteralClass:
+    case Stmt::ObjCStringLiteralClass:
+    case Stmt::CXXBindTemporaryExprClass:
+    case Stmt::CXXNullPtrLiteralExprClass: {
+      Bldr.takeNodes(Pred);
+      ExplodedNodeSet preVisit;
+      getCheckerManager().runCheckersForPreStmt(preVisit, Pred, S, *this);
+      getCheckerManager().runCheckersForPostStmt(Dst, preVisit, S, *this);
+      Bldr.addNodes(Dst);
       break;
+    }
+
+    case Expr::ObjCArrayLiteralClass:
+    case Expr::ObjCDictionaryLiteralClass: {
+      Bldr.takeNodes(Pred);
+
+      ExplodedNodeSet preVisit;
+      getCheckerManager().runCheckersForPreStmt(preVisit, Pred, S, *this);
+      
+      // FIXME: explicitly model with a region and the actual contents
+      // of the container.  For now, conjure a symbol.
+      ExplodedNodeSet Tmp;
+      StmtNodeBuilder Bldr2(preVisit, Tmp, *currentBuilderContext);
+
+      for (ExplodedNodeSet::iterator it = preVisit.begin(), et = preVisit.end();
+           it != et; ++it) {      
+        ExplodedNode *N = *it;
+        const Expr *Ex = cast<Expr>(S);
+        QualType resultType = Ex->getType();
+        const LocationContext *LCtx = N->getLocationContext();
+        SVal result =
+          svalBuilder.getConjuredSymbolVal(0, Ex, LCtx, resultType, 
+                                 currentBuilderContext->getCurrentBlockCount());
+        ProgramStateRef state = N->getState()->BindExpr(Ex, LCtx, result);
+        Bldr2.generateNode(S, N, state);
+      }
+      
+      getCheckerManager().runCheckersForPostStmt(Dst, Tmp, S, *this);
+      Bldr.addNodes(Dst);
+      break;      
+    }
 
     case Stmt::ArraySubscriptExprClass:
+      Bldr.takeNodes(Pred);
       VisitLvalArraySubscriptExpr(cast<ArraySubscriptExpr>(S), Pred, Dst);
+      Bldr.addNodes(Dst);
       break;
 
     case Stmt::AsmStmtClass:
+      Bldr.takeNodes(Pred);
       VisitAsmStmt(cast<AsmStmt>(S), Pred, Dst);
+      Bldr.addNodes(Dst);
       break;
 
-    case Stmt::BlockDeclRefExprClass: {
-      const BlockDeclRefExpr *BE = cast<BlockDeclRefExpr>(S);
-      VisitCommonDeclRefExpr(BE, BE->getDecl(), Pred, Dst);
-      break;
-    }
-
     case Stmt::BlockExprClass:
+      Bldr.takeNodes(Pred);
       VisitBlockExpr(cast<BlockExpr>(S), Pred, Dst);
+      Bldr.addNodes(Dst);
       break;
 
     case Stmt::BinaryOperatorClass: {
       const BinaryOperator* B = cast<BinaryOperator>(S);
       if (B->isLogicalOp()) {
+        Bldr.takeNodes(Pred);
         VisitLogicalExpr(B, Pred, Dst);
+        Bldr.addNodes(Dst);
         break;
       }
       else if (B->getOpcode() == BO_Comma) {
-        const ProgramState *state = Pred->getState();
-        MakeNode(Dst, B, Pred, state->BindExpr(B, state->getSVal(B->getRHS())));
+        ProgramStateRef state = Pred->getState();
+        Bldr.generateNode(B, Pred,
+                          state->BindExpr(B, Pred->getLocationContext(),
+                                          state->getSVal(B->getRHS(),
+                                                  Pred->getLocationContext())));
         break;
       }
 
+      Bldr.takeNodes(Pred);
+      
       if (AMgr.shouldEagerlyAssume() &&
           (B->isRelationalOp() || B->isEqualityOp())) {
         ExplodedNodeSet Tmp;
@@ -618,13 +704,24 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
       else
         VisitBinaryOperator(cast<BinaryOperator>(S), Pred, Dst);
 
+      Bldr.addNodes(Dst);
       break;
     }
 
     case Stmt::CallExprClass:
     case Stmt::CXXOperatorCallExprClass:
-    case Stmt::CXXMemberCallExprClass: {
+    case Stmt::CXXMemberCallExprClass:
+    case Stmt::UserDefinedLiteralClass: {
+      Bldr.takeNodes(Pred);
       VisitCallExpr(cast<CallExpr>(S), Pred, Dst);
+      Bldr.addNodes(Dst);
+      break;
+    }
+    
+    case Stmt::CXXCatchStmtClass: {
+      Bldr.takeNodes(Pred);
+      VisitCXXCatchStmt(cast<CXXCatchStmt>(S), Pred, Dst);
+      Bldr.addNodes(Dst);
       break;
     }
 
@@ -633,58 +730,78 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
       const CXXConstructExpr *C = cast<CXXConstructExpr>(S);
       // For block-level CXXConstructExpr, we don't have a destination region.
       // Let VisitCXXConstructExpr() create one.
+      Bldr.takeNodes(Pred);
       VisitCXXConstructExpr(C, 0, Pred, Dst);
+      Bldr.addNodes(Dst);
       break;
     }
 
     case Stmt::CXXNewExprClass: {
+      Bldr.takeNodes(Pred);
       const CXXNewExpr *NE = cast<CXXNewExpr>(S);
       VisitCXXNewExpr(NE, Pred, Dst);
+      Bldr.addNodes(Dst);
       break;
     }
 
     case Stmt::CXXDeleteExprClass: {
+      Bldr.takeNodes(Pred);
       const CXXDeleteExpr *CDE = cast<CXXDeleteExpr>(S);
       VisitCXXDeleteExpr(CDE, Pred, Dst);
+      Bldr.addNodes(Dst);
       break;
     }
       // FIXME: ChooseExpr is really a constant.  We need to fix
       //        the CFG do not model them as explicit control-flow.
 
     case Stmt::ChooseExprClass: { // __builtin_choose_expr
+      Bldr.takeNodes(Pred);
       const ChooseExpr *C = cast<ChooseExpr>(S);
       VisitGuardedExpr(C, C->getLHS(), C->getRHS(), Pred, Dst);
+      Bldr.addNodes(Dst);
       break;
     }
 
     case Stmt::CompoundAssignOperatorClass:
+      Bldr.takeNodes(Pred);
       VisitBinaryOperator(cast<BinaryOperator>(S), Pred, Dst);
+      Bldr.addNodes(Dst);
       break;
 
     case Stmt::CompoundLiteralExprClass:
+      Bldr.takeNodes(Pred);
       VisitCompoundLiteralExpr(cast<CompoundLiteralExpr>(S), Pred, Dst);
+      Bldr.addNodes(Dst);
       break;
 
     case Stmt::BinaryConditionalOperatorClass:
     case Stmt::ConditionalOperatorClass: { // '?' operator
+      Bldr.takeNodes(Pred);
       const AbstractConditionalOperator *C
         = cast<AbstractConditionalOperator>(S);
       VisitGuardedExpr(C, C->getTrueExpr(), C->getFalseExpr(), Pred, Dst);
+      Bldr.addNodes(Dst);
       break;
     }
 
     case Stmt::CXXThisExprClass:
+      Bldr.takeNodes(Pred);
       VisitCXXThisExpr(cast<CXXThisExpr>(S), Pred, Dst);
+      Bldr.addNodes(Dst);
       break;
 
     case Stmt::DeclRefExprClass: {
+      Bldr.takeNodes(Pred);
       const DeclRefExpr *DE = cast<DeclRefExpr>(S);
       VisitCommonDeclRefExpr(DE, DE->getDecl(), Pred, Dst);
+      Bldr.addNodes(Dst);
       break;
     }
 
     case Stmt::DeclStmtClass:
+      Bldr.takeNodes(Pred);
       VisitDeclStmt(cast<DeclStmt>(S), Pred, Dst);
+      Bldr.addNodes(Dst);
       break;
 
     case Stmt::ImplicitCastExprClass:
@@ -695,6 +812,7 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
     case Stmt::CXXConstCastExprClass:
     case Stmt::CXXFunctionalCastExprClass: 
     case Stmt::ObjCBridgedCastExprClass: {
+      Bldr.takeNodes(Pred);
       const CastExpr *C = cast<CastExpr>(S);
       // Handle the previsit checks.
       ExplodedNodeSet dstPrevisit;
@@ -709,58 +827,98 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
 
       // Handle the postvisit checks.
       getCheckerManager().runCheckersForPostStmt(Dst, dstExpr, C, *this);
+      Bldr.addNodes(Dst);
       break;
     }
 
     case Expr::MaterializeTemporaryExprClass: {
+      Bldr.takeNodes(Pred);
       const MaterializeTemporaryExpr *Materialize
                                             = cast<MaterializeTemporaryExpr>(S);
-      if (!Materialize->getType()->isRecordType())
-        CreateCXXTemporaryObject(Materialize, Pred, Dst);
+      if (Materialize->getType()->isRecordType())
+        Dst.Add(Pred);
       else
-        Visit(Materialize->GetTemporaryExpr(), Pred, Dst);
+        CreateCXXTemporaryObject(Materialize, Pred, Dst);
+      Bldr.addNodes(Dst);
       break;
     }
       
     case Stmt::InitListExprClass:
+      Bldr.takeNodes(Pred);
       VisitInitListExpr(cast<InitListExpr>(S), Pred, Dst);
+      Bldr.addNodes(Dst);
       break;
 
     case Stmt::MemberExprClass:
+      Bldr.takeNodes(Pred);
       VisitMemberExpr(cast<MemberExpr>(S), Pred, Dst);
+      Bldr.addNodes(Dst);
       break;
+
     case Stmt::ObjCIvarRefExprClass:
+      Bldr.takeNodes(Pred);
       VisitLvalObjCIvarRefExpr(cast<ObjCIvarRefExpr>(S), Pred, Dst);
+      Bldr.addNodes(Dst);
       break;
 
     case Stmt::ObjCForCollectionStmtClass:
+      Bldr.takeNodes(Pred);
       VisitObjCForCollectionStmt(cast<ObjCForCollectionStmt>(S), Pred, Dst);
+      Bldr.addNodes(Dst);
       break;
 
-    case Stmt::ObjCMessageExprClass:
-      VisitObjCMessage(cast<ObjCMessageExpr>(S), Pred, Dst);
+    case Stmt::ObjCMessageExprClass: {
+      Bldr.takeNodes(Pred);
+      // Is this a property access?
+      const ParentMap &PM = Pred->getLocationContext()->getParentMap();
+      const ObjCMessageExpr *ME = cast<ObjCMessageExpr>(S);
+      bool evaluated = false;
+      
+      if (const PseudoObjectExpr *PO =
+          dyn_cast_or_null<PseudoObjectExpr>(PM.getParent(S))) {
+        const Expr *syntactic = PO->getSyntacticForm();
+        if (const ObjCPropertyRefExpr *PR =
+              dyn_cast<ObjCPropertyRefExpr>(syntactic)) {
+          bool isSetter = ME->getNumArgs() > 0;
+          VisitObjCMessage(ObjCMessage(ME, PR, isSetter), Pred, Dst);
+          evaluated = true;
+        }
+        else if (isa<BinaryOperator>(syntactic)) {
+          VisitObjCMessage(ObjCMessage(ME, 0, true), Pred, Dst);
+        }
+      }
+      
+      if (!evaluated)
+        VisitObjCMessage(ME, Pred, Dst);
+
+      Bldr.addNodes(Dst);
       break;
+    }
 
     case Stmt::ObjCAtThrowStmtClass: {
       // FIXME: This is not complete.  We basically treat @throw as
       // an abort.
-      SaveAndRestore<bool> OldSink(Builder->BuildSinks);
-      Builder->BuildSinks = true;
-      MakeNode(Dst, S, Pred, Pred->getState());
+      Bldr.generateNode(S, Pred, Pred->getState());
       break;
     }
 
     case Stmt::ReturnStmtClass:
+      Bldr.takeNodes(Pred);
       VisitReturnStmt(cast<ReturnStmt>(S), Pred, Dst);
+      Bldr.addNodes(Dst);
       break;
 
     case Stmt::OffsetOfExprClass:
+      Bldr.takeNodes(Pred);
       VisitOffsetOfExpr(cast<OffsetOfExpr>(S), Pred, Dst);
+      Bldr.addNodes(Dst);
       break;
 
     case Stmt::UnaryExprOrTypeTraitExprClass:
+      Bldr.takeNodes(Pred);
       VisitUnaryExprOrTypeTraitExpr(cast<UnaryExprOrTypeTraitExpr>(S),
                                     Pred, Dst);
+      Bldr.addNodes(Dst);
       break;
 
     case Stmt::StmtExprClass: {
@@ -770,81 +928,154 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
         // Empty statement expression.
         assert(SE->getType() == getContext().VoidTy
                && "Empty statement expression must have void type.");
-        Dst.Add(Pred);
         break;
       }
 
       if (Expr *LastExpr = dyn_cast<Expr>(*SE->getSubStmt()->body_rbegin())) {
-        const ProgramState *state = Pred->getState();
-        MakeNode(Dst, SE, Pred, state->BindExpr(SE, state->getSVal(LastExpr)));
+        ProgramStateRef state = Pred->getState();
+        Bldr.generateNode(SE, Pred,
+                          state->BindExpr(SE, Pred->getLocationContext(),
+                                          state->getSVal(LastExpr,
+                                                  Pred->getLocationContext())));
       }
-      else
-        Dst.Add(Pred);
-
       break;
     }
 
-    case Stmt::StringLiteralClass: {
-      const ProgramState *state = Pred->getState();
-      SVal V = state->getLValue(cast<StringLiteral>(S));
-      MakeNode(Dst, S, Pred, state->BindExpr(S, V));
-      return;
-    }
-
     case Stmt::UnaryOperatorClass: {
+      Bldr.takeNodes(Pred);
       const UnaryOperator *U = cast<UnaryOperator>(S);
-      if (AMgr.shouldEagerlyAssume()&&(U->getOpcode() == UO_LNot)) {
+      if (AMgr.shouldEagerlyAssume() && (U->getOpcode() == UO_LNot)) {
         ExplodedNodeSet Tmp;
         VisitUnaryOperator(U, Pred, Tmp);
         evalEagerlyAssume(Dst, Tmp, U);
       }
       else
         VisitUnaryOperator(U, Pred, Dst);
+      Bldr.addNodes(Dst);
+      break;
+    }
+
+    case Stmt::PseudoObjectExprClass: {
+      Bldr.takeNodes(Pred);
+      ProgramStateRef state = Pred->getState();
+      const PseudoObjectExpr *PE = cast<PseudoObjectExpr>(S);
+      if (const Expr *Result = PE->getResultExpr()) { 
+        SVal V = state->getSVal(Result, Pred->getLocationContext());
+        Bldr.generateNode(S, Pred,
+                          state->BindExpr(S, Pred->getLocationContext(), V));
+      }
+      else
+        Bldr.generateNode(S, Pred,
+                          state->BindExpr(S, Pred->getLocationContext(),
+                                                   UnknownVal()));
+
+      Bldr.addNodes(Dst);
       break;
     }
   }
 }
 
-//===----------------------------------------------------------------------===//
-// Block entrance.  (Update counters).
-//===----------------------------------------------------------------------===//
+bool ExprEngine::replayWithoutInlining(ExplodedNode *N,
+                                       const LocationContext *CalleeLC) {
+  const StackFrameContext *CalleeSF = CalleeLC->getCurrentStackFrame();
+  const StackFrameContext *CallerSF = CalleeSF->getParent()->getCurrentStackFrame();
+  assert(CalleeSF && CallerSF);
+  ExplodedNode *BeforeProcessingCall = 0;
+
+  // Find the first node before we started processing the call expression.
+  while (N) {
+    ProgramPoint L = N->getLocation();
+    BeforeProcessingCall = N;
+    N = N->pred_empty() ? NULL : *(N->pred_begin());
+
+    // Skip the nodes corresponding to the inlined code.
+    if (L.getLocationContext()->getCurrentStackFrame() != CallerSF)
+      continue;
+    // We reached the caller. Find the node right before we started
+    // processing the CallExpr.
+    if (isa<PostPurgeDeadSymbols>(L))
+      continue;
+    if (const StmtPoint *SP = dyn_cast<StmtPoint>(&L))
+      if (SP->getStmt() == CalleeSF->getCallSite())
+        continue;
+    break;
+  }
+
+  if (!BeforeProcessingCall)
+    return false;
+
+  // TODO: Clean up the unneeded nodes.
+
+  // Build an Epsilon node from which we will restart the analyzes.
+  const Stmt *CE = CalleeSF->getCallSite();
+  ProgramPoint NewNodeLoc =
+               EpsilonPoint(BeforeProcessingCall->getLocationContext(), CE);
+  // Add the special flag to GDM to signal retrying with no inlining.
+  // Note, changing the state ensures that we are not going to cache out.
+  ProgramStateRef NewNodeState = BeforeProcessingCall->getState();
+  NewNodeState = NewNodeState->set<ReplayWithoutInlining>((void*)CE);
+
+  // Make the new node a successor of BeforeProcessingCall.
+  bool IsNew = false;
+  ExplodedNode *NewNode = G.getNode(NewNodeLoc, NewNodeState, false, &IsNew);
+  // We cached out at this point. Caching out is common due to us backtracking
+  // from the inlined function, which might spawn several paths.
+  if (!IsNew)
+    return true;
+
+  NewNode->addPredecessor(BeforeProcessingCall, G);
 
-void ExprEngine::processCFGBlockEntrance(ExplodedNodeSet &dstNodes,
-                               GenericNodeBuilder<BlockEntrance> &nodeBuilder){
+  // Add the new node to the work list.
+  Engine.enqueueStmtNode(NewNode, CalleeSF->getCallSiteBlock(),
+                                  CalleeSF->getIndex());
+  NumTimesRetriedWithoutInlining++;
+  return true;
+}
+
+/// Block entrance.  (Update counters).
+void ExprEngine::processCFGBlockEntrance(const BlockEdge &L,
+                                         NodeBuilderWithSinks &nodeBuilder) {
   
   // FIXME: Refactor this into a checker.
-  const CFGBlock *block = nodeBuilder.getProgramPoint().getBlock();
-  ExplodedNode *pred = nodeBuilder.getPredecessor();
+  ExplodedNode *pred = nodeBuilder.getContext().getPred();
   
-  if (nodeBuilder.getBlockCounter().getNumVisited(
-                       pred->getLocationContext()->getCurrentStackFrame(), 
-                       block->getBlockID()) >= AMgr.getMaxVisit()) {
+  if (nodeBuilder.getContext().getCurrentBlockCount() >= AMgr.getMaxVisit()) {
     static SimpleProgramPointTag tag("ExprEngine : Block count exceeded");
-    nodeBuilder.generateNode(pred->getState(), pred, &tag, true);
-  }
-}
-
-//===----------------------------------------------------------------------===//
-// Generic node creation.
-//===----------------------------------------------------------------------===//
+    const ExplodedNode *Sink =
+                   nodeBuilder.generateNode(pred->getState(), pred, &tag, true);
+
+    // Check if we stopped at the top level function or not.
+    // Root node should have the location context of the top most function.
+    const LocationContext *CalleeLC = pred->getLocation().getLocationContext();
+    const LocationContext *CalleeSF = CalleeLC->getCurrentStackFrame();
+    const LocationContext *RootLC =
+                        (*G.roots_begin())->getLocation().getLocationContext();
+    if (RootLC->getCurrentStackFrame() != CalleeSF) {
+      Engine.FunctionSummaries->markReachedMaxBlockCount(CalleeSF->getDecl());
+
+      // Re-run the call evaluation without inlining it, by storing the
+      // no-inlining policy in the state and enqueuing the new work item on
+      // the list. Replay should almost never fail. Use the stats to catch it
+      // if it does.
+      if ((!AMgr.NoRetryExhausted && replayWithoutInlining(pred, CalleeLC)))
+        return;
+      NumMaxBlockCountReachedInInlined++;
+    } else
+      NumMaxBlockCountReached++;
 
-ExplodedNode *ExprEngine::MakeNode(ExplodedNodeSet &Dst, const Stmt *S,
-                                   ExplodedNode *Pred, const ProgramState *St,
-                                   ProgramPoint::Kind K,
-                                   const ProgramPointTag *tag) {
-  assert (Builder && "StmtNodeBuilder not present.");
-  SaveAndRestore<const ProgramPointTag*> OldTag(Builder->Tag);
-  Builder->Tag = tag;
-  return Builder->MakeNode(Dst, S, Pred, St, K);
+    // Make sink nodes as exhausted(for stats) only if retry failed.
+    Engine.blocksExhausted.push_back(std::make_pair(L, Sink));
+  }
 }
 
 //===----------------------------------------------------------------------===//
 // Branch processing.
 //===----------------------------------------------------------------------===//
 
-const ProgramState *ExprEngine::MarkBranch(const ProgramState *state,
-                                        const Stmt *Terminator,
-                                        bool branchTaken) {
+ProgramStateRef ExprEngine::MarkBranch(ProgramStateRef state,
+                                           const Stmt *Terminator,
+                                           const LocationContext *LCtx,
+                                           bool branchTaken) {
 
   switch (Terminator->getStmtClass()) {
     default:
@@ -867,7 +1098,7 @@ const ProgramState *ExprEngine::MarkBranch(const ProgramState *state,
                        (Op == BO_LOr && !branchTaken)
                        ? B->getRHS() : B->getLHS();
 
-      return state->BindExpr(B, UndefinedVal(Ex));
+      return state->BindExpr(B, LCtx, UndefinedVal(Ex));
     }
 
     case Stmt::BinaryConditionalOperatorClass:
@@ -885,7 +1116,7 @@ const ProgramState *ExprEngine::MarkBranch(const ProgramState *state,
       else
         Ex = C->getFalseExpr();
 
-      return state->BindExpr(C, UndefinedVal(Ex));
+      return state->BindExpr(C, LCtx, UndefinedVal(Ex));
     }
 
     case Stmt::ChooseExprClass: { // ?:
@@ -893,7 +1124,7 @@ const ProgramState *ExprEngine::MarkBranch(const ProgramState *state,
       const ChooseExpr *C = cast<ChooseExpr>(Terminator);
 
       const Expr *Ex = branchTaken ? C->getLHS() : C->getRHS();
-      return state->BindExpr(C, UndefinedVal(Ex));
+      return state->BindExpr(C, LCtx, UndefinedVal(Ex));
     }
   }
 }
@@ -904,8 +1135,9 @@ const ProgramState *ExprEngine::MarkBranch(const ProgramState *state,
 /// This function returns the SVal bound to Condition->IgnoreCasts if all the
 //  cast(s) did was sign-extend the original value.
 static SVal RecoverCastedSymbol(ProgramStateManager& StateMgr,
-                                const ProgramState *state,
+                                ProgramStateRef state,
                                 const Stmt *Condition,
+                                const LocationContext *LCtx,
                                 ASTContext &Ctx) {
 
   const Expr *Ex = dyn_cast<Expr>(Condition);
@@ -936,15 +1168,22 @@ static SVal RecoverCastedSymbol(ProgramStateManager& StateMgr,
   if (!bitsInit || !T->isIntegerType() || Ctx.getTypeSize(T) > bits)
     return UnknownVal();
 
-  return state->getSVal(Ex);
+  return state->getSVal(Ex, LCtx);
 }
 
 void ExprEngine::processBranch(const Stmt *Condition, const Stmt *Term,
-                                 BranchNodeBuilder& builder) {
+                               NodeBuilderContext& BldCtx,
+                               ExplodedNode *Pred,
+                               ExplodedNodeSet &Dst,
+                               const CFGBlock *DstT,
+                               const CFGBlock *DstF) {
+  currentBuilderContext = &BldCtx;
 
   // Check for NULL conditions; e.g. "for(;;)"
   if (!Condition) {
-    builder.markInfeasible(false);
+    BranchNodeBuilder NullCondBldr(Pred, Dst, BldCtx, DstT, DstF);
+    NullCondBldr.markInfeasible(false);
+    NullCondBldr.generateNode(Pred->getState(), true, Pred);
     return;
   }
 
@@ -952,65 +1191,84 @@ void ExprEngine::processBranch(const Stmt *Condition, const Stmt *Term,
                                 Condition->getLocStart(),
                                 "Error evaluating branch");
 
-  getCheckerManager().runCheckersForBranchCondition(Condition, builder, *this);
-
-  // If the branch condition is undefined, return;
-  if (!builder.isFeasible(true) && !builder.isFeasible(false))
+  ExplodedNodeSet CheckersOutSet;
+  getCheckerManager().runCheckersForBranchCondition(Condition, CheckersOutSet,
+                                                    Pred, *this);
+  // We generated only sinks.
+  if (CheckersOutSet.empty())
     return;
 
-  const ProgramState *PrevState = builder.getState();
-  SVal X = PrevState->getSVal(Condition);
-
-  if (X.isUnknownOrUndef()) {
-    // Give it a chance to recover from unknown.
-    if (const Expr *Ex = dyn_cast<Expr>(Condition)) {
-      if (Ex->getType()->isIntegerType()) {
-        // Try to recover some path-sensitivity.  Right now casts of symbolic
-        // integers that promote their values are currently not tracked well.
-        // If 'Condition' is such an expression, try and recover the
-        // underlying value and use that instead.
-        SVal recovered = RecoverCastedSymbol(getStateManager(),
-                                             builder.getState(), Condition,
-                                             getContext());
-
-        if (!recovered.isUnknown()) {
-          X = recovered;
+  BranchNodeBuilder builder(CheckersOutSet, Dst, BldCtx, DstT, DstF);
+  for (NodeBuilder::iterator I = CheckersOutSet.begin(),
+                             E = CheckersOutSet.end(); E != I; ++I) {
+    ExplodedNode *PredI = *I;
+
+    if (PredI->isSink())
+      continue;
+
+    ProgramStateRef PrevState = Pred->getState();
+    SVal X = PrevState->getSVal(Condition, Pred->getLocationContext());
+
+    if (X.isUnknownOrUndef()) {
+      // Give it a chance to recover from unknown.
+      if (const Expr *Ex = dyn_cast<Expr>(Condition)) {
+        if (Ex->getType()->isIntegerType()) {
+          // Try to recover some path-sensitivity.  Right now casts of symbolic
+          // integers that promote their values are currently not tracked well.
+          // If 'Condition' is such an expression, try and recover the
+          // underlying value and use that instead.
+          SVal recovered = RecoverCastedSymbol(getStateManager(),
+                                               PrevState, Condition,
+                                               Pred->getLocationContext(),
+                                               getContext());
+
+          if (!recovered.isUnknown()) {
+            X = recovered;
+          }
         }
       }
     }
+    
+    const LocationContext *LCtx = PredI->getLocationContext();
+
     // If the condition is still unknown, give up.
     if (X.isUnknownOrUndef()) {
-      builder.generateNode(MarkBranch(PrevState, Term, true), true);
-      builder.generateNode(MarkBranch(PrevState, Term, false), false);
-      return;
+      builder.generateNode(MarkBranch(PrevState, Term, LCtx, true),
+                           true, PredI);
+      builder.generateNode(MarkBranch(PrevState, Term, LCtx, false),
+                           false, PredI);
+      continue;
     }
-  }
 
-  DefinedSVal V = cast<DefinedSVal>(X);
+    DefinedSVal V = cast<DefinedSVal>(X);
 
-  // Process the true branch.
-  if (builder.isFeasible(true)) {
-    if (const ProgramState *state = PrevState->assume(V, true))
-      builder.generateNode(MarkBranch(state, Term, true), true);
-    else
-      builder.markInfeasible(true);
-  }
+    // Process the true branch.
+    if (builder.isFeasible(true)) {
+      if (ProgramStateRef state = PrevState->assume(V, true))
+        builder.generateNode(MarkBranch(state, Term, LCtx, true),
+                             true, PredI);
+      else
+        builder.markInfeasible(true);
+    }
 
-  // Process the false branch.
-  if (builder.isFeasible(false)) {
-    if (const ProgramState *state = PrevState->assume(V, false))
-      builder.generateNode(MarkBranch(state, Term, false), false);
-    else
-      builder.markInfeasible(false);
+    // Process the false branch.
+    if (builder.isFeasible(false)) {
+      if (ProgramStateRef state = PrevState->assume(V, false))
+        builder.generateNode(MarkBranch(state, Term, LCtx, false),
+                             false, PredI);
+      else
+        builder.markInfeasible(false);
+    }
   }
+  currentBuilderContext = 0;
 }
 
 /// processIndirectGoto - Called by CoreEngine.  Used to generate successor
 ///  nodes by processing the 'effects' of a computed goto jump.
 void ExprEngine::processIndirectGoto(IndirectGotoNodeBuilder &builder) {
 
-  const ProgramState *state = builder.getState();
-  SVal V = state->getSVal(builder.getTarget());
+  ProgramStateRef state = builder.getState();
+  SVal V = state->getSVal(builder.getTarget(), builder.getLocationContext());
 
   // Three possibilities:
   //
@@ -1051,18 +1309,20 @@ void ExprEngine::processIndirectGoto(IndirectGotoNodeBuilder &builder) {
 
 /// ProcessEndPath - Called by CoreEngine.  Used to generate end-of-path
 ///  nodes when the control reaches the end of a function.
-void ExprEngine::processEndOfFunction(EndOfFunctionNodeBuilder& builder) {
-  StateMgr.EndPath(builder.getState());
-  getCheckerManager().runCheckersForEndPath(builder, *this);
+void ExprEngine::processEndOfFunction(NodeBuilderContext& BC) {
+  StateMgr.EndPath(BC.Pred->getState());
+  ExplodedNodeSet Dst;
+  getCheckerManager().runCheckersForEndPath(BC, Dst, *this);
+  Engine.enqueueEndOfFunction(Dst);
 }
 
 /// ProcessSwitch - Called by CoreEngine.  Used to generate successor
 ///  nodes by processing the 'effects' of a switch statement.
 void ExprEngine::processSwitch(SwitchNodeBuilder& builder) {
   typedef SwitchNodeBuilder::iterator iterator;
-  const ProgramState *state = builder.getState();
+  ProgramStateRef state = builder.getState();
   const Expr *CondE = builder.getCondition();
-  SVal  CondV_untested = state->getSVal(CondE);
+  SVal  CondV_untested = state->getSVal(CondE, builder.getLocationContext());
 
   if (CondV_untested.isUndef()) {
     //ExplodedNode* N = builder.generateDefaultCaseNode(state, true);
@@ -1073,7 +1333,7 @@ void ExprEngine::processSwitch(SwitchNodeBuilder& builder) {
   }
   DefinedOrUnknownSVal CondV = cast<DefinedOrUnknownSVal>(CondV_untested);
 
-  const ProgramState *DefaultSt = state;
+  ProgramStateRef DefaultSt = state;
   
   iterator I = builder.begin(), EI = builder.end();
   bool defaultIsFeasible = I == EI;
@@ -1106,7 +1366,7 @@ void ExprEngine::processSwitch(SwitchNodeBuilder& builder) {
                                                CondV, CaseVal);
 
       // Now "assume" that the case matches.
-      if (const ProgramState *stateNew = state->assume(Res, true)) {
+      if (ProgramStateRef stateNew = state->assume(Res, true)) {
         builder.generateCaseStmtNode(I, stateNew);
 
         // If CondV evaluates to a constant, then we know that this
@@ -1119,7 +1379,7 @@ void ExprEngine::processSwitch(SwitchNodeBuilder& builder) {
       // Now "assume" that the case doesn't match.  Add this state
       // to the default state (if it is feasible).
       if (DefaultSt) {
-        if (const ProgramState *stateNew = DefaultSt->assume(Res, false)) {
+        if (ProgramStateRef stateNew = DefaultSt->assume(Res, false)) {
           defaultIsFeasible = true;
           DefaultSt = stateNew;
         }
@@ -1166,7 +1426,10 @@ void ExprEngine::processSwitch(SwitchNodeBuilder& builder) {
 void ExprEngine::VisitCommonDeclRefExpr(const Expr *Ex, const NamedDecl *D,
                                         ExplodedNode *Pred,
                                         ExplodedNodeSet &Dst) {
-  const ProgramState *state = Pred->getState();
+  StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext);
+
+  ProgramStateRef state = Pred->getState();
+  const LocationContext *LCtx = Pred->getLocationContext();
 
   if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
     assert(Ex->isLValue());
@@ -1181,22 +1444,29 @@ void ExprEngine::VisitCommonDeclRefExpr(const Expr *Ex, const NamedDecl *D,
         V = UnknownVal();
     }
 
-    MakeNode(Dst, Ex, Pred, state->BindExpr(Ex, V),
-             ProgramPoint::PostLValueKind);
+    Bldr.generateNode(Ex, Pred, state->BindExpr(Ex, LCtx, V), false, 0,
+                      ProgramPoint::PostLValueKind);
     return;
   }
   if (const EnumConstantDecl *ED = dyn_cast<EnumConstantDecl>(D)) {
     assert(!Ex->isLValue());
     SVal V = svalBuilder.makeIntVal(ED->getInitVal());
-    MakeNode(Dst, Ex, Pred, state->BindExpr(Ex, V));
+    Bldr.generateNode(Ex, Pred, state->BindExpr(Ex, LCtx, V));
     return;
   }
   if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
     SVal V = svalBuilder.getFunctionPointer(FD);
-    MakeNode(Dst, Ex, Pred, state->BindExpr(Ex, V),
-             ProgramPoint::PostLValueKind);
+    Bldr.generateNode(Ex, Pred, state->BindExpr(Ex, LCtx, V), false, 0,
+                      ProgramPoint::PostLValueKind);
+    return;
+  }
+  if (isa<FieldDecl>(D)) {
+    // FIXME: Compute lvalue of fields.
+    Bldr.generateNode(Ex, Pred, state->BindExpr(Ex, LCtx, UnknownVal()),
+		      false, 0, ProgramPoint::PostLValueKind);
     return;
   }
+
   assert (false &&
           "ValueDecl support for this ValueDecl not implemented.");
 }
@@ -1213,24 +1483,33 @@ void ExprEngine::VisitLvalArraySubscriptExpr(const ArraySubscriptExpr *A,
   ExplodedNodeSet checkerPreStmt;
   getCheckerManager().runCheckersForPreStmt(checkerPreStmt, Pred, A, *this);
 
+  StmtNodeBuilder Bldr(checkerPreStmt, Dst, *currentBuilderContext);
+
   for (ExplodedNodeSet::iterator it = checkerPreStmt.begin(),
                                  ei = checkerPreStmt.end(); it != ei; ++it) {
-    const ProgramState *state = (*it)->getState();
-    SVal V = state->getLValue(A->getType(), state->getSVal(Idx),
-                              state->getSVal(Base));
+    const LocationContext *LCtx = (*it)->getLocationContext();
+    ProgramStateRef state = (*it)->getState();
+    SVal V = state->getLValue(A->getType(),
+                              state->getSVal(Idx, LCtx),
+                              state->getSVal(Base, LCtx));
     assert(A->isLValue());
-    MakeNode(Dst, A, *it, state->BindExpr(A, V), ProgramPoint::PostLValueKind);
+    Bldr.generateNode(A, *it, state->BindExpr(A, LCtx, V),
+                      false, 0, ProgramPoint::PostLValueKind);
   }
 }
 
 /// VisitMemberExpr - Transfer function for member expressions.
 void ExprEngine::VisitMemberExpr(const MemberExpr *M, ExplodedNode *Pred,
-                                 ExplodedNodeSet &Dst) {
+                                 ExplodedNodeSet &TopDst) {
 
+  StmtNodeBuilder Bldr(Pred, TopDst, *currentBuilderContext);
+  ExplodedNodeSet Dst;
   Decl *member = M->getMemberDecl();
   if (VarDecl *VD = dyn_cast<VarDecl>(member)) {
     assert(M->isLValue());
+    Bldr.takeNodes(Pred);
     VisitCommonDeclRefExpr(M, VD, Pred, Dst);
+    Bldr.addNodes(Dst);
     return;
   }
   
@@ -1239,15 +1518,16 @@ void ExprEngine::VisitMemberExpr(const MemberExpr *M, ExplodedNode *Pred,
     return;
 
   Expr *baseExpr = M->getBase()->IgnoreParens();
-  const ProgramState *state = Pred->getState();
-  SVal baseExprVal = state->getSVal(baseExpr);
+  ProgramStateRef state = Pred->getState();
+  const LocationContext *LCtx = Pred->getLocationContext();
+  SVal baseExprVal = state->getSVal(baseExpr, Pred->getLocationContext());
   if (isa<nonloc::LazyCompoundVal>(baseExprVal) ||
       isa<nonloc::CompoundVal>(baseExprVal) ||
       // FIXME: This can originate by conjuring a symbol for an unknown
       // temporary struct object, see test/Analysis/fields.c:
       // (p = getit()).x
       isa<nonloc::SymbolVal>(baseExprVal)) {
-    MakeNode(Dst, M, Pred, state->BindExpr(M, UnknownVal()));
+    Bldr.generateNode(M, Pred, state->BindExpr(M, LCtx, UnknownVal()));
     return;
   }
 
@@ -1258,9 +1538,13 @@ void ExprEngine::VisitMemberExpr(const MemberExpr *M, ExplodedNode *Pred,
   // For all other cases, compute an lvalue.    
   SVal L = state->getLValue(field, baseExprVal);
   if (M->isLValue())
-    MakeNode(Dst, M, Pred, state->BindExpr(M, L), ProgramPoint::PostLValueKind);
-  else
-    evalLoad(Dst, M, Pred, state, L);
+    Bldr.generateNode(M, Pred, state->BindExpr(M, LCtx, L), false, 0,
+                      ProgramPoint::PostLValueKind);
+  else {
+    Bldr.takeNodes(Pred);
+    evalLoad(Dst, M, M, Pred, state, L);
+    Bldr.addNodes(Dst);
+  }
 }
 
 /// evalBind - Handle the semantics of binding a value to a specific location.
@@ -1272,12 +1556,17 @@ void ExprEngine::evalBind(ExplodedNodeSet &Dst, const Stmt *StoreE,
   // Do a previsit of the bind.
   ExplodedNodeSet CheckedSet;
   getCheckerManager().runCheckersForBind(CheckedSet, Pred, location, Val,
-                                         StoreE, *this);
+                                         StoreE, *this,
+                                         ProgramPoint::PostStmtKind);
 
+  ExplodedNodeSet TmpDst;
+  StmtNodeBuilder Bldr(CheckedSet, TmpDst, *currentBuilderContext);
+
+  const LocationContext *LC = Pred->getLocationContext();
   for (ExplodedNodeSet::iterator I = CheckedSet.begin(), E = CheckedSet.end();
        I!=E; ++I) {
-
-    const ProgramState *state = (*I)->getState();
+    ExplodedNode *PredI = *I;
+    ProgramStateRef state = PredI->getState();
 
     if (atDeclInit) {
       const VarRegion *VR =
@@ -1288,8 +1577,15 @@ void ExprEngine::evalBind(ExplodedNodeSet &Dst, const Stmt *StoreE,
       state = state->bindLoc(location, Val);
     }
 
-    MakeNode(Dst, StoreE, *I, state);
+    const MemRegion *LocReg = 0;
+    if (loc::MemRegionVal *LocRegVal = dyn_cast<loc::MemRegionVal>(&location))
+      LocReg = LocRegVal->getRegion();
+
+    const ProgramPoint L = PostStore(StoreE, LC, LocReg, 0);
+    Bldr.generateNode(L, PredI, state, false);
   }
+
+  Dst.insert(TmpDst);
 }
 
 /// evalStore - Handle the semantics of a store via an assignment.
@@ -1303,24 +1599,19 @@ void ExprEngine::evalBind(ExplodedNodeSet &Dst, const Stmt *StoreE,
 void ExprEngine::evalStore(ExplodedNodeSet &Dst, const Expr *AssignE,
                              const Expr *LocationE,
                              ExplodedNode *Pred,
-                             const ProgramState *state, SVal location, SVal Val,
+                             ProgramStateRef state, SVal location, SVal Val,
                              const ProgramPointTag *tag) {
-
-  assert(Builder && "StmtNodeBuilder must be defined.");
-
   // Proceed with the store.  We use AssignE as the anchor for the PostStore
   // ProgramPoint if it is non-NULL, and LocationE otherwise.
   const Expr *StoreE = AssignE ? AssignE : LocationE;
 
   if (isa<loc::ObjCPropRef>(location)) {
-    loc::ObjCPropRef prop = cast<loc::ObjCPropRef>(location);
-    return VisitObjCMessage(ObjCPropertySetter(prop.getPropRefExpr(),
-                                               StoreE, Val), Pred, Dst);
+    assert(false);
   }
 
   // Evaluate the location (checks for bad dereferences).
   ExplodedNodeSet Tmp;
-  evalLocation(Tmp, LocationE, Pred, state, location, tag, false);
+  evalLocation(Tmp, AssignE, LocationE, Pred, state, location, tag, false);
 
   if (Tmp.empty())
     return;
@@ -1328,24 +1619,21 @@ void ExprEngine::evalStore(ExplodedNodeSet &Dst, const Expr *AssignE,
   if (location.isUndef())
     return;
 
-  SaveAndRestore<ProgramPoint::Kind> OldSPointKind(Builder->PointKind,
-                                                   ProgramPoint::PostStoreKind);
-
   for (ExplodedNodeSet::iterator NI=Tmp.begin(), NE=Tmp.end(); NI!=NE; ++NI)
-    evalBind(Dst, StoreE, *NI, location, Val);
+    evalBind(Dst, StoreE, *NI, location, Val, false);
 }
 
-void ExprEngine::evalLoad(ExplodedNodeSet &Dst, const Expr *Ex,
-                            ExplodedNode *Pred,
-                            const ProgramState *state, SVal location,
-                            const ProgramPointTag *tag, QualType LoadTy) {
+void ExprEngine::evalLoad(ExplodedNodeSet &Dst,
+                          const Expr *NodeEx,
+                          const Expr *BoundEx,
+                          ExplodedNode *Pred,
+                          ProgramStateRef state,
+                          SVal location,
+                          const ProgramPointTag *tag,
+                          QualType LoadTy)
+{
   assert(!isa<NonLoc>(location) && "location cannot be a NonLoc.");
-
-  if (isa<loc::ObjCPropRef>(location)) {
-    loc::ObjCPropRef prop = cast<loc::ObjCPropRef>(location);
-    return VisitObjCMessage(ObjCPropertyGetter(prop.getPropRefExpr(), Ex),
-                            Pred, Dst);
-  }
+  assert(!isa<loc::ObjCPropRef>(location));
 
   // Are we loading from a region?  This actually results in two loads; one
   // to fetch the address of the referenced value and one to fetch the
@@ -1358,72 +1646,84 @@ void ExprEngine::evalLoad(ExplodedNodeSet &Dst, const Expr *Ex,
       static SimpleProgramPointTag
              loadReferenceTag("ExprEngine : Load Reference");
       ExplodedNodeSet Tmp;
-      evalLoadCommon(Tmp, Ex, Pred, state, location, &loadReferenceTag,
+      evalLoadCommon(Tmp, NodeEx, BoundEx, Pred, state,
+                     location, &loadReferenceTag,
                      getContext().getPointerType(RT->getPointeeType()));
 
       // Perform the load from the referenced value.
       for (ExplodedNodeSet::iterator I=Tmp.begin(), E=Tmp.end() ; I!=E; ++I) {
         state = (*I)->getState();
-        location = state->getSVal(Ex);
-        evalLoadCommon(Dst, Ex, *I, state, location, tag, LoadTy);
+        location = state->getSVal(BoundEx, (*I)->getLocationContext());
+        evalLoadCommon(Dst, NodeEx, BoundEx, *I, state, location, tag, LoadTy);
       }
       return;
     }
   }
 
-  evalLoadCommon(Dst, Ex, Pred, state, location, tag, LoadTy);
+  evalLoadCommon(Dst, NodeEx, BoundEx, Pred, state, location, tag, LoadTy);
 }
 
-void ExprEngine::evalLoadCommon(ExplodedNodeSet &Dst, const Expr *Ex,
-                                  ExplodedNode *Pred,
-                                  const ProgramState *state, SVal location,
-                                  const ProgramPointTag *tag, QualType LoadTy) {
-
+void ExprEngine::evalLoadCommon(ExplodedNodeSet &Dst,
+                                const Expr *NodeEx,
+                                const Expr *BoundEx,
+                                ExplodedNode *Pred,
+                                ProgramStateRef state,
+                                SVal location,
+                                const ProgramPointTag *tag,
+                                QualType LoadTy) {
+  assert(NodeEx);
+  assert(BoundEx);
   // Evaluate the location (checks for bad dereferences).
   ExplodedNodeSet Tmp;
-  evalLocation(Tmp, Ex, Pred, state, location, tag, true);
-
+  evalLocation(Tmp, NodeEx, BoundEx, Pred, state, location, tag, true);
   if (Tmp.empty())
     return;
 
+  StmtNodeBuilder Bldr(Tmp, Dst, *currentBuilderContext);
   if (location.isUndef())
     return;
 
-  SaveAndRestore<ProgramPoint::Kind> OldSPointKind(Builder->PointKind);
-
   // Proceed with the load.
   for (ExplodedNodeSet::iterator NI=Tmp.begin(), NE=Tmp.end(); NI!=NE; ++NI) {
     state = (*NI)->getState();
+    const LocationContext *LCtx = (*NI)->getLocationContext();
 
     if (location.isUnknown()) {
       // This is important.  We must nuke the old binding.
-      MakeNode(Dst, Ex, *NI, state->BindExpr(Ex, UnknownVal()),
-               ProgramPoint::PostLoadKind, tag);
+      Bldr.generateNode(NodeEx, *NI,
+                        state->BindExpr(BoundEx, LCtx, UnknownVal()),
+                        false, tag,
+                        ProgramPoint::PostLoadKind);
     }
     else {
       if (LoadTy.isNull())
-        LoadTy = Ex->getType();
+        LoadTy = BoundEx->getType();
       SVal V = state->getSVal(cast<Loc>(location), LoadTy);
-      MakeNode(Dst, Ex, *NI, state->bindExprAndLocation(Ex, location, V),
-               ProgramPoint::PostLoadKind, tag);
+      Bldr.generateNode(NodeEx, *NI,
+                        state->bindExprAndLocation(BoundEx, LCtx, location, V),
+                        false, tag, ProgramPoint::PostLoadKind);
     }
   }
 }
 
-void ExprEngine::evalLocation(ExplodedNodeSet &Dst, const Stmt *S,
-                                ExplodedNode *Pred,
-                                const ProgramState *state, SVal location,
-                                const ProgramPointTag *tag, bool isLoad) {
+void ExprEngine::evalLocation(ExplodedNodeSet &Dst,
+                              const Stmt *NodeEx,
+                              const Stmt *BoundEx,
+                              ExplodedNode *Pred,
+                              ProgramStateRef state,
+                              SVal location,
+                              const ProgramPointTag *tag,
+                              bool isLoad) {
+  StmtNodeBuilder BldrTop(Pred, Dst, *currentBuilderContext);
   // Early checks for performance reason.
   if (location.isUnknown()) {
-    Dst.Add(Pred);
     return;
   }
 
   ExplodedNodeSet Src;
-  if (Pred->getState() == state) {
-    Src.Add(Pred);
-  } else {
+  BldrTop.takeNodes(Pred);
+  StmtNodeBuilder Bldr(Pred, Src, *currentBuilderContext);
+  if (Pred->getState() != state) {
     // Associate this new state with an ExplodedNode.
     // FIXME: If I pass null tag, the graph is incorrect, e.g for
     //   int *p;
@@ -1435,88 +1735,12 @@ void ExprEngine::evalLocation(ExplodedNodeSet &Dst, const Stmt *S,
     
     // FIXME: why is 'tag' not used instead of etag?
     static SimpleProgramPointTag etag("ExprEngine: Location");
-
-    ExplodedNode *N = Builder->generateNode(S, state, Pred, &etag);
-    Src.Add(N ? N : Pred);
+    Bldr.generateNode(NodeEx, Pred, state, false, &etag);
   }
-  getCheckerManager().runCheckersForLocation(Dst, Src, location, isLoad, S,
-                                             *this);
-}
-
-bool ExprEngine::InlineCall(ExplodedNodeSet &Dst, const CallExpr *CE, 
-                              ExplodedNode *Pred) {
-  return false;
-  
-  // Inlining isn't correct right now because we:
-  // (a) don't generate CallExit nodes.
-  // (b) we need a way to postpone doing post-visits of CallExprs until
-  // the CallExit.  This means we need CallExits for the non-inline
-  // cases as well.
-  
-#if 0
-  const ProgramState *state = Pred->getState();
-  const Expr *Callee = CE->getCallee();
-  SVal L = state->getSVal(Callee);
-  
-  const FunctionDecl *FD = L.getAsFunctionDecl();
-  if (!FD)
-    return false;
-
-  // Specially handle CXXMethods.
-  const CXXMethodDecl *methodDecl = 0;
-  
-  switch (CE->getStmtClass()) {
-    default: break;
-    case Stmt::CXXOperatorCallExprClass: {
-      const CXXOperatorCallExpr *opCall = cast<CXXOperatorCallExpr>(CE);
-      methodDecl = 
-        dyn_cast_or_null<CXXMethodDecl>(opCall->getCalleeDecl());
-      break;
-    }
-    case Stmt::CXXMemberCallExprClass: {
-      const CXXMemberCallExpr *memberCall = cast<CXXMemberCallExpr>(CE);
-      const MemberExpr *memberExpr = 
-        cast<MemberExpr>(memberCall->getCallee()->IgnoreParens());
-      methodDecl = cast<CXXMethodDecl>(memberExpr->getMemberDecl());
-      break;
-    }
-  }
-      
-  
-  
-  
-  // Check if the function definition is in the same translation unit.
-  if (FD->hasBody(FD)) {
-    const StackFrameContext *stackFrame = 
-      AMgr.getStackFrame(AMgr.getAnalysisContext(FD), 
-                         Pred->getLocationContext(),
-                         CE, Builder->getBlock(), Builder->getIndex());
-    // Now we have the definition of the callee, create a CallEnter node.
-    CallEnter Loc(CE, stackFrame, Pred->getLocationContext());
-
-    ExplodedNode *N = Builder->generateNode(Loc, state, Pred);
-    Dst.Add(N);
-    return true;
-  }
-
-  // Check if we can find the function definition in other translation units.
-  if (AMgr.hasIndexer()) {
-    AnalysisContext *C = AMgr.getAnalysisContextInAnotherTU(FD);
-    if (C == 0)
-      return false;
-    const StackFrameContext *stackFrame = 
-      AMgr.getStackFrame(C, Pred->getLocationContext(),
-                         CE, Builder->getBlock(), Builder->getIndex());
-    CallEnter Loc(CE, stackFrame, Pred->getLocationContext());
-    ExplodedNode *N = Builder->generateNode(Loc, state, Pred);
-    Dst.Add(N);
-    return true;
-  }
-  
-  // Generate the CallExit node.
-
-  return false;
-#endif
+  ExplodedNodeSet Tmp;
+  getCheckerManager().runCheckersForLocation(Tmp, Src, location, isLoad,
+                                             NodeEx, BoundEx, *this);
+  BldrTop.addNodes(Tmp);
 }
 
 std::pair<const ProgramPointTag *, const ProgramPointTag*>
@@ -1528,108 +1752,67 @@ ExprEngine::getEagerlyAssumeTags() {
 }
 
 void ExprEngine::evalEagerlyAssume(ExplodedNodeSet &Dst, ExplodedNodeSet &Src,
-                                     const Expr *Ex) {
-  
+                                   const Expr *Ex) {
+  StmtNodeBuilder Bldr(Src, Dst, *currentBuilderContext);
   
   for (ExplodedNodeSet::iterator I=Src.begin(), E=Src.end(); I!=E; ++I) {
     ExplodedNode *Pred = *I;
-
     // Test if the previous node was as the same expression.  This can happen
     // when the expression fails to evaluate to anything meaningful and
     // (as an optimization) we don't generate a node.
     ProgramPoint P = Pred->getLocation();
     if (!isa<PostStmt>(P) || cast<PostStmt>(P).getStmt() != Ex) {
-      Dst.Add(Pred);
       continue;
     }
 
-    const ProgramState *state = Pred->getState();
-    SVal V = state->getSVal(Ex);
-    if (nonloc::SymExprVal *SEV = dyn_cast<nonloc::SymExprVal>(&V)) {
+    ProgramStateRef state = Pred->getState();
+    SVal V = state->getSVal(Ex, Pred->getLocationContext());
+    nonloc::SymbolVal *SEV = dyn_cast<nonloc::SymbolVal>(&V);
+    if (SEV && SEV->isExpression()) {
       const std::pair<const ProgramPointTag *, const ProgramPointTag*> &tags =
         getEagerlyAssumeTags();
 
       // First assume that the condition is true.
-      if (const ProgramState *StateTrue = state->assume(*SEV, true)) {
+      if (ProgramStateRef StateTrue = state->assume(*SEV, true)) {
         SVal Val = svalBuilder.makeIntVal(1U, Ex->getType());        
-        StateTrue = StateTrue->BindExpr(Ex, Val);
-        Dst.Add(Builder->generateNode(Ex, StateTrue, Pred, tags.first));
+        StateTrue = StateTrue->BindExpr(Ex, Pred->getLocationContext(), Val);
+        Bldr.generateNode(Ex, Pred, StateTrue, false, tags.first);
       }
 
       // Next, assume that the condition is false.
-      if (const ProgramState *StateFalse = state->assume(*SEV, false)) {
+      if (ProgramStateRef StateFalse = state->assume(*SEV, false)) {
         SVal Val = svalBuilder.makeIntVal(0U, Ex->getType());
-        StateFalse = StateFalse->BindExpr(Ex, Val);
-        Dst.Add(Builder->generateNode(Ex, StateFalse, Pred, tags.second));
+        StateFalse = StateFalse->BindExpr(Ex, Pred->getLocationContext(), Val);
+        Bldr.generateNode(Ex, Pred, StateFalse, false, tags.second);
       }
     }
-    else
-      Dst.Add(Pred);
   }
 }
 
 void ExprEngine::VisitAsmStmt(const AsmStmt *A, ExplodedNode *Pred,
-                                ExplodedNodeSet &Dst) {
-  VisitAsmStmtHelperOutputs(A, A->begin_outputs(), A->end_outputs(), Pred, Dst);
-}
-
-void ExprEngine::VisitAsmStmtHelperOutputs(const AsmStmt *A,
-                                             AsmStmt::const_outputs_iterator I,
-                                             AsmStmt::const_outputs_iterator E,
-                                     ExplodedNode *Pred, ExplodedNodeSet &Dst) {
-  if (I == E) {
-    VisitAsmStmtHelperInputs(A, A->begin_inputs(), A->end_inputs(), Pred, Dst);
-    return;
-  }
-
-  ExplodedNodeSet Tmp;
-  Visit(*I, Pred, Tmp);
-  ++I;
+                              ExplodedNodeSet &Dst) {
+  StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext);
+  // We have processed both the inputs and the outputs.  All of the outputs
+  // should evaluate to Locs.  Nuke all of their values.
 
-  for (ExplodedNodeSet::iterator NI = Tmp.begin(), NE = Tmp.end();NI != NE;++NI)
-    VisitAsmStmtHelperOutputs(A, I, E, *NI, Dst);
-}
-
-void ExprEngine::VisitAsmStmtHelperInputs(const AsmStmt *A,
-                                            AsmStmt::const_inputs_iterator I,
-                                            AsmStmt::const_inputs_iterator E,
-                                            ExplodedNode *Pred,
-                                            ExplodedNodeSet &Dst) {
-  if (I == E) {
-
-    // We have processed both the inputs and the outputs.  All of the outputs
-    // should evaluate to Locs.  Nuke all of their values.
-
-    // FIXME: Some day in the future it would be nice to allow a "plug-in"
-    // which interprets the inline asm and stores proper results in the
-    // outputs.
+  // FIXME: Some day in the future it would be nice to allow a "plug-in"
+  // which interprets the inline asm and stores proper results in the
+  // outputs.
 
-    const ProgramState *state = Pred->getState();
+  ProgramStateRef state = Pred->getState();
 
-    for (AsmStmt::const_outputs_iterator OI = A->begin_outputs(),
-                                   OE = A->end_outputs(); OI != OE; ++OI) {
-
-      SVal X = state->getSVal(*OI);
-      assert (!isa<NonLoc>(X));  // Should be an Lval, or unknown, undef.
-
-      if (isa<Loc>(X))
-        state = state->bindLoc(cast<Loc>(X), UnknownVal());
-    }
+  for (AsmStmt::const_outputs_iterator OI = A->begin_outputs(),
+       OE = A->end_outputs(); OI != OE; ++OI) {
+    SVal X = state->getSVal(*OI, Pred->getLocationContext());
+    assert (!isa<NonLoc>(X));  // Should be an Lval, or unknown, undef.
 
-    MakeNode(Dst, A, Pred, state);
-    return;
+    if (isa<Loc>(X))
+      state = state->bindLoc(cast<Loc>(X), UnknownVal());
   }
 
-  ExplodedNodeSet Tmp;
-  Visit(*I, Pred, Tmp);
-
-  ++I;
-
-  for (ExplodedNodeSet::iterator NI = Tmp.begin(), NE = Tmp.end(); NI!=NE; ++NI)
-    VisitAsmStmtHelperInputs(A, I, E, *NI, Dst);
+  Bldr.generateNode(A, Pred, state);
 }
 
-
 //===----------------------------------------------------------------------===//
 // Visualization.
 //===----------------------------------------------------------------------===//
@@ -1694,6 +1877,10 @@ struct DOTGraphTraits<ExplodedNode*> :
         Out << "CallExit";
         break;
 
+      case ProgramPoint::EpsilonKind:
+        Out << "Epsilon Point";
+        break;
+
       default: {
         if (StmtPoint *L = dyn_cast<StmtPoint>(&Loc)) {
           const Stmt *S = L->getStmt();
@@ -1811,10 +1998,10 @@ struct DOTGraphTraits<ExplodedNode*> :
       }
     }
 
-    const ProgramState *state = N->getState();
-    Out << "\\|StateID: " << (void*) state
+    ProgramStateRef state = N->getState();
+    Out << "\\|StateID: " << (void*) state.getPtr()
         << " NodeID: " << (void*) N << "\\|";
-    state->printDOT(Out, *N->getLocationContext()->getCFG());
+    state->printDOT(Out);
 
     Out << "\\l";    
 
@@ -1852,9 +2039,7 @@ void ExprEngine::ViewGraph(bool trim) {
     // Iterate through the reports and get their nodes.
     for (BugReporter::EQClasses_iterator
            EI = BR.EQClasses_begin(), EE = BR.EQClasses_end(); EI != EE; ++EI) {
-      BugReportEquivClass& EQ = *EI;
-      const BugReport &R = **EQ.begin();
-      ExplodedNode *N = const_cast<ExplodedNode*>(R.getErrorNode());
+      ExplodedNode *N = const_cast<ExplodedNode*>(EI->begin()->getErrorNode());
       if (N) Src.push_back(N);
     }
 
-- 
cgit v1.1