[cfe-commits] r142831 - in /cfe/trunk: include/clang/StaticAnalyzer/Core/ include/clang/StaticAnalyzer/Core/PathSensitive/ lib/StaticAnalyzer/Core/

Anna Zaks ganna at apple.com
Mon Oct 24 11:26:19 PDT 2011


Author: zaks
Date: Mon Oct 24 13:26:19 2011
New Revision: 142831

URL: http://llvm.org/viewvc/llvm-project?rev=142831&view=rev
Log:
[analyzer] Convert ExprEngine::visit() to use short lived builders.

This commit removes the major functional dependency on the ExprEngine::Builder
member variable.

In some cases the code became more verbose. Particularly, we call takeNodes()
and addNodes() to move responsibility for the nodes from one builder to another.
This will get simplified later on.

Modified:
    cfe/trunk/include/clang/StaticAnalyzer/Core/CheckerManager.h
    cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h
    cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h
    cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
    cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h
    cfe/trunk/lib/StaticAnalyzer/Core/CheckerManager.cpp
    cfe/trunk/lib/StaticAnalyzer/Core/CoreEngine.cpp
    cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp
    cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineC.cpp
    cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
    cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
    cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp

Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/CheckerManager.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/CheckerManager.h?rev=142831&r1=142830&r2=142831&view=diff
==============================================================================
--- cfe/trunk/include/clang/StaticAnalyzer/Core/CheckerManager.h (original)
+++ cfe/trunk/include/clang/StaticAnalyzer/Core/CheckerManager.h Mon Oct 24 13:26:19 2011
@@ -19,6 +19,7 @@
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/FoldingSet.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/Store.h"
+#include "clang/Analysis/ProgramPoint.h"
 #include <vector>
 
 namespace clang {
@@ -221,7 +222,8 @@
   void runCheckersForBind(ExplodedNodeSet &Dst,
                           const ExplodedNodeSet &Src,
                           SVal location, SVal val,
-                          const Stmt *S, ExprEngine &Eng);
+                          const Stmt *S, ExprEngine &Eng,
+                          ProgramPoint::Kind PointKind);
 
   /// \brief Run checkers for end of analysis.
   void runCheckersForEndAnalysis(ExplodedGraph &G, BugReporter &BR,

Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h?rev=142831&r1=142830&r2=142831&view=diff
==============================================================================
--- cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h (original)
+++ cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h Mon Oct 24 13:26:19 2011
@@ -69,7 +69,9 @@
 
   /// \brief Returns the number of times the current block has been visited
   /// along the analyzed path.
-  unsigned getCurrentBlockCount() {return NB.getCurrentBlockCount();}
+  unsigned getCurrentBlockCount() {
+    return NB.getContext().getCurrentBlockCount();
+  }
 
   ASTContext &getASTContext() {
     return Eng.getContext();

Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h?rev=142831&r1=142830&r2=142831&view=diff
==============================================================================
--- cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h (original)
+++ cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h Mon Oct 24 13:26:19 2011
@@ -39,16 +39,17 @@
 ///   at the statement and block-level.  The analyses themselves must implement
 ///   any transfer function logic and the sub-expression level (if any).
 class CoreEngine {
-  friend class CommonNodeBuilder;
+  friend struct NodeBuilderContext;
   friend class NodeBuilder;
   friend class StmtNodeBuilder;
+  friend class CommonNodeBuilder;
   friend class GenericNodeBuilderImpl;
-  friend class BranchNodeBuilder;
   friend class IndirectGotoNodeBuilder;
   friend class SwitchNodeBuilder;
   friend class EndOfFunctionNodeBuilder;
   friend class CallEnterNodeBuilder;
   friend class CallExitNodeBuilder;
+  friend class ExprEngine;
 
 public:
   typedef std::vector<std::pair<BlockEdge, const ExplodedNode*> >
@@ -174,6 +175,18 @@
   ExplodedNode *ContextPred;
   NodeBuilderContext(CoreEngine &E, const CFGBlock *B, ExplodedNode *N)
     : Eng(E), Block(B), ContextPred(N) { assert(B); assert(!N->isSink()); }
+
+  /// \brief Return the CFGBlock associated with this builder.
+  const CFGBlock *getBlock() const { return Block; }
+
+  /// \brief Returns the number of times the current basic block has been
+  /// visited on the exploded graph path.
+  unsigned getCurrentBlockCount() const {
+    return Eng.WList->getBlockCounter().getNumVisited(
+                    ContextPred->getLocationContext()->getCurrentStackFrame(),
+                    Block->getBlockID());
+  }
+
 };
 
 /// This is the simplest builder which generates nodes in the ExplodedGraph.
@@ -193,8 +206,6 @@
   /// the builder dies.
   ExplodedNodeSet &Frontier;
 
-  BlockCounter getBlockCounter() const { return C.Eng.WList->getBlockCounter();}
-
   /// Checkes if the results are ready.
   virtual bool checkResults() {
     if (!Finalized)
@@ -271,19 +282,8 @@
     return Frontier.end();
   }
 
-  /// \brief Return the CFGBlock associated with this builder.
-  const CFGBlock *getBlock() const { return C.Block; }
-
   const NodeBuilderContext &getContext() { return C; }
 
-  /// \brief Returns the number of times the current basic block has been
-  /// visited on the exploded graph path.
-  unsigned getCurrentBlockCount() const {
-    return getBlockCounter().getNumVisited(
-                    C.ContextPred->getLocationContext()->getCurrentStackFrame(),
-                    C.Block->getBlockID());
-  }
-
   void takeNodes(const ExplodedNodeSet &S) {
     for (ExplodedNodeSet::iterator I = S.begin(), E = S.end(); I != E; ++I )
       Frontier.erase(*I);
@@ -306,7 +306,7 @@
 class CommonNodeBuilder {
 protected:
   ExplodedNode *Pred;
-  CoreEngine& Eng;
+  CoreEngine &Eng;
 
   CommonNodeBuilder(CoreEngine* E, ExplodedNode *P) : Pred(P), Eng(*E) {}
   BlockCounter getBlockCounter() const { return Eng.WList->getBlockCounter(); }
@@ -314,21 +314,38 @@
 
 
 class PureStmtNodeBuilder: public NodeBuilder {
+  NodeBuilder *EnclosingBldr;
 public:
   PureStmtNodeBuilder(ExplodedNode *SrcNode, ExplodedNodeSet &DstSet,
-                      const NodeBuilderContext &Ctx)
-    : NodeBuilder(SrcNode, DstSet, Ctx) {}
+                      const NodeBuilderContext &Ctx, NodeBuilder *Enclosing = 0)
+    : NodeBuilder(SrcNode, DstSet, Ctx), EnclosingBldr(Enclosing) {
+    if (EnclosingBldr)
+      EnclosingBldr->takeNodes(SrcNode);
+  }
 
   PureStmtNodeBuilder(ExplodedNodeSet &SrcSet, ExplodedNodeSet &DstSet,
-                      const NodeBuilderContext &Ctx)
-    : NodeBuilder(SrcSet, DstSet, Ctx) {}
+                      const NodeBuilderContext &Ctx, NodeBuilder *Enclosing = 0)
+    : NodeBuilder(SrcSet, DstSet, Ctx), EnclosingBldr(Enclosing) {
+    if (EnclosingBldr)
+      for (ExplodedNodeSet::iterator I = SrcSet.begin(),
+                                     E = SrcSet.end(); I != E; ++I )
+        EnclosingBldr->takeNodes(*I);
+
+  }
+
+  virtual ~PureStmtNodeBuilder() {
+    if (EnclosingBldr)
+      for (ExplodedNodeSet::iterator I = Frontier.begin(),
+                                     E = Frontier.end(); I != E; ++I )
+        EnclosingBldr->addNodes(*I);
+  }
 
   ExplodedNode *generateNode(const Stmt *S,
                              ExplodedNode *Pred,
                              const ProgramState *St,
-                             ProgramPoint::Kind K = ProgramPoint::PostStmtKind,
                              bool MarkAsSink = false,
                              const ProgramPointTag *tag = 0,
+                             ProgramPoint::Kind K = ProgramPoint::PostStmtKind,
                              bool Purging = false) {
     if (Purging) {
       assert(K == ProgramPoint::PostStmtKind);
@@ -339,6 +356,14 @@
                                   Pred->getLocationContext(), tag);
     return generateNodeImpl(L, St, Pred, MarkAsSink);
   }
+
+  ExplodedNode *generateNode(const ProgramPoint &PP,
+                             ExplodedNode *Pred,
+                             const ProgramState *State,
+                             bool MarkAsSink = false) {
+    return generateNodeImpl(PP, State, Pred, MarkAsSink);
+  }
+
 };
 
 class StmtNodeBuilder : public NodeBuilder {
@@ -360,8 +385,6 @@
       PurgingDeadSymbols(false), BuildSinks(false), hasGeneratedNode(false),
       PointKind(ProgramPoint::PostStmtKind), Tag(0) {}
 
-  virtual ~StmtNodeBuilder();
-
   ExplodedNode *generateNode(const Stmt *S,
                              const ProgramState *St,
                              ExplodedNode *Pred,

Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h?rev=142831&r1=142830&r2=142831&view=diff
==============================================================================
--- cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h (original)
+++ cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h Mon Oct 24 13:26:19 2011
@@ -120,12 +120,16 @@
 
   StmtNodeBuilder &getBuilder() { assert(Builder); return *Builder; }
   const NodeBuilderContext &getBuilderContext() {
-    assert(Builder);
-    return Builder->getContext();
+    assert(currentBuilderContext);
+    return *currentBuilderContext;
   }
 
   bool isObjCGCEnabled() { return ObjCGCEnabled; }
 
+  const Stmt *getStmt() const;
+
+  void GenerateAutoTransition(ExplodedNode *N);
+
   /// ViewGraph - Visualize the ExplodedGraph created by executing the
   ///  simulation.
   void ViewGraph(bool trim = false);
@@ -141,17 +145,14 @@
 
   /// processCFGElement - Called by CoreEngine. Used to generate new successor
   ///  nodes by processing the 'effects' of a CFG element.
-  void processCFGElement(const CFGElement E, StmtNodeBuilder& Bldr,
-                         ExplodedNode *Pred);
+  void processCFGElement(const CFGElement E, ExplodedNode *Pred,
+                         unsigned StmtIdx, NodeBuilderContext *Ctx);
 
-  void ProcessStmt(const CFGStmt S, StmtNodeBuilder &builder,
-                   ExplodedNode *Pred);
+  void ProcessStmt(const CFGStmt S, ExplodedNode *Pred);
 
-  void ProcessInitializer(const CFGInitializer I, StmtNodeBuilder &Bldr,
-                          ExplodedNode *Pred);
+  void ProcessInitializer(const CFGInitializer I, ExplodedNode *Pred);
 
-  void ProcessImplicitDtor(const CFGImplicitDtor D, StmtNodeBuilder &builder,
-                           ExplodedNode *Pred);
+  void ProcessImplicitDtor(const CFGImplicitDtor D, ExplodedNode *Pred);
 
   void ProcessAutomaticObjDtor(const CFGAutomaticObjDtor D, 
                                StmtNodeBuilder &builder, ExplodedNode *Pred);
@@ -431,8 +432,9 @@
   }
   
 protected:
-  void evalObjCMessage(ExplodedNodeSet &Dst, const ObjCMessage &msg, 
-                       ExplodedNode *Pred, const ProgramState *state);
+  void evalObjCMessage(PureStmtNodeBuilder &Bldr, const ObjCMessage &msg,
+                       ExplodedNode *Pred, const ProgramState *state,
+                       bool GenSink);
 
   const ProgramState *invalidateArguments(const ProgramState *State,
                                           const CallOrObjCMessage &Call,
@@ -444,7 +446,8 @@
   /// evalBind - Handle the semantics of binding a value to a specific location.
   ///  This method is used by evalStore, VisitDeclStmt, and others.
   void evalBind(ExplodedNodeSet &Dst, const Stmt *StoreE, ExplodedNode *Pred,
-                SVal location, SVal Val, bool atDeclInit = false);
+                SVal location, SVal Val, bool atDeclInit = false,
+                ProgramPoint::Kind PP = ProgramPoint::PostStmtKind);
 
 public:
   // FIXME: 'tag' should be removed, and a LocationContext should be used

Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h?rev=142831&r1=142830&r2=142831&view=diff
==============================================================================
--- cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h (original)
+++ cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h Mon Oct 24 13:26:19 2011
@@ -55,8 +55,8 @@
 
   /// Called by CoreEngine. Used to generate new successor
   /// nodes by processing the 'effects' of a block-level statement.
-  virtual void processCFGElement(const CFGElement E, StmtNodeBuilder& builder,
-                                 ExplodedNode* Pred)=0;
+  virtual void processCFGElement(const CFGElement E, ExplodedNode* Pred,
+                                 unsigned StmtIdx, NodeBuilderContext *Ctx)=0;
 
   /// Called by CoreEngine when it starts processing a CFGBlock.  The
   /// SubEngine is expected to populate dstNodes with new nodes representing

Modified: cfe/trunk/lib/StaticAnalyzer/Core/CheckerManager.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/CheckerManager.cpp?rev=142831&r1=142830&r2=142831&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/CheckerManager.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/CheckerManager.cpp Mon Oct 24 13:26:19 2011
@@ -245,6 +245,7 @@
 }
 
 /// \brief Run checkers for load/store of a location.
+
 void CheckerManager::runCheckersForLocation(ExplodedNodeSet &Dst,
                                             const ExplodedNodeSet &Src,
                                             SVal location, bool isLoad,
@@ -261,18 +262,19 @@
     SVal Val;
     const Stmt *S;
     ExprEngine &Eng;
+    ProgramPoint::Kind PointKind;
 
     CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
     CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
 
     CheckBindContext(const CheckersTy &checkers,
-                     SVal loc, SVal val, const Stmt *s, ExprEngine &eng)
-      : Checkers(checkers), Loc(loc), Val(val), S(s), Eng(eng) { }
+                     SVal loc, SVal val, const Stmt *s, ExprEngine &eng,
+                     ProgramPoint::Kind PK)
+      : Checkers(checkers), Loc(loc), Val(val), S(s), Eng(eng), PointKind(PK) {}
 
     void runChecker(CheckerManager::CheckBindFunc checkFn,
                     NodeBuilder &Bldr, ExplodedNode *Pred) {
-      ProgramPoint::Kind K =  ProgramPoint::PreStmtKind;
-      const ProgramPoint &L = ProgramPoint::getProgramPoint(S, K,
+      const ProgramPoint &L = ProgramPoint::getProgramPoint(S, PointKind,
                                 Pred->getLocationContext(), checkFn.Checker);
       CheckerContext C(Bldr, Eng, Pred, L, 0);
 
@@ -285,8 +287,9 @@
 void CheckerManager::runCheckersForBind(ExplodedNodeSet &Dst,
                                         const ExplodedNodeSet &Src,
                                         SVal location, SVal val,
-                                        const Stmt *S, ExprEngine &Eng) {
-  CheckBindContext C(BindCheckers, location, val, S, Eng);
+                                        const Stmt *S, ExprEngine &Eng,
+                                        ProgramPoint::Kind PointKind) {
+  CheckBindContext C(BindCheckers, location, val, S, Eng, PointKind);
   expandGraphWithCheckers(C, Dst, Src);
 }
 

Modified: cfe/trunk/lib/StaticAnalyzer/Core/CoreEngine.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/CoreEngine.cpp?rev=142831&r1=142830&r2=142831&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/CoreEngine.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/CoreEngine.cpp Mon Oct 24 13:26:19 2011
@@ -315,9 +315,7 @@
   // Process the entrance of the block.
   if (CFGElement E = L.getFirstElement()) {
     NodeBuilderContext Ctx(*this, L.getBlock(), Pred);
-    ExplodedNodeSet Dst;
-    StmtNodeBuilder Builder(Pred, Dst, 0, Ctx);
-    SubEng.processCFGElement(E, Builder, Pred);
+    SubEng.processCFGElement(E, Pred, 0, &Ctx);
   }
   else
     HandleBlockExit(L.getBlock(), Pred);
@@ -436,9 +434,7 @@
     HandleBlockExit(B, Pred);
   else {
     NodeBuilderContext Ctx(*this, B, Pred);
-    ExplodedNodeSet Dst;
-    StmtNodeBuilder Builder(Pred, Dst, StmtIdx, Ctx);
-    SubEng.processCFGElement((*B)[StmtIdx], Builder, Pred);
+    SubEng.processCFGElement((*B)[StmtIdx], Pred, StmtIdx, &Ctx);
   }
 }
 
@@ -510,12 +506,6 @@
   return (IsNew ? N : 0);
 }
 
-StmtNodeBuilder::~StmtNodeBuilder() {
-  for (iterator I=Frontier.begin(), E=Frontier.end(); I!=E; ++I)
-    if (!(*I)->isSink())
-      GenerateAutoTransition(*I);
-}
-
 void StmtNodeBuilder::GenerateAutoTransition(ExplodedNode *N) {
   assert (!N->isSink());
 

Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp?rev=142831&r1=142830&r2=142831&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp Mon Oct 24 13:26:19 2011
@@ -197,30 +197,77 @@
   getCheckerManager().runCheckersForEndAnalysis(G, BR, *this);
 }
 
-void ExprEngine::processCFGElement(const CFGElement E, 
-                                  StmtNodeBuilder& Bldr,
-                                  ExplodedNode *Pred) {
+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()), Bldr, Pred);
+      ProcessStmt(const_cast<Stmt*>(E.getAs<CFGStmt>()->getStmt()), Pred);
       return;
     case CFGElement::Initializer:
-      ProcessInitializer(E.getAs<CFGInitializer>()->getInitializer(),
-                         Bldr, Pred);
+      ProcessInitializer(E.getAs<CFGInitializer>()->getInitializer(), Pred);
       return;
     case CFGElement::AutomaticObjectDtor:
     case CFGElement::BaseDtor:
     case CFGElement::MemberDtor:
     case CFGElement::TemporaryDtor:
-      ProcessImplicitDtor(*E.getAs<CFGImplicitDtor>(), Bldr, Pred);
+      ProcessImplicitDtor(*E.getAs<CFGImplicitDtor>(), Pred);
       return;
   }
 }
 
-void ExprEngine::ProcessStmt(const CFGStmt S, StmtNodeBuilder& builder,
+const Stmt *ExprEngine::getStmt() const {
+  const CFGStmt *CS = (*currentBuilderContext->getBlock())[currentStmtIdx].getAs<CFGStmt>();
+  return CS ? CS->getStmt() : 0;
+}
+
+// TODO: Adding nodes to the worklist shoudl be a function inside CoreEngine.
+void ExprEngine::GenerateAutoTransition(ExplodedNode *N) {
+  assert (!N->isSink());
+  const CFGBlock *Block = currentBuilderContext->getBlock();
+  unsigned Idx = currentStmtIdx;
+
+  // Check if this node entered a callee.
+  if (isa<CallEnter>(N->getLocation())) {
+    // Still use the index of the CallExpr. It's needed to create the callee
+    // StackFrameContext.
+    Engine.WList->enqueue(N, Block, Idx);
+    return;
+  }
+
+  // Do not create extra nodes. Move to the next CFG element.
+  if (isa<PostInitializer>(N->getLocation())) {
+    Engine.WList->enqueue(N, Block, Idx+1);
+    return;
+  }
+
+  PostStmt Loc(getStmt(), N->getLocationContext());
+
+  if (Loc == N->getLocation()) {
+    // Note: 'N' should be a fresh node because otherwise it shouldn't be
+    // a member of Deferred.
+    Engine.WList->enqueue(N, Block, Idx+1);
+    return;
+  }
+
+  bool IsNew;
+  ExplodedNode *Succ = Engine.G->getNode(Loc, N->getState(), &IsNew);
+  Succ->addPredecessor(N, *Engine.G);
+
+  if (IsNew)
+    Engine.WList->enqueue(Succ, Block, Idx+1);
+}
+
+
+void ExprEngine::ProcessStmt(const CFGStmt S,
                              ExplodedNode *Pred) {
+  ExplodedNodeSet TopDst;
+  StmtNodeBuilder builder(Pred, TopDst, currentStmtIdx, *currentBuilderContext);
+
   // TODO: Use RAII to remove the unnecessary, tagged nodes.
   //RegisterCreatedNodes registerCreatedNodes(getGraph());
 
@@ -230,9 +277,6 @@
   StateMgr.recycleUnusedStates();
   
   currentStmt = S.getStmt();
-  currentStmtIdx = builder.getIndex();
-  currentBuilderContext = &builder.getContext();
-
   PrettyStackTraceLoc CrashInfo(getContext().getSourceManager(),
                                 currentStmt->getLocStart(),
                                 "Error evaluating statement");
@@ -268,15 +312,15 @@
     // up. Since no symbols are dead, we can optimize and not clean out
     // the constraint manager.
     CleanedNode =
-      Builder->generateNode(currentStmt, CleanedState, EntryNode, &cleanupTag);
+      builder.generateNode(currentStmt, CleanedState, EntryNode, &cleanupTag);
     Tmp.Add(CleanedNode);
 
   } else {
-    SaveAndRestore<bool> OldSink(Builder->BuildSinks);
-    SaveOr OldHasGen(Builder->hasGeneratedNode);
+    SaveAndRestore<bool> OldSink(builder.BuildSinks);
+    SaveOr OldHasGen(builder.hasGeneratedNode);
 
-    SaveAndRestore<bool> OldPurgeDeadSymbols(Builder->PurgingDeadSymbols);
-    Builder->PurgingDeadSymbols = true;
+    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.
@@ -306,18 +350,25 @@
       // generate a transition to that state.
       const ProgramState *CleanedCheckerSt =
         StateMgr.getPersistentStateWithGDM(CleanedState, CheckerState);
-      ExplodedNode *CleanedNode = Builder->generateNode(currentStmt,
+      ExplodedNode *CleanedNode = builder.generateNode(currentStmt,
                                                         CleanedCheckerSt, *I,
                                                         &cleanupTag);
       Tmp.Add(CleanedNode);
     }
   }
 
+  ExplodedNodeSet AllDst;
   for (ExplodedNodeSet::iterator I=Tmp.begin(), E=Tmp.end(); I!=E; ++I) {
-    // TODO: Remove Dest set, it's no longer needed.
     ExplodedNodeSet Dst;
     // Visit the statement.
     Visit(currentStmt, *I, Dst);
+    AllDst.insert(Dst);
+  }
+
+  for (ExplodedNodeSet::iterator I = AllDst.begin(),
+                                 E = AllDst.end(); I != E; ++I) {
+    assert(!(*I)->isSink());
+      GenerateAutoTransition(*I);
   }
 
   // NULL out these variables to cleanup.
@@ -328,8 +379,10 @@
 }
 
 void ExprEngine::ProcessInitializer(const CFGInitializer Init,
-                                    StmtNodeBuilder &builder,
                                     ExplodedNode *pred) {
+  ExplodedNodeSet Dst;
+  StmtNodeBuilder Bldr(pred, Dst, currentStmtIdx, *currentBuilderContext);
+
   // We don't set EntryNode and currentStmt. And we don't clean up state.
   const CXXCtorInitializer *BMI = Init.getInitializer();
   const StackFrameContext *stackFrame = cast<StackFrameContext>(pred->getLocationContext());
@@ -358,7 +411,7 @@
       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);
+      Bldr.generateNode(PP, state, Pred);
     }
     return;
   }
@@ -373,14 +426,20 @@
     getStoreManager().evalDerivedToBase(thisVal, ctorExpr->getType());
   const MemRegion *baseReg = baseVal.getAsRegion();
   assert(baseReg);
-  Builder = &builder;
+  Builder = &Bldr;
   ExplodedNodeSet dst;
   VisitCXXConstructExpr(ctorExpr, baseReg, pred, dst);
+  for (ExplodedNodeSet::iterator I = dst.begin(),
+                                 E = dst.end(); I != E; ++I) {
+      GenerateAutoTransition(*I);
+  }
 }
 
 void ExprEngine::ProcessImplicitDtor(const CFGImplicitDtor D,
-                                       StmtNodeBuilder &builder,
-                                       ExplodedNode *Pred) {
+                                     ExplodedNode *Pred) {
+  ExplodedNodeSet Dst;
+  StmtNodeBuilder builder(Pred, Dst, currentStmtIdx, *currentBuilderContext);
+
   Builder = &builder;
 
   switch (D.getKind()) {
@@ -399,6 +458,11 @@
   default:
     llvm_unreachable("Unexpected dtor kind.");
   }
+
+  for (ExplodedNodeSet::iterator I = Dst.begin(),
+                                 E = Dst.end(); I != E; ++I) {
+      GenerateAutoTransition(*I);
+  }
 }
 
 void ExprEngine::ProcessAutomaticObjDtor(const CFGAutomaticObjDtor dtor,
@@ -440,6 +504,7 @@
   PrettyStackTraceLoc CrashInfo(getContext().getSourceManager(),
                                 S->getLocStart(),
                                 "Error evaluating statement");
+  PureStmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext);
 
   // Expressions to ignore.
   if (const Expr *Ex = dyn_cast<Expr>(S))
@@ -449,10 +514,8 @@
   //  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.
@@ -479,22 +542,17 @@
     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::SEHFinallyStmtClass: {
+      const ExplodedNode *node = Bldr.generateNode(S, Pred, Pred->getState());
+      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.");
@@ -525,31 +583,33 @@
       // 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);
+      Bldr.generateNode(S, Pred, state);
       break;
     }
 
     case Stmt::ObjCAtSynchronizedStmtClass:
+      Bldr.takeNodes(Pred);
       VisitObjCAtSynchronizedStmt(cast<ObjCAtSynchronizedStmt>(S), Pred, Dst);
+      Bldr.addNodes(Dst);
       break;
 
     case Stmt::ObjCPropertyRefExprClass:
       // Implicitly handled by Environment::getSVal().
-      Dst.Add(Pred);
       break;
 
     case Stmt::ImplicitValueInitExprClass: {
       const ProgramState *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, val));
       break;
     }
       
-    case Stmt::ExprWithCleanupsClass: {
+    case Stmt::ExprWithCleanupsClass:
+      Bldr.takeNodes(Pred);
       Visit(cast<ExprWithCleanups>(S)->getSubExpr(), Pred, Dst);
+      Bldr.addNodes(Dst);
       break;
-    }
 
     // Cases not handled yet; but will handle some day.
     case Stmt::DesignatedInitExprClass:
@@ -583,39 +643,52 @@
     case Stmt::FloatingLiteralClass:
     case Stmt::SizeOfPackExprClass:
     case Stmt::CXXNullPtrLiteralExprClass:
-      Dst.Add(Pred); // No-op. Simply propagate the current state unchanged.
+      // No-op. Simply propagate the current state unchanged.
       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: {
+      Bldr.takeNodes(Pred);
       const BlockDeclRefExpr *BE = cast<BlockDeclRefExpr>(S);
       VisitCommonDeclRefExpr(BE, BE->getDecl(), Pred, Dst);
+      Bldr.addNodes(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())));
+        Bldr.generateNode(B, Pred,
+                          state->BindExpr(B, state->getSVal(B->getRHS())));
         break;
       }
 
+      Bldr.takeNodes(Pred);
+      
       if (AMgr.shouldEagerlyAssume() &&
           (B->isRelationalOp() || B->isEqualityOp())) {
         ExplodedNodeSet Tmp;
@@ -625,13 +698,16 @@
       else
         VisitBinaryOperator(cast<BinaryOperator>(S), Pred, Dst);
 
+      Bldr.addNodes(Dst);
       break;
     }
 
     case Stmt::CallExprClass:
     case Stmt::CXXOperatorCallExprClass:
     case Stmt::CXXMemberCallExprClass: {
+      Bldr.takeNodes(Pred);
       VisitCallExpr(cast<CallExpr>(S), Pred, Dst);
+      Bldr.addNodes(Dst);
       break;
     }
 
@@ -640,58 +716,78 @@
       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:
@@ -702,6 +798,7 @@
     case Stmt::CXXConstCastExprClass:
     case Stmt::CXXFunctionalCastExprClass: 
     case Stmt::ObjCBridgedCastExprClass: {
+      Bldr.takeNodes(Pred);
       const CastExpr *C = cast<CastExpr>(S);
       // Handle the previsit checks.
       ExplodedNodeSet dstPrevisit;
@@ -716,58 +813,76 @@
 
       // 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);
       else
         Visit(Materialize->GetTemporaryExpr(), 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:
+      Bldr.takeNodes(Pred);
       VisitObjCMessage(cast<ObjCMessageExpr>(S), 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: {
@@ -777,36 +892,35 @@
         // 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)));
+        Bldr.generateNode(SE, Pred,
+                          state->BindExpr(SE, state->getSVal(LastExpr)));
       }
-      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));
+      Bldr.generateNode(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;
     }
   }
@@ -1189,6 +1303,8 @@
 void ExprEngine::VisitCommonDeclRefExpr(const Expr *Ex, const NamedDecl *D,
                                         ExplodedNode *Pred,
                                         ExplodedNodeSet &Dst) {
+  PureStmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext, Builder);
+
   const ProgramState *state = Pred->getState();
 
   if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
@@ -1204,20 +1320,20 @@
         V = UnknownVal();
     }
 
-    MakeNode(Dst, Ex, Pred, state->BindExpr(Ex, V),
-             ProgramPoint::PostLValueKind);
+    Bldr.generateNode(Ex, Pred, state->BindExpr(Ex, 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, 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, V), false, 0,
+                      ProgramPoint::PostLValueKind);
     return;
   }
   assert (false &&
@@ -1236,13 +1352,16 @@
   ExplodedNodeSet checkerPreStmt;
   getCheckerManager().runCheckersForPreStmt(checkerPreStmt, Pred, A, *this);
 
+  PureStmtNodeBuilder Bldr(checkerPreStmt, Dst, *currentBuilderContext, Builder);
+
   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));
     assert(A->isLValue());
-    MakeNode(Dst, A, *it, state->BindExpr(A, V), ProgramPoint::PostLValueKind);
+    Bldr.generateNode(A, *it, state->BindExpr(A, V),
+                      false, 0, ProgramPoint::PostLValueKind);
   }
 }
 
@@ -1250,10 +1369,13 @@
 void ExprEngine::VisitMemberExpr(const MemberExpr *M, ExplodedNode *Pred,
                                  ExplodedNodeSet &Dst) {
 
+  PureStmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext, Builder);
   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;
   }
   
@@ -1270,7 +1392,7 @@
       // 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, UnknownVal()));
     return;
   }
 
@@ -1281,25 +1403,29 @@
   // 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
+    Bldr.generateNode(M, Pred, state->BindExpr(M, L), false, 0,
+                      ProgramPoint::PostLValueKind);
+  else {
+    Bldr.takeNodes(Pred);
     evalLoad(Dst, M, Pred, state, L);
+    Bldr.addNodes(Dst);
+  }
 }
 
 /// evalBind - Handle the semantics of binding a value to a specific location.
 ///  This method is used by evalStore and (soon) VisitDeclStmt, and others.
 void ExprEngine::evalBind(ExplodedNodeSet &Dst, const Stmt *StoreE,
                           ExplodedNode *Pred,
-                          SVal location, SVal Val, bool atDeclInit) {
+                          SVal location, SVal Val, bool atDeclInit,
+                          ProgramPoint::Kind PointKind) {
 
   // Do a previsit of the bind.
   ExplodedNodeSet CheckedSet;
   getCheckerManager().runCheckersForBind(CheckedSet, Pred, location, Val,
-                                         StoreE, *this);
+                                         StoreE, *this, PointKind);
 
   // TODO:AZ Remove TmpDst after NB refactoring is done.
   ExplodedNodeSet TmpDst;
-  Builder->takeNodes(CheckedSet);
   PureStmtNodeBuilder Bldr(CheckedSet, TmpDst, *currentBuilderContext);
 
   for (ExplodedNodeSet::iterator I = CheckedSet.begin(), E = CheckedSet.end();
@@ -1315,9 +1441,9 @@
       state = state->bindLoc(location, Val);
     }
 
-    Bldr.generateNode(StoreE, *I, state);
+    Bldr.generateNode(StoreE, *I, state, false, 0, PointKind);
   }
-  Builder->addNodes(TmpDst);
+
   Dst.insert(TmpDst);
 }
 
@@ -1357,11 +1483,9 @@
   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,
+             ProgramPoint::PostStoreKind);
 }
 
 void ExprEngine::evalLoad(ExplodedNodeSet &Dst, const Expr *Ex,
@@ -1411,30 +1535,28 @@
   // Evaluate the location (checks for bad dereferences).
   ExplodedNodeSet Tmp;
   evalLocation(Tmp, Ex, Pred, state, location, tag, true);
-
   if (Tmp.empty())
     return;
 
+  PureStmtNodeBuilder Bldr(Tmp, Dst, *currentBuilderContext, Builder);
   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();
 
     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(Ex, *NI, state->BindExpr(Ex, UnknownVal()),
+                        false, tag, ProgramPoint::PostLoadKind);
     }
     else {
       if (LoadTy.isNull())
         LoadTy = Ex->getType();
       SVal V = state->getSVal(cast<Loc>(location), LoadTy);
-      MakeNode(Dst, Ex, *NI, state->bindExprAndLocation(Ex, location, V),
-               ProgramPoint::PostLoadKind, tag);
+      Bldr.generateNode(Ex, *NI, state->bindExprAndLocation(Ex, location, V),
+                        false, tag, ProgramPoint::PostLoadKind);
     }
   }
 }
@@ -1443,16 +1565,16 @@
                                 ExplodedNode *Pred,
                                 const ProgramState *state, SVal location,
                                 const ProgramPointTag *tag, bool isLoad) {
+  PureStmtNodeBuilder BldrTop(Pred, Dst, *currentBuilderContext, Builder);
   // 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);
+  PureStmtNodeBuilder 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;
@@ -1465,11 +1587,12 @@
     // 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(S, Pred, state, false, &etag);
   }
-  getCheckerManager().runCheckersForLocation(Dst, Src, location, isLoad, S,
+  ExplodedNodeSet Tmp;
+  getCheckerManager().runCheckersForLocation(Tmp, Src, location, isLoad, S,
                                              *this);
+  BldrTop.addNodes(Tmp);
 }
 
 bool ExprEngine::InlineCall(ExplodedNodeSet &Dst, const CallExpr *CE, 
@@ -1558,17 +1681,15 @@
 
 void ExprEngine::evalEagerlyAssume(ExplodedNodeSet &Dst, ExplodedNodeSet &Src,
                                      const Expr *Ex) {
-  
+  PureStmtNodeBuilder Bldr(Src, Dst, *currentBuilderContext, Builder);
   
   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;
     }
 
@@ -1582,18 +1703,16 @@
       if (const ProgramState *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));
+        Bldr.generateNode(Ex, Pred, StateTrue, false, tags.first);
       }
 
       // Next, assume that the condition is false.
       if (const ProgramState *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));
+        Bldr.generateNode(Ex, Pred, StateFalse, false, tags.second);
       }
     }
-    else
-      Dst.Add(Pred);
   }
 }
 
@@ -1625,7 +1744,7 @@
                                             ExplodedNode *Pred,
                                             ExplodedNodeSet &Dst) {
   if (I == E) {
-
+    PureStmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext, Builder);
     // We have processed both the inputs and the outputs.  All of the outputs
     // should evaluate to Locs.  Nuke all of their values.
 
@@ -1645,7 +1764,7 @@
         state = state->bindLoc(cast<Loc>(X), UnknownVal());
     }
 
-    MakeNode(Dst, A, Pred, state);
+    Bldr.generateNode(A, Pred, state);
     return;
   }
 

Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineC.cpp?rev=142831&r1=142830&r2=142831&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineC.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineC.cpp Mon Oct 24 13:26:19 2011
@@ -46,7 +46,7 @@
       // FIXME: Handle structs.
       if (RightV.isUnknown() ||
           !getConstraintManager().canReasonAbout(RightV)) {
-        unsigned Count = Builder->getCurrentBlockCount();
+        unsigned Count = currentBuilderContext->getCurrentBlockCount();
         RightV = svalBuilder.getConjuredSymbolVal(NULL, B->getRHS(), Count);
       }
       // Simulate the effects of a "store":  bind the value of the RHS
@@ -57,16 +57,17 @@
     }
       
     if (!B->isAssignmentOp()) {
+      PureStmtNodeBuilder Bldr(*it, Tmp2, *currentBuilderContext, Builder);
       // Process non-assignments except commas or short-circuited
       // logical expressions (LAnd and LOr).
       SVal Result = evalBinOp(state, Op, LeftV, RightV, B->getType());      
       if (Result.isUnknown()) {
-        MakeNode(Tmp2, B, *it, state);
+        Bldr.generateNode(B, *it, state);
         continue;
       }        
 
       state = state->BindExpr(B, Result);      
-      MakeNode(Tmp2, B, *it, state);
+      Bldr.generateNode(B, *it, state);
       continue;
     }
       
@@ -125,7 +126,7 @@
       if (Result.isUnknown() ||
           !getConstraintManager().canReasonAbout(Result)) {
         
-        unsigned Count = Builder->getCurrentBlockCount();
+        unsigned Count = currentBuilderContext->getCurrentBlockCount();
         
         // The symbolic value is actually for the type of the left-hand side
         // expression, not the computation type, as this is the value the
@@ -165,8 +166,9 @@
                                        Pred->getLocationContext());
   
   ExplodedNodeSet Tmp;
-  MakeNode(Tmp, BE, Pred, Pred->getState()->BindExpr(BE, V),
-           ProgramPoint::PostLValueKind);
+  PureStmtNodeBuilder Bldr(Pred, Tmp, *currentBuilderContext);
+  Bldr.generateNode(BE, Pred, Pred->getState()->BindExpr(BE, V), false, 0,
+                    ProgramPoint::PostLValueKind);
   
   // FIXME: Move all post/pre visits to ::Visit().
   getCheckerManager().runCheckersForPostStmt(Dst, Tmp, BE, *this);
@@ -196,6 +198,7 @@
   if (const ExplicitCastExpr *ExCast=dyn_cast_or_null<ExplicitCastExpr>(CastE))
     T = ExCast->getTypeAsWritten();
   
+  PureStmtNodeBuilder Bldr(dstPreStmt, Dst, *currentBuilderContext, Builder);
   for (ExplodedNodeSet::iterator I = dstPreStmt.begin(), E = dstPreStmt.end();
        I != E; ++I) {
     
@@ -207,7 +210,6 @@
       case CK_GetObjCProperty:
         llvm_unreachable("GetObjCProperty casts handled earlier.");
       case CK_ToVoid:
-        Dst.Add(Pred);
         continue;
         // The analyzer doesn't do anything special with these casts,
         // since it understands retain/release semantics already.
@@ -222,7 +224,7 @@
         const ProgramState *state = Pred->getState();
         SVal V = state->getSVal(Ex);
         state = state->BindExpr(CastE, V);
-        MakeNode(Dst, CastE, Pred, state);
+        Bldr.generateNode(CastE, Pred, state);
         continue;
       }
       case CK_Dependent:
@@ -258,7 +260,7 @@
         SVal V = state->getSVal(Ex);
         V = svalBuilder.evalCast(V, T, ExTy);
         state = state->BindExpr(CastE, V);
-        MakeNode(Dst, CastE, Pred, state);
+        Bldr.generateNode(CastE, Pred, state);
         continue;
       }
       case CK_DerivedToBase:
@@ -268,7 +270,7 @@
         SVal val = state->getSVal(Ex);
         val = getStoreManager().evalDerivedToBase(val, T);
         state = state->BindExpr(CastE, val);
-        MakeNode(Dst, CastE, Pred, state);
+        Bldr.generateNode(CastE, Pred, state);
         continue;
       }
         // Various C++ casts that are not handled yet.
@@ -289,10 +291,10 @@
         
         SVal result =
         svalBuilder.getConjuredSymbolVal(NULL, CastE, resultType,
-                                         Builder->getCurrentBlockCount());
+                               currentBuilderContext->getCurrentBlockCount());
         
         const ProgramState *state = Pred->getState()->BindExpr(CastE, result);
-        MakeNode(Dst, CastE, Pred, state);
+        Bldr.generateNode(CastE, Pred, state);
         continue;
       }
     }
@@ -302,8 +304,7 @@
 void ExprEngine::VisitCompoundLiteralExpr(const CompoundLiteralExpr *CL,
                                           ExplodedNode *Pred,
                                           ExplodedNodeSet &Dst) {
-  PureStmtNodeBuilder B(Pred, Dst, *currentBuilderContext);
-  Builder->takeNodes(Pred);
+  PureStmtNodeBuilder B(Pred, Dst, *currentBuilderContext, Builder);
 
   const InitListExpr *ILE 
     = cast<InitListExpr>(CL->getInitializer()->IgnoreParens());
@@ -317,7 +318,6 @@
     B.generateNode(CL, Pred, state->BindExpr(CL, state->getLValue(CL, LC)));
   else
     B.generateNode(CL, Pred, state->BindExpr(CL, ILV));
-  Builder->addNodes(Dst);
 }
 
 void ExprEngine::VisitDeclStmt(const DeclStmt *DS, ExplodedNode *Pred,
@@ -330,15 +330,17 @@
   // Assumption: The CFG has one DeclStmt per Decl.
   const Decl *D = *DS->decl_begin();
   
-  if (!D || !isa<VarDecl>(D))
+  if (!D || !isa<VarDecl>(D)) {
+    //TODO:AZ: remove explicit insertion after refactoring is done.
+    Dst.insert(Pred);
     return;
+  }
   
   // FIXME: all pre/post visits should eventually be handled by ::Visit().
   ExplodedNodeSet dstPreVisit;
   getCheckerManager().runCheckersForPreStmt(dstPreVisit, Pred, DS, *this);
   
-  PureStmtNodeBuilder B(dstPreVisit, Dst, *currentBuilderContext);
-  Builder->takeNodes(dstPreVisit);
+  PureStmtNodeBuilder B(dstPreVisit, Dst, *currentBuilderContext, Builder);
   const VarDecl *VD = dyn_cast<VarDecl>(D);
   for (ExplodedNodeSet::iterator I = dstPreVisit.begin(), E = dstPreVisit.end();
        I!=E; ++I) {
@@ -365,7 +367,7 @@
            !getConstraintManager().canReasonAbout(InitVal)) &&
           !VD->getType()->isReferenceType()) {
         InitVal = svalBuilder.getConjuredSymbolVal(NULL, InitEx,
-                                                   Builder->getCurrentBlockCount());
+                                 currentBuilderContext->getCurrentBlockCount());
       }
       B.takeNodes(N);
       evalBind(Dst, DS, N, state->getLValue(VD, LC), InitVal, true);
@@ -375,17 +377,14 @@
       B.generateNode(DS, N,state->bindDeclWithNoInit(state->getRegion(VD, LC)));
     }
   }
-  Builder->addNodes(Dst);
 }
 
 void ExprEngine::VisitLogicalExpr(const BinaryOperator* B, ExplodedNode *Pred,
                                   ExplodedNodeSet &Dst) {
-  Builder->takeNodes(Pred);
-  PureStmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext);
-
   assert(B->getOpcode() == BO_LAnd ||
          B->getOpcode() == BO_LOr);
-  
+
+  PureStmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext, Builder);
   const ProgramState *state = Pred->getState();
   SVal X = state->getSVal(B);
   assert(X.isUndef());
@@ -399,7 +398,6 @@
     // Handle undefined values.
     if (X.isUndef()) {
       Bldr.generateNode(B, Pred, state->BindExpr(B, X));
-      Builder->addNodes(Dst);
       return;
     }
     
@@ -427,14 +425,12 @@
                                B->getType());
     Bldr.generateNode(B, Pred, state->BindExpr(B, X));
   }
-  Builder->addNodes(Dst);
 }
 
 void ExprEngine::VisitInitListExpr(const InitListExpr *IE,
                                    ExplodedNode *Pred,
                                    ExplodedNodeSet &Dst) {
-  Builder->takeNodes(Pred);
-  PureStmtNodeBuilder B(Pred, Dst, *currentBuilderContext);
+  PureStmtNodeBuilder B(Pred, Dst, *currentBuilderContext, Builder);
 
   const ProgramState *state = Pred->getState();
   QualType T = getContext().getCanonicalType(IE->getType());
@@ -448,7 +444,6 @@
     if (NumInitElements == 0) {
       SVal V = svalBuilder.makeCompoundVal(T, vals);
       B.generateNode(IE, Pred, state->BindExpr(IE, V));
-      Builder->addNodes(Dst);
       return;
     }
     
@@ -459,7 +454,6 @@
     
     B.generateNode(IE, Pred,
                    state->BindExpr(IE, svalBuilder.makeCompoundVal(T, vals)));
-    Builder->addNodes(Dst);
     return;
   }
   
@@ -467,7 +461,6 @@
     assert(IE->getNumInits() == 1);
     const Expr *initEx = IE->getInit(0);
     B.generateNode(IE, Pred, state->BindExpr(IE, state->getSVal(initEx)));
-    Builder->addNodes(Dst);
     return;
   }
   
@@ -479,8 +472,7 @@
                                   const Expr *R,
                                   ExplodedNode *Pred,
                                   ExplodedNodeSet &Dst) {
-  Builder->takeNodes(Pred);
-  PureStmtNodeBuilder B(Pred, Dst, *currentBuilderContext);
+  PureStmtNodeBuilder B(Pred, Dst, *currentBuilderContext, Builder);
   
   const ProgramState *state = Pred->getState();
   SVal X = state->getSVal(Ex);  
@@ -491,14 +483,12 @@
   
   // Make sure that we invalidate the previous binding.
   B.generateNode(Ex, Pred, state->BindExpr(Ex, X, true));
-  Builder->addNodes(Dst);
 }
 
 void ExprEngine::
 VisitOffsetOfExpr(const OffsetOfExpr *OOE, 
                   ExplodedNode *Pred, ExplodedNodeSet &Dst) {
-  Builder->takeNodes(Pred);
-  PureStmtNodeBuilder B(Pred, Dst, *currentBuilderContext);
+  PureStmtNodeBuilder B(Pred, Dst, *currentBuilderContext, Builder);
   Expr::EvalResult Res;
   if (OOE->Evaluate(Res, getContext()) && Res.Val.isInt()) {
     const APSInt &IV = Res.Val.getInt();
@@ -509,7 +499,6 @@
     B.generateNode(OOE, Pred, Pred->getState()->BindExpr(OOE, X));
   }
   // FIXME: Handle the case where __builtin_offsetof is not a constant.
-  Builder->addNodes(Dst);
 }
 
 
@@ -517,6 +506,7 @@
 VisitUnaryExprOrTypeTraitExpr(const UnaryExprOrTypeTraitExpr *Ex,
                               ExplodedNode *Pred,
                               ExplodedNodeSet &Dst) {
+  PureStmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext, Builder);
 
   QualType T = Ex->getTypeOfArgument();
   
@@ -526,14 +516,12 @@
       
       // FIXME: Add support for VLA type arguments and VLA expressions.
       // When that happens, we should probably refactor VLASizeChecker's code.
-      Dst.Add(Pred);
       return;
     }
     else if (T->getAs<ObjCObjectType>()) {
       // Some code tries to take the sizeof an ObjCObjectType, relying that
       // the compiler has laid out its representation.  Just report Unknown
       // for these.
-      Dst.Add(Pred);
       return;
     }
   }
@@ -545,20 +533,22 @@
   const ProgramState *state = Pred->getState();
   state = state->BindExpr(Ex, svalBuilder.makeIntVal(amt.getQuantity(),
                                                      Ex->getType()));
-  MakeNode(Dst, Ex, Pred, state);
+  Bldr.generateNode(Ex, Pred, state);
 }
 
 void ExprEngine::VisitUnaryOperator(const UnaryOperator* U, 
                                     ExplodedNode *Pred,
                                     ExplodedNodeSet &Dst) {
-  Builder->takeNodes(Pred);
   PureStmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext);
   bool IncDec = false;
   switch (U->getOpcode()) {
-    default:
-      Builder->addNodes(Pred);
+    default: {
+      Bldr.takeNodes(Pred);
       IncDec = true;
-      VisitIncrementDecrementOperator(U, Pred, Dst);
+      ExplodedNodeSet Tmp;
+      VisitIncrementDecrementOperator(U, Pred, Tmp);
+      Bldr.addNodes(Tmp);
+    }
       break;
     case UO_Real: {
       const Expr *Ex = U->getSubExpr()->IgnoreParens();
@@ -690,8 +680,6 @@
     }
   }
 
-  if (!IncDec)
-    Builder->addNodes(Dst);
 }
 
 void ExprEngine::VisitIncrementDecrementOperator(const UnaryOperator* U,
@@ -712,6 +700,8 @@
     ExplodedNodeSet Tmp2;
     evalLoad(Tmp2, Ex, *I, state, loc);
     
+    ExplodedNodeSet Dst2;
+    PureStmtNodeBuilder Bldr(Tmp2, Dst2, *currentBuilderContext, Builder);
     for (ExplodedNodeSet::iterator I2=Tmp2.begin(), E2=Tmp2.end();I2!=E2;++I2) {
       
       state = (*I2)->getState();
@@ -719,7 +709,7 @@
       
       // Propagate unknown and undefined values.
       if (V2_untested.isUnknownOrUndef()) {
-        MakeNode(Dst, U, *I2, state->BindExpr(U, V2_untested));
+        Bldr.generateNode(U, *I2, state->BindExpr(U, V2_untested));
         continue;
       }
       DefinedSVal V2 = cast<DefinedSVal>(V2_untested);
@@ -744,7 +734,7 @@
       if (Result.isUnknown() || !getConstraintManager().canReasonAbout(Result)){
         DefinedOrUnknownSVal SymVal =
         svalBuilder.getConjuredSymbolVal(NULL, Ex,
-                                         Builder->getCurrentBlockCount());
+                                 currentBuilderContext->getCurrentBlockCount());
         Result = SymVal;
         
         // If the value is a location, ++/-- should always preserve
@@ -775,7 +765,11 @@
         state = state->BindExpr(U, U->isPostfix() ? V2 : Result);
       
       // Perform the store.
-      evalStore(Dst, NULL, U, *I2, state, loc, Result);
+      Bldr.takeNodes(*I2);
+      ExplodedNodeSet Dst4;
+      evalStore(Dst4, NULL, U, *I2, state, loc, Result);
+      Bldr.addNodes(Dst4);
     }
+    Dst.insert(Dst2);
   }
 }

Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp?rev=142831&r1=142830&r2=142831&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp Mon Oct 24 13:26:19 2011
@@ -107,6 +107,7 @@
 void ExprEngine::CreateCXXTemporaryObject(const MaterializeTemporaryExpr *ME,
                                           ExplodedNode *Pred,
                                           ExplodedNodeSet &Dst) {
+  PureStmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext, Builder);
   const Expr *tempExpr = ME->GetTemporaryExpr()->IgnoreParens();
   const ProgramState *state = Pred->getState();
 
@@ -119,7 +120,7 @@
                                                  Pred->getLocationContext());
 
   state = state->bindLoc(loc::MemRegionVal(R), V);
-  MakeNode(Dst, ME, Pred, state->BindExpr(ME, loc::MemRegionVal(R)));
+  Bldr.generateNode(ME, Pred, state->BindExpr(ME, loc::MemRegionVal(R)));
 }
 
 void ExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *E, 
@@ -174,7 +175,8 @@
     // parameter region.
     const StackFrameContext *SFC = 
       AMgr.getStackFrame(CD, Pred->getLocationContext(),
-                         E, Builder->getBlock(), Builder->getIndex());
+                         E, currentBuilderContext->getBlock(),
+                         currentStmtIdx);
 
     // Create the 'this' region.
     const CXXThisRegion *ThisR =
@@ -182,43 +184,45 @@
 
     CallEnter Loc(E, SFC, Pred->getLocationContext());
 
-
+    PureStmtNodeBuilder Bldr(argsEvaluated, destNodes, *currentBuilderContext);
     for (ExplodedNodeSet::iterator NI = argsEvaluated.begin(),
                                   NE = argsEvaluated.end(); NI != NE; ++NI) {
       const ProgramState *state = (*NI)->getState();
       // Setup 'this' region, so that the ctor is evaluated on the object pointed
       // by 'Dest'.
       state = state->bindLoc(loc::MemRegionVal(ThisR), loc::MemRegionVal(Dest));
-      if (ExplodedNode *N = Builder->generateNode(Loc, state, *NI))
-        destNodes.Add(N);
+      Bldr.generateNode(Loc, *NI, state);
     }
   }
 #endif
   
   // Default semantics: invalidate all regions passed as arguments.
   ExplodedNodeSet destCall;
-
-  for (ExplodedNodeSet::iterator
-        i = destPreVisit.begin(), e = destPreVisit.end();
-       i != e; ++i)
   {
-    ExplodedNode *Pred = *i;
-    const LocationContext *LC = Pred->getLocationContext();
-    const ProgramState *state = Pred->getState();
+    PureStmtNodeBuilder Bldr(destPreVisit, destCall,
+                             *currentBuilderContext, Builder);
+    for (ExplodedNodeSet::iterator
+        i = destPreVisit.begin(), e = destPreVisit.end();
+        i != e; ++i)
+    {
+      ExplodedNode *Pred = *i;
+      const LocationContext *LC = Pred->getLocationContext();
+      const ProgramState *state = Pred->getState();
 
-    state = invalidateArguments(state, CallOrObjCMessage(E, state), LC);
-    Builder->MakeNode(destCall, E, Pred, state);
+      state = invalidateArguments(state, CallOrObjCMessage(E, state), LC);
+      Bldr.generateNode(E, Pred, state);
+    }
   }
-  
   // Do the post visit.
   getCheckerManager().runCheckersForPostStmt(destNodes, destCall, E, *this);  
 }
 
 void ExprEngine::VisitCXXDestructor(const CXXDestructorDecl *DD,
-                                    const MemRegion *Dest,
-                                    const Stmt *S,
-                                    ExplodedNode *Pred, 
-                                    ExplodedNodeSet &Dst) {
+                                      const MemRegion *Dest,
+                                      const Stmt *S,
+                                      ExplodedNode *Pred, 
+                                      ExplodedNodeSet &Dst) {
+  PureStmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext, Builder);
   if (!(DD->doesThisDeclarationHaveABody() && AMgr.shouldInlineCall()))
     return;
 
@@ -226,7 +230,7 @@
   const StackFrameContext *SFC =
     AnalysisDeclContexts.getContext(DD)->
       getStackFrame(Pred->getLocationContext(), S,
-                    Builder->getBlock(), Builder->getIndex());
+      currentBuilderContext->getBlock(), currentStmtIdx);
 
   const CXXThisRegion *ThisR = getCXXThisRegion(DD->getParent(), SFC);
 
@@ -234,15 +238,14 @@
 
   const ProgramState *state = Pred->getState();
   state = state->bindLoc(loc::MemRegionVal(ThisR), loc::MemRegionVal(Dest));
-  ExplodedNode *N = Builder->generateNode(PP, state, Pred);
-  if (N)
-    Dst.Add(N);
+  Bldr.generateNode(PP, Pred, state);
 }
 
 void ExprEngine::VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred,
                                    ExplodedNodeSet &Dst) {
+  PureStmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext, Builder);
   
-  unsigned blockCount = Builder->getCurrentBlockCount();
+  unsigned blockCount = currentBuilderContext->getCurrentBlockCount();
   DefinedOrUnknownSVal symVal =
     svalBuilder.getConjuredSymbolVal(NULL, CNE, CNE->getType(), blockCount);
   const MemRegion *NewReg = cast<loc::MemRegionVal>(symVal).getRegion();  
@@ -255,7 +258,7 @@
     // For now, just return a symbolicated region.
     const ProgramState *state = Pred->getState();
     state = state->BindExpr(CNE, loc::MemRegionVal(EleReg));
-    MakeNode(Dst, CNE, Pred, state);
+    Bldr.generateNode(CNE, Pred, state);
     return;
   }
 
@@ -265,8 +268,10 @@
   if (CD)
     FnType = CD->getType()->getAs<FunctionProtoType>();
   ExplodedNodeSet argsEvaluated;
+  Bldr.takeNodes(Pred);
   evalArguments(CNE->constructor_arg_begin(), CNE->constructor_arg_end(),
                 FnType, Pred, argsEvaluated);
+  Bldr.addNodes(argsEvaluated);
 
   // Initialize the object region and bind the 'new' expression.
   for (ExplodedNodeSet::iterator I = argsEvaluated.begin(), 
@@ -310,24 +315,27 @@
       }
     }
     state = state->BindExpr(CNE, loc::MemRegionVal(EleReg));
-    MakeNode(Dst, CNE, *I, state);
+    Bldr.generateNode(CNE, *I, state);
   }
 }
 
 void ExprEngine::VisitCXXDeleteExpr(const CXXDeleteExpr *CDE, 
-                                      ExplodedNode *Pred,ExplodedNodeSet &Dst) {
+                                    ExplodedNode *Pred, ExplodedNodeSet &Dst) {
   // Should do more checking.
   ExplodedNodeSet Argevaluated;
   Visit(CDE->getArgument(), Pred, Argevaluated);
+  PureStmtNodeBuilder Bldr(Argevaluated, Dst, *currentBuilderContext, Builder);
   for (ExplodedNodeSet::iterator I = Argevaluated.begin(), 
                                  E = Argevaluated.end(); I != E; ++I) {
     const ProgramState *state = (*I)->getState();
-    MakeNode(Dst, CDE, *I, state);
+    Bldr.generateNode(CDE, *I, state);
   }
 }
 
 void ExprEngine::VisitCXXThisExpr(const CXXThisExpr *TE, ExplodedNode *Pred,
                                     ExplodedNodeSet &Dst) {
+  PureStmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext, Builder);
+
   // Get the this object region from StoreManager.
   const MemRegion *R =
     svalBuilder.getRegionManager().getCXXThisRegion(
@@ -336,5 +344,5 @@
 
   const ProgramState *state = Pred->getState();
   SVal V = state->getSVal(loc::MemRegionVal(R));
-  MakeNode(Dst, TE, Pred, state->BindExpr(TE, V));
+  Bldr.generateNode(TE, Pred, state->BindExpr(TE, V));
 }

Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp?rev=142831&r1=142830&r2=142831&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp Mon Oct 24 13:26:19 2011
@@ -147,7 +147,7 @@
   //  expression (the context) and the expression itself.  This should
   //  disambiguate conjured symbols.
   assert(Builder && "Invalidating arguments outside of a statement context");
-  unsigned Count = Builder->getCurrentBlockCount();
+  unsigned Count = currentBuilderContext->getCurrentBlockCount();
   StoreManager::InvalidatedSymbols IS;
 
   // NOTE: Even if RegionsToInvalidate is empty, we may still invalidate
@@ -180,8 +180,7 @@
       }
 
       // First handle the return value.
-      StmtNodeBuilder &Builder = Eng.getBuilder();
-      assert(&Builder && "StmtNodeBuilder must be defined.");
+      PureStmtNodeBuilder Bldr(Pred, Dst, *Eng.currentBuilderContext, Eng.Builder);
 
       // Get the callee.
       const Expr *Callee = CE->getCallee()->IgnoreParens();
@@ -200,7 +199,7 @@
 
       // Conjure a symbol value to use as the result.
       SValBuilder &SVB = Eng.getSValBuilder();
-      unsigned Count = Builder.getCurrentBlockCount();
+      unsigned Count = Eng.currentBuilderContext->getCurrentBlockCount();
       SVal RetVal = SVB.getConjuredSymbolVal(0, CE, ResultTy, Count);
 
       // Generate a new state with the return value set.
@@ -211,7 +210,7 @@
       state = Eng.invalidateArguments(state, CallOrObjCMessage(CE, state), LC);
 
       // And make the result node.
-      Eng.MakeNode(Dst, CE, Pred, state);
+      Bldr.generateNode(CE, Pred, state);
     }
   };
   
@@ -232,21 +231,25 @@
 void ExprEngine::VisitReturnStmt(const ReturnStmt *RS, ExplodedNode *Pred,
                                  ExplodedNodeSet &Dst) {
   ExplodedNodeSet Src;
-  if (const Expr *RetE = RS->getRetValue()) {
-    // Record the returned expression in the state. It will be used in
-    // processCallExit to bind the return value to the call expr.
-    {
-      static SimpleProgramPointTag tag("ExprEngine: ReturnStmt");
-      const ProgramState *state = Pred->getState();
-      state = state->set<ReturnExpr>(RetE);
-      Pred = Builder->generateNode(RetE, state, Pred, &tag);
+  {
+    PureStmtNodeBuilder Bldr(Pred, Src, *currentBuilderContext, Builder);
+    if (const Expr *RetE = RS->getRetValue()) {
+      // Record the returned expression in the state. It will be used in
+      // processCallExit to bind the return value to the call expr.
+      {
+        static SimpleProgramPointTag tag("ExprEngine: ReturnStmt");
+        const ProgramState *state = Pred->getState();
+        state = state->set<ReturnExpr>(RetE);
+        Pred = Bldr.generateNode(RetE, Pred, state, false, &tag);
+      }
+      // We may get a NULL Pred because we generated a cached node.
+      if (Pred) {
+        Bldr.takeNodes(Pred);
+        ExplodedNodeSet Tmp;
+        Visit(RetE, Pred, Tmp);
+        Bldr.addNodes(Tmp);
+      }
     }
-    // We may get a NULL Pred because we generated a cached node.
-    if (Pred)
-      Visit(RetE, Pred, Src);
-  }
-  else {
-    Src.Add(Pred);
   }
   
   getCheckerManager().runCheckersForPreStmt(Dst, Src, RS, *this);

Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp?rev=142831&r1=142830&r2=142831&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp Mon Oct 24 13:26:19 2011
@@ -14,7 +14,6 @@
 #include "clang/StaticAnalyzer/Core/CheckerManager.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.h"
-#include "clang/Analysis/Support/SaveAndRestore.h"
 
 using namespace clang;
 using namespace ento;
@@ -22,13 +21,13 @@
 void ExprEngine::VisitLvalObjCIvarRefExpr(const ObjCIvarRefExpr *Ex, 
                                           ExplodedNode *Pred,
                                           ExplodedNodeSet &Dst) {
-  
   const ProgramState *state = Pred->getState();
   SVal baseVal = state->getSVal(Ex->getBase());
   SVal location = state->getLValue(Ex->getDecl(), baseVal);
   
   ExplodedNodeSet dstIvar;
-  MakeNode(dstIvar, Ex, Pred, state->BindExpr(Ex, location));
+  PureStmtNodeBuilder Bldr(Pred, dstIvar, *currentBuilderContext);
+  Bldr.generateNode(Ex, Pred, state->BindExpr(Ex, location));
   
   // Perform the post-condition check of the ObjCIvarRefExpr and store
   // the created nodes in 'Dst'.
@@ -69,10 +68,11 @@
   //  For now: simulate (1) by assigning either a symbol or nil if the
   //    container is empty.  Thus this transfer function will by default
   //    result in state splitting.
-  
+
   const Stmt *elem = S->getElement();
   const ProgramState *state = Pred->getState();
   SVal elementV;
+  PureStmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext);
   
   if (const DeclStmt *DS = dyn_cast<DeclStmt>(elem)) {
     const VarDecl *elemD = cast<VarDecl>(DS->getSingleDecl());
@@ -84,10 +84,9 @@
   }
   
   ExplodedNodeSet dstLocation;
+  Bldr.takeNodes(Pred);
   evalLocation(dstLocation, elem, Pred, state, elementV, NULL, false);
-  
-  if (dstLocation.empty())
-    return;
+  Bldr.addNodes(dstLocation);
   
   for (ExplodedNodeSet::iterator NI = dstLocation.begin(),
        NE = dstLocation.end(); NI!=NE; ++NI) {
@@ -110,7 +109,7 @@
         //  For now, just 'conjure' up a symbolic value.
         QualType T = R->getValueType();
         assert(Loc::isLocType(T));
-        unsigned Count = Builder->getCurrentBlockCount();
+        unsigned Count = currentBuilderContext->getCurrentBlockCount();
         SymbolRef Sym = SymMgr.getConjuredSymbol(elem, T, Count);
         SVal V = svalBuilder.makeLoc(Sym);
         hasElems = hasElems->bindLoc(elementV, V);
@@ -121,8 +120,8 @@
       }
     
     // Create the new nodes.
-    MakeNode(Dst, S, Pred, hasElems);
-    MakeNode(Dst, S, Pred, noElems);
+    Bldr.generateNode(S, Pred, hasElems);
+    Bldr.generateNode(S, Pred, noElems);
   }
 }
 
@@ -137,14 +136,13 @@
   
   // Proceed with evaluate the message expression.
   ExplodedNodeSet dstEval;
-  
+  PureStmtNodeBuilder Bldr(dstPrevisit, dstEval, *currentBuilderContext);
+
   for (ExplodedNodeSet::iterator DI = dstPrevisit.begin(),
        DE = dstPrevisit.end(); DI != DE; ++DI) {
     
     ExplodedNode *Pred = *DI;
     bool RaisesException = false;
-    SaveAndRestore<bool> OldSink(Builder->BuildSinks);
-    SaveOr OldHasGen(Builder->hasGeneratedNode);
     
     if (const Expr *Receiver = msg.getInstanceReceiver()) {
       const ProgramState *state = Pred->getState();
@@ -159,7 +157,6 @@
         // There are three cases: can be nil or non-nil, must be nil, must be
         // non-nil. We ignore must be nil, and merge the rest two into non-nil.
         if (nilState && !notNilState) {
-          dstEval.insert(Pred);
           continue;
         }
         
@@ -168,13 +165,10 @@
         if (msg.getSelector() == RaiseSel)
           RaisesException = true;
         
-        // Check if we raise an exception.  For now treat these as sinks.
+        // If we raise an exception, for now treat it as a sink.
         // Eventually we will want to handle exceptions properly.
-        if (RaisesException)
-          Builder->BuildSinks = true;
-        
         // Dispatch to plug-in transfer function.
-        evalObjCMessage(dstEval, msg, Pred, notNilState);
+        evalObjCMessage(Bldr, msg, Pred, notNilState, RaisesException);
       }
     }
     else if (const ObjCInterfaceDecl *Iface = msg.getReceiverInterface()) {
@@ -217,16 +211,11 @@
           }
       }
       
-      // Check if we raise an exception.  For now treat these as sinks.
+      // If we raise an exception, for now treat it as a sink.
       // Eventually we will want to handle exceptions properly.
-      if (RaisesException)
-        Builder->BuildSinks = true;
-      
       // Dispatch to plug-in transfer function.
-      evalObjCMessage(dstEval, msg, Pred, Pred->getState());
+      evalObjCMessage(Bldr, msg, Pred, Pred->getState(), RaisesException);
     }
-
-    assert(Builder->BuildSinks || Builder->hasGeneratedNodes());
   }
   
   // Finally, perform the post-condition check of the ObjCMessageExpr and store
@@ -234,11 +223,11 @@
   getCheckerManager().runCheckersForPostObjCMessage(Dst, dstEval, msg, *this);
 }
 
-void ExprEngine::evalObjCMessage(ExplodedNodeSet &Dst, const ObjCMessage &msg, 
+void ExprEngine::evalObjCMessage(PureStmtNodeBuilder &Bldr,
+                                 const ObjCMessage &msg,
                                  ExplodedNode *Pred,
-                                 const ProgramState *state) {
-  assert (Builder && "StmtNodeBuilder must be defined.");
-
+                                 const ProgramState *state,
+                                 bool GenSink) {
   // First handle the return value.
   SVal ReturnValue = UnknownVal();
 
@@ -261,7 +250,7 @@
   if (ReturnValue.isUnknown()) {
     SValBuilder &SVB = getSValBuilder();
     QualType ResultTy = msg.getResultType(getContext());
-    unsigned Count = Builder->getCurrentBlockCount();
+    unsigned Count = currentBuilderContext->getCurrentBlockCount();
     const Expr *CurrentE = cast<Expr>(currentStmt);
     ReturnValue = SVB.getConjuredSymbolVal(NULL, CurrentE, ResultTy, Count);
   }
@@ -274,6 +263,7 @@
   state = invalidateArguments(state, CallOrObjCMessage(msg, state), LC);
 
   // And create the new node.
-  MakeNode(Dst, msg.getOriginExpr(), Pred, state);
+  Bldr.generateNode(msg.getOriginExpr(), Pred, state, GenSink);
+  assert(Bldr.hasGeneratedNodes());
 }
 





More information about the cfe-commits mailing list