clang API Documentation
00001 //== CallGraph.h - AST-based Call 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 declares the AST-based CallGraph. 00011 // 00012 // A call graph for functions whose definitions/bodies are available in the 00013 // current translation unit. The graph has a "virtual" root node that contains 00014 // edges to all externally available functions. 00015 //===----------------------------------------------------------------------===// 00016 00017 #ifndef LLVM_CLANG_ANALYSIS_CALLGRAPH_H 00018 #define LLVM_CLANG_ANALYSIS_CALLGRAPH_H 00019 00020 #include "clang/AST/DeclBase.h" 00021 #include "clang/AST/RecursiveASTVisitor.h" 00022 #include "llvm/ADT/DenseMap.h" 00023 #include "llvm/ADT/GraphTraits.h" 00024 #include "llvm/ADT/SetVector.h" 00025 00026 namespace clang { 00027 class CallGraphNode; 00028 00029 /// \brief The AST-based call graph. 00030 /// 00031 /// The call graph extends itself with the given declarations by implementing 00032 /// the recursive AST visitor, which constructs the graph by visiting the given 00033 /// declarations. 00034 class CallGraph : public RecursiveASTVisitor<CallGraph> { 00035 friend class CallGraphNode; 00036 00037 typedef llvm::DenseMap<const Decl *, CallGraphNode *> FunctionMapTy; 00038 00039 /// FunctionMap owns all CallGraphNodes. 00040 FunctionMapTy FunctionMap; 00041 00042 /// This is a virtual root node that has edges to all the functions. 00043 CallGraphNode *Root; 00044 00045 public: 00046 CallGraph(); 00047 ~CallGraph(); 00048 00049 /// \brief Populate the call graph with the functions in the given 00050 /// declaration. 00051 /// 00052 /// Recursively walks the declaration to find all the dependent Decls as well. 00053 void addToCallGraph(Decl *D) { 00054 TraverseDecl(D); 00055 } 00056 00057 /// \brief Determine if a declaration should be included in the graph. 00058 static bool includeInGraph(const Decl *D); 00059 00060 /// \brief Lookup the node for the given declaration. 00061 CallGraphNode *getNode(const Decl *) const; 00062 00063 /// \brief Lookup the node for the given declaration. If none found, insert 00064 /// one into the graph. 00065 CallGraphNode *getOrInsertNode(Decl *); 00066 00067 /// Iterators through all the elements in the graph. Note, this gives 00068 /// non-deterministic order. 00069 typedef FunctionMapTy::iterator iterator; 00070 typedef FunctionMapTy::const_iterator const_iterator; 00071 iterator begin() { return FunctionMap.begin(); } 00072 iterator end() { return FunctionMap.end(); } 00073 const_iterator begin() const { return FunctionMap.begin(); } 00074 const_iterator end() const { return FunctionMap.end(); } 00075 00076 /// \brief Get the number of nodes in the graph. 00077 unsigned size() const { return FunctionMap.size(); } 00078 00079 /// \ brief Get the virtual root of the graph, all the functions available 00080 /// externally are represented as callees of the node. 00081 CallGraphNode *getRoot() const { return Root; } 00082 00083 /// Iterators through all the nodes of the graph that have no parent. These 00084 /// are the unreachable nodes, which are either unused or are due to us 00085 /// failing to add a call edge due to the analysis imprecision. 00086 typedef llvm::SetVector<CallGraphNode *>::iterator nodes_iterator; 00087 typedef llvm::SetVector<CallGraphNode *>::const_iterator const_nodes_iterator; 00088 00089 void print(raw_ostream &os) const; 00090 void dump() const; 00091 void viewGraph() const; 00092 00093 void addNodesForBlocks(DeclContext *D); 00094 00095 /// Part of recursive declaration visitation. We recursively visit all the 00096 /// declarations to collect the root functions. 00097 bool VisitFunctionDecl(FunctionDecl *FD) { 00098 // We skip function template definitions, as their semantics is 00099 // only determined when they are instantiated. 00100 if (includeInGraph(FD)) { 00101 // Add all blocks declared inside this function to the graph. 00102 addNodesForBlocks(FD); 00103 // If this function has external linkage, anything could call it. 00104 // Note, we are not precise here. For example, the function could have 00105 // its address taken. 00106 addNodeForDecl(FD, FD->isGlobal()); 00107 } 00108 return true; 00109 } 00110 00111 /// Part of recursive declaration visitation. 00112 bool VisitObjCMethodDecl(ObjCMethodDecl *MD) { 00113 if (includeInGraph(MD)) { 00114 addNodesForBlocks(MD); 00115 addNodeForDecl(MD, true); 00116 } 00117 return true; 00118 } 00119 00120 // We are only collecting the declarations, so do not step into the bodies. 00121 bool TraverseStmt(Stmt *S) { return true; } 00122 00123 bool shouldWalkTypesOfTypeLocs() const { return false; } 00124 00125 private: 00126 /// \brief Add the given declaration to the call graph. 00127 void addNodeForDecl(Decl *D, bool IsGlobal); 00128 00129 /// \brief Allocate a new node in the graph. 00130 CallGraphNode *allocateNewNode(Decl *); 00131 }; 00132 00133 class CallGraphNode { 00134 public: 00135 typedef CallGraphNode* CallRecord; 00136 00137 private: 00138 /// \brief The function/method declaration. 00139 Decl *FD; 00140 00141 /// \brief The list of functions called from this node. 00142 SmallVector<CallRecord, 5> CalledFunctions; 00143 00144 public: 00145 CallGraphNode(Decl *D) : FD(D) {} 00146 00147 typedef SmallVectorImpl<CallRecord>::iterator iterator; 00148 typedef SmallVectorImpl<CallRecord>::const_iterator const_iterator; 00149 00150 /// Iterators through all the callees/children of the node. 00151 inline iterator begin() { return CalledFunctions.begin(); } 00152 inline iterator end() { return CalledFunctions.end(); } 00153 inline const_iterator begin() const { return CalledFunctions.begin(); } 00154 inline const_iterator end() const { return CalledFunctions.end(); } 00155 00156 inline bool empty() const {return CalledFunctions.empty(); } 00157 inline unsigned size() const {return CalledFunctions.size(); } 00158 00159 void addCallee(CallGraphNode *N, CallGraph *CG) { 00160 CalledFunctions.push_back(N); 00161 } 00162 00163 Decl *getDecl() const { return FD; } 00164 00165 void print(raw_ostream &os) const; 00166 void dump() const; 00167 }; 00168 00169 } // end clang namespace 00170 00171 // Graph traits for iteration, viewing. 00172 namespace llvm { 00173 template <> struct GraphTraits<clang::CallGraphNode*> { 00174 typedef clang::CallGraphNode NodeType; 00175 typedef clang::CallGraphNode::CallRecord CallRecordTy; 00176 typedef std::pointer_to_unary_function<CallRecordTy, 00177 clang::CallGraphNode*> CGNDerefFun; 00178 static NodeType *getEntryNode(clang::CallGraphNode *CGN) { return CGN; } 00179 typedef mapped_iterator<NodeType::iterator, CGNDerefFun> ChildIteratorType; 00180 static inline ChildIteratorType child_begin(NodeType *N) { 00181 return map_iterator(N->begin(), CGNDerefFun(CGNDeref)); 00182 } 00183 static inline ChildIteratorType child_end (NodeType *N) { 00184 return map_iterator(N->end(), CGNDerefFun(CGNDeref)); 00185 } 00186 static clang::CallGraphNode *CGNDeref(CallRecordTy P) { 00187 return P; 00188 } 00189 }; 00190 00191 template <> struct GraphTraits<const clang::CallGraphNode*> { 00192 typedef const clang::CallGraphNode NodeType; 00193 typedef NodeType::const_iterator ChildIteratorType; 00194 static NodeType *getEntryNode(const clang::CallGraphNode *CGN) { return CGN; } 00195 static inline ChildIteratorType child_begin(NodeType *N) { return N->begin();} 00196 static inline ChildIteratorType child_end(NodeType *N) { return N->end(); } 00197 }; 00198 00199 template <> struct GraphTraits<clang::CallGraph*> 00200 : public GraphTraits<clang::CallGraphNode*> { 00201 00202 static NodeType *getEntryNode(clang::CallGraph *CGN) { 00203 return CGN->getRoot(); // Start at the external node! 00204 } 00205 typedef std::pair<const clang::Decl*, clang::CallGraphNode*> PairTy; 00206 typedef std::pointer_to_unary_function<PairTy, clang::CallGraphNode&> DerefFun; 00207 // nodes_iterator/begin/end - Allow iteration over all nodes in the graph 00208 typedef mapped_iterator<clang::CallGraph::iterator, DerefFun> nodes_iterator; 00209 00210 static nodes_iterator nodes_begin(clang::CallGraph *CG) { 00211 return map_iterator(CG->begin(), DerefFun(CGdereference)); 00212 } 00213 static nodes_iterator nodes_end (clang::CallGraph *CG) { 00214 return map_iterator(CG->end(), DerefFun(CGdereference)); 00215 } 00216 static clang::CallGraphNode &CGdereference(PairTy P) { 00217 return *(P.second); 00218 } 00219 00220 static unsigned size(clang::CallGraph *CG) { 00221 return CG->size(); 00222 } 00223 }; 00224 00225 template <> struct GraphTraits<const clang::CallGraph*> : 00226 public GraphTraits<const clang::CallGraphNode*> { 00227 static NodeType *getEntryNode(const clang::CallGraph *CGN) { 00228 return CGN->getRoot(); 00229 } 00230 typedef std::pair<const clang::Decl*, clang::CallGraphNode*> PairTy; 00231 typedef std::pointer_to_unary_function<PairTy, clang::CallGraphNode&> DerefFun; 00232 // nodes_iterator/begin/end - Allow iteration over all nodes in the graph 00233 typedef mapped_iterator<clang::CallGraph::const_iterator, 00234 DerefFun> nodes_iterator; 00235 00236 static nodes_iterator nodes_begin(const clang::CallGraph *CG) { 00237 return map_iterator(CG->begin(), DerefFun(CGdereference)); 00238 } 00239 static nodes_iterator nodes_end(const clang::CallGraph *CG) { 00240 return map_iterator(CG->end(), DerefFun(CGdereference)); 00241 } 00242 static clang::CallGraphNode &CGdereference(PairTy P) { 00243 return *(P.second); 00244 } 00245 00246 static unsigned size(const clang::CallGraph *CG) { 00247 return CG->size(); 00248 } 00249 }; 00250 00251 } // end llvm namespace 00252 00253 #endif