CallGraph.cpp revision 1.1 1 1.1 joerg //===- CallGraph.cpp - AST-based Call graph -------------------------------===//
2 1.1 joerg //
3 1.1 joerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 1.1 joerg // See https://llvm.org/LICENSE.txt for license information.
5 1.1 joerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 1.1 joerg //
7 1.1 joerg //===----------------------------------------------------------------------===//
8 1.1 joerg //
9 1.1 joerg // This file defines the AST-based CallGraph.
10 1.1 joerg //
11 1.1 joerg //===----------------------------------------------------------------------===//
12 1.1 joerg
13 1.1 joerg #include "clang/Analysis/CallGraph.h"
14 1.1 joerg #include "clang/AST/Decl.h"
15 1.1 joerg #include "clang/AST/DeclBase.h"
16 1.1 joerg #include "clang/AST/DeclObjC.h"
17 1.1 joerg #include "clang/AST/Expr.h"
18 1.1 joerg #include "clang/AST/ExprObjC.h"
19 1.1 joerg #include "clang/AST/Stmt.h"
20 1.1 joerg #include "clang/AST/StmtVisitor.h"
21 1.1 joerg #include "clang/Basic/IdentifierTable.h"
22 1.1 joerg #include "clang/Basic/LLVM.h"
23 1.1 joerg #include "llvm/ADT/PostOrderIterator.h"
24 1.1 joerg #include "llvm/ADT/STLExtras.h"
25 1.1 joerg #include "llvm/ADT/Statistic.h"
26 1.1 joerg #include "llvm/Support/Casting.h"
27 1.1 joerg #include "llvm/Support/Compiler.h"
28 1.1 joerg #include "llvm/Support/DOTGraphTraits.h"
29 1.1 joerg #include "llvm/Support/GraphWriter.h"
30 1.1 joerg #include "llvm/Support/raw_ostream.h"
31 1.1 joerg #include <cassert>
32 1.1 joerg #include <memory>
33 1.1 joerg #include <string>
34 1.1 joerg
35 1.1 joerg using namespace clang;
36 1.1 joerg
37 1.1 joerg #define DEBUG_TYPE "CallGraph"
38 1.1 joerg
39 1.1 joerg STATISTIC(NumObjCCallEdges, "Number of Objective-C method call edges");
40 1.1 joerg STATISTIC(NumBlockCallEdges, "Number of block call edges");
41 1.1 joerg
42 1.1 joerg namespace {
43 1.1 joerg
44 1.1 joerg /// A helper class, which walks the AST and locates all the call sites in the
45 1.1 joerg /// given function body.
46 1.1 joerg class CGBuilder : public StmtVisitor<CGBuilder> {
47 1.1 joerg CallGraph *G;
48 1.1 joerg CallGraphNode *CallerNode;
49 1.1 joerg
50 1.1 joerg public:
51 1.1 joerg CGBuilder(CallGraph *g, CallGraphNode *N) : G(g), CallerNode(N) {}
52 1.1 joerg
53 1.1 joerg void VisitStmt(Stmt *S) { VisitChildren(S); }
54 1.1 joerg
55 1.1 joerg Decl *getDeclFromCall(CallExpr *CE) {
56 1.1 joerg if (FunctionDecl *CalleeDecl = CE->getDirectCallee())
57 1.1 joerg return CalleeDecl;
58 1.1 joerg
59 1.1 joerg // Simple detection of a call through a block.
60 1.1 joerg Expr *CEE = CE->getCallee()->IgnoreParenImpCasts();
61 1.1 joerg if (BlockExpr *Block = dyn_cast<BlockExpr>(CEE)) {
62 1.1 joerg NumBlockCallEdges++;
63 1.1 joerg return Block->getBlockDecl();
64 1.1 joerg }
65 1.1 joerg
66 1.1 joerg return nullptr;
67 1.1 joerg }
68 1.1 joerg
69 1.1 joerg void addCalledDecl(Decl *D) {
70 1.1 joerg if (G->includeInGraph(D)) {
71 1.1 joerg CallGraphNode *CalleeNode = G->getOrInsertNode(D);
72 1.1 joerg CallerNode->addCallee(CalleeNode);
73 1.1 joerg }
74 1.1 joerg }
75 1.1 joerg
76 1.1 joerg void VisitCallExpr(CallExpr *CE) {
77 1.1 joerg if (Decl *D = getDeclFromCall(CE))
78 1.1 joerg addCalledDecl(D);
79 1.1 joerg VisitChildren(CE);
80 1.1 joerg }
81 1.1 joerg
82 1.1 joerg void VisitLambdaExpr(LambdaExpr *LE) {
83 1.1 joerg if (FunctionTemplateDecl *FTD = LE->getDependentCallOperator())
84 1.1 joerg for (FunctionDecl *FD : FTD->specializations())
85 1.1 joerg G->VisitFunctionDecl(FD);
86 1.1 joerg else if (CXXMethodDecl *MD = LE->getCallOperator())
87 1.1 joerg G->VisitFunctionDecl(MD);
88 1.1 joerg }
89 1.1 joerg
90 1.1 joerg void VisitCXXNewExpr(CXXNewExpr *E) {
91 1.1 joerg if (FunctionDecl *FD = E->getOperatorNew())
92 1.1 joerg addCalledDecl(FD);
93 1.1 joerg VisitChildren(E);
94 1.1 joerg }
95 1.1 joerg
96 1.1 joerg void VisitCXXConstructExpr(CXXConstructExpr *E) {
97 1.1 joerg CXXConstructorDecl *Ctor = E->getConstructor();
98 1.1 joerg if (FunctionDecl *Def = Ctor->getDefinition())
99 1.1 joerg addCalledDecl(Def);
100 1.1 joerg VisitChildren(E);
101 1.1 joerg }
102 1.1 joerg
103 1.1 joerg // Include the evaluation of the default argument.
104 1.1 joerg void VisitCXXDefaultArgExpr(CXXDefaultArgExpr *E) {
105 1.1 joerg Visit(E->getExpr());
106 1.1 joerg }
107 1.1 joerg
108 1.1 joerg // Include the evaluation of the default initializers in a class.
109 1.1 joerg void VisitCXXDefaultInitExpr(CXXDefaultInitExpr *E) {
110 1.1 joerg Visit(E->getExpr());
111 1.1 joerg }
112 1.1 joerg
113 1.1 joerg // Adds may-call edges for the ObjC message sends.
114 1.1 joerg void VisitObjCMessageExpr(ObjCMessageExpr *ME) {
115 1.1 joerg if (ObjCInterfaceDecl *IDecl = ME->getReceiverInterface()) {
116 1.1 joerg Selector Sel = ME->getSelector();
117 1.1 joerg
118 1.1 joerg // Find the callee definition within the same translation unit.
119 1.1 joerg Decl *D = nullptr;
120 1.1 joerg if (ME->isInstanceMessage())
121 1.1 joerg D = IDecl->lookupPrivateMethod(Sel);
122 1.1 joerg else
123 1.1 joerg D = IDecl->lookupPrivateClassMethod(Sel);
124 1.1 joerg if (D) {
125 1.1 joerg addCalledDecl(D);
126 1.1 joerg NumObjCCallEdges++;
127 1.1 joerg }
128 1.1 joerg }
129 1.1 joerg }
130 1.1 joerg
131 1.1 joerg void VisitChildren(Stmt *S) {
132 1.1 joerg for (Stmt *SubStmt : S->children())
133 1.1 joerg if (SubStmt)
134 1.1 joerg this->Visit(SubStmt);
135 1.1 joerg }
136 1.1 joerg };
137 1.1 joerg
138 1.1 joerg } // namespace
139 1.1 joerg
140 1.1 joerg void CallGraph::addNodesForBlocks(DeclContext *D) {
141 1.1 joerg if (BlockDecl *BD = dyn_cast<BlockDecl>(D))
142 1.1 joerg addNodeForDecl(BD, true);
143 1.1 joerg
144 1.1 joerg for (auto *I : D->decls())
145 1.1 joerg if (auto *DC = dyn_cast<DeclContext>(I))
146 1.1 joerg addNodesForBlocks(DC);
147 1.1 joerg }
148 1.1 joerg
149 1.1 joerg CallGraph::CallGraph() {
150 1.1 joerg Root = getOrInsertNode(nullptr);
151 1.1 joerg }
152 1.1 joerg
153 1.1 joerg CallGraph::~CallGraph() = default;
154 1.1 joerg
155 1.1 joerg bool CallGraph::includeInGraph(const Decl *D) {
156 1.1 joerg assert(D);
157 1.1 joerg if (!D->hasBody())
158 1.1 joerg return false;
159 1.1 joerg
160 1.1 joerg if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
161 1.1 joerg // We skip function template definitions, as their semantics is
162 1.1 joerg // only determined when they are instantiated.
163 1.1 joerg if (FD->isDependentContext())
164 1.1 joerg return false;
165 1.1 joerg
166 1.1 joerg IdentifierInfo *II = FD->getIdentifier();
167 1.1 joerg if (II && II->getName().startswith("__inline"))
168 1.1 joerg return false;
169 1.1 joerg }
170 1.1 joerg
171 1.1 joerg return true;
172 1.1 joerg }
173 1.1 joerg
174 1.1 joerg void CallGraph::addNodeForDecl(Decl* D, bool IsGlobal) {
175 1.1 joerg assert(D);
176 1.1 joerg
177 1.1 joerg // Allocate a new node, mark it as root, and process its calls.
178 1.1 joerg CallGraphNode *Node = getOrInsertNode(D);
179 1.1 joerg
180 1.1 joerg // Process all the calls by this function as well.
181 1.1 joerg CGBuilder builder(this, Node);
182 1.1 joerg if (Stmt *Body = D->getBody())
183 1.1 joerg builder.Visit(Body);
184 1.1 joerg
185 1.1 joerg // Include C++ constructor member initializers.
186 1.1 joerg if (auto constructor = dyn_cast<CXXConstructorDecl>(D)) {
187 1.1 joerg for (CXXCtorInitializer *init : constructor->inits()) {
188 1.1 joerg builder.Visit(init->getInit());
189 1.1 joerg }
190 1.1 joerg }
191 1.1 joerg }
192 1.1 joerg
193 1.1 joerg CallGraphNode *CallGraph::getNode(const Decl *F) const {
194 1.1 joerg FunctionMapTy::const_iterator I = FunctionMap.find(F);
195 1.1 joerg if (I == FunctionMap.end()) return nullptr;
196 1.1 joerg return I->second.get();
197 1.1 joerg }
198 1.1 joerg
199 1.1 joerg CallGraphNode *CallGraph::getOrInsertNode(Decl *F) {
200 1.1 joerg if (F && !isa<ObjCMethodDecl>(F))
201 1.1 joerg F = F->getCanonicalDecl();
202 1.1 joerg
203 1.1 joerg std::unique_ptr<CallGraphNode> &Node = FunctionMap[F];
204 1.1 joerg if (Node)
205 1.1 joerg return Node.get();
206 1.1 joerg
207 1.1 joerg Node = std::make_unique<CallGraphNode>(F);
208 1.1 joerg // Make Root node a parent of all functions to make sure all are reachable.
209 1.1 joerg if (F)
210 1.1 joerg Root->addCallee(Node.get());
211 1.1 joerg return Node.get();
212 1.1 joerg }
213 1.1 joerg
214 1.1 joerg void CallGraph::print(raw_ostream &OS) const {
215 1.1 joerg OS << " --- Call graph Dump --- \n";
216 1.1 joerg
217 1.1 joerg // We are going to print the graph in reverse post order, partially, to make
218 1.1 joerg // sure the output is deterministic.
219 1.1 joerg llvm::ReversePostOrderTraversal<const CallGraph *> RPOT(this);
220 1.1 joerg for (llvm::ReversePostOrderTraversal<const CallGraph *>::rpo_iterator
221 1.1 joerg I = RPOT.begin(), E = RPOT.end(); I != E; ++I) {
222 1.1 joerg const CallGraphNode *N = *I;
223 1.1 joerg
224 1.1 joerg OS << " Function: ";
225 1.1 joerg if (N == Root)
226 1.1 joerg OS << "< root >";
227 1.1 joerg else
228 1.1 joerg N->print(OS);
229 1.1 joerg
230 1.1 joerg OS << " calls: ";
231 1.1 joerg for (CallGraphNode::const_iterator CI = N->begin(),
232 1.1 joerg CE = N->end(); CI != CE; ++CI) {
233 1.1 joerg assert(*CI != Root && "No one can call the root node.");
234 1.1 joerg (*CI)->print(OS);
235 1.1 joerg OS << " ";
236 1.1 joerg }
237 1.1 joerg OS << '\n';
238 1.1 joerg }
239 1.1 joerg OS.flush();
240 1.1 joerg }
241 1.1 joerg
242 1.1 joerg LLVM_DUMP_METHOD void CallGraph::dump() const {
243 1.1 joerg print(llvm::errs());
244 1.1 joerg }
245 1.1 joerg
246 1.1 joerg void CallGraph::viewGraph() const {
247 1.1 joerg llvm::ViewGraph(this, "CallGraph");
248 1.1 joerg }
249 1.1 joerg
250 1.1 joerg void CallGraphNode::print(raw_ostream &os) const {
251 1.1 joerg if (const NamedDecl *ND = dyn_cast_or_null<NamedDecl>(FD))
252 1.1 joerg return ND->printQualifiedName(os);
253 1.1 joerg os << "< >";
254 1.1 joerg }
255 1.1 joerg
256 1.1 joerg LLVM_DUMP_METHOD void CallGraphNode::dump() const {
257 1.1 joerg print(llvm::errs());
258 1.1 joerg }
259 1.1 joerg
260 1.1 joerg namespace llvm {
261 1.1 joerg
262 1.1 joerg template <>
263 1.1 joerg struct DOTGraphTraits<const CallGraph*> : public DefaultDOTGraphTraits {
264 1.1 joerg DOTGraphTraits (bool isSimple = false) : DefaultDOTGraphTraits(isSimple) {}
265 1.1 joerg
266 1.1 joerg static std::string getNodeLabel(const CallGraphNode *Node,
267 1.1 joerg const CallGraph *CG) {
268 1.1 joerg if (CG->getRoot() == Node) {
269 1.1 joerg return "< root >";
270 1.1 joerg }
271 1.1 joerg if (const NamedDecl *ND = dyn_cast_or_null<NamedDecl>(Node->getDecl()))
272 1.1 joerg return ND->getNameAsString();
273 1.1 joerg else
274 1.1 joerg return "< >";
275 1.1 joerg }
276 1.1 joerg };
277 1.1 joerg
278 1.1 joerg } // namespace llvm
279