From d30952838421ddfb9f7e346b2ba8213889a5f789 Mon Sep 17 00:00:00 2001 From: Anna Zaks Date: Fri, 30 Sep 2011 02:03:00 +0000 Subject: [PATCH] [analyzer] Add -analyzer-purge option which can take on multiple values, remove -analyzer-purge=none. (Small refactor as well: move the work of constructing AnalysisManager from the callers to the class itself.) git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@140838 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Driver/CC1Options.td | 6 ++-- include/clang/Frontend/Analyses.def | 10 +++++- include/clang/Frontend/AnalyzerOptions.h | 11 +++++-- .../Core/PathSensitive/AnalysisManager.h | 13 ++++++-- lib/Frontend/CompilerInvocation.cpp | 32 +++++++++++++++++-- lib/StaticAnalyzer/Core/AnalysisManager.cpp | 29 ++++++++++++++++- lib/StaticAnalyzer/Core/CoreEngine.cpp | 22 ++----------- lib/StaticAnalyzer/Core/ExprEngine.cpp | 2 +- .../Frontend/AnalysisConsumer.cpp | 2 +- test/Analysis/null-deref-ps.c | 2 +- 10 files changed, 94 insertions(+), 35 deletions(-) diff --git a/include/clang/Driver/CC1Options.td b/include/clang/Driver/CC1Options.td index ad61f6a9f4..45c3a66141 100644 --- a/include/clang/Driver/CC1Options.td +++ b/include/clang/Driver/CC1Options.td @@ -57,6 +57,10 @@ def analyzer_output : Separate<"-analyzer-output">, def analyzer_output_EQ : Joined<"-analyzer-output=">, Alias; +def analyzer_purge : Separate<"-analyzer-purge">, + HelpText<"Source Code Analysis - Dead Symbol Removal Frequency">; +def analyzer_purge_EQ : Joined<"-analyzer-purge=">, Alias; + def analyzer_opt_analyze_headers : Flag<"-analyzer-opt-analyze-headers">, HelpText<"Force the static analyzer to analyze functions defined in header files">; def analyzer_opt_analyze_nested_blocks : Flag<"-analyzer-opt-analyze-nested-blocks">, @@ -68,8 +72,6 @@ def analyze_function : Separate<"-analyze-function">, def analyze_function_EQ : Joined<"-analyze-function=">, Alias; def analyzer_eagerly_assume : Flag<"-analyzer-eagerly-assume">, HelpText<"Eagerly assume the truth/falseness of some symbolic constraints">; -def analyzer_no_purge_dead : Flag<"-analyzer-no-purge-dead">, - HelpText<"Don't remove dead symbols, bindings, and constraints before processing a statement">; def analyzer_no_eagerly_trim_egraph : Flag<"-analyzer-no-eagerly-trim-egraph">, HelpText<"Don't eagerly remove uninteresting ExplodedNodes from the ExplodedGraph">; def trim_egraph : Flag<"-trim-egraph">, diff --git a/include/clang/Frontend/Analyses.def b/include/clang/Frontend/Analyses.def index f2a3bbd384..010f889c09 100644 --- a/include/clang/Frontend/Analyses.def +++ b/include/clang/Frontend/Analyses.def @@ -33,8 +33,16 @@ ANALYSIS_DIAGNOSTICS(PLIST, "plist", "Output analysis results using Plists", cre ANALYSIS_DIAGNOSTICS(PLIST_HTML, "plist-html", "Output analysis results using HTML wrapped with Plists", createPlistHTMLDiagnosticConsumer, true) ANALYSIS_DIAGNOSTICS(TEXT, "text", "Text output of analysis results", createTextPathDiagnosticConsumer, true) +#ifndef ANALYSIS_PURGE +#define ANALYSIS_PURGE(NAME, CMDFLAG, DESC) +#endif + +ANALYSIS_PURGE(PurgeStmt, "statement", "Purge symbols, bindings, and constraints before every statement") +ANALYSIS_PURGE(PurgeBlock, "block", "Purge symbols, bindings, and constraints before every basic block") +ANALYSIS_PURGE(PurgeNone, "none", "Do not purge symbols, bindings, or constraints") + #undef ANALYSIS_STORE #undef ANALYSIS_CONSTRAINTS #undef ANALYSIS_DIAGNOSTICS -#undef ANALYSIS_STORE +#undef ANALYSIS_PURGE diff --git a/include/clang/Frontend/AnalyzerOptions.h b/include/clang/Frontend/AnalyzerOptions.h index 20e4156ad6..3565a51d07 100644 --- a/include/clang/Frontend/AnalyzerOptions.h +++ b/include/clang/Frontend/AnalyzerOptions.h @@ -53,6 +53,13 @@ enum AnalysisDiagClients { NUM_ANALYSIS_DIAG_CLIENTS }; +/// AnalysisPurgeModes - Set of available strategies for dead symbol removal. +enum AnalysisPurgeMode { +#define ANALYSIS_PURGE(NAME, CMDFLAG, DESC) NAME, +#include "clang/Frontend/Analyses.def" +NumPurgeModes +}; + class AnalyzerOptions { public: /// \brief Pair of checker name and enable/disable. @@ -60,6 +67,7 @@ public: AnalysisStores AnalysisStoreOpt; AnalysisConstraints AnalysisConstraintsOpt; AnalysisDiagClients AnalysisDiagOpt; + AnalysisPurgeMode AnalysisPurgeOpt; std::string AnalyzeSpecificFunction; unsigned MaxNodes; unsigned MaxLoop; @@ -68,7 +76,6 @@ public: unsigned AnalyzerDisplayProgress : 1; unsigned AnalyzeNestedBlocks : 1; unsigned EagerlyAssume : 1; - unsigned PurgeDead : 1; unsigned TrimGraph : 1; unsigned VisualizeEGDot : 1; unsigned VisualizeEGUbi : 1; @@ -83,12 +90,12 @@ public: AnalysisStoreOpt = RegionStoreModel; AnalysisConstraintsOpt = RangeConstraintsModel; AnalysisDiagOpt = PD_HTML; + AnalysisPurgeOpt = PurgeStmt; ShowCheckerHelp = 0; AnalyzeAll = 0; AnalyzerDisplayProgress = 0; AnalyzeNestedBlocks = 0; EagerlyAssume = 0; - PurgeDead = 1; TrimGraph = 0; VisualizeEGDot = 0; VisualizeEGUbi = 0; diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h b/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h index 8a1c0bc153..9c333ce268 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h @@ -16,6 +16,7 @@ #define LLVM_CLANG_GR_ANALYSISMANAGER_H #include "clang/Analysis/AnalysisContext.h" +#include "clang/Frontend/AnalyzerOptions.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h" #include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h" @@ -60,7 +61,7 @@ class AnalysisManager : public BugReporterData { bool VisualizeEGDot; bool VisualizeEGUbi; - bool PurgeDead; + AnalysisPurgeMode PurgeDead; /// EargerlyAssume - A flag indicating how the engine should handle // expressions such as: 'x = (y != 0)'. When this flag is true then @@ -82,11 +83,17 @@ public: CheckerManager *checkerMgr, idx::Indexer *idxer, unsigned maxnodes, unsigned maxvisit, - bool vizdot, bool vizubi, bool purge, bool eager, bool trim, + bool vizdot, bool vizubi, AnalysisPurgeMode purge, + bool eager, bool trim, bool inlinecall, bool useUnoptimizedCFG, bool addImplicitDtors, bool addInitializers, bool eagerlyTrimEGraph); + /// Construct a clone of the given AnalysisManager with the given ASTContext + /// and DiagnosticsEngine. + AnalysisManager(ASTContext &ctx, DiagnosticsEngine &diags, + AnalysisManager &ParentAM); + ~AnalysisManager() { FlushDiagnostics(); } void ClearContexts() { @@ -151,7 +158,7 @@ public: bool shouldTrimGraph() const { return TrimGraph; } - bool shouldPurgeDead() const { return PurgeDead; } + AnalysisPurgeMode getPurgeMode() const { return PurgeDead; } bool shouldEagerlyAssume() const { return EagerlyAssume; } diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index 3426e19c0c..671e3da295 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -60,6 +60,16 @@ static const char *getAnalysisDiagClientName(AnalysisDiagClients Kind) { } } +static const char *getAnalysisPurgeModeName(AnalysisPurgeMode Kind) { + switch (Kind) { + default: + llvm_unreachable("Unknown analysis client!"); +#define ANALYSIS_PURGE(NAME, CMDFLAG, DESC) \ + case NAME: return CMDFLAG; +#include "clang/Frontend/Analyses.def" + } +} + //===----------------------------------------------------------------------===// // Serialization (to args) //===----------------------------------------------------------------------===// @@ -80,6 +90,10 @@ static void AnalyzerOptsToArgs(const AnalyzerOptions &Opts, Res.push_back("-analyzer-output"); Res.push_back(getAnalysisDiagClientName(Opts.AnalysisDiagOpt)); } + if (Opts.AnalysisPurgeOpt != PurgeStmt) { + Res.push_back("-analyzer-purge"); + Res.push_back(getAnalysisPurgeModeName(Opts.AnalysisPurgeOpt)); + } if (!Opts.AnalyzeSpecificFunction.empty()) { Res.push_back("-analyze-function"); Res.push_back(Opts.AnalyzeSpecificFunction); @@ -92,8 +106,6 @@ static void AnalyzerOptsToArgs(const AnalyzerOptions &Opts, Res.push_back("-analyzer-opt-analyze-nested-blocks"); if (Opts.EagerlyAssume) Res.push_back("-analyzer-eagerly-assume"); - if (!Opts.PurgeDead) - Res.push_back("-analyzer-no-purge-dead"); if (Opts.TrimGraph) Res.push_back("-trim-egraph"); if (Opts.VisualizeEGDot) @@ -930,6 +942,21 @@ static void ParseAnalyzerArgs(AnalyzerOptions &Opts, ArgList &Args, Opts.AnalysisDiagOpt = Value; } + if (Arg *A = Args.getLastArg(OPT_analyzer_purge)) { + StringRef Name = A->getValue(Args); + AnalysisPurgeMode Value = llvm::StringSwitch(Name) +#define ANALYSIS_PURGE(NAME, CMDFLAG, DESC) \ + .Case(CMDFLAG, NAME) +#include "clang/Frontend/Analyses.def" + .Default(NumPurgeModes); + // FIXME: Error handling. + if (Value == NumPurgeModes) + Diags.Report(diag::err_drv_invalid_value) + << A->getAsString(Args) << Name; + else + Opts.AnalysisPurgeOpt = Value; + } + Opts.ShowCheckerHelp = Args.hasArg(OPT_analyzer_checker_help); Opts.VisualizeEGDot = Args.hasArg(OPT_analyzer_viz_egraph_graphviz); Opts.VisualizeEGUbi = Args.hasArg(OPT_analyzer_viz_egraph_ubigraph); @@ -937,7 +964,6 @@ static void ParseAnalyzerArgs(AnalyzerOptions &Opts, ArgList &Args, Opts.AnalyzerDisplayProgress = Args.hasArg(OPT_analyzer_display_progress); Opts.AnalyzeNestedBlocks = Args.hasArg(OPT_analyzer_opt_analyze_nested_blocks); - Opts.PurgeDead = !Args.hasArg(OPT_analyzer_no_purge_dead); Opts.EagerlyAssume = Args.hasArg(OPT_analyzer_eagerly_assume); Opts.AnalyzeSpecificFunction = Args.getLastArgValue(OPT_analyze_function); Opts.UnoptimizedCFG = Args.hasArg(OPT_analysis_UnoptimizedCFG); diff --git a/lib/StaticAnalyzer/Core/AnalysisManager.cpp b/lib/StaticAnalyzer/Core/AnalysisManager.cpp index f43ce5ad66..17ec70d39b 100644 --- a/lib/StaticAnalyzer/Core/AnalysisManager.cpp +++ b/lib/StaticAnalyzer/Core/AnalysisManager.cpp @@ -22,7 +22,8 @@ AnalysisManager::AnalysisManager(ASTContext &ctx, DiagnosticsEngine &diags, CheckerManager *checkerMgr, idx::Indexer *idxer, unsigned maxnodes, unsigned maxvisit, - bool vizdot, bool vizubi, bool purge, + bool vizdot, bool vizubi, + AnalysisPurgeMode purge, bool eager, bool trim, bool inlinecall, bool useUnoptimizedCFG, bool addImplicitDtors, bool addInitializers, @@ -39,6 +40,32 @@ AnalysisManager::AnalysisManager(ASTContext &ctx, DiagnosticsEngine &diags, AnaCtxMgr.getCFGBuildOptions().setAllAlwaysAdd(); } +AnalysisManager::AnalysisManager(ASTContext &ctx, DiagnosticsEngine &diags, + AnalysisManager &ParentAM) + : AnaCtxMgr(ParentAM.AnaCtxMgr.getUseUnoptimizedCFG(), + ParentAM.AnaCtxMgr.getCFGBuildOptions().AddImplicitDtors, + ParentAM.AnaCtxMgr.getCFGBuildOptions().AddInitializers), + Ctx(ctx), Diags(diags), + LangInfo(ParentAM.LangInfo), PD(ParentAM.getPathDiagnosticConsumer()), + CreateStoreMgr(ParentAM.CreateStoreMgr), + CreateConstraintMgr(ParentAM.CreateConstraintMgr), + CheckerMgr(ParentAM.CheckerMgr), + Idxer(ParentAM.Idxer), + AScope(ScopeDecl), + MaxNodes(ParentAM.MaxNodes), + MaxVisit(ParentAM.MaxVisit), + VisualizeEGDot(ParentAM.VisualizeEGDot), + VisualizeEGUbi(ParentAM.VisualizeEGUbi), + PurgeDead(ParentAM.PurgeDead), + EagerlyAssume(ParentAM.EagerlyAssume), + TrimGraph(ParentAM.TrimGraph), + InlineCall(ParentAM.InlineCall), + EagerlyTrimEGraph(ParentAM.EagerlyTrimEGraph) +{ + AnaCtxMgr.getCFGBuildOptions().setAllAlwaysAdd(); +} + + AnalysisContext * AnalysisManager::getAnalysisContextInAnotherTU(const Decl *D) { idx::Entity Ent = idx::Entity::get(const_cast(D), diff --git a/lib/StaticAnalyzer/Core/CoreEngine.cpp b/lib/StaticAnalyzer/Core/CoreEngine.cpp index e01c5d1090..20b86a8fd3 100644 --- a/lib/StaticAnalyzer/Core/CoreEngine.cpp +++ b/lib/StaticAnalyzer/Core/CoreEngine.cpp @@ -784,26 +784,8 @@ void CallEnterNodeBuilder::generateNode(const ProgramState *state) { // Create a new AnalysisManager with components of the callee's // TranslationUnit. // The Diagnostic is actually shared when we create ASTUnits from AST files. - AnalysisManager AMgr(TU->getASTContext(), TU->getDiagnostic(), - OldMgr.getLangOptions(), - OldMgr.getPathDiagnosticConsumer(), - OldMgr.getStoreManagerCreator(), - OldMgr.getConstraintManagerCreator(), - OldMgr.getCheckerManager(), - OldMgr.getIndexer(), - OldMgr.getMaxNodes(), OldMgr.getMaxVisit(), - OldMgr.shouldVisualizeGraphviz(), - OldMgr.shouldVisualizeUbigraph(), - OldMgr.shouldPurgeDead(), - OldMgr.shouldEagerlyAssume(), - OldMgr.shouldTrimGraph(), - OldMgr.shouldInlineCall(), - OldMgr.getAnalysisContextManager().getUseUnoptimizedCFG(), - OldMgr.getAnalysisContextManager(). - getCFGBuildOptions().AddImplicitDtors, - OldMgr.getAnalysisContextManager(). - getCFGBuildOptions().AddInitializers, - OldMgr.shouldEagerlyTrimExplodedGraph()); + AnalysisManager AMgr(TU->getASTContext(), TU->getDiagnostic(), OldMgr); + // Create the new engine. // FIXME: This cast isn't really safe. bool GCEnabled = static_cast(Eng.SubEng).isObjCGCEnabled(); diff --git a/lib/StaticAnalyzer/Core/ExprEngine.cpp b/lib/StaticAnalyzer/Core/ExprEngine.cpp index d982a698d3..da9b70594b 100644 --- a/lib/StaticAnalyzer/Core/ExprEngine.cpp +++ b/lib/StaticAnalyzer/Core/ExprEngine.cpp @@ -242,7 +242,7 @@ void ExprEngine::ProcessStmt(const CFGStmt S, StmtNodeBuilder& builder) { const LocationContext *LC = EntryNode->getLocationContext(); SymbolReaper SymReaper(LC, currentStmt, SymMgr, getStoreManager()); - if (AMgr.shouldPurgeDead()) { + if (AMgr.getPurgeMode() != PurgeNone) { getCheckerManager().runCheckersForLiveSymbols(CleanedState, SymReaper); const StackFrameContext *SFC = LC->getCurrentStackFrame(); diff --git a/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp b/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp index 75ecb97fb7..876136ba68 100644 --- a/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp +++ b/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp @@ -152,7 +152,7 @@ public: /* Indexer */ 0, Opts.MaxNodes, Opts.MaxLoop, Opts.VisualizeEGDot, Opts.VisualizeEGUbi, - Opts.PurgeDead, Opts.EagerlyAssume, + Opts.AnalysisPurgeOpt, Opts.EagerlyAssume, Opts.TrimGraph, Opts.InlineCall, Opts.UnoptimizedCFG, Opts.CFGAddImplicitDtors, Opts.CFGAddInitializers, diff --git a/test/Analysis/null-deref-ps.c b/test/Analysis/null-deref-ps.c index f33b9d2b03..641dde2075 100644 --- a/test/Analysis/null-deref-ps.c +++ b/test/Analysis/null-deref-ps.c @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -triple i386-apple-darwin10 -analyze -analyzer-checker=core,deadcode,experimental.core -std=gnu99 -analyzer-store=region -analyzer-constraints=range -analyzer-no-purge-dead -verify %s -Wreturn-type +// RUN: %clang_cc1 -triple i386-apple-darwin10 -analyze -analyzer-checker=core,deadcode,experimental.core -std=gnu99 -analyzer-store=region -analyzer-constraints=range -analyzer-purge=none -verify %s -Wreturn-type // RUN: %clang_cc1 -triple i386-apple-darwin10 -analyze -analyzer-checker=core,deadcode,experimental.core -std=gnu99 -analyzer-store=region -analyzer-constraints=range -verify %s -Wreturn-type typedef unsigned uintptr_t; -- 2.40.0