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