Static Analyzer driver/options (partial) cleanup:
- Move all analyzer options logic to AnalysisConsumer.cpp.
- Unified specification of stores/constraints/output to be:
-analyzer-output=...
-analyzer-store=...
-analyzer-constraints=...
instead of -analyzer-range-constraints, -analyzer-store-basic, etc.
- Updated drivers (ccc-analyzer, scan-builds, new ccc) to obey this new
interface
- Updated test cases to conform to new driver options
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@64737 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/Driver/AnalysisConsumer.cpp b/Driver/AnalysisConsumer.cpp
index 5c1e3d8..66fe299 100644
--- a/Driver/AnalysisConsumer.cpp
+++ b/Driver/AnalysisConsumer.cpp
@@ -42,18 +42,124 @@
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 @@
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 @@
}
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 @@
return liveness.get();
}
- bool shouldVisualizeGraphviz() const {
- return C.VisGraphviz;
+ bool shouldVisualizeGraphviz() const { return VisualizeEGDot; }
+
+ bool shouldVisualizeUbigraph() const { return VisualizeEGUbi; }
+
+ bool shouldVisualize() const {
+ return VisualizeEGDot || VisualizeEGUbi;
}
- bool shouldVisualizeUbigraph() const {
- return C.VisUbigraph;
- }
-
- bool shouldVisualize() const {
- return C.VisGraphviz || C.VisUbigraph;
- }
-
- bool shouldTrimGraph() const {
- return C.TrimGraph;
- }
-
+ bool shouldTrimGraph() const { return TrimGraph; }
+
void DisplayFunction() {
if (DisplayedFunction)
@@ -282,25 +366,31 @@
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 @@
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 @@
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::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 @@
// 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 @@
// 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 @@
#include "Analyses.def"
default: break;
}
-
+
return C.take();
}