clang API Documentation
00001 //==- CoreEngine.h - 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. 00012 // 00013 //===----------------------------------------------------------------------===// 00014 00015 #ifndef LLVM_CLANG_GR_COREENGINE 00016 #define LLVM_CLANG_GR_COREENGINE 00017 00018 #include "clang/AST/Expr.h" 00019 #include "clang/Analysis/AnalysisContext.h" 00020 #include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h" 00021 #include "clang/StaticAnalyzer/Core/PathSensitive/FunctionSummary.h" 00022 #include "clang/StaticAnalyzer/Core/PathSensitive/WorkList.h" 00023 #include "clang/StaticAnalyzer/Core/PathSensitive/BlockCounter.h" 00024 #include "llvm/ADT/OwningPtr.h" 00025 00026 namespace clang { 00027 00028 class ProgramPointTag; 00029 00030 namespace ento { 00031 00032 class NodeBuilder; 00033 00034 //===----------------------------------------------------------------------===// 00035 /// CoreEngine - Implements the core logic of the graph-reachability 00036 /// analysis. It traverses the CFG and generates the ExplodedGraph. 00037 /// Program "states" are treated as opaque void pointers. 00038 /// The template class CoreEngine (which subclasses CoreEngine) 00039 /// provides the matching component to the engine that knows the actual types 00040 /// for states. Note that this engine only dispatches to transfer functions 00041 /// at the statement and block-level. The analyses themselves must implement 00042 /// any transfer function logic and the sub-expression level (if any). 00043 class CoreEngine { 00044 friend struct NodeBuilderContext; 00045 friend class NodeBuilder; 00046 friend class ExprEngine; 00047 friend class CommonNodeBuilder; 00048 friend class IndirectGotoNodeBuilder; 00049 friend class SwitchNodeBuilder; 00050 friend class EndOfFunctionNodeBuilder; 00051 public: 00052 typedef std::vector<std::pair<BlockEdge, const ExplodedNode*> > 00053 BlocksExhausted; 00054 00055 typedef std::vector<std::pair<const CFGBlock*, const ExplodedNode*> > 00056 BlocksAborted; 00057 00058 private: 00059 00060 SubEngine& SubEng; 00061 00062 /// G - The simulation graph. Each node is a (location,state) pair. 00063 OwningPtr<ExplodedGraph> G; 00064 00065 /// WList - A set of queued nodes that need to be processed by the 00066 /// worklist algorithm. It is up to the implementation of WList to decide 00067 /// the order that nodes are processed. 00068 WorkList* WList; 00069 00070 /// BCounterFactory - A factory object for created BlockCounter objects. 00071 /// These are used to record for key nodes in the ExplodedGraph the 00072 /// number of times different CFGBlocks have been visited along a path. 00073 BlockCounter::Factory BCounterFactory; 00074 00075 /// The locations where we stopped doing work because we visited a location 00076 /// too many times. 00077 BlocksExhausted blocksExhausted; 00078 00079 /// The locations where we stopped because the engine aborted analysis, 00080 /// usually because it could not reason about something. 00081 BlocksAborted blocksAborted; 00082 00083 /// The functions which have been analyzed through inlining. This is owned by 00084 /// AnalysisConsumer. It can be null. 00085 SetOfConstDecls *AnalyzedCallees; 00086 00087 /// The information about functions shared by the whole translation unit. 00088 /// (This data is owned by AnalysisConsumer.) 00089 FunctionSummariesTy *FunctionSummaries; 00090 00091 void generateNode(const ProgramPoint &Loc, 00092 ProgramStateRef State, 00093 ExplodedNode *Pred); 00094 00095 void HandleBlockEdge(const BlockEdge &E, ExplodedNode *Pred); 00096 void HandleBlockEntrance(const BlockEntrance &E, ExplodedNode *Pred); 00097 void HandleBlockExit(const CFGBlock *B, ExplodedNode *Pred); 00098 void HandlePostStmt(const CFGBlock *B, unsigned StmtIdx, ExplodedNode *Pred); 00099 00100 void HandleBranch(const Stmt *Cond, const Stmt *Term, const CFGBlock *B, 00101 ExplodedNode *Pred); 00102 00103 private: 00104 CoreEngine(const CoreEngine&); // Do not implement. 00105 CoreEngine& operator=(const CoreEngine&); 00106 00107 ExplodedNode *generateCallExitBeginNode(ExplodedNode *N); 00108 00109 public: 00110 /// Construct a CoreEngine object to analyze the provided CFG using 00111 /// a DFS exploration of the exploded graph. 00112 CoreEngine(SubEngine& subengine, SetOfConstDecls *VisitedCallees, 00113 FunctionSummariesTy *FS) 00114 : SubEng(subengine), G(new ExplodedGraph()), 00115 WList(WorkList::makeBFS()), 00116 BCounterFactory(G->getAllocator()), 00117 AnalyzedCallees(VisitedCallees), 00118 FunctionSummaries(FS){} 00119 00120 ~CoreEngine() { 00121 delete WList; 00122 } 00123 00124 /// getGraph - Returns the exploded graph. 00125 ExplodedGraph& getGraph() { return *G.get(); } 00126 00127 /// takeGraph - Returns the exploded graph. Ownership of the graph is 00128 /// transferred to the caller. 00129 ExplodedGraph* takeGraph() { return G.take(); } 00130 00131 /// ExecuteWorkList - Run the worklist algorithm for a maximum number of 00132 /// steps. Returns true if there is still simulation state on the worklist. 00133 bool ExecuteWorkList(const LocationContext *L, unsigned Steps, 00134 ProgramStateRef InitState); 00135 /// Returns true if there is still simulation state on the worklist. 00136 bool ExecuteWorkListWithInitialState(const LocationContext *L, 00137 unsigned Steps, 00138 ProgramStateRef InitState, 00139 ExplodedNodeSet &Dst); 00140 00141 /// Dispatch the work list item based on the given location information. 00142 /// Use Pred parameter as the predecessor state. 00143 void dispatchWorkItem(ExplodedNode* Pred, ProgramPoint Loc, 00144 const WorkListUnit& WU); 00145 00146 // Functions for external checking of whether we have unfinished work 00147 bool wasBlockAborted() const { return !blocksAborted.empty(); } 00148 bool wasBlocksExhausted() const { return !blocksExhausted.empty(); } 00149 bool hasWorkRemaining() const { return wasBlocksExhausted() || 00150 WList->hasWork() || 00151 wasBlockAborted(); } 00152 00153 /// Inform the CoreEngine that a basic block was aborted because 00154 /// it could not be completely analyzed. 00155 void addAbortedBlock(const ExplodedNode *node, const CFGBlock *block) { 00156 blocksAborted.push_back(std::make_pair(block, node)); 00157 } 00158 00159 WorkList *getWorkList() const { return WList; } 00160 00161 BlocksExhausted::const_iterator blocks_exhausted_begin() const { 00162 return blocksExhausted.begin(); 00163 } 00164 BlocksExhausted::const_iterator blocks_exhausted_end() const { 00165 return blocksExhausted.end(); 00166 } 00167 BlocksAborted::const_iterator blocks_aborted_begin() const { 00168 return blocksAborted.begin(); 00169 } 00170 BlocksAborted::const_iterator blocks_aborted_end() const { 00171 return blocksAborted.end(); 00172 } 00173 00174 /// \brief Enqueue the given set of nodes onto the work list. 00175 void enqueue(ExplodedNodeSet &Set); 00176 00177 /// \brief Enqueue nodes that were created as a result of processing 00178 /// a statement onto the work list. 00179 void enqueue(ExplodedNodeSet &Set, const CFGBlock *Block, unsigned Idx); 00180 00181 /// \brief enqueue the nodes corresponding to the end of function onto the 00182 /// end of path / work list. 00183 void enqueueEndOfFunction(ExplodedNodeSet &Set); 00184 00185 /// \brief Enqueue a single node created as a result of statement processing. 00186 void enqueueStmtNode(ExplodedNode *N, const CFGBlock *Block, unsigned Idx); 00187 }; 00188 00189 // TODO: Turn into a calss. 00190 struct NodeBuilderContext { 00191 const CoreEngine &Eng; 00192 const CFGBlock *Block; 00193 ExplodedNode *Pred; 00194 NodeBuilderContext(const CoreEngine &E, const CFGBlock *B, ExplodedNode *N) 00195 : Eng(E), Block(B), Pred(N) { assert(B); assert(!N->isSink()); } 00196 00197 ExplodedNode *getPred() const { return Pred; } 00198 00199 /// \brief Return the CFGBlock associated with this builder. 00200 const CFGBlock *getBlock() const { return Block; } 00201 00202 /// \brief Returns the number of times the current basic block has been 00203 /// visited on the exploded graph path. 00204 unsigned getCurrentBlockCount() const { 00205 return Eng.WList->getBlockCounter().getNumVisited( 00206 Pred->getLocationContext()->getCurrentStackFrame(), 00207 Block->getBlockID()); 00208 } 00209 }; 00210 00211 /// \class NodeBuilder 00212 /// \brief This is the simplest builder which generates nodes in the 00213 /// ExplodedGraph. 00214 /// 00215 /// The main benefit of the builder is that it automatically tracks the 00216 /// frontier nodes (or destination set). This is the set of nodes which should 00217 /// be propagated to the next step / builder. They are the nodes which have been 00218 /// added to the builder (either as the input node set or as the newly 00219 /// constructed nodes) but did not have any outgoing transitions added. 00220 class NodeBuilder { 00221 virtual void anchor(); 00222 protected: 00223 const NodeBuilderContext &C; 00224 00225 /// Specifies if the builder results have been finalized. For example, if it 00226 /// is set to false, autotransitions are yet to be generated. 00227 bool Finalized; 00228 bool HasGeneratedNodes; 00229 /// \brief The frontier set - a set of nodes which need to be propagated after 00230 /// the builder dies. 00231 ExplodedNodeSet &Frontier; 00232 00233 /// Checkes if the results are ready. 00234 virtual bool checkResults() { 00235 if (!Finalized) 00236 return false; 00237 return true; 00238 } 00239 00240 bool hasNoSinksInFrontier() { 00241 for (iterator I = Frontier.begin(), E = Frontier.end(); I != E; ++I) { 00242 if ((*I)->isSink()) 00243 return false; 00244 } 00245 return true; 00246 } 00247 00248 /// Allow subclasses to finalize results before result_begin() is executed. 00249 virtual void finalizeResults() {} 00250 00251 ExplodedNode *generateNodeImpl(const ProgramPoint &PP, 00252 ProgramStateRef State, 00253 ExplodedNode *Pred, 00254 bool MarkAsSink = false); 00255 00256 public: 00257 NodeBuilder(ExplodedNode *SrcNode, ExplodedNodeSet &DstSet, 00258 const NodeBuilderContext &Ctx, bool F = true) 00259 : C(Ctx), Finalized(F), HasGeneratedNodes(false), Frontier(DstSet) { 00260 Frontier.Add(SrcNode); 00261 } 00262 00263 NodeBuilder(const ExplodedNodeSet &SrcSet, ExplodedNodeSet &DstSet, 00264 const NodeBuilderContext &Ctx, bool F = true) 00265 : C(Ctx), Finalized(F), HasGeneratedNodes(false), Frontier(DstSet) { 00266 Frontier.insert(SrcSet); 00267 assert(hasNoSinksInFrontier()); 00268 } 00269 00270 virtual ~NodeBuilder() {} 00271 00272 /// \brief Generates a node in the ExplodedGraph. 00273 /// 00274 /// When a node is marked as sink, the exploration from the node is stopped - 00275 /// the node becomes the last node on the path. 00276 ExplodedNode *generateNode(const ProgramPoint &PP, 00277 ProgramStateRef State, 00278 ExplodedNode *Pred, 00279 bool MarkAsSink = false) { 00280 return generateNodeImpl(PP, State, Pred, MarkAsSink); 00281 } 00282 00283 const ExplodedNodeSet &getResults() { 00284 finalizeResults(); 00285 assert(checkResults()); 00286 return Frontier; 00287 } 00288 00289 typedef ExplodedNodeSet::iterator iterator; 00290 /// \brief Iterators through the results frontier. 00291 inline iterator begin() { 00292 finalizeResults(); 00293 assert(checkResults()); 00294 return Frontier.begin(); 00295 } 00296 inline iterator end() { 00297 finalizeResults(); 00298 return Frontier.end(); 00299 } 00300 00301 const NodeBuilderContext &getContext() { return C; } 00302 bool hasGeneratedNodes() { return HasGeneratedNodes; } 00303 00304 void takeNodes(const ExplodedNodeSet &S) { 00305 for (ExplodedNodeSet::iterator I = S.begin(), E = S.end(); I != E; ++I ) 00306 Frontier.erase(*I); 00307 } 00308 void takeNodes(ExplodedNode *N) { Frontier.erase(N); } 00309 void addNodes(const ExplodedNodeSet &S) { Frontier.insert(S); } 00310 void addNodes(ExplodedNode *N) { Frontier.Add(N); } 00311 }; 00312 00313 /// \class NodeBuilderWithSinks 00314 /// \brief This node builder keeps track of the generated sink nodes. 00315 class NodeBuilderWithSinks: public NodeBuilder { 00316 virtual void anchor(); 00317 protected: 00318 SmallVector<ExplodedNode*, 2> sinksGenerated; 00319 ProgramPoint &Location; 00320 00321 public: 00322 NodeBuilderWithSinks(ExplodedNode *Pred, ExplodedNodeSet &DstSet, 00323 const NodeBuilderContext &Ctx, ProgramPoint &L) 00324 : NodeBuilder(Pred, DstSet, Ctx), Location(L) {} 00325 ExplodedNode *generateNode(ProgramStateRef State, 00326 ExplodedNode *Pred, 00327 const ProgramPointTag *Tag = 0, 00328 bool MarkAsSink = false) { 00329 ProgramPoint LocalLoc = (Tag ? Location.withTag(Tag): Location); 00330 00331 ExplodedNode *N = generateNodeImpl(LocalLoc, State, Pred, MarkAsSink); 00332 if (N && N->isSink()) 00333 sinksGenerated.push_back(N); 00334 return N; 00335 } 00336 00337 const SmallVectorImpl<ExplodedNode*> &getSinks() const { 00338 return sinksGenerated; 00339 } 00340 }; 00341 00342 /// \class StmtNodeBuilder 00343 /// \brief This builder class is useful for generating nodes that resulted from 00344 /// visiting a statement. The main difference from it's parent NodeBuilder is 00345 /// that it creates a statement specific ProgramPoint. 00346 class StmtNodeBuilder: public NodeBuilder { 00347 NodeBuilder *EnclosingBldr; 00348 public: 00349 00350 /// \brief Constructs a StmtNodeBuilder. If the builder is going to process 00351 /// nodes currently owned by another builder(with larger scope), use 00352 /// Enclosing builder to transfer ownership. 00353 StmtNodeBuilder(ExplodedNode *SrcNode, ExplodedNodeSet &DstSet, 00354 const NodeBuilderContext &Ctx, NodeBuilder *Enclosing = 0) 00355 : NodeBuilder(SrcNode, DstSet, Ctx), EnclosingBldr(Enclosing) { 00356 if (EnclosingBldr) 00357 EnclosingBldr->takeNodes(SrcNode); 00358 } 00359 00360 StmtNodeBuilder(ExplodedNodeSet &SrcSet, ExplodedNodeSet &DstSet, 00361 const NodeBuilderContext &Ctx, NodeBuilder *Enclosing = 0) 00362 : NodeBuilder(SrcSet, DstSet, Ctx), EnclosingBldr(Enclosing) { 00363 if (EnclosingBldr) 00364 for (ExplodedNodeSet::iterator I = SrcSet.begin(), 00365 E = SrcSet.end(); I != E; ++I ) 00366 EnclosingBldr->takeNodes(*I); 00367 } 00368 00369 virtual ~StmtNodeBuilder(); 00370 00371 ExplodedNode *generateNode(const Stmt *S, 00372 ExplodedNode *Pred, 00373 ProgramStateRef St, 00374 bool MarkAsSink = false, 00375 const ProgramPointTag *tag = 0, 00376 ProgramPoint::Kind K = ProgramPoint::PostStmtKind){ 00377 const ProgramPoint &L = ProgramPoint::getProgramPoint(S, K, 00378 Pred->getLocationContext(), tag); 00379 return generateNodeImpl(L, St, Pred, MarkAsSink); 00380 } 00381 00382 ExplodedNode *generateNode(const ProgramPoint &PP, 00383 ExplodedNode *Pred, 00384 ProgramStateRef State, 00385 bool MarkAsSink = false) { 00386 return generateNodeImpl(PP, State, Pred, MarkAsSink); 00387 } 00388 }; 00389 00390 /// \brief BranchNodeBuilder is responsible for constructing the nodes 00391 /// corresponding to the two branches of the if statement - true and false. 00392 class BranchNodeBuilder: public NodeBuilder { 00393 virtual void anchor(); 00394 const CFGBlock *DstT; 00395 const CFGBlock *DstF; 00396 00397 bool InFeasibleTrue; 00398 bool InFeasibleFalse; 00399 00400 public: 00401 BranchNodeBuilder(ExplodedNode *SrcNode, ExplodedNodeSet &DstSet, 00402 const NodeBuilderContext &C, 00403 const CFGBlock *dstT, const CFGBlock *dstF) 00404 : NodeBuilder(SrcNode, DstSet, C), DstT(dstT), DstF(dstF), 00405 InFeasibleTrue(!DstT), InFeasibleFalse(!DstF) { 00406 // The branch node builder does not generate autotransitions. 00407 // If there are no successors it means that both branches are infeasible. 00408 takeNodes(SrcNode); 00409 } 00410 00411 BranchNodeBuilder(const ExplodedNodeSet &SrcSet, ExplodedNodeSet &DstSet, 00412 const NodeBuilderContext &C, 00413 const CFGBlock *dstT, const CFGBlock *dstF) 00414 : NodeBuilder(SrcSet, DstSet, C), DstT(dstT), DstF(dstF), 00415 InFeasibleTrue(!DstT), InFeasibleFalse(!DstF) { 00416 takeNodes(SrcSet); 00417 } 00418 00419 ExplodedNode *generateNode(ProgramStateRef State, bool branch, 00420 ExplodedNode *Pred); 00421 00422 const CFGBlock *getTargetBlock(bool branch) const { 00423 return branch ? DstT : DstF; 00424 } 00425 00426 void markInfeasible(bool branch) { 00427 if (branch) 00428 InFeasibleTrue = true; 00429 else 00430 InFeasibleFalse = true; 00431 } 00432 00433 bool isFeasible(bool branch) { 00434 return branch ? !InFeasibleTrue : !InFeasibleFalse; 00435 } 00436 }; 00437 00438 class IndirectGotoNodeBuilder { 00439 CoreEngine& Eng; 00440 const CFGBlock *Src; 00441 const CFGBlock &DispatchBlock; 00442 const Expr *E; 00443 ExplodedNode *Pred; 00444 00445 public: 00446 IndirectGotoNodeBuilder(ExplodedNode *pred, const CFGBlock *src, 00447 const Expr *e, const CFGBlock *dispatch, CoreEngine* eng) 00448 : Eng(*eng), Src(src), DispatchBlock(*dispatch), E(e), Pred(pred) {} 00449 00450 class iterator { 00451 CFGBlock::const_succ_iterator I; 00452 00453 friend class IndirectGotoNodeBuilder; 00454 iterator(CFGBlock::const_succ_iterator i) : I(i) {} 00455 public: 00456 00457 iterator &operator++() { ++I; return *this; } 00458 bool operator!=(const iterator &X) const { return I != X.I; } 00459 00460 const LabelDecl *getLabel() const { 00461 return llvm::cast<LabelStmt>((*I)->getLabel())->getDecl(); 00462 } 00463 00464 const CFGBlock *getBlock() const { 00465 return *I; 00466 } 00467 }; 00468 00469 iterator begin() { return iterator(DispatchBlock.succ_begin()); } 00470 iterator end() { return iterator(DispatchBlock.succ_end()); } 00471 00472 ExplodedNode *generateNode(const iterator &I, 00473 ProgramStateRef State, 00474 bool isSink = false); 00475 00476 const Expr *getTarget() const { return E; } 00477 00478 ProgramStateRef getState() const { return Pred->State; } 00479 00480 const LocationContext *getLocationContext() const { 00481 return Pred->getLocationContext(); 00482 } 00483 }; 00484 00485 class SwitchNodeBuilder { 00486 CoreEngine& Eng; 00487 const CFGBlock *Src; 00488 const Expr *Condition; 00489 ExplodedNode *Pred; 00490 00491 public: 00492 SwitchNodeBuilder(ExplodedNode *pred, const CFGBlock *src, 00493 const Expr *condition, CoreEngine* eng) 00494 : Eng(*eng), Src(src), Condition(condition), Pred(pred) {} 00495 00496 class iterator { 00497 CFGBlock::const_succ_reverse_iterator I; 00498 00499 friend class SwitchNodeBuilder; 00500 iterator(CFGBlock::const_succ_reverse_iterator i) : I(i) {} 00501 00502 public: 00503 iterator &operator++() { ++I; return *this; } 00504 bool operator!=(const iterator &X) const { return I != X.I; } 00505 bool operator==(const iterator &X) const { return I == X.I; } 00506 00507 const CaseStmt *getCase() const { 00508 return llvm::cast<CaseStmt>((*I)->getLabel()); 00509 } 00510 00511 const CFGBlock *getBlock() const { 00512 return *I; 00513 } 00514 }; 00515 00516 iterator begin() { return iterator(Src->succ_rbegin()+1); } 00517 iterator end() { return iterator(Src->succ_rend()); } 00518 00519 const SwitchStmt *getSwitch() const { 00520 return llvm::cast<SwitchStmt>(Src->getTerminator()); 00521 } 00522 00523 ExplodedNode *generateCaseStmtNode(const iterator &I, 00524 ProgramStateRef State); 00525 00526 ExplodedNode *generateDefaultCaseNode(ProgramStateRef State, 00527 bool isSink = false); 00528 00529 const Expr *getCondition() const { return Condition; } 00530 00531 ProgramStateRef getState() const { return Pred->State; } 00532 00533 const LocationContext *getLocationContext() const { 00534 return Pred->getLocationContext(); 00535 } 00536 }; 00537 00538 } // end ento namespace 00539 } // end clang namespace 00540 00541 #endif