1 //===- CallGraph.cpp - AST-based Call graph -------------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 // This file defines the AST-based CallGraph.
11 //===----------------------------------------------------------------------===//
13 #include "clang/Analysis/CallGraph.h"
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"
20 #include "clang/AST/StmtVisitor.h"
21 #include "clang/Basic/IdentifierTable.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"
35 using namespace clang
;
37 #define DEBUG_TYPE "CallGraph"
39 STATISTIC(NumObjCCallEdges
, "Number of Objective-C method call edges");
40 STATISTIC(NumBlockCallEdges
, "Number of block call edges");
44 /// A helper class, which walks the AST and locates all the call sites in the
45 /// given function body.
46 class CGBuilder
: public StmtVisitor
<CGBuilder
> {
48 CallGraphNode
*CallerNode
;
51 CGBuilder(CallGraph
*g
, CallGraphNode
*N
) : G(g
), CallerNode(N
) {}
53 void VisitStmt(Stmt
*S
) { VisitChildren(S
); }
55 Decl
*getDeclFromCall(CallExpr
*CE
) {
56 if (FunctionDecl
*CalleeDecl
= CE
->getDirectCallee())
59 // Simple detection of a call through a block.
60 Expr
*CEE
= CE
->getCallee()->IgnoreParenImpCasts();
61 if (BlockExpr
*Block
= dyn_cast
<BlockExpr
>(CEE
)) {
63 return Block
->getBlockDecl();
69 void addCalledDecl(Decl
*D
, Expr
*CallExpr
) {
70 if (G
->includeCalleeInGraph(D
)) {
71 CallGraphNode
*CalleeNode
= G
->getOrInsertNode(D
);
72 CallerNode
->addCallee({CalleeNode
, CallExpr
});
76 void VisitCallExpr(CallExpr
*CE
) {
77 if (Decl
*D
= getDeclFromCall(CE
))
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
);
90 void VisitCXXNewExpr(CXXNewExpr
*E
) {
91 if (FunctionDecl
*FD
= E
->getOperatorNew())
96 void VisitCXXConstructExpr(CXXConstructExpr
*E
) {
97 CXXConstructorDecl
*Ctor
= E
->getConstructor();
98 if (FunctionDecl
*Def
= Ctor
->getDefinition())
99 addCalledDecl(Def
, E
);
103 // Include the evaluation of the default argument.
104 void VisitCXXDefaultArgExpr(CXXDefaultArgExpr
*E
) {
108 // Include the evaluation of the default initializers in a class.
109 void VisitCXXDefaultInitExpr(CXXDefaultInitExpr
*E
) {
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();
118 // Find the callee definition within the same translation unit.
120 if (ME
->isInstanceMessage())
121 D
= IDecl
->lookupPrivateMethod(Sel
);
123 D
= IDecl
->lookupPrivateClassMethod(Sel
);
125 addCalledDecl(D
, ME
);
131 void VisitChildren(Stmt
*S
) {
132 for (Stmt
*SubStmt
: S
->children())
134 this->Visit(SubStmt
);
140 void CallGraph::addNodesForBlocks(DeclContext
*D
) {
141 if (BlockDecl
*BD
= dyn_cast
<BlockDecl
>(D
))
142 addNodeForDecl(BD
, true);
144 for (auto *I
: D
->decls())
145 if (auto *DC
= dyn_cast
<DeclContext
>(I
))
146 addNodesForBlocks(DC
);
149 CallGraph::CallGraph() {
150 ShouldWalkTypesOfTypeLocs
= false;
151 ShouldVisitTemplateInstantiations
= true;
152 ShouldVisitImplicitCode
= true;
153 Root
= getOrInsertNode(nullptr);
156 CallGraph::~CallGraph() = default;
158 bool CallGraph::includeInGraph(const Decl
*D
) {
163 return includeCalleeInGraph(D
);
166 bool CallGraph::includeCalleeInGraph(const Decl
*D
) {
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())
173 IdentifierInfo
*II
= FD
->getIdentifier();
174 if (II
&& II
->getName().starts_with("__inline"))
181 void CallGraph::addNodeForDecl(Decl
* D
, bool IsGlobal
) {
184 // Allocate a new node, mark it as root, and process its calls.
185 CallGraphNode
*Node
= getOrInsertNode(D
);
187 // Process all the calls by this function as well.
188 CGBuilder
builder(this, Node
);
189 if (Stmt
*Body
= D
->getBody())
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());
200 CallGraphNode
*CallGraph::getNode(const Decl
*F
) const {
201 FunctionMapTy::const_iterator I
= FunctionMap
.find(F
);
202 if (I
== FunctionMap
.end()) return nullptr;
203 return I
->second
.get();
206 CallGraphNode
*CallGraph::getOrInsertNode(Decl
*F
) {
207 if (F
&& !isa
<ObjCMethodDecl
>(F
))
208 F
= F
->getCanonicalDecl();
210 std::unique_ptr
<CallGraphNode
> &Node
= FunctionMap
[F
];
214 Node
= std::make_unique
<CallGraphNode
>(F
);
215 // Make Root node a parent of all functions to make sure all are reachable.
217 Root
->addCallee({Node
.get(), /*Call=*/nullptr});
221 void CallGraph::print(raw_ostream
&OS
) const {
222 OS
<< " --- Call graph Dump --- \n";
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
;
238 for (CallGraphNode::const_iterator CI
= N
->begin(),
239 CE
= N
->end(); CI
!= CE
; ++CI
) {
240 assert(CI
->Callee
!= Root
&& "No one can call the root node.");
241 CI
->Callee
->print(OS
);
249 LLVM_DUMP_METHOD
void CallGraph::dump() const {
253 void CallGraph::viewGraph() const {
254 llvm::ViewGraph(this, "CallGraph");
257 void CallGraphNode::print(raw_ostream
&os
) const {
258 if (const NamedDecl
*ND
= dyn_cast_or_null
<NamedDecl
>(FD
))
259 return ND
->printQualifiedName(os
);
263 LLVM_DUMP_METHOD
void CallGraphNode::dump() const {
270 struct DOTGraphTraits
<const CallGraph
*> : public DefaultDOTGraphTraits
{
271 DOTGraphTraits (bool isSimple
= false) : DefaultDOTGraphTraits(isSimple
) {}
273 static std::string
getNodeLabel(const CallGraphNode
*Node
,
274 const CallGraph
*CG
) {
275 if (CG
->getRoot() == Node
) {
278 if (const NamedDecl
*ND
= dyn_cast_or_null
<NamedDecl
>(Node
->getDecl()))
279 return ND
->getNameAsString();