aboutsummaryrefslogtreecommitdiff
path: root/lib/Analysis/CallGraph.cpp
diff options
context:
space:
mode:
authorAnna Zaks <ganna@apple.com>2012-03-13 19:32:08 +0000
committerAnna Zaks <ganna@apple.com>2012-03-13 19:32:08 +0000
commita2e589e60d147f4f04cee5682b8389b55c410244 (patch)
tree55be06b5d7ae97bf16e030947d01e665d0460f00 /lib/Analysis/CallGraph.cpp
parentaa5609891df937291bf962dd2fc7deb2ceae292f (diff)
[analyzer] Refactor CallGraph to use Recursive AST visitor when
collecting function Decls. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@152651 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Analysis/CallGraph.cpp')
-rw-r--r--lib/Analysis/CallGraph.cpp68
1 files changed, 32 insertions, 36 deletions
diff --git a/lib/Analysis/CallGraph.cpp b/lib/Analysis/CallGraph.cpp
index cc6e62c388..1e9aec23dd 100644
--- a/lib/Analysis/CallGraph.cpp
+++ b/lib/Analysis/CallGraph.cpp
@@ -14,6 +14,7 @@
#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
+#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/AST/StmtVisitor.h"
#include "llvm/Support/GraphWriter.h"
@@ -71,6 +72,35 @@ public:
static_cast<CGBuilder*>(this)->Visit(*I);
}
};
+
+/// A helper class which walks the AST declarations.
+// TODO: We might want to specialize the visitor to shrink the call graph.
+// For example, we might not want to include the inline methods from header
+// files.
+class CGDeclVisitor : public RecursiveASTVisitor<CGDeclVisitor> {
+ CallGraph *CG;
+
+public:
+ CGDeclVisitor(CallGraph * InCG) : CG(InCG) {}
+
+ bool VisitFunctionDecl(FunctionDecl *FD) {
+ // We skip function template definitions, as their semantics is
+ // only determined when they are instantiated.
+ if (includeInGraph(FD))
+ // If this function has external linkage, anything could call it.
+ // Note, we are not precise here. For example, the function could have
+ // its address taken.
+ CG->addToCallGraph(FD, FD->isGlobal());
+ return true;
+ }
+
+ bool VisitObjCMethodDecl(ObjCMethodDecl *MD) {
+ if (includeInGraph(MD))
+ CG->addToCallGraph(MD, true);
+ return true;
+ }
+};
+
} // end anonymous namespace
CallGraph::CallGraph() {
@@ -98,42 +128,8 @@ void CallGraph::addToCallGraph(Decl* D, bool IsGlobal) {
builder.Visit(D->getBody());
}
-void CallGraph::addToCallGraph(DeclContext *DC) {
- for (DeclContext::decl_iterator I = DC->decls_begin(), E = DC->decls_end();
- I != E; ++I) {
- Decl *D = *I;
- switch (D->getKind()) {
- case Decl::CXXConstructor:
- case Decl::CXXDestructor:
- case Decl::CXXConversion:
- case Decl::CXXMethod:
- case Decl::Function: {
- FunctionDecl *FD = cast<FunctionDecl>(D);
- // We skip function template definitions, as their semantics is
- // only determined when they are instantiated.
- if (includeInGraph(FD))
- // If this function has external linkage, anything could call it.
- // Note, we are not precise here. For example, the function could have
- // its address taken.
- addToCallGraph(FD, FD->isGlobal());
- break;
- }
-
- case Decl::ObjCCategoryImpl:
- case Decl::ObjCImplementation: {
- ObjCImplDecl *ID = cast<ObjCImplDecl>(D);
- for (ObjCContainerDecl::method_iterator MI = ID->meth_begin(),
- ME = ID->meth_end(); MI != ME; ++MI) {
- if (includeInGraph(*MI))
- addToCallGraph(*MI, true);
- }
- break;
- }
-
- default:
- break;
- }
- }
+void CallGraph::addToCallGraph(TranslationUnitDecl *TU) {
+ CGDeclVisitor(this).TraverseDecl(TU);
}
CallGraphNode *CallGraph::getNode(const Decl *F) const {