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 Root
= getOrInsertNode(nullptr);
153 CallGraph::~CallGraph() = default;
155 bool CallGraph::includeInGraph(const Decl
*D
) {
160 return includeCalleeInGraph(D
);
163 bool CallGraph::includeCalleeInGraph(const Decl
*D
) {
164 if (const FunctionDecl
*FD
= dyn_cast
<FunctionDecl
>(D
)) {
165 // We skip function template definitions, as their semantics is
166 // only determined when they are instantiated.
167 if (FD
->isDependentContext())
170 IdentifierInfo
*II
= FD
->getIdentifier();
171 if (II
&& II
->getName().startswith("__inline"))
178 void CallGraph::addNodeForDecl(Decl
* D
, bool IsGlobal
) {
181 // Allocate a new node, mark it as root, and process its calls.
182 CallGraphNode
*Node
= getOrInsertNode(D
);
184 // Process all the calls by this function as well.
185 CGBuilder
builder(this, Node
);
186 if (Stmt
*Body
= D
->getBody())
189 // Include C++ constructor member initializers.
190 if (auto constructor
= dyn_cast
<CXXConstructorDecl
>(D
)) {
191 for (CXXCtorInitializer
*init
: constructor
->inits()) {
192 builder
.Visit(init
->getInit());
197 CallGraphNode
*CallGraph::getNode(const Decl
*F
) const {
198 FunctionMapTy::const_iterator I
= FunctionMap
.find(F
);
199 if (I
== FunctionMap
.end()) return nullptr;
200 return I
->second
.get();
203 CallGraphNode
*CallGraph::getOrInsertNode(Decl
*F
) {
204 if (F
&& !isa
<ObjCMethodDecl
>(F
))
205 F
= F
->getCanonicalDecl();
207 std::unique_ptr
<CallGraphNode
> &Node
= FunctionMap
[F
];
211 Node
= std::make_unique
<CallGraphNode
>(F
);
212 // Make Root node a parent of all functions to make sure all are reachable.
214 Root
->addCallee({Node
.get(), /*Call=*/nullptr});
218 void CallGraph::print(raw_ostream
&OS
) const {
219 OS
<< " --- Call graph Dump --- \n";
221 // We are going to print the graph in reverse post order, partially, to make
222 // sure the output is deterministic.
223 llvm::ReversePostOrderTraversal
<const CallGraph
*> RPOT(this);
224 for (llvm::ReversePostOrderTraversal
<const CallGraph
*>::rpo_iterator
225 I
= RPOT
.begin(), E
= RPOT
.end(); I
!= E
; ++I
) {
226 const CallGraphNode
*N
= *I
;
235 for (CallGraphNode::const_iterator CI
= N
->begin(),
236 CE
= N
->end(); CI
!= CE
; ++CI
) {
237 assert(CI
->Callee
!= Root
&& "No one can call the root node.");
238 CI
->Callee
->print(OS
);
246 LLVM_DUMP_METHOD
void CallGraph::dump() const {
250 void CallGraph::viewGraph() const {
251 llvm::ViewGraph(this, "CallGraph");
254 void CallGraphNode::print(raw_ostream
&os
) const {
255 if (const NamedDecl
*ND
= dyn_cast_or_null
<NamedDecl
>(FD
))
256 return ND
->printQualifiedName(os
);
260 LLVM_DUMP_METHOD
void CallGraphNode::dump() const {
267 struct DOTGraphTraits
<const CallGraph
*> : public DefaultDOTGraphTraits
{
268 DOTGraphTraits (bool isSimple
= false) : DefaultDOTGraphTraits(isSimple
) {}
270 static std::string
getNodeLabel(const CallGraphNode
*Node
,
271 const CallGraph
*CG
) {
272 if (CG
->getRoot() == Node
) {
275 if (const NamedDecl
*ND
= dyn_cast_or_null
<NamedDecl
>(Node
->getDecl()))
276 return ND
->getNameAsString();