blob: 16f14d787f4fcb961dc397a8f020cac4772e1311 [file] [log] [blame]
Zhongxing Xu6bd8fb52009-07-16 00:54:12 +00001//== CallGraph.cpp - Call graph building ------------------------*- C++ -*--==//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file defined the CallGraph and CGBuilder classes.
11//
12//===----------------------------------------------------------------------===//
13
14#include "clang/Analysis/CallGraph.h"
15
16#include "clang/AST/ASTContext.h"
17#include "clang/AST/StmtVisitor.h"
18
19using namespace clang;
20using namespace idx;
21
22namespace {
23class CGBuilder : public StmtVisitor<CGBuilder> {
24
25 CallGraph &G;
26 FunctionDecl *FD;
27
28 Entity *CallerEnt;
29
30 CallGraphNode *CallerNode;
31
32public:
33 CGBuilder(CallGraph &g, FunctionDecl *fd, Entity *E, CallGraphNode *N)
34 : G(g), FD(fd), CallerEnt(E), CallerNode(N) {}
35
Zhongxing Xu6fc45052009-07-17 07:05:19 +000036 void VisitCompoundStmt(CompoundStmt *S) { VisitChildren(S); }
Zhongxing Xu6bd8fb52009-07-16 00:54:12 +000037
Zhongxing Xu6fc45052009-07-17 07:05:19 +000038 void VisitCastStmt(CaseStmt *S) { VisitChildren(S); }
39
40 void VisitDefaultStmt(DefaultStmt *S) { VisitChildren(S); }
41
42 void VisitLabelStmt(LabelStmt *S) { VisitChildren(S); }
43
44 void VisitIfStmt(IfStmt *S) { VisitChildren(S); }
45
46 void VisitSwitchStmt(SwitchStmt *S) { VisitChildren(S); }
47
48 void VisitDoStmt(DoStmt *S) { VisitChildren(S); }
49
50 void VisitForStmt(ForStmt *S) { VisitChildren(S); }
51
52 void VisitIndirectGotoStmt(IndirectGotoStmt *S) { VisitChildren(S); }
53
54 void VisitReturnStmt(ReturnStmt *S) { VisitChildren(S); }
55
56 void VisitDeclStmt(DeclStmt *S) { VisitChildren(S); }
Zhongxing Xu24ff0302009-07-17 05:49:16 +000057
Zhongxing Xu6bd8fb52009-07-16 00:54:12 +000058 void VisitCallExpr(CallExpr *CE);
59
60 void VisitChildren(Stmt *S) {
61 for (Stmt::child_iterator I=S->child_begin(), E=S->child_end(); I != E;++I)
62 if (*I)
63 static_cast<CGBuilder*>(this)->Visit(*I);
64 }
65};
66}
67
68void CGBuilder::VisitCallExpr(CallExpr *CE) {
69 Expr *Callee = CE->getCallee();
70
71 if (CastExpr *CE = dyn_cast<CastExpr>(Callee))
72 Callee = CE->getSubExpr();
73
74 if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Callee)) {
75 Decl *D = DRE->getDecl();
76 if (FunctionDecl *CalleeDecl = dyn_cast<FunctionDecl>(D)) {
77
78 Entity *Ent = Entity::get(CalleeDecl, G.getProgram());
79
80 CallGraphNode *CalleeNode = G.getOrInsertFunction(Ent);
81
82 CallerNode->addCallee(ASTLocation(FD, CE), CalleeNode);
83 }
84 }
85}
86
87CallGraph::~CallGraph() {
88 if (!FunctionMap.empty()) {
89 for (FunctionMapTy::iterator I = FunctionMap.begin(), E = FunctionMap.end();
90 I != E; ++I)
91 delete I->second;
92 FunctionMap.clear();
93 }
94}
95
96void CallGraph::addTU(ASTUnit &AST) {
97 ASTContext &Ctx = AST.getASTContext();
98 DeclContext *DC = Ctx.getTranslationUnitDecl();
99
100 for (DeclContext::decl_iterator I = DC->decls_begin(), E = DC->decls_end();
101 I != E; ++I) {
102
103 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(*I)) {
104 if (FD->isThisDeclarationADefinition()) {
105 // Set caller's ASTContext.
106 Entity *Ent = Entity::get(FD, Prog);
107 CallGraphNode *Node = getOrInsertFunction(Ent);
108 CallerCtx[Node] = &Ctx;
109
110 CGBuilder builder(*this, FD, Ent, Node);
111 builder.Visit(FD->getBody());
112 }
113 }
114 }
115}
116
117CallGraphNode *CallGraph::getOrInsertFunction(Entity *F) {
118 CallGraphNode *&Node = FunctionMap[F];
119 if (Node)
120 return Node;
121
122 return Node = new CallGraphNode(F);
123}
124
125void CallGraph::print(llvm::raw_ostream &os) {
126 for (iterator I = begin(), E = end(); I != E; ++I) {
Zhongxing Xu24ff0302009-07-17 05:49:16 +0000127 if (I->second->hasCallee()) {
128 ASTContext &Ctx = *CallerCtx[I->second];
129 os << "function: " << I->first->getName(Ctx) << " calls:\n";
130 for (CallGraphNode::iterator CI = I->second->begin(),
131 CE = I->second->end(); CI != CE; ++CI) {
132 os << " " << CI->second->getName(Ctx);
133 }
134 os << '\n';
Zhongxing Xu6bd8fb52009-07-16 00:54:12 +0000135 }
Zhongxing Xu6bd8fb52009-07-16 00:54:12 +0000136 }
137}
138
139void CallGraph::dump() {
140 print(llvm::errs());
141}