瀏覽代碼

[analyzer] Evaluate all non-checker config options before analysis

In earlier patches regarding AnalyzerOptions, a lot of effort went into
gathering all config options, and changing the interface so that potential
misuse can be eliminited.

Up until this point, AnalyzerOptions only evaluated an option when it was
querried. For example, if we had a "-no-false-positives" flag, AnalyzerOptions
would store an Optional field for it that would be None up until somewhere in
the code until the flag's getter function is called.

However, now that we're confident that we've gathered all configs, we can
evaluate off of them before analysis, so we can emit a error on invalid input
even if that prticular flag will not matter in that particular run of the
analyzer. Another very big benefit of this is that debug.ConfigDumper will now
show the value of all configs every single time.

Also, almost all options related class have a similar interface, so uniformity
is also a benefit.

The implementation for errors on invalid input will be commited shorty.

Differential Revision: https://reviews.llvm.org/D53692


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@348031 91177308-0d34-0410-b5e6-96231b3b80d8
Kristof Umann 6 年之前
父節點
當前提交
d1b208c30b

+ 165 - 260
include/clang/StaticAnalyzer/Core/AnalyzerOptions.def

@@ -9,29 +9,6 @@
 //
 //
 //  This file defines the analyzer options avaible with -analyzer-config.
 //  This file defines the analyzer options avaible with -analyzer-config.
 //
 //
-//  This file is in part intended for method generation. If it's not included
-//  for that purpose, the following function-like macros should be predefined,
-//  through which all registered options are accessible:
-//
-//    * ANALYZER_OPTION: Register a new option.
-//    * ANALYZER_OPTION_DEPENDS_ON_USER_MODE: Register a new option, default
-//      value depends on the "user-mode" option.
-//
-//  Options where a simple getter method is sufficient are registered with the
-//  following macros:
-//
-//    * ANALYZER_OPTION_GEN_FN: Register a new option, and generate a getter
-//      method for it in AnalyzerOptions.
-//
-//    * ANALYZER_OPTION_GEN_FN_DEPENDS_ON_USER_MODE: Same as above, but
-//      generates a getter function that depends on the "user-mode" option.
-//
-//  You can only include this file when both or none of the above two macros
-//  are defined!
-//  When they are defined, entries that do not generate functions  won't appear,
-//  and when they aren't, all entries are converted to ANALYZER_OPTION or to
-//  ANALYZER_OPTION_DEPENDS_ON_USER_MODE.
-//
 //===----------------------------------------------------------------------===//
 //===----------------------------------------------------------------------===//
 
 
 #ifndef LLVM_ADT_STRINGREF_H
 #ifndef LLVM_ADT_STRINGREF_H
@@ -53,22 +30,6 @@ define both 'ANALYZER_OPTION' and 'ANALYZER_OPTION_DEPENDS_ON_USER_MODE' macros!
 #endif
 #endif
 #endif
 #endif
 
 
-#ifdef ANALYZER_OPTION_GEN_FN
-#ifndef ANALYZER_OPTION_GEN_FN_DEPENDS_ON_USER_MODE
-#error If you include this file with the intent of generating functions, \
-define both 'ANALYZER_OPTION_GEN_FN' and \
-'ANALYZER_OPTION_GEN_FN_DEPENDS_ON_USER_MODE' macros!
-#endif
-#endif
-
-#ifdef ANALYZER_OPTION_GEN_FN_DEPENDS_ON_USER_MODE
-#ifndef ANALYZER_OPTION_GEN_FN
-#error If you include this file with the intent of generating functions, \
-define both 'ANALYZER_OPTION_GEN_FN' and \
-'ANALYZER_OPTION_GEN_FN_DEPENDS_ON_USER_MODE' macros!
-#endif
-#endif
-
 #ifndef ANALYZER_OPTION
 #ifndef ANALYZER_OPTION
 /// Create a new analyzer option, but dont generate a method for it in
 /// Create a new analyzer option, but dont generate a method for it in
 /// AnalyzerOptions.
 /// AnalyzerOptions.
@@ -105,231 +66,187 @@ define both 'ANALYZER_OPTION_GEN_FN' and \
                                              SHALLOW_VAL, DEEP_VAL)
                                              SHALLOW_VAL, DEEP_VAL)
 #endif
 #endif
 
 
-#ifndef ANALYZER_OPTION_GEN_FN
-/// Create a new analyzer option, and generate a getter method for it in
-/// AnalyzerOptions.
-///
-///   TYPE - The type of the option object that will be stored in
-///          AnalyzerOptions. This file is expected to be icluded in translation
-///          units where AnalyzerOptions.h is included, so types from that
-///          header should be used.
-///   NAME - The name of the option object.
-///   CMDFLAG - The command line flag for the option.
-///             (-analyzer-config CMDFLAG=VALUE)
-///   DESC - Description of the flag.
-///   DEFAULT_VAL - The default value for CMDFLAG.
-///   CREATE_FN - Name of the getter function.
-//
-// If this def file wasn't included with the intent of generating functions,
-// regard all entries as ANALYZER_OPTION.
-#define ANALYZER_OPTION_GEN_FN(TYPE, NAME, CMDFLAG, DESC, DEFAULT_VAL,         \
-                               CREATE_FN)                                      \
-  ANALYZER_OPTION(TYPE, NAME, CMDFLAG, DESC, DEFAULT_VAL)
-#endif
+//===----------------------------------------------------------------------===//
+// The "mode" option. Since some options depend on this, we list it on top of
+// this file in order to make sure that the generated field for it is
+// initialized before the rest.
+//===----------------------------------------------------------------------===//
 
 
-#ifndef ANALYZER_OPTION_GEN_FN_DEPENDS_ON_USER_MODE
-/// Create a new analyzer option, and generate a getter method for it in
-/// AnalyzerOptions, and make it's default value depend on the "user-mode"
-/// option.
-///
-///   TYPE - The type of the option object that will be stored in
-///          AnalyzerOptions. This file is expected to be icluded in translation
-///          units where AnalyzerOptions.h is included, so types from that
-///          header should be used.
-///   NAME - The name of the option object.
-///   CMDFLAG - The command line flag for the option.
-///               (-analyzer-config CMDFLAG=VALUE)
-///   DESC - Description of the flago.
-///   SHALLOW_VAL - The default value for CMDFLAG, when "user-mode" was set to
-///                 "shallow".
-///   DEEP_VAL - The default value for CMDFLAG, when "user-mode" was set to
-///              "deep".
-///   CREATE_FN - Name of the getter function.
-//
-// If this def file wasn't included with the intent of generating functions,
-// regard all entries as ANALYZER_OPTION_DEPENDS_ON_USER_MODE.
-#define ANALYZER_OPTION_GEN_FN_DEPENDS_ON_USER_MODE(                           \
-    TYPE, NAME, CMDFLAG, DESC, SHALLOW_VAL, DEEP_VAL, CREATE_FN)               \
-  ANALYZER_OPTION_DEPENDS_ON_USER_MODE(TYPE, NAME, CMDFLAG, DESC, SHALLOW_VAL, \
-                                       DEEP_VAL)
-#endif
+ANALYZER_OPTION(
+    StringRef, UserMode, "mode",
+    "(string) Controls the high-level analyzer mode, which influences the "
+    "default settings for some of the lower-level config options (such as "
+    "IPAMode). Value: \"deep\", \"shallow\".",
+    "deep")
 
 
 //===----------------------------------------------------------------------===//
 //===----------------------------------------------------------------------===//
 // Boolean analyzer options.
 // Boolean analyzer options.
 //===----------------------------------------------------------------------===//
 //===----------------------------------------------------------------------===//
 
 
-ANALYZER_OPTION_GEN_FN(bool, IncludeImplicitDtorsInCFG, "cfg-implicit-dtors",
-                       "Whether or not implicit destructors for C++ objects "
-                       "should be included in the CFG.",
-                       true, includeImplicitDtorsInCFG)
+ANALYZER_OPTION(bool, ShouldIncludeImplicitDtorsInCFG, "cfg-implicit-dtors",
+                "Whether or not implicit destructors for C++ objects "
+                "should be included in the CFG.",
+                true)
 
 
-ANALYZER_OPTION_GEN_FN(bool, IncludeTemporaryDtorsInCFG, "cfg-temporary-dtors",
-                       "Whether or not the destructors for C++ temporary "
-                       "objects should be included in the CFG.",
-                       true, includeTemporaryDtorsInCFG)
+ANALYZER_OPTION(bool, ShouldIncludeTemporaryDtorsInCFG, "cfg-temporary-dtors",
+                "Whether or not the destructors for C++ temporary "
+                "objects should be included in the CFG.",
+                true)
 
 
-ANALYZER_OPTION_GEN_FN(
-    bool, IncludeLifetimeInCFG, "cfg-lifetime",
+ANALYZER_OPTION(
+    bool, ShouldIncludeLifetimeInCFG, "cfg-lifetime",
     "Whether or not end-of-lifetime information should be included in the CFG.",
     "Whether or not end-of-lifetime information should be included in the CFG.",
-    false, includeLifetimeInCFG)
-
-ANALYZER_OPTION_GEN_FN(bool, IncludeLoopExitInCFG, "cfg-loopexit",
-                       "Whether or not the end of the loop information should "
-                       "be included in the CFG.",
-                       false, includeLoopExitInCFG)
-
-ANALYZER_OPTION_GEN_FN(bool, IncludeRichConstructorsInCFG,
-                       "cfg-rich-constructors",
-                       "Whether or not construction site information should be "
-                       "included in the CFG C++ constructor elements.",
-                       true, includeRichConstructorsInCFG)
-
-ANALYZER_OPTION_GEN_FN(
-    bool, IncludeScopesInCFG, "cfg-scopes",
-    "Whether or not scope information should be included in the CFG.", false,
-    includeScopesInCFG)
-
-ANALYZER_OPTION_GEN_FN(
-    bool, InlineTemplateFunctions, "c++-template-inlining",
-    "Whether or not templated functions may be considered for inlining.", true,
-    mayInlineTemplateFunctions)
-
-ANALYZER_OPTION_GEN_FN(bool, InlineCXXStandardLibrary, "c++-stdlib-inlining",
-                       "Whether or not C++ standard library functions may be "
-                       "considered for inlining.",
-                       true, mayInlineCXXStandardLibrary)
-
-ANALYZER_OPTION_GEN_FN(
-    bool, InlineCXXAllocator, "c++-allocator-inlining",
-    "Whether or not allocator call may be considered for inlining.", true,
-    mayInlineCXXAllocator)
-
-ANALYZER_OPTION_GEN_FN(
-    bool, InlineCXXSharedPtrDtor, "c++-shared_ptr-inlining",
+    false)
+
+ANALYZER_OPTION(bool, ShouldIncludeLoopExitInCFG, "cfg-loopexit",
+                "Whether or not the end of the loop information should "
+                "be included in the CFG.",
+                false)
+
+ANALYZER_OPTION(bool, ShouldIncludeRichConstructorsInCFG,
+                "cfg-rich-constructors",
+                "Whether or not construction site information should be "
+                "included in the CFG C++ constructor elements.",
+                true)
+
+ANALYZER_OPTION(
+    bool, ShouldIncludeScopesInCFG, "cfg-scopes",
+    "Whether or not scope information should be included in the CFG.", false)
+
+ANALYZER_OPTION(
+    bool, MayInlineTemplateFunctions, "c++-template-inlining",
+    "Whether or not templated functions may be considered for inlining.", true)
+
+ANALYZER_OPTION(bool, MayInlineCXXStandardLibrary, "c++-stdlib-inlining",
+                "Whether or not C++ standard library functions may be "
+                "considered for inlining.",
+                true)
+
+ANALYZER_OPTION(bool, MayInlineCXXAllocator, "c++-allocator-inlining",
+                "Whether or not allocator call may be considered for inlining.",
+                true)
+
+ANALYZER_OPTION(
+    bool, MayInlineCXXSharedPtrDtor, "c++-shared_ptr-inlining",
     "Whether or not the destructor of C++ 'shared_ptr' may be considered for "
     "Whether or not the destructor of C++ 'shared_ptr' may be considered for "
     "inlining. This covers std::shared_ptr, std::tr1::shared_ptr, and "
     "inlining. This covers std::shared_ptr, std::tr1::shared_ptr, and "
     "boost::shared_ptr, and indeed any destructor named '~shared_ptr'.",
     "boost::shared_ptr, and indeed any destructor named '~shared_ptr'.",
-    false, mayInlineCXXSharedPtrDtor)
+    false)
 
 
-ANALYZER_OPTION_GEN_FN(bool, InlineCXXTemporaryDtors, "c++-temp-dtor-inlining",
-                       "Whether C++ temporary destructors should be inlined "
-                       "during analysis. If temporary destructors are disabled "
-                       "in the CFG via the 'cfg-temporary-dtors' option, "
-                       "temporary destructors would not be inlined anyway.",
-                       true, mayInlineCXXTemporaryDtors)
+ANALYZER_OPTION(bool, MayInlineCXXTemporaryDtors, "c++-temp-dtor-inlining",
+                "Whether C++ temporary destructors should be inlined "
+                "during analysis. If temporary destructors are disabled "
+                "in the CFG via the 'cfg-temporary-dtors' option, "
+                "temporary destructors would not be inlined anyway.",
+                true)
 
 
-ANALYZER_OPTION_GEN_FN(
-    bool, SuppressNullReturnPaths, "suppress-null-return-paths",
+ANALYZER_OPTION(
+    bool, ShouldSuppressNullReturnPaths, "suppress-null-return-paths",
     "Whether or not paths that go through null returns should be suppressed. "
     "Whether or not paths that go through null returns should be suppressed. "
     "This is a heuristic for avoiding bug reports with paths that go through "
     "This is a heuristic for avoiding bug reports with paths that go through "
     "inlined functions that are more defensive than their callers.",
     "inlined functions that are more defensive than their callers.",
-    true, shouldSuppressNullReturnPaths)
+    true)
 
 
-ANALYZER_OPTION_GEN_FN(
-    bool, AvoidSuppressingNullArgumentPaths,
+ANALYZER_OPTION(
+    bool, ShouldAvoidSuppressingNullArgumentPaths,
     "avoid-suppressing-null-argument-paths",
     "avoid-suppressing-null-argument-paths",
     "Whether a bug report should not be suppressed if its path includes a call "
     "Whether a bug report should not be suppressed if its path includes a call "
     "with a null argument, even if that call has a null return. This option "
     "with a null argument, even if that call has a null return. This option "
-    "has no effect when #shouldSuppressNullReturnPaths() is false. This is a "
+    "has no effect when ShouldSuppressNullReturnPaths is false. This is a "
     "counter-heuristic to avoid false negatives.",
     "counter-heuristic to avoid false negatives.",
-    false, shouldAvoidSuppressingNullArgumentPaths)
-
-ANALYZER_OPTION_GEN_FN(bool, SuppressInlinedDefensiveChecks,
-                       "suppress-inlined-defensive-checks",
-                       "Whether or not diagnostics containing inlined "
-                       "defensive NULL checks should be suppressed.",
-                       true, shouldSuppressInlinedDefensiveChecks)
-
-ANALYZER_OPTION_GEN_FN(bool, InlineCXXContainerMethods,
-                       "c++-container-inlining",
-                       "Whether or not methods of C++ container objects may be "
-                       "considered for inlining.",
-                       false, mayInlineCXXContainerMethods)
-
-ANALYZER_OPTION_GEN_FN(bool, SuppressFromCXXStandardLibrary,
-                       "suppress-c++-stdlib",
-                       "Whether or not diagnostics reported within the C++ "
-                       "standard library should be suppressed.",
-                       true, shouldSuppressFromCXXStandardLibrary)
-
-ANALYZER_OPTION_GEN_FN(bool, CrosscheckWithZ3, "crosscheck-with-z3",
-                       "Whether bug reports should be crosschecked with the Z3 "
-                       "constraint manager backend.",
-                       false, shouldCrosscheckWithZ3)
-
-ANALYZER_OPTION_GEN_FN(bool, ReportIssuesInMainSourceFile,
-                       "report-in-main-source-file",
-                       "Whether or not the diagnostic report should be always "
-                       "reported in the main source file and not the headers.",
-                       false, shouldReportIssuesInMainSourceFile)
-
-ANALYZER_OPTION_GEN_FN(
-    bool, WriteStableReportFilename, "stable-report-filename",
-    "Whether or not the report filename should be random or not.", false,
-    shouldWriteStableReportFilename)
-
-ANALYZER_OPTION_GEN_FN(
-    bool, SerializeStats, "serialize-stats",
+    false)
+
+ANALYZER_OPTION(bool, ShouldSuppressInlinedDefensiveChecks,
+                "suppress-inlined-defensive-checks",
+                "Whether or not diagnostics containing inlined "
+                "defensive NULL checks should be suppressed.",
+                true)
+
+ANALYZER_OPTION(bool, MayInlineCXXContainerMethods, "c++-container-inlining",
+                "Whether or not methods of C++ container objects may be "
+                "considered for inlining.",
+                false)
+
+ANALYZER_OPTION(bool, ShouldSuppressFromCXXStandardLibrary,
+                "suppress-c++-stdlib",
+                "Whether or not diagnostics reported within the C++ "
+                "standard library should be suppressed.",
+                true)
+
+ANALYZER_OPTION(bool, ShouldCrosscheckWithZ3, "crosscheck-with-z3",
+                "Whether bug reports should be crosschecked with the Z3 "
+                "constraint manager backend.",
+                false)
+
+ANALYZER_OPTION(bool, ShouldReportIssuesInMainSourceFile,
+                "report-in-main-source-file",
+                "Whether or not the diagnostic report should be always "
+                "reported in the main source file and not the headers.",
+                false)
+
+ANALYZER_OPTION(bool, ShouldWriteStableReportFilename, "stable-report-filename",
+                "Whether or not the report filename should be random or not.",
+                false)
+
+ANALYZER_OPTION(
+    bool, ShouldSerializeStats, "serialize-stats",
     "Whether the analyzer should serialize statistics to plist output. "
     "Whether the analyzer should serialize statistics to plist output. "
     "Statistics would be serialized in JSON format inside the main dictionary "
     "Statistics would be serialized in JSON format inside the main dictionary "
     "under the statistics key. Available only if compiled in assert mode or "
     "under the statistics key. Available only if compiled in assert mode or "
     "with LLVM statistics explicitly enabled.",
     "with LLVM statistics explicitly enabled.",
-    false, shouldSerializeStats)
+    false)
 
 
-ANALYZER_OPTION_GEN_FN(
-    bool, InlineObjCMethod, "objc-inlining",
-    "Whether ObjectiveC inlining is enabled, false otherwise.", true,
-    mayInlineObjCMethod)
+ANALYZER_OPTION(bool, MayInlineObjCMethod, "objc-inlining",
+                "Whether ObjectiveC inlining is enabled, false otherwise.",
+                true)
 
 
-ANALYZER_OPTION_GEN_FN(bool, PrunePaths, "prune-paths",
-                       "Whether irrelevant parts of a bug report path should "
-                       "be pruned out of the final output.",
-                       true, shouldPrunePaths)
+ANALYZER_OPTION(bool, ShouldPrunePaths, "prune-paths",
+                "Whether irrelevant parts of a bug report path should "
+                "be pruned out of the final output.",
+                true)
 
 
-ANALYZER_OPTION_GEN_FN(
-    bool, ConditionalizeStaticInitializers,
+ANALYZER_OPTION(
+    bool, ShouldConditionalizeStaticInitializers,
     "cfg-conditional-static-initializers",
     "cfg-conditional-static-initializers",
     "Whether 'static' initializers should be in conditional logic in the CFG.",
     "Whether 'static' initializers should be in conditional logic in the CFG.",
-    true, shouldConditionalizeStaticInitializers)
+    true)
 
 
-ANALYZER_OPTION_GEN_FN(bool, SynthesizeBodies, "faux-bodies",
-                       "Whether the analyzer engine should synthesize fake "
-                       "bodies for well-known functions.",
-                       true, shouldSynthesizeBodies)
+ANALYZER_OPTION(bool, ShouldSynthesizeBodies, "faux-bodies",
+                "Whether the analyzer engine should synthesize fake "
+                "bodies for well-known functions.",
+                true)
 
 
-ANALYZER_OPTION_GEN_FN(
-    bool, ElideConstructors, "elide-constructors",
+ANALYZER_OPTION(
+    bool, ShouldElideConstructors, "elide-constructors",
     "Whether elidable C++ copy-constructors and move-constructors should be "
     "Whether elidable C++ copy-constructors and move-constructors should be "
     "actually elided during analysis. Both behaviors are allowed by the C++ "
     "actually elided during analysis. Both behaviors are allowed by the C++ "
     "standard, and the analyzer, like CodeGen, defaults to eliding. Starting "
     "standard, and the analyzer, like CodeGen, defaults to eliding. Starting "
     "with C++17 some elisions become mandatory, and in these cases the option "
     "with C++17 some elisions become mandatory, and in these cases the option "
     "will be ignored.",
     "will be ignored.",
-    true, shouldElideConstructors)
+    true)
 
 
-ANALYZER_OPTION_GEN_FN(
-    bool, InlineLambdas, "inline-lambdas",
+ANALYZER_OPTION(
+    bool, ShouldInlineLambdas, "inline-lambdas",
     "Whether lambdas should be inlined. Otherwise a sink node will be "
     "Whether lambdas should be inlined. Otherwise a sink node will be "
     "generated each time a LambdaExpr is visited.",
     "generated each time a LambdaExpr is visited.",
-    true, shouldInlineLambdas)
+    true)
 
 
-ANALYZER_OPTION_GEN_FN(bool, WidenLoops, "widen-loops",
-                       "Whether the analysis should try to widen loops.", false,
-                       shouldWidenLoops)
+ANALYZER_OPTION(bool, ShouldWidenLoops, "widen-loops",
+                "Whether the analysis should try to widen loops.", false)
 
 
-ANALYZER_OPTION_GEN_FN(
-    bool, UnrollLoops, "unroll-loops",
-    "Whether the analysis should try to unroll loops with known bounds.", false,
-    shouldUnrollLoops)
+ANALYZER_OPTION(
+    bool, ShouldUnrollLoops, "unroll-loops",
+    "Whether the analysis should try to unroll loops with known bounds.", false)
 
 
-ANALYZER_OPTION_GEN_FN(
-    bool, DisplayNotesAsEvents, "notes-as-events",
+ANALYZER_OPTION(
+    bool, ShouldDisplayNotesAsEvents, "notes-as-events",
     "Whether the bug reporter should transparently treat extra note diagnostic "
     "Whether the bug reporter should transparently treat extra note diagnostic "
     "pieces as event diagnostic pieces. Useful when the diagnostic consumer "
     "pieces as event diagnostic pieces. Useful when the diagnostic consumer "
     "doesn't support the extra note pieces.",
     "doesn't support the extra note pieces.",
-    false, shouldDisplayNotesAsEvents)
+    false)
 
 
-ANALYZER_OPTION_GEN_FN(
-    bool, AggressivelySimplifyBinaryOperation,
+ANALYZER_OPTION(
+    bool, ShouldAggressivelySimplifyBinaryOperation,
     "aggressive-binary-operation-simplification",
     "aggressive-binary-operation-simplification",
     "Whether SValBuilder should rearrange comparisons and additive operations "
     "Whether SValBuilder should rearrange comparisons and additive operations "
     "of symbolic expressions which consist of a sum of a symbol and a concrete "
     "of symbolic expressions which consist of a sum of a symbol and a concrete "
@@ -342,10 +259,10 @@ ANALYZER_OPTION_GEN_FN(
     "'<', '<=', '>', '>=', '+' or '-'. The rearrangement also happens with '-' "
     "'<', '<=', '>', '>=', '+' or '-'. The rearrangement also happens with '-' "
     "instead of '+' on either or both side and also if any or both integers "
     "instead of '+' on either or both side and also if any or both integers "
     "are missing.",
     "are missing.",
-    false, shouldAggressivelySimplifyBinaryOperation)
+    false)
 
 
-ANALYZER_OPTION_GEN_FN(
-    bool, EagerlyAssume, "eagerly-assume",
+ANALYZER_OPTION(
+    bool, ShouldEagerlyAssume, "eagerly-assume",
     "Whether we should eagerly assume evaluations of conditionals, thus, "
     "Whether we should eagerly assume evaluations of conditionals, thus, "
     "bifurcating the path. This indicates how the engine should handle "
     "bifurcating the path. This indicates how the engine should handle "
     "expressions such as: 'x = (y != 0)'. When this is true then the "
     "expressions such as: 'x = (y != 0)'. When this is true then the "
@@ -353,69 +270,66 @@ ANALYZER_OPTION_GEN_FN(
     "evaluating it to the integers 0 or 1 respectively. The upside is that "
     "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 "
     "this can increase analysis precision until we have a better way to lazily "
     "evaluate such logic. The downside is that it eagerly bifurcates paths.",
     "evaluate such logic. The downside is that it eagerly bifurcates paths.",
-    true, shouldEagerlyAssume)
+    true)
 
 
-ANALYZER_OPTION_GEN_FN(
-    bool, NaiveCTU, "experimental-enable-naive-ctu-analysis",
+ANALYZER_OPTION(
+    bool, IsNaiveCTUEnabled, "experimental-enable-naive-ctu-analysis",
     "Whether naive cross translation unit analysis is enabled. This is an "
     "Whether naive cross translation unit analysis is enabled. This is an "
     "experimental feature to inline functions from another translation units.",
     "experimental feature to inline functions from another translation units.",
-    false, naiveCTUEnabled)
+    false)
 
 
-ANALYZER_OPTION_GEN_FN(bool, DisplayMacroExpansions, "expand-macros",
-                       "Whether macros related to the bugpath should be "
-                       "expanded and included in the plist output.",
-                       false, shouldDisplayMacroExpansions)
+ANALYZER_OPTION(bool, ShouldDisplayMacroExpansions, "expand-macros",
+                "Whether macros related to the bugpath should be "
+                "expanded and included in the plist output.",
+                false)
 
 
 //===----------------------------------------------------------------------===//
 //===----------------------------------------------------------------------===//
 // Unsinged analyzer options.
 // Unsinged analyzer options.
 //===----------------------------------------------------------------------===//
 //===----------------------------------------------------------------------===//
 
 
-ANALYZER_OPTION_GEN_FN(
+ANALYZER_OPTION(
     unsigned, AlwaysInlineSize, "ipa-always-inline-size",
     unsigned, AlwaysInlineSize, "ipa-always-inline-size",
     "The size of the functions (in basic blocks), which should be considered "
     "The size of the functions (in basic blocks), which should be considered "
     "to be small enough to always inline.",
     "to be small enough to always inline.",
-    3, getAlwaysInlineSize)
+    3)
 
 
-ANALYZER_OPTION_GEN_FN(
+ANALYZER_OPTION(
     unsigned, GraphTrimInterval, "graph-trim-interval",
     unsigned, GraphTrimInterval, "graph-trim-interval",
     "How often nodes in the ExplodedGraph should be recycled to save memory. "
     "How often nodes in the ExplodedGraph should be recycled to save memory. "
     "To disable node reclamation, set the option to 0.",
     "To disable node reclamation, set the option to 0.",
-    1000, getGraphTrimInterval)
+    1000)
 
 
-ANALYZER_OPTION_GEN_FN(
+ANALYZER_OPTION(
     unsigned, MinCFGSizeTreatFunctionsAsLarge,
     unsigned, MinCFGSizeTreatFunctionsAsLarge,
     "min-cfg-size-treat-functions-as-large",
     "min-cfg-size-treat-functions-as-large",
     "The number of basic blocks a function needs to have to be considered "
     "The number of basic blocks a function needs to have to be considered "
     "large for the 'max-times-inline-large' config option.",
     "large for the 'max-times-inline-large' config option.",
-    14, getMinCFGSizeTreatFunctionsAsLarge)
+    14)
 
 
-ANALYZER_OPTION_GEN_FN(unsigned, MaxSymbolComplexity, "max-symbol-complexity",
-                       "The maximum complexity of symbolic constraint.", 35,
-                       getMaxSymbolComplexity)
+ANALYZER_OPTION(unsigned, MaxSymbolComplexity, "max-symbol-complexity",
+                "The maximum complexity of symbolic constraint.", 35)
 
 
-ANALYZER_OPTION_GEN_FN(unsigned, MaxTimesInlineLarge, "max-times-inline-large",
-                       "The maximum times a large function could be inlined.",
-                       32, getMaxTimesInlineLarge)
+ANALYZER_OPTION(unsigned, MaxTimesInlineLarge, "max-times-inline-large",
+                "The maximum times a large function could be inlined.", 32)
 
 
-ANALYZER_OPTION_GEN_FN_DEPENDS_ON_USER_MODE(
+ANALYZER_OPTION_DEPENDS_ON_USER_MODE(
     unsigned, MaxInlinableSize, "max-inlinable-size",
     unsigned, MaxInlinableSize, "max-inlinable-size",
     "The bound on the number of basic blocks in an inlined function.",
     "The bound on the number of basic blocks in an inlined function.",
-    /* SHALLOW_VAL */ 4, /* DEEP_VAL */ 100, getMaxInlinableSize)
+    /* SHALLOW_VAL */ 4, /* DEEP_VAL */ 100)
 
 
-ANALYZER_OPTION_GEN_FN_DEPENDS_ON_USER_MODE(
+ANALYZER_OPTION_DEPENDS_ON_USER_MODE(
     unsigned, MaxNodesPerTopLevelFunction, "max-nodes",
     unsigned, MaxNodesPerTopLevelFunction, "max-nodes",
     "The maximum number of nodes the analyzer can generate while exploring a "
     "The maximum number of nodes the analyzer can generate while exploring a "
     "top level function (for each exploded graph). 0 means no limit.",
     "top level function (for each exploded graph). 0 means no limit.",
-    /* SHALLOW_VAL */ 75000, /* DEEP_VAL */ 225000,
-    getMaxNodesPerTopLevelFunction)
+    /* SHALLOW_VAL */ 75000, /* DEEP_VAL */ 225000)
 
 
-ANALYZER_OPTION_GEN_FN(
+ANALYZER_OPTION(
     unsigned, RegionStoreSmallStructLimit, "region-store-small-struct-limit",
     unsigned, RegionStoreSmallStructLimit, "region-store-small-struct-limit",
     "The largest number of fields a struct can have and still be considered "
     "The largest number of fields a struct can have and still be considered "
     "small This is currently used to decide whether or not it is worth forcing "
     "small This is currently used to decide whether or not it is worth forcing "
     "a LazyCompoundVal on bind. To disable all small-struct-dependent "
     "a LazyCompoundVal on bind. To disable all small-struct-dependent "
     "behavior, set the option to 0.",
     "behavior, set the option to 0.",
-    2, getRegionStoreSmallStructLimit)
+    2)
 
 
 //===----------------------------------------------------------------------===//
 //===----------------------------------------------------------------------===//
 // String analyzer options.
 // String analyzer options.
@@ -424,23 +338,16 @@ ANALYZER_OPTION_GEN_FN(
 ANALYZER_OPTION(StringRef, CTUDir, "ctu-dir",
 ANALYZER_OPTION(StringRef, CTUDir, "ctu-dir",
                 "The directory containing the CTU related files.", "")
                 "The directory containing the CTU related files.", "")
 
 
-ANALYZER_OPTION_GEN_FN(
-    StringRef, CTUIndexName, "ctu-index-name",
-    "the name of the file containing the CTU index of functions.",
-    "externalFnMap.txt", getCTUIndexName)
+ANALYZER_OPTION(StringRef, CTUIndexName, "ctu-index-name",
+                "the name of the file containing the CTU index of functions.",
+                "externalFnMap.txt")
 
 
-ANALYZER_OPTION_GEN_FN(
+ANALYZER_OPTION(
     StringRef, ModelPath, "model-path",
     StringRef, ModelPath, "model-path",
     "The analyzer can inline an alternative implementation written in C at the "
     "The analyzer can inline an alternative implementation written in C at the "
     "call site if the called function's body is not available. This is a path "
     "call site if the called function's body is not available. This is a path "
     "where to look for those alternative implementations (called models).",
     "where to look for those alternative implementations (called models).",
-    "", getModelPath)
-
-ANALYZER_OPTION(StringRef, UserMode, "mode",
-                "Controls the high-level analyzer mode, which influences the "
-                "default settings for some of the lower-level config options "
-                "(such as IPAMode). Value: \"deep\", \"shallow\".",
-                "deep")
+    "")
 
 
 ANALYZER_OPTION(
 ANALYZER_OPTION(
     StringRef, CXXMemberInliningMode, "c++-inlining",
     StringRef, CXXMemberInliningMode, "c++-inlining",
@@ -461,7 +368,5 @@ ANALYZER_OPTION(
     "\"bfs_block_dfs_contents\".",
     "\"bfs_block_dfs_contents\".",
     "unexplored_first_queue")
     "unexplored_first_queue")
 
 
-#undef ANALYZER_OPTION_GEN_FN_DEPENDS_ON_USER_MODE
-#undef ANALYZER_OPTION_GEN_FN
 #undef ANALYZER_OPTION_DEPENDS_ON_USER_MODE
 #undef ANALYZER_OPTION_DEPENDS_ON_USER_MODE
 #undef ANALYZER_OPTION
 #undef ANALYZER_OPTION

+ 28 - 54
include/clang/StaticAnalyzer/Core/AnalyzerOptions.h

@@ -20,6 +20,7 @@
 #include "llvm/ADT/Optional.h"
 #include "llvm/ADT/Optional.h"
 #include "llvm/ADT/StringMap.h"
 #include "llvm/ADT/StringMap.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/StringSwitch.h"
 #include <string>
 #include <string>
 #include <utility>
 #include <utility>
 #include <vector>
 #include <vector>
@@ -170,6 +171,7 @@ public:
   std::vector<std::pair<std::string, bool>> CheckersControlList;
   std::vector<std::pair<std::string, bool>> CheckersControlList;
 
 
   /// A key-value table of use-specified configuration values.
   /// A key-value table of use-specified configuration values.
+  // TODO: This shouldn't be public.
   ConfigTable Config;
   ConfigTable Config;
   AnalysisStores AnalysisStoreOpt = RegionStoreModel;
   AnalysisStores AnalysisStoreOpt = RegionStoreModel;
   AnalysisConstraints AnalysisConstraintsOpt = RangeConstraintsModel;
   AnalysisConstraints AnalysisConstraintsOpt = RangeConstraintsModel;
@@ -220,33 +222,17 @@ public:
   /// The mode of function selection used during inlining.
   /// The mode of function selection used during inlining.
   AnalysisInliningMode InliningMode = NoRedundancy;
   AnalysisInliningMode InliningMode = NoRedundancy;
 
 
-private:
-
-#define ANALYZER_OPTION(TYPE, NAME, CMDFLAG, DESC, DEFAULT_VAL)                \
-  Optional<TYPE> NAME;
 #define ANALYZER_OPTION_DEPENDS_ON_USER_MODE(TYPE, NAME, CMDFLAG, DESC,        \
 #define ANALYZER_OPTION_DEPENDS_ON_USER_MODE(TYPE, NAME, CMDFLAG, DESC,        \
                                              SHALLOW_VAL, DEEP_VAL)            \
                                              SHALLOW_VAL, DEEP_VAL)            \
-  Optional<TYPE> NAME;
+  ANALYZER_OPTION(TYPE, NAME, CMDFLAG, DESC, SHALLOW_VAL)
+
+#define ANALYZER_OPTION(TYPE, NAME, CMDFLAG, DESC, DEFAULT_VAL)                \
+  TYPE NAME;
+
 #include "clang/StaticAnalyzer/Core/AnalyzerOptions.def"
 #include "clang/StaticAnalyzer/Core/AnalyzerOptions.def"
 #undef ANALYZER_OPTION
 #undef ANALYZER_OPTION
 #undef ANALYZER_OPTION_DEPENDS_ON_USER_MODE
 #undef ANALYZER_OPTION_DEPENDS_ON_USER_MODE
 
 
-  /// Query an option's string value.
-  ///
-  /// If an option value is not provided, returns the given \p DefaultVal.
-  /// @param [in] OptionName Name for option to retrieve.
-  /// @param [in] DefaultVal Default value returned if no such option was
-  /// specified.
-  StringRef getStringOption(StringRef OptionName, StringRef DefaultVal);
-
-  void initOption(Optional<StringRef> &V, StringRef Name,
-                                          StringRef DefaultVal);
-
-  void initOption(Optional<bool> &V, StringRef Name, bool DefaultVal);
-
-  void initOption(Optional<unsigned> &V, StringRef Name,
-                                         unsigned DefaultVal);
-public:
   AnalyzerOptions()
   AnalyzerOptions()
       : DisableAllChecks(false), ShowCheckerHelp(false),
       : DisableAllChecks(false), ShowCheckerHelp(false),
         ShowEnabledCheckerList(false), ShowConfigOptionsList(false),
         ShowEnabledCheckerList(false), ShowConfigOptionsList(false),
@@ -308,42 +294,15 @@ public:
                               const ento::CheckerBase *C,
                               const ento::CheckerBase *C,
                               bool SearchInParents = false) const;
                               bool SearchInParents = false) const;
 
 
-#define ANALYZER_OPTION_GEN_FN(TYPE, NAME, CMDFLAG, DESC, DEFAULT_VAL,  \
-                               CREATE_FN)                               \
-  TYPE CREATE_FN() {                                                    \
-    initOption(NAME, CMDFLAG, DEFAULT_VAL);                             \
-    return NAME.getValue();                                             \
-  }
-
-#define ANALYZER_OPTION_GEN_FN_DEPENDS_ON_USER_MODE(                    \
-    TYPE, NAME, CMDFLAG, DESC, SHALLOW_VAL, DEEP_VAL, CREATE_FN)        \
-  TYPE CREATE_FN() {                                                    \
-    switch (getUserMode()) {                                            \
-    case UMK_Shallow:                                                   \
-      initOption(NAME, CMDFLAG, SHALLOW_VAL);                           \
-      break;                                                            \
-    case UMK_Deep:                                                      \
-      initOption(NAME, CMDFLAG, DEEP_VAL);                              \
-      break;                                                            \
-    }                                                                   \
-                                                                        \
-    return NAME.getValue();                                             \
-  }
-
-#include "clang/StaticAnalyzer/Core/AnalyzerOptions.def"
-
-#undef ANALYZER_OPTION_GEN_FN_DEPENDS_ON_USER_MODE
-#undef ANALYZER_OPTION_WITH_FN
-
   /// Retrieves and sets the UserMode. This is a high-level option,
   /// Retrieves and sets the UserMode. This is a high-level option,
   /// which is used to set other low-level options. It is not accessible
   /// which is used to set other low-level options. It is not accessible
   /// outside of AnalyzerOptions.
   /// outside of AnalyzerOptions.
-  UserModeKind getUserMode();
+  UserModeKind getUserMode() const;
 
 
-  ExplorationStrategyKind getExplorationStrategy();
+  ExplorationStrategyKind getExplorationStrategy() const;
 
 
   /// Returns the inter-procedural analysis mode.
   /// Returns the inter-procedural analysis mode.
-  IPAKind getIPAMode();
+  IPAKind getIPAMode() const;
 
 
   /// Returns the option controlling which C++ member functions will be
   /// Returns the option controlling which C++ member functions will be
   /// considered for inlining.
   /// considered for inlining.
@@ -351,13 +310,28 @@ public:
   /// This is controlled by the 'c++-inlining' config option.
   /// This is controlled by the 'c++-inlining' config option.
   ///
   ///
   /// \sa CXXMemberInliningMode
   /// \sa CXXMemberInliningMode
-  bool mayInlineCXXMemberFunction(CXXInlineableMemberKind K);
-
-  StringRef getCTUDir();
+  bool mayInlineCXXMemberFunction(CXXInlineableMemberKind K) const;
 };
 };
 
 
 using AnalyzerOptionsRef = IntrusiveRefCntPtr<AnalyzerOptions>;
 using AnalyzerOptionsRef = IntrusiveRefCntPtr<AnalyzerOptions>;
 
 
+//===----------------------------------------------------------------------===//
+// We'll use AnalyzerOptions in the frontend, but we can't link the frontend
+// with clangStaticAnalyzerCore, because clangStaticAnalyzerCore depends on
+// clangFrontend.
+//
+// For this reason, implement some methods in this header file.
+//===----------------------------------------------------------------------===//
+
+inline UserModeKind AnalyzerOptions::getUserMode() const {
+  auto K = llvm::StringSwitch<llvm::Optional<UserModeKind>>(UserMode)
+    .Case("shallow", UMK_Shallow)
+    .Case("deep", UMK_Deep)
+    .Default(None);
+  assert(K.hasValue() && "User mode is invalid.");
+  return K.getValue();
+}
+
 } // namespace clang
 } // namespace clang
 
 
 #endif // LLVM_CLANG_STATICANALYZER_CORE_ANALYZEROPTIONS_H
 #endif // LLVM_CLANG_STATICANALYZER_CORE_ANALYZEROPTIONS_H

+ 63 - 0
lib/Frontend/CompilerInvocation.cpp

@@ -181,6 +181,9 @@ static void addDiagnosticArgs(ArgList &Args, OptSpecifier Group,
   }
   }
 }
 }
 
 
+static void parseAnalyzerConfigs(AnalyzerOptions &AnOpts,
+                                 DiagnosticsEngine &Diags);
+
 static void getAllNoBuiltinFuncValues(ArgList &Args,
 static void getAllNoBuiltinFuncValues(ArgList &Args,
                                       std::vector<std::string> &Funcs) {
                                       std::vector<std::string> &Funcs) {
   SmallVector<const char *, 8> Values;
   SmallVector<const char *, 8> Values;
@@ -343,6 +346,8 @@ static bool ParseAnalyzerArgs(AnalyzerOptions &Opts, ArgList &Args,
     }
     }
   }
   }
 
 
+  parseAnalyzerConfigs(Opts, Diags);
+
   llvm::raw_string_ostream os(Opts.FullCompilerInvocation);
   llvm::raw_string_ostream os(Opts.FullCompilerInvocation);
   for (unsigned i = 0; i < Args.getNumInputArgStrings(); ++i) {
   for (unsigned i = 0; i < Args.getNumInputArgStrings(); ++i) {
     if (i != 0)
     if (i != 0)
@@ -354,6 +359,64 @@ static bool ParseAnalyzerArgs(AnalyzerOptions &Opts, ArgList &Args,
   return Success;
   return Success;
 }
 }
 
 
+static StringRef getStringOption(AnalyzerOptions::ConfigTable &Config,
+                                 StringRef OptionName, StringRef DefaultVal) {
+  return Config.insert({OptionName, DefaultVal}).first->second;
+}
+
+static void initOption(AnalyzerOptions::ConfigTable &Config,
+                       StringRef &OptionField, StringRef Name,
+                       StringRef DefaultVal) {
+  OptionField = getStringOption(Config, Name, DefaultVal);
+}
+
+static void initOption(AnalyzerOptions::ConfigTable &Config,
+                       bool &OptionField, StringRef Name, bool DefaultVal) {
+  // FIXME: We should emit a warning here if the value is something other than
+  // "true", "false", or the empty string (meaning the default value),
+  // but the AnalyzerOptions doesn't have access to a diagnostic engine.
+  OptionField = llvm::StringSwitch<bool>(getStringOption(Config, Name,
+                                               (DefaultVal ? "true" : "false")))
+      .Case("true", true)
+      .Case("false", false)
+      .Default(DefaultVal);
+}
+
+static void initOption(AnalyzerOptions::ConfigTable &Config,
+                       unsigned &OptionField, StringRef Name,
+                       unsigned DefaultVal) {
+  OptionField = DefaultVal;
+  bool HasFailed = getStringOption(Config, Name, std::to_string(DefaultVal))
+                     .getAsInteger(10, OptionField);
+  assert(!HasFailed && "analyzer-config option should be numeric");
+  (void)HasFailed;
+}
+
+static void parseAnalyzerConfigs(AnalyzerOptions &AnOpts,
+                                 DiagnosticsEngine &Diags) {
+  // TODO: Emit warnings for incorrect options.
+  // TODO: There's no need to store the entire configtable, it'd be plenty
+  // enough tostore checker options.
+
+#define ANALYZER_OPTION(TYPE, NAME, CMDFLAG, DESC, DEFAULT_VAL)                \
+  initOption(AnOpts.Config, AnOpts.NAME, CMDFLAG, DEFAULT_VAL);                \
+
+#define ANALYZER_OPTION_DEPENDS_ON_USER_MODE(TYPE, NAME, CMDFLAG, DESC,        \
+                                           SHALLOW_VAL, DEEP_VAL)              \
+  switch (AnOpts.getUserMode()) {                                              \
+  case UMK_Shallow:                                                            \
+    initOption(AnOpts.Config, AnOpts.NAME, CMDFLAG, SHALLOW_VAL);              \
+    break;                                                                     \
+  case UMK_Deep:                                                               \
+    initOption(AnOpts.Config, AnOpts.NAME, CMDFLAG, DEEP_VAL);                 \
+    break;                                                                     \
+  }                                                                            \
+
+#include "clang/StaticAnalyzer/Core/AnalyzerOptions.def"
+#undef ANALYZER_OPTION
+#undef ANALYZER_OPTION_DEPENDS_ON_USER_MODE
+}
+
 static bool ParseMigratorArgs(MigratorOptions &Opts, ArgList &Args) {
 static bool ParseMigratorArgs(MigratorOptions &Opts, ArgList &Args) {
   Opts.NoNSAllocReallocError = Args.hasArg(OPT_migrator_no_nsalloc_error);
   Opts.NoNSAllocReallocError = Args.hasArg(OPT_migrator_no_nsalloc_error);
   Opts.NoFinalizeRemoval = Args.hasArg(OPT_migrator_no_finalize_removal);
   Opts.NoFinalizeRemoval = Args.hasArg(OPT_migrator_no_finalize_removal);

+ 3 - 1
lib/StaticAnalyzer/Checkers/DebugCheckers.cpp

@@ -182,7 +182,9 @@ public:
 
 
     llvm::errs() << "[config]\n";
     llvm::errs() << "[config]\n";
     for (unsigned I = 0, E = Keys.size(); I != E; ++I)
     for (unsigned I = 0, E = Keys.size(); I != E; ++I)
-      llvm::errs() << Keys[I]->getKey() << " = " << Keys[I]->second << '\n';
+      llvm::errs() << Keys[I]->getKey() << " = "
+                   << (Keys[I]->second.empty() ? "\"\"" : Keys[I]->second)
+                   << '\n';
 
 
     llvm::errs() << "[stats]\n" << "num-entries = " << Keys.size() << '\n';
     llvm::errs() << "[stats]\n" << "num-entries = " << Keys.size() << '\n';
   }
   }

+ 1 - 1
lib/StaticAnalyzer/Checkers/MallocChecker.cpp

@@ -1094,7 +1094,7 @@ void MallocChecker::processNewAllocation(const CXXNewExpr *NE,
 
 
 void MallocChecker::checkPostStmt(const CXXNewExpr *NE,
 void MallocChecker::checkPostStmt(const CXXNewExpr *NE,
                                   CheckerContext &C) const {
                                   CheckerContext &C) const {
-  if (!C.getAnalysisManager().getAnalyzerOptions().mayInlineCXXAllocator())
+  if (!C.getAnalysisManager().getAnalyzerOptions().MayInlineCXXAllocator)
     processNewAllocation(NE, C, C.getSVal(NE));
     processNewAllocation(NE, C, C.getSVal(NE));
 }
 }
 
 

+ 13 - 8
lib/StaticAnalyzer/Core/AnalysisManager.cpp

@@ -22,16 +22,21 @@ AnalysisManager::AnalysisManager(ASTContext &ASTCtx, DiagnosticsEngine &diags,
                                  AnalyzerOptions &Options,
                                  AnalyzerOptions &Options,
                                  CodeInjector *injector)
                                  CodeInjector *injector)
     : AnaCtxMgr(
     : AnaCtxMgr(
-          ASTCtx, Options.UnoptimizedCFG, Options.includeImplicitDtorsInCFG(),
-          /*AddInitializers=*/true, Options.includeTemporaryDtorsInCFG(),
-          Options.includeLifetimeInCFG(),
+          ASTCtx, Options.UnoptimizedCFG,
+          Options.ShouldIncludeImplicitDtorsInCFG,
+          /*AddInitializers=*/true,
+          Options.ShouldIncludeTemporaryDtorsInCFG,
+          Options.ShouldIncludeLifetimeInCFG,
           // Adding LoopExit elements to the CFG is a requirement for loop
           // Adding LoopExit elements to the CFG is a requirement for loop
           // unrolling.
           // unrolling.
-          Options.includeLoopExitInCFG() || Options.shouldUnrollLoops(),
-          Options.includeScopesInCFG(), Options.shouldSynthesizeBodies(),
-          Options.shouldConditionalizeStaticInitializers(),
-          /*addCXXNewAllocator=*/true, Options.includeRichConstructorsInCFG(),
-          Options.shouldElideConstructors(), injector),
+          Options.ShouldIncludeLoopExitInCFG ||
+            Options.ShouldUnrollLoops,
+          Options.ShouldIncludeScopesInCFG,
+          Options.ShouldSynthesizeBodies,
+          Options.ShouldConditionalizeStaticInitializers,
+          /*addCXXNewAllocator=*/true,
+          Options.ShouldIncludeRichConstructorsInCFG,
+          Options.ShouldElideConstructors, injector),
       Ctx(ASTCtx), Diags(diags), LangOpts(ASTCtx.getLangOpts()),
       Ctx(ASTCtx), Diags(diags), LangOpts(ASTCtx.getLangOpts()),
       PathConsumers(PDC), CreateStoreMgr(storemgr),
       PathConsumers(PDC), CreateStoreMgr(storemgr),
       CreateConstraintMgr(constraintmgr), CheckerMgr(checkerMgr),
       CreateConstraintMgr(constraintmgr), CheckerMgr(checkerMgr),

+ 9 - 91
lib/StaticAnalyzer/Core/AnalyzerOptions.cpp

@@ -49,28 +49,11 @@ AnalyzerOptions::getRegisteredCheckers(bool IncludeExperimental /* = false */) {
   return Result;
   return Result;
 }
 }
 
 
-UserModeKind AnalyzerOptions::getUserMode() {
-  if (!UserMode.hasValue()) {
-    UserMode = getStringOption("mode", "deep");
-  }
-
-  auto K = llvm::StringSwitch<llvm::Optional<UserModeKind>>(*UserMode)
-    .Case("shallow", UMK_Shallow)
-    .Case("deep", UMK_Deep)
-    .Default(None);
-  assert(UserMode.hasValue() && "User mode is invalid.");
-  return K.getValue();
-}
-
 ExplorationStrategyKind
 ExplorationStrategyKind
-AnalyzerOptions::getExplorationStrategy() {
-  if (!ExplorationStrategy.hasValue()) {
-    ExplorationStrategy = getStringOption("exploration_strategy",
-                                            "unexplored_first_queue");
-  }
+AnalyzerOptions::getExplorationStrategy() const {
   auto K =
   auto K =
     llvm::StringSwitch<llvm::Optional<ExplorationStrategyKind>>(
     llvm::StringSwitch<llvm::Optional<ExplorationStrategyKind>>(
-                                                           *ExplorationStrategy)
+                                                            ExplorationStrategy)
           .Case("dfs", ExplorationStrategyKind::DFS)
           .Case("dfs", ExplorationStrategyKind::DFS)
           .Case("bfs", ExplorationStrategyKind::BFS)
           .Case("bfs", ExplorationStrategyKind::BFS)
           .Case("unexplored_first",
           .Case("unexplored_first",
@@ -86,18 +69,8 @@ AnalyzerOptions::getExplorationStrategy() {
   return K.getValue();
   return K.getValue();
 }
 }
 
 
-IPAKind AnalyzerOptions::getIPAMode() {
-  if (!IPAMode.hasValue()) {
-    switch (getUserMode()) {
-    case UMK_Shallow:
-      IPAMode = getStringOption("ipa", "inlining");
-      break;
-    case UMK_Deep:
-      IPAMode = getStringOption("ipa", "dynamic-bifurcate");
-      break;
-    }
-  }
-  auto K = llvm::StringSwitch<llvm::Optional<IPAKind>>(*IPAMode)
+IPAKind AnalyzerOptions::getIPAMode() const {
+  auto K = llvm::StringSwitch<llvm::Optional<IPAKind>>(IPAMode)
           .Case("none", IPAK_None)
           .Case("none", IPAK_None)
           .Case("basic-inlining", IPAK_BasicInlining)
           .Case("basic-inlining", IPAK_BasicInlining)
           .Case("inlining", IPAK_Inlining)
           .Case("inlining", IPAK_Inlining)
@@ -110,17 +83,14 @@ IPAKind AnalyzerOptions::getIPAMode() {
 }
 }
 
 
 bool
 bool
-AnalyzerOptions::mayInlineCXXMemberFunction(CXXInlineableMemberKind Param) {
-  if (!CXXMemberInliningMode.hasValue()) {
-    CXXMemberInliningMode = getStringOption("c++-inlining", "destructors");
-  }
-
+AnalyzerOptions::mayInlineCXXMemberFunction(
+                                          CXXInlineableMemberKind Param) const {
   if (getIPAMode() < IPAK_Inlining)
   if (getIPAMode() < IPAK_Inlining)
     return false;
     return false;
 
 
   auto K =
   auto K =
     llvm::StringSwitch<llvm::Optional<CXXInlineableMemberKind>>(
     llvm::StringSwitch<llvm::Optional<CXXInlineableMemberKind>>(
-                                                         *CXXMemberInliningMode)
+                                                          CXXMemberInliningMode)
     .Case("constructors", CIMK_Constructors)
     .Case("constructors", CIMK_Constructors)
     .Case("destructors", CIMK_Destructors)
     .Case("destructors", CIMK_Destructors)
     .Case("methods", CIMK_MemberFunctions)
     .Case("methods", CIMK_MemberFunctions)
@@ -132,50 +102,6 @@ AnalyzerOptions::mayInlineCXXMemberFunction(CXXInlineableMemberKind Param) {
   return *K >= Param;
   return *K >= Param;
 }
 }
 
 
-StringRef AnalyzerOptions::getStringOption(StringRef OptionName,
-                                           StringRef DefaultVal) {
-  return Config.insert({OptionName, DefaultVal}).first->second;
-}
-
-static StringRef toString(bool B) { return (B ? "true" : "false"); }
-
-template <typename T>
-static StringRef toString(T) = delete;
-
-void AnalyzerOptions::initOption(Optional<StringRef> &V, StringRef Name,
-                                                         StringRef DefaultVal) {
-  if (V.hasValue())
-    return;
-
-  V = getStringOption(Name, DefaultVal);
-}
-
-void AnalyzerOptions::initOption(Optional<bool> &V, StringRef Name,
-                                                    bool DefaultVal) {
-  if (V.hasValue())
-    return;
-
-  // FIXME: We should emit a warning here if the value is something other than
-  // "true", "false", or the empty string (meaning the default value),
-  // but the AnalyzerOptions doesn't have access to a diagnostic engine.
-  V = llvm::StringSwitch<bool>(getStringOption(Name, toString(DefaultVal)))
-      .Case("true", true)
-      .Case("false", false)
-      .Default(DefaultVal);
-}
-
-void AnalyzerOptions::initOption(Optional<unsigned> &V, StringRef Name,
-                                                        unsigned DefaultVal) {
-  if (V.hasValue())
-    return;
-
-  V = DefaultVal;
-  bool HasFailed = getStringOption(Name, std::to_string(DefaultVal))
-                     .getAsInteger(10, *V);
-  assert(!HasFailed && "analyzer-config option should be numeric");
-  (void)HasFailed;
-}
-
 StringRef AnalyzerOptions::getCheckerStringOption(StringRef OptionName,
 StringRef AnalyzerOptions::getCheckerStringOption(StringRef OptionName,
                                                   StringRef DefaultVal,
                                                   StringRef DefaultVal,
                                                   const CheckerBase *C,
                                                   const CheckerBase *C,
@@ -210,7 +136,8 @@ bool AnalyzerOptions::getCheckerBooleanOption(StringRef Name, bool DefaultVal,
   // but the AnalyzerOptions doesn't have access to a diagnostic engine.
   // but the AnalyzerOptions doesn't have access to a diagnostic engine.
   assert(C);
   assert(C);
   return llvm::StringSwitch<bool>(
   return llvm::StringSwitch<bool>(
-      getCheckerStringOption(Name, toString(DefaultVal), C, SearchInParents))
+      getCheckerStringOption(Name, DefaultVal ? "true" : "false", C,
+                             SearchInParents))
       .Case("true", true)
       .Case("true", true)
       .Case("false", false)
       .Case("false", false)
       .Default(DefaultVal);
       .Default(DefaultVal);
@@ -227,12 +154,3 @@ int AnalyzerOptions::getCheckerIntegerOption(StringRef Name, int DefaultVal,
   (void)HasFailed;
   (void)HasFailed;
   return Ret;
   return Ret;
 }
 }
-
-StringRef AnalyzerOptions::getCTUDir() {
-  if (!CTUDir.hasValue()) {
-    CTUDir = getStringOption("ctu-dir", "");
-    if (!llvm::sys::fs::is_directory(*CTUDir))
-      CTUDir = "";
-  }
-  return CTUDir.getValue();
-}

+ 5 - 5
lib/StaticAnalyzer/Core/BugReporter.cpp

@@ -1976,7 +1976,7 @@ static std::unique_ptr<PathDiagnostic> generatePathDiagnosticForConsumer(
 
 
   // Finally, prune the diagnostic path of uninteresting stuff.
   // Finally, prune the diagnostic path of uninteresting stuff.
   if (!PD->path.empty()) {
   if (!PD->path.empty()) {
-    if (R->shouldPrunePath() && Opts.shouldPrunePaths()) {
+    if (R->shouldPrunePath() && Opts.ShouldPrunePaths) {
       bool stillHasNotes =
       bool stillHasNotes =
           removeUnneededCalls(PD->getMutablePieces(), R, LCM);
           removeUnneededCalls(PD->getMutablePieces(), R, LCM);
       assert(stillHasNotes);
       assert(stillHasNotes);
@@ -2007,7 +2007,7 @@ static std::unique_ptr<PathDiagnostic> generatePathDiagnosticForConsumer(
     removeEdgesToDefaultInitializers(PD->getMutablePieces());
     removeEdgesToDefaultInitializers(PD->getMutablePieces());
   }
   }
 
 
-  if (GenerateDiagnostics && Opts.shouldDisplayMacroExpansions())
+  if (GenerateDiagnostics && Opts.ShouldDisplayMacroExpansions)
     CompactMacroExpandedPieces(PD->getMutablePieces(), SM);
     CompactMacroExpandedPieces(PD->getMutablePieces(), SM);
 
 
   return PD;
   return PD;
@@ -2621,7 +2621,7 @@ std::pair<BugReport*, std::unique_ptr<VisitorsDiagnosticsTy>> findValidReport(
         generateVisitorsDiagnostics(R, ErrorNode, BRC);
         generateVisitorsDiagnostics(R, ErrorNode, BRC);
 
 
     if (R->isValid()) {
     if (R->isValid()) {
-      if (Opts.shouldCrosscheckWithZ3()) {
+      if (Opts.ShouldCrosscheckWithZ3) {
         // If crosscheck is enabled, remove all visitors, add the refutation
         // If crosscheck is enabled, remove all visitors, add the refutation
         // visitor and check again
         // visitor and check again
         R->clearVisitors();
         R->clearVisitors();
@@ -2963,7 +2963,7 @@ void BugReporter::FlushReport(BugReportEquivClass& EQ) {
     }
     }
 
 
     PathPieces &Pieces = PD->getMutablePieces();
     PathPieces &Pieces = PD->getMutablePieces();
-    if (getAnalyzerOptions().shouldDisplayNotesAsEvents()) {
+    if (getAnalyzerOptions().ShouldDisplayNotesAsEvents) {
       // For path diagnostic consumers that don't support extra notes,
       // For path diagnostic consumers that don't support extra notes,
       // we may optionally convert those to path notes.
       // we may optionally convert those to path notes.
       for (auto I = report->getNotes().rbegin(),
       for (auto I = report->getNotes().rbegin(),
@@ -3100,7 +3100,7 @@ BugReporter::generateDiagnosticForConsumerMap(
   // report location to the last piece in the main source file.
   // report location to the last piece in the main source file.
   AnalyzerOptions &Opts = getAnalyzerOptions();
   AnalyzerOptions &Opts = getAnalyzerOptions();
   for (auto const &P : *Out)
   for (auto const &P : *Out)
-    if (Opts.shouldReportIssuesInMainSourceFile() && !Opts.AnalyzeAll)
+    if (Opts.ShouldReportIssuesInMainSourceFile && !Opts.AnalyzeAll)
       P.second->resetDiagnosticLocationToMainFile();
       P.second->resetDiagnosticLocationToMainFile();
 
 
   return Out;
   return Out;

+ 8 - 7
lib/StaticAnalyzer/Core/BugReporterVisitors.cpp

@@ -676,8 +676,8 @@ public:
         bool EnableNullFPSuppression, BugReport &BR,
         bool EnableNullFPSuppression, BugReport &BR,
         const SVal V) {
         const SVal V) {
     AnalyzerOptions &Options = N->getState()->getAnalysisManager().options;
     AnalyzerOptions &Options = N->getState()->getAnalysisManager().options;
-    if (EnableNullFPSuppression && Options.shouldSuppressNullReturnPaths()
-          && V.getAs<Loc>())
+    if (EnableNullFPSuppression &&
+        Options.ShouldSuppressNullReturnPaths && V.getAs<Loc>())
       BR.addVisitor(llvm::make_unique<MacroNullReturnSuppressionVisitor>(
       BR.addVisitor(llvm::make_unique<MacroNullReturnSuppressionVisitor>(
               R->getAs<SubRegion>(), V));
               R->getAs<SubRegion>(), V));
   }
   }
@@ -808,7 +808,8 @@ public:
     AnalyzerOptions &Options = State->getAnalysisManager().options;
     AnalyzerOptions &Options = State->getAnalysisManager().options;
 
 
     bool EnableNullFPSuppression = false;
     bool EnableNullFPSuppression = false;
-    if (InEnableNullFPSuppression && Options.shouldSuppressNullReturnPaths())
+    if (InEnableNullFPSuppression &&
+        Options.ShouldSuppressNullReturnPaths)
       if (Optional<Loc> RetLoc = RetVal.getAs<Loc>())
       if (Optional<Loc> RetLoc = RetVal.getAs<Loc>())
         EnableNullFPSuppression = State->isNull(*RetLoc).isConstrainedTrue();
         EnableNullFPSuppression = State->isNull(*RetLoc).isConstrainedTrue();
 
 
@@ -877,7 +878,7 @@ public:
         // future nodes. We want to emit a path note as well, in case
         // future nodes. We want to emit a path note as well, in case
         // the report is resurrected as valid later on.
         // the report is resurrected as valid later on.
         if (EnableNullFPSuppression &&
         if (EnableNullFPSuppression &&
-            Options.shouldAvoidSuppressingNullArgumentPaths())
+            Options.ShouldAvoidSuppressingNullArgumentPaths)
           Mode = MaybeUnsuppress;
           Mode = MaybeUnsuppress;
 
 
         if (RetE->getType()->isObjCObjectPointerType()) {
         if (RetE->getType()->isObjCObjectPointerType()) {
@@ -925,7 +926,7 @@ public:
   visitNodeMaybeUnsuppress(const ExplodedNode *N,
   visitNodeMaybeUnsuppress(const ExplodedNode *N,
                            BugReporterContext &BRC, BugReport &BR) {
                            BugReporterContext &BRC, BugReport &BR) {
 #ifndef NDEBUG
 #ifndef NDEBUG
-    assert(Options.shouldAvoidSuppressingNullArgumentPaths());
+    assert(Options.ShouldAvoidSuppressingNullArgumentPaths);
 #endif
 #endif
 
 
     // Are we at the entry node for this call?
     // Are we at the entry node for this call?
@@ -1378,7 +1379,7 @@ SuppressInlineDefensiveChecksVisitor(DefinedSVal Value, const ExplodedNode *N)
     : V(Value) {
     : V(Value) {
   // Check if the visitor is disabled.
   // Check if the visitor is disabled.
   AnalyzerOptions &Options = N->getState()->getAnalysisManager().options;
   AnalyzerOptions &Options = N->getState()->getAnalysisManager().options;
-  if (!Options.shouldSuppressInlinedDefensiveChecks())
+  if (!Options.ShouldSuppressInlinedDefensiveChecks)
     IsSatisfied = true;
     IsSatisfied = true;
 
 
   assert(N->getState()->isNull(V).isConstrainedTrue() &&
   assert(N->getState()->isNull(V).isConstrainedTrue() &&
@@ -2219,7 +2220,7 @@ void LikelyFalsePositiveSuppressionBRVisitor::finalizeVisitor(
     // the user's fault, we currently don't report them very well, and
     // the user's fault, we currently don't report them very well, and
     // Note that this will not help for any other data structure libraries, like
     // Note that this will not help for any other data structure libraries, like
     // TR1, Boost, or llvm/ADT.
     // TR1, Boost, or llvm/ADT.
-    if (Options.shouldSuppressFromCXXStandardLibrary()) {
+    if (Options.ShouldSuppressFromCXXStandardLibrary) {
       BR.markInvalid(getTag(), nullptr);
       BR.markInvalid(getTag(), nullptr);
       return;
       return;
     } else {
     } else {

+ 3 - 2
lib/StaticAnalyzer/Core/CallEvent.cpp

@@ -554,13 +554,14 @@ RuntimeDefinition AnyFunctionCall::getRuntimeDefinition() const {
   AnalyzerOptions &Opts = Engine->getAnalysisManager().options;
   AnalyzerOptions &Opts = Engine->getAnalysisManager().options;
 
 
   // Try to get CTU definition only if CTUDir is provided.
   // Try to get CTU definition only if CTUDir is provided.
-  if (!Opts.naiveCTUEnabled())
+  if (!Opts.IsNaiveCTUEnabled)
     return {};
     return {};
 
 
   cross_tu::CrossTranslationUnitContext &CTUCtx =
   cross_tu::CrossTranslationUnitContext &CTUCtx =
       *Engine->getCrossTranslationUnitContext();
       *Engine->getCrossTranslationUnitContext();
   llvm::Expected<const FunctionDecl *> CTUDeclOrError =
   llvm::Expected<const FunctionDecl *> CTUDeclOrError =
-      CTUCtx.getCrossTUDefinition(FD, Opts.getCTUDir(), Opts.getCTUIndexName());
+      CTUCtx.getCrossTUDefinition(FD, Opts.CTUDir,
+                                  Opts.CTUIndexName);
 
 
   if (!CTUDeclOrError) {
   if (!CTUDeclOrError) {
     handleAllErrors(CTUDeclOrError.takeError(),
     handleAllErrors(CTUDeclOrError.takeError(),

+ 10 - 10
lib/StaticAnalyzer/Core/ExprEngine.cpp

@@ -193,7 +193,7 @@ ExprEngine::ExprEngine(cross_tu::CrossTranslationUnitContext &CTU,
       svalBuilder(StateMgr.getSValBuilder()), ObjCNoRet(mgr.getASTContext()),
       svalBuilder(StateMgr.getSValBuilder()), ObjCNoRet(mgr.getASTContext()),
       BR(mgr, *this),
       BR(mgr, *this),
       VisitedCallees(VisitedCalleesIn), HowToInline(HowToInlineIn) {
       VisitedCallees(VisitedCalleesIn), HowToInline(HowToInlineIn) {
-  unsigned TrimInterval = mgr.options.getGraphTrimInterval();
+  unsigned TrimInterval = mgr.options.GraphTrimInterval;
   if (TrimInterval != 0) {
   if (TrimInterval != 0) {
     // Enable eager node reclaimation when constructing the ExplodedGraph.
     // Enable eager node reclaimation when constructing the ExplodedGraph.
     G.enableNodeReclamation(TrimInterval);
     G.enableNodeReclamation(TrimInterval);
@@ -746,7 +746,7 @@ void ExprEngine::ProcessLoopExit(const Stmt* S, ExplodedNode *Pred) {
   NodeBuilder Bldr(Pred, Dst, *currBldrCtx);
   NodeBuilder Bldr(Pred, Dst, *currBldrCtx);
   ProgramStateRef NewState = Pred->getState();
   ProgramStateRef NewState = Pred->getState();
 
 
-  if(AMgr.options.shouldUnrollLoops())
+  if(AMgr.options.ShouldUnrollLoops)
     NewState = processLoopEnd(S, NewState);
     NewState = processLoopEnd(S, NewState);
 
 
   LoopExit PP(S, Pred->getLocationContext());
   LoopExit PP(S, Pred->getLocationContext());
@@ -878,7 +878,7 @@ void ExprEngine::ProcessNewAllocator(const CXXNewExpr *NE,
   // TODO: We're not evaluating allocators for all cases just yet as
   // TODO: We're not evaluating allocators for all cases just yet as
   // we're not handling the return value correctly, which causes false
   // we're not handling the return value correctly, which causes false
   // positives when the alpha.cplusplus.NewDeleteLeaks check is on.
   // positives when the alpha.cplusplus.NewDeleteLeaks check is on.
-  if (Opts.mayInlineCXXAllocator())
+  if (Opts.MayInlineCXXAllocator)
     VisitCXXNewAllocatorCall(NE, Pred, Dst);
     VisitCXXNewAllocatorCall(NE, Pred, Dst);
   else {
   else {
     NodeBuilder Bldr(Pred, Dst, *currBldrCtx);
     NodeBuilder Bldr(Pred, Dst, *currBldrCtx);
@@ -1093,7 +1093,7 @@ void ExprEngine::VisitCXXBindTemporaryExpr(const CXXBindTemporaryExpr *BTE,
   // This is a fallback solution in case we didn't have a construction
   // This is a fallback solution in case we didn't have a construction
   // context when we were constructing the temporary. Otherwise the map should
   // context when we were constructing the temporary. Otherwise the map should
   // have been populated there.
   // have been populated there.
-  if (!getAnalysisManager().options.includeTemporaryDtorsInCFG()) {
+  if (!getAnalysisManager().options.ShouldIncludeTemporaryDtorsInCFG) {
     // In case we don't have temporary destructors in the CFG, do not mark
     // In case we don't have temporary destructors in the CFG, do not mark
     // the initialization - we would otherwise never clean it up.
     // the initialization - we would otherwise never clean it up.
     Dst = PreVisit;
     Dst = PreVisit;
@@ -1454,7 +1454,7 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
       break;
       break;
 
 
     case Stmt::LambdaExprClass:
     case Stmt::LambdaExprClass:
-      if (AMgr.options.shouldInlineLambdas()) {
+      if (AMgr.options.ShouldInlineLambdas) {
         Bldr.takeNodes(Pred);
         Bldr.takeNodes(Pred);
         VisitLambdaExpr(cast<LambdaExpr>(S), Pred, Dst);
         VisitLambdaExpr(cast<LambdaExpr>(S), Pred, Dst);
         Bldr.addNodes(Dst);
         Bldr.addNodes(Dst);
@@ -1483,7 +1483,7 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
 
 
       Bldr.takeNodes(Pred);
       Bldr.takeNodes(Pred);
 
 
-      if (AMgr.options.shouldEagerlyAssume() &&
+      if (AMgr.options.ShouldEagerlyAssume &&
           (B->isRelationalOp() || B->isEqualityOp())) {
           (B->isRelationalOp() || B->isEqualityOp())) {
         ExplodedNodeSet Tmp;
         ExplodedNodeSet Tmp;
         VisitBinaryOperator(cast<BinaryOperator>(S), Pred, Tmp);
         VisitBinaryOperator(cast<BinaryOperator>(S), Pred, Tmp);
@@ -1747,7 +1747,7 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
     case Stmt::UnaryOperatorClass: {
     case Stmt::UnaryOperatorClass: {
       Bldr.takeNodes(Pred);
       Bldr.takeNodes(Pred);
       const auto *U = cast<UnaryOperator>(S);
       const auto *U = cast<UnaryOperator>(S);
-      if (AMgr.options.shouldEagerlyAssume() && (U->getOpcode() == UO_LNot)) {
+      if (AMgr.options.ShouldEagerlyAssume && (U->getOpcode() == UO_LNot)) {
         ExplodedNodeSet Tmp;
         ExplodedNodeSet Tmp;
         VisitUnaryOperator(U, Pred, Tmp);
         VisitUnaryOperator(U, Pred, Tmp);
         evalEagerlyAssumeBinOpBifurcation(Dst, Tmp, U);
         evalEagerlyAssumeBinOpBifurcation(Dst, Tmp, U);
@@ -1848,7 +1848,7 @@ void ExprEngine::processCFGBlockEntrance(const BlockEdge &L,
   PrettyStackTraceLocationContext CrashInfo(Pred->getLocationContext());
   PrettyStackTraceLocationContext CrashInfo(Pred->getLocationContext());
   // If we reach a loop which has a known bound (and meets
   // If we reach a loop which has a known bound (and meets
   // other constraints) then consider completely unrolling it.
   // other constraints) then consider completely unrolling it.
-  if(AMgr.options.shouldUnrollLoops()) {
+  if(AMgr.options.ShouldUnrollLoops) {
     unsigned maxBlockVisitOnPath = AMgr.options.maxBlockVisitOnPath;
     unsigned maxBlockVisitOnPath = AMgr.options.maxBlockVisitOnPath;
     const Stmt *Term = nodeBuilder.getContext().getBlock()->getTerminator();
     const Stmt *Term = nodeBuilder.getContext().getBlock()->getTerminator();
     if (Term) {
     if (Term) {
@@ -1870,7 +1870,7 @@ void ExprEngine::processCFGBlockEntrance(const BlockEdge &L,
   // maximum number of times, widen the loop.
   // maximum number of times, widen the loop.
   unsigned int BlockCount = nodeBuilder.getContext().blockCount();
   unsigned int BlockCount = nodeBuilder.getContext().blockCount();
   if (BlockCount == AMgr.options.maxBlockVisitOnPath - 1 &&
   if (BlockCount == AMgr.options.maxBlockVisitOnPath - 1 &&
-      AMgr.options.shouldWidenLoops()) {
+      AMgr.options.ShouldWidenLoops) {
     const Stmt *Term = nodeBuilder.getContext().getBlock()->getTerminator();
     const Stmt *Term = nodeBuilder.getContext().getBlock()->getTerminator();
     if (!(Term &&
     if (!(Term &&
           (isa<ForStmt>(Term) || isa<WhileStmt>(Term) || isa<DoStmt>(Term))))
           (isa<ForStmt>(Term) || isa<WhileStmt>(Term) || isa<DoStmt>(Term))))
@@ -2371,7 +2371,7 @@ void ExprEngine::VisitCommonDeclRefExpr(const Expr *Ex, const NamedDecl *D,
     const auto *DeclRefEx = dyn_cast<DeclRefExpr>(Ex);
     const auto *DeclRefEx = dyn_cast<DeclRefExpr>(Ex);
     Optional<std::pair<SVal, QualType>> VInfo;
     Optional<std::pair<SVal, QualType>> VInfo;
 
 
-    if (AMgr.options.shouldInlineLambdas() && DeclRefEx &&
+    if (AMgr.options.ShouldInlineLambdas && DeclRefEx &&
         DeclRefEx->refersToEnclosingVariableOrCapture() && MD &&
         DeclRefEx->refersToEnclosingVariableOrCapture() && MD &&
         MD->getParent()->isLambda()) {
         MD->getParent()->isLambda()) {
       // Lookup the field of the lambda.
       // Lookup the field of the lambda.

+ 4 - 4
lib/StaticAnalyzer/Core/ExprEngineCXX.cpp

@@ -159,7 +159,7 @@ std::pair<ProgramStateRef, SVal> ExprEngine::prepareForObjectConstruction(
       return std::make_pair(State, FieldVal);
       return std::make_pair(State, FieldVal);
     }
     }
     case ConstructionContext::NewAllocatedObjectKind: {
     case ConstructionContext::NewAllocatedObjectKind: {
-      if (AMgr.getAnalyzerOptions().mayInlineCXXAllocator()) {
+      if (AMgr.getAnalyzerOptions().MayInlineCXXAllocator) {
         const auto *NECC = cast<NewAllocatedObjectConstructionContext>(CC);
         const auto *NECC = cast<NewAllocatedObjectConstructionContext>(CC);
         const auto *NE = NECC->getCXXNewExpr();
         const auto *NE = NECC->getCXXNewExpr();
         SVal V = *getObjectUnderConstruction(State, NE, LCtx);
         SVal V = *getObjectUnderConstruction(State, NE, LCtx);
@@ -210,7 +210,7 @@ std::pair<ProgramStateRef, SVal> ExprEngine::prepareForObjectConstruction(
       llvm_unreachable("Unhandled return value construction context!");
       llvm_unreachable("Unhandled return value construction context!");
     }
     }
     case ConstructionContext::ElidedTemporaryObjectKind: {
     case ConstructionContext::ElidedTemporaryObjectKind: {
-      assert(AMgr.getAnalyzerOptions().shouldElideConstructors());
+      assert(AMgr.getAnalyzerOptions().ShouldElideConstructors);
       const auto *TCC = cast<ElidedTemporaryObjectConstructionContext>(CC);
       const auto *TCC = cast<ElidedTemporaryObjectConstructionContext>(CC);
       const CXXBindTemporaryExpr *BTE = TCC->getCXXBindTemporaryExpr();
       const CXXBindTemporaryExpr *BTE = TCC->getCXXBindTemporaryExpr();
       const MaterializeTemporaryExpr *MTE = TCC->getMaterializedTemporaryExpr();
       const MaterializeTemporaryExpr *MTE = TCC->getMaterializedTemporaryExpr();
@@ -706,7 +706,7 @@ void ExprEngine::VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred,
   ProgramStateRef State = Pred->getState();
   ProgramStateRef State = Pred->getState();
 
 
   // Retrieve the stored operator new() return value.
   // Retrieve the stored operator new() return value.
-  if (AMgr.getAnalyzerOptions().mayInlineCXXAllocator()) {
+  if (AMgr.getAnalyzerOptions().MayInlineCXXAllocator) {
     symVal = *getObjectUnderConstruction(State, CNE, LCtx);
     symVal = *getObjectUnderConstruction(State, CNE, LCtx);
     State = finishObjectConstruction(State, CNE, LCtx);
     State = finishObjectConstruction(State, CNE, LCtx);
   }
   }
@@ -726,7 +726,7 @@ void ExprEngine::VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred,
   CallEventRef<CXXAllocatorCall> Call =
   CallEventRef<CXXAllocatorCall> Call =
     CEMgr.getCXXAllocatorCall(CNE, State, LCtx);
     CEMgr.getCXXAllocatorCall(CNE, State, LCtx);
 
 
-  if (!AMgr.getAnalyzerOptions().mayInlineCXXAllocator()) {
+  if (!AMgr.getAnalyzerOptions().MayInlineCXXAllocator) {
     // Invalidate placement args.
     // Invalidate placement args.
     // FIXME: Once we figure out how we want allocators to work,
     // FIXME: Once we figure out how we want allocators to work,
     // we should be using the usual pre-/(default-)eval-/post-call checks here.
     // we should be using the usual pre-/(default-)eval-/post-call checks here.

+ 17 - 16
lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp

@@ -349,7 +349,7 @@ void ExprEngine::processCallExit(ExplodedNode *CEBNode) {
                                                         /*WasInlined=*/true);
                                                         /*WasInlined=*/true);
     } else if (CE &&
     } else if (CE &&
                !(isa<CXXNewExpr>(CE) && // Called when visiting CXXNewExpr.
                !(isa<CXXNewExpr>(CE) && // Called when visiting CXXNewExpr.
-                 AMgr.getAnalyzerOptions().mayInlineCXXAllocator())) {
+                 AMgr.getAnalyzerOptions().MayInlineCXXAllocator)) {
       getCheckerManager().runCheckersForPostStmt(Dst, DstPostCall, CE,
       getCheckerManager().runCheckersForPostStmt(Dst, DstPostCall, CE,
                                                  *this, /*WasInlined=*/true);
                                                  *this, /*WasInlined=*/true);
     } else {
     } else {
@@ -386,7 +386,7 @@ void ExprEngine::examineStackFrames(const Decl *D, const LocationContext *LCtx,
       // Do not count the small functions when determining the stack depth.
       // Do not count the small functions when determining the stack depth.
       AnalysisDeclContext *CalleeADC = AMgr.getAnalysisDeclContext(DI);
       AnalysisDeclContext *CalleeADC = AMgr.getAnalysisDeclContext(DI);
       const CFG *CalleeCFG = CalleeADC->getCFG();
       const CFG *CalleeCFG = CalleeADC->getCFG();
-      if (CalleeCFG->getNumBlockIDs() > AMgr.options.getAlwaysInlineSize())
+      if (CalleeCFG->getNumBlockIDs() > AMgr.options.AlwaysInlineSize)
         ++StackDepth;
         ++StackDepth;
     }
     }
     LCtx = LCtx->getParent();
     LCtx = LCtx->getParent();
@@ -683,7 +683,7 @@ ExprEngine::mayInlineCallKind(const CallEvent &Call, const ExplodedNode *Pred,
                                         : nullptr;
                                         : nullptr;
 
 
     if (CC && isa<NewAllocatedObjectConstructionContext>(CC) &&
     if (CC && isa<NewAllocatedObjectConstructionContext>(CC) &&
-        !Opts.mayInlineCXXAllocator())
+        !Opts.MayInlineCXXAllocator)
       return CIP_DisallowedOnce;
       return CIP_DisallowedOnce;
 
 
     // FIXME: We don't handle constructors or destructors for arrays properly.
     // FIXME: We don't handle constructors or destructors for arrays properly.
@@ -712,7 +712,7 @@ ExprEngine::mayInlineCallKind(const CallEvent &Call, const ExplodedNode *Pred,
       // If we don't handle temporary destructors, we shouldn't inline
       // If we don't handle temporary destructors, we shouldn't inline
       // their constructors.
       // their constructors.
       if (CallOpts.IsTemporaryCtorOrDtor &&
       if (CallOpts.IsTemporaryCtorOrDtor &&
-          !Opts.includeTemporaryDtorsInCFG())
+          !Opts.ShouldIncludeTemporaryDtorsInCFG)
         return CIP_DisallowedOnce;
         return CIP_DisallowedOnce;
 
 
       // If we did not find the correct this-region, it would be pointless
       // If we did not find the correct this-region, it would be pointless
@@ -743,7 +743,8 @@ ExprEngine::mayInlineCallKind(const CallEvent &Call, const ExplodedNode *Pred,
       return CIP_DisallowedOnce;
       return CIP_DisallowedOnce;
 
 
     // Allow disabling temporary destructor inlining with a separate option.
     // Allow disabling temporary destructor inlining with a separate option.
-    if (CallOpts.IsTemporaryCtorOrDtor && !Opts.mayInlineCXXTemporaryDtors())
+    if (CallOpts.IsTemporaryCtorOrDtor &&
+        !Opts.MayInlineCXXTemporaryDtors)
       return CIP_DisallowedOnce;
       return CIP_DisallowedOnce;
 
 
     // If we did not find the correct this-region, it would be pointless
     // If we did not find the correct this-region, it would be pointless
@@ -754,13 +755,13 @@ ExprEngine::mayInlineCallKind(const CallEvent &Call, const ExplodedNode *Pred,
     break;
     break;
   }
   }
   case CE_CXXAllocator:
   case CE_CXXAllocator:
-    if (Opts.mayInlineCXXAllocator())
+    if (Opts.MayInlineCXXAllocator)
       break;
       break;
     // Do not inline allocators until we model deallocators.
     // Do not inline allocators until we model deallocators.
     // This is unfortunate, but basically necessary for smart pointers and such.
     // This is unfortunate, but basically necessary for smart pointers and such.
     return CIP_DisallowedAlways;
     return CIP_DisallowedAlways;
   case CE_ObjCMessage:
   case CE_ObjCMessage:
-    if (!Opts.mayInlineObjCMethod())
+    if (!Opts.MayInlineObjCMethod)
       return CIP_DisallowedAlways;
       return CIP_DisallowedAlways;
     if (!(Opts.getIPAMode() == IPAK_DynamicDispatch ||
     if (!(Opts.getIPAMode() == IPAK_DynamicDispatch ||
           Opts.getIPAMode() == IPAK_DynamicDispatchBifurcate))
           Opts.getIPAMode() == IPAK_DynamicDispatchBifurcate))
@@ -844,19 +845,19 @@ static bool mayInlineDecl(AnalysisManager &AMgr,
   if (Ctx.getLangOpts().CPlusPlus) {
   if (Ctx.getLangOpts().CPlusPlus) {
     if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(CalleeADC->getDecl())) {
     if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(CalleeADC->getDecl())) {
       // Conditionally control the inlining of template functions.
       // Conditionally control the inlining of template functions.
-      if (!Opts.mayInlineTemplateFunctions())
+      if (!Opts.MayInlineTemplateFunctions)
         if (FD->getTemplatedKind() != FunctionDecl::TK_NonTemplate)
         if (FD->getTemplatedKind() != FunctionDecl::TK_NonTemplate)
           return false;
           return false;
 
 
       // Conditionally control the inlining of C++ standard library functions.
       // Conditionally control the inlining of C++ standard library functions.
-      if (!Opts.mayInlineCXXStandardLibrary())
+      if (!Opts.MayInlineCXXStandardLibrary)
         if (Ctx.getSourceManager().isInSystemHeader(FD->getLocation()))
         if (Ctx.getSourceManager().isInSystemHeader(FD->getLocation()))
           if (AnalysisDeclContext::isInStdNamespace(FD))
           if (AnalysisDeclContext::isInStdNamespace(FD))
             return false;
             return false;
 
 
       // Conditionally control the inlining of methods on objects that look
       // Conditionally control the inlining of methods on objects that look
       // like C++ containers.
       // like C++ containers.
-      if (!Opts.mayInlineCXXContainerMethods())
+      if (!Opts.MayInlineCXXContainerMethods)
         if (!AMgr.isInCodeFile(FD->getLocation()))
         if (!AMgr.isInCodeFile(FD->getLocation()))
           if (isContainerMethod(Ctx, FD))
           if (isContainerMethod(Ctx, FD))
             return false;
             return false;
@@ -865,7 +866,7 @@ static bool mayInlineDecl(AnalysisManager &AMgr,
       // We don't currently do a good job modeling shared_ptr because we can't
       // We don't currently do a good job modeling shared_ptr because we can't
       // see the reference count, so treating as opaque is probably the best
       // see the reference count, so treating as opaque is probably the best
       // idea.
       // idea.
-      if (!Opts.mayInlineCXXSharedPtrDtor())
+      if (!Opts.MayInlineCXXSharedPtrDtor)
         if (isCXXSharedPtrDtor(FD))
         if (isCXXSharedPtrDtor(FD))
           return false;
           return false;
     }
     }
@@ -878,7 +879,7 @@ static bool mayInlineDecl(AnalysisManager &AMgr,
     return false;
     return false;
 
 
   // Do not inline large functions.
   // Do not inline large functions.
-  if (CalleeCFG->getNumBlockIDs() > Opts.getMaxInlinableSize())
+  if (CalleeCFG->getNumBlockIDs() > Opts.MaxInlinableSize)
     return false;
     return false;
 
 
   // It is possible that the live variables analysis cannot be
   // It is possible that the live variables analysis cannot be
@@ -946,21 +947,21 @@ bool ExprEngine::shouldInlineCall(const CallEvent &Call, const Decl *D,
   unsigned StackDepth = 0;
   unsigned StackDepth = 0;
   examineStackFrames(D, Pred->getLocationContext(), IsRecursive, StackDepth);
   examineStackFrames(D, Pred->getLocationContext(), IsRecursive, StackDepth);
   if ((StackDepth >= Opts.InlineMaxStackDepth) &&
   if ((StackDepth >= Opts.InlineMaxStackDepth) &&
-      ((CalleeCFG->getNumBlockIDs() > Opts.getAlwaysInlineSize())
+      ((CalleeCFG->getNumBlockIDs() > Opts.AlwaysInlineSize)
        || IsRecursive))
        || IsRecursive))
     return false;
     return false;
 
 
   // Do not inline large functions too many times.
   // Do not inline large functions too many times.
   if ((Engine.FunctionSummaries->getNumTimesInlined(D) >
   if ((Engine.FunctionSummaries->getNumTimesInlined(D) >
-       Opts.getMaxTimesInlineLarge()) &&
+       Opts.MaxTimesInlineLarge) &&
        CalleeCFG->getNumBlockIDs() >=
        CalleeCFG->getNumBlockIDs() >=
-       Opts.getMinCFGSizeTreatFunctionsAsLarge()) {
+       Opts.MinCFGSizeTreatFunctionsAsLarge) {
     NumReachedInlineCountMax++;
     NumReachedInlineCountMax++;
     return false;
     return false;
   }
   }
 
 
   if (HowToInline == Inline_Minimal &&
   if (HowToInline == Inline_Minimal &&
-      (CalleeCFG->getNumBlockIDs() > Opts.getAlwaysInlineSize()
+      (CalleeCFG->getNumBlockIDs() > Opts.AlwaysInlineSize
       || IsRecursive))
       || IsRecursive))
     return false;
     return false;
 
 

+ 1 - 1
lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp

@@ -218,7 +218,7 @@ void HTMLDiagnostics::ReportDiag(const PathDiagnostic& D,
   int FD;
   int FD;
   SmallString<128> Model, ResultPath;
   SmallString<128> Model, ResultPath;
 
 
-  if (!AnalyzerOpts.shouldWriteStableReportFilename()) {
+  if (!AnalyzerOpts.ShouldWriteStableReportFilename) {
       llvm::sys::path::append(Model, Directory, "report-%%%%%%.html");
       llvm::sys::path::append(Model, Directory, "report-%%%%%%.html");
       if (std::error_code EC =
       if (std::error_code EC =
           llvm::sys::fs::make_absolute(Model)) {
           llvm::sys::fs::make_absolute(Model)) {

+ 2 - 2
lib/StaticAnalyzer/Core/PlistDiagnostics.cpp

@@ -471,7 +471,7 @@ static void printBugPath(llvm::raw_ostream &o, const FIDMap& FM,
 
 
   o << "   </array>\n";
   o << "   </array>\n";
 
 
-  if (!AnOpts.shouldDisplayMacroExpansions())
+  if (!AnOpts.ShouldDisplayMacroExpansions)
     return;
     return;
 
 
   o << "   <key>macro_expansions</key>\n"
   o << "   <key>macro_expansions</key>\n"
@@ -704,7 +704,7 @@ void PlistDiagnostics::FlushDiagnosticsImpl(
     EmitString(o << "  ", SM.getFileEntryForID(FID)->getName()) << '\n';
     EmitString(o << "  ", SM.getFileEntryForID(FID)->getName()) << '\n';
   o << " </array>\n";
   o << " </array>\n";
 
 
-  if (llvm::AreStatisticsEnabled() && AnOpts.shouldSerializeStats()) {
+  if (llvm::AreStatisticsEnabled() && AnOpts.ShouldSerializeStats) {
     o << " <key>statistics</key>\n";
     o << " <key>statistics</key>\n";
     std::string stats;
     std::string stats;
     llvm::raw_string_ostream os(stats);
     llvm::raw_string_ostream os(stats);

+ 1 - 1
lib/StaticAnalyzer/Core/RegionStore.cpp

@@ -350,7 +350,7 @@ public:
     if (SubEngine *Eng = StateMgr.getOwningEngine()) {
     if (SubEngine *Eng = StateMgr.getOwningEngine()) {
       AnalyzerOptions &Options = Eng->getAnalysisManager().options;
       AnalyzerOptions &Options = Eng->getAnalysisManager().options;
       SmallStructLimit =
       SmallStructLimit =
-        Options.getRegionStoreSmallStructLimit();
+        Options.RegionStoreSmallStructLimit;
     }
     }
   }
   }
 
 

+ 1 - 1
lib/StaticAnalyzer/Core/SValBuilder.cpp

@@ -385,7 +385,7 @@ SVal SValBuilder::makeSymExprValNN(BinaryOperator::Opcode Op,
   // instead of generating an Unknown value and propagate the taint info to it.
   // instead of generating an Unknown value and propagate the taint info to it.
   const unsigned MaxComp = StateMgr.getOwningEngine()
   const unsigned MaxComp = StateMgr.getOwningEngine()
                                ->getAnalysisManager()
                                ->getAnalysisManager()
-                               .options.getMaxSymbolComplexity();
+                               .options.MaxSymbolComplexity;
 
 
   if (symLHS && symRHS &&
   if (symLHS && symRHS &&
       (symLHS->computeComplexity() + symRHS->computeComplexity()) <  MaxComp)
       (symLHS->computeComplexity() + symRHS->computeComplexity()) <  MaxComp)

+ 1 - 1
lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp

@@ -459,7 +459,7 @@ static Optional<NonLoc> tryRearrange(ProgramStateRef State,
   // FIXME: After putting complexity threshold to the symbols we can always
   // FIXME: After putting complexity threshold to the symbols we can always
   //        rearrange additive operations but rearrange comparisons only if
   //        rearrange additive operations but rearrange comparisons only if
   //        option is set.
   //        option is set.
-  if(!Opts.shouldAggressivelySimplifyBinaryOperation())
+  if(!Opts.ShouldAggressivelySimplifyBinaryOperation)
     return None;
     return None;
 
 
   SymbolRef LSym = Lhs.getAsSymbol();
   SymbolRef LSym = Lhs.getAsSymbol();

+ 2 - 2
lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp

@@ -204,7 +204,7 @@ public:
         PP(CI.getPreprocessor()), OutDir(outdir), Opts(std::move(opts)),
         PP(CI.getPreprocessor()), OutDir(outdir), Opts(std::move(opts)),
         Plugins(plugins), Injector(injector), CTU(CI) {
         Plugins(plugins), Injector(injector), CTU(CI) {
     DigestAnalyzerOptions();
     DigestAnalyzerOptions();
-    if (Opts->PrintStats || Opts->shouldSerializeStats()) {
+    if (Opts->PrintStats || Opts->ShouldSerializeStats) {
       AnalyzerTimers = llvm::make_unique<llvm::TimerGroup>(
       AnalyzerTimers = llvm::make_unique<llvm::TimerGroup>(
           "analyzer", "Analyzer timers");
           "analyzer", "Analyzer timers");
       TUTotalTimer = llvm::make_unique<llvm::Timer>(
       TUTotalTimer = llvm::make_unique<llvm::Timer>(
@@ -739,7 +739,7 @@ void AnalysisConsumer::RunPathSensitiveChecks(Decl *D,
 
 
   // Execute the worklist algorithm.
   // Execute the worklist algorithm.
   Eng.ExecuteWorkList(Mgr->getAnalysisDeclContextManager().getStackFrame(D),
   Eng.ExecuteWorkList(Mgr->getAnalysisDeclContextManager().getStackFrame(D),
-                      Mgr->options.getMaxNodesPerTopLevelFunction());
+                      Mgr->options.MaxNodesPerTopLevelFunction);
 
 
   if (!Mgr->options.DumpExplodedGraphTo.empty())
   if (!Mgr->options.DumpExplodedGraphTo.empty())
     Eng.DumpGraph(Mgr->options.TrimGraph, Mgr->options.DumpExplodedGraphTo);
     Eng.DumpGraph(Mgr->options.TrimGraph, Mgr->options.DumpExplodedGraphTo);

+ 1 - 1
lib/StaticAnalyzer/Frontend/ModelInjector.cpp

@@ -48,7 +48,7 @@ void ModelInjector::onBodySynthesis(const NamedDecl *D) {
   FileID mainFileID = SM.getMainFileID();
   FileID mainFileID = SM.getMainFileID();
 
 
   AnalyzerOptionsRef analyzerOpts = CI.getAnalyzerOpts();
   AnalyzerOptionsRef analyzerOpts = CI.getAnalyzerOpts();
-  llvm::StringRef modelPath = analyzerOpts->getModelPath();
+  llvm::StringRef modelPath = analyzerOpts->ModelPath;
 
 
   llvm::SmallString<128> fileName;
   llvm::SmallString<128> fileName;
 
 

+ 25 - 10
test/Analysis/analyzer-config.c

@@ -1,16 +1,16 @@
 // RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin10 %s -o /dev/null -analyzer-checker=core,osx.cocoa,debug.ConfigDumper -analyzer-max-loop 34 > %t 2>&1
 // RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin10 %s -o /dev/null -analyzer-checker=core,osx.cocoa,debug.ConfigDumper -analyzer-max-loop 34 > %t 2>&1
 // RUN: FileCheck --input-file=%t %s --match-full-lines
 // RUN: FileCheck --input-file=%t %s --match-full-lines
 
 
-void bar() {}
-void foo() {
-  // Call bar 33 times so max-times-inline-large is met and
-  // min-blocks-for-inline-large is checked
-  for (int i = 0; i < 34; ++i) {
-    bar();
-  }
-}
-
 // CHECK: [config]
 // CHECK: [config]
+// CHECK-NEXT: aggressive-binary-operation-simplification = false
+// CHECK-NEXT: avoid-suppressing-null-argument-paths = false
+// CHECK-NEXT: c++-allocator-inlining = true
+// CHECK-NEXT: c++-container-inlining = false
+// CHECK-NEXT: c++-inlining = destructors
+// CHECK-NEXT: c++-shared_ptr-inlining = false
+// CHECK-NEXT: c++-stdlib-inlining = true
+// CHECK-NEXT: c++-temp-dtor-inlining = true
+// CHECK-NEXT: c++-template-inlining = true
 // CHECK-NEXT: cfg-conditional-static-initializers = true
 // CHECK-NEXT: cfg-conditional-static-initializers = true
 // CHECK-NEXT: cfg-implicit-dtors = true
 // CHECK-NEXT: cfg-implicit-dtors = true
 // CHECK-NEXT: cfg-lifetime = false
 // CHECK-NEXT: cfg-lifetime = false
@@ -18,8 +18,13 @@ void foo() {
 // CHECK-NEXT: cfg-rich-constructors = true
 // CHECK-NEXT: cfg-rich-constructors = true
 // CHECK-NEXT: cfg-scopes = false
 // CHECK-NEXT: cfg-scopes = false
 // CHECK-NEXT: cfg-temporary-dtors = true
 // CHECK-NEXT: cfg-temporary-dtors = true
+// CHECK-NEXT: crosscheck-with-z3 = false
+// CHECK-NEXT: ctu-dir = ""
+// CHECK-NEXT: ctu-index-name = externalFnMap.txt
 // CHECK-NEXT: eagerly-assume = true
 // CHECK-NEXT: eagerly-assume = true
 // CHECK-NEXT: elide-constructors = true
 // CHECK-NEXT: elide-constructors = true
+// CHECK-NEXT: expand-macros = false
+// CHECK-NEXT: experimental-enable-naive-ctu-analysis = false
 // CHECK-NEXT: exploration_strategy = unexplored_first_queue
 // CHECK-NEXT: exploration_strategy = unexplored_first_queue
 // CHECK-NEXT: faux-bodies = true
 // CHECK-NEXT: faux-bodies = true
 // CHECK-NEXT: graph-trim-interval = 1000
 // CHECK-NEXT: graph-trim-interval = 1000
@@ -28,12 +33,22 @@ void foo() {
 // CHECK-NEXT: ipa-always-inline-size = 3
 // CHECK-NEXT: ipa-always-inline-size = 3
 // CHECK-NEXT: max-inlinable-size = 100
 // CHECK-NEXT: max-inlinable-size = 100
 // CHECK-NEXT: max-nodes = 225000
 // CHECK-NEXT: max-nodes = 225000
+// CHECK-NEXT: max-symbol-complexity = 35
 // CHECK-NEXT: max-times-inline-large = 32
 // CHECK-NEXT: max-times-inline-large = 32
 // CHECK-NEXT: min-cfg-size-treat-functions-as-large = 14
 // CHECK-NEXT: min-cfg-size-treat-functions-as-large = 14
 // CHECK-NEXT: mode = deep
 // CHECK-NEXT: mode = deep
+// CHECK-NEXT: model-path = ""
+// CHECK-NEXT: notes-as-events = false
+// CHECK-NEXT: objc-inlining = true
+// CHECK-NEXT: prune-paths = true
 // CHECK-NEXT: region-store-small-struct-limit = 2
 // CHECK-NEXT: region-store-small-struct-limit = 2
+// CHECK-NEXT: report-in-main-source-file = false
 // CHECK-NEXT: serialize-stats = false
 // CHECK-NEXT: serialize-stats = false
+// CHECK-NEXT: stable-report-filename = false
+// CHECK-NEXT: suppress-c++-stdlib = true
+// CHECK-NEXT: suppress-inlined-defensive-checks = true
+// CHECK-NEXT: suppress-null-return-paths = true
 // CHECK-NEXT: unroll-loops = false
 // CHECK-NEXT: unroll-loops = false
 // CHECK-NEXT: widen-loops = false
 // CHECK-NEXT: widen-loops = false
 // CHECK-NEXT: [stats]
 // CHECK-NEXT: [stats]
-// CHECK-NEXT: num-entries = 24
+// CHECK-NEXT: num-entries = 48

+ 18 - 18
test/Analysis/analyzer-config.cpp

@@ -1,24 +1,10 @@
 // RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin10 %s -o /dev/null -analyzer-checker=core,osx.cocoa,debug.ConfigDumper -analyzer-max-loop 34 > %t 2>&1
 // RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin10 %s -o /dev/null -analyzer-checker=core,osx.cocoa,debug.ConfigDumper -analyzer-max-loop 34 > %t 2>&1
 // RUN: FileCheck --input-file=%t %s --match-full-lines
 // RUN: FileCheck --input-file=%t %s --match-full-lines
 
 
-void bar() {}
-void foo() {
-  // Call bar 33 times so max-times-inline-large is met and
-  // min-blocks-for-inline-large is checked
-  for (int i = 0; i < 34; ++i) {
-    bar();
-  }
-}
-
-class Foo {
-public:
-  ~Foo() {}
-  void baz() { Foo(); }
-	void bar() { const Foo &f = Foo(); }
-	void foo() { bar(); }
-};
-
 // CHECK: [config]
 // CHECK: [config]
+// CHECK-NEXT: aggressive-binary-operation-simplification = false
+// CHECK-NEXT: avoid-suppressing-null-argument-paths = false
+// CHECK-NEXT: c++-allocator-inlining = true
 // CHECK-NEXT: c++-container-inlining = false
 // CHECK-NEXT: c++-container-inlining = false
 // CHECK-NEXT: c++-inlining = destructors
 // CHECK-NEXT: c++-inlining = destructors
 // CHECK-NEXT: c++-shared_ptr-inlining = false
 // CHECK-NEXT: c++-shared_ptr-inlining = false
@@ -32,8 +18,12 @@ public:
 // CHECK-NEXT: cfg-rich-constructors = true
 // CHECK-NEXT: cfg-rich-constructors = true
 // CHECK-NEXT: cfg-scopes = false
 // CHECK-NEXT: cfg-scopes = false
 // CHECK-NEXT: cfg-temporary-dtors = true
 // CHECK-NEXT: cfg-temporary-dtors = true
+// CHECK-NEXT: crosscheck-with-z3 = false
+// CHECK-NEXT: ctu-dir = ""
+// CHECK-NEXT: ctu-index-name = externalFnMap.txt
 // CHECK-NEXT: eagerly-assume = true
 // CHECK-NEXT: eagerly-assume = true
 // CHECK-NEXT: elide-constructors = true
 // CHECK-NEXT: elide-constructors = true
+// CHECK-NEXT:expand-macros = false
 // CHECK-NEXT: experimental-enable-naive-ctu-analysis = false
 // CHECK-NEXT: experimental-enable-naive-ctu-analysis = false
 // CHECK-NEXT: exploration_strategy = unexplored_first_queue
 // CHECK-NEXT: exploration_strategy = unexplored_first_queue
 // CHECK-NEXT: faux-bodies = true
 // CHECK-NEXT: faux-bodies = true
@@ -43,12 +33,22 @@ public:
 // CHECK-NEXT: ipa-always-inline-size = 3
 // CHECK-NEXT: ipa-always-inline-size = 3
 // CHECK-NEXT: max-inlinable-size = 100
 // CHECK-NEXT: max-inlinable-size = 100
 // CHECK-NEXT: max-nodes = 225000
 // CHECK-NEXT: max-nodes = 225000
+// CHECK-NEXT: max-symbol-complexity = 35
 // CHECK-NEXT: max-times-inline-large = 32
 // CHECK-NEXT: max-times-inline-large = 32
 // CHECK-NEXT: min-cfg-size-treat-functions-as-large = 14
 // CHECK-NEXT: min-cfg-size-treat-functions-as-large = 14
 // CHECK-NEXT: mode = deep
 // CHECK-NEXT: mode = deep
+// CHECK-NEXT: model-path = ""
+// CHECK-NEXT: notes-as-events = false
+// CHECK-NEXT: objc-inlining = true
+// CHECK-NEXT: prune-paths = true
 // CHECK-NEXT: region-store-small-struct-limit = 2
 // CHECK-NEXT: region-store-small-struct-limit = 2
+// CHECK-NEXT: report-in-main-source-file = false
 // CHECK-NEXT: serialize-stats = false
 // CHECK-NEXT: serialize-stats = false
+// CHECK-NEXT: stable-report-filename = false
+// CHECK-NEXT: suppress-c++-stdlib = true
+// CHECK-NEXT: suppress-inlined-defensive-checks = true
+// CHECK-NEXT: suppress-null-return-paths = true
 // CHECK-NEXT: unroll-loops = false
 // CHECK-NEXT: unroll-loops = false
 // CHECK-NEXT: widen-loops = false
 // CHECK-NEXT: widen-loops = false
 // CHECK-NEXT: [stats]
 // CHECK-NEXT: [stats]
-// CHECK-NEXT: num-entries = 31
+// CHECK-NEXT: num-entries = 48