diff options
author | Anna Zaks <ganna@apple.com> | 2012-03-13 19:32:08 +0000 |
---|---|---|
committer | Anna Zaks <ganna@apple.com> | 2012-03-13 19:32:08 +0000 |
commit | 32da47b9a1373d8379b6f5b390e98ec43c314e49 (patch) | |
tree | be1e0503ba882c81f666ab61fd9250808d5e8190 /clang/lib | |
parent | 14189514054461f3139f02f2fcc13c47858fbb22 (diff) | |
download | bcm5719-llvm-32da47b9a1373d8379b6f5b390e98ec43c314e49.tar.gz bcm5719-llvm-32da47b9a1373d8379b6f5b390e98ec43c314e49.zip |
[analyzer] Refactor CallGraph to use Recursive AST visitor when
collecting function Decls.
llvm-svn: 152651
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/Analysis/CallGraph.cpp | 68 | ||||
-rw-r--r-- | clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp | 11 |
2 files changed, 37 insertions, 42 deletions
diff --git a/clang/lib/Analysis/CallGraph.cpp b/clang/lib/Analysis/CallGraph.cpp index cc6e62c388e..1e9aec23dd6 100644 --- a/clang/lib/Analysis/CallGraph.cpp +++ b/clang/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 { diff --git a/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp b/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp index 93a3ab47b98..a97ff4a1cd2 100644 --- a/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp +++ b/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp @@ -206,9 +206,9 @@ public: virtual void HandleTranslationUnit(ASTContext &C); - /// \brief Build the call graph for the context and use it to define the order + /// \brief Build the call graph for the TU and use it to define the order /// in which the functions should be visited. - void HandleDeclContextGallGraph(ASTContext &C, DeclContext *dc); + void HandleDeclsGallGraph(TranslationUnitDecl *TU); /// \brief Run analyzes(syntax or path sensitive) on the given function. /// \param Mode - determines if we are requesting syntax only or path @@ -261,12 +261,11 @@ public: //===----------------------------------------------------------------------===// llvm::Timer* AnalysisConsumer::TUTotalTimer = 0; -void AnalysisConsumer::HandleDeclContextGallGraph(ASTContext &C, - DeclContext *dc) { +void AnalysisConsumer::HandleDeclsGallGraph(TranslationUnitDecl *TU) { // Otherwise, use the Callgraph to derive the order. // Build the Call Graph. CallGraph CG; - CG.addToCallGraph(dc); + CG.addToCallGraph(TU); // Find the top level nodes - children of root + the unreachable (parentless) // nodes. @@ -334,7 +333,7 @@ void AnalysisConsumer::HandleTranslationUnit(ASTContext &C) { TraverseDecl(TU); if (Mgr->shouldInlineCall()) - HandleDeclContextGallGraph(C, TU); + HandleDeclsGallGraph(TU); // After all decls handled, run checkers on the entire TranslationUnit. checkerMgr->runCheckersOnEndOfTranslationUnit(TU, *Mgr, BR); |