Add include needed for MSVC.
[clang/acc.git] / lib / Analysis / CallGraph.cpp
blobcf8f6205abe4db6a99a2e5c369128f9ca798cbdc
1 //== 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.
12 //===----------------------------------------------------------------------===//
14 #include "clang/Analysis/CallGraph.h"
16 #include "clang/AST/ASTContext.h"
17 #include "clang/AST/StmtVisitor.h"
19 using namespace clang;
20 using namespace idx;
22 namespace {
23 class CGBuilder : public StmtVisitor<CGBuilder> {
25 CallGraph &G;
26 FunctionDecl *FD;
28 Entity *CallerEnt;
30 CallGraphNode *CallerNode;
32 public:
33 CGBuilder(CallGraph &g, FunctionDecl *fd, Entity *E, CallGraphNode *N)
34 : G(g), FD(fd), CallerEnt(E), CallerNode(N) {}
36 void VisitStmt(Stmt *S) { VisitChildren(S); }
38 void VisitCallExpr(CallExpr *CE);
40 void VisitChildren(Stmt *S) {
41 for (Stmt::child_iterator I=S->child_begin(), E=S->child_end(); I != E;++I)
42 if (*I)
43 static_cast<CGBuilder*>(this)->Visit(*I);
48 void CGBuilder::VisitCallExpr(CallExpr *CE) {
49 if (FunctionDecl *CalleeDecl = CE->getDirectCallee()) {
50 Entity *Ent = Entity::get(CalleeDecl, G.getProgram());
51 CallGraphNode *CalleeNode = G.getOrInsertFunction(Ent);
53 Decl *Parent = ASTLocation::FindImmediateParent(FD, CE);
55 CallerNode->addCallee(ASTLocation(Parent, CE), CalleeNode);
59 CallGraph::~CallGraph() {
60 if (!FunctionMap.empty()) {
61 for (FunctionMapTy::iterator I = FunctionMap.begin(), E = FunctionMap.end();
62 I != E; ++I)
63 delete I->second;
64 FunctionMap.clear();
68 void CallGraph::addTU(ASTUnit &AST) {
69 ASTContext &Ctx = AST.getASTContext();
70 DeclContext *DC = Ctx.getTranslationUnitDecl();
72 for (DeclContext::decl_iterator I = DC->decls_begin(), E = DC->decls_end();
73 I != E; ++I) {
75 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(*I)) {
76 if (FD->isThisDeclarationADefinition()) {
77 // Set caller's ASTContext.
78 Entity *Ent = Entity::get(FD, Prog);
79 CallGraphNode *Node = getOrInsertFunction(Ent);
80 CallerCtx[Node] = &Ctx;
82 CGBuilder builder(*this, FD, Ent, Node);
83 builder.Visit(FD->getBody());
89 CallGraphNode *CallGraph::getOrInsertFunction(Entity *F) {
90 CallGraphNode *&Node = FunctionMap[F];
91 if (Node)
92 return Node;
94 return Node = new CallGraphNode(F);
97 void CallGraph::print(llvm::raw_ostream &os) {
98 for (iterator I = begin(), E = end(); I != E; ++I) {
99 if (I->second->hasCallee()) {
100 ASTContext &Ctx = *CallerCtx[I->second];
101 os << "function: " << I->first->getPrintableName(Ctx).c_str()
102 << " calls:\n";
103 for (CallGraphNode::iterator CI = I->second->begin(),
104 CE = I->second->end(); CI != CE; ++CI) {
105 os << " " << CI->second->getName(Ctx).c_str();
107 os << '\n';
112 void CallGraph::dump() {
113 print(llvm::errs());