[analyzer] Run remove dead bindings right before leaving a function.

This is needed to ensure that we always report issues in the correct
function. For example, leaks are identified when we call remove dead
bindings. In order to make sure we report a callee's leak in the callee,
we have to run the operation in the callee's context.

This change required quite a bit of infrastructure work since:
 - We used to only run remove dead bindings before a given statement;
here we need to run it after the last statement in the function. For
this, we added additional Program Point and special mode in the
SymbolReaper to remove all symbols in context lower than the current
one.
 - The call exit operation turned into a sequence of nodes, which are
now guarded by CallExitBegin and CallExitEnd nodes for clarity and
convenience.

(Sorry for the long diff.)

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@155244 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/StaticAnalyzer/Core/BugReporter.cpp b/lib/StaticAnalyzer/Core/BugReporter.cpp
index a264212..4330d2e 100644
--- a/lib/StaticAnalyzer/Core/BugReporter.cpp
+++ b/lib/StaticAnalyzer/Core/BugReporter.cpp
@@ -427,7 +427,7 @@
 
     ProgramPoint P = N->getLocation();
     
-    if (const CallExit *CE = dyn_cast<CallExit>(&P)) {
+    if (const CallExitEnd *CE = dyn_cast<CallExitEnd>(&P)) {
       PathDiagnosticCallPiece *C =
         PathDiagnosticCallPiece::construct(N, *CE, SMgr);
       PD.getActivePath().push_front(C);
@@ -440,7 +440,7 @@
       PD.popActivePath();
       // The current active path should never be empty.  Either we
       // just added a bunch of stuff to the top-level path, or
-      // we have a previous CallExit.  If the front of the active
+      // we have a previous CallExitEnd.  If the front of the active
       // path is not a PathDiagnosticCallPiece, it means that the
       // path terminated within a function call.  We must then take the
       // current contents of the active path and place it within
@@ -1066,10 +1066,10 @@
     ProgramPoint P = N->getLocation();
 
     do {
-      if (const CallExit *CE = dyn_cast<CallExit>(&P)) {
+      if (const CallExitEnd *CE = dyn_cast<CallExitEnd>(&P)) {
         const StackFrameContext *LCtx =
         CE->getLocationContext()->getCurrentStackFrame();
-        PathDiagnosticLocation Loc(LCtx->getCallSite(),
+        PathDiagnosticLocation Loc(CE->getStmt(),
                                    PDB.getSourceManager(),
                                    LCtx);
         EB.addEdge(Loc, true);
@@ -1099,7 +1099,7 @@
 
         // The current active path should never be empty.  Either we
         // just added a bunch of stuff to the top-level path, or
-        // we have a previous CallExit.  If the front of the active
+        // we have a previous CallExitEnd.  If the front of the active
         // path is not a PathDiagnosticCallPiece, it means that the
         // path terminated within a function call.  We must then take the
         // current contents of the active path and place it within
diff --git a/lib/StaticAnalyzer/Core/CheckerManager.cpp b/lib/StaticAnalyzer/Core/CheckerManager.cpp
index 0bcc343..8a6ea1d 100644
--- a/lib/StaticAnalyzer/Core/CheckerManager.cpp
+++ b/lib/StaticAnalyzer/Core/CheckerManager.cpp
@@ -381,21 +381,25 @@
     SymbolReaper &SR;
     const Stmt *S;
     ExprEngine &Eng;
+    ProgramPoint::Kind ProgarmPointKind;
 
     CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
     CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
 
     CheckDeadSymbolsContext(const CheckersTy &checkers, SymbolReaper &sr,
-                            const Stmt *s, ExprEngine &eng)
-      : Checkers(checkers), SR(sr), S(s), Eng(eng) { }
+                            const Stmt *s, ExprEngine &eng,
+                            ProgramPoint::Kind K)
+      : Checkers(checkers), SR(sr), S(s), Eng(eng), ProgarmPointKind(K) { }
 
     void runChecker(CheckerManager::CheckDeadSymbolsFunc checkFn,
                     NodeBuilder &Bldr, ExplodedNode *Pred) {
-      ProgramPoint::Kind K = ProgramPoint::PostPurgeDeadSymbolsKind;
-      const ProgramPoint &L = ProgramPoint::getProgramPoint(S, K,
+      const ProgramPoint &L = ProgramPoint::getProgramPoint(S, ProgarmPointKind,
                                 Pred->getLocationContext(), checkFn.Checker);
       CheckerContext C(Bldr, Eng, Pred, L);
 
+      // Note, do not pass the statement to the checkers without letting them
+      // differentiate if we ran remove dead bindings before or after the
+      // statement.
       checkFn(SR, C);
     }
   };
@@ -406,8 +410,9 @@
                                                const ExplodedNodeSet &Src,
                                                SymbolReaper &SymReaper,
                                                const Stmt *S,
-                                               ExprEngine &Eng) {
-  CheckDeadSymbolsContext C(DeadSymbolsCheckers, SymReaper, S, Eng);
+                                               ExprEngine &Eng,
+                                               ProgramPoint::Kind K) {
+  CheckDeadSymbolsContext C(DeadSymbolsCheckers, SymReaper, S, Eng, K);
   expandGraphWithCheckers(C, Dst, Src);
 }
 
diff --git a/lib/StaticAnalyzer/Core/CoreEngine.cpp b/lib/StaticAnalyzer/Core/CoreEngine.cpp
index ca662c7..c9de20e 100644
--- a/lib/StaticAnalyzer/Core/CoreEngine.cpp
+++ b/lib/StaticAnalyzer/Core/CoreEngine.cpp
@@ -248,7 +248,7 @@
       break;
     }
 
-    case ProgramPoint::CallExitKind:
+    case ProgramPoint::CallExitBeginKind:
       SubEng.processCallExit(Pred);
       break;
 
@@ -531,14 +531,14 @@
     WList->enqueue(Succ, Block, Idx+1);
 }
 
-ExplodedNode *CoreEngine::generateCallExitNode(ExplodedNode *N) {
-  // Create a CallExit node and enqueue it.
+ExplodedNode *CoreEngine::generateCallExitBeginNode(ExplodedNode *N) {
+  // Create a CallExitBegin node and enqueue it.
   const StackFrameContext *LocCtx
                          = cast<StackFrameContext>(N->getLocationContext());
   const Stmt *CE = LocCtx->getCallSite();
 
   // Use the the callee location context.
-  CallExit Loc(CE, LocCtx);
+  CallExitBegin Loc(CE, LocCtx);
 
   bool isNew;
   ExplodedNode *Node = G->getNode(Loc, N->getState(), false, &isNew);
@@ -565,12 +565,13 @@
 void CoreEngine::enqueueEndOfFunction(ExplodedNodeSet &Set) {
   for (ExplodedNodeSet::iterator I = Set.begin(), E = Set.end(); I != E; ++I) {
     ExplodedNode *N = *I;
-    // If we are in an inlined call, generate CallExit node.
+    // If we are in an inlined call, generate CallExitBegin node.
     if (N->getLocationContext()->getParent()) {
-      N = generateCallExitNode(N);
+      N = generateCallExitBeginNode(N);
       if (N)
         WList->enqueue(N);
     } else {
+      // TODO: We should run remove dead bindings here.
       G->addEndOfPath(N);
       NumPathsExplored++;
     }
diff --git a/lib/StaticAnalyzer/Core/ExplodedGraph.cpp b/lib/StaticAnalyzer/Core/ExplodedGraph.cpp
index 0dcbe1f..e433c35 100644
--- a/lib/StaticAnalyzer/Core/ExplodedGraph.cpp
+++ b/lib/StaticAnalyzer/Core/ExplodedGraph.cpp
@@ -57,7 +57,7 @@
 //===----------------------------------------------------------------------===//
 
 bool ExplodedGraph::shouldCollect(const ExplodedNode *node) {
-  // Reclaimn all nodes that match *all* the following criteria:
+  // Reclaim all nodes that match *all* the following criteria:
   //
   // (1) 1 predecessor (that has one successor)
   // (2) 1 successor (that has one predecessor)
@@ -83,7 +83,8 @@
   // Condition 3.
   ProgramPoint progPoint = node->getLocation();
   if (!isa<PostStmt>(progPoint) ||
-      (isa<CallEnter>(progPoint) || isa<CallExit>(progPoint)))
+      (isa<CallEnter>(progPoint) ||
+       isa<CallExitBegin>(progPoint) || isa<CallExitEnd>(progPoint)))
     return false;
 
   // Condition 4.
diff --git a/lib/StaticAnalyzer/Core/ExprEngine.cpp b/lib/StaticAnalyzer/Core/ExprEngine.cpp
index abc6316..1fd4dcf 100644
--- a/lib/StaticAnalyzer/Core/ExprEngine.cpp
+++ b/lib/StaticAnalyzer/Core/ExprEngine.cpp
@@ -42,8 +42,6 @@
 
 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");
@@ -231,6 +229,7 @@
       ProcessImplicitDtor(*E.getAs<CFGImplicitDtor>(), Pred);
       return;
   }
+  currentBuilderContext = 0;
 }
 
 static bool shouldRemoveDeadBindings(AnalysisManager &AMgr,
@@ -260,62 +259,47 @@
   return !PM.isConsumedExpr(cast<Expr>(S.getStmt()));
 }
 
-void ExprEngine::ProcessStmt(const CFGStmt S,
-                             ExplodedNode *Pred) {
-  // Reclaim any unnecessary nodes in the ExplodedGraph.
-  G.reclaimRecentlyAllocatedNodes();
-  
-  currentStmt = S.getStmt();
-  PrettyStackTraceLoc CrashInfo(getContext().getSourceManager(),
-                                currentStmt->getLocStart(),
-                                "Error evaluating statement");
+void ExprEngine::removeDead(ExplodedNode *Pred, ExplodedNodeSet &Out,
+                            const Stmt *ReferenceStmt,
+                            const LocationContext *LC,
+                            const Stmt *DiagnosticStmt,
+                            ProgramPoint::Kind K) {
+  assert((K == ProgramPoint::PreStmtPurgeDeadSymbolsKind ||
+          ReferenceStmt == 0) && "PreStmt is not generally supported by "
+                                 "the SymbolReaper yet");
+  NumRemoveDeadBindings++;
+  CleanedState = Pred->getState();
+  SymbolReaper SymReaper(LC, ReferenceStmt, SymMgr, getStoreManager());
 
-  EntryNode = Pred;
+  getCheckerManager().runCheckersForLiveSymbols(CleanedState, SymReaper);
 
-  ProgramStateRef EntryState = EntryNode->getState();
-  CleanedState = EntryState;
-
-  // Create the cleaned state.
-  const LocationContext *LC = EntryNode->getLocationContext();
-  SymbolReaper SymReaper(LC, currentStmt, SymMgr, getStoreManager());
-
-  if (shouldRemoveDeadBindings(AMgr, S, Pred, LC)) {
-    NumRemoveDeadBindings++;
-    getCheckerManager().runCheckersForLiveSymbols(CleanedState, SymReaper);
-
-    const StackFrameContext *SFC = LC->getCurrentStackFrame();
-
-    // Create a state in which dead bindings are removed from the environment
-    // 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++;
-  }
+  // Create a state in which dead bindings are removed from the environment
+  // and the store. TODO: The function should just return new env and store,
+  // not a new state.
+  const StackFrameContext *SFC = LC->getCurrentStackFrame();
+  CleanedState = StateMgr.removeDeadBindings(CleanedState, SFC, SymReaper);
 
   // 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.
-    StmtNodeBuilder Bldr(Pred, Tmp, *currentBuilderContext);
-    Bldr.generateNode(currentStmt, EntryNode, CleanedState, false, &cleanupTag);
+    StmtNodeBuilder Bldr(Pred, Out, *currentBuilderContext);
+    Bldr.generateNode(DiagnosticStmt, Pred, CleanedState, false, &cleanupTag,K);
 
   } else {
     // Call checkers with the non-cleaned state so that they could query the
     // values of the soon to be dead symbols.
     ExplodedNodeSet CheckedSet;
-    getCheckerManager().runCheckersForDeadSymbols(CheckedSet, EntryNode,
-                                                 SymReaper, currentStmt, *this);
+    getCheckerManager().runCheckersForDeadSymbols(CheckedSet, Pred, SymReaper,
+                                                  DiagnosticStmt, *this, K);
 
     // 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);
+    StmtNodeBuilder Bldr(CheckedSet, Out, *currentBuilderContext);
     for (ExplodedNodeSet::const_iterator
           I = CheckedSet.begin(), E = CheckedSet.end(); I != E; ++I) {
       ProgramStateRef CheckerState = (*I)->getState();
@@ -324,10 +308,10 @@
       CheckerState = getConstraintManager().removeDeadBindings(CheckerState,
                                                                SymReaper);
 
-      assert(StateMgr.haveEqualEnvironments(CheckerState, EntryState) &&
+      assert(StateMgr.haveEqualEnvironments(CheckerState, Pred->getState()) &&
         "Checkers are not allowed to modify the Environment as a part of "
         "checkDeadSymbols processing.");
-      assert(StateMgr.haveEqualStores(CheckerState, EntryState) &&
+      assert(StateMgr.haveEqualStores(CheckerState, Pred->getState()) &&
         "Checkers are not allowed to modify the Store as a part of "
         "checkDeadSymbols processing.");
 
@@ -335,13 +319,35 @@
       // generate a transition to that state.
       ProgramStateRef CleanedCheckerSt =
         StateMgr.getPersistentStateWithGDM(CleanedState, CheckerState);
-      Bldr.generateNode(currentStmt, *I, CleanedCheckerSt, false, &cleanupTag,
-                        ProgramPoint::PostPurgeDeadSymbolsKind);
+      Bldr.generateNode(DiagnosticStmt, *I, CleanedCheckerSt, false,
+                        &cleanupTag, K);
     }
   }
+}
 
+void ExprEngine::ProcessStmt(const CFGStmt S,
+                             ExplodedNode *Pred) {
+  // Reclaim any unnecessary nodes in the ExplodedGraph.
+  G.reclaimRecentlyAllocatedNodes();
+
+  currentStmt = S.getStmt();
+  PrettyStackTraceLoc CrashInfo(getContext().getSourceManager(),
+                                currentStmt->getLocStart(),
+                                "Error evaluating statement");
+
+  // Remove dead bindings and symbols.
+  EntryNode = Pred;
+  ExplodedNodeSet CleanedStates;
+  if (shouldRemoveDeadBindings(AMgr, S, Pred, EntryNode->getLocationContext())){
+    removeDead(EntryNode, CleanedStates, currentStmt,
+               Pred->getLocationContext(), currentStmt);
+  } else
+    CleanedStates.Add(EntryNode);
+
+  // Visit the statement.
   ExplodedNodeSet Dst;
-  for (ExplodedNodeSet::iterator I=Tmp.begin(), E=Tmp.end(); I!=E; ++I) {
+  for (ExplodedNodeSet::iterator I = CleanedStates.begin(),
+                                 E = CleanedStates.end(); I != E; ++I) {
     ExplodedNodeSet DstI;
     // Visit the statement.
     Visit(currentStmt, *I, DstI);
@@ -994,7 +1000,7 @@
       continue;
     // We reached the caller. Find the node right before we started
     // processing the CallExpr.
-    if (isa<PostPurgeDeadSymbols>(L))
+    if (L.isPurgeKind())
       continue;
     if (const StmtPoint *SP = dyn_cast<StmtPoint>(&L))
       if (SP->getStmt() == CalleeSF->getCallSite())
@@ -1861,10 +1867,17 @@
     ProgramPoint Loc = N->getLocation();
 
     switch (Loc.getKind()) {
-      case ProgramPoint::BlockEntranceKind:
+      case ProgramPoint::BlockEntranceKind: {
         Out << "Block Entrance: B"
             << cast<BlockEntrance>(Loc).getBlock()->getBlockID();
+        if (const NamedDecl *ND =
+                    dyn_cast<NamedDecl>(Loc.getLocationContext()->getDecl())) {
+          Out << " (";
+          ND->printName(Out);
+          Out << ")";
+        }
         break;
+      }
 
       case ProgramPoint::BlockExitKind:
         assert (false);
@@ -1874,8 +1887,20 @@
         Out << "CallEnter";
         break;
 
-      case ProgramPoint::CallExitKind:
-        Out << "CallExit";
+      case ProgramPoint::CallExitBeginKind:
+        Out << "CallExitBegin";
+        break;
+
+      case ProgramPoint::CallExitEndKind:
+        Out << "CallExitEnd";
+        break;
+
+      case ProgramPoint::PostStmtPurgeDeadSymbolsKind:
+        Out << "PostStmtPurgeDeadSymbols";
+        break;
+
+      case ProgramPoint::PreStmtPurgeDeadSymbolsKind:
+        Out << "PreStmtPurgeDeadSymbols";
         break;
 
       case ProgramPoint::EpsilonKind:
diff --git a/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp b/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
index b9f4e15..4d0da06 100644
--- a/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
+++ b/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
@@ -51,71 +51,140 @@
     Engine.getWorkList()->enqueue(Node);
 }
 
-static const ReturnStmt *getReturnStmt(const ExplodedNode *Node) {
+// Find the last statement on the path to the exploded node and the
+// corresponding Block.
+static std::pair<const Stmt*,
+                 const CFGBlock*> getLastStmt(const ExplodedNode *Node) {
+  const Stmt *S = 0;
+  const CFGBlock *Blk = 0;
+  const StackFrameContext *SF =
+          Node->getLocation().getLocationContext()->getCurrentStackFrame();
   while (Node) {
     const ProgramPoint &PP = Node->getLocation();
-    // Skip any BlockEdges.
-    if (isa<BlockEdge>(PP) || isa<CallExit>(PP)) {
+    // Skip any BlockEdges, empty blocks, and the CallExitBegin node.
+    if (isa<BlockEdge>(PP) || isa<CallExitBegin>(PP) || isa<BlockEntrance>(PP)){
       assert(Node->pred_size() == 1);
       Node = *Node->pred_begin();
       continue;
-    } 
+    }
+    // If we reached the CallEnter, the function has no statements.
+    if (isa<CallEnter>(PP))
+      break;
     if (const StmtPoint *SP = dyn_cast<StmtPoint>(&PP)) {
-      const Stmt *S = SP->getStmt();
-      return dyn_cast<ReturnStmt>(S);
+      S = SP->getStmt();
+      // Now, get the enclosing basic block.
+      while (Node && Node->pred_size() >=1 ) {
+        const ProgramPoint &PP = Node->getLocation();
+        if (isa<BlockEdge>(PP) &&
+            (PP.getLocationContext()->getCurrentStackFrame() == SF)) {
+          BlockEdge &EPP = cast<BlockEdge>(PP);
+          Blk = EPP.getDst();
+          break;
+        }
+        Node = *Node->pred_begin();
+      }
+      break;
     }
     break;
   }
-  return 0;
+  return std::pair<const Stmt*, const CFGBlock*>(S, Blk);
 }
 
-void ExprEngine::processCallExit(ExplodedNode *Pred) {
-  ProgramStateRef state = Pred->getState();
-  const StackFrameContext *calleeCtx = 
-    Pred->getLocationContext()->getCurrentStackFrame();
+/// The call exit is simulated with a sequence of nodes, which occur between 
+/// CallExitBegin and CallExitEnd. The following operations occur between the 
+/// two program points:
+/// 1. CallExitBegin (triggers the start of call exit sequence)
+/// 2. Bind the return value
+/// 3. Run Remove dead bindings to clean up the dead symbols from the callee.
+/// 4. CallExitEnd (switch to the caller context)
+/// 5. PostStmt<CallExpr>
+void ExprEngine::processCallExit(ExplodedNode *CEBNode) {
+  // Step 1 CEBNode was generated before the call.
+
+  const StackFrameContext *calleeCtx =
+      CEBNode->getLocationContext()->getCurrentStackFrame();
   const LocationContext *callerCtx = calleeCtx->getParent();
   const Stmt *CE = calleeCtx->getCallSite();
-  
+  ProgramStateRef state = CEBNode->getState();
+  // Find the last statement in the function and the corresponding basic block.
+  const Stmt *LastSt = 0;
+  const CFGBlock *Blk = 0;
+  llvm::tie(LastSt, Blk) = getLastStmt(CEBNode);
+
+  // Step 2: generate node with binded return value: CEBNode -> BindedRetNode.
+
   // If the callee returns an expression, bind its value to CallExpr.
-  if (const ReturnStmt *RS = getReturnStmt(Pred)) {
-    const LocationContext *LCtx = Pred->getLocationContext();
+  if (const ReturnStmt *RS = dyn_cast_or_null<ReturnStmt>(LastSt)) {
+    const LocationContext *LCtx = CEBNode->getLocationContext();
     SVal V = state->getSVal(RS, LCtx);
     state = state->BindExpr(CE, callerCtx, V);
   }
-  
+
   // Bind the constructed object value to CXXConstructExpr.
   if (const CXXConstructExpr *CCE = dyn_cast<CXXConstructExpr>(CE)) {
     const CXXThisRegion *ThisR =
-    getCXXThisRegion(CCE->getConstructor()->getParent(), calleeCtx);
-    
+        getCXXThisRegion(CCE->getConstructor()->getParent(), calleeCtx);
+
     SVal ThisV = state->getSVal(ThisR);
     // Always bind the region to the CXXConstructExpr.
-    state = state->BindExpr(CCE, Pred->getLocationContext(), ThisV);
+    state = state->BindExpr(CCE, CEBNode->getLocationContext(), ThisV);
   }
-  
-  static SimpleProgramPointTag returnTag("ExprEngine : Call Return");
-  PostStmt Loc(CE, callerCtx, &returnTag);
+
+  static SimpleProgramPointTag retValBindTag("ExprEngine : Bind Return Value");
+  PostStmt Loc(LastSt, calleeCtx, &retValBindTag);
   bool isNew;
-  ExplodedNode *N = G.getNode(Loc, state, false, &isNew);
-  N->addPredecessor(Pred, G);
+  ExplodedNode *BindedRetNode = G.getNode(Loc, state, false, &isNew);
+  BindedRetNode->addPredecessor(CEBNode, G);
   if (!isNew)
     return;
-  
-  // Perform the post-condition check of the CallExpr.
-  ExplodedNodeSet Dst;
-  NodeBuilderContext Ctx(Engine, calleeCtx->getCallSiteBlock(), N);
-  SaveAndRestore<const NodeBuilderContext*> NBCSave(currentBuilderContext,
-                                                    &Ctx);
-  SaveAndRestore<unsigned> CBISave(currentStmtIdx, calleeCtx->getIndex());
-  
-  getCheckerManager().runCheckersForPostStmt(Dst, N, CE, *this,
-                                             /* wasInlined */ true);
-  
-  // Enqueue the next element in the block.
-  for (ExplodedNodeSet::iterator I = Dst.begin(), E = Dst.end(); I != E; ++I) {
-    Engine.getWorkList()->enqueue(*I,
-                                  calleeCtx->getCallSiteBlock(),
-                                  calleeCtx->getIndex()+1);
+
+  // Step 3: BindedRetNode -> CleanedNodes
+  // If we can find a statement and a block in the inlined function, run remove
+  // dead bindings before returning from the call. This is important to ensure
+  // that we report the issues such as leaks in the stack contexts in which
+  // they occurred.
+  ExplodedNodeSet CleanedNodes;
+  if (LastSt && Blk) {
+    NodeBuilderContext Ctx(getCoreEngine(), Blk, BindedRetNode);
+    currentBuilderContext = &Ctx;
+    // Here, we call the Symbol Reaper with 0 statement and caller location
+    // context, telling it to clean up everything in the callee's context
+    // (and it's children). We use LastStmt as a diagnostic statement, which
+    // which the PreStmtPurge Dead point will be associated.
+    removeDead(BindedRetNode, CleanedNodes, 0, callerCtx, LastSt,
+               ProgramPoint::PostStmtPurgeDeadSymbolsKind);
+    currentBuilderContext = 0;
+  }
+
+  for (ExplodedNodeSet::iterator I = CleanedNodes.begin(),
+                                 E = CleanedNodes.end(); I != E; ++I) {
+
+    // Step 4: Generate the CallExit and leave the callee's context.
+    // CleanedNodes -> CEENode
+    CallExitEnd Loc(CE, callerCtx);
+    bool isNew;
+    ExplodedNode *CEENode = G.getNode(Loc, (*I)->getState(), false, &isNew);
+    CEENode->addPredecessor(*I, G);
+    if (!isNew)
+      return;
+
+    // Step 5: Perform the post-condition check of the CallExpr and enqueue the
+    // result onto the work list.
+    // CEENode -> Dst -> WorkList
+    ExplodedNodeSet Dst;
+    NodeBuilderContext Ctx(Engine, calleeCtx->getCallSiteBlock(), CEENode);
+    SaveAndRestore<const NodeBuilderContext*> NBCSave(currentBuilderContext,
+        &Ctx);
+    SaveAndRestore<unsigned> CBISave(currentStmtIdx, calleeCtx->getIndex());
+
+    getCheckerManager().runCheckersForPostStmt(Dst, CEENode, CE, *this, true);
+
+    // Enqueue the next element in the block.
+    for (ExplodedNodeSet::iterator PSI = Dst.begin(), PSE = Dst.end();
+                                   PSI != PSE; ++PSI) {
+      Engine.getWorkList()->enqueue(*PSI, calleeCtx->getCallSiteBlock(),
+                                    calleeCtx->getIndex()+1);
+    }
   }
 }
 
diff --git a/lib/StaticAnalyzer/Core/PathDiagnostic.cpp b/lib/StaticAnalyzer/Core/PathDiagnostic.cpp
index 01dd965..a1e662f 100644
--- a/lib/StaticAnalyzer/Core/PathDiagnostic.cpp
+++ b/lib/StaticAnalyzer/Core/PathDiagnostic.cpp
@@ -510,9 +510,9 @@
 
 PathDiagnosticCallPiece *
 PathDiagnosticCallPiece::construct(const ExplodedNode *N,
-                                   const CallExit &CE,
+                                   const CallExitEnd &CE,
                                    const SourceManager &SM) {
-  const Decl *caller = CE.getLocationContext()->getParent()->getDecl();
+  const Decl *caller = CE.getLocationContext()->getDecl();
   PathDiagnosticLocation pos = getLastStmtLoc(N, SM);
   return new PathDiagnosticCallPiece(caller, pos);
 }
@@ -667,16 +667,13 @@
 
 std::string StackHintGeneratorForSymbol::getMessage(const ExplodedNode *N){
   ProgramPoint P = N->getLocation();
-  const CallExit *CExit = dyn_cast<CallExit>(&P);
-  assert(CExit && "Stack Hints should be constructed at CallExit points.");
+  const CallExitEnd *CExit = dyn_cast<CallExitEnd>(&P);
+  assert(CExit && "Stack Hints should be constructed at CallExitEnd points.");
 
   const CallExpr *CE = dyn_cast_or_null<CallExpr>(CExit->getStmt());
   if (!CE)
     return "";
 
-  // Get the successor node to make sure the return statement is evaluated and
-  // CE is set to the result value.
-  N = *N->succ_begin();
   if (!N)
     return getMessageForSymbolNotFound();
 
diff --git a/lib/StaticAnalyzer/Core/SymbolManager.cpp b/lib/StaticAnalyzer/Core/SymbolManager.cpp
index adefb58..5fee9af 100644
--- a/lib/StaticAnalyzer/Core/SymbolManager.cpp
+++ b/lib/StaticAnalyzer/Core/SymbolManager.cpp
@@ -501,6 +501,9 @@
       return false;
     return true;
   }
+  // If no statement is provided, everything is this and parent contexts is live.
+  if (!Loc)
+    return true;
 
   return LCtx->getAnalysis<RelaxedLiveVariables>()->isLive(Loc, ExprVal);
 }
@@ -510,6 +513,10 @@
   const StackFrameContext *CurrentContext = LCtx->getCurrentStackFrame();
 
   if (VarContext == CurrentContext) {
+    // If no statemetnt is provided, everything is live.
+    if (!Loc)
+      return true;
+
     if (LCtx->getAnalysis<RelaxedLiveVariables>()->isLive(Loc, VR->getDecl()))
       return true;