clang API Documentation
00001 //=-- ExplodedGraph.h - Local, Path-Sens. "Exploded Graph" -*- 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 the template classes ExplodedNode and ExplodedGraph, 00011 // which represent a path-sensitive, intra-procedural "exploded graph." 00012 // See "Precise interprocedural dataflow analysis via graph reachability" 00013 // by Reps, Horwitz, and Sagiv 00014 // (http://portal.acm.org/citation.cfm?id=199462) for the definition of an 00015 // exploded graph. 00016 // 00017 //===----------------------------------------------------------------------===// 00018 00019 #ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_EXPLODEDGRAPH_H 00020 #define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_EXPLODEDGRAPH_H 00021 00022 #include "clang/AST/Decl.h" 00023 #include "clang/Analysis/AnalysisContext.h" 00024 #include "clang/Analysis/ProgramPoint.h" 00025 #include "clang/Analysis/Support/BumpVector.h" 00026 #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h" 00027 #include "llvm/ADT/DepthFirstIterator.h" 00028 #include "llvm/ADT/FoldingSet.h" 00029 #include "llvm/ADT/GraphTraits.h" 00030 #include "llvm/ADT/SmallPtrSet.h" 00031 #include "llvm/ADT/SmallVector.h" 00032 #include "llvm/Support/Allocator.h" 00033 #include "llvm/Support/Casting.h" 00034 #include <memory> 00035 #include <vector> 00036 00037 namespace clang { 00038 00039 class CFG; 00040 00041 namespace ento { 00042 00043 class ExplodedGraph; 00044 00045 //===----------------------------------------------------------------------===// 00046 // ExplodedGraph "implementation" classes. These classes are not typed to 00047 // contain a specific kind of state. Typed-specialized versions are defined 00048 // on top of these classes. 00049 //===----------------------------------------------------------------------===// 00050 00051 // ExplodedNode is not constified all over the engine because we need to add 00052 // successors to it at any time after creating it. 00053 00054 class ExplodedNode : public llvm::FoldingSetNode { 00055 friend class ExplodedGraph; 00056 friend class CoreEngine; 00057 friend class NodeBuilder; 00058 friend class BranchNodeBuilder; 00059 friend class IndirectGotoNodeBuilder; 00060 friend class SwitchNodeBuilder; 00061 friend class EndOfFunctionNodeBuilder; 00062 00063 /// Efficiently stores a list of ExplodedNodes, or an optional flag. 00064 /// 00065 /// NodeGroup provides opaque storage for a list of ExplodedNodes, optimizing 00066 /// for the case when there is only one node in the group. This is a fairly 00067 /// common case in an ExplodedGraph, where most nodes have only one 00068 /// predecessor and many have only one successor. It can also be used to 00069 /// store a flag rather than a node list, which ExplodedNode uses to mark 00070 /// whether a node is a sink. If the flag is set, the group is implicitly 00071 /// empty and no nodes may be added. 00072 class NodeGroup { 00073 // Conceptually a discriminated union. If the low bit is set, the node is 00074 // a sink. If the low bit is not set, the pointer refers to the storage 00075 // for the nodes in the group. 00076 // This is not a PointerIntPair in order to keep the storage type opaque. 00077 uintptr_t P; 00078 00079 public: 00080 NodeGroup(bool Flag = false) : P(Flag) { 00081 assert(getFlag() == Flag); 00082 } 00083 00084 ExplodedNode * const *begin() const; 00085 00086 ExplodedNode * const *end() const; 00087 00088 unsigned size() const; 00089 00090 bool empty() const { return P == 0 || getFlag() != 0; } 00091 00092 /// Adds a node to the list. 00093 /// 00094 /// The group must not have been created with its flag set. 00095 void addNode(ExplodedNode *N, ExplodedGraph &G); 00096 00097 /// Replaces the single node in this group with a new node. 00098 /// 00099 /// Note that this should only be used when you know the group was not 00100 /// created with its flag set, and that the group is empty or contains 00101 /// only a single node. 00102 void replaceNode(ExplodedNode *node); 00103 00104 /// Returns whether this group was created with its flag set. 00105 bool getFlag() const { 00106 return (P & 1); 00107 } 00108 }; 00109 00110 /// Location - The program location (within a function body) associated 00111 /// with this node. 00112 const ProgramPoint Location; 00113 00114 /// State - The state associated with this node. 00115 ProgramStateRef State; 00116 00117 /// Preds - The predecessors of this node. 00118 NodeGroup Preds; 00119 00120 /// Succs - The successors of this node. 00121 NodeGroup Succs; 00122 00123 public: 00124 00125 explicit ExplodedNode(const ProgramPoint &loc, ProgramStateRef state, 00126 bool IsSink) 00127 : Location(loc), State(state), Succs(IsSink) { 00128 assert(isSink() == IsSink); 00129 } 00130 00131 ~ExplodedNode() {} 00132 00133 /// getLocation - Returns the edge associated with the given node. 00134 ProgramPoint getLocation() const { return Location; } 00135 00136 const LocationContext *getLocationContext() const { 00137 return getLocation().getLocationContext(); 00138 } 00139 00140 const StackFrameContext *getStackFrame() const { 00141 return getLocationContext()->getCurrentStackFrame(); 00142 } 00143 00144 const Decl &getCodeDecl() const { return *getLocationContext()->getDecl(); } 00145 00146 CFG &getCFG() const { return *getLocationContext()->getCFG(); } 00147 00148 ParentMap &getParentMap() const {return getLocationContext()->getParentMap();} 00149 00150 template <typename T> 00151 T &getAnalysis() const { 00152 return *getLocationContext()->getAnalysis<T>(); 00153 } 00154 00155 const ProgramStateRef &getState() const { return State; } 00156 00157 template <typename T> 00158 Optional<T> getLocationAs() const LLVM_LVALUE_FUNCTION { 00159 return Location.getAs<T>(); 00160 } 00161 00162 static void Profile(llvm::FoldingSetNodeID &ID, 00163 const ProgramPoint &Loc, 00164 const ProgramStateRef &state, 00165 bool IsSink) { 00166 ID.Add(Loc); 00167 ID.AddPointer(state.get()); 00168 ID.AddBoolean(IsSink); 00169 } 00170 00171 void Profile(llvm::FoldingSetNodeID& ID) const { 00172 // We avoid copy constructors by not using accessors. 00173 Profile(ID, Location, State, isSink()); 00174 } 00175 00176 /// addPredeccessor - Adds a predecessor to the current node, and 00177 /// in tandem add this node as a successor of the other node. 00178 void addPredecessor(ExplodedNode *V, ExplodedGraph &G); 00179 00180 unsigned succ_size() const { return Succs.size(); } 00181 unsigned pred_size() const { return Preds.size(); } 00182 bool succ_empty() const { return Succs.empty(); } 00183 bool pred_empty() const { return Preds.empty(); } 00184 00185 bool isSink() const { return Succs.getFlag(); } 00186 00187 bool hasSinglePred() const { 00188 return (pred_size() == 1); 00189 } 00190 00191 ExplodedNode *getFirstPred() { 00192 return pred_empty() ? nullptr : *(pred_begin()); 00193 } 00194 00195 const ExplodedNode *getFirstPred() const { 00196 return const_cast<ExplodedNode*>(this)->getFirstPred(); 00197 } 00198 00199 const ExplodedNode *getFirstSucc() const { 00200 return succ_empty() ? nullptr : *(succ_begin()); 00201 } 00202 00203 // Iterators over successor and predecessor vertices. 00204 typedef ExplodedNode* const * succ_iterator; 00205 typedef const ExplodedNode* const * const_succ_iterator; 00206 typedef ExplodedNode* const * pred_iterator; 00207 typedef const ExplodedNode* const * const_pred_iterator; 00208 00209 pred_iterator pred_begin() { return Preds.begin(); } 00210 pred_iterator pred_end() { return Preds.end(); } 00211 00212 const_pred_iterator pred_begin() const { 00213 return const_cast<ExplodedNode*>(this)->pred_begin(); 00214 } 00215 const_pred_iterator pred_end() const { 00216 return const_cast<ExplodedNode*>(this)->pred_end(); 00217 } 00218 00219 succ_iterator succ_begin() { return Succs.begin(); } 00220 succ_iterator succ_end() { return Succs.end(); } 00221 00222 const_succ_iterator succ_begin() const { 00223 return const_cast<ExplodedNode*>(this)->succ_begin(); 00224 } 00225 const_succ_iterator succ_end() const { 00226 return const_cast<ExplodedNode*>(this)->succ_end(); 00227 } 00228 00229 // For debugging. 00230 00231 public: 00232 00233 class Auditor { 00234 public: 00235 virtual ~Auditor(); 00236 virtual void AddEdge(ExplodedNode *Src, ExplodedNode *Dst) = 0; 00237 }; 00238 00239 static void SetAuditor(Auditor* A); 00240 00241 private: 00242 void replaceSuccessor(ExplodedNode *node) { Succs.replaceNode(node); } 00243 void replacePredecessor(ExplodedNode *node) { Preds.replaceNode(node); } 00244 }; 00245 00246 typedef llvm::DenseMap<const ExplodedNode *, const ExplodedNode *> 00247 InterExplodedGraphMap; 00248 00249 class ExplodedGraph { 00250 protected: 00251 friend class CoreEngine; 00252 00253 // Type definitions. 00254 typedef std::vector<ExplodedNode *> NodeVector; 00255 00256 /// The roots of the simulation graph. Usually there will be only 00257 /// one, but clients are free to establish multiple subgraphs within a single 00258 /// SimulGraph. Moreover, these subgraphs can often merge when paths from 00259 /// different roots reach the same state at the same program location. 00260 NodeVector Roots; 00261 00262 /// The nodes in the simulation graph which have been 00263 /// specially marked as the endpoint of an abstract simulation path. 00264 NodeVector EndNodes; 00265 00266 /// Nodes - The nodes in the graph. 00267 llvm::FoldingSet<ExplodedNode> Nodes; 00268 00269 /// BVC - Allocator and context for allocating nodes and their predecessor 00270 /// and successor groups. 00271 BumpVectorContext BVC; 00272 00273 /// NumNodes - The number of nodes in the graph. 00274 unsigned NumNodes; 00275 00276 /// A list of recently allocated nodes that can potentially be recycled. 00277 NodeVector ChangedNodes; 00278 00279 /// A list of nodes that can be reused. 00280 NodeVector FreeNodes; 00281 00282 /// Determines how often nodes are reclaimed. 00283 /// 00284 /// If this is 0, nodes will never be reclaimed. 00285 unsigned ReclaimNodeInterval; 00286 00287 /// Counter to determine when to reclaim nodes. 00288 unsigned ReclaimCounter; 00289 00290 public: 00291 00292 /// \brief Retrieve the node associated with a (Location,State) pair, 00293 /// where the 'Location' is a ProgramPoint in the CFG. If no node for 00294 /// this pair exists, it is created. IsNew is set to true if 00295 /// the node was freshly created. 00296 ExplodedNode *getNode(const ProgramPoint &L, ProgramStateRef State, 00297 bool IsSink = false, 00298 bool* IsNew = nullptr); 00299 00300 std::unique_ptr<ExplodedGraph> MakeEmptyGraph() const { 00301 return llvm::make_unique<ExplodedGraph>(); 00302 } 00303 00304 /// addRoot - Add an untyped node to the set of roots. 00305 ExplodedNode *addRoot(ExplodedNode *V) { 00306 Roots.push_back(V); 00307 return V; 00308 } 00309 00310 /// addEndOfPath - Add an untyped node to the set of EOP nodes. 00311 ExplodedNode *addEndOfPath(ExplodedNode *V) { 00312 EndNodes.push_back(V); 00313 return V; 00314 } 00315 00316 ExplodedGraph(); 00317 00318 ~ExplodedGraph(); 00319 00320 unsigned num_roots() const { return Roots.size(); } 00321 unsigned num_eops() const { return EndNodes.size(); } 00322 00323 bool empty() const { return NumNodes == 0; } 00324 unsigned size() const { return NumNodes; } 00325 00326 // Iterators. 00327 typedef ExplodedNode NodeTy; 00328 typedef llvm::FoldingSet<ExplodedNode> AllNodesTy; 00329 typedef NodeVector::iterator roots_iterator; 00330 typedef NodeVector::const_iterator const_roots_iterator; 00331 typedef NodeVector::iterator eop_iterator; 00332 typedef NodeVector::const_iterator const_eop_iterator; 00333 typedef AllNodesTy::iterator node_iterator; 00334 typedef AllNodesTy::const_iterator const_node_iterator; 00335 00336 node_iterator nodes_begin() { return Nodes.begin(); } 00337 00338 node_iterator nodes_end() { return Nodes.end(); } 00339 00340 const_node_iterator nodes_begin() const { return Nodes.begin(); } 00341 00342 const_node_iterator nodes_end() const { return Nodes.end(); } 00343 00344 roots_iterator roots_begin() { return Roots.begin(); } 00345 00346 roots_iterator roots_end() { return Roots.end(); } 00347 00348 const_roots_iterator roots_begin() const { return Roots.begin(); } 00349 00350 const_roots_iterator roots_end() const { return Roots.end(); } 00351 00352 eop_iterator eop_begin() { return EndNodes.begin(); } 00353 00354 eop_iterator eop_end() { return EndNodes.end(); } 00355 00356 const_eop_iterator eop_begin() const { return EndNodes.begin(); } 00357 00358 const_eop_iterator eop_end() const { return EndNodes.end(); } 00359 00360 llvm::BumpPtrAllocator & getAllocator() { return BVC.getAllocator(); } 00361 BumpVectorContext &getNodeAllocator() { return BVC; } 00362 00363 typedef llvm::DenseMap<const ExplodedNode*, ExplodedNode*> NodeMap; 00364 00365 /// Creates a trimmed version of the graph that only contains paths leading 00366 /// to the given nodes. 00367 /// 00368 /// \param Nodes The nodes which must appear in the final graph. Presumably 00369 /// these are end-of-path nodes (i.e. they have no successors). 00370 /// \param[out] ForwardMap A optional map from nodes in this graph to nodes in 00371 /// the returned graph. 00372 /// \param[out] InverseMap An optional map from nodes in the returned graph to 00373 /// nodes in this graph. 00374 /// \returns The trimmed graph 00375 std::unique_ptr<ExplodedGraph> 00376 trim(ArrayRef<const NodeTy *> Nodes, 00377 InterExplodedGraphMap *ForwardMap = nullptr, 00378 InterExplodedGraphMap *InverseMap = nullptr) const; 00379 00380 /// Enable tracking of recently allocated nodes for potential reclamation 00381 /// when calling reclaimRecentlyAllocatedNodes(). 00382 void enableNodeReclamation(unsigned Interval) { 00383 ReclaimCounter = ReclaimNodeInterval = Interval; 00384 } 00385 00386 /// Reclaim "uninteresting" nodes created since the last time this method 00387 /// was called. 00388 void reclaimRecentlyAllocatedNodes(); 00389 00390 /// \brief Returns true if nodes for the given expression kind are always 00391 /// kept around. 00392 static bool isInterestingLValueExpr(const Expr *Ex); 00393 00394 private: 00395 bool shouldCollect(const ExplodedNode *node); 00396 void collectNode(ExplodedNode *node); 00397 }; 00398 00399 class ExplodedNodeSet { 00400 typedef llvm::SmallPtrSet<ExplodedNode*,5> ImplTy; 00401 ImplTy Impl; 00402 00403 public: 00404 ExplodedNodeSet(ExplodedNode *N) { 00405 assert (N && !static_cast<ExplodedNode*>(N)->isSink()); 00406 Impl.insert(N); 00407 } 00408 00409 ExplodedNodeSet() {} 00410 00411 inline void Add(ExplodedNode *N) { 00412 if (N && !static_cast<ExplodedNode*>(N)->isSink()) Impl.insert(N); 00413 } 00414 00415 typedef ImplTy::iterator iterator; 00416 typedef ImplTy::const_iterator const_iterator; 00417 00418 unsigned size() const { return Impl.size(); } 00419 bool empty() const { return Impl.empty(); } 00420 bool erase(ExplodedNode *N) { return Impl.erase(N); } 00421 00422 void clear() { Impl.clear(); } 00423 void insert(const ExplodedNodeSet &S) { 00424 assert(&S != this); 00425 if (empty()) 00426 Impl = S.Impl; 00427 else 00428 Impl.insert(S.begin(), S.end()); 00429 } 00430 00431 inline iterator begin() { return Impl.begin(); } 00432 inline iterator end() { return Impl.end(); } 00433 00434 inline const_iterator begin() const { return Impl.begin(); } 00435 inline const_iterator end() const { return Impl.end(); } 00436 }; 00437 00438 } // end GR namespace 00439 00440 } // end clang namespace 00441 00442 // GraphTraits 00443 00444 namespace llvm { 00445 template<> struct GraphTraits<clang::ento::ExplodedNode*> { 00446 typedef clang::ento::ExplodedNode NodeType; 00447 typedef NodeType::succ_iterator ChildIteratorType; 00448 typedef llvm::df_iterator<NodeType*> nodes_iterator; 00449 00450 static inline NodeType* getEntryNode(NodeType* N) { 00451 return N; 00452 } 00453 00454 static inline ChildIteratorType child_begin(NodeType* N) { 00455 return N->succ_begin(); 00456 } 00457 00458 static inline ChildIteratorType child_end(NodeType* N) { 00459 return N->succ_end(); 00460 } 00461 00462 static inline nodes_iterator nodes_begin(NodeType* N) { 00463 return df_begin(N); 00464 } 00465 00466 static inline nodes_iterator nodes_end(NodeType* N) { 00467 return df_end(N); 00468 } 00469 }; 00470 00471 template<> struct GraphTraits<const clang::ento::ExplodedNode*> { 00472 typedef const clang::ento::ExplodedNode NodeType; 00473 typedef NodeType::const_succ_iterator ChildIteratorType; 00474 typedef llvm::df_iterator<NodeType*> nodes_iterator; 00475 00476 static inline NodeType* getEntryNode(NodeType* N) { 00477 return N; 00478 } 00479 00480 static inline ChildIteratorType child_begin(NodeType* N) { 00481 return N->succ_begin(); 00482 } 00483 00484 static inline ChildIteratorType child_end(NodeType* N) { 00485 return N->succ_end(); 00486 } 00487 00488 static inline nodes_iterator nodes_begin(NodeType* N) { 00489 return df_begin(N); 00490 } 00491 00492 static inline nodes_iterator nodes_end(NodeType* N) { 00493 return df_end(N); 00494 } 00495 }; 00496 00497 } // end llvm namespace 00498 00499 #endif