clang API Documentation

CoreEngine.cpp
Go to the documentation of this file.
00001 //==- CoreEngine.cpp - Path-Sensitive Dataflow Engine ------------*- C++ -*-//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 //
00010 //  This file defines a generic engine for intraprocedural, path-sensitive,
00011 //  dataflow analysis via graph reachability engine.
00012 //
00013 //===----------------------------------------------------------------------===//
00014 
00015 #include "clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h"
00016 #include "clang/AST/Expr.h"
00017 #include "clang/AST/ExprCXX.h"
00018 #include "clang/AST/StmtCXX.h"
00019 #include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
00020 #include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
00021 #include "llvm/ADT/DenseMap.h"
00022 #include "llvm/ADT/Statistic.h"
00023 #include "llvm/Support/Casting.h"
00024 
00025 using namespace clang;
00026 using namespace ento;
00027 
00028 #define DEBUG_TYPE "CoreEngine"
00029 
00030 STATISTIC(NumSteps,
00031             "The # of steps executed.");
00032 STATISTIC(NumReachedMaxSteps,
00033             "The # of times we reached the max number of steps.");
00034 STATISTIC(NumPathsExplored,
00035             "The # of paths explored by the analyzer.");
00036 
00037 //===----------------------------------------------------------------------===//
00038 // Worklist classes for exploration of reachable states.
00039 //===----------------------------------------------------------------------===//
00040 
00041 WorkList::Visitor::~Visitor() {}
00042 
00043 namespace {
00044 class DFS : public WorkList {
00045   SmallVector<WorkListUnit,20> Stack;
00046 public:
00047   bool hasWork() const override {
00048     return !Stack.empty();
00049   }
00050 
00051   void enqueue(const WorkListUnit& U) override {
00052     Stack.push_back(U);
00053   }
00054 
00055   WorkListUnit dequeue() override {
00056     assert (!Stack.empty());
00057     const WorkListUnit& U = Stack.back();
00058     Stack.pop_back(); // This technically "invalidates" U, but we are fine.
00059     return U;
00060   }
00061 
00062   bool visitItemsInWorkList(Visitor &V) override {
00063     for (SmallVectorImpl<WorkListUnit>::iterator
00064          I = Stack.begin(), E = Stack.end(); I != E; ++I) {
00065       if (V.visit(*I))
00066         return true;
00067     }
00068     return false;
00069   }
00070 };
00071 
00072 class BFS : public WorkList {
00073   std::deque<WorkListUnit> Queue;
00074 public:
00075   bool hasWork() const override {
00076     return !Queue.empty();
00077   }
00078 
00079   void enqueue(const WorkListUnit& U) override {
00080     Queue.push_back(U);
00081   }
00082 
00083   WorkListUnit dequeue() override {
00084     WorkListUnit U = Queue.front();
00085     Queue.pop_front();
00086     return U;
00087   }
00088 
00089   bool visitItemsInWorkList(Visitor &V) override {
00090     for (std::deque<WorkListUnit>::iterator
00091          I = Queue.begin(), E = Queue.end(); I != E; ++I) {
00092       if (V.visit(*I))
00093         return true;
00094     }
00095     return false;
00096   }
00097 };
00098 
00099 } // end anonymous namespace
00100 
00101 // Place the dstor for WorkList here because it contains virtual member
00102 // functions, and we the code for the dstor generated in one compilation unit.
00103 WorkList::~WorkList() {}
00104 
00105 WorkList *WorkList::makeDFS() { return new DFS(); }
00106 WorkList *WorkList::makeBFS() { return new BFS(); }
00107 
00108 namespace {
00109   class BFSBlockDFSContents : public WorkList {
00110     std::deque<WorkListUnit> Queue;
00111     SmallVector<WorkListUnit,20> Stack;
00112   public:
00113     bool hasWork() const override {
00114       return !Queue.empty() || !Stack.empty();
00115     }
00116 
00117     void enqueue(const WorkListUnit& U) override {
00118       if (U.getNode()->getLocation().getAs<BlockEntrance>())
00119         Queue.push_front(U);
00120       else
00121         Stack.push_back(U);
00122     }
00123 
00124     WorkListUnit dequeue() override {
00125       // Process all basic blocks to completion.
00126       if (!Stack.empty()) {
00127         const WorkListUnit& U = Stack.back();
00128         Stack.pop_back(); // This technically "invalidates" U, but we are fine.
00129         return U;
00130       }
00131 
00132       assert(!Queue.empty());
00133       // Don't use const reference.  The subsequent pop_back() might make it
00134       // unsafe.
00135       WorkListUnit U = Queue.front();
00136       Queue.pop_front();
00137       return U;
00138     }
00139     bool visitItemsInWorkList(Visitor &V) override {
00140       for (SmallVectorImpl<WorkListUnit>::iterator
00141            I = Stack.begin(), E = Stack.end(); I != E; ++I) {
00142         if (V.visit(*I))
00143           return true;
00144       }
00145       for (std::deque<WorkListUnit>::iterator
00146            I = Queue.begin(), E = Queue.end(); I != E; ++I) {
00147         if (V.visit(*I))
00148           return true;
00149       }
00150       return false;
00151     }
00152 
00153   };
00154 } // end anonymous namespace
00155 
00156 WorkList* WorkList::makeBFSBlockDFSContents() {
00157   return new BFSBlockDFSContents();
00158 }
00159 
00160 //===----------------------------------------------------------------------===//
00161 // Core analysis engine.
00162 //===----------------------------------------------------------------------===//
00163 
00164 /// ExecuteWorkList - Run the worklist algorithm for a maximum number of steps.
00165 bool CoreEngine::ExecuteWorkList(const LocationContext *L, unsigned Steps,
00166                                    ProgramStateRef InitState) {
00167 
00168   if (G.num_roots() == 0) { // Initialize the analysis by constructing
00169     // the root if none exists.
00170 
00171     const CFGBlock *Entry = &(L->getCFG()->getEntry());
00172 
00173     assert (Entry->empty() &&
00174             "Entry block must be empty.");
00175 
00176     assert (Entry->succ_size() == 1 &&
00177             "Entry block must have 1 successor.");
00178 
00179     // Mark the entry block as visited.
00180     FunctionSummaries->markVisitedBasicBlock(Entry->getBlockID(),
00181                                              L->getDecl(),
00182                                              L->getCFG()->getNumBlockIDs());
00183 
00184     // Get the solitary successor.
00185     const CFGBlock *Succ = *(Entry->succ_begin());
00186 
00187     // Construct an edge representing the
00188     // starting location in the function.
00189     BlockEdge StartLoc(Entry, Succ, L);
00190 
00191     // Set the current block counter to being empty.
00192     WList->setBlockCounter(BCounterFactory.GetEmptyCounter());
00193 
00194     if (!InitState)
00195       // Generate the root.
00196       generateNode(StartLoc, SubEng.getInitialState(L), nullptr);
00197     else
00198       generateNode(StartLoc, InitState, nullptr);
00199   }
00200 
00201   // Check if we have a steps limit
00202   bool UnlimitedSteps = Steps == 0;
00203 
00204   while (WList->hasWork()) {
00205     if (!UnlimitedSteps) {
00206       if (Steps == 0) {
00207         NumReachedMaxSteps++;
00208         break;
00209       }
00210       --Steps;
00211     }
00212 
00213     NumSteps++;
00214 
00215     const WorkListUnit& WU = WList->dequeue();
00216 
00217     // Set the current block counter.
00218     WList->setBlockCounter(WU.getBlockCounter());
00219 
00220     // Retrieve the node.
00221     ExplodedNode *Node = WU.getNode();
00222 
00223     dispatchWorkItem(Node, Node->getLocation(), WU);
00224   }
00225   SubEng.processEndWorklist(hasWorkRemaining());
00226   return WList->hasWork();
00227 }
00228 
00229 void CoreEngine::dispatchWorkItem(ExplodedNode* Pred, ProgramPoint Loc,
00230                                   const WorkListUnit& WU) {
00231   // Dispatch on the location type.
00232   switch (Loc.getKind()) {
00233     case ProgramPoint::BlockEdgeKind:
00234       HandleBlockEdge(Loc.castAs<BlockEdge>(), Pred);
00235       break;
00236 
00237     case ProgramPoint::BlockEntranceKind:
00238       HandleBlockEntrance(Loc.castAs<BlockEntrance>(), Pred);
00239       break;
00240 
00241     case ProgramPoint::BlockExitKind:
00242       assert (false && "BlockExit location never occur in forward analysis.");
00243       break;
00244 
00245     case ProgramPoint::CallEnterKind: {
00246       CallEnter CEnter = Loc.castAs<CallEnter>();
00247       SubEng.processCallEnter(CEnter, Pred);
00248       break;
00249     }
00250 
00251     case ProgramPoint::CallExitBeginKind:
00252       SubEng.processCallExit(Pred);
00253       break;
00254 
00255     case ProgramPoint::EpsilonKind: {
00256       assert(Pred->hasSinglePred() &&
00257              "Assume epsilon has exactly one predecessor by construction");
00258       ExplodedNode *PNode = Pred->getFirstPred();
00259       dispatchWorkItem(Pred, PNode->getLocation(), WU);
00260       break;
00261     }
00262     default:
00263       assert(Loc.getAs<PostStmt>() ||
00264              Loc.getAs<PostInitializer>() ||
00265              Loc.getAs<PostImplicitCall>() ||
00266              Loc.getAs<CallExitEnd>());
00267       HandlePostStmt(WU.getBlock(), WU.getIndex(), Pred);
00268       break;
00269   }
00270 }
00271 
00272 bool CoreEngine::ExecuteWorkListWithInitialState(const LocationContext *L,
00273                                                  unsigned Steps,
00274                                                  ProgramStateRef InitState, 
00275                                                  ExplodedNodeSet &Dst) {
00276   bool DidNotFinish = ExecuteWorkList(L, Steps, InitState);
00277   for (ExplodedGraph::eop_iterator I = G.eop_begin(), E = G.eop_end(); I != E;
00278        ++I) {
00279     Dst.Add(*I);
00280   }
00281   return DidNotFinish;
00282 }
00283 
00284 void CoreEngine::HandleBlockEdge(const BlockEdge &L, ExplodedNode *Pred) {
00285 
00286   const CFGBlock *Blk = L.getDst();
00287   NodeBuilderContext BuilderCtx(*this, Blk, Pred);
00288 
00289   // Mark this block as visited.
00290   const LocationContext *LC = Pred->getLocationContext();
00291   FunctionSummaries->markVisitedBasicBlock(Blk->getBlockID(),
00292                                            LC->getDecl(),
00293                                            LC->getCFG()->getNumBlockIDs());
00294 
00295   // Check if we are entering the EXIT block.
00296   if (Blk == &(L.getLocationContext()->getCFG()->getExit())) {
00297 
00298     assert (L.getLocationContext()->getCFG()->getExit().size() == 0
00299             && "EXIT block cannot contain Stmts.");
00300 
00301     // Process the final state transition.
00302     SubEng.processEndOfFunction(BuilderCtx, Pred);
00303 
00304     // This path is done. Don't enqueue any more nodes.
00305     return;
00306   }
00307 
00308   // Call into the SubEngine to process entering the CFGBlock.
00309   ExplodedNodeSet dstNodes;
00310   BlockEntrance BE(Blk, Pred->getLocationContext());
00311   NodeBuilderWithSinks nodeBuilder(Pred, dstNodes, BuilderCtx, BE);
00312   SubEng.processCFGBlockEntrance(L, nodeBuilder, Pred);
00313 
00314   // Auto-generate a node.
00315   if (!nodeBuilder.hasGeneratedNodes()) {
00316     nodeBuilder.generateNode(Pred->State, Pred);
00317   }
00318 
00319   // Enqueue nodes onto the worklist.
00320   enqueue(dstNodes);
00321 }
00322 
00323 void CoreEngine::HandleBlockEntrance(const BlockEntrance &L,
00324                                        ExplodedNode *Pred) {
00325 
00326   // Increment the block counter.
00327   const LocationContext *LC = Pred->getLocationContext();
00328   unsigned BlockId = L.getBlock()->getBlockID();
00329   BlockCounter Counter = WList->getBlockCounter();
00330   Counter = BCounterFactory.IncrementCount(Counter, LC->getCurrentStackFrame(),
00331                                            BlockId);
00332   WList->setBlockCounter(Counter);
00333 
00334   // Process the entrance of the block.
00335   if (Optional<CFGElement> E = L.getFirstElement()) {
00336     NodeBuilderContext Ctx(*this, L.getBlock(), Pred);
00337     SubEng.processCFGElement(*E, Pred, 0, &Ctx);
00338   }
00339   else
00340     HandleBlockExit(L.getBlock(), Pred);
00341 }
00342 
00343 void CoreEngine::HandleBlockExit(const CFGBlock * B, ExplodedNode *Pred) {
00344 
00345   if (const Stmt *Term = B->getTerminator()) {
00346     switch (Term->getStmtClass()) {
00347       default:
00348         llvm_unreachable("Analysis for this terminator not implemented.");
00349 
00350       case Stmt::CXXBindTemporaryExprClass:
00351         HandleCleanupTemporaryBranch(
00352             cast<CXXBindTemporaryExpr>(B->getTerminator().getStmt()), B, Pred);
00353         return;
00354 
00355       // Model static initializers.
00356       case Stmt::DeclStmtClass:
00357         HandleStaticInit(cast<DeclStmt>(Term), B, Pred);
00358         return;
00359 
00360       case Stmt::BinaryOperatorClass: // '&&' and '||'
00361         HandleBranch(cast<BinaryOperator>(Term)->getLHS(), Term, B, Pred);
00362         return;
00363 
00364       case Stmt::BinaryConditionalOperatorClass:
00365       case Stmt::ConditionalOperatorClass:
00366         HandleBranch(cast<AbstractConditionalOperator>(Term)->getCond(),
00367                      Term, B, Pred);
00368         return;
00369 
00370         // FIXME: Use constant-folding in CFG construction to simplify this
00371         // case.
00372 
00373       case Stmt::ChooseExprClass:
00374         HandleBranch(cast<ChooseExpr>(Term)->getCond(), Term, B, Pred);
00375         return;
00376 
00377       case Stmt::CXXTryStmtClass: {
00378         // Generate a node for each of the successors.
00379         // Our logic for EH analysis can certainly be improved.
00380         for (CFGBlock::const_succ_iterator it = B->succ_begin(),
00381              et = B->succ_end(); it != et; ++it) {
00382           if (const CFGBlock *succ = *it) {
00383             generateNode(BlockEdge(B, succ, Pred->getLocationContext()),
00384                          Pred->State, Pred);
00385           }
00386         }
00387         return;
00388       }
00389         
00390       case Stmt::DoStmtClass:
00391         HandleBranch(cast<DoStmt>(Term)->getCond(), Term, B, Pred);
00392         return;
00393 
00394       case Stmt::CXXForRangeStmtClass:
00395         HandleBranch(cast<CXXForRangeStmt>(Term)->getCond(), Term, B, Pred);
00396         return;
00397 
00398       case Stmt::ForStmtClass:
00399         HandleBranch(cast<ForStmt>(Term)->getCond(), Term, B, Pred);
00400         return;
00401 
00402       case Stmt::ContinueStmtClass:
00403       case Stmt::BreakStmtClass:
00404       case Stmt::GotoStmtClass:
00405         break;
00406 
00407       case Stmt::IfStmtClass:
00408         HandleBranch(cast<IfStmt>(Term)->getCond(), Term, B, Pred);
00409         return;
00410 
00411       case Stmt::IndirectGotoStmtClass: {
00412         // Only 1 successor: the indirect goto dispatch block.
00413         assert (B->succ_size() == 1);
00414 
00415         IndirectGotoNodeBuilder
00416            builder(Pred, B, cast<IndirectGotoStmt>(Term)->getTarget(),
00417                    *(B->succ_begin()), this);
00418 
00419         SubEng.processIndirectGoto(builder);
00420         return;
00421       }
00422 
00423       case Stmt::ObjCForCollectionStmtClass: {
00424         // In the case of ObjCForCollectionStmt, it appears twice in a CFG:
00425         //
00426         //  (1) inside a basic block, which represents the binding of the
00427         //      'element' variable to a value.
00428         //  (2) in a terminator, which represents the branch.
00429         //
00430         // For (1), subengines will bind a value (i.e., 0 or 1) indicating
00431         // whether or not collection contains any more elements.  We cannot
00432         // just test to see if the element is nil because a container can
00433         // contain nil elements.
00434         HandleBranch(Term, Term, B, Pred);
00435         return;
00436       }
00437 
00438       case Stmt::SwitchStmtClass: {
00439         SwitchNodeBuilder builder(Pred, B, cast<SwitchStmt>(Term)->getCond(),
00440                                     this);
00441 
00442         SubEng.processSwitch(builder);
00443         return;
00444       }
00445 
00446       case Stmt::WhileStmtClass:
00447         HandleBranch(cast<WhileStmt>(Term)->getCond(), Term, B, Pred);
00448         return;
00449     }
00450   }
00451 
00452   assert (B->succ_size() == 1 &&
00453           "Blocks with no terminator should have at most 1 successor.");
00454 
00455   generateNode(BlockEdge(B, *(B->succ_begin()), Pred->getLocationContext()),
00456                Pred->State, Pred);
00457 }
00458 
00459 void CoreEngine::HandleBranch(const Stmt *Cond, const Stmt *Term, 
00460                                 const CFGBlock * B, ExplodedNode *Pred) {
00461   assert(B->succ_size() == 2);
00462   NodeBuilderContext Ctx(*this, B, Pred);
00463   ExplodedNodeSet Dst;
00464   SubEng.processBranch(Cond, Term, Ctx, Pred, Dst,
00465                        *(B->succ_begin()), *(B->succ_begin()+1));
00466   // Enqueue the new frontier onto the worklist.
00467   enqueue(Dst);
00468 }
00469 
00470 void CoreEngine::HandleCleanupTemporaryBranch(const CXXBindTemporaryExpr *BTE,
00471                                               const CFGBlock *B,
00472                                               ExplodedNode *Pred) {
00473   assert(B->succ_size() == 2);
00474   NodeBuilderContext Ctx(*this, B, Pred);
00475   ExplodedNodeSet Dst;
00476   SubEng.processCleanupTemporaryBranch(BTE, Ctx, Pred, Dst, *(B->succ_begin()),
00477                                        *(B->succ_begin() + 1));
00478   // Enqueue the new frontier onto the worklist.
00479   enqueue(Dst);
00480 }
00481 
00482 void CoreEngine::HandleStaticInit(const DeclStmt *DS, const CFGBlock *B,
00483                                   ExplodedNode *Pred) {
00484   assert(B->succ_size() == 2);
00485   NodeBuilderContext Ctx(*this, B, Pred);
00486   ExplodedNodeSet Dst;
00487   SubEng.processStaticInitializer(DS, Ctx, Pred, Dst,
00488                                   *(B->succ_begin()), *(B->succ_begin()+1));
00489   // Enqueue the new frontier onto the worklist.
00490   enqueue(Dst);
00491 }
00492 
00493 
00494 void CoreEngine::HandlePostStmt(const CFGBlock *B, unsigned StmtIdx, 
00495                                   ExplodedNode *Pred) {
00496   assert(B);
00497   assert(!B->empty());
00498 
00499   if (StmtIdx == B->size())
00500     HandleBlockExit(B, Pred);
00501   else {
00502     NodeBuilderContext Ctx(*this, B, Pred);
00503     SubEng.processCFGElement((*B)[StmtIdx], Pred, StmtIdx, &Ctx);
00504   }
00505 }
00506 
00507 /// generateNode - Utility method to generate nodes, hook up successors,
00508 ///  and add nodes to the worklist.
00509 void CoreEngine::generateNode(const ProgramPoint &Loc,
00510                               ProgramStateRef State,
00511                               ExplodedNode *Pred) {
00512 
00513   bool IsNew;
00514   ExplodedNode *Node = G.getNode(Loc, State, false, &IsNew);
00515 
00516   if (Pred)
00517     Node->addPredecessor(Pred, G); // Link 'Node' with its predecessor.
00518   else {
00519     assert (IsNew);
00520     G.addRoot(Node); // 'Node' has no predecessor.  Make it a root.
00521   }
00522 
00523   // Only add 'Node' to the worklist if it was freshly generated.
00524   if (IsNew) WList->enqueue(Node);
00525 }
00526 
00527 void CoreEngine::enqueueStmtNode(ExplodedNode *N,
00528                                  const CFGBlock *Block, unsigned Idx) {
00529   assert(Block);
00530   assert (!N->isSink());
00531 
00532   // Check if this node entered a callee.
00533   if (N->getLocation().getAs<CallEnter>()) {
00534     // Still use the index of the CallExpr. It's needed to create the callee
00535     // StackFrameContext.
00536     WList->enqueue(N, Block, Idx);
00537     return;
00538   }
00539 
00540   // Do not create extra nodes. Move to the next CFG element.
00541   if (N->getLocation().getAs<PostInitializer>() ||
00542       N->getLocation().getAs<PostImplicitCall>()) {
00543     WList->enqueue(N, Block, Idx+1);
00544     return;
00545   }
00546 
00547   if (N->getLocation().getAs<EpsilonPoint>()) {
00548     WList->enqueue(N, Block, Idx);
00549     return;
00550   }
00551 
00552   if ((*Block)[Idx].getKind() == CFGElement::NewAllocator) {
00553     WList->enqueue(N, Block, Idx+1);
00554     return;
00555   }
00556 
00557   // At this point, we know we're processing a normal statement.
00558   CFGStmt CS = (*Block)[Idx].castAs<CFGStmt>();
00559   PostStmt Loc(CS.getStmt(), N->getLocationContext());
00560 
00561   if (Loc == N->getLocation().withTag(nullptr)) {
00562     // Note: 'N' should be a fresh node because otherwise it shouldn't be
00563     // a member of Deferred.
00564     WList->enqueue(N, Block, Idx+1);
00565     return;
00566   }
00567 
00568   bool IsNew;
00569   ExplodedNode *Succ = G.getNode(Loc, N->getState(), false, &IsNew);
00570   Succ->addPredecessor(N, G);
00571 
00572   if (IsNew)
00573     WList->enqueue(Succ, Block, Idx+1);
00574 }
00575 
00576 ExplodedNode *CoreEngine::generateCallExitBeginNode(ExplodedNode *N) {
00577   // Create a CallExitBegin node and enqueue it.
00578   const StackFrameContext *LocCtx
00579                          = cast<StackFrameContext>(N->getLocationContext());
00580 
00581   // Use the callee location context.
00582   CallExitBegin Loc(LocCtx);
00583 
00584   bool isNew;
00585   ExplodedNode *Node = G.getNode(Loc, N->getState(), false, &isNew);
00586   Node->addPredecessor(N, G);
00587   return isNew ? Node : nullptr;
00588 }
00589 
00590 
00591 void CoreEngine::enqueue(ExplodedNodeSet &Set) {
00592   for (ExplodedNodeSet::iterator I = Set.begin(),
00593                                  E = Set.end(); I != E; ++I) {
00594     WList->enqueue(*I);
00595   }
00596 }
00597 
00598 void CoreEngine::enqueue(ExplodedNodeSet &Set,
00599                          const CFGBlock *Block, unsigned Idx) {
00600   for (ExplodedNodeSet::iterator I = Set.begin(),
00601                                  E = Set.end(); I != E; ++I) {
00602     enqueueStmtNode(*I, Block, Idx);
00603   }
00604 }
00605 
00606 void CoreEngine::enqueueEndOfFunction(ExplodedNodeSet &Set) {
00607   for (ExplodedNodeSet::iterator I = Set.begin(), E = Set.end(); I != E; ++I) {
00608     ExplodedNode *N = *I;
00609     // If we are in an inlined call, generate CallExitBegin node.
00610     if (N->getLocationContext()->getParent()) {
00611       N = generateCallExitBeginNode(N);
00612       if (N)
00613         WList->enqueue(N);
00614     } else {
00615       // TODO: We should run remove dead bindings here.
00616       G.addEndOfPath(N);
00617       NumPathsExplored++;
00618     }
00619   }
00620 }
00621 
00622 
00623 void NodeBuilder::anchor() { }
00624 
00625 ExplodedNode* NodeBuilder::generateNodeImpl(const ProgramPoint &Loc,
00626                                             ProgramStateRef State,
00627                                             ExplodedNode *FromN,
00628                                             bool MarkAsSink) {
00629   HasGeneratedNodes = true;
00630   bool IsNew;
00631   ExplodedNode *N = C.Eng.G.getNode(Loc, State, MarkAsSink, &IsNew);
00632   N->addPredecessor(FromN, C.Eng.G);
00633   Frontier.erase(FromN);
00634 
00635   if (!IsNew)
00636     return nullptr;
00637 
00638   if (!MarkAsSink)
00639     Frontier.Add(N);
00640 
00641   return N;
00642 }
00643 
00644 void NodeBuilderWithSinks::anchor() { }
00645 
00646 StmtNodeBuilder::~StmtNodeBuilder() {
00647   if (EnclosingBldr)
00648     for (ExplodedNodeSet::iterator I = Frontier.begin(),
00649                                    E = Frontier.end(); I != E; ++I )
00650       EnclosingBldr->addNodes(*I);
00651 }
00652 
00653 void BranchNodeBuilder::anchor() { }
00654 
00655 ExplodedNode *BranchNodeBuilder::generateNode(ProgramStateRef State,
00656                                               bool branch,
00657                                               ExplodedNode *NodePred) {
00658   // If the branch has been marked infeasible we should not generate a node.
00659   if (!isFeasible(branch))
00660     return nullptr;
00661 
00662   ProgramPoint Loc = BlockEdge(C.Block, branch ? DstT:DstF,
00663                                NodePred->getLocationContext());
00664   ExplodedNode *Succ = generateNodeImpl(Loc, State, NodePred);
00665   return Succ;
00666 }
00667 
00668 ExplodedNode*
00669 IndirectGotoNodeBuilder::generateNode(const iterator &I,
00670                                       ProgramStateRef St,
00671                                       bool IsSink) {
00672   bool IsNew;
00673   ExplodedNode *Succ =
00674       Eng.G.getNode(BlockEdge(Src, I.getBlock(), Pred->getLocationContext()),
00675                     St, IsSink, &IsNew);
00676   Succ->addPredecessor(Pred, Eng.G);
00677 
00678   if (!IsNew)
00679     return nullptr;
00680 
00681   if (!IsSink)
00682     Eng.WList->enqueue(Succ);
00683 
00684   return Succ;
00685 }
00686 
00687 
00688 ExplodedNode*
00689 SwitchNodeBuilder::generateCaseStmtNode(const iterator &I,
00690                                         ProgramStateRef St) {
00691 
00692   bool IsNew;
00693   ExplodedNode *Succ =
00694       Eng.G.getNode(BlockEdge(Src, I.getBlock(), Pred->getLocationContext()),
00695                     St, false, &IsNew);
00696   Succ->addPredecessor(Pred, Eng.G);
00697   if (!IsNew)
00698     return nullptr;
00699 
00700   Eng.WList->enqueue(Succ);
00701   return Succ;
00702 }
00703 
00704 
00705 ExplodedNode*
00706 SwitchNodeBuilder::generateDefaultCaseNode(ProgramStateRef St,
00707                                            bool IsSink) {
00708   // Get the block for the default case.
00709   assert(Src->succ_rbegin() != Src->succ_rend());
00710   CFGBlock *DefaultBlock = *Src->succ_rbegin();
00711 
00712   // Sanity check for default blocks that are unreachable and not caught
00713   // by earlier stages.
00714   if (!DefaultBlock)
00715     return nullptr;
00716 
00717   bool IsNew;
00718   ExplodedNode *Succ =
00719       Eng.G.getNode(BlockEdge(Src, DefaultBlock, Pred->getLocationContext()),
00720                     St, IsSink, &IsNew);
00721   Succ->addPredecessor(Pred, Eng.G);
00722 
00723   if (!IsNew)
00724     return nullptr;
00725 
00726   if (!IsSink)
00727     Eng.WList->enqueue(Succ);
00728 
00729   return Succ;
00730 }