clang API Documentation

CallGraph.cpp
Go to the documentation of this file.
00001 //== CallGraph.cpp - AST-based Call graph  ----------------------*- C++ -*--==//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 //
00010 //  This file defines the AST-based CallGraph.
00011 //
00012 //===----------------------------------------------------------------------===//
00013 #include "clang/Analysis/CallGraph.h"
00014 
00015 #include "clang/AST/ASTContext.h"
00016 #include "clang/AST/Decl.h"
00017 #include "clang/AST/StmtVisitor.h"
00018 
00019 #include "llvm/Support/GraphWriter.h"
00020 
00021 using namespace clang;
00022 
00023 namespace {
00024 /// A helper class, which walks the AST and locates all the call sites in the
00025 /// given function body.
00026 class CGBuilder : public StmtVisitor<CGBuilder> {
00027   CallGraph *G;
00028   const Decl *FD;
00029   CallGraphNode *CallerNode;
00030 
00031 public:
00032   CGBuilder(CallGraph *g, const Decl *D, CallGraphNode *N)
00033     : G(g), FD(D), CallerNode(N) {}
00034 
00035   void VisitStmt(Stmt *S) { VisitChildren(S); }
00036 
00037   void VisitCallExpr(CallExpr *CE) {
00038     // TODO: We need to handle ObjC method calls as well.
00039     if (FunctionDecl *CalleeDecl = CE->getDirectCallee())
00040       if (G->includeInGraph(CalleeDecl)) {
00041         CallGraphNode *CalleeNode = G->getOrInsertNode(CalleeDecl);
00042         CallerNode->addCallee(CalleeNode, G);
00043       }
00044   }
00045 
00046   void VisitChildren(Stmt *S) {
00047     for (Stmt::child_range I = S->children(); I; ++I)
00048       if (*I)
00049         static_cast<CGBuilder*>(this)->Visit(*I);
00050   }
00051 };
00052 
00053 } // end anonymous namespace
00054 
00055 CallGraph::CallGraph() {
00056   Root = getOrInsertNode(0);
00057 }
00058 
00059 CallGraph::~CallGraph() {
00060   if (!FunctionMap.empty()) {
00061     for (FunctionMapTy::iterator I = FunctionMap.begin(), E = FunctionMap.end();
00062         I != E; ++I)
00063       delete I->second;
00064     FunctionMap.clear();
00065   }
00066 }
00067 
00068 bool CallGraph::includeInGraph(const Decl *D) {
00069   if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
00070     // We skip function template definitions, as their semantics is
00071     // only determined when they are instantiated.
00072     if (!FD->isThisDeclarationADefinition() ||
00073         FD->isDependentContext())
00074       return false;
00075 
00076     IdentifierInfo *II = FD->getIdentifier();
00077     if (II && II->getName().startswith("__inline"))
00078       return false;
00079   }
00080 
00081   if (const ObjCMethodDecl *ID = dyn_cast<ObjCMethodDecl>(D)) {
00082     if (!ID->isThisDeclarationADefinition())
00083       return false;
00084   }
00085 
00086   return true;
00087 }
00088 
00089 void CallGraph::addNodeForDecl(Decl* D, bool IsGlobal) {
00090   assert(D);
00091 
00092   // Do nothing if the node already exists.
00093   if (FunctionMap.find(D) != FunctionMap.end())
00094     return;
00095 
00096   // Allocate a new node, mark it as root, and process it's calls.
00097   CallGraphNode *Node = getOrInsertNode(D);
00098   if (IsGlobal)
00099     Root->addCallee(Node, this);
00100 
00101   // Process all the calls by this function as well.
00102   CGBuilder builder(this, D, Node);
00103   if (Stmt *Body = D->getBody())
00104     builder.Visit(Body);
00105 }
00106 
00107 CallGraphNode *CallGraph::getNode(const Decl *F) const {
00108   FunctionMapTy::const_iterator I = FunctionMap.find(F);
00109   if (I == FunctionMap.end()) return 0;
00110   return I->second;
00111 }
00112 
00113 CallGraphNode *CallGraph::getOrInsertNode(Decl *F) {
00114   CallGraphNode *&Node = FunctionMap[F];
00115   if (Node)
00116     return Node;
00117 
00118   Node = new CallGraphNode(F);
00119   // If not root, add to the parentless list.
00120   if (F != 0)
00121     ParentlessNodes.insert(Node);
00122   return Node;
00123 }
00124 
00125 void CallGraph::print(raw_ostream &OS) const {
00126   OS << " --- Call graph Dump --- \n";
00127   for (const_iterator I = begin(), E = end(); I != E; ++I) {
00128     OS << "  Function: ";
00129     if (I->second == Root)
00130       OS << "< root >";
00131     else
00132       I->second->print(OS);
00133     OS << " calls: ";
00134     for (CallGraphNode::iterator CI = I->second->begin(),
00135         CE = I->second->end(); CI != CE; ++CI) {
00136       assert(*CI != Root && "No one can call the root node.");
00137       (*CI)->print(OS);
00138       OS << " ";
00139     }
00140     OS << '\n';
00141   }
00142   OS.flush();
00143 }
00144 
00145 void CallGraph::dump() const {
00146   print(llvm::errs());
00147 }
00148 
00149 void CallGraph::viewGraph() const {
00150   llvm::ViewGraph(this, "CallGraph");
00151 }
00152 
00153 StringRef CallGraphNode::getName() const {
00154   if (const FunctionDecl *D = dyn_cast_or_null<FunctionDecl>(FD))
00155     if (const IdentifierInfo *II = D->getIdentifier())
00156       return II->getName();
00157     return "< >";
00158 }
00159 
00160 void CallGraphNode::print(raw_ostream &os) const {
00161   os << getName();
00162 }
00163 
00164 void CallGraphNode::dump() const {
00165   print(llvm::errs());
00166 }
00167 
00168 namespace llvm {
00169 
00170 template <>
00171 struct DOTGraphTraits<const CallGraph*> : public DefaultDOTGraphTraits {
00172 
00173   DOTGraphTraits (bool isSimple=false) : DefaultDOTGraphTraits(isSimple) {}
00174 
00175   static std::string getNodeLabel(const CallGraphNode *Node,
00176                                   const CallGraph *CG) {
00177     if (CG->getRoot() == Node) {
00178       return "< root >";
00179     }
00180     return Node->getName();
00181   }
00182 
00183 };
00184 }