clang 20.0.0git
CallGraph.cpp
Go to the documentation of this file.
1//===- CallGraph.cpp - AST-based Call graph -------------------------------===//
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 defines the AST-based CallGraph.
10//
11//===----------------------------------------------------------------------===//
12
14#include "clang/AST/Decl.h"
15#include "clang/AST/DeclBase.h"
16#include "clang/AST/DeclObjC.h"
17#include "clang/AST/Expr.h"
18#include "clang/AST/ExprObjC.h"
19#include "clang/AST/Stmt.h"
22#include "clang/Basic/LLVM.h"
23#include "llvm/ADT/PostOrderIterator.h"
24#include "llvm/ADT/STLExtras.h"
25#include "llvm/ADT/Statistic.h"
26#include "llvm/Support/Casting.h"
27#include "llvm/Support/Compiler.h"
28#include "llvm/Support/DOTGraphTraits.h"
29#include "llvm/Support/GraphWriter.h"
30#include "llvm/Support/raw_ostream.h"
31#include <cassert>
32#include <memory>
33#include <string>
34
35using namespace clang;
36
37#define DEBUG_TYPE "CallGraph"
38
39STATISTIC(NumObjCCallEdges, "Number of Objective-C method call edges");
40STATISTIC(NumBlockCallEdges, "Number of block call edges");
41
42namespace {
43
44/// A helper class, which walks the AST and locates all the call sites in the
45/// given function body.
46class CGBuilder : public StmtVisitor<CGBuilder> {
47 CallGraph *G;
48 CallGraphNode *CallerNode;
49
50public:
51 CGBuilder(CallGraph *g, CallGraphNode *N) : G(g), CallerNode(N) {}
52
53 void VisitStmt(Stmt *S) { VisitChildren(S); }
54
55 Decl *getDeclFromCall(CallExpr *CE) {
56 if (FunctionDecl *CalleeDecl = CE->getDirectCallee())
57 return CalleeDecl;
58
59 // Simple detection of a call through a block.
60 Expr *CEE = CE->getCallee()->IgnoreParenImpCasts();
61 if (BlockExpr *Block = dyn_cast<BlockExpr>(CEE)) {
62 NumBlockCallEdges++;
63 return Block->getBlockDecl();
64 }
65
66 return nullptr;
67 }
68
69 void addCalledDecl(Decl *D, Expr *CallExpr) {
70 if (G->includeCalleeInGraph(D)) {
71 CallGraphNode *CalleeNode = G->getOrInsertNode(D);
72 CallerNode->addCallee({CalleeNode, CallExpr});
73 }
74 }
75
76 void VisitCallExpr(CallExpr *CE) {
77 if (Decl *D = getDeclFromCall(CE))
78 addCalledDecl(D, CE);
79 VisitChildren(CE);
80 }
81
82 void VisitLambdaExpr(LambdaExpr *LE) {
83 if (FunctionTemplateDecl *FTD = LE->getDependentCallOperator())
84 for (FunctionDecl *FD : FTD->specializations())
85 G->VisitFunctionDecl(FD);
86 else if (CXXMethodDecl *MD = LE->getCallOperator())
87 G->VisitFunctionDecl(MD);
88 }
89
90 void VisitCXXNewExpr(CXXNewExpr *E) {
91 if (FunctionDecl *FD = E->getOperatorNew())
92 addCalledDecl(FD, E);
93 VisitChildren(E);
94 }
95
96 void VisitCXXConstructExpr(CXXConstructExpr *E) {
97 CXXConstructorDecl *Ctor = E->getConstructor();
98 if (FunctionDecl *Def = Ctor->getDefinition())
99 addCalledDecl(Def, E);
100 VisitChildren(E);
101 }
102
103 // Include the evaluation of the default argument.
104 void VisitCXXDefaultArgExpr(CXXDefaultArgExpr *E) {
105 Visit(E->getExpr());
106 }
107
108 // Include the evaluation of the default initializers in a class.
109 void VisitCXXDefaultInitExpr(CXXDefaultInitExpr *E) {
110 Visit(E->getExpr());
111 }
112
113 // Adds may-call edges for the ObjC message sends.
114 void VisitObjCMessageExpr(ObjCMessageExpr *ME) {
115 if (ObjCInterfaceDecl *IDecl = ME->getReceiverInterface()) {
116 Selector Sel = ME->getSelector();
117
118 // Find the callee definition within the same translation unit.
119 Decl *D = nullptr;
120 if (ME->isInstanceMessage())
121 D = IDecl->lookupPrivateMethod(Sel);
122 else
123 D = IDecl->lookupPrivateClassMethod(Sel);
124 if (D) {
125 addCalledDecl(D, ME);
126 NumObjCCallEdges++;
127 }
128 }
129 }
130
131 void VisitChildren(Stmt *S) {
132 for (Stmt *SubStmt : S->children())
133 if (SubStmt)
134 this->Visit(SubStmt);
135 }
136};
137
138} // namespace
139
141 if (BlockDecl *BD = dyn_cast<BlockDecl>(D))
142 addNodeForDecl(BD, true);
143
144 for (auto *I : D->decls())
145 if (auto *DC = dyn_cast<DeclContext>(I))
147}
148
153 Root = getOrInsertNode(nullptr);
154}
155
156CallGraph::~CallGraph() = default;
157
159 assert(D);
160 if (!D->hasBody())
161 return false;
162
163 return includeCalleeInGraph(D);
164}
165
167 if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
168 // We skip function template definitions, as their semantics is
169 // only determined when they are instantiated.
170 if (FD->isDependentContext())
171 return false;
172
173 IdentifierInfo *II = FD->getIdentifier();
174 if (II && II->getName().starts_with("__inline"))
175 return false;
176 }
177
178 return true;
179}
180
181void CallGraph::addNodeForDecl(Decl* D, bool IsGlobal) {
182 assert(D);
183
184 // Allocate a new node, mark it as root, and process its calls.
186
187 // Process all the calls by this function as well.
188 CGBuilder builder(this, Node);
189 if (Stmt *Body = D->getBody())
190 builder.Visit(Body);
191
192 // Include C++ constructor member initializers.
193 if (auto constructor = dyn_cast<CXXConstructorDecl>(D)) {
194 for (CXXCtorInitializer *init : constructor->inits()) {
195 builder.Visit(init->getInit());
196 }
197 }
198}
199
201 FunctionMapTy::const_iterator I = FunctionMap.find(F);
202 if (I == FunctionMap.end()) return nullptr;
203 return I->second.get();
204}
205
207 if (F && !isa<ObjCMethodDecl>(F))
208 F = F->getCanonicalDecl();
209
210 std::unique_ptr<CallGraphNode> &Node = FunctionMap[F];
211 if (Node)
212 return Node.get();
213
214 Node = std::make_unique<CallGraphNode>(F);
215 // Make Root node a parent of all functions to make sure all are reachable.
216 if (F)
217 Root->addCallee({Node.get(), /*Call=*/nullptr});
218 return Node.get();
219}
220
221void CallGraph::print(raw_ostream &OS) const {
222 OS << " --- Call graph Dump --- \n";
223
224 // We are going to print the graph in reverse post order, partially, to make
225 // sure the output is deterministic.
226 llvm::ReversePostOrderTraversal<const CallGraph *> RPOT(this);
227 for (llvm::ReversePostOrderTraversal<const CallGraph *>::rpo_iterator
228 I = RPOT.begin(), E = RPOT.end(); I != E; ++I) {
229 const CallGraphNode *N = *I;
230
231 OS << " Function: ";
232 if (N == Root)
233 OS << "< root >";
234 else
235 N->print(OS);
236
237 OS << " calls: ";
239 CE = N->end(); CI != CE; ++CI) {
240 assert(CI->Callee != Root && "No one can call the root node.");
241 CI->Callee->print(OS);
242 OS << " ";
243 }
244 OS << '\n';
245 }
246 OS.flush();
247}
248
249LLVM_DUMP_METHOD void CallGraph::dump() const {
250 print(llvm::errs());
251}
252
254 llvm::ViewGraph(this, "CallGraph");
255}
256
257void CallGraphNode::print(raw_ostream &os) const {
258 if (const NamedDecl *ND = dyn_cast_or_null<NamedDecl>(FD))
259 return ND->printQualifiedName(os);
260 os << "< >";
261}
262
263LLVM_DUMP_METHOD void CallGraphNode::dump() const {
264 print(llvm::errs());
265}
266
267namespace llvm {
268
269template <>
270struct DOTGraphTraits<const CallGraph*> : public DefaultDOTGraphTraits {
271 DOTGraphTraits (bool isSimple = false) : DefaultDOTGraphTraits(isSimple) {}
272
273 static std::string getNodeLabel(const CallGraphNode *Node,
274 const CallGraph *CG) {
275 if (CG->getRoot() == Node) {
276 return "< root >";
277 }
278 if (const NamedDecl *ND = dyn_cast_or_null<NamedDecl>(Node->getDecl()))
279 return ND->getNameAsString();
280 else
281 return "< >";
282 }
283};
284
285} // namespace llvm
DynTypedNode Node
STATISTIC(NumObjCCallEdges, "Number of Objective-C method call edges")
const Decl * D
Expr * E
const CFGBlock * Block
Definition: HTMLLogger.cpp:152
Defines the clang::IdentifierInfo, clang::IdentifierTable, and clang::Selector interfaces.
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified.
Represents a block literal declaration, which is like an unnamed FunctionDecl.
Definition: Decl.h:4474
BlockExpr - Adaptor class for mixing a BlockDecl with expressions.
Definition: Expr.h:6414
Represents a call to a C++ constructor.
Definition: ExprCXX.h:1546
Represents a C++ constructor within a class.
Definition: DeclCXX.h:2553
Represents a C++ base or member initializer.
Definition: DeclCXX.h:2318
A default argument (C++ [dcl.fct.default]).
Definition: ExprCXX.h:1268
A use of a default initializer in a constructor or in aggregate initialization.
Definition: ExprCXX.h:1375
Represents a static or instance method of a struct/union/class.
Definition: DeclCXX.h:2078
Represents a new-expression for memory allocation and constructor calls, e.g: "new CXXNewExpr(foo)".
Definition: ExprCXX.h:2241
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Definition: Expr.h:2874
FunctionDecl * getDirectCallee()
If the callee is a FunctionDecl, return it. Otherwise return null.
Definition: Expr.h:3047
Expr * getCallee()
Definition: Expr.h:3024
void dump() const
Definition: CallGraph.cpp:263
iterator begin()
Iterators through all the callees/children of the node.
Definition: CallGraph.h:174
void print(raw_ostream &os) const
Definition: CallGraph.cpp:257
SmallVectorImpl< CallRecord >::const_iterator const_iterator
Definition: CallGraph.h:171
void addCallee(CallRecord Call)
Definition: CallGraph.h:190
The AST-based call graph.
Definition: CallGraph.h:43
void viewGraph() const
Definition: CallGraph.cpp:253
CallGraphNode * getNode(const Decl *) const
Lookup the node for the given declaration.
Definition: CallGraph.cpp:200
void dump() const
Definition: CallGraph.cpp:249
void addNodesForBlocks(DeclContext *D)
Definition: CallGraph.cpp:140
bool VisitFunctionDecl(FunctionDecl *FD) override
Part of recursive declaration visitation.
Definition: CallGraph.h:113
CallGraphNode * getOrInsertNode(Decl *)
Lookup the node for the given declaration.
Definition: CallGraph.cpp:206
void print(raw_ostream &os) const
Definition: CallGraph.cpp:221
static bool includeCalleeInGraph(const Decl *D)
Determine if a declaration should be included in the graph for the purposes of being a callee.
Definition: CallGraph.cpp:166
CallGraphNode * getRoot() const
Get the virtual root of the graph, all the functions available externally are represented as callees ...
Definition: CallGraph.h:97
static bool includeInGraph(const Decl *D)
Determine if a declaration should be included in the graph.
Definition: CallGraph.cpp:158
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
Definition: DeclBase.h:1435
Decl - This represents one declaration (or definition), e.g.
Definition: DeclBase.h:86
virtual Stmt * getBody() const
getBody - If this Decl represents a declaration for a body of code, such as a function or method defi...
Definition: DeclBase.h:1076
virtual bool hasBody() const
Returns true if this Decl represents a declaration for a body of code, such as a function or method d...
Definition: DeclBase.h:1082
virtual Decl * getCanonicalDecl()
Retrieves the "canonical" declaration of the given declaration.
Definition: DeclBase.h:967
const T * get() const
Retrieve the stored node as type T.
bool ShouldWalkTypesOfTypeLocs
Whether this visitor should recurse into the types of TypeLocs.
bool ShouldVisitImplicitCode
Whether this visitor should recurse into implicit code, e.g.
bool ShouldVisitTemplateInstantiations
Whether this visitor should recurse into template instantiations.
This represents one expression.
Definition: Expr.h:110
Expr * IgnoreParenImpCasts() LLVM_READONLY
Skip past any parentheses and implicit casts which might surround this expression until reaching a fi...
Definition: Expr.cpp:3090
Represents a function declaration or definition.
Definition: Decl.h:1935
FunctionDecl * getDefinition()
Get the definition for this declaration.
Definition: Decl.h:2217
Declaration of a template function.
Definition: DeclTemplate.h:959
One of these records is kept for each identifier that is lexed.
StringRef getName() const
Return the actual identifier string.
A C++ lambda expression, which produces a function object (of unspecified type) that can be invoked l...
Definition: ExprCXX.h:1954
This represents a decl that may have a name.
Definition: Decl.h:253
Represents an ObjC class declaration.
Definition: DeclObjC.h:1153
An expression that sends a message to the given Objective-C object or class.
Definition: ExprObjC.h:941
Selector getSelector() const
Definition: ExprObjC.cpp:291
bool isInstanceMessage() const
Determine whether this is an instance message to either a computed object or to super.
Definition: ExprObjC.h:1244
ObjCInterfaceDecl * getReceiverInterface() const
Retrieve the Objective-C interface to which this message is being directed, if known.
Definition: ExprObjC.cpp:312
Smart pointer class that efficiently represents Objective-C method names.
RetTy Visit(PTR(Stmt) S, ParamTys... P)
Definition: StmtVisitor.h:44
StmtVisitor - This class implements a simple visitor for Stmt subclasses.
Definition: StmtVisitor.h:185
Stmt - This represents one statement.
Definition: Stmt.h:84
bool LE(InterpState &S, CodePtr OpPC)
Definition: Interp.h:1171
The JSON file list parser is used to communicate input to InstallAPI.
Diagnostic wrappers for TextAPI types for error reporting.
Definition: Dominators.h:30
static std::string getNodeLabel(const CallGraphNode *Node, const CallGraph *CG)
Definition: CallGraph.cpp:273