138c70521SEugene Zelenko //===- CallGraph.cpp - AST-based Call graph -------------------------------===//
2c000e7edSAnna Zaks //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6c000e7edSAnna Zaks //
7c000e7edSAnna Zaks //===----------------------------------------------------------------------===//
8c000e7edSAnna Zaks //
9c000e7edSAnna Zaks //  This file defines the AST-based CallGraph.
10c000e7edSAnna Zaks //
11c000e7edSAnna Zaks //===----------------------------------------------------------------------===//
1238c70521SEugene Zelenko 
13c000e7edSAnna Zaks #include "clang/Analysis/CallGraph.h"
14c000e7edSAnna Zaks #include "clang/AST/Decl.h"
1538c70521SEugene Zelenko #include "clang/AST/DeclBase.h"
1638c70521SEugene Zelenko #include "clang/AST/DeclObjC.h"
1738c70521SEugene Zelenko #include "clang/AST/Expr.h"
1838c70521SEugene Zelenko #include "clang/AST/ExprObjC.h"
1938c70521SEugene Zelenko #include "clang/AST/Stmt.h"
20c000e7edSAnna Zaks #include "clang/AST/StmtVisitor.h"
2138c70521SEugene Zelenko #include "clang/Basic/IdentifierTable.h"
2238c70521SEugene Zelenko #include "clang/Basic/LLVM.h"
231ee76c1bSAnna Zaks #include "llvm/ADT/PostOrderIterator.h"
2438c70521SEugene Zelenko #include "llvm/ADT/STLExtras.h"
255c32dfc5SAnna Zaks #include "llvm/ADT/Statistic.h"
2638c70521SEugene Zelenko #include "llvm/Support/Casting.h"
2738c70521SEugene Zelenko #include "llvm/Support/Compiler.h"
2838c70521SEugene Zelenko #include "llvm/Support/DOTGraphTraits.h"
29c000e7edSAnna Zaks #include "llvm/Support/GraphWriter.h"
3038c70521SEugene Zelenko #include "llvm/Support/raw_ostream.h"
3138c70521SEugene Zelenko #include <cassert>
3238c70521SEugene Zelenko #include <memory>
3338c70521SEugene Zelenko #include <string>
34c000e7edSAnna Zaks 
35c000e7edSAnna Zaks using namespace clang;
36c000e7edSAnna Zaks 
3710346667SChandler Carruth #define DEBUG_TYPE "CallGraph"
3810346667SChandler Carruth 
394127750eSAnna Zaks STATISTIC(NumObjCCallEdges, "Number of Objective-C method call edges");
405c32dfc5SAnna Zaks STATISTIC(NumBlockCallEdges, "Number of block call edges");
415c32dfc5SAnna Zaks 
428e078528SAnna Zaks namespace {
4338c70521SEugene Zelenko 
448e078528SAnna Zaks /// A helper class, which walks the AST and locates all the call sites in the
458e078528SAnna Zaks /// given function body.
468e078528SAnna Zaks class CGBuilder : public StmtVisitor<CGBuilder> {
478e078528SAnna Zaks   CallGraph *G;
488e078528SAnna Zaks   CallGraphNode *CallerNode;
498e078528SAnna Zaks 
508e078528SAnna Zaks public:
CGBuilder(CallGraph * g,CallGraphNode * N)5138c70521SEugene Zelenko   CGBuilder(CallGraph *g, CallGraphNode *N) : G(g), CallerNode(N) {}
528e078528SAnna Zaks 
VisitStmt(Stmt * S)538e078528SAnna Zaks   void VisitStmt(Stmt *S) { VisitChildren(S); }
548e078528SAnna Zaks 
getDeclFromCall(CallExpr * CE)555c32dfc5SAnna Zaks   Decl *getDeclFromCall(CallExpr *CE) {
568e078528SAnna Zaks     if (FunctionDecl *CalleeDecl = CE->getDirectCallee())
575c32dfc5SAnna Zaks       return CalleeDecl;
585c32dfc5SAnna Zaks 
595c32dfc5SAnna Zaks     // Simple detection of a call through a block.
605c32dfc5SAnna Zaks     Expr *CEE = CE->getCallee()->IgnoreParenImpCasts();
615c32dfc5SAnna Zaks     if (BlockExpr *Block = dyn_cast<BlockExpr>(CEE)) {
625c32dfc5SAnna Zaks       NumBlockCallEdges++;
635c32dfc5SAnna Zaks       return Block->getBlockDecl();
645c32dfc5SAnna Zaks     }
655c32dfc5SAnna Zaks 
6625542943SCraig Topper     return nullptr;
675c32dfc5SAnna Zaks   }
685c32dfc5SAnna Zaks 
addCalledDecl(Decl * D,Expr * CallExpr)69d68c7b8eSRoman Lebedev   void addCalledDecl(Decl *D, Expr *CallExpr) {
70*ffcc076aSErich Keane     if (G->includeCalleeInGraph(D)) {
715c32dfc5SAnna Zaks       CallGraphNode *CalleeNode = G->getOrInsertNode(D);
72d68c7b8eSRoman Lebedev       CallerNode->addCallee({CalleeNode, CallExpr});
738e078528SAnna Zaks     }
748e078528SAnna Zaks   }
758e078528SAnna Zaks 
VisitCallExpr(CallExpr * CE)765c32dfc5SAnna Zaks   void VisitCallExpr(CallExpr *CE) {
775c32dfc5SAnna Zaks     if (Decl *D = getDeclFromCall(CE))
78d68c7b8eSRoman Lebedev       addCalledDecl(D, CE);
7912caf8e1SArtem Dergachev     VisitChildren(CE);
805c32dfc5SAnna Zaks   }
815c32dfc5SAnna Zaks 
VisitLambdaExpr(LambdaExpr * LE)828cf3dfeaSArtem Dergachev   void VisitLambdaExpr(LambdaExpr *LE) {
835c2c60d2SErich Keane     if (FunctionTemplateDecl *FTD = LE->getDependentCallOperator())
845c2c60d2SErich Keane       for (FunctionDecl *FD : FTD->specializations())
855c2c60d2SErich Keane         G->VisitFunctionDecl(FD);
865c2c60d2SErich Keane     else if (CXXMethodDecl *MD = LE->getCallOperator())
878cf3dfeaSArtem Dergachev       G->VisitFunctionDecl(MD);
888cf3dfeaSArtem Dergachev   }
898cf3dfeaSArtem Dergachev 
VisitCXXNewExpr(CXXNewExpr * E)908cf3dfeaSArtem Dergachev   void VisitCXXNewExpr(CXXNewExpr *E) {
918cf3dfeaSArtem Dergachev     if (FunctionDecl *FD = E->getOperatorNew())
92d68c7b8eSRoman Lebedev       addCalledDecl(FD, E);
938cf3dfeaSArtem Dergachev     VisitChildren(E);
948cf3dfeaSArtem Dergachev   }
958cf3dfeaSArtem Dergachev 
VisitCXXConstructExpr(CXXConstructExpr * E)968cf3dfeaSArtem Dergachev   void VisitCXXConstructExpr(CXXConstructExpr *E) {
978cf3dfeaSArtem Dergachev     CXXConstructorDecl *Ctor = E->getConstructor();
988cf3dfeaSArtem Dergachev     if (FunctionDecl *Def = Ctor->getDefinition())
99d68c7b8eSRoman Lebedev       addCalledDecl(Def, E);
1008cf3dfeaSArtem Dergachev     VisitChildren(E);
1018cf3dfeaSArtem Dergachev   }
1028cf3dfeaSArtem Dergachev 
1038cf3dfeaSArtem Dergachev   // Include the evaluation of the default argument.
VisitCXXDefaultArgExpr(CXXDefaultArgExpr * E)1048cf3dfeaSArtem Dergachev   void VisitCXXDefaultArgExpr(CXXDefaultArgExpr *E) {
1058cf3dfeaSArtem Dergachev     Visit(E->getExpr());
1068cf3dfeaSArtem Dergachev   }
1078cf3dfeaSArtem Dergachev 
1088cf3dfeaSArtem Dergachev   // Include the evaluation of the default initializers in a class.
VisitCXXDefaultInitExpr(CXXDefaultInitExpr * E)1098cf3dfeaSArtem Dergachev   void VisitCXXDefaultInitExpr(CXXDefaultInitExpr *E) {
1108cf3dfeaSArtem Dergachev     Visit(E->getExpr());
1118cf3dfeaSArtem Dergachev   }
1128cf3dfeaSArtem Dergachev 
1135c32dfc5SAnna Zaks   // Adds may-call edges for the ObjC message sends.
VisitObjCMessageExpr(ObjCMessageExpr * ME)1145c32dfc5SAnna Zaks   void VisitObjCMessageExpr(ObjCMessageExpr *ME) {
1155c32dfc5SAnna Zaks     if (ObjCInterfaceDecl *IDecl = ME->getReceiverInterface()) {
1165c32dfc5SAnna Zaks       Selector Sel = ME->getSelector();
1175c32dfc5SAnna Zaks 
1184127750eSAnna Zaks       // Find the callee definition within the same translation unit.
11925542943SCraig Topper       Decl *D = nullptr;
1205c32dfc5SAnna Zaks       if (ME->isInstanceMessage())
1215c32dfc5SAnna Zaks         D = IDecl->lookupPrivateMethod(Sel);
1225c32dfc5SAnna Zaks       else
1235c32dfc5SAnna Zaks         D = IDecl->lookupPrivateClassMethod(Sel);
1245c32dfc5SAnna Zaks       if (D) {
125d68c7b8eSRoman Lebedev         addCalledDecl(D, ME);
1265c32dfc5SAnna Zaks         NumObjCCallEdges++;
1275c32dfc5SAnna Zaks       }
1285c32dfc5SAnna Zaks     }
1295c32dfc5SAnna Zaks   }
1305c32dfc5SAnna Zaks 
VisitChildren(Stmt * S)1318e078528SAnna Zaks   void VisitChildren(Stmt *S) {
132642f173aSBenjamin Kramer     for (Stmt *SubStmt : S->children())
133642f173aSBenjamin Kramer       if (SubStmt)
134642f173aSBenjamin Kramer         this->Visit(SubStmt);
1358e078528SAnna Zaks   }
1368e078528SAnna Zaks };
1378e078528SAnna Zaks 
13838c70521SEugene Zelenko } // namespace
1398e078528SAnna Zaks 
addNodesForBlocks(DeclContext * D)1405c32dfc5SAnna Zaks void CallGraph::addNodesForBlocks(DeclContext *D) {
1415c32dfc5SAnna Zaks   if (BlockDecl *BD = dyn_cast<BlockDecl>(D))
1425c32dfc5SAnna Zaks     addNodeForDecl(BD, true);
1435c32dfc5SAnna Zaks 
144629afaefSAaron Ballman   for (auto *I : D->decls())
145629afaefSAaron Ballman     if (auto *DC = dyn_cast<DeclContext>(I))
1465c32dfc5SAnna Zaks       addNodesForBlocks(DC);
1475c32dfc5SAnna Zaks }
1485c32dfc5SAnna Zaks 
CallGraph()1498e078528SAnna Zaks CallGraph::CallGraph() {
15025542943SCraig Topper   Root = getOrInsertNode(nullptr);
1518e078528SAnna Zaks }
1528e078528SAnna Zaks 
15338c70521SEugene Zelenko CallGraph::~CallGraph() = default;
1548e078528SAnna Zaks 
includeInGraph(const Decl * D)1558e078528SAnna Zaks bool CallGraph::includeInGraph(const Decl *D) {
1565c32dfc5SAnna Zaks   assert(D);
15787d404d4SAnna Zaks   if (!D->hasBody())
1585c32dfc5SAnna Zaks     return false;
1595c32dfc5SAnna Zaks 
160*ffcc076aSErich Keane   return includeCalleeInGraph(D);
161*ffcc076aSErich Keane }
162*ffcc076aSErich Keane 
includeCalleeInGraph(const Decl * D)163*ffcc076aSErich Keane bool CallGraph::includeCalleeInGraph(const Decl *D) {
164c000e7edSAnna Zaks   if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
165c000e7edSAnna Zaks     // We skip function template definitions, as their semantics is
166c000e7edSAnna Zaks     // only determined when they are instantiated.
16787d404d4SAnna Zaks     if (FD->isDependentContext())
168c000e7edSAnna Zaks       return false;
169c000e7edSAnna Zaks 
170c000e7edSAnna Zaks     IdentifierInfo *II = FD->getIdentifier();
171c000e7edSAnna Zaks     if (II && II->getName().startswith("__inline"))
172c000e7edSAnna Zaks       return false;
173c000e7edSAnna Zaks   }
174c000e7edSAnna Zaks 
175c000e7edSAnna Zaks   return true;
176c000e7edSAnna Zaks }
177c000e7edSAnna Zaks 
addNodeForDecl(Decl * D,bool IsGlobal)1788e078528SAnna Zaks void CallGraph::addNodeForDecl(Decl* D, bool IsGlobal) {
1799a008bb7SAnna Zaks   assert(D);
180c000e7edSAnna Zaks 
1818cf3dfeaSArtem Dergachev   // Allocate a new node, mark it as root, and process its calls.
1828e078528SAnna Zaks   CallGraphNode *Node = getOrInsertNode(D);
183c000e7edSAnna Zaks 
184c000e7edSAnna Zaks   // Process all the calls by this function as well.
185d1d76b2dSBenjamin Kramer   CGBuilder builder(this, Node);
186504957f4STed Kremenek   if (Stmt *Body = D->getBody())
187504957f4STed Kremenek     builder.Visit(Body);
1888cf3dfeaSArtem Dergachev 
1898cf3dfeaSArtem Dergachev   // Include C++ constructor member initializers.
1908cf3dfeaSArtem Dergachev   if (auto constructor = dyn_cast<CXXConstructorDecl>(D)) {
1918cf3dfeaSArtem Dergachev     for (CXXCtorInitializer *init : constructor->inits()) {
1928cf3dfeaSArtem Dergachev       builder.Visit(init->getInit());
1938cf3dfeaSArtem Dergachev     }
1948cf3dfeaSArtem Dergachev   }
195c000e7edSAnna Zaks }
196c000e7edSAnna Zaks 
getNode(const Decl * F) const197c2555770SAnna Zaks CallGraphNode *CallGraph::getNode(const Decl *F) const {
198dcc425ecSMatt Beaumont-Gay   FunctionMapTy::const_iterator I = FunctionMap.find(F);
19925542943SCraig Topper   if (I == FunctionMap.end()) return nullptr;
2005f3d1dc4SJustin Lebar   return I->second.get();
201c2555770SAnna Zaks }
202c2555770SAnna Zaks 
getOrInsertNode(Decl * F)2038e078528SAnna Zaks CallGraphNode *CallGraph::getOrInsertNode(Decl *F) {
20487d404d4SAnna Zaks   if (F && !isa<ObjCMethodDecl>(F))
20587d404d4SAnna Zaks     F = F->getCanonicalDecl();
20687d404d4SAnna Zaks 
2075f3d1dc4SJustin Lebar   std::unique_ptr<CallGraphNode> &Node = FunctionMap[F];
208c000e7edSAnna Zaks   if (Node)
2095f3d1dc4SJustin Lebar     return Node.get();
210c000e7edSAnna Zaks 
2112b3d49b6SJonas Devlieghere   Node = std::make_unique<CallGraphNode>(F);
2121ee76c1bSAnna Zaks   // Make Root node a parent of all functions to make sure all are reachable.
21325542943SCraig Topper   if (F)
214d68c7b8eSRoman Lebedev     Root->addCallee({Node.get(), /*Call=*/nullptr});
2155f3d1dc4SJustin Lebar   return Node.get();
216c000e7edSAnna Zaks }
217c000e7edSAnna Zaks 
print(raw_ostream & OS) const218c000e7edSAnna Zaks void CallGraph::print(raw_ostream &OS) const {
219c000e7edSAnna Zaks   OS << " --- Call graph Dump --- \n";
2201ee76c1bSAnna Zaks 
2211ee76c1bSAnna Zaks   // We are going to print the graph in reverse post order, partially, to make
2221ee76c1bSAnna Zaks   // sure the output is deterministic.
22338c70521SEugene Zelenko   llvm::ReversePostOrderTraversal<const CallGraph *> RPOT(this);
22438c70521SEugene Zelenko   for (llvm::ReversePostOrderTraversal<const CallGraph *>::rpo_iterator
2251ee76c1bSAnna Zaks          I = RPOT.begin(), E = RPOT.end(); I != E; ++I) {
2261ee76c1bSAnna Zaks     const CallGraphNode *N = *I;
2271ee76c1bSAnna Zaks 
228c000e7edSAnna Zaks     OS << "  Function: ";
2291ee76c1bSAnna Zaks     if (N == Root)
230c000e7edSAnna Zaks       OS << "< root >";
231c000e7edSAnna Zaks     else
2321ee76c1bSAnna Zaks       N->print(OS);
2331ee76c1bSAnna Zaks 
234c000e7edSAnna Zaks     OS << " calls: ";
2351ee76c1bSAnna Zaks     for (CallGraphNode::const_iterator CI = N->begin(),
2361ee76c1bSAnna Zaks                                        CE = N->end(); CI != CE; ++CI) {
237d68c7b8eSRoman Lebedev       assert(CI->Callee != Root && "No one can call the root node.");
238d68c7b8eSRoman Lebedev       CI->Callee->print(OS);
239c000e7edSAnna Zaks       OS << " ";
240c000e7edSAnna Zaks     }
241c000e7edSAnna Zaks     OS << '\n';
242c000e7edSAnna Zaks   }
243c000e7edSAnna Zaks   OS.flush();
244c000e7edSAnna Zaks }
245c000e7edSAnna Zaks 
dump() const246cdae941eSYaron Keren LLVM_DUMP_METHOD void CallGraph::dump() const {
247c000e7edSAnna Zaks   print(llvm::errs());
248c000e7edSAnna Zaks }
249c000e7edSAnna Zaks 
viewGraph() const250c000e7edSAnna Zaks void CallGraph::viewGraph() const {
251c000e7edSAnna Zaks   llvm::ViewGraph(this, "CallGraph");
252c000e7edSAnna Zaks }
253c000e7edSAnna Zaks 
print(raw_ostream & os) const254c000e7edSAnna Zaks void CallGraphNode::print(raw_ostream &os) const {
2555c32dfc5SAnna Zaks   if (const NamedDecl *ND = dyn_cast_or_null<NamedDecl>(FD))
2568e46c4b8SErich Keane       return ND->printQualifiedName(os);
2575c32dfc5SAnna Zaks   os << "< >";
258c000e7edSAnna Zaks }
259c000e7edSAnna Zaks 
dump() const260cdae941eSYaron Keren LLVM_DUMP_METHOD void CallGraphNode::dump() const {
261c000e7edSAnna Zaks   print(llvm::errs());
262c000e7edSAnna Zaks }
263c000e7edSAnna Zaks 
264c000e7edSAnna Zaks namespace llvm {
265c000e7edSAnna Zaks 
266c000e7edSAnna Zaks template <>
267c000e7edSAnna Zaks struct DOTGraphTraits<const CallGraph*> : public DefaultDOTGraphTraits {
DOTGraphTraitsllvm::DOTGraphTraits268c000e7edSAnna Zaks   DOTGraphTraits (bool isSimple = false) : DefaultDOTGraphTraits(isSimple) {}
269c000e7edSAnna Zaks 
getNodeLabelllvm::DOTGraphTraits270c000e7edSAnna Zaks   static std::string getNodeLabel(const CallGraphNode *Node,
271c000e7edSAnna Zaks                                   const CallGraph *CG) {
272c000e7edSAnna Zaks     if (CG->getRoot() == Node) {
273c000e7edSAnna Zaks       return "< root >";
274c000e7edSAnna Zaks     }
2755c32dfc5SAnna Zaks     if (const NamedDecl *ND = dyn_cast_or_null<NamedDecl>(Node->getDecl()))
2765c32dfc5SAnna Zaks       return ND->getNameAsString();
2775c32dfc5SAnna Zaks     else
2785c32dfc5SAnna Zaks       return "< >";
279c000e7edSAnna Zaks   }
280c000e7edSAnna Zaks };
28138c70521SEugene Zelenko 
28238c70521SEugene Zelenko } // namespace llvm
283