CoreEngine.h revision a7a8a450d908b34fa5f569f2e694ebd4b61aae2f
12bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian//==- GRCoreEngine.h - Path-Sensitive Dataflow Engine --------------*- C++ -*-// 22bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian// 32bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian// The LLVM Compiler Infrastructure 42bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian// 52bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian// This file is distributed under the University of Illinois Open Source 62bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian// License. See LICENSE.TXT for details. 72bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian// 82bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian//===----------------------------------------------------------------------===// 92bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian// 102bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian// This file defines a generic engine for intraprocedural, path-sensitive, 112bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian// dataflow analysis via graph reachability. 122bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian// 132bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian//===----------------------------------------------------------------------===// 142bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian 152bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#ifndef LLVM_CLANG_ANALYSIS_GRENGINE 162bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#define LLVM_CLANG_ANALYSIS_GRENGINE 172bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian 182bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#include "clang/AST/Expr.h" 192bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#include "clang/Checker/PathSensitive/ExplodedGraph.h" 202bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#include "clang/Checker/PathSensitive/GRWorkList.h" 212bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#include "clang/Checker/PathSensitive/GRBlockCounter.h" 222bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#include "clang/Checker/PathSensitive/GRAuditor.h" 232bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#include "clang/Checker/PathSensitive/GRSubEngine.h" 242bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#include "llvm/ADT/OwningPtr.h" 252bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian 262bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramaniannamespace clang { 272bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian 282bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian//===----------------------------------------------------------------------===// 292bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian/// GRCoreEngine - Implements the core logic of the graph-reachability 302bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian/// analysis. It traverses the CFG and generates the ExplodedGraph. 312bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian/// Program "states" are treated as opaque void pointers. 322bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian/// The template class GRCoreEngine (which subclasses GRCoreEngine) 332bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian/// provides the matching component to the engine that knows the actual types 342bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian/// for states. Note that this engine only dispatches to transfer functions 352bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian/// at the statement and block-level. The analyses themselves must implement 362bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian/// any transfer function logic and the sub-expression level (if any). 372bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanianclass GRCoreEngine { 382bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian friend class GRStmtNodeBuilder; 392bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian friend class GRBranchNodeBuilder; 402bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian friend class GRIndirectGotoNodeBuilder; 412bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian friend class GRSwitchNodeBuilder; 422bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian friend class GREndPathNodeBuilder; 432bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian friend class GRCallEnterNodeBuilder; 442bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian friend class GRCallExitNodeBuilder; 452bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian 462bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanianpublic: 472bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian typedef std::vector<std::pair<BlockEdge, const ExplodedNode*> > 482bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian BlocksAborted; 492bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanianprivate: 502bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian 512bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian GRSubEngine& SubEngine; 522bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian 532bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian /// G - The simulation graph. Each node is a (location,state) pair. 542bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian llvm::OwningPtr<ExplodedGraph> G; 552bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian 562bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian /// WList - A set of queued nodes that need to be processed by the 572bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian /// worklist algorithm. It is up to the implementation of WList to decide 582bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian /// the order that nodes are processed. 592bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian GRWorkList* WList; 602bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian 612bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian /// BCounterFactory - A factory object for created GRBlockCounter objects. 622bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian /// These are used to record for key nodes in the ExplodedGraph the 632bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian /// number of times different CFGBlocks have been visited along a path. 642bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian GRBlockCounter::Factory BCounterFactory; 652bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian 662bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian /// The locations where we stopped doing work because we visited a location 672bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian /// too many times. 682bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian BlocksAborted blocksAborted; 692bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian 702bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian void GenerateNode(const ProgramPoint& Loc, const GRState* State, 712bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian ExplodedNode* Pred); 722bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian 732bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian void HandleBlockEdge(const BlockEdge& E, ExplodedNode* Pred); 742bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian void HandleBlockEntrance(const BlockEntrance& E, ExplodedNode* Pred); 752bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian void HandleBlockExit(const CFGBlock* B, ExplodedNode* Pred); 762bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian void HandlePostStmt(const PostStmt& S, const CFGBlock* B, 772bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian unsigned StmtIdx, ExplodedNode *Pred); 782bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian 792bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian void HandleBranch(const Stmt* Cond, const Stmt* Term, const CFGBlock* B, 802bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian ExplodedNode* Pred); 812bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian void HandleCallEnter(const CallEnter &L, const CFGBlock *Block, 822bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian unsigned Index, ExplodedNode *Pred); 832bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian void HandleCallExit(const CallExit &L, ExplodedNode *Pred); 842bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian 852bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian /// Get the initial state from the subengine. 862bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian const GRState* getInitialState(const LocationContext *InitLoc) { 872bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian return SubEngine.getInitialState(InitLoc); 882bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian } 892bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian 902bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian void ProcessEndPath(GREndPathNodeBuilder& Builder) { 912bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian SubEngine.ProcessEndPath(Builder); 922bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian } 932bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian 942bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian void ProcessStmt(const CFGElement E, GRStmtNodeBuilder& Builder) { 952bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian SubEngine.ProcessStmt(E, Builder); 962bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian } 972bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian 982bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian bool ProcessBlockEntrance(const CFGBlock* Blk, const ExplodedNode *Pred, 992bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian GRBlockCounter BC) { 1002bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian return SubEngine.ProcessBlockEntrance(Blk, Pred, BC); 1012bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian } 102 103 104 void ProcessBranch(const Stmt* Condition, const Stmt* Terminator, 105 GRBranchNodeBuilder& Builder) { 106 SubEngine.ProcessBranch(Condition, Terminator, Builder); 107 } 108 109 110 void ProcessIndirectGoto(GRIndirectGotoNodeBuilder& Builder) { 111 SubEngine.ProcessIndirectGoto(Builder); 112 } 113 114 115 void ProcessSwitch(GRSwitchNodeBuilder& Builder) { 116 SubEngine.ProcessSwitch(Builder); 117 } 118 119 void ProcessCallEnter(GRCallEnterNodeBuilder &Builder) { 120 SubEngine.ProcessCallEnter(Builder); 121 } 122 123 void ProcessCallExit(GRCallExitNodeBuilder &Builder) { 124 SubEngine.ProcessCallExit(Builder); 125 } 126 127private: 128 GRCoreEngine(const GRCoreEngine&); // Do not implement. 129 GRCoreEngine& operator=(const GRCoreEngine&); 130 131public: 132 /// Construct a GRCoreEngine object to analyze the provided CFG using 133 /// a DFS exploration of the exploded graph. 134 GRCoreEngine(GRSubEngine& subengine) 135 : SubEngine(subengine), G(new ExplodedGraph()), 136 WList(GRWorkList::MakeBFS()), 137 BCounterFactory(G->getAllocator()) {} 138 139 /// Construct a GRCoreEngine object to analyze the provided CFG and to 140 /// use the provided worklist object to execute the worklist algorithm. 141 /// The GRCoreEngine object assumes ownership of 'wlist'. 142 GRCoreEngine(GRWorkList* wlist, GRSubEngine& subengine) 143 : SubEngine(subengine), G(new ExplodedGraph()), WList(wlist), 144 BCounterFactory(G->getAllocator()) {} 145 146 ~GRCoreEngine() { 147 delete WList; 148 } 149 150 /// getGraph - Returns the exploded graph. 151 ExplodedGraph& getGraph() { return *G.get(); } 152 153 /// takeGraph - Returns the exploded graph. Ownership of the graph is 154 /// transfered to the caller. 155 ExplodedGraph* takeGraph() { return G.take(); } 156 157 /// ExecuteWorkList - Run the worklist algorithm for a maximum number of 158 /// steps. Returns true if there is still simulation state on the worklist. 159 bool ExecuteWorkList(const LocationContext *L, unsigned Steps, 160 const GRState *InitState); 161 void ExecuteWorkListWithInitialState(const LocationContext *L, unsigned Steps, 162 const GRState *InitState, 163 ExplodedNodeSet &Dst); 164 165 // Functions for external checking of whether we have unfinished work 166 bool wasBlockAborted() const { return !blocksAborted.empty(); } 167 bool hasWorkRemaining() const { return wasBlockAborted() || WList->hasWork(); } 168 169 GRWorkList *getWorkList() const { return WList; } 170 171 BlocksAborted::const_iterator blocks_aborted_begin() const { 172 return blocksAborted.begin(); 173 } 174 BlocksAborted::const_iterator blocks_aborted_end() const { 175 return blocksAborted.end(); 176 } 177}; 178 179class GRStmtNodeBuilder { 180 GRCoreEngine& Eng; 181 const CFGBlock& B; 182 const unsigned Idx; 183 ExplodedNode* Pred; 184 GRStateManager& Mgr; 185 GRAuditor* Auditor; 186 187public: 188 bool PurgingDeadSymbols; 189 bool BuildSinks; 190 bool HasGeneratedNode; 191 ProgramPoint::Kind PointKind; 192 const void *Tag; 193 194 const GRState* CleanedState; 195 196 197 typedef llvm::SmallPtrSet<ExplodedNode*,5> DeferredTy; 198 DeferredTy Deferred; 199 200 void GenerateAutoTransition(ExplodedNode* N); 201 202public: 203 GRStmtNodeBuilder(const CFGBlock* b, unsigned idx, ExplodedNode* N, 204 GRCoreEngine* e, GRStateManager &mgr); 205 206 ~GRStmtNodeBuilder(); 207 208 ExplodedNode* getBasePredecessor() const { return Pred; } 209 210 // FIXME: This should not be exposed. 211 GRWorkList *getWorkList() { return Eng.WList; } 212 213 void SetCleanedState(const GRState* St) { 214 CleanedState = St; 215 } 216 217 GRBlockCounter getBlockCounter() const { return Eng.WList->getBlockCounter();} 218 219 unsigned getCurrentBlockCount() const { 220 return getBlockCounter().getNumVisited( 221 Pred->getLocationContext()->getCurrentStackFrame(), 222 B.getBlockID()); 223 } 224 225 ExplodedNode* generateNode(PostStmt PP,const GRState* St,ExplodedNode* Pred) { 226 HasGeneratedNode = true; 227 return generateNodeInternal(PP, St, Pred); 228 } 229 230 ExplodedNode* generateNode(const Stmt *S, const GRState *St, 231 ExplodedNode *Pred, ProgramPoint::Kind K) { 232 HasGeneratedNode = true; 233 234 if (PurgingDeadSymbols) 235 K = ProgramPoint::PostPurgeDeadSymbolsKind; 236 237 return generateNodeInternal(S, St, Pred, K, Tag); 238 } 239 240 ExplodedNode* generateNode(const Stmt *S, const GRState *St, 241 ExplodedNode *Pred) { 242 return generateNode(S, St, Pred, PointKind); 243 } 244 245 ExplodedNode *generateNode(const ProgramPoint &PP, const GRState* State, 246 ExplodedNode* Pred) { 247 HasGeneratedNode = true; 248 return generateNodeInternal(PP, State, Pred); 249 } 250 251 ExplodedNode* 252 generateNodeInternal(const ProgramPoint &PP, const GRState* State, 253 ExplodedNode* Pred); 254 255 ExplodedNode* 256 generateNodeInternal(const Stmt* S, const GRState* State, ExplodedNode* Pred, 257 ProgramPoint::Kind K = ProgramPoint::PostStmtKind, 258 const void *tag = 0); 259 260 /// getStmt - Return the current block-level expression associated with 261 /// this builder. 262 const Stmt* getStmt() const { return B[Idx]; } 263 264 /// getBlock - Return the CFGBlock associated with the block-level expression 265 /// of this builder. 266 const CFGBlock* getBlock() const { return &B; } 267 268 unsigned getIndex() const { return Idx; } 269 270 void setAuditor(GRAuditor* A) { Auditor = A; } 271 272 const GRState* GetState(ExplodedNode* Pred) const { 273 if (Pred == getBasePredecessor()) 274 return CleanedState; 275 else 276 return Pred->getState(); 277 } 278 279 ExplodedNode* MakeNode(ExplodedNodeSet& Dst, const Stmt* S, 280 ExplodedNode* Pred, const GRState* St) { 281 return MakeNode(Dst, S, Pred, St, PointKind); 282 } 283 284 ExplodedNode* MakeNode(ExplodedNodeSet& Dst, const Stmt* S,ExplodedNode* Pred, 285 const GRState* St, ProgramPoint::Kind K); 286 287 ExplodedNode* MakeSinkNode(ExplodedNodeSet& Dst, const Stmt* S, 288 ExplodedNode* Pred, const GRState* St) { 289 bool Tmp = BuildSinks; 290 BuildSinks = true; 291 ExplodedNode* N = MakeNode(Dst, S, Pred, St); 292 BuildSinks = Tmp; 293 return N; 294 } 295}; 296 297class GRBranchNodeBuilder { 298 GRCoreEngine& Eng; 299 const CFGBlock* Src; 300 const CFGBlock* DstT; 301 const CFGBlock* DstF; 302 ExplodedNode* Pred; 303 304 typedef llvm::SmallVector<ExplodedNode*,3> DeferredTy; 305 DeferredTy Deferred; 306 307 bool GeneratedTrue; 308 bool GeneratedFalse; 309 bool InFeasibleTrue; 310 bool InFeasibleFalse; 311 312public: 313 GRBranchNodeBuilder(const CFGBlock* src, const CFGBlock* dstT, 314 const CFGBlock* dstF, ExplodedNode* pred, GRCoreEngine* e) 315 : Eng(*e), Src(src), DstT(dstT), DstF(dstF), Pred(pred), 316 GeneratedTrue(false), GeneratedFalse(false), 317 InFeasibleTrue(!DstT), InFeasibleFalse(!DstF) {} 318 319 ~GRBranchNodeBuilder(); 320 321 ExplodedNode* getPredecessor() const { return Pred; } 322 323 const ExplodedGraph& getGraph() const { return *Eng.G; } 324 325 GRBlockCounter getBlockCounter() const { return Eng.WList->getBlockCounter();} 326 327 ExplodedNode* generateNode(const GRState* State, bool branch); 328 329 const CFGBlock* getTargetBlock(bool branch) const { 330 return branch ? DstT : DstF; 331 } 332 333 void markInfeasible(bool branch) { 334 if (branch) 335 InFeasibleTrue = GeneratedTrue = true; 336 else 337 InFeasibleFalse = GeneratedFalse = true; 338 } 339 340 bool isFeasible(bool branch) { 341 return branch ? !InFeasibleTrue : !InFeasibleFalse; 342 } 343 344 const GRState* getState() const { 345 return getPredecessor()->getState(); 346 } 347}; 348 349class GRIndirectGotoNodeBuilder { 350 GRCoreEngine& Eng; 351 const CFGBlock* Src; 352 const CFGBlock& DispatchBlock; 353 const Expr* E; 354 ExplodedNode* Pred; 355 356public: 357 GRIndirectGotoNodeBuilder(ExplodedNode* pred, const CFGBlock* src, 358 const Expr* e, const CFGBlock* dispatch, GRCoreEngine* eng) 359 : Eng(*eng), Src(src), DispatchBlock(*dispatch), E(e), Pred(pred) {} 360 361 class iterator { 362 CFGBlock::const_succ_iterator I; 363 364 friend class GRIndirectGotoNodeBuilder; 365 iterator(CFGBlock::const_succ_iterator i) : I(i) {} 366 public: 367 368 iterator& operator++() { ++I; return *this; } 369 bool operator!=(const iterator& X) const { return I != X.I; } 370 371 const LabelStmt* getLabel() const { 372 return llvm::cast<LabelStmt>((*I)->getLabel()); 373 } 374 375 const CFGBlock* getBlock() const { 376 return *I; 377 } 378 }; 379 380 iterator begin() { return iterator(DispatchBlock.succ_begin()); } 381 iterator end() { return iterator(DispatchBlock.succ_end()); } 382 383 ExplodedNode* generateNode(const iterator& I, const GRState* State, 384 bool isSink = false); 385 386 const Expr* getTarget() const { return E; } 387 388 const GRState* getState() const { return Pred->State; } 389}; 390 391class GRSwitchNodeBuilder { 392 GRCoreEngine& Eng; 393 const CFGBlock* Src; 394 const Expr* Condition; 395 ExplodedNode* Pred; 396 397public: 398 GRSwitchNodeBuilder(ExplodedNode* pred, const CFGBlock* src, 399 const Expr* condition, GRCoreEngine* eng) 400 : Eng(*eng), Src(src), Condition(condition), Pred(pred) {} 401 402 class iterator { 403 CFGBlock::const_succ_reverse_iterator I; 404 405 friend class GRSwitchNodeBuilder; 406 iterator(CFGBlock::const_succ_reverse_iterator i) : I(i) {} 407 408 public: 409 iterator& operator++() { ++I; return *this; } 410 bool operator!=(const iterator& X) const { return I != X.I; } 411 412 const CaseStmt* getCase() const { 413 return llvm::cast<CaseStmt>((*I)->getLabel()); 414 } 415 416 const CFGBlock* getBlock() const { 417 return *I; 418 } 419 }; 420 421 iterator begin() { return iterator(Src->succ_rbegin()+1); } 422 iterator end() { return iterator(Src->succ_rend()); } 423 424 ExplodedNode* generateCaseStmtNode(const iterator& I, const GRState* State); 425 426 ExplodedNode* generateDefaultCaseNode(const GRState* State, 427 bool isSink = false); 428 429 const Expr* getCondition() const { return Condition; } 430 431 const GRState* getState() const { return Pred->State; } 432}; 433 434class GREndPathNodeBuilder { 435 GRCoreEngine &Eng; 436 const CFGBlock& B; 437 ExplodedNode* Pred; 438 439public: 440 bool HasGeneratedNode; 441 442public: 443 GREndPathNodeBuilder(const CFGBlock* b, ExplodedNode* N, GRCoreEngine* e) 444 : Eng(*e), B(*b), Pred(N), HasGeneratedNode(false) {} 445 446 ~GREndPathNodeBuilder(); 447 448 GRWorkList &getWorkList() { return *Eng.WList; } 449 450 ExplodedNode* getPredecessor() const { return Pred; } 451 452 GRBlockCounter getBlockCounter() const { 453 return Eng.WList->getBlockCounter(); 454 } 455 456 unsigned getCurrentBlockCount() const { 457 return getBlockCounter().getNumVisited( 458 Pred->getLocationContext()->getCurrentStackFrame(), 459 B.getBlockID()); 460 } 461 462 ExplodedNode* generateNode(const GRState* State, const void *tag = 0, 463 ExplodedNode *P = 0); 464 465 void GenerateCallExitNode(const GRState *state); 466 467 const CFGBlock* getBlock() const { return &B; } 468 469 const GRState* getState() const { 470 return getPredecessor()->getState(); 471 } 472}; 473 474class GRCallEnterNodeBuilder { 475 GRCoreEngine &Eng; 476 477 const ExplodedNode *Pred; 478 479 // The call site. 480 const Stmt *CE; 481 482 // The AnalysisContext of the callee. 483 AnalysisContext *CalleeCtx; 484 485 // The parent block of the CallExpr. 486 const CFGBlock *Block; 487 488 // The CFGBlock index of the CallExpr. 489 unsigned Index; 490 491public: 492 GRCallEnterNodeBuilder(GRCoreEngine &eng, const ExplodedNode *pred, 493 const Stmt *s, AnalysisContext *callee, 494 const CFGBlock *blk, unsigned idx) 495 : Eng(eng), Pred(pred), CE(s), CalleeCtx(callee), Block(blk), Index(idx) {} 496 497 const GRState *getState() const { return Pred->getState(); } 498 499 const LocationContext *getLocationContext() const { 500 return Pred->getLocationContext(); 501 } 502 503 const Stmt *getCallExpr() const { return CE; } 504 505 AnalysisContext *getCalleeContext() const { return CalleeCtx; } 506 507 const CFGBlock *getBlock() const { return Block; } 508 509 unsigned getIndex() const { return Index; } 510 511 void GenerateNode(const GRState *state, const LocationContext *LocCtx); 512}; 513 514class GRCallExitNodeBuilder { 515 GRCoreEngine &Eng; 516 const ExplodedNode *Pred; 517 518public: 519 GRCallExitNodeBuilder(GRCoreEngine &eng, const ExplodedNode *pred) 520 : Eng(eng), Pred(pred) {} 521 522 const ExplodedNode *getPredecessor() const { return Pred; } 523 524 const GRState *getState() const { return Pred->getState(); } 525 526 void GenerateNode(const GRState *state); 527}; 528} // end clang namespace 529 530#endif 531