//
// 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
#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
/// Create a new analyzer option, but dont generate a method for it in
/// AnalyzerOptions.
SHALLOW_VAL, DEEP_VAL)
#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.
//===----------------------------------------------------------------------===//
-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.",
- 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 "
"inlining. This covers std::shared_ptr, std::tr1::shared_ptr, and "
"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. "
"This is a heuristic for avoiding bug reports with paths that go through "
"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",
"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 "
- "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.",
- 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. "
"Statistics would be serialized in JSON format inside the main dictionary "
"under the statistics key. Available only if compiled in assert mode or "
"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",
"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 "
"actually elided during analysis. Both behaviors are allowed by the C++ "
"standard, and the analyzer, like CodeGen, defaults to eliding. Starting "
"with C++17 some elisions become mandatory, and in these cases the option "
"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 "
"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 "
"pieces as event diagnostic pieces. Useful when the diagnostic consumer "
"doesn't support the extra note pieces.",
- false, shouldDisplayNotesAsEvents)
+ false)
-ANALYZER_OPTION_GEN_FN(
- bool, AggressivelySimplifyBinaryOperation,
+ANALYZER_OPTION(
+ bool, ShouldAggressivelySimplifyBinaryOperation,
"aggressive-binary-operation-simplification",
"Whether SValBuilder should rearrange comparisons and additive operations "
"of symbolic expressions which consist of a sum of a symbol and a concrete "
"'<', '<=', '>', '>=', '+' or '-'. The rearrangement also happens with '-' "
"instead of '+' on either or both side and also if any or both integers "
"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, "
"bifurcating the path. This indicates how the engine should handle "
"expressions such as: 'x = (y != 0)'. When this is true then the "
"evaluating it to the integers 0 or 1 respectively. The upside is that "
"this can increase analysis precision until we have a better way to lazily "
"evaluate such logic. The downside is that it eagerly bifurcates paths.",
- 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 "
"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.
//===----------------------------------------------------------------------===//
-ANALYZER_OPTION_GEN_FN(
+ANALYZER_OPTION(
unsigned, AlwaysInlineSize, "ipa-always-inline-size",
"The size of the functions (in basic blocks), which should be considered "
"to be small enough to always inline.",
- 3, getAlwaysInlineSize)
+ 3)
-ANALYZER_OPTION_GEN_FN(
+ANALYZER_OPTION(
unsigned, GraphTrimInterval, "graph-trim-interval",
"How often nodes in the ExplodedGraph should be recycled to save memory. "
"To disable node reclamation, set the option to 0.",
- 1000, getGraphTrimInterval)
+ 1000)
-ANALYZER_OPTION_GEN_FN(
+ANALYZER_OPTION(
unsigned, MinCFGSizeTreatFunctionsAsLarge,
"min-cfg-size-treat-functions-as-large",
"The number of basic blocks a function needs to have to be considered "
"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",
"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",
"The maximum number of nodes the analyzer can generate while exploring a "
"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",
"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 "
"a LazyCompoundVal on bind. To disable all small-struct-dependent "
"behavior, set the option to 0.",
- 2, getRegionStoreSmallStructLimit)
+ 2)
//===----------------------------------------------------------------------===//
// String analyzer options.
ANALYZER_OPTION(StringRef, CTUDir, "ctu-dir",
"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",
"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 "
"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(
StringRef, CXXMemberInliningMode, "c++-inlining",
"\"bfs_block_dfs_contents\".",
"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
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/StringSwitch.h"
#include <string>
#include <utility>
#include <vector>
std::vector<std::pair<std::string, bool>> CheckersControlList;
/// A key-value table of use-specified configuration values.
+ // TODO: This shouldn't be public.
ConfigTable Config;
AnalysisStores AnalysisStoreOpt = RegionStoreModel;
AnalysisConstraints AnalysisConstraintsOpt = RangeConstraintsModel;
/// The mode of function selection used during inlining.
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, \
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"
#undef ANALYZER_OPTION
#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()
: DisableAllChecks(false), ShowCheckerHelp(false),
ShowEnabledCheckerList(false), ShowConfigOptionsList(false),
const ento::CheckerBase *C,
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,
/// which is used to set other low-level options. It is not accessible
/// outside of AnalyzerOptions.
- UserModeKind getUserMode();
+ UserModeKind getUserMode() const;
- ExplorationStrategyKind getExplorationStrategy();
+ ExplorationStrategyKind getExplorationStrategy() const;
/// Returns the inter-procedural analysis mode.
- IPAKind getIPAMode();
+ IPAKind getIPAMode() const;
/// Returns the option controlling which C++ member functions will be
/// considered for inlining.
/// This is controlled by the 'c++-inlining' config option.
///
/// \sa CXXMemberInliningMode
- bool mayInlineCXXMemberFunction(CXXInlineableMemberKind K);
-
- StringRef getCTUDir();
+ bool mayInlineCXXMemberFunction(CXXInlineableMemberKind K) const;
};
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
#endif // LLVM_CLANG_STATICANALYZER_CORE_ANALYZEROPTIONS_H
}
}
+static void parseAnalyzerConfigs(AnalyzerOptions &AnOpts,
+ DiagnosticsEngine &Diags);
+
static void getAllNoBuiltinFuncValues(ArgList &Args,
std::vector<std::string> &Funcs) {
SmallVector<const char *, 8> Values;
}
}
+ parseAnalyzerConfigs(Opts, Diags);
+
llvm::raw_string_ostream os(Opts.FullCompilerInvocation);
for (unsigned i = 0; i < Args.getNumInputArgStrings(); ++i) {
if (i != 0)
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) {
Opts.NoNSAllocReallocError = Args.hasArg(OPT_migrator_no_nsalloc_error);
Opts.NoFinalizeRemoval = Args.hasArg(OPT_migrator_no_finalize_removal);
llvm::errs() << "[config]\n";
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';
}
void MallocChecker::checkPostStmt(const CXXNewExpr *NE,
CheckerContext &C) const {
- if (!C.getAnalysisManager().getAnalyzerOptions().mayInlineCXXAllocator())
+ if (!C.getAnalysisManager().getAnalyzerOptions().MayInlineCXXAllocator)
processNewAllocation(NE, C, C.getSVal(NE));
}
AnalyzerOptions &Options,
CodeInjector *injector)
: 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
// 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()),
PathConsumers(PDC), CreateStoreMgr(storemgr),
CreateConstraintMgr(constraintmgr), CheckerMgr(checkerMgr),
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
-AnalyzerOptions::getExplorationStrategy() {
- if (!ExplorationStrategy.hasValue()) {
- ExplorationStrategy = getStringOption("exploration_strategy",
- "unexplored_first_queue");
- }
+AnalyzerOptions::getExplorationStrategy() const {
auto K =
llvm::StringSwitch<llvm::Optional<ExplorationStrategyKind>>(
- *ExplorationStrategy)
+ ExplorationStrategy)
.Case("dfs", ExplorationStrategyKind::DFS)
.Case("bfs", ExplorationStrategyKind::BFS)
.Case("unexplored_first",
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("basic-inlining", IPAK_BasicInlining)
.Case("inlining", IPAK_Inlining)
}
bool
-AnalyzerOptions::mayInlineCXXMemberFunction(CXXInlineableMemberKind Param) {
- if (!CXXMemberInliningMode.hasValue()) {
- CXXMemberInliningMode = getStringOption("c++-inlining", "destructors");
- }
-
+AnalyzerOptions::mayInlineCXXMemberFunction(
+ CXXInlineableMemberKind Param) const {
if (getIPAMode() < IPAK_Inlining)
return false;
auto K =
llvm::StringSwitch<llvm::Optional<CXXInlineableMemberKind>>(
- *CXXMemberInliningMode)
+ CXXMemberInliningMode)
.Case("constructors", CIMK_Constructors)
.Case("destructors", CIMK_Destructors)
.Case("methods", CIMK_MemberFunctions)
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 DefaultVal,
const CheckerBase *C,
// but the AnalyzerOptions doesn't have access to a diagnostic engine.
assert(C);
return llvm::StringSwitch<bool>(
- getCheckerStringOption(Name, toString(DefaultVal), C, SearchInParents))
+ getCheckerStringOption(Name, DefaultVal ? "true" : "false", C,
+ SearchInParents))
.Case("true", true)
.Case("false", false)
.Default(DefaultVal);
(void)HasFailed;
return Ret;
}
-
-StringRef AnalyzerOptions::getCTUDir() {
- if (!CTUDir.hasValue()) {
- CTUDir = getStringOption("ctu-dir", "");
- if (!llvm::sys::fs::is_directory(*CTUDir))
- CTUDir = "";
- }
- return CTUDir.getValue();
-}
// Finally, prune the diagnostic path of uninteresting stuff.
if (!PD->path.empty()) {
- if (R->shouldPrunePath() && Opts.shouldPrunePaths()) {
+ if (R->shouldPrunePath() && Opts.ShouldPrunePaths) {
bool stillHasNotes =
removeUnneededCalls(PD->getMutablePieces(), R, LCM);
assert(stillHasNotes);
removeEdgesToDefaultInitializers(PD->getMutablePieces());
}
- if (GenerateDiagnostics && Opts.shouldDisplayMacroExpansions())
+ if (GenerateDiagnostics && Opts.ShouldDisplayMacroExpansions)
CompactMacroExpandedPieces(PD->getMutablePieces(), SM);
return PD;
generateVisitorsDiagnostics(R, ErrorNode, BRC);
if (R->isValid()) {
- if (Opts.shouldCrosscheckWithZ3()) {
+ if (Opts.ShouldCrosscheckWithZ3) {
// If crosscheck is enabled, remove all visitors, add the refutation
// visitor and check again
R->clearVisitors();
}
PathPieces &Pieces = PD->getMutablePieces();
- if (getAnalyzerOptions().shouldDisplayNotesAsEvents()) {
+ if (getAnalyzerOptions().ShouldDisplayNotesAsEvents) {
// For path diagnostic consumers that don't support extra notes,
// we may optionally convert those to path notes.
for (auto I = report->getNotes().rbegin(),
// report location to the last piece in the main source file.
AnalyzerOptions &Opts = getAnalyzerOptions();
for (auto const &P : *Out)
- if (Opts.shouldReportIssuesInMainSourceFile() && !Opts.AnalyzeAll)
+ if (Opts.ShouldReportIssuesInMainSourceFile && !Opts.AnalyzeAll)
P.second->resetDiagnosticLocationToMainFile();
return Out;
bool EnableNullFPSuppression, BugReport &BR,
const SVal V) {
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>(
R->getAs<SubRegion>(), V));
}
AnalyzerOptions &Options = State->getAnalysisManager().options;
bool EnableNullFPSuppression = false;
- if (InEnableNullFPSuppression && Options.shouldSuppressNullReturnPaths())
+ if (InEnableNullFPSuppression &&
+ Options.ShouldSuppressNullReturnPaths)
if (Optional<Loc> RetLoc = RetVal.getAs<Loc>())
EnableNullFPSuppression = State->isNull(*RetLoc).isConstrainedTrue();
// future nodes. We want to emit a path note as well, in case
// the report is resurrected as valid later on.
if (EnableNullFPSuppression &&
- Options.shouldAvoidSuppressingNullArgumentPaths())
+ Options.ShouldAvoidSuppressingNullArgumentPaths)
Mode = MaybeUnsuppress;
if (RetE->getType()->isObjCObjectPointerType()) {
visitNodeMaybeUnsuppress(const ExplodedNode *N,
BugReporterContext &BRC, BugReport &BR) {
#ifndef NDEBUG
- assert(Options.shouldAvoidSuppressingNullArgumentPaths());
+ assert(Options.ShouldAvoidSuppressingNullArgumentPaths);
#endif
// Are we at the entry node for this call?
: V(Value) {
// Check if the visitor is disabled.
AnalyzerOptions &Options = N->getState()->getAnalysisManager().options;
- if (!Options.shouldSuppressInlinedDefensiveChecks())
+ if (!Options.ShouldSuppressInlinedDefensiveChecks)
IsSatisfied = true;
assert(N->getState()->isNull(V).isConstrainedTrue() &&
// 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
// TR1, Boost, or llvm/ADT.
- if (Options.shouldSuppressFromCXXStandardLibrary()) {
+ if (Options.ShouldSuppressFromCXXStandardLibrary) {
BR.markInvalid(getTag(), nullptr);
return;
} else {
AnalyzerOptions &Opts = Engine->getAnalysisManager().options;
// Try to get CTU definition only if CTUDir is provided.
- if (!Opts.naiveCTUEnabled())
+ if (!Opts.IsNaiveCTUEnabled)
return {};
cross_tu::CrossTranslationUnitContext &CTUCtx =
*Engine->getCrossTranslationUnitContext();
llvm::Expected<const FunctionDecl *> CTUDeclOrError =
- CTUCtx.getCrossTUDefinition(FD, Opts.getCTUDir(), Opts.getCTUIndexName());
+ CTUCtx.getCrossTUDefinition(FD, Opts.CTUDir,
+ Opts.CTUIndexName);
if (!CTUDeclOrError) {
handleAllErrors(CTUDeclOrError.takeError(),
svalBuilder(StateMgr.getSValBuilder()), ObjCNoRet(mgr.getASTContext()),
BR(mgr, *this),
VisitedCallees(VisitedCalleesIn), HowToInline(HowToInlineIn) {
- unsigned TrimInterval = mgr.options.getGraphTrimInterval();
+ unsigned TrimInterval = mgr.options.GraphTrimInterval;
if (TrimInterval != 0) {
// Enable eager node reclaimation when constructing the ExplodedGraph.
G.enableNodeReclamation(TrimInterval);
NodeBuilder Bldr(Pred, Dst, *currBldrCtx);
ProgramStateRef NewState = Pred->getState();
- if(AMgr.options.shouldUnrollLoops())
+ if(AMgr.options.ShouldUnrollLoops)
NewState = processLoopEnd(S, NewState);
LoopExit PP(S, Pred->getLocationContext());
// TODO: We're not evaluating allocators for all cases just yet as
// we're not handling the return value correctly, which causes false
// positives when the alpha.cplusplus.NewDeleteLeaks check is on.
- if (Opts.mayInlineCXXAllocator())
+ if (Opts.MayInlineCXXAllocator)
VisitCXXNewAllocatorCall(NE, Pred, Dst);
else {
NodeBuilder Bldr(Pred, Dst, *currBldrCtx);
// This is a fallback solution in case we didn't have a construction
// context when we were constructing the temporary. Otherwise the map should
// 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
// the initialization - we would otherwise never clean it up.
Dst = PreVisit;
break;
case Stmt::LambdaExprClass:
- if (AMgr.options.shouldInlineLambdas()) {
+ if (AMgr.options.ShouldInlineLambdas) {
Bldr.takeNodes(Pred);
VisitLambdaExpr(cast<LambdaExpr>(S), Pred, Dst);
Bldr.addNodes(Dst);
Bldr.takeNodes(Pred);
- if (AMgr.options.shouldEagerlyAssume() &&
+ if (AMgr.options.ShouldEagerlyAssume &&
(B->isRelationalOp() || B->isEqualityOp())) {
ExplodedNodeSet Tmp;
VisitBinaryOperator(cast<BinaryOperator>(S), Pred, Tmp);
case Stmt::UnaryOperatorClass: {
Bldr.takeNodes(Pred);
const auto *U = cast<UnaryOperator>(S);
- if (AMgr.options.shouldEagerlyAssume() && (U->getOpcode() == UO_LNot)) {
+ if (AMgr.options.ShouldEagerlyAssume && (U->getOpcode() == UO_LNot)) {
ExplodedNodeSet Tmp;
VisitUnaryOperator(U, Pred, Tmp);
evalEagerlyAssumeBinOpBifurcation(Dst, Tmp, U);
PrettyStackTraceLocationContext CrashInfo(Pred->getLocationContext());
// If we reach a loop which has a known bound (and meets
// other constraints) then consider completely unrolling it.
- if(AMgr.options.shouldUnrollLoops()) {
+ if(AMgr.options.ShouldUnrollLoops) {
unsigned maxBlockVisitOnPath = AMgr.options.maxBlockVisitOnPath;
const Stmt *Term = nodeBuilder.getContext().getBlock()->getTerminator();
if (Term) {
// maximum number of times, widen the loop.
unsigned int BlockCount = nodeBuilder.getContext().blockCount();
if (BlockCount == AMgr.options.maxBlockVisitOnPath - 1 &&
- AMgr.options.shouldWidenLoops()) {
+ AMgr.options.ShouldWidenLoops) {
const Stmt *Term = nodeBuilder.getContext().getBlock()->getTerminator();
if (!(Term &&
(isa<ForStmt>(Term) || isa<WhileStmt>(Term) || isa<DoStmt>(Term))))
const auto *DeclRefEx = dyn_cast<DeclRefExpr>(Ex);
Optional<std::pair<SVal, QualType>> VInfo;
- if (AMgr.options.shouldInlineLambdas() && DeclRefEx &&
+ if (AMgr.options.ShouldInlineLambdas && DeclRefEx &&
DeclRefEx->refersToEnclosingVariableOrCapture() && MD &&
MD->getParent()->isLambda()) {
// Lookup the field of the lambda.
return std::make_pair(State, FieldVal);
}
case ConstructionContext::NewAllocatedObjectKind: {
- if (AMgr.getAnalyzerOptions().mayInlineCXXAllocator()) {
+ if (AMgr.getAnalyzerOptions().MayInlineCXXAllocator) {
const auto *NECC = cast<NewAllocatedObjectConstructionContext>(CC);
const auto *NE = NECC->getCXXNewExpr();
SVal V = *getObjectUnderConstruction(State, NE, LCtx);
llvm_unreachable("Unhandled return value construction context!");
}
case ConstructionContext::ElidedTemporaryObjectKind: {
- assert(AMgr.getAnalyzerOptions().shouldElideConstructors());
+ assert(AMgr.getAnalyzerOptions().ShouldElideConstructors);
const auto *TCC = cast<ElidedTemporaryObjectConstructionContext>(CC);
const CXXBindTemporaryExpr *BTE = TCC->getCXXBindTemporaryExpr();
const MaterializeTemporaryExpr *MTE = TCC->getMaterializedTemporaryExpr();
ProgramStateRef State = Pred->getState();
// Retrieve the stored operator new() return value.
- if (AMgr.getAnalyzerOptions().mayInlineCXXAllocator()) {
+ if (AMgr.getAnalyzerOptions().MayInlineCXXAllocator) {
symVal = *getObjectUnderConstruction(State, CNE, LCtx);
State = finishObjectConstruction(State, CNE, LCtx);
}
CallEventRef<CXXAllocatorCall> Call =
CEMgr.getCXXAllocatorCall(CNE, State, LCtx);
- if (!AMgr.getAnalyzerOptions().mayInlineCXXAllocator()) {
+ if (!AMgr.getAnalyzerOptions().MayInlineCXXAllocator) {
// Invalidate placement args.
// FIXME: Once we figure out how we want allocators to work,
// we should be using the usual pre-/(default-)eval-/post-call checks here.
/*WasInlined=*/true);
} else if (CE &&
!(isa<CXXNewExpr>(CE) && // Called when visiting CXXNewExpr.
- AMgr.getAnalyzerOptions().mayInlineCXXAllocator())) {
+ AMgr.getAnalyzerOptions().MayInlineCXXAllocator)) {
getCheckerManager().runCheckersForPostStmt(Dst, DstPostCall, CE,
*this, /*WasInlined=*/true);
} else {
// Do not count the small functions when determining the stack depth.
AnalysisDeclContext *CalleeADC = AMgr.getAnalysisDeclContext(DI);
const CFG *CalleeCFG = CalleeADC->getCFG();
- if (CalleeCFG->getNumBlockIDs() > AMgr.options.getAlwaysInlineSize())
+ if (CalleeCFG->getNumBlockIDs() > AMgr.options.AlwaysInlineSize)
++StackDepth;
}
LCtx = LCtx->getParent();
: nullptr;
if (CC && isa<NewAllocatedObjectConstructionContext>(CC) &&
- !Opts.mayInlineCXXAllocator())
+ !Opts.MayInlineCXXAllocator)
return CIP_DisallowedOnce;
// FIXME: We don't handle constructors or destructors for arrays properly.
// If we don't handle temporary destructors, we shouldn't inline
// their constructors.
if (CallOpts.IsTemporaryCtorOrDtor &&
- !Opts.includeTemporaryDtorsInCFG())
+ !Opts.ShouldIncludeTemporaryDtorsInCFG)
return CIP_DisallowedOnce;
// If we did not find the correct this-region, it would be pointless
return CIP_DisallowedOnce;
// Allow disabling temporary destructor inlining with a separate option.
- if (CallOpts.IsTemporaryCtorOrDtor && !Opts.mayInlineCXXTemporaryDtors())
+ if (CallOpts.IsTemporaryCtorOrDtor &&
+ !Opts.MayInlineCXXTemporaryDtors)
return CIP_DisallowedOnce;
// If we did not find the correct this-region, it would be pointless
break;
}
case CE_CXXAllocator:
- if (Opts.mayInlineCXXAllocator())
+ if (Opts.MayInlineCXXAllocator)
break;
// Do not inline allocators until we model deallocators.
// This is unfortunate, but basically necessary for smart pointers and such.
return CIP_DisallowedAlways;
case CE_ObjCMessage:
- if (!Opts.mayInlineObjCMethod())
+ if (!Opts.MayInlineObjCMethod)
return CIP_DisallowedAlways;
if (!(Opts.getIPAMode() == IPAK_DynamicDispatch ||
Opts.getIPAMode() == IPAK_DynamicDispatchBifurcate))
if (Ctx.getLangOpts().CPlusPlus) {
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(CalleeADC->getDecl())) {
// Conditionally control the inlining of template functions.
- if (!Opts.mayInlineTemplateFunctions())
+ if (!Opts.MayInlineTemplateFunctions)
if (FD->getTemplatedKind() != FunctionDecl::TK_NonTemplate)
return false;
// Conditionally control the inlining of C++ standard library functions.
- if (!Opts.mayInlineCXXStandardLibrary())
+ if (!Opts.MayInlineCXXStandardLibrary)
if (Ctx.getSourceManager().isInSystemHeader(FD->getLocation()))
if (AnalysisDeclContext::isInStdNamespace(FD))
return false;
// Conditionally control the inlining of methods on objects that look
// like C++ containers.
- if (!Opts.mayInlineCXXContainerMethods())
+ if (!Opts.MayInlineCXXContainerMethods)
if (!AMgr.isInCodeFile(FD->getLocation()))
if (isContainerMethod(Ctx, FD))
return false;
// 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
// idea.
- if (!Opts.mayInlineCXXSharedPtrDtor())
+ if (!Opts.MayInlineCXXSharedPtrDtor)
if (isCXXSharedPtrDtor(FD))
return false;
}
return false;
// Do not inline large functions.
- if (CalleeCFG->getNumBlockIDs() > Opts.getMaxInlinableSize())
+ if (CalleeCFG->getNumBlockIDs() > Opts.MaxInlinableSize)
return false;
// It is possible that the live variables analysis cannot be
unsigned StackDepth = 0;
examineStackFrames(D, Pred->getLocationContext(), IsRecursive, StackDepth);
if ((StackDepth >= Opts.InlineMaxStackDepth) &&
- ((CalleeCFG->getNumBlockIDs() > Opts.getAlwaysInlineSize())
+ ((CalleeCFG->getNumBlockIDs() > Opts.AlwaysInlineSize)
|| IsRecursive))
return false;
// Do not inline large functions too many times.
if ((Engine.FunctionSummaries->getNumTimesInlined(D) >
- Opts.getMaxTimesInlineLarge()) &&
+ Opts.MaxTimesInlineLarge) &&
CalleeCFG->getNumBlockIDs() >=
- Opts.getMinCFGSizeTreatFunctionsAsLarge()) {
+ Opts.MinCFGSizeTreatFunctionsAsLarge) {
NumReachedInlineCountMax++;
return false;
}
if (HowToInline == Inline_Minimal &&
- (CalleeCFG->getNumBlockIDs() > Opts.getAlwaysInlineSize()
+ (CalleeCFG->getNumBlockIDs() > Opts.AlwaysInlineSize
|| IsRecursive))
return false;
int FD;
SmallString<128> Model, ResultPath;
- if (!AnalyzerOpts.shouldWriteStableReportFilename()) {
+ if (!AnalyzerOpts.ShouldWriteStableReportFilename) {
llvm::sys::path::append(Model, Directory, "report-%%%%%%.html");
if (std::error_code EC =
llvm::sys::fs::make_absolute(Model)) {
o << " </array>\n";
- if (!AnOpts.shouldDisplayMacroExpansions())
+ if (!AnOpts.ShouldDisplayMacroExpansions)
return;
o << " <key>macro_expansions</key>\n"
EmitString(o << " ", SM.getFileEntryForID(FID)->getName()) << '\n';
o << " </array>\n";
- if (llvm::AreStatisticsEnabled() && AnOpts.shouldSerializeStats()) {
+ if (llvm::AreStatisticsEnabled() && AnOpts.ShouldSerializeStats) {
o << " <key>statistics</key>\n";
std::string stats;
llvm::raw_string_ostream os(stats);
if (SubEngine *Eng = StateMgr.getOwningEngine()) {
AnalyzerOptions &Options = Eng->getAnalysisManager().options;
SmallStructLimit =
- Options.getRegionStoreSmallStructLimit();
+ Options.RegionStoreSmallStructLimit;
}
}
// instead of generating an Unknown value and propagate the taint info to it.
const unsigned MaxComp = StateMgr.getOwningEngine()
->getAnalysisManager()
- .options.getMaxSymbolComplexity();
+ .options.MaxSymbolComplexity;
if (symLHS && symRHS &&
(symLHS->computeComplexity() + symRHS->computeComplexity()) < MaxComp)
// FIXME: After putting complexity threshold to the symbols we can always
// rearrange additive operations but rearrange comparisons only if
// option is set.
- if(!Opts.shouldAggressivelySimplifyBinaryOperation())
+ if(!Opts.ShouldAggressivelySimplifyBinaryOperation)
return None;
SymbolRef LSym = Lhs.getAsSymbol();
PP(CI.getPreprocessor()), OutDir(outdir), Opts(std::move(opts)),
Plugins(plugins), Injector(injector), CTU(CI) {
DigestAnalyzerOptions();
- if (Opts->PrintStats || Opts->shouldSerializeStats()) {
+ if (Opts->PrintStats || Opts->ShouldSerializeStats) {
AnalyzerTimers = llvm::make_unique<llvm::TimerGroup>(
"analyzer", "Analyzer timers");
TUTotalTimer = llvm::make_unique<llvm::Timer>(
// Execute the worklist algorithm.
Eng.ExecuteWorkList(Mgr->getAnalysisDeclContextManager().getStackFrame(D),
- Mgr->options.getMaxNodesPerTopLevelFunction());
+ Mgr->options.MaxNodesPerTopLevelFunction);
if (!Mgr->options.DumpExplodedGraphTo.empty())
Eng.DumpGraph(Mgr->options.TrimGraph, Mgr->options.DumpExplodedGraphTo);
FileID mainFileID = SM.getMainFileID();
AnalyzerOptionsRef analyzerOpts = CI.getAnalyzerOpts();
- llvm::StringRef modelPath = analyzerOpts->getModelPath();
+ llvm::StringRef modelPath = analyzerOpts->ModelPath;
llvm::SmallString<128> fileName;
// 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
-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-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-implicit-dtors = true
// CHECK-NEXT: cfg-lifetime = false
// CHECK-NEXT: cfg-rich-constructors = true
// CHECK-NEXT: cfg-scopes = false
// 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: 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: faux-bodies = true
// CHECK-NEXT: graph-trim-interval = 1000
// CHECK-NEXT: ipa-always-inline-size = 3
// CHECK-NEXT: max-inlinable-size = 100
// CHECK-NEXT: max-nodes = 225000
+// CHECK-NEXT: max-symbol-complexity = 35
// CHECK-NEXT: max-times-inline-large = 32
// CHECK-NEXT: min-cfg-size-treat-functions-as-large = 14
// 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: report-in-main-source-file = 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: widen-loops = false
// CHECK-NEXT: [stats]
-// CHECK-NEXT: num-entries = 24
+// CHECK-NEXT: num-entries = 48
// 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
-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-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: cfg-rich-constructors = true
// CHECK-NEXT: cfg-scopes = false
// 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: 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: faux-bodies = true
// CHECK-NEXT: ipa-always-inline-size = 3
// CHECK-NEXT: max-inlinable-size = 100
// CHECK-NEXT: max-nodes = 225000
+// CHECK-NEXT: max-symbol-complexity = 35
// CHECK-NEXT: max-times-inline-large = 32
// CHECK-NEXT: min-cfg-size-treat-functions-as-large = 14
// 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: report-in-main-source-file = 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: widen-loops = false
// CHECK-NEXT: [stats]
-// CHECK-NEXT: num-entries = 31
+// CHECK-NEXT: num-entries = 48