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_GR_EXPLODEDGRAPH 00020 #define LLVM_CLANG_GR_EXPLODEDGRAPH 00021 00022 #include "clang/Analysis/ProgramPoint.h" 00023 #include "clang/Analysis/AnalysisContext.h" 00024 #include "clang/AST/Decl.h" 00025 #include "llvm/ADT/SmallVector.h" 00026 #include "llvm/ADT/FoldingSet.h" 00027 #include "llvm/ADT/SmallPtrSet.h" 00028 #include "llvm/Support/Allocator.h" 00029 #include "llvm/ADT/OwningPtr.h" 00030 #include "llvm/ADT/GraphTraits.h" 00031 #include "llvm/ADT/DepthFirstIterator.h" 00032 #include "llvm/Support/Casting.h" 00033 #include "clang/Analysis/Support/BumpVector.h" 00034 #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h" 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 class NodeGroup { 00064 enum { Size1 = 0x0, SizeOther = 0x1, AuxFlag = 0x2, Mask = 0x3 }; 00065 uintptr_t P; 00066 00067 unsigned getKind() const { 00068 return P & 0x1; 00069 } 00070 00071 void *getPtr() const { 00072 assert (!getFlag()); 00073 return reinterpret_cast<void*>(P & ~Mask); 00074 } 00075 00076 ExplodedNode *getNode() const { 00077 return reinterpret_cast<ExplodedNode*>(getPtr()); 00078 } 00079 00080 public: 00081 NodeGroup() : P(0) {} 00082 00083 ExplodedNode **begin() const; 00084 00085 ExplodedNode **end() const; 00086 00087 unsigned size() const; 00088 00089 bool empty() const { return (P & ~Mask) == 0; } 00090 00091 void addNode(ExplodedNode *N, ExplodedGraph &G); 00092 00093 void replaceNode(ExplodedNode *node); 00094 00095 void setFlag() { 00096 assert(P == 0); 00097 P = AuxFlag; 00098 } 00099 00100 bool getFlag() const { 00101 return P & AuxFlag ? true : false; 00102 } 00103 }; 00104 00105 /// Location - The program location (within a function body) associated 00106 /// with this node. 00107 const ProgramPoint Location; 00108 00109 /// State - The state associated with this node. 00110 ProgramStateRef State; 00111 00112 /// Preds - The predecessors of this node. 00113 NodeGroup Preds; 00114 00115 /// Succs - The successors of this node. 00116 NodeGroup Succs; 00117 00118 public: 00119 00120 explicit ExplodedNode(const ProgramPoint &loc, ProgramStateRef state, 00121 bool IsSink) 00122 : Location(loc), State(state) { 00123 if (IsSink) 00124 Succs.setFlag(); 00125 } 00126 00127 ~ExplodedNode() {} 00128 00129 /// getLocation - Returns the edge associated with the given node. 00130 ProgramPoint getLocation() const { return Location; } 00131 00132 const LocationContext *getLocationContext() const { 00133 return getLocation().getLocationContext(); 00134 } 00135 00136 const Decl &getCodeDecl() const { return *getLocationContext()->getDecl(); } 00137 00138 CFG &getCFG() const { return *getLocationContext()->getCFG(); } 00139 00140 ParentMap &getParentMap() const {return getLocationContext()->getParentMap();} 00141 00142 template <typename T> 00143 T &getAnalysis() const { 00144 return *getLocationContext()->getAnalysis<T>(); 00145 } 00146 00147 ProgramStateRef getState() const { return State; } 00148 00149 template <typename T> 00150 const T* getLocationAs() const { return llvm::dyn_cast<T>(&Location); } 00151 00152 static void Profile(llvm::FoldingSetNodeID &ID, 00153 const ProgramPoint &Loc, 00154 ProgramStateRef state, 00155 bool IsSink) { 00156 ID.Add(Loc); 00157 ID.AddPointer(state.getPtr()); 00158 ID.AddBoolean(IsSink); 00159 } 00160 00161 void Profile(llvm::FoldingSetNodeID& ID) const { 00162 Profile(ID, getLocation(), getState(), isSink()); 00163 } 00164 00165 /// addPredeccessor - Adds a predecessor to the current node, and 00166 /// in tandem add this node as a successor of the other node. 00167 void addPredecessor(ExplodedNode *V, ExplodedGraph &G); 00168 00169 unsigned succ_size() const { return Succs.size(); } 00170 unsigned pred_size() const { return Preds.size(); } 00171 bool succ_empty() const { return Succs.empty(); } 00172 bool pred_empty() const { return Preds.empty(); } 00173 00174 bool isSink() const { return Succs.getFlag(); } 00175 00176 bool hasSinglePred() const { 00177 return (pred_size() == 1); 00178 } 00179 00180 ExplodedNode *getFirstPred() { 00181 return pred_empty() ? NULL : *(pred_begin()); 00182 } 00183 00184 const ExplodedNode *getFirstPred() const { 00185 return const_cast<ExplodedNode*>(this)->getFirstPred(); 00186 } 00187 00188 // Iterators over successor and predecessor vertices. 00189 typedef ExplodedNode** succ_iterator; 00190 typedef const ExplodedNode* const * const_succ_iterator; 00191 typedef ExplodedNode** pred_iterator; 00192 typedef const ExplodedNode* const * const_pred_iterator; 00193 00194 pred_iterator pred_begin() { return Preds.begin(); } 00195 pred_iterator pred_end() { return Preds.end(); } 00196 00197 const_pred_iterator pred_begin() const { 00198 return const_cast<ExplodedNode*>(this)->pred_begin(); 00199 } 00200 const_pred_iterator pred_end() const { 00201 return const_cast<ExplodedNode*>(this)->pred_end(); 00202 } 00203 00204 succ_iterator succ_begin() { return Succs.begin(); } 00205 succ_iterator succ_end() { return Succs.end(); } 00206 00207 const_succ_iterator succ_begin() const { 00208 return const_cast<ExplodedNode*>(this)->succ_begin(); 00209 } 00210 const_succ_iterator succ_end() const { 00211 return const_cast<ExplodedNode*>(this)->succ_end(); 00212 } 00213 00214 // For debugging. 00215 00216 public: 00217 00218 class Auditor { 00219 public: 00220 virtual ~Auditor(); 00221 virtual void AddEdge(ExplodedNode *Src, ExplodedNode *Dst) = 0; 00222 }; 00223 00224 static void SetAuditor(Auditor* A); 00225 00226 private: 00227 void replaceSuccessor(ExplodedNode *node) { Succs.replaceNode(node); } 00228 void replacePredecessor(ExplodedNode *node) { Preds.replaceNode(node); } 00229 }; 00230 00231 // FIXME: Is this class necessary? 00232 class InterExplodedGraphMap { 00233 virtual void anchor(); 00234 llvm::DenseMap<const ExplodedNode*, ExplodedNode*> M; 00235 friend class ExplodedGraph; 00236 00237 public: 00238 ExplodedNode *getMappedNode(const ExplodedNode *N) const; 00239 00240 InterExplodedGraphMap() {} 00241 virtual ~InterExplodedGraphMap() {} 00242 }; 00243 00244 class ExplodedGraph { 00245 protected: 00246 friend class CoreEngine; 00247 00248 // Type definitions. 00249 typedef std::vector<ExplodedNode *> NodeVector; 00250 00251 /// The roots of the simulation graph. Usually there will be only 00252 /// one, but clients are free to establish multiple subgraphs within a single 00253 /// SimulGraph. Moreover, these subgraphs can often merge when paths from 00254 /// different roots reach the same state at the same program location. 00255 NodeVector Roots; 00256 00257 /// The nodes in the simulation graph which have been 00258 /// specially marked as the endpoint of an abstract simulation path. 00259 NodeVector EndNodes; 00260 00261 /// Nodes - The nodes in the graph. 00262 llvm::FoldingSet<ExplodedNode> Nodes; 00263 00264 /// BVC - Allocator and context for allocating nodes and their predecessor 00265 /// and successor groups. 00266 BumpVectorContext BVC; 00267 00268 /// NumNodes - The number of nodes in the graph. 00269 unsigned NumNodes; 00270 00271 /// A list of recently allocated nodes that can potentially be recycled. 00272 NodeVector ChangedNodes; 00273 00274 /// A list of nodes that can be reused. 00275 NodeVector FreeNodes; 00276 00277 /// A flag that indicates whether nodes should be recycled. 00278 bool reclaimNodes; 00279 00280 /// Counter to determine when to reclaim nodes. 00281 unsigned reclaimCounter; 00282 00283 public: 00284 00285 /// \brief Retrieve the node associated with a (Location,State) pair, 00286 /// where the 'Location' is a ProgramPoint in the CFG. If no node for 00287 /// this pair exists, it is created. IsNew is set to true if 00288 /// the node was freshly created. 00289 ExplodedNode *getNode(const ProgramPoint &L, ProgramStateRef State, 00290 bool IsSink = false, 00291 bool* IsNew = 0); 00292 00293 ExplodedGraph* MakeEmptyGraph() const { 00294 return new ExplodedGraph(); 00295 } 00296 00297 /// addRoot - Add an untyped node to the set of roots. 00298 ExplodedNode *addRoot(ExplodedNode *V) { 00299 Roots.push_back(V); 00300 return V; 00301 } 00302 00303 /// addEndOfPath - Add an untyped node to the set of EOP nodes. 00304 ExplodedNode *addEndOfPath(ExplodedNode *V) { 00305 EndNodes.push_back(V); 00306 return V; 00307 } 00308 00309 ExplodedGraph(); 00310 00311 ~ExplodedGraph(); 00312 00313 unsigned num_roots() const { return Roots.size(); } 00314 unsigned num_eops() const { return EndNodes.size(); } 00315 00316 bool empty() const { return NumNodes == 0; } 00317 unsigned size() const { return NumNodes; } 00318 00319 // Iterators. 00320 typedef ExplodedNode NodeTy; 00321 typedef llvm::FoldingSet<ExplodedNode> AllNodesTy; 00322 typedef NodeVector::iterator roots_iterator; 00323 typedef NodeVector::const_iterator const_roots_iterator; 00324 typedef NodeVector::iterator eop_iterator; 00325 typedef NodeVector::const_iterator const_eop_iterator; 00326 typedef AllNodesTy::iterator node_iterator; 00327 typedef AllNodesTy::const_iterator const_node_iterator; 00328 00329 node_iterator nodes_begin() { return Nodes.begin(); } 00330 00331 node_iterator nodes_end() { return Nodes.end(); } 00332 00333 const_node_iterator nodes_begin() const { return Nodes.begin(); } 00334 00335 const_node_iterator nodes_end() const { return Nodes.end(); } 00336 00337 roots_iterator roots_begin() { return Roots.begin(); } 00338 00339 roots_iterator roots_end() { return Roots.end(); } 00340 00341 const_roots_iterator roots_begin() const { return Roots.begin(); } 00342 00343 const_roots_iterator roots_end() const { return Roots.end(); } 00344 00345 eop_iterator eop_begin() { return EndNodes.begin(); } 00346 00347 eop_iterator eop_end() { return EndNodes.end(); } 00348 00349 const_eop_iterator eop_begin() const { return EndNodes.begin(); } 00350 00351 const_eop_iterator eop_end() const { return EndNodes.end(); } 00352 00353 llvm::BumpPtrAllocator & getAllocator() { return BVC.getAllocator(); } 00354 BumpVectorContext &getNodeAllocator() { return BVC; } 00355 00356 typedef llvm::DenseMap<const ExplodedNode*, ExplodedNode*> NodeMap; 00357 00358 std::pair<ExplodedGraph*, InterExplodedGraphMap*> 00359 Trim(const NodeTy* const* NBeg, const NodeTy* const* NEnd, 00360 llvm::DenseMap<const void*, const void*> *InverseMap = 0) const; 00361 00362 ExplodedGraph* TrimInternal(const ExplodedNode* const * NBeg, 00363 const ExplodedNode* const * NEnd, 00364 InterExplodedGraphMap *M, 00365 llvm::DenseMap<const void*, const void*> *InverseMap) const; 00366 00367 /// Enable tracking of recently allocated nodes for potential reclamation 00368 /// when calling reclaimRecentlyAllocatedNodes(). 00369 void enableNodeReclamation() { reclaimNodes = true; } 00370 00371 /// Reclaim "uninteresting" nodes created since the last time this method 00372 /// was called. 00373 void reclaimRecentlyAllocatedNodes(); 00374 00375 private: 00376 bool shouldCollect(const ExplodedNode *node); 00377 void collectNode(ExplodedNode *node); 00378 }; 00379 00380 class ExplodedNodeSet { 00381 typedef llvm::SmallPtrSet<ExplodedNode*,5> ImplTy; 00382 ImplTy Impl; 00383 00384 public: 00385 ExplodedNodeSet(ExplodedNode *N) { 00386 assert (N && !static_cast<ExplodedNode*>(N)->isSink()); 00387 Impl.insert(N); 00388 } 00389 00390 ExplodedNodeSet() {} 00391 00392 inline void Add(ExplodedNode *N) { 00393 if (N && !static_cast<ExplodedNode*>(N)->isSink()) Impl.insert(N); 00394 } 00395 00396 typedef ImplTy::iterator iterator; 00397 typedef ImplTy::const_iterator const_iterator; 00398 00399 unsigned size() const { return Impl.size(); } 00400 bool empty() const { return Impl.empty(); } 00401 bool erase(ExplodedNode *N) { return Impl.erase(N); } 00402 00403 void clear() { Impl.clear(); } 00404 void insert(const ExplodedNodeSet &S) { 00405 assert(&S != this); 00406 if (empty()) 00407 Impl = S.Impl; 00408 else 00409 Impl.insert(S.begin(), S.end()); 00410 } 00411 00412 inline iterator begin() { return Impl.begin(); } 00413 inline iterator end() { return Impl.end(); } 00414 00415 inline const_iterator begin() const { return Impl.begin(); } 00416 inline const_iterator end() const { return Impl.end(); } 00417 }; 00418 00419 } // end GR namespace 00420 00421 } // end clang namespace 00422 00423 // GraphTraits 00424 00425 namespace llvm { 00426 template<> struct GraphTraits<clang::ento::ExplodedNode*> { 00427 typedef clang::ento::ExplodedNode NodeType; 00428 typedef NodeType::succ_iterator ChildIteratorType; 00429 typedef llvm::df_iterator<NodeType*> nodes_iterator; 00430 00431 static inline NodeType* getEntryNode(NodeType* N) { 00432 return N; 00433 } 00434 00435 static inline ChildIteratorType child_begin(NodeType* N) { 00436 return N->succ_begin(); 00437 } 00438 00439 static inline ChildIteratorType child_end(NodeType* N) { 00440 return N->succ_end(); 00441 } 00442 00443 static inline nodes_iterator nodes_begin(NodeType* N) { 00444 return df_begin(N); 00445 } 00446 00447 static inline nodes_iterator nodes_end(NodeType* N) { 00448 return df_end(N); 00449 } 00450 }; 00451 00452 template<> struct GraphTraits<const clang::ento::ExplodedNode*> { 00453 typedef const clang::ento::ExplodedNode NodeType; 00454 typedef NodeType::const_succ_iterator ChildIteratorType; 00455 typedef llvm::df_iterator<NodeType*> nodes_iterator; 00456 00457 static inline NodeType* getEntryNode(NodeType* N) { 00458 return N; 00459 } 00460 00461 static inline ChildIteratorType child_begin(NodeType* N) { 00462 return N->succ_begin(); 00463 } 00464 00465 static inline ChildIteratorType child_end(NodeType* N) { 00466 return N->succ_end(); 00467 } 00468 00469 static inline nodes_iterator nodes_begin(NodeType* N) { 00470 return df_begin(N); 00471 } 00472 00473 static inline nodes_iterator nodes_end(NodeType* N) { 00474 return df_end(N); 00475 } 00476 }; 00477 00478 } // end llvm namespace 00479 00480 #endif