Home | History | Annotate | Line # | Download | only in Analysis
      1      1.1  joerg //===- CallGraph.cpp - AST-based Call graph -------------------------------===//
      2      1.1  joerg //
      3      1.1  joerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
      4      1.1  joerg // See https://llvm.org/LICENSE.txt for license information.
      5      1.1  joerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
      6      1.1  joerg //
      7      1.1  joerg //===----------------------------------------------------------------------===//
      8      1.1  joerg //
      9      1.1  joerg //  This file defines the AST-based CallGraph.
     10      1.1  joerg //
     11      1.1  joerg //===----------------------------------------------------------------------===//
     12      1.1  joerg 
     13      1.1  joerg #include "clang/Analysis/CallGraph.h"
     14      1.1  joerg #include "clang/AST/Decl.h"
     15      1.1  joerg #include "clang/AST/DeclBase.h"
     16      1.1  joerg #include "clang/AST/DeclObjC.h"
     17      1.1  joerg #include "clang/AST/Expr.h"
     18      1.1  joerg #include "clang/AST/ExprObjC.h"
     19      1.1  joerg #include "clang/AST/Stmt.h"
     20      1.1  joerg #include "clang/AST/StmtVisitor.h"
     21      1.1  joerg #include "clang/Basic/IdentifierTable.h"
     22      1.1  joerg #include "clang/Basic/LLVM.h"
     23      1.1  joerg #include "llvm/ADT/PostOrderIterator.h"
     24      1.1  joerg #include "llvm/ADT/STLExtras.h"
     25      1.1  joerg #include "llvm/ADT/Statistic.h"
     26      1.1  joerg #include "llvm/Support/Casting.h"
     27      1.1  joerg #include "llvm/Support/Compiler.h"
     28      1.1  joerg #include "llvm/Support/DOTGraphTraits.h"
     29      1.1  joerg #include "llvm/Support/GraphWriter.h"
     30      1.1  joerg #include "llvm/Support/raw_ostream.h"
     31      1.1  joerg #include <cassert>
     32      1.1  joerg #include <memory>
     33      1.1  joerg #include <string>
     34      1.1  joerg 
     35      1.1  joerg using namespace clang;
     36      1.1  joerg 
     37      1.1  joerg #define DEBUG_TYPE "CallGraph"
     38      1.1  joerg 
     39      1.1  joerg STATISTIC(NumObjCCallEdges, "Number of Objective-C method call edges");
     40      1.1  joerg STATISTIC(NumBlockCallEdges, "Number of block call edges");
     41      1.1  joerg 
     42      1.1  joerg namespace {
     43      1.1  joerg 
     44      1.1  joerg /// A helper class, which walks the AST and locates all the call sites in the
     45      1.1  joerg /// given function body.
     46      1.1  joerg class CGBuilder : public StmtVisitor<CGBuilder> {
     47      1.1  joerg   CallGraph *G;
     48      1.1  joerg   CallGraphNode *CallerNode;
     49      1.1  joerg 
     50      1.1  joerg public:
     51      1.1  joerg   CGBuilder(CallGraph *g, CallGraphNode *N) : G(g), CallerNode(N) {}
     52      1.1  joerg 
     53      1.1  joerg   void VisitStmt(Stmt *S) { VisitChildren(S); }
     54      1.1  joerg 
     55      1.1  joerg   Decl *getDeclFromCall(CallExpr *CE) {
     56      1.1  joerg     if (FunctionDecl *CalleeDecl = CE->getDirectCallee())
     57      1.1  joerg       return CalleeDecl;
     58      1.1  joerg 
     59      1.1  joerg     // Simple detection of a call through a block.
     60      1.1  joerg     Expr *CEE = CE->getCallee()->IgnoreParenImpCasts();
     61      1.1  joerg     if (BlockExpr *Block = dyn_cast<BlockExpr>(CEE)) {
     62      1.1  joerg       NumBlockCallEdges++;
     63      1.1  joerg       return Block->getBlockDecl();
     64      1.1  joerg     }
     65      1.1  joerg 
     66      1.1  joerg     return nullptr;
     67      1.1  joerg   }
     68      1.1  joerg 
     69  1.1.1.2  joerg   void addCalledDecl(Decl *D, Expr *CallExpr) {
     70  1.1.1.2  joerg     if (G->includeCalleeInGraph(D)) {
     71      1.1  joerg       CallGraphNode *CalleeNode = G->getOrInsertNode(D);
     72  1.1.1.2  joerg       CallerNode->addCallee({CalleeNode, CallExpr});
     73      1.1  joerg     }
     74      1.1  joerg   }
     75      1.1  joerg 
     76      1.1  joerg   void VisitCallExpr(CallExpr *CE) {
     77      1.1  joerg     if (Decl *D = getDeclFromCall(CE))
     78  1.1.1.2  joerg       addCalledDecl(D, CE);
     79      1.1  joerg     VisitChildren(CE);
     80      1.1  joerg   }
     81      1.1  joerg 
     82      1.1  joerg   void VisitLambdaExpr(LambdaExpr *LE) {
     83      1.1  joerg     if (FunctionTemplateDecl *FTD = LE->getDependentCallOperator())
     84      1.1  joerg       for (FunctionDecl *FD : FTD->specializations())
     85      1.1  joerg         G->VisitFunctionDecl(FD);
     86      1.1  joerg     else if (CXXMethodDecl *MD = LE->getCallOperator())
     87      1.1  joerg       G->VisitFunctionDecl(MD);
     88      1.1  joerg   }
     89      1.1  joerg 
     90      1.1  joerg   void VisitCXXNewExpr(CXXNewExpr *E) {
     91      1.1  joerg     if (FunctionDecl *FD = E->getOperatorNew())
     92  1.1.1.2  joerg       addCalledDecl(FD, E);
     93      1.1  joerg     VisitChildren(E);
     94      1.1  joerg   }
     95      1.1  joerg 
     96      1.1  joerg   void VisitCXXConstructExpr(CXXConstructExpr *E) {
     97      1.1  joerg     CXXConstructorDecl *Ctor = E->getConstructor();
     98      1.1  joerg     if (FunctionDecl *Def = Ctor->getDefinition())
     99  1.1.1.2  joerg       addCalledDecl(Def, E);
    100      1.1  joerg     VisitChildren(E);
    101      1.1  joerg   }
    102      1.1  joerg 
    103      1.1  joerg   // Include the evaluation of the default argument.
    104      1.1  joerg   void VisitCXXDefaultArgExpr(CXXDefaultArgExpr *E) {
    105      1.1  joerg     Visit(E->getExpr());
    106      1.1  joerg   }
    107      1.1  joerg 
    108      1.1  joerg   // Include the evaluation of the default initializers in a class.
    109      1.1  joerg   void VisitCXXDefaultInitExpr(CXXDefaultInitExpr *E) {
    110      1.1  joerg     Visit(E->getExpr());
    111      1.1  joerg   }
    112      1.1  joerg 
    113      1.1  joerg   // Adds may-call edges for the ObjC message sends.
    114      1.1  joerg   void VisitObjCMessageExpr(ObjCMessageExpr *ME) {
    115      1.1  joerg     if (ObjCInterfaceDecl *IDecl = ME->getReceiverInterface()) {
    116      1.1  joerg       Selector Sel = ME->getSelector();
    117      1.1  joerg 
    118      1.1  joerg       // Find the callee definition within the same translation unit.
    119      1.1  joerg       Decl *D = nullptr;
    120      1.1  joerg       if (ME->isInstanceMessage())
    121      1.1  joerg         D = IDecl->lookupPrivateMethod(Sel);
    122      1.1  joerg       else
    123      1.1  joerg         D = IDecl->lookupPrivateClassMethod(Sel);
    124      1.1  joerg       if (D) {
    125  1.1.1.2  joerg         addCalledDecl(D, ME);
    126      1.1  joerg         NumObjCCallEdges++;
    127      1.1  joerg       }
    128      1.1  joerg     }
    129      1.1  joerg   }
    130      1.1  joerg 
    131      1.1  joerg   void VisitChildren(Stmt *S) {
    132      1.1  joerg     for (Stmt *SubStmt : S->children())
    133      1.1  joerg       if (SubStmt)
    134      1.1  joerg         this->Visit(SubStmt);
    135      1.1  joerg   }
    136      1.1  joerg };
    137      1.1  joerg 
    138      1.1  joerg } // namespace
    139      1.1  joerg 
    140      1.1  joerg void CallGraph::addNodesForBlocks(DeclContext *D) {
    141      1.1  joerg   if (BlockDecl *BD = dyn_cast<BlockDecl>(D))
    142      1.1  joerg     addNodeForDecl(BD, true);
    143      1.1  joerg 
    144      1.1  joerg   for (auto *I : D->decls())
    145      1.1  joerg     if (auto *DC = dyn_cast<DeclContext>(I))
    146      1.1  joerg       addNodesForBlocks(DC);
    147      1.1  joerg }
    148      1.1  joerg 
    149      1.1  joerg CallGraph::CallGraph() {
    150      1.1  joerg   Root = getOrInsertNode(nullptr);
    151      1.1  joerg }
    152      1.1  joerg 
    153      1.1  joerg CallGraph::~CallGraph() = default;
    154      1.1  joerg 
    155      1.1  joerg bool CallGraph::includeInGraph(const Decl *D) {
    156      1.1  joerg   assert(D);
    157      1.1  joerg   if (!D->hasBody())
    158      1.1  joerg     return false;
    159      1.1  joerg 
    160  1.1.1.2  joerg   return includeCalleeInGraph(D);
    161  1.1.1.2  joerg }
    162  1.1.1.2  joerg 
    163  1.1.1.2  joerg bool CallGraph::includeCalleeInGraph(const Decl *D) {
    164      1.1  joerg   if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
    165      1.1  joerg     // We skip function template definitions, as their semantics is
    166      1.1  joerg     // only determined when they are instantiated.
    167      1.1  joerg     if (FD->isDependentContext())
    168      1.1  joerg       return false;
    169      1.1  joerg 
    170      1.1  joerg     IdentifierInfo *II = FD->getIdentifier();
    171      1.1  joerg     if (II && II->getName().startswith("__inline"))
    172      1.1  joerg       return false;
    173      1.1  joerg   }
    174      1.1  joerg 
    175      1.1  joerg   return true;
    176      1.1  joerg }
    177      1.1  joerg 
    178      1.1  joerg void CallGraph::addNodeForDecl(Decl* D, bool IsGlobal) {
    179      1.1  joerg   assert(D);
    180      1.1  joerg 
    181      1.1  joerg   // Allocate a new node, mark it as root, and process its calls.
    182      1.1  joerg   CallGraphNode *Node = getOrInsertNode(D);
    183      1.1  joerg 
    184      1.1  joerg   // Process all the calls by this function as well.
    185      1.1  joerg   CGBuilder builder(this, Node);
    186      1.1  joerg   if (Stmt *Body = D->getBody())
    187      1.1  joerg     builder.Visit(Body);
    188      1.1  joerg 
    189      1.1  joerg   // Include C++ constructor member initializers.
    190      1.1  joerg   if (auto constructor = dyn_cast<CXXConstructorDecl>(D)) {
    191      1.1  joerg     for (CXXCtorInitializer *init : constructor->inits()) {
    192      1.1  joerg       builder.Visit(init->getInit());
    193      1.1  joerg     }
    194      1.1  joerg   }
    195      1.1  joerg }
    196      1.1  joerg 
    197      1.1  joerg CallGraphNode *CallGraph::getNode(const Decl *F) const {
    198      1.1  joerg   FunctionMapTy::const_iterator I = FunctionMap.find(F);
    199      1.1  joerg   if (I == FunctionMap.end()) return nullptr;
    200      1.1  joerg   return I->second.get();
    201      1.1  joerg }
    202      1.1  joerg 
    203      1.1  joerg CallGraphNode *CallGraph::getOrInsertNode(Decl *F) {
    204      1.1  joerg   if (F && !isa<ObjCMethodDecl>(F))
    205      1.1  joerg     F = F->getCanonicalDecl();
    206      1.1  joerg 
    207      1.1  joerg   std::unique_ptr<CallGraphNode> &Node = FunctionMap[F];
    208      1.1  joerg   if (Node)
    209      1.1  joerg     return Node.get();
    210      1.1  joerg 
    211      1.1  joerg   Node = std::make_unique<CallGraphNode>(F);
    212      1.1  joerg   // Make Root node a parent of all functions to make sure all are reachable.
    213      1.1  joerg   if (F)
    214  1.1.1.2  joerg     Root->addCallee({Node.get(), /*Call=*/nullptr});
    215      1.1  joerg   return Node.get();
    216      1.1  joerg }
    217      1.1  joerg 
    218      1.1  joerg void CallGraph::print(raw_ostream &OS) const {
    219      1.1  joerg   OS << " --- Call graph Dump --- \n";
    220      1.1  joerg 
    221      1.1  joerg   // We are going to print the graph in reverse post order, partially, to make
    222      1.1  joerg   // sure the output is deterministic.
    223      1.1  joerg   llvm::ReversePostOrderTraversal<const CallGraph *> RPOT(this);
    224      1.1  joerg   for (llvm::ReversePostOrderTraversal<const CallGraph *>::rpo_iterator
    225      1.1  joerg          I = RPOT.begin(), E = RPOT.end(); I != E; ++I) {
    226      1.1  joerg     const CallGraphNode *N = *I;
    227      1.1  joerg 
    228      1.1  joerg     OS << "  Function: ";
    229      1.1  joerg     if (N == Root)
    230      1.1  joerg       OS << "< root >";
    231      1.1  joerg     else
    232      1.1  joerg       N->print(OS);
    233      1.1  joerg 
    234      1.1  joerg     OS << " calls: ";
    235      1.1  joerg     for (CallGraphNode::const_iterator CI = N->begin(),
    236      1.1  joerg                                        CE = N->end(); CI != CE; ++CI) {
    237  1.1.1.2  joerg       assert(CI->Callee != Root && "No one can call the root node.");
    238  1.1.1.2  joerg       CI->Callee->print(OS);
    239      1.1  joerg       OS << " ";
    240      1.1  joerg     }
    241      1.1  joerg     OS << '\n';
    242      1.1  joerg   }
    243      1.1  joerg   OS.flush();
    244      1.1  joerg }
    245      1.1  joerg 
    246      1.1  joerg LLVM_DUMP_METHOD void CallGraph::dump() const {
    247      1.1  joerg   print(llvm::errs());
    248      1.1  joerg }
    249      1.1  joerg 
    250      1.1  joerg void CallGraph::viewGraph() const {
    251      1.1  joerg   llvm::ViewGraph(this, "CallGraph");
    252      1.1  joerg }
    253      1.1  joerg 
    254      1.1  joerg void CallGraphNode::print(raw_ostream &os) const {
    255      1.1  joerg   if (const NamedDecl *ND = dyn_cast_or_null<NamedDecl>(FD))
    256      1.1  joerg       return ND->printQualifiedName(os);
    257      1.1  joerg   os << "< >";
    258      1.1  joerg }
    259      1.1  joerg 
    260      1.1  joerg LLVM_DUMP_METHOD void CallGraphNode::dump() const {
    261      1.1  joerg   print(llvm::errs());
    262      1.1  joerg }
    263      1.1  joerg 
    264      1.1  joerg namespace llvm {
    265      1.1  joerg 
    266      1.1  joerg template <>
    267      1.1  joerg struct DOTGraphTraits<const CallGraph*> : public DefaultDOTGraphTraits {
    268      1.1  joerg   DOTGraphTraits (bool isSimple = false) : DefaultDOTGraphTraits(isSimple) {}
    269      1.1  joerg 
    270      1.1  joerg   static std::string getNodeLabel(const CallGraphNode *Node,
    271      1.1  joerg                                   const CallGraph *CG) {
    272      1.1  joerg     if (CG->getRoot() == Node) {
    273      1.1  joerg       return "< root >";
    274      1.1  joerg     }
    275      1.1  joerg     if (const NamedDecl *ND = dyn_cast_or_null<NamedDecl>(Node->getDecl()))
    276      1.1  joerg       return ND->getNameAsString();
    277      1.1  joerg     else
    278      1.1  joerg       return "< >";
    279      1.1  joerg   }
    280      1.1  joerg };
    281      1.1  joerg 
    282      1.1  joerg } // namespace llvm
    283