From 255d4d4226b24036ceb11228fbb74286e58620f7 Mon Sep 17 00:00:00 2001 From: Ted Kremenek Date: Thu, 30 Aug 2012 19:26:43 +0000 Subject: [PATCH] Store const& to AnalyzerOptions in AnalysisManager instead of copying individual flags. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@162929 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../clang/StaticAnalyzer/AnalyzerOptions.h | 40 ++++++++- .../Core/PathSensitive/AnalysisManager.h | 81 ++----------------- .../Core/PathSensitive/CheckerContext.h | 4 +- lib/Frontend/CompilerInvocation.cpp | 2 +- lib/StaticAnalyzer/Core/AnalysisManager.cpp | 34 ++------ lib/StaticAnalyzer/Core/ExprEngine.cpp | 23 +++--- .../Core/ExprEngineCallAndReturn.cpp | 16 ++-- .../Frontend/AnalysisConsumer.cpp | 27 ++----- 8 files changed, 80 insertions(+), 147 deletions(-) diff --git a/include/clang/StaticAnalyzer/AnalyzerOptions.h b/include/clang/StaticAnalyzer/AnalyzerOptions.h index 972887edea..356d13aec4 100644 --- a/include/clang/StaticAnalyzer/AnalyzerOptions.h +++ b/include/clang/StaticAnalyzer/AnalyzerOptions.h @@ -77,32 +77,66 @@ NumInliningModes class AnalyzerOptions { public: + typedef llvm::StringMap ConfigTable; + /// \brief Pair of checker name and enable/disable. std::vector > CheckersControlList; - llvm::StringMap Config; + + /// \brief A key-value table of use-specified configuration values. + ConfigTable Config; AnalysisStores AnalysisStoreOpt; AnalysisConstraints AnalysisConstraintsOpt; AnalysisDiagClients AnalysisDiagOpt; AnalysisPurgeMode AnalysisPurgeOpt; + + // \brief The interprocedural analysis mode. AnalysisIPAMode IPAMode; + std::string AnalyzeSpecificFunction; + + /// \brief The maximum number of exploded nodes the analyzer will generate. unsigned MaxNodes; + + /// \brief The maximum number of times the analyzer visits a block. unsigned MaxLoop; + + unsigned ShowCheckerHelp : 1; unsigned AnalyzeAll : 1; unsigned AnalyzerDisplayProgress : 1; unsigned AnalyzeNestedBlocks : 1; + + /// \brief The flag regulates if we should eagerly assume evaluations of + /// conditionals, thus, bifurcating the path. + /// + /// EagerlyAssume - A flag indicating how the engine should handle + /// expressions such as: 'x = (y != 0)'. When this flag is true then + /// the subexpression 'y != 0' will be eagerly assumed to be true or false, + /// thus evaluating it to the integers 0 or 1 respectively. The upside + /// is that this can increase analysis precision until we have a better way + /// to lazily evaluate such logic. The downside is that it eagerly + /// bifurcates paths. unsigned EagerlyAssume : 1; + unsigned TrimGraph : 1; unsigned VisualizeEGDot : 1; unsigned VisualizeEGUbi : 1; unsigned UnoptimizedCFG : 1; unsigned CFGAddImplicitDtors : 1; - unsigned EagerlyTrimEGraph : 1; + unsigned eagerlyTrimExplodedGraph : 1; unsigned PrintStats : 1; + + /// \brief Do not re-analyze paths leading to exhausted nodes with a different + /// strategy. We get better code coverage when retry is enabled. unsigned NoRetryExhausted : 1; + + /// \brief The inlining stack depth limit. unsigned InlineMaxStackDepth; + + /// \brief The mode of function selection used during inlining. unsigned InlineMaxFunctionSize; + + /// \brief The mode of function selection used during inlining. AnalysisInliningMode InliningMode; public: @@ -122,7 +156,7 @@ public: VisualizeEGUbi = 0; UnoptimizedCFG = 0; CFGAddImplicitDtors = 0; - EagerlyTrimEGraph = 0; + eagerlyTrimExplodedGraph = 0; PrintStats = 0; NoRetryExhausted = 0; // Cap the stack depth at 4 calls (5 stack frames, base + 4 calls). diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h b/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h index ab569a869a..b010372014 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h @@ -41,70 +41,16 @@ class AnalysisManager : public BugReporterData { CheckerManager *CheckerMgr; - /// \brief The maximum number of exploded nodes the analyzer will generate. - unsigned MaxNodes; - - /// \brief The maximum number of times the analyzer visits a block. - unsigned MaxVisit; - - bool VisualizeEGDot; - bool VisualizeEGUbi; - AnalysisPurgeMode PurgeDead; - - /// \brief The flag regulates if we should eagerly assume evaluations of - /// conditionals, thus, bifurcating the path. - /// - /// EagerlyAssume - A flag indicating how the engine should handle - /// expressions such as: 'x = (y != 0)'. When this flag is true then - /// the subexpression 'y != 0' will be eagerly assumed to be true or false, - /// thus evaluating it to the integers 0 or 1 respectively. The upside - /// is that this can increase analysis precision until we have a better way - /// to lazily evaluate such logic. The downside is that it eagerly - /// bifurcates paths. - bool EagerlyAssume; - bool TrimGraph; - bool EagerlyTrimEGraph; - public: - // \brief inter-procedural analysis mode. - AnalysisIPAMode IPAMode; - - // Settings for inlining tuning. - /// \brief The inlining stack depth limit. - unsigned InlineMaxStackDepth; - /// \brief The max number of basic blocks in a function being inlined. - unsigned InlineMaxFunctionSize; - /// \brief The mode of function selection used during inlining. - AnalysisInliningMode InliningMode; - - /// \brief Do not re-analyze paths leading to exhausted nodes with a different - /// strategy. We get better code coverage when retry is enabled. - bool NoRetryExhausted; - - typedef llvm::StringMap ConfigTable; - - /// \brief A key-value table of use-specified configuration values. - const ConfigTable &Config; + const AnalyzerOptions &options; -public: AnalysisManager(ASTContext &ctx,DiagnosticsEngine &diags, const LangOptions &lang, const PathDiagnosticConsumers &Consumers, StoreManagerCreator storemgr, ConstraintManagerCreator constraintmgr, CheckerManager *checkerMgr, - const ConfigTable &Config, - unsigned maxnodes, unsigned maxvisit, - bool vizdot, bool vizubi, AnalysisPurgeMode purge, - bool eager, bool trim, - bool useUnoptimizedCFG, - bool addImplicitDtors, - bool eagerlyTrimEGraph, - AnalysisIPAMode ipa, - unsigned inlineMaxStack, - unsigned inlineMaxFunctionSize, - AnalysisInliningMode inliningMode, - bool NoRetry); + const AnalyzerOptions &Options); ~AnalysisManager(); @@ -148,27 +94,13 @@ public: void FlushDiagnostics(); - unsigned getMaxNodes() const { return MaxNodes; } - - unsigned getMaxVisit() const { return MaxVisit; } - - bool shouldVisualizeGraphviz() const { return VisualizeEGDot; } - - bool shouldVisualizeUbigraph() const { return VisualizeEGUbi; } - bool shouldVisualize() const { - return VisualizeEGDot || VisualizeEGUbi; + return options.VisualizeEGDot || options.VisualizeEGUbi; } - bool shouldEagerlyTrimExplodedGraph() const { return EagerlyTrimEGraph; } - - bool shouldTrimGraph() const { return TrimGraph; } - - AnalysisPurgeMode getPurgeMode() const { return PurgeDead; } - - bool shouldEagerlyAssume() const { return EagerlyAssume; } - - bool shouldInlineCall() const { return (IPAMode != None); } + bool shouldInlineCall() const { + return options.IPAMode != None; + } CFG *getCFG(Decl const *D) { return AnaCtxMgr.getContext(D)->getCFG(); @@ -186,7 +118,6 @@ public: AnalysisDeclContext *getAnalysisDeclContext(const Decl *D) { return AnaCtxMgr.getContext(D); } - }; } // enAnaCtxMgrspace diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h b/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h index c260c1b363..13bb3f6a90 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h @@ -64,8 +64,8 @@ public: return Eng.getStoreManager(); } - const AnalysisManager::ConfigTable &getConfig() const { - return Eng.getAnalysisManager().Config; + const AnalyzerOptions::ConfigTable &getConfig() const { + return Eng.getAnalysisManager().options.Config; } /// \brief Returns the previous node in the exploded graph, which includes diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index 4f489fe5fc..69acd418fa 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -1130,7 +1130,7 @@ static bool ParseAnalyzerArgs(AnalyzerOptions &Opts, ArgList &Args, Opts.TrimGraph = Args.hasArg(OPT_trim_egraph); Opts.MaxNodes = Args.getLastArgIntValue(OPT_analyzer_max_nodes, 150000,Diags); Opts.MaxLoop = Args.getLastArgIntValue(OPT_analyzer_max_loop, 4, Diags); - Opts.EagerlyTrimEGraph = !Args.hasArg(OPT_analyzer_no_eagerly_trim_egraph); + Opts.eagerlyTrimExplodedGraph = !Args.hasArg(OPT_analyzer_no_eagerly_trim_egraph); Opts.PrintStats = Args.hasArg(OPT_analyzer_stats); Opts.InlineMaxStackDepth = Args.getLastArgIntValue(OPT_analyzer_inline_max_stack_depth, diff --git a/lib/StaticAnalyzer/Core/AnalysisManager.cpp b/lib/StaticAnalyzer/Core/AnalysisManager.cpp index 339208b374..6a01edf7ce 100644 --- a/lib/StaticAnalyzer/Core/AnalysisManager.cpp +++ b/lib/StaticAnalyzer/Core/AnalysisManager.cpp @@ -20,35 +20,17 @@ AnalysisManager::AnalysisManager(ASTContext &ctx, DiagnosticsEngine &diags, StoreManagerCreator storemgr, ConstraintManagerCreator constraintmgr, CheckerManager *checkerMgr, - const ConfigTable &Config, - unsigned maxnodes, unsigned maxvisit, - bool vizdot, bool vizubi, - AnalysisPurgeMode purge, - bool eager, bool trim, - bool useUnoptimizedCFG, - bool addImplicitDtors, - bool eagerlyTrimEGraph, - AnalysisIPAMode ipa, - unsigned inlineMaxStack, - unsigned inlineMaxFunctionSize, - AnalysisInliningMode IMode, - bool NoRetry) - : AnaCtxMgr(useUnoptimizedCFG, addImplicitDtors, /*addInitializers=*/true), - Ctx(ctx), Diags(diags), LangOpts(lang), + const AnalyzerOptions &Options) + : AnaCtxMgr(Options.UnoptimizedCFG, + Options.CFGAddImplicitDtors, + /*addInitializers=*/true), + Ctx(ctx), + Diags(diags), + LangOpts(lang), PathConsumers(PDC), CreateStoreMgr(storemgr), CreateConstraintMgr(constraintmgr), CheckerMgr(checkerMgr), - MaxNodes(maxnodes), MaxVisit(maxvisit), - VisualizeEGDot(vizdot), VisualizeEGUbi(vizubi), PurgeDead(purge), - EagerlyAssume(eager), TrimGraph(trim), - EagerlyTrimEGraph(eagerlyTrimEGraph), - IPAMode(ipa), - InlineMaxStackDepth(inlineMaxStack), - InlineMaxFunctionSize(inlineMaxFunctionSize), - InliningMode(IMode), - NoRetryExhausted(NoRetry), - Config(Config) -{ + options(Options) { AnaCtxMgr.getCFGBuildOptions().setAllAlwaysAdd(); } diff --git a/lib/StaticAnalyzer/Core/ExprEngine.cpp b/lib/StaticAnalyzer/Core/ExprEngine.cpp index 6603b6ca5d..5f52724ab9 100644 --- a/lib/StaticAnalyzer/Core/ExprEngine.cpp +++ b/lib/StaticAnalyzer/Core/ExprEngine.cpp @@ -70,12 +70,12 @@ ExprEngine::ExprEngine(AnalysisManager &mgr, bool gcEnabled, currStmt(NULL), currStmtIdx(0), currBldrCtx(0), NSExceptionII(NULL), NSExceptionInstanceRaiseSelectors(NULL), RaiseSel(GetNullarySelector("raise", getContext())), - ObjCGCEnabled(gcEnabled), BR(mgr, *this) { - - if (mgr.shouldEagerlyTrimExplodedGraph()) { - // Enable eager node reclaimation when constructing the ExplodedGraph. - G.enableNodeReclamation(); - } + ObjCGCEnabled(gcEnabled), BR(mgr, *this) +{ + if (mgr.options.eagerlyTrimExplodedGraph) { + // Enable eager node reclaimation when constructing the ExplodedGraph. + G.enableNodeReclamation(); + } } ExprEngine::~ExprEngine() { @@ -228,7 +228,7 @@ static bool shouldRemoveDeadBindings(AnalysisManager &AMgr, const LocationContext *LC) { // Are we never purging state values? - if (AMgr.getPurgeMode() == PurgeNone) + if (AMgr.options.AnalysisPurgeOpt == PurgeNone) return false; // Is this the beginning of a basic block? @@ -704,7 +704,7 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred, Bldr.takeNodes(Pred); - if (AMgr.shouldEagerlyAssume() && + if (AMgr.options.EagerlyAssume && (B->isRelationalOp() || B->isEqualityOp())) { ExplodedNodeSet Tmp; VisitBinaryOperator(cast(S), Pred, Tmp); @@ -924,7 +924,7 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred, case Stmt::UnaryOperatorClass: { Bldr.takeNodes(Pred); const UnaryOperator *U = cast(S); - if (AMgr.shouldEagerlyAssume() && (U->getOpcode() == UO_LNot)) { + if (AMgr.options.EagerlyAssume && (U->getOpcode() == UO_LNot)) { ExplodedNodeSet Tmp; VisitUnaryOperator(U, Pred, Tmp); evalEagerlyAssume(Dst, Tmp, U); @@ -1024,7 +1024,7 @@ void ExprEngine::processCFGBlockEntrance(const BlockEdge &L, // FIXME: Refactor this into a checker. ExplodedNode *pred = nodeBuilder.getContext().getPred(); - if (nodeBuilder.getContext().blockCount() >= AMgr.getMaxVisit()) { + if (nodeBuilder.getContext().blockCount() >= AMgr.options.MaxLoop) { static SimpleProgramPointTag tag("ExprEngine : Block count exceeded"); const ExplodedNode *Sink = nodeBuilder.generateSink(pred->getState(), pred, &tag); @@ -1042,7 +1042,8 @@ void ExprEngine::processCFGBlockEntrance(const BlockEdge &L, // no-inlining policy in the state and enqueuing the new work item on // the list. Replay should almost never fail. Use the stats to catch it // if it does. - if ((!AMgr.NoRetryExhausted && replayWithoutInlining(pred, CalleeLC))) + if ((!AMgr.options.NoRetryExhausted && + replayWithoutInlining(pred, CalleeLC))) return; NumMaxBlockCountReachedInInlined++; } else diff --git a/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp b/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp index 0f29735dc9..70350ce0c1 100644 --- a/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp +++ b/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp @@ -176,7 +176,7 @@ void ExprEngine::processCallExit(ExplodedNode *CEBNode) { // that we report the issues such as leaks in the stack contexts in which // they occurred. ExplodedNodeSet CleanedNodes; - if (LastSt && Blk && AMgr.getPurgeMode() != PurgeNone) { + if (LastSt && Blk && AMgr.options.AnalysisPurgeOpt != PurgeNone) { static SimpleProgramPointTag retValBind("ExprEngine : Bind Return Value"); PostStmt Loc(LastSt, calleeCtx, &retValBind); bool isNew; @@ -268,13 +268,13 @@ bool ExprEngine::shouldInlineDecl(const Decl *D, ExplodedNode *Pred) { return false; if (getNumberStackFrames(Pred->getLocationContext()) - == AMgr.InlineMaxStackDepth) + == AMgr.options.InlineMaxStackDepth) return false; if (Engine.FunctionSummaries->hasReachedMaxBlockCount(D)) return false; - if (CalleeCFG->getNumBlockIDs() > AMgr.InlineMaxFunctionSize) + if (CalleeCFG->getNumBlockIDs() > AMgr.options.InlineMaxFunctionSize) return false; // Do not inline variadic calls (for now). @@ -317,7 +317,7 @@ template<> struct ProgramStateTrait }} static bool shouldInlineCXX(AnalysisManager &AMgr) { - switch (AMgr.IPAMode) { + switch (AMgr.options.IPAMode) { case None: case BasicInlining: return false; @@ -424,8 +424,8 @@ bool ExprEngine::inlineCall(const CallEvent &Call, const Decl *D, break; } case CE_ObjCMessage: - if (!(getAnalysisManager().IPAMode == DynamicDispatch || - getAnalysisManager().IPAMode == DynamicDispatchBifurcate)) + if (!(getAnalysisManager().options.IPAMode == DynamicDispatch || + getAnalysisManager().options.IPAMode == DynamicDispatchBifurcate)) return false; break; } @@ -600,13 +600,13 @@ void ExprEngine::defaultEvalCall(NodeBuilder &Bldr, ExplodedNode *Pred, if (D) { if (RD.mayHaveOtherDefinitions()) { // Explore with and without inlining the call. - if (getAnalysisManager().IPAMode == DynamicDispatchBifurcate) { + if (getAnalysisManager().options.IPAMode == DynamicDispatchBifurcate) { BifurcateCall(RD.getDispatchRegion(), *Call, D, Bldr, Pred); return; } // Don't inline if we're not in any dynamic dispatch mode. - if (getAnalysisManager().IPAMode != DynamicDispatch) { + if (getAnalysisManager().options.IPAMode != DynamicDispatch) { conservativeEvalCall(*Call, Bldr, Pred, State); return; } diff --git a/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp b/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp index 0be0afa388..2c96115bbc 100644 --- a/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp +++ b/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp @@ -255,22 +255,7 @@ public: CreateStoreMgr, CreateConstraintMgr, checkerMgr.get(), - Opts.Config, - Opts.MaxNodes, - Opts.MaxLoop, - Opts.VisualizeEGDot, - Opts.VisualizeEGUbi, - Opts.AnalysisPurgeOpt, - Opts.EagerlyAssume, - Opts.TrimGraph, - Opts.UnoptimizedCFG, - Opts.CFGAddImplicitDtors, - Opts.EagerlyTrimEGraph, - Opts.IPAMode, - Opts.InlineMaxStackDepth, - Opts.InlineMaxFunctionSize, - Opts.InliningMode, - Opts.NoRetryExhausted)); + Opts)); } /// \brief Store the top level decls in the set to be processed later on. @@ -426,7 +411,7 @@ void AnalysisConsumer::HandleDeclsGallGraph(const unsigned LocalTUDeclsSize) { Decl *D = N->getDecl(); assert(D); HandleCode(D, ANALYSIS_PATH, - (Mgr->InliningMode == All ? 0 : &VisitedCallees)); + (Mgr->options.InliningMode == All ? 0 : &VisitedCallees)); // Add the visited callees to the global visited set. for (SetOfConstDecls::iterator I = VisitedCallees.begin(), @@ -588,22 +573,22 @@ void AnalysisConsumer::ActionExprEngine(Decl *D, bool ObjCGCEnabled, // Set the graph auditor. OwningPtr Auditor; - if (Mgr->shouldVisualizeUbigraph()) { + if (Mgr->options.VisualizeEGUbi) { Auditor.reset(CreateUbiViz()); ExplodedNode::SetAuditor(Auditor.get()); } // Execute the worklist algorithm. Eng.ExecuteWorkList(Mgr->getAnalysisDeclContextManager().getStackFrame(D), - Mgr->getMaxNodes()); + Mgr->options.MaxNodes); // Release the auditor (if any) so that it doesn't monitor the graph // created BugReporter. ExplodedNode::SetAuditor(0); // Visualize the exploded graph. - if (Mgr->shouldVisualizeGraphviz()) - Eng.ViewGraph(Mgr->shouldTrimGraph()); + if (Mgr->options.VisualizeEGDot) + Eng.ViewGraph(Mgr->options.TrimGraph); // Display warnings. Eng.getBugReporter().FlushReports(); -- 2.40.0