1 //===- CallGraph.h - AST-based Call graph -----------------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file declares the AST-based CallGraph. 10 // 11 // A call graph for functions whose definitions/bodies are available in the 12 // current translation unit. The graph has a "virtual" root node that contains 13 // edges to all externally available functions. 14 // 15 //===----------------------------------------------------------------------===// 16 17 #ifndef LLVM_CLANG_ANALYSIS_CALLGRAPH_H 18 #define LLVM_CLANG_ANALYSIS_CALLGRAPH_H 19 20 #include "clang/AST/Decl.h" 21 #include "clang/AST/DeclObjC.h" 22 #include "clang/AST/DynamicRecursiveASTVisitor.h" 23 #include "llvm/ADT/DenseMap.h" 24 #include "llvm/ADT/GraphTraits.h" 25 #include "llvm/ADT/STLExtras.h" 26 #include "llvm/ADT/SetVector.h" 27 #include "llvm/ADT/SmallVector.h" 28 #include "llvm/ADT/iterator_range.h" 29 #include <memory> 30 31 namespace clang { 32 33 class CallGraphNode; 34 class Decl; 35 class DeclContext; 36 class Stmt; 37 38 /// The AST-based call graph. 39 /// 40 /// The call graph extends itself with the given declarations by implementing 41 /// the recursive AST visitor, which constructs the graph by visiting the given 42 /// declarations. 43 class CallGraph : public DynamicRecursiveASTVisitor { 44 friend class CallGraphNode; 45 46 using FunctionMapTy = 47 llvm::DenseMap<const Decl *, std::unique_ptr<CallGraphNode>>; 48 49 /// FunctionMap owns all CallGraphNodes. 50 FunctionMapTy FunctionMap; 51 52 /// This is a virtual root node that has edges to all the functions. 53 CallGraphNode *Root; 54 55 public: 56 CallGraph(); 57 ~CallGraph(); 58 59 /// Populate the call graph with the functions in the given 60 /// declaration. 61 /// 62 /// Recursively walks the declaration to find all the dependent Decls as well. 63 void addToCallGraph(Decl *D) { 64 TraverseDecl(D); 65 } 66 67 /// Determine if a declaration should be included in the graph. 68 static bool includeInGraph(const Decl *D); 69 70 /// Determine if a declaration should be included in the graph for the 71 /// purposes of being a callee. This is similar to includeInGraph except 72 /// it permits declarations, not just definitions. 73 static bool includeCalleeInGraph(const Decl *D); 74 75 /// Lookup the node for the given declaration. 76 CallGraphNode *getNode(const Decl *) const; 77 78 /// Lookup the node for the given declaration. If none found, insert 79 /// one into the graph. 80 CallGraphNode *getOrInsertNode(Decl *); 81 82 using iterator = FunctionMapTy::iterator; 83 using const_iterator = FunctionMapTy::const_iterator; 84 85 /// Iterators through all the elements in the graph. Note, this gives 86 /// non-deterministic order. 87 iterator begin() { return FunctionMap.begin(); } 88 iterator end() { return FunctionMap.end(); } 89 const_iterator begin() const { return FunctionMap.begin(); } 90 const_iterator end() const { return FunctionMap.end(); } 91 92 /// Get the number of nodes in the graph. 93 unsigned size() const { return FunctionMap.size(); } 94 95 /// Get the virtual root of the graph, all the functions available externally 96 /// are represented as callees of the node. 97 CallGraphNode *getRoot() const { return Root; } 98 99 /// Iterators through all the nodes of the graph that have no parent. These 100 /// are the unreachable nodes, which are either unused or are due to us 101 /// failing to add a call edge due to the analysis imprecision. 102 using nodes_iterator = llvm::SetVector<CallGraphNode *>::iterator; 103 using const_nodes_iterator = llvm::SetVector<CallGraphNode *>::const_iterator; 104 105 void print(raw_ostream &os) const; 106 void dump() const; 107 void viewGraph() const; 108 109 void addNodesForBlocks(DeclContext *D); 110 111 /// Part of recursive declaration visitation. We recursively visit all the 112 /// declarations to collect the root functions. 113 bool VisitFunctionDecl(FunctionDecl *FD) override { 114 // We skip function template definitions, as their semantics is 115 // only determined when they are instantiated. 116 if (includeInGraph(FD) && FD->isThisDeclarationADefinition()) { 117 // Add all blocks declared inside this function to the graph. 118 addNodesForBlocks(FD); 119 // If this function has external linkage, anything could call it. 120 // Note, we are not precise here. For example, the function could have 121 // its address taken. 122 addNodeForDecl(FD, FD->isGlobal()); 123 } 124 return true; 125 } 126 127 /// Part of recursive declaration visitation. 128 bool VisitObjCMethodDecl(ObjCMethodDecl *MD) override { 129 if (includeInGraph(MD)) { 130 addNodesForBlocks(MD); 131 addNodeForDecl(MD, true); 132 } 133 return true; 134 } 135 136 // We are only collecting the declarations, so do not step into the bodies. 137 bool TraverseStmt(Stmt *S) override { return true; } 138 139 private: 140 /// Add the given declaration to the call graph. 141 void addNodeForDecl(Decl *D, bool IsGlobal); 142 }; 143 144 class CallGraphNode { 145 public: 146 struct CallRecord { 147 CallGraphNode *Callee; 148 Expr *CallExpr; 149 150 CallRecord() = default; 151 152 CallRecord(CallGraphNode *Callee_, Expr *CallExpr_) 153 : Callee(Callee_), CallExpr(CallExpr_) {} 154 155 // The call destination is the only important data here, 156 // allow to transparently unwrap into it. 157 operator CallGraphNode *() const { return Callee; } 158 }; 159 160 private: 161 /// The function/method declaration. 162 Decl *FD; 163 164 /// The list of functions called from this node. 165 SmallVector<CallRecord, 5> CalledFunctions; 166 167 public: 168 CallGraphNode(Decl *D) : FD(D) {} 169 170 using iterator = SmallVectorImpl<CallRecord>::iterator; 171 using const_iterator = SmallVectorImpl<CallRecord>::const_iterator; 172 173 /// Iterators through all the callees/children of the node. 174 iterator begin() { return CalledFunctions.begin(); } 175 iterator end() { return CalledFunctions.end(); } 176 const_iterator begin() const { return CalledFunctions.begin(); } 177 const_iterator end() const { return CalledFunctions.end(); } 178 179 /// Iterator access to callees/children of the node. 180 llvm::iterator_range<iterator> callees() { 181 return llvm::make_range(begin(), end()); 182 } 183 llvm::iterator_range<const_iterator> callees() const { 184 return llvm::make_range(begin(), end()); 185 } 186 187 bool empty() const { return CalledFunctions.empty(); } 188 unsigned size() const { return CalledFunctions.size(); } 189 190 void addCallee(CallRecord Call) { CalledFunctions.push_back(Call); } 191 192 Decl *getDecl() const { return FD; } 193 194 FunctionDecl *getDefinition() const { 195 return getDecl()->getAsFunction()->getDefinition(); 196 } 197 198 void print(raw_ostream &os) const; 199 void dump() const; 200 }; 201 202 // NOTE: we are comparing based on the callee only. So different call records 203 // (with different call expressions) to the same callee will compare equal! 204 inline bool operator==(const CallGraphNode::CallRecord &LHS, 205 const CallGraphNode::CallRecord &RHS) { 206 return LHS.Callee == RHS.Callee; 207 } 208 209 } // namespace clang 210 211 namespace llvm { 212 213 // Specialize DenseMapInfo for clang::CallGraphNode::CallRecord. 214 template <> struct DenseMapInfo<clang::CallGraphNode::CallRecord> { 215 static inline clang::CallGraphNode::CallRecord getEmptyKey() { 216 return clang::CallGraphNode::CallRecord( 217 DenseMapInfo<clang::CallGraphNode *>::getEmptyKey(), 218 DenseMapInfo<clang::Expr *>::getEmptyKey()); 219 } 220 221 static inline clang::CallGraphNode::CallRecord getTombstoneKey() { 222 return clang::CallGraphNode::CallRecord( 223 DenseMapInfo<clang::CallGraphNode *>::getTombstoneKey(), 224 DenseMapInfo<clang::Expr *>::getTombstoneKey()); 225 } 226 227 static unsigned getHashValue(const clang::CallGraphNode::CallRecord &Val) { 228 // NOTE: we are comparing based on the callee only. 229 // Different call records with the same callee will compare equal! 230 return DenseMapInfo<clang::CallGraphNode *>::getHashValue(Val.Callee); 231 } 232 233 static bool isEqual(const clang::CallGraphNode::CallRecord &LHS, 234 const clang::CallGraphNode::CallRecord &RHS) { 235 return LHS == RHS; 236 } 237 }; 238 239 // Graph traits for iteration, viewing. 240 template <> struct GraphTraits<clang::CallGraphNode*> { 241 using NodeType = clang::CallGraphNode; 242 using NodeRef = clang::CallGraphNode *; 243 using ChildIteratorType = NodeType::iterator; 244 245 static NodeType *getEntryNode(clang::CallGraphNode *CGN) { return CGN; } 246 static ChildIteratorType child_begin(NodeType *N) { return N->begin(); } 247 static ChildIteratorType child_end(NodeType *N) { return N->end(); } 248 }; 249 250 template <> struct GraphTraits<const clang::CallGraphNode*> { 251 using NodeType = const clang::CallGraphNode; 252 using NodeRef = const clang::CallGraphNode *; 253 using ChildIteratorType = NodeType::const_iterator; 254 255 static NodeType *getEntryNode(const clang::CallGraphNode *CGN) { return CGN; } 256 static ChildIteratorType child_begin(NodeType *N) { return N->begin();} 257 static ChildIteratorType child_end(NodeType *N) { return N->end(); } 258 }; 259 260 template <> struct GraphTraits<clang::CallGraph*> 261 : public GraphTraits<clang::CallGraphNode*> { 262 static NodeType *getEntryNode(clang::CallGraph *CGN) { 263 return CGN->getRoot(); // Start at the external node! 264 } 265 266 static clang::CallGraphNode * 267 CGGetValue(clang::CallGraph::const_iterator::value_type &P) { 268 return P.second.get(); 269 } 270 271 // nodes_iterator/begin/end - Allow iteration over all nodes in the graph 272 using nodes_iterator = 273 mapped_iterator<clang::CallGraph::iterator, decltype(&CGGetValue)>; 274 275 static nodes_iterator nodes_begin(clang::CallGraph *CG) { 276 return nodes_iterator(CG->begin(), &CGGetValue); 277 } 278 279 static nodes_iterator nodes_end (clang::CallGraph *CG) { 280 return nodes_iterator(CG->end(), &CGGetValue); 281 } 282 283 static unsigned size(clang::CallGraph *CG) { return CG->size(); } 284 }; 285 286 template <> struct GraphTraits<const clang::CallGraph*> : 287 public GraphTraits<const clang::CallGraphNode*> { 288 static NodeType *getEntryNode(const clang::CallGraph *CGN) { 289 return CGN->getRoot(); 290 } 291 292 static clang::CallGraphNode * 293 CGGetValue(clang::CallGraph::const_iterator::value_type &P) { 294 return P.second.get(); 295 } 296 297 // nodes_iterator/begin/end - Allow iteration over all nodes in the graph 298 using nodes_iterator = 299 mapped_iterator<clang::CallGraph::const_iterator, decltype(&CGGetValue)>; 300 301 static nodes_iterator nodes_begin(const clang::CallGraph *CG) { 302 return nodes_iterator(CG->begin(), &CGGetValue); 303 } 304 305 static nodes_iterator nodes_end(const clang::CallGraph *CG) { 306 return nodes_iterator(CG->end(), &CGGetValue); 307 } 308 309 static unsigned size(const clang::CallGraph *CG) { return CG->size(); } 310 }; 311 312 } // namespace llvm 313 314 #endif // LLVM_CLANG_ANALYSIS_CALLGRAPH_H 315