1 //== CallGraph.cpp - Call graph building ------------------------*- C++ -*--==//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file defined the CallGraph and CGBuilder classes.
12 //===----------------------------------------------------------------------===//
14 #include "clang/Index/CallGraph.h"
16 #include "clang/AST/ASTContext.h"
17 #include "clang/AST/StmtVisitor.h"
19 #include "llvm/Support/GraphWriter.h"
21 using namespace clang;
25 class CGBuilder : public StmtVisitor<CGBuilder> {
32 CallGraphNode *CallerNode;
35 CGBuilder(CallGraph &g, FunctionDecl *fd, Entity E, CallGraphNode *N)
36 : G(g), FD(fd), CallerEnt(E), CallerNode(N) {}
38 void VisitStmt(Stmt *S) { VisitChildren(S); }
40 void VisitCallExpr(CallExpr *CE);
42 void VisitChildren(Stmt *S) {
43 for (Stmt::child_iterator I=S->child_begin(), E=S->child_end(); I != E;++I)
45 static_cast<CGBuilder*>(this)->Visit(*I);
50 void CGBuilder::VisitCallExpr(CallExpr *CE) {
51 if (FunctionDecl *CalleeDecl = CE->getDirectCallee()) {
52 Entity Ent = Entity::get(CalleeDecl, G.getProgram());
53 CallGraphNode *CalleeNode = G.getOrInsertFunction(Ent);
54 CallerNode->addCallee(ASTLocation(FD, CE), CalleeNode);
58 CallGraph::CallGraph() : Root(0) {
59 ExternalCallingNode = getOrInsertFunction(Entity());
62 CallGraph::~CallGraph() {
63 if (!FunctionMap.empty()) {
64 for (FunctionMapTy::iterator I = FunctionMap.begin(), E = FunctionMap.end();
71 void CallGraph::addTU(ASTContext& Ctx) {
72 DeclContext *DC = Ctx.getTranslationUnitDecl();
73 for (DeclContext::decl_iterator I = DC->decls_begin(), E = DC->decls_end();
76 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(*I)) {
77 if (FD->isThisDeclarationADefinition()) {
78 // Set caller's ASTContext.
79 Entity Ent = Entity::get(FD, Prog);
80 CallGraphNode *Node = getOrInsertFunction(Ent);
81 CallerCtx[Node] = &Ctx;
83 // If this function has external linkage, anything could call it.
85 ExternalCallingNode->addCallee(idx::ASTLocation(), Node);
87 // Set root node to 'main' function.
88 if (FD->getNameAsString() == "main")
91 CGBuilder builder(*this, FD, Ent, Node);
92 builder.Visit(FD->getBody());
98 CallGraphNode *CallGraph::getOrInsertFunction(Entity F) {
99 CallGraphNode *&Node = FunctionMap[F];
103 return Node = new CallGraphNode(F);
106 Decl *CallGraph::getDecl(CallGraphNode *Node) {
107 // Get the function's context.
108 ASTContext *Ctx = CallerCtx[Node];
110 return Node->getDecl(*Ctx);
113 void CallGraph::print(llvm::raw_ostream &os) {
114 for (iterator I = begin(), E = end(); I != E; ++I) {
115 if (I->second->hasCallee()) {
116 os << "function: " << I->first.getPrintableName()
118 for (CallGraphNode::iterator CI = I->second->begin(),
119 CE = I->second->end(); CI != CE; ++CI) {
120 os << " " << CI->second->getName();
127 void CallGraph::dump() {
131 void CallGraph::ViewCallGraph() const {
132 llvm::ViewGraph(*this, "CallGraph");
138 struct DOTGraphTraits<CallGraph> : public DefaultDOTGraphTraits {
140 DOTGraphTraits (bool isSimple=false) : DefaultDOTGraphTraits(isSimple) {}
142 static std::string getNodeLabel(const CallGraphNode *Node,
143 const CallGraph &CG) {
144 return Node->getName();