CoreEngine.h revision f178ac8b68b29e44867777232ba8fee59edc4037
1bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch//==- CoreEngine.h - Path-Sensitive Dataflow Engine ----------------*- C++ -*-// 2bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch// 3bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch// The LLVM Compiler Infrastructure 4bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch// 5bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch// This file is distributed under the University of Illinois Open Source 6bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch// License. See LICENSE.TXT for details. 7bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch// 8bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch//===----------------------------------------------------------------------===// 9bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch// 10bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch// This file defines a generic engine for intraprocedural, path-sensitive, 11bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch// dataflow analysis via graph reachability. 12bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch// 13bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch//===----------------------------------------------------------------------===// 140f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 150f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)#ifndef LLVM_CLANG_GR_COREENGINE 160f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)#define LLVM_CLANG_GR_COREENGINE 170f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 180f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)#include "clang/AST/Expr.h" 190f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)#include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h" 200f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)#include "clang/StaticAnalyzer/Core/PathSensitive/WorkList.h" 210f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)#include "clang/StaticAnalyzer/Core/PathSensitive/BlockCounter.h" 220f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)#include "clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h" 230f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)#include "llvm/ADT/OwningPtr.h" 240f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 250f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)namespace clang { 260f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 270f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)namespace ento { 280f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 290f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)//===----------------------------------------------------------------------===// 300f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)/// CoreEngine - Implements the core logic of the graph-reachability 310f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)/// analysis. It traverses the CFG and generates the ExplodedGraph. 320f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)/// Program "states" are treated as opaque void pointers. 330f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)/// The template class CoreEngine (which subclasses CoreEngine) 340f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)/// provides the matching component to the engine that knows the actual types 35bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch/// for states. Note that this engine only dispatches to transfer functions 36bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch/// at the statement and block-level. The analyses themselves must implement 37bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch/// any transfer function logic and the sub-expression level (if any). 38bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdochclass CoreEngine { 39bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch friend class StmtNodeBuilder; 40bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch friend class GenericNodeBuilderImpl; 410f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) friend class BranchNodeBuilder; 42bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch friend class IndirectGotoNodeBuilder; 430f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) friend class SwitchNodeBuilder; 44bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch friend class EndOfFunctionNodeBuilder; 45bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch friend class CallEnterNodeBuilder; 46bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch friend class CallExitNodeBuilder; 47bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch 48bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdochpublic: 49bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch typedef std::vector<std::pair<BlockEdge, const ExplodedNode*> > 50bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch BlocksAborted; 51bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdochprivate: 52bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch 53bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch SubEngine& SubEng; 5458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 55bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch /// G - The simulation graph. Each node is a (location,state) pair. 56bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch llvm::OwningPtr<ExplodedGraph> G; 57bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch 58bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch /// WList - A set of queued nodes that need to be processed by the 59bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch /// worklist algorithm. It is up to the implementation of WList to decide 60bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch /// the order that nodes are processed. 61bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch WorkList* WList; 62bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch 63bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch /// BCounterFactory - A factory object for created BlockCounter objects. 64bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch /// These are used to record for key nodes in the ExplodedGraph the 65bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch /// number of times different CFGBlocks have been visited along a path. 660f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) BlockCounter::Factory BCounterFactory; 670f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 68bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch /// The locations where we stopped doing work because we visited a location 69bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch /// too many times. 70bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch BlocksAborted blocksAborted; 71bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch 72bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch void generateNode(const ProgramPoint& Loc, const GRState* State, 73bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch ExplodedNode* Pred); 74bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch 75bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch void HandleBlockEdge(const BlockEdge& E, ExplodedNode* Pred); 7658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) void HandleBlockEntrance(const BlockEntrance& E, ExplodedNode* Pred); 77bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch void HandleBlockExit(const CFGBlock* B, ExplodedNode* Pred); 78bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch void HandlePostStmt(const CFGBlock* B, unsigned StmtIdx, ExplodedNode *Pred); 79bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch 80bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch void HandleBranch(const Stmt* Cond, const Stmt* Term, const CFGBlock* B, 81bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch ExplodedNode* Pred); 82bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch void HandleCallEnter(const CallEnter &L, const CFGBlock *Block, 83bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch unsigned Index, ExplodedNode *Pred); 84bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch void HandleCallExit(const CallExit &L, ExplodedNode *Pred); 85bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch 86bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdochprivate: 87bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch CoreEngine(const CoreEngine&); // Do not implement. 880f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) CoreEngine& operator=(const CoreEngine&); 890f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 90bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdochpublic: 91bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch /// Construct a CoreEngine object to analyze the provided CFG using 92bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch /// a DFS exploration of the exploded graph. 93bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch CoreEngine(SubEngine& subengine) 94bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch : SubEng(subengine), G(new ExplodedGraph()), 95bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch WList(WorkList::makeBFS()), 96bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch BCounterFactory(G->getAllocator()) {} 97bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch 9858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) /// Construct a CoreEngine object to analyze the provided CFG and to 99bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch /// use the provided worklist object to execute the worklist algorithm. 100bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch /// The CoreEngine object assumes ownership of 'wlist'. 101bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch CoreEngine(WorkList* wlist, SubEngine& subengine) 102bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch : SubEng(subengine), G(new ExplodedGraph()), WList(wlist), 103bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch BCounterFactory(G->getAllocator()) {} 104bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch 105bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch ~CoreEngine() { 106bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch delete WList; 1070f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) } 1080f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 109bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch /// getGraph - Returns the exploded graph. 110bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch ExplodedGraph& getGraph() { return *G.get(); } 111bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch 112bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch /// takeGraph - Returns the exploded graph. Ownership of the graph is 113bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch /// transfered to the caller. 114bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch ExplodedGraph* takeGraph() { return G.take(); } 115bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch 116bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch /// ExecuteWorkList - Run the worklist algorithm for a maximum number of 11758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) /// steps. Returns true if there is still simulation state on the worklist. 118bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch bool ExecuteWorkList(const LocationContext *L, unsigned Steps, 119bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch const GRState *InitState); 120bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch void ExecuteWorkListWithInitialState(const LocationContext *L, unsigned Steps, 121bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch const GRState *InitState, 122bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch ExplodedNodeSet &Dst); 123bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch 124bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch // Functions for external checking of whether we have unfinished work 125bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch bool wasBlockAborted() const { return !blocksAborted.empty(); } 126bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch bool hasWorkRemaining() const { return wasBlockAborted() || WList->hasWork(); } 127bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch 128bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch WorkList *getWorkList() const { return WList; } 129bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch 130bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch BlocksAborted::const_iterator blocks_aborted_begin() const { 1310f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) return blocksAborted.begin(); 132bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch } 1330f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) BlocksAborted::const_iterator blocks_aborted_end() const { 134bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch return blocksAborted.end(); 135bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch } 136bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch}; 137bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch 138bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdochclass StmtNodeBuilder { 139bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch CoreEngine& Eng; 140bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch const CFGBlock& B; 141bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch const unsigned Idx; 14258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) ExplodedNode* Pred; 143bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch GRStateManager& Mgr; 144bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch 145bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdochpublic: 146bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch bool PurgingDeadSymbols; 147bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch bool BuildSinks; 148bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch bool hasGeneratedNode; 149bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch ProgramPoint::Kind PointKind; 150bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch const void *Tag; 151bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch 152bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch const GRState* CleanedState; 153bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch 154bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch 155bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch typedef llvm::SmallPtrSet<ExplodedNode*,5> DeferredTy; 156bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch DeferredTy Deferred; 1570f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 158bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch void GenerateAutoTransition(ExplodedNode* N); 1590f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 160bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdochpublic: 161bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch StmtNodeBuilder(const CFGBlock* b, unsigned idx, ExplodedNode* N, 162bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch CoreEngine* e, GRStateManager &mgr); 163bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch 164bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch ~StmtNodeBuilder(); 165bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch 166bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch ExplodedNode* getPredecessor() const { return Pred; } 167bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch 16858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // FIXME: This should not be exposed. 1690f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) WorkList *getWorkList() { return Eng.WList; } 1700f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 1710f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) void SetCleanedState(const GRState* St) { 1720f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) CleanedState = St; 1730f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) } 1740f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 1750f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) BlockCounter getBlockCounter() const { return Eng.WList->getBlockCounter();} 1760f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 1770f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) unsigned getCurrentBlockCount() const { 1780f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) return getBlockCounter().getNumVisited( 1790f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) Pred->getLocationContext()->getCurrentStackFrame(), 1800f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) B.getBlockID()); 1810f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) } 1820f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 1830f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) ExplodedNode* generateNode(PostStmt PP,const GRState* St,ExplodedNode* Pred) { 1840f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) hasGeneratedNode = true; 1850f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) return generateNodeInternal(PP, St, Pred); 1860f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) } 1870f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 1880f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) ExplodedNode* generateNode(const Stmt *S, const GRState *St, 1890f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) ExplodedNode *Pred, ProgramPoint::Kind K, 1900f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) const void *tag = 0) { 1910f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) hasGeneratedNode = true; 1920f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 1930f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) if (PurgingDeadSymbols) 1940f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) K = ProgramPoint::PostPurgeDeadSymbolsKind; 1950f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 1960f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) return generateNodeInternal(S, St, Pred, K, tag ? tag : Tag); 1970f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) } 1980f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 1990f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) ExplodedNode* generateNode(const Stmt *S, const GRState *St, 2000f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) ExplodedNode *Pred, const void *tag = 0) { 2010f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) return generateNode(S, St, Pred, PointKind, tag); 2020f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) } 2030f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 2040f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) ExplodedNode *generateNode(const ProgramPoint &PP, const GRState* State, 2050f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) ExplodedNode* Pred) { 2060f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) hasGeneratedNode = true; 2070f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) return generateNodeInternal(PP, State, Pred); 2080f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) } 2090f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 2100f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) ExplodedNode* 2110f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) generateNodeInternal(const ProgramPoint &PP, const GRState* State, 2120f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) ExplodedNode* Pred); 2130f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 2140f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) ExplodedNode* 2150f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) generateNodeInternal(const Stmt* S, const GRState* State, ExplodedNode* Pred, 2160f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) ProgramPoint::Kind K = ProgramPoint::PostStmtKind, 2170f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) const void *tag = 0); 2180f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 2190f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) /// getStmt - Return the current block-level expression associated with 2200f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) /// this builder. 2210f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) const Stmt* getStmt() const { 2220f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) CFGStmt CS = B[Idx].getAs<CFGStmt>(); 2230f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) if (CS) 2240f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) return CS.getStmt(); 2250f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) else 2260f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) return 0; 2270f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) } 2280f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 2290f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) /// getBlock - Return the CFGBlock associated with the block-level expression 2300f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) /// of this builder. 2310f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) const CFGBlock* getBlock() const { return &B; } 2320f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 2330f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) unsigned getIndex() const { return Idx; } 2340f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 2350f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) const GRState* GetState(ExplodedNode* Pred) const { 2360f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) if (Pred == getPredecessor()) 2370f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) return CleanedState; 23858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) else 23958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return Pred->getState(); 24058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 24158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 24258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) ExplodedNode* MakeNode(ExplodedNodeSet& Dst, const Stmt* S, 24358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) ExplodedNode* Pred, const GRState* St) { 2440f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) return MakeNode(Dst, S, Pred, St, PointKind); 24558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 2460f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 24758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) ExplodedNode* MakeNode(ExplodedNodeSet& Dst, const Stmt* S,ExplodedNode* Pred, 24858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) const GRState* St, ProgramPoint::Kind K); 24958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 25058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) ExplodedNode* MakeSinkNode(ExplodedNodeSet& Dst, const Stmt* S, 25158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) ExplodedNode* Pred, const GRState* St) { 25258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) bool Tmp = BuildSinks; 25358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) BuildSinks = true; 25458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) ExplodedNode* N = MakeNode(Dst, S, Pred, St); 25558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) BuildSinks = Tmp; 25658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return N; 2570f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) } 25858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}; 2590f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 26058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)class BranchNodeBuilder { 26158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) CoreEngine& Eng; 26258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) const CFGBlock* Src; 26358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) const CFGBlock* DstT; 26458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) const CFGBlock* DstF; 26558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) ExplodedNode* Pred; 26658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 26758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) typedef llvm::SmallVector<ExplodedNode*,3> DeferredTy; 268bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch DeferredTy Deferred; 269bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch 2700f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) bool GeneratedTrue; 2710f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) bool GeneratedFalse; 2720f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) bool InFeasibleTrue; 2730f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) bool InFeasibleFalse; 274bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch 2750f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)public: 2760f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) BranchNodeBuilder(const CFGBlock* src, const CFGBlock* dstT, 2770f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) const CFGBlock* dstF, ExplodedNode* pred, CoreEngine* e) 278bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch : Eng(*e), Src(src), DstT(dstT), DstF(dstF), Pred(pred), 2790f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) GeneratedTrue(false), GeneratedFalse(false), 2800f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) InFeasibleTrue(!DstT), InFeasibleFalse(!DstF) {} 2810f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 2820f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) ~BranchNodeBuilder(); 2830f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 2840f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) ExplodedNode* getPredecessor() const { return Pred; } 2850f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 2860f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) const ExplodedGraph& getGraph() const { return *Eng.G; } 2870f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 2880f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) BlockCounter getBlockCounter() const { return Eng.WList->getBlockCounter();} 2890f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 2900f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) ExplodedNode* generateNode(const GRState* State, bool branch); 2910f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 2920f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) const CFGBlock* getTargetBlock(bool branch) const { 2930f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) return branch ? DstT : DstF; 2940f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) } 295bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch 296bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch void markInfeasible(bool branch) { 297bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch if (branch) 298bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch InFeasibleTrue = GeneratedTrue = true; 299bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch else 300bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch InFeasibleFalse = GeneratedFalse = true; 3010f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) } 302bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch 303bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch bool isFeasible(bool branch) { 304bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch return branch ? !InFeasibleTrue : !InFeasibleFalse; 305bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch } 306bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch 307bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch const GRState* getState() const { 308bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch return getPredecessor()->getState(); 309bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch } 310bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch}; 311bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch 312bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdochclass IndirectGotoNodeBuilder { 313bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch CoreEngine& Eng; 314bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch const CFGBlock* Src; 3150f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) const CFGBlock& DispatchBlock; 316bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch const Expr* E; 3170f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) ExplodedNode* Pred; 318bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch 319bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdochpublic: 320bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch IndirectGotoNodeBuilder(ExplodedNode* pred, const CFGBlock* src, 321bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch const Expr* e, const CFGBlock* dispatch, CoreEngine* eng) 322bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch : Eng(*eng), Src(src), DispatchBlock(*dispatch), E(e), Pred(pred) {} 323bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch 324bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch class iterator { 325bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch CFGBlock::const_succ_iterator I; 326bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch 327bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch friend class IndirectGotoNodeBuilder; 328bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch iterator(CFGBlock::const_succ_iterator i) : I(i) {} 3290f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) public: 330bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch 3310f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) iterator& operator++() { ++I; return *this; } 332bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch bool operator!=(const iterator& X) const { return I != X.I; } 333bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch 334bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch const LabelDecl *getLabel() const { 335bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch return llvm::cast<LabelStmt>((*I)->getLabel())->getDecl(); 336bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch } 337bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch 338bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch const CFGBlock *getBlock() const { 339bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch return *I; 340bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch } 341 }; 342 343 iterator begin() { return iterator(DispatchBlock.succ_begin()); } 344 iterator end() { return iterator(DispatchBlock.succ_end()); } 345 346 ExplodedNode* generateNode(const iterator& I, const GRState* State, 347 bool isSink = false); 348 349 const Expr* getTarget() const { return E; } 350 351 const GRState* getState() const { return Pred->State; } 352}; 353 354class SwitchNodeBuilder { 355 CoreEngine& Eng; 356 const CFGBlock* Src; 357 const Expr* Condition; 358 ExplodedNode* Pred; 359 360public: 361 SwitchNodeBuilder(ExplodedNode* pred, const CFGBlock* src, 362 const Expr* condition, CoreEngine* eng) 363 : Eng(*eng), Src(src), Condition(condition), Pred(pred) {} 364 365 class iterator { 366 CFGBlock::const_succ_reverse_iterator I; 367 368 friend class SwitchNodeBuilder; 369 iterator(CFGBlock::const_succ_reverse_iterator i) : I(i) {} 370 371 public: 372 iterator& operator++() { ++I; return *this; } 373 bool operator!=(const iterator &X) const { return I != X.I; } 374 bool operator==(const iterator &X) const { return I == X.I; } 375 376 const CaseStmt* getCase() const { 377 return llvm::cast<CaseStmt>((*I)->getLabel()); 378 } 379 380 const CFGBlock* getBlock() const { 381 return *I; 382 } 383 }; 384 385 iterator begin() { return iterator(Src->succ_rbegin()+1); } 386 iterator end() { return iterator(Src->succ_rend()); } 387 388 const SwitchStmt *getSwitch() const { 389 return llvm::cast<SwitchStmt>(Src->getTerminator()); 390 } 391 392 ExplodedNode* generateCaseStmtNode(const iterator& I, const GRState* State); 393 394 ExplodedNode* generateDefaultCaseNode(const GRState* State, 395 bool isSink = false); 396 397 const Expr* getCondition() const { return Condition; } 398 399 const GRState* getState() const { return Pred->State; } 400}; 401 402class GenericNodeBuilderImpl { 403protected: 404 CoreEngine &engine; 405 ExplodedNode *pred; 406 ProgramPoint pp; 407 llvm::SmallVector<ExplodedNode*, 2> sinksGenerated; 408 409 ExplodedNode *generateNodeImpl(const GRState *state, ExplodedNode *pred, 410 ProgramPoint programPoint, bool asSink); 411 412 GenericNodeBuilderImpl(CoreEngine &eng, ExplodedNode *pr, ProgramPoint p) 413 : engine(eng), pred(pr), pp(p), hasGeneratedNode(false) {} 414 415public: 416 bool hasGeneratedNode; 417 418 WorkList &getWorkList() { return *engine.WList; } 419 420 ExplodedNode* getPredecessor() const { return pred; } 421 422 BlockCounter getBlockCounter() const { 423 return engine.WList->getBlockCounter(); 424 } 425 426 const llvm::SmallVectorImpl<ExplodedNode*> &sinks() const { 427 return sinksGenerated; 428 } 429}; 430 431template <typename PP_T> 432class GenericNodeBuilder : public GenericNodeBuilderImpl { 433public: 434 GenericNodeBuilder(CoreEngine &eng, ExplodedNode *pr, const PP_T &p) 435 : GenericNodeBuilderImpl(eng, pr, p) {} 436 437 ExplodedNode *generateNode(const GRState *state, ExplodedNode *pred, 438 const void *tag, bool asSink) { 439 return generateNodeImpl(state, pred, cast<PP_T>(pp).withTag(tag), 440 asSink); 441 } 442 443 const PP_T &getProgramPoint() const { return cast<PP_T>(pp); } 444}; 445 446class EndOfFunctionNodeBuilder { 447 CoreEngine &Eng; 448 const CFGBlock& B; 449 ExplodedNode* Pred; 450 void *Tag; 451 452public: 453 bool hasGeneratedNode; 454 455public: 456 EndOfFunctionNodeBuilder(const CFGBlock* b, ExplodedNode* N, CoreEngine* e, 457 void *checkerTag = 0) 458 : Eng(*e), B(*b), Pred(N), Tag(checkerTag), hasGeneratedNode(false) {} 459 460 ~EndOfFunctionNodeBuilder(); 461 462 EndOfFunctionNodeBuilder withCheckerTag(void *tag) { 463 return EndOfFunctionNodeBuilder(&B, Pred, &Eng, tag); 464 } 465 466 WorkList &getWorkList() { return *Eng.WList; } 467 468 ExplodedNode* getPredecessor() const { return Pred; } 469 470 BlockCounter getBlockCounter() const { 471 return Eng.WList->getBlockCounter(); 472 } 473 474 unsigned getCurrentBlockCount() const { 475 return getBlockCounter().getNumVisited( 476 Pred->getLocationContext()->getCurrentStackFrame(), 477 B.getBlockID()); 478 } 479 480 ExplodedNode* generateNode(const GRState* State, ExplodedNode *P = 0, 481 const void *tag = 0); 482 483 void GenerateCallExitNode(const GRState *state); 484 485 const CFGBlock* getBlock() const { return &B; } 486 487 const GRState* getState() const { 488 return getPredecessor()->getState(); 489 } 490}; 491 492class CallEnterNodeBuilder { 493 CoreEngine &Eng; 494 495 const ExplodedNode *Pred; 496 497 // The call site. For implicit automatic object dtor, this is the trigger 498 // statement. 499 const Stmt *CE; 500 501 // The context of the callee. 502 const StackFrameContext *CalleeCtx; 503 504 // The parent block of the CallExpr. 505 const CFGBlock *Block; 506 507 // The CFGBlock index of the CallExpr. 508 unsigned Index; 509 510public: 511 CallEnterNodeBuilder(CoreEngine &eng, const ExplodedNode *pred, 512 const Stmt *s, const StackFrameContext *callee, 513 const CFGBlock *blk, unsigned idx) 514 : Eng(eng), Pred(pred), CE(s), CalleeCtx(callee), Block(blk), Index(idx) {} 515 516 const GRState *getState() const { return Pred->getState(); } 517 518 const LocationContext *getLocationContext() const { 519 return Pred->getLocationContext(); 520 } 521 522 const Stmt *getCallExpr() const { return CE; } 523 524 const StackFrameContext *getCalleeContext() const { return CalleeCtx; } 525 526 const CFGBlock *getBlock() const { return Block; } 527 528 unsigned getIndex() const { return Index; } 529 530 void generateNode(const GRState *state); 531}; 532 533class CallExitNodeBuilder { 534 CoreEngine &Eng; 535 const ExplodedNode *Pred; 536 537public: 538 CallExitNodeBuilder(CoreEngine &eng, const ExplodedNode *pred) 539 : Eng(eng), Pred(pred) {} 540 541 const ExplodedNode *getPredecessor() const { return Pred; } 542 543 const GRState *getState() const { return Pred->getState(); } 544 545 void generateNode(const GRState *state); 546}; 547 548} // end GR namespace 549 550} // end clang namespace 551 552#endif 553