diff options
Diffstat (limited to 'Driver/AnalysisConsumer.cpp')
-rw-r--r-- | Driver/AnalysisConsumer.cpp | 228 |
1 files changed, 155 insertions, 73 deletions
diff --git a/Driver/AnalysisConsumer.cpp b/Driver/AnalysisConsumer.cpp index 5c1e3d87bf..66fe299e37 100644 --- a/Driver/AnalysisConsumer.cpp +++ b/Driver/AnalysisConsumer.cpp @@ -42,18 +42,124 @@ using namespace clang; static ExplodedNodeImpl::Auditor* CreateUbiViz(); -// Analyzer options. +//===----------------------------------------------------------------------===// +// Analyzer Options: available analyses. +//===----------------------------------------------------------------------===// + +/// Analysis - Set of available source code analyses. +enum Analyses { +#define ANALYSIS(NAME, CMDFLAG, DESC, SCOPE) NAME, +#include "Analyses.def" +NumAnalyses +}; + +static llvm::cl::list<Analyses> +AnalysisList(llvm::cl::desc("Source Code Analysis - Checks and Analyses"), +llvm::cl::values( +#define ANALYSIS(NAME, CMDFLAG, DESC, SCOPE)\ +clEnumValN(NAME, CMDFLAG, DESC), +#include "Analyses.def" +clEnumValEnd)); + +//===----------------------------------------------------------------------===// +// Analyzer Options: store model. +//===----------------------------------------------------------------------===// + +/// AnalysisStores - Set of available analysis store models. +enum AnalysisStores { +#define ANALYSIS_STORE(NAME, CMDFLAG, DESC, CREATFN) NAME##Model, +#include "Analyses.def" +NumStores +}; + +static llvm::cl::opt<AnalysisStores> +AnalysisStoreOpt("analyzer-store", + llvm::cl::desc("Source Code Analysis - Abstract Memory Store Models"), + llvm::cl::init(BasicStoreModel), + llvm::cl::values( +#define ANALYSIS_STORE(NAME, CMDFLAG, DESC, CREATFN)\ +clEnumValN(NAME##Model, CMDFLAG, DESC), +#include "Analyses.def" +clEnumValEnd)); + +//===----------------------------------------------------------------------===// +// Analyzer Options: constraint engines. +//===----------------------------------------------------------------------===// + +/// AnalysisConstraints - Set of available constraint models. +enum AnalysisConstraints { +#define ANALYSIS_CONSTRAINTS(NAME, CMDFLAG, DESC, CREATFN) NAME##Model, +#include "Analyses.def" +NumConstraints +}; + +static llvm::cl::opt<AnalysisConstraints> +AnalysisConstraintsOpt("analyzer-constraints", + llvm::cl::desc("Source Code Analysis - Symbolic Constraint Engines"), + llvm::cl::init(BasicConstraintsModel), + llvm::cl::values( +#define ANALYSIS_CONSTRAINTS(NAME, CMDFLAG, DESC, CREATFN)\ +clEnumValN(NAME##Model, CMDFLAG, DESC), +#include "Analyses.def" +clEnumValEnd)); + +//===----------------------------------------------------------------------===// +// Analyzer Options: diagnostic clients. +//===----------------------------------------------------------------------===// + +/// AnalysisDiagClients - Set of available diagnostic clients for rendering +/// analysis results. +enum AnalysisDiagClients { +#define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATFN, AUTOCREAT) PD_##NAME, +#include "Analyses.def" +NUM_ANALYSIS_DIAG_CLIENTS +}; + +static llvm::cl::opt<AnalysisDiagClients> +AnalysisDiagOpt("analyzer-output", + llvm::cl::desc("Source Code Analysis - Output Options"), + llvm::cl::init(PD_HTML), + llvm::cl::values( +#define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATFN, AUTOCREATE)\ +clEnumValN(PD_##NAME, CMDFLAG, DESC), +#include "Analyses.def" +clEnumValEnd)); + +//===----------------------------------------------------------------------===// +// Misc. fun options. +//===----------------------------------------------------------------------===// + +static llvm::cl::opt<bool> +VisualizeEGDot("analyzer-viz-egraph-graphviz", + llvm::cl::desc("Display exploded graph using GraphViz")); + +static llvm::cl::opt<bool> +VisualizeEGUbi("analyzer-viz-egraph-ubigraph", + llvm::cl::desc("Display exploded graph using Ubigraph")); + +static llvm::cl::opt<bool> +AnalyzeAll("analyzer-opt-analyze-headers", + llvm::cl::desc("Force the static analyzer to analyze " + "functions defined in header files")); + +static llvm::cl::opt<bool> +AnalyzerDisplayProgress("analyzer-display-progress", + llvm::cl::desc("Emit verbose output about the analyzer's progress.")); + static llvm::cl::opt<bool> PurgeDead("analyzer-purge-dead", llvm::cl::init(true), llvm::cl::desc("Remove dead symbols, bindings, and constraints before" " processing a statement.")); + +static llvm::cl::opt<std::string> +AnalyzeSpecificFunction("analyze-function", + llvm::cl::desc("Run analysis on specific function")); + static llvm::cl::opt<bool> -UseRanges("analyzer-range-constraints", - llvm::cl::init(false), - llvm::cl::desc("Use the range constraint manager instead of the basic" - " constraint manager")); - +TrimGraph("trim-egraph", + llvm::cl::desc("Only show error-related paths in the analysis graph")); + //===----------------------------------------------------------------------===// // Basic type definitions. //===----------------------------------------------------------------------===// @@ -77,37 +183,21 @@ namespace { Actions TranslationUnitActions; public: - const bool VisGraphviz; - const bool VisUbigraph; - const bool TrimGraph; const LangOptions& LOpts; Diagnostic &Diags; ASTContext* Ctx; Preprocessor* PP; PreprocessorFactory* PPF; - const std::string HTMLDir; - const std::string FName; + const std::string OutDir; llvm::OwningPtr<PathDiagnosticClient> PD; - bool AnalyzeAll; - AnalysisStores SM; - AnalysisDiagClients DC; - const bool DisplayProgress; AnalysisConsumer(Diagnostic &diags, Preprocessor* pp, PreprocessorFactory* ppf, const LangOptions& lopts, - const std::string& fname, - const std::string& htmldir, - AnalysisStores sm, AnalysisDiagClients dc, - bool visgraphviz, bool visubi, bool trim, bool analyzeAll, - bool displayProgress) - : VisGraphviz(visgraphviz), VisUbigraph(visubi), TrimGraph(trim), - LOpts(lopts), Diags(diags), + const std::string& outdir) + : LOpts(lopts), Diags(diags), Ctx(0), PP(pp), PPF(ppf), - HTMLDir(htmldir), - FName(fname), - AnalyzeAll(analyzeAll), SM(sm), DC(dc), - DisplayProgress(displayProgress) {} + OutDir(outdir) {} void addCodeAction(CodeAction action) { FunctionActions.push_back(action); @@ -215,11 +305,11 @@ namespace { } virtual PathDiagnosticClient* getPathDiagnosticClient() { - if (C.PD.get() == 0 && !C.HTMLDir.empty()) { - switch (C.DC) { + if (C.PD.get() == 0 && !C.OutDir.empty()) { + switch (AnalysisDiagOpt) { default: #define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATEFN, AUTOCREATE)\ -case PD_##NAME: C.PD.reset(CREATEFN(C.HTMLDir, C.PP, C.PPF)); break; +case PD_##NAME: C.PD.reset(CREATEFN(C.OutDir, C.PP, C.PPF)); break; #include "Analyses.def" } } @@ -239,22 +329,16 @@ case PD_##NAME: C.PD.reset(CREATEFN(C.HTMLDir, C.PP, C.PPF)); break; return liveness.get(); } - bool shouldVisualizeGraphviz() const { - return C.VisGraphviz; - } + bool shouldVisualizeGraphviz() const { return VisualizeEGDot; } + + bool shouldVisualizeUbigraph() const { return VisualizeEGUbi; } - bool shouldVisualizeUbigraph() const { - return C.VisUbigraph; - } - bool shouldVisualize() const { - return C.VisGraphviz || C.VisUbigraph; - } - - bool shouldTrimGraph() const { - return C.TrimGraph; + return VisualizeEGDot || VisualizeEGUbi; } - + + bool shouldTrimGraph() const { return TrimGraph; } + void DisplayFunction() { if (DisplayedFunction) @@ -282,25 +366,31 @@ case PD_##NAME: C.PD.reset(CREATEFN(C.HTMLDir, C.PP, C.PPF)); break; CreateStoreMgr = ManagerRegistry::StoreMgrCreator; } else { - switch (C.SM) { + switch (AnalysisStoreOpt) { default: assert(0 && "Unknown store manager."); -#define ANALYSIS_STORE(NAME, CMDFLAG, DESC) \ - case NAME##Model: CreateStoreMgr = Create##NAME##Manager; break; +#define ANALYSIS_STORE(NAME, CMDFLAG, DESC, CREATEFN) \ + case NAME##Model: CreateStoreMgr = CREATEFN; break; #include "Analyses.def" } } if (ManagerRegistry::ConstraintMgrCreator != 0) CreateConstraintMgr = ManagerRegistry::ConstraintMgrCreator; - else if (UseRanges) - CreateConstraintMgr = CreateRangeConstraintManager; - else - CreateConstraintMgr = CreateBasicConstraintManager; + else { + switch (AnalysisConstraintsOpt) { + default: + assert(0 && "Unknown store manager."); +#define ANALYSIS_CONSTRAINTS(NAME, CMDFLAG, DESC, CREATEFN) \ + case NAME##Model: CreateConstraintMgr = CREATEFN; break; +#include "Analyses.def" + } + } + // Some DiagnosticClients should be created all the time instead of // lazily. Create those now. - switch (C.DC) { + switch (AnalysisDiagOpt) { default: break; #define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATEFN, AUTOCREATE)\ case PD_##NAME: if (AUTOCREATE) getPathDiagnosticClient(); break; @@ -329,7 +419,8 @@ void AnalysisConsumer::HandleTopLevelDecl(Decl *D) { case Decl::Function: { FunctionDecl* FD = cast<FunctionDecl>(D); - if (FName.size() > 0 && FName != FD->getIdentifier()->getName()) + if (AnalyzeSpecificFunction.size() > 0 && + AnalyzeSpecificFunction != FD->getIdentifier()->getName()) break; Stmt* Body = FD->getBody(); @@ -340,7 +431,8 @@ void AnalysisConsumer::HandleTopLevelDecl(Decl *D) { case Decl::ObjCMethod: { ObjCMethodDecl* MD = cast<ObjCMethodDecl>(D); - if (FName.size() > 0 && FName != MD->getSelector().getAsString()) + if (AnalyzeSpecificFunction.size() > 0 && + AnalyzeSpecificFunction != MD->getSelector().getAsString()) return; Stmt* Body = MD->getBody(); @@ -356,7 +448,7 @@ void AnalysisConsumer::HandleTopLevelDecl(Decl *D) { void AnalysisConsumer::HandleTranslationUnit(TranslationUnit& TU) { if(!TranslationUnitActions.empty()) { - AnalysisManager mgr(*this, &TU, DisplayProgress); + AnalysisManager mgr(*this, &TU, AnalyzerDisplayProgress); for (Actions::iterator I = TranslationUnitActions.begin(), E = TranslationUnitActions.end(); I != E; ++I) (*I)(mgr); @@ -386,7 +478,7 @@ void AnalysisConsumer::HandleCode(Decl* D, Stmt* Body, Actions& actions) { // Create an AnalysisManager that will manage the state for analyzing // this method/function. - AnalysisManager mgr(*this, D, Body, DisplayProgress); + AnalysisManager mgr(*this, D, Body, AnalyzerDisplayProgress); // Dispatch on the actions. for (Actions::iterator I = actions.begin(), E = actions.end(); I != E; ++I) @@ -538,26 +630,16 @@ static void ActionWarnObjCMethSigs(AnalysisManager& mgr) { // AnalysisConsumer creation. //===----------------------------------------------------------------------===// -ASTConsumer* clang::CreateAnalysisConsumer(Analyses* Beg, Analyses* End, - AnalysisStores SM, - AnalysisDiagClients DC, - Diagnostic &diags, Preprocessor* pp, +ASTConsumer* clang::CreateAnalysisConsumer(Diagnostic &diags, Preprocessor* pp, PreprocessorFactory* ppf, const LangOptions& lopts, - const std::string& fname, - const std::string& htmldir, - bool VisGraphviz, bool VisUbi, - bool trim, - bool analyzeAll, - bool displayProgress) { - - llvm::OwningPtr<AnalysisConsumer> - C(new AnalysisConsumer(diags, pp, ppf, lopts, fname, htmldir, SM, DC, - VisGraphviz, VisUbi, trim, analyzeAll, - displayProgress)); - - for ( ; Beg != End ; ++Beg) - switch (*Beg) { + const std::string& OutDir) { + + llvm::OwningPtr<AnalysisConsumer> C(new AnalysisConsumer(diags, pp, ppf, + lopts, OutDir)); + + for (unsigned i = 0; i < AnalysisList.size(); ++i) + switch (AnalysisList[i]) { #define ANALYSIS(NAME, CMD, DESC, SCOPE)\ case NAME:\ C->add ## SCOPE ## Action(&Action ## NAME);\ @@ -565,7 +647,7 @@ ASTConsumer* clang::CreateAnalysisConsumer(Analyses* Beg, Analyses* End, #include "Analyses.def" default: break; } - + return C.take(); } |