forked from OSchip/llvm-project
[analyzer][NFC] Collect all -analyzer-config options in a .def file
I'm in the process of refactoring AnalyzerOptions. The main motivation behind here is to emit warnings if an invalid -analyzer-config option is given from the command line, and be able to list them all. In this patch, I'm moving all analyzer options to a def file, and move 2 enums to global namespace. Differential Revision: https://reviews.llvm.org/D53277 llvm-svn: 345986
This commit is contained in:
parent
c83b0dda49
commit
e390633d46
|
@ -0,0 +1,467 @@
|
|||
//===-- AnalyzerOptions.def - Metadata about Static Analyses ----*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
||||
#error This .def file is expected to be included in translation units where \
|
||||
"llvm/ADT/StringRef.h" is already included!
|
||||
#endif
|
||||
|
||||
#ifdef ANALYZER_OPTION
|
||||
#ifndef ANALYZER_OPTION_DEPENDS_ON_USER_MODE
|
||||
#error If you didn't include this file with the intent of generating methods, \
|
||||
define both 'ANALYZER_OPTION' and 'ANALYZER_OPTION_DEPENDS_ON_USER_MODE' macros!
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef ANALYZER_OPTION_DEPENDS_ON_USER_MODE
|
||||
#ifdef ANALYZER_OPTION
|
||||
#error If you didn't include this file with the intent of generating methods, \
|
||||
define both 'ANALYZER_OPTION' and 'ANALYZER_OPTION_DEPENDS_ON_USER_MODE' macros!
|
||||
#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.
|
||||
///
|
||||
/// 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.
|
||||
#define ANALYZER_OPTION(TYPE, NAME, CMDFLAG, DESC, DEFAULT_VAL)
|
||||
#endif
|
||||
|
||||
#ifndef ANALYZER_OPTION_DEPENDS_ON_USER_MODE
|
||||
/// Create a new analyzer option, but dont generate a method for it in
|
||||
/// AnalyzerOptions. It's value depends on the option "user-mode".
|
||||
///
|
||||
/// 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.
|
||||
/// 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".
|
||||
#define ANALYZER_OPTION_DEPENDS_ON_USER_MODE(TYPE, NAME, CMDFLAG, DESC, \
|
||||
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
|
||||
|
||||
#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
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// 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_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_GEN_FN(
|
||||
bool, IncludeLifetimeInCFG, "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",
|
||||
"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)
|
||||
|
||||
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_GEN_FN(
|
||||
bool, SuppressNullReturnPaths, "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)
|
||||
|
||||
ANALYZER_OPTION_GEN_FN(
|
||||
bool, AvoidSuppressingNullArgumentPaths,
|
||||
"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 "
|
||||
"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",
|
||||
"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)
|
||||
|
||||
ANALYZER_OPTION_GEN_FN(
|
||||
bool, InlineObjCMethod, "objc-inlining",
|
||||
"Whether ObjectiveC inlining is enabled, false otherwise.", true,
|
||||
mayInlineObjCMethod)
|
||||
|
||||
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_GEN_FN(
|
||||
bool, ConditionalizeStaticInitializers,
|
||||
"cfg-conditional-static-initializers",
|
||||
"Whether 'static' initializers should be in conditional logic in the CFG.",
|
||||
true, shouldConditionalizeStaticInitializers)
|
||||
|
||||
ANALYZER_OPTION_GEN_FN(bool, SynthesizeBodies, "faux-bodies",
|
||||
"Whether the analyzer engine should synthesize fake "
|
||||
"bodies for well-known functions.",
|
||||
true, shouldSynthesizeBodies)
|
||||
|
||||
ANALYZER_OPTION_GEN_FN(
|
||||
bool, ElideConstructors, "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)
|
||||
|
||||
ANALYZER_OPTION_GEN_FN(
|
||||
bool, InlineLambdas, "inline-lambdas",
|
||||
"Whether lambdas should be inlined. Otherwise a sink node will be "
|
||||
"generated each time a LambdaExpr is visited.",
|
||||
true, shouldInlineLambdas)
|
||||
|
||||
ANALYZER_OPTION_GEN_FN(bool, WidenLoops, "widen-loops",
|
||||
"Whether the analysis should try to widen loops.", false,
|
||||
shouldWidenLoops)
|
||||
|
||||
ANALYZER_OPTION_GEN_FN(
|
||||
bool, UnrollLoops, "unroll-loops",
|
||||
"Whether the analysis should try to unroll loops with known bounds.", false,
|
||||
shouldUnrollLoops)
|
||||
|
||||
ANALYZER_OPTION_GEN_FN(
|
||||
bool, DisplayNotesAsEvents, "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)
|
||||
|
||||
ANALYZER_OPTION_GEN_FN(
|
||||
bool, AggressivelySimplifyBinaryOperation,
|
||||
"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 "
|
||||
"integer into the format where symbols are on the left-hand side and the "
|
||||
"integer is on the right. This is only done if both symbols and both "
|
||||
"concrete integers are signed, greater than or equal to the quarter of the "
|
||||
"minimum value of the type and less than or equal to the quarter of the "
|
||||
"maximum value of that type. A + n <OP> B + m becomes A - B <OP> m - n, "
|
||||
"where A and B symbolic, n and m are integers. <OP> is any of '==', '!=', "
|
||||
"'<', '<=', '>', '>=', '+' or '-'. The rearrangement also happens with '-' "
|
||||
"instead of '+' on either or both side and also if any or both integers "
|
||||
"are missing.",
|
||||
false, shouldAggressivelySimplifyBinaryOperation)
|
||||
|
||||
ANALYZER_OPTION_GEN_FN(
|
||||
bool, EagerlyAssume, "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 "
|
||||
"subexpression 'y != 0' will be eagerly assumed to be true or false, thus "
|
||||
"evaluating it to the integers 0 or 1 respectively. The upside is that "
|
||||
"this can increase analysis precision until we have a better way to lazily "
|
||||
"evaluate such logic. The downside is that it eagerly bifurcates paths.",
|
||||
true, shouldEagerlyAssume)
|
||||
|
||||
ANALYZER_OPTION_GEN_FN(
|
||||
bool, NaiveCTU, "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)
|
||||
|
||||
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)
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Unsinged analyzer options.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
ANALYZER_OPTION_GEN_FN(
|
||||
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)
|
||||
|
||||
ANALYZER_OPTION_GEN_FN(
|
||||
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)
|
||||
|
||||
ANALYZER_OPTION_GEN_FN(
|
||||
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)
|
||||
|
||||
ANALYZER_OPTION_GEN_FN(unsigned, MaxSymbolComplexity, "max-symbol-complexity",
|
||||
"The maximum complexity of symbolic constraint.", 35,
|
||||
getMaxSymbolComplexity)
|
||||
|
||||
ANALYZER_OPTION_GEN_FN(unsigned, MaxTimesInlineLarge, "max-times-inline-large",
|
||||
"The maximum times a large function could be inlined.",
|
||||
32, getMaxTimesInlineLarge)
|
||||
|
||||
ANALYZER_OPTION_GEN_FN_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)
|
||||
|
||||
ANALYZER_OPTION_GEN_FN_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)
|
||||
|
||||
ANALYZER_OPTION_GEN_FN(
|
||||
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)
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// 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_GEN_FN(
|
||||
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",
|
||||
"Controls which C++ member functions will be considered for inlining. "
|
||||
"Value: \"constructors\", \"destructors\", \"methods\".",
|
||||
"destructors")
|
||||
|
||||
ANALYZER_OPTION_DEPENDS_ON_USER_MODE(
|
||||
StringRef, IPAMode, "ipa",
|
||||
"Controls the mode of inter-procedural analysis. Value: \"none\", "
|
||||
"\"basic-inlining\", \"inlining\", \"dynamic\", \"dynamic-bifurcate\".",
|
||||
/* SHALLOW_VAL */ "inlining", /* DEEP_VAL */ "dynamic-bifurcate")
|
||||
|
||||
ANALYZER_OPTION(
|
||||
StringRef, ExplorationStrategy, "exploration_strategy",
|
||||
"Value: \"dfs\", \"bfs\", \"unexplored_first\", "
|
||||
"\"unexplored_first_queue\", \"unexplored_first_location_queue\", "
|
||||
"\"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
|
|
@ -119,6 +119,24 @@ enum IPAKind {
|
|||
IPAK_DynamicDispatchBifurcate = 5
|
||||
};
|
||||
|
||||
enum class ExplorationStrategyKind {
|
||||
DFS,
|
||||
BFS,
|
||||
UnexploredFirst,
|
||||
UnexploredFirstQueue,
|
||||
UnexploredFirstLocationQueue,
|
||||
BFSBlockDFSContents,
|
||||
};
|
||||
|
||||
/// Describes the kinds for high-level analyzer mode.
|
||||
enum UserModeKind {
|
||||
/// Perform shallow but fast analyzes.
|
||||
UMK_Shallow = 1,
|
||||
|
||||
/// Perform deep analyzes.
|
||||
UMK_Deep = 2
|
||||
};
|
||||
|
||||
class AnalyzerOptions : public RefCountedBase<AnalyzerOptions> {
|
||||
public:
|
||||
using ConfigTable = llvm::StringMap<std::string>;
|
||||
|
@ -179,160 +197,16 @@ public:
|
|||
/// The mode of function selection used during inlining.
|
||||
AnalysisInliningMode InliningMode = NoRedundancy;
|
||||
|
||||
enum class ExplorationStrategyKind {
|
||||
DFS,
|
||||
BFS,
|
||||
UnexploredFirst,
|
||||
UnexploredFirstQueue,
|
||||
UnexploredFirstLocationQueue,
|
||||
BFSBlockDFSContents,
|
||||
};
|
||||
|
||||
private:
|
||||
/// Describes the kinds for high-level analyzer mode.
|
||||
enum UserModeKind {
|
||||
/// Perform shallow but fast analyzes.
|
||||
UMK_Shallow = 1,
|
||||
|
||||
/// Perform deep analyzes.
|
||||
UMK_Deep = 2
|
||||
};
|
||||
|
||||
llvm::Optional<ExplorationStrategyKind> ExplorationStrategy;
|
||||
|
||||
/// Controls the high-level analyzer mode, which influences the default
|
||||
/// settings for some of the lower-level config options (such as IPAMode).
|
||||
/// \sa getUserMode
|
||||
llvm::Optional<UserModeKind> UserMode;
|
||||
|
||||
/// Controls the mode of inter-procedural analysis.
|
||||
llvm::Optional<IPAKind> IPAMode;
|
||||
|
||||
/// Controls which C++ member functions will be considered for inlining.
|
||||
llvm::Optional<CXXInlineableMemberKind> CXXMemberInliningMode;
|
||||
|
||||
/// \sa includeImplicitDtorsInCFG
|
||||
Optional<bool> IncludeImplicitDtorsInCFG;
|
||||
|
||||
/// \sa includeTemporaryDtorsInCFG
|
||||
Optional<bool> IncludeTemporaryDtorsInCFG;
|
||||
|
||||
/// \sa IncludeLifetimeInCFG
|
||||
Optional<bool> IncludeLifetimeInCFG;
|
||||
|
||||
/// \sa IncludeLoopExitInCFG
|
||||
Optional<bool> IncludeLoopExitInCFG;
|
||||
|
||||
/// \sa IncludeRichConstructorsInCFG
|
||||
Optional<bool> IncludeRichConstructorsInCFG;
|
||||
|
||||
/// \sa mayInlineCXXStandardLibrary
|
||||
Optional<bool> InlineCXXStandardLibrary;
|
||||
|
||||
/// \sa includeScopesInCFG
|
||||
Optional<bool> IncludeScopesInCFG;
|
||||
|
||||
/// \sa mayInlineTemplateFunctions
|
||||
Optional<bool> InlineTemplateFunctions;
|
||||
|
||||
/// \sa mayInlineCXXAllocator
|
||||
Optional<bool> InlineCXXAllocator;
|
||||
|
||||
/// \sa mayInlineCXXContainerMethods
|
||||
Optional<bool> InlineCXXContainerMethods;
|
||||
|
||||
/// \sa mayInlineCXXSharedPtrDtor
|
||||
Optional<bool> InlineCXXSharedPtrDtor;
|
||||
|
||||
/// \sa mayInlineCXXTemporaryDtors
|
||||
Optional<bool> InlineCXXTemporaryDtors;
|
||||
|
||||
/// \sa mayInlineObjCMethod
|
||||
Optional<bool> ObjCInliningMode;
|
||||
|
||||
// Cache of the "ipa-always-inline-size" setting.
|
||||
// \sa getAlwaysInlineSize
|
||||
Optional<unsigned> AlwaysInlineSize;
|
||||
|
||||
/// \sa shouldSuppressNullReturnPaths
|
||||
Optional<bool> SuppressNullReturnPaths;
|
||||
|
||||
// \sa getMaxInlinableSize
|
||||
Optional<unsigned> MaxInlinableSize;
|
||||
|
||||
/// \sa shouldAvoidSuppressingNullArgumentPaths
|
||||
Optional<bool> AvoidSuppressingNullArgumentPaths;
|
||||
|
||||
/// \sa shouldSuppressInlinedDefensiveChecks
|
||||
Optional<bool> SuppressInlinedDefensiveChecks;
|
||||
|
||||
/// \sa shouldSuppressFromCXXStandardLibrary
|
||||
Optional<bool> SuppressFromCXXStandardLibrary;
|
||||
|
||||
/// \sa shouldCrosscheckWithZ3
|
||||
Optional<bool> CrosscheckWithZ3;
|
||||
|
||||
/// \sa reportIssuesInMainSourceFile
|
||||
Optional<bool> ReportIssuesInMainSourceFile;
|
||||
|
||||
/// \sa StableReportFilename
|
||||
Optional<bool> StableReportFilename;
|
||||
|
||||
Optional<bool> SerializeStats;
|
||||
|
||||
/// \sa getGraphTrimInterval
|
||||
Optional<unsigned> GraphTrimInterval;
|
||||
|
||||
/// \sa getMaxSymbolComplexity
|
||||
Optional<unsigned> MaxSymbolComplexity;
|
||||
|
||||
/// \sa getMaxTimesInlineLarge
|
||||
Optional<unsigned> MaxTimesInlineLarge;
|
||||
|
||||
/// \sa getMinCFGSizeTreatFunctionsAsLarge
|
||||
Optional<unsigned> MinCFGSizeTreatFunctionsAsLarge;
|
||||
|
||||
/// \sa getMaxNodesPerTopLevelFunction
|
||||
Optional<unsigned> MaxNodesPerTopLevelFunction;
|
||||
|
||||
/// \sa shouldInlineLambdas
|
||||
Optional<bool> InlineLambdas;
|
||||
|
||||
/// \sa shouldWidenLoops
|
||||
Optional<bool> WidenLoops;
|
||||
|
||||
/// \sa shouldUnrollLoops
|
||||
Optional<bool> UnrollLoops;
|
||||
|
||||
/// \sa shouldDisplayNotesAsEvents
|
||||
Optional<bool> DisplayNotesAsEvents;
|
||||
|
||||
/// \sa shouldDisplayMacroExpansions
|
||||
Optional<bool> DisplayMacroExpansions;
|
||||
|
||||
/// \sa shouldAggressivelySimplifyBinaryOperation
|
||||
Optional<bool> AggressiveBinaryOperationSimplification;
|
||||
|
||||
/// \sa shouldEagerlyAssume
|
||||
Optional<bool> EagerlyAssumeBinOpBifurcation;
|
||||
|
||||
/// \sa getCTUDir
|
||||
Optional<StringRef> CTUDir;
|
||||
|
||||
/// \sa getCTUIndexName
|
||||
Optional<StringRef> CTUIndexName;
|
||||
|
||||
/// \sa naiveCTUEnabled
|
||||
Optional<bool> NaiveCTU;
|
||||
|
||||
/// \sa shouldElideConstructors
|
||||
Optional<bool> ElideConstructors;
|
||||
|
||||
/// \sa getModelPath
|
||||
Optional<StringRef> ModelPath;
|
||||
|
||||
/// \sa getRegionStoreSmallStructLimit
|
||||
Optional<unsigned> RegionStoreSmallStructLimit;
|
||||
#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;
|
||||
#include "clang/StaticAnalyzer/Core/AnalyzerOptions.def"
|
||||
#undef ANALYZER_OPTION
|
||||
#undef ANALYZER_OPTION_DEPENDS_ON_USER_MODE
|
||||
|
||||
/// A helper function that retrieves option for a given full-qualified
|
||||
/// checker name.
|
||||
|
@ -368,7 +242,7 @@ public:
|
|||
eagerlyAssumeBinOpBifurcation(false), TrimGraph(false),
|
||||
visualizeExplodedGraphWithGraphViz(false),
|
||||
UnoptimizedCFG(false),
|
||||
PrintStats(false), NoRetryExhausted(false), CXXMemberInliningMode() {}
|
||||
PrintStats(false), NoRetryExhausted(false) {}
|
||||
|
||||
/// Interprets an option's string value as a boolean. The "true" string is
|
||||
/// interpreted as true and the "false" string is interpreted as false.
|
||||
|
@ -423,7 +297,6 @@ public:
|
|||
const ento::CheckerBase *C = nullptr,
|
||||
bool SearchInParents = false);
|
||||
|
||||
|
||||
unsigned getOptionAsUInt(Optional<unsigned> &V, StringRef Name,
|
||||
unsigned DefaultVal,
|
||||
const ento::CheckerBase *C = nullptr,
|
||||
|
@ -451,6 +324,19 @@ public:
|
|||
const ento::CheckerBase *C = nullptr,
|
||||
bool SearchInParents = false);
|
||||
|
||||
#define ANALYZER_OPTION_GEN_FN(TYPE, NAME, CMDFLAG, DESC, DEFAULT_VAL, \
|
||||
CREATE_FN) \
|
||||
TYPE CREATE_FN();
|
||||
|
||||
#define ANALYZER_OPTION_GEN_FN_DEPENDS_ON_USER_MODE( \
|
||||
TYPE, NAME, CMDFLAG, DESC, SHALLOW_VAL, DEEP_VAL, CREATE_FN) \
|
||||
TYPE CREATE_FN();
|
||||
|
||||
#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.
|
||||
|
@ -469,302 +355,7 @@ public:
|
|||
/// \sa CXXMemberInliningMode
|
||||
bool mayInlineCXXMemberFunction(CXXInlineableMemberKind K);
|
||||
|
||||
/// Returns true if ObjectiveC inlining is enabled, false otherwise.
|
||||
bool mayInlineObjCMethod();
|
||||
|
||||
/// Returns whether or not the destructors for C++ temporary objects should
|
||||
/// be included in the CFG.
|
||||
///
|
||||
/// This is controlled by the 'cfg-temporary-dtors' config option, which
|
||||
/// accepts the values "true" and "false".
|
||||
bool includeTemporaryDtorsInCFG();
|
||||
|
||||
/// Returns whether or not implicit destructors for C++ objects should
|
||||
/// be included in the CFG.
|
||||
///
|
||||
/// This is controlled by the 'cfg-implicit-dtors' config option, which
|
||||
/// accepts the values "true" and "false".
|
||||
bool includeImplicitDtorsInCFG();
|
||||
|
||||
/// Returns whether or not end-of-lifetime information should be included in
|
||||
/// the CFG.
|
||||
///
|
||||
/// This is controlled by the 'cfg-lifetime' config option, which accepts
|
||||
/// the values "true" and "false".
|
||||
bool includeLifetimeInCFG();
|
||||
|
||||
/// Returns whether or not the end of the loop information should be included
|
||||
/// in the CFG.
|
||||
///
|
||||
/// This is controlled by the 'cfg-loopexit' config option, which accepts
|
||||
/// the values "true" and "false".
|
||||
bool includeLoopExitInCFG();
|
||||
|
||||
/// Returns whether or not construction site information should be included
|
||||
/// in the CFG C++ constructor elements.
|
||||
///
|
||||
/// This is controlled by the 'cfg-rich-constructors' config options,
|
||||
/// which accepts the values "true" and "false".
|
||||
bool includeRichConstructorsInCFG();
|
||||
|
||||
/// Returns whether or not scope information should be included in the CFG.
|
||||
///
|
||||
/// This is controlled by the 'cfg-scope-info' config option, which accepts
|
||||
/// the values "true" and "false".
|
||||
bool includeScopesInCFG();
|
||||
|
||||
/// Returns whether or not C++ standard library functions may be considered
|
||||
/// for inlining.
|
||||
///
|
||||
/// This is controlled by the 'c++-stdlib-inlining' config option, which
|
||||
/// accepts the values "true" and "false".
|
||||
bool mayInlineCXXStandardLibrary();
|
||||
|
||||
/// Returns whether or not templated functions may be considered for inlining.
|
||||
///
|
||||
/// This is controlled by the 'c++-template-inlining' config option, which
|
||||
/// accepts the values "true" and "false".
|
||||
bool mayInlineTemplateFunctions();
|
||||
|
||||
/// Returns whether or not allocator call may be considered for inlining.
|
||||
///
|
||||
/// This is controlled by the 'c++-allocator-inlining' config option, which
|
||||
/// accepts the values "true" and "false".
|
||||
bool mayInlineCXXAllocator();
|
||||
|
||||
/// Returns whether or not methods of C++ container objects may be considered
|
||||
/// for inlining.
|
||||
///
|
||||
/// This is controlled by the 'c++-container-inlining' config option, which
|
||||
/// accepts the values "true" and "false".
|
||||
bool mayInlineCXXContainerMethods();
|
||||
|
||||
/// Returns 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".
|
||||
///
|
||||
/// This is controlled by the 'c++-shared_ptr-inlining' config option, which
|
||||
/// accepts the values "true" and "false".
|
||||
bool mayInlineCXXSharedPtrDtor();
|
||||
|
||||
/// Returns true if 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.
|
||||
///
|
||||
/// This is controlled by the 'c++-temp-dtor-inlining' config option, which
|
||||
/// accepts the values "true" and "false".
|
||||
bool mayInlineCXXTemporaryDtors();
|
||||
|
||||
/// Returns 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.
|
||||
///
|
||||
/// This is controlled by the 'suppress-null-return-paths' config option,
|
||||
/// which accepts the values "true" and "false".
|
||||
bool shouldSuppressNullReturnPaths();
|
||||
|
||||
/// Returns whether a bug report should \em 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 counter-heuristic to avoid false negatives.
|
||||
///
|
||||
/// This is controlled by the 'avoid-suppressing-null-argument-paths' config
|
||||
/// option, which accepts the values "true" and "false".
|
||||
bool shouldAvoidSuppressingNullArgumentPaths();
|
||||
|
||||
/// Returns whether or not diagnostics containing inlined defensive NULL
|
||||
/// checks should be suppressed.
|
||||
///
|
||||
/// This is controlled by the 'suppress-inlined-defensive-checks' config
|
||||
/// option, which accepts the values "true" and "false".
|
||||
bool shouldSuppressInlinedDefensiveChecks();
|
||||
|
||||
/// Returns whether or not diagnostics reported within the C++ standard
|
||||
/// library should be suppressed.
|
||||
///
|
||||
/// This is controlled by the 'suppress-c++-stdlib' config option,
|
||||
/// which accepts the values "true" and "false".
|
||||
bool shouldSuppressFromCXXStandardLibrary();
|
||||
|
||||
/// Returns whether bug reports should be crosschecked with the Z3
|
||||
/// constraint manager backend.
|
||||
///
|
||||
/// This is controlled by the 'crosscheck-with-z3' config option,
|
||||
/// which accepts the values "true" and "false".
|
||||
bool shouldCrosscheckWithZ3();
|
||||
|
||||
/// Returns whether or not the diagnostic report should be always reported
|
||||
/// in the main source file and not the headers.
|
||||
///
|
||||
/// This is controlled by the 'report-in-main-source-file' config option,
|
||||
/// which accepts the values "true" and "false".
|
||||
bool shouldReportIssuesInMainSourceFile();
|
||||
|
||||
/// Returns whether or not the report filename should be random or not.
|
||||
///
|
||||
/// This is controlled by the 'stable-report-filename' config option,
|
||||
/// which accepts the values "true" and "false". Default = false
|
||||
bool shouldWriteStableReportFilename();
|
||||
|
||||
/// \return Whether the analyzer should
|
||||
/// serialize statistics to plist output.
|
||||
/// Statistics would be serialized in JSON format inside the main dictionary
|
||||
/// under the \c statistics key.
|
||||
/// Available only if compiled in assert mode or with LLVM statistics
|
||||
/// explicitly enabled.
|
||||
bool shouldSerializeStats();
|
||||
|
||||
/// Returns whether irrelevant parts of a bug report path should be pruned
|
||||
/// out of the final output.
|
||||
///
|
||||
/// This is controlled by the 'prune-paths' config option, which accepts the
|
||||
/// values "true" and "false".
|
||||
bool shouldPrunePaths();
|
||||
|
||||
/// Returns true if 'static' initializers should be in conditional logic
|
||||
/// in the CFG.
|
||||
bool shouldConditionalizeStaticInitializers();
|
||||
|
||||
// Returns the size of the functions (in basic blocks), which should be
|
||||
// considered to be small enough to always inline.
|
||||
//
|
||||
// This is controlled by "ipa-always-inline-size" analyzer-config option.
|
||||
unsigned getAlwaysInlineSize();
|
||||
|
||||
// Returns the bound on the number of basic blocks in an inlined function
|
||||
// (50 by default).
|
||||
//
|
||||
// This is controlled by "-analyzer-config max-inlinable-size" option.
|
||||
unsigned getMaxInlinableSize();
|
||||
|
||||
/// Returns true if the analyzer engine should synthesize fake bodies
|
||||
/// for well-known functions.
|
||||
bool shouldSynthesizeBodies();
|
||||
|
||||
/// Returns how often nodes in the ExplodedGraph should be recycled to save
|
||||
/// memory.
|
||||
///
|
||||
/// This is controlled by the 'graph-trim-interval' config option. To disable
|
||||
/// node reclamation, set the option to "0".
|
||||
unsigned getGraphTrimInterval();
|
||||
|
||||
/// Returns the maximum complexity of symbolic constraint (50 by default).
|
||||
///
|
||||
/// This is controlled by "-analyzer-config max-symbol-complexity" option.
|
||||
unsigned getMaxSymbolComplexity();
|
||||
|
||||
/// Returns the maximum times a large function could be inlined.
|
||||
///
|
||||
/// This is controlled by the 'max-times-inline-large' config option.
|
||||
unsigned getMaxTimesInlineLarge();
|
||||
|
||||
/// Returns the number of basic blocks a function needs to have to be
|
||||
/// considered large for the 'max-times-inline-large' config option.
|
||||
///
|
||||
/// This is controlled by the 'min-cfg-size-treat-functions-as-large' config
|
||||
/// option.
|
||||
unsigned getMinCFGSizeTreatFunctionsAsLarge();
|
||||
|
||||
/// Returns the maximum number of nodes the analyzer can generate while
|
||||
/// exploring a top level function (for each exploded graph).
|
||||
/// 150000 is default; 0 means no limit.
|
||||
///
|
||||
/// This is controlled by the 'max-nodes' config option.
|
||||
unsigned getMaxNodesPerTopLevelFunction();
|
||||
|
||||
/// Returns true if lambdas should be inlined. Otherwise a sink node will be
|
||||
/// generated each time a LambdaExpr is visited.
|
||||
bool shouldInlineLambdas();
|
||||
|
||||
/// Returns true if the analysis should try to widen loops.
|
||||
/// This is controlled by the 'widen-loops' config option.
|
||||
bool shouldWidenLoops();
|
||||
|
||||
/// Returns true if the analysis should try to unroll loops with known bounds.
|
||||
/// This is controlled by the 'unroll-loops' config option.
|
||||
bool shouldUnrollLoops();
|
||||
|
||||
/// Returns true if 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.
|
||||
///
|
||||
/// This is controlled by the 'extra-notes-as-events' option, which defaults
|
||||
/// to false when unset.
|
||||
bool shouldDisplayNotesAsEvents();
|
||||
|
||||
/// Returns true if macros related to the bugpath should be expanded and
|
||||
/// included in the plist output.
|
||||
///
|
||||
/// This is controlled by the 'expand-macros' option, which defaults to false
|
||||
/// when unset.
|
||||
bool shouldDisplayMacroExpansions();
|
||||
|
||||
/// Returns true if SValBuilder should rearrange comparisons and additive
|
||||
/// operations of symbolic expressions which consist of a sum of a symbol and
|
||||
/// a concrete integer into the format where symbols are on the left-hand
|
||||
/// side and the integer is on the right. This is only done if both symbols
|
||||
/// and both concrete integers are signed, greater than or equal to the
|
||||
/// quarter of the minimum value of the type and less than or equal to the
|
||||
/// quarter of the maximum value of that type.
|
||||
///
|
||||
/// A + n <OP> B + m becomes A - B <OP> m - n, where A and B symbolic,
|
||||
/// n and m are integers. <OP> is any of '==', '!=', '<', '<=', '>', '>=',
|
||||
/// '+' or '-'. The rearrangement also happens with '-' instead of '+' on
|
||||
// either or both side and also if any or both integers are missing.
|
||||
bool shouldAggressivelySimplifyBinaryOperation();
|
||||
|
||||
/// Returns true if 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 subexpression 'y != 0' will be
|
||||
/// eagerly assumed to be true or false, thus evaluating it to the integers 0
|
||||
/// or 1 respectively. The upside is that this can increase analysis
|
||||
/// precision until we have a better way to lazily evaluate such logic. The
|
||||
/// downside is that it eagerly bifurcates paths.
|
||||
bool shouldEagerlyAssume();
|
||||
|
||||
/// Returns the directory containing the CTU related files.
|
||||
StringRef getCTUDir();
|
||||
|
||||
/// Returns the name of the file containing the CTU index of functions.
|
||||
StringRef getCTUIndexName();
|
||||
|
||||
/// Returns true when naive cross translation unit analysis is enabled.
|
||||
/// This is an experimental feature to inline functions from another
|
||||
/// translation units.
|
||||
bool naiveCTUEnabled();
|
||||
|
||||
/// Returns true if 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.
|
||||
bool shouldElideConstructors();
|
||||
|
||||
/// 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.
|
||||
///
|
||||
/// This is controlled by 'region-store-small-struct-limit' option.
|
||||
/// To disable all small-struct-dependent behavior, set the option to "0".
|
||||
unsigned getRegionStoreSmallStructLimit();
|
||||
|
||||
/// 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)
|
||||
StringRef getModelPath();
|
||||
};
|
||||
|
||||
using AnalyzerOptionsRef = IntrusiveRefCntPtr<AnalyzerOptions>;
|
||||
|
|
|
@ -49,91 +49,87 @@ AnalyzerOptions::getRegisteredCheckers(bool IncludeExperimental /* = false */) {
|
|||
return Result;
|
||||
}
|
||||
|
||||
AnalyzerOptions::UserModeKind AnalyzerOptions::getUserMode() {
|
||||
UserModeKind AnalyzerOptions::getUserMode() {
|
||||
if (!UserMode.hasValue()) {
|
||||
StringRef ModeStr = getOptionAsString("mode", "deep");
|
||||
UserMode = llvm::StringSwitch<llvm::Optional<UserModeKind>>(ModeStr)
|
||||
.Case("shallow", UMK_Shallow)
|
||||
.Case("deep", UMK_Deep)
|
||||
.Default(None);
|
||||
assert(UserMode.getValue() && "User mode is invalid.");
|
||||
UserMode = getOptionAsString("mode", "deep");
|
||||
}
|
||||
return UserMode.getValue();
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
AnalyzerOptions::ExplorationStrategyKind
|
||||
ExplorationStrategyKind
|
||||
AnalyzerOptions::getExplorationStrategy() {
|
||||
if (!ExplorationStrategy.hasValue()) {
|
||||
StringRef StratStr = getOptionAsString("exploration_strategy",
|
||||
"unexplored_first_queue");
|
||||
ExplorationStrategy =
|
||||
llvm::StringSwitch<llvm::Optional<ExplorationStrategyKind>>(StratStr)
|
||||
.Case("dfs", ExplorationStrategyKind::DFS)
|
||||
.Case("bfs", ExplorationStrategyKind::BFS)
|
||||
.Case("unexplored_first",
|
||||
ExplorationStrategyKind::UnexploredFirst)
|
||||
.Case("unexplored_first_queue",
|
||||
ExplorationStrategyKind::UnexploredFirstQueue)
|
||||
.Case("unexplored_first_location_queue",
|
||||
ExplorationStrategyKind::UnexploredFirstLocationQueue)
|
||||
.Case("bfs_block_dfs_contents",
|
||||
ExplorationStrategyKind::BFSBlockDFSContents)
|
||||
.Default(None);
|
||||
assert(ExplorationStrategy.hasValue() &&
|
||||
"User mode is invalid.");
|
||||
ExplorationStrategy = getOptionAsString("exploration_strategy",
|
||||
"unexplored_first_queue");
|
||||
}
|
||||
return ExplorationStrategy.getValue();
|
||||
auto K =
|
||||
llvm::StringSwitch<llvm::Optional<ExplorationStrategyKind>>(
|
||||
*ExplorationStrategy)
|
||||
.Case("dfs", ExplorationStrategyKind::DFS)
|
||||
.Case("bfs", ExplorationStrategyKind::BFS)
|
||||
.Case("unexplored_first",
|
||||
ExplorationStrategyKind::UnexploredFirst)
|
||||
.Case("unexplored_first_queue",
|
||||
ExplorationStrategyKind::UnexploredFirstQueue)
|
||||
.Case("unexplored_first_location_queue",
|
||||
ExplorationStrategyKind::UnexploredFirstLocationQueue)
|
||||
.Case("bfs_block_dfs_contents",
|
||||
ExplorationStrategyKind::BFSBlockDFSContents)
|
||||
.Default(None);
|
||||
assert(K.hasValue() && "User mode is invalid.");
|
||||
return K.getValue();
|
||||
}
|
||||
|
||||
IPAKind AnalyzerOptions::getIPAMode() {
|
||||
if (!IPAMode.hasValue()) {
|
||||
// Use the User Mode to set the default IPA value.
|
||||
// Note, we have to add the string to the Config map for the ConfigDumper
|
||||
// checker to function properly.
|
||||
const char *DefaultIPA = nullptr;
|
||||
UserModeKind HighLevelMode = getUserMode();
|
||||
if (HighLevelMode == UMK_Shallow)
|
||||
DefaultIPA = "inlining";
|
||||
else if (HighLevelMode == UMK_Deep)
|
||||
DefaultIPA = "dynamic-bifurcate";
|
||||
assert(DefaultIPA);
|
||||
|
||||
// Lookup the ipa configuration option, use the default from User Mode.
|
||||
StringRef ModeStr = getOptionAsString("ipa", DefaultIPA);
|
||||
IPAMode = llvm::StringSwitch<llvm::Optional<IPAKind>>(ModeStr)
|
||||
.Case("none", IPAK_None)
|
||||
.Case("basic-inlining", IPAK_BasicInlining)
|
||||
.Case("inlining", IPAK_Inlining)
|
||||
.Case("dynamic", IPAK_DynamicDispatch)
|
||||
.Case("dynamic-bifurcate", IPAK_DynamicDispatchBifurcate)
|
||||
.Default(None);
|
||||
assert(IPAMode.hasValue() && "IPA Mode is invalid.");
|
||||
switch (getUserMode()) {
|
||||
case UMK_Shallow:
|
||||
IPAMode = getOptionAsString("ipa", "inlining");
|
||||
break;
|
||||
case UMK_Deep:
|
||||
IPAMode = getOptionAsString("ipa", "dynamic-bifurcate");
|
||||
break;
|
||||
}
|
||||
}
|
||||
auto K = llvm::StringSwitch<llvm::Optional<IPAKind>>(*IPAMode)
|
||||
.Case("none", IPAK_None)
|
||||
.Case("basic-inlining", IPAK_BasicInlining)
|
||||
.Case("inlining", IPAK_Inlining)
|
||||
.Case("dynamic", IPAK_DynamicDispatch)
|
||||
.Case("dynamic-bifurcate", IPAK_DynamicDispatchBifurcate)
|
||||
.Default(None);
|
||||
assert(K.hasValue() && "IPA Mode is invalid.");
|
||||
|
||||
return IPAMode.getValue();
|
||||
return K.getValue();
|
||||
}
|
||||
|
||||
bool
|
||||
AnalyzerOptions::mayInlineCXXMemberFunction(CXXInlineableMemberKind K) {
|
||||
AnalyzerOptions::mayInlineCXXMemberFunction(CXXInlineableMemberKind Param) {
|
||||
if (!CXXMemberInliningMode.hasValue()) {
|
||||
CXXMemberInliningMode = getOptionAsString("c++-inlining", "destructors");
|
||||
}
|
||||
|
||||
if (getIPAMode() < IPAK_Inlining)
|
||||
return false;
|
||||
|
||||
if (!CXXMemberInliningMode) {
|
||||
StringRef ModeStr = getOptionAsString("c++-inlining", "destructors");
|
||||
auto K =
|
||||
llvm::StringSwitch<llvm::Optional<CXXInlineableMemberKind>>(
|
||||
*CXXMemberInliningMode)
|
||||
.Case("constructors", CIMK_Constructors)
|
||||
.Case("destructors", CIMK_Destructors)
|
||||
.Case("methods", CIMK_MemberFunctions)
|
||||
.Case("none", CIMK_None)
|
||||
.Default(None);
|
||||
|
||||
CXXMemberInliningMode =
|
||||
llvm::StringSwitch<llvm::Optional<CXXInlineableMemberKind>>(ModeStr)
|
||||
.Case("constructors", CIMK_Constructors)
|
||||
.Case("destructors", CIMK_Destructors)
|
||||
.Case("methods", CIMK_MemberFunctions)
|
||||
.Case("none", CIMK_None)
|
||||
.Default(None);
|
||||
assert(K.hasValue() && "Invalid c++ member function inlining mode.");
|
||||
|
||||
assert(CXXMemberInliningMode.hasValue() &&
|
||||
"Invalid c++ member function inlining mode.");
|
||||
}
|
||||
|
||||
return *CXXMemberInliningMode >= K;
|
||||
return *K >= Param;
|
||||
}
|
||||
|
||||
static StringRef toString(bool b) { return b ? "true" : "false"; }
|
||||
|
@ -183,137 +179,6 @@ bool AnalyzerOptions::getBooleanOption(Optional<bool> &V, StringRef Name,
|
|||
return V.getValue();
|
||||
}
|
||||
|
||||
bool AnalyzerOptions::includeTemporaryDtorsInCFG() {
|
||||
return getBooleanOption(IncludeTemporaryDtorsInCFG,
|
||||
"cfg-temporary-dtors",
|
||||
/* Default = */ true);
|
||||
}
|
||||
|
||||
bool AnalyzerOptions::includeImplicitDtorsInCFG() {
|
||||
return getBooleanOption(IncludeImplicitDtorsInCFG,
|
||||
"cfg-implicit-dtors",
|
||||
/* Default = */ true);
|
||||
}
|
||||
|
||||
bool AnalyzerOptions::includeLifetimeInCFG() {
|
||||
return getBooleanOption(IncludeLifetimeInCFG, "cfg-lifetime",
|
||||
/* Default = */ false);
|
||||
}
|
||||
|
||||
bool AnalyzerOptions::includeLoopExitInCFG() {
|
||||
return getBooleanOption(IncludeLoopExitInCFG, "cfg-loopexit",
|
||||
/* Default = */ false);
|
||||
}
|
||||
|
||||
bool AnalyzerOptions::includeRichConstructorsInCFG() {
|
||||
return getBooleanOption(IncludeRichConstructorsInCFG,
|
||||
"cfg-rich-constructors",
|
||||
/* Default = */ true);
|
||||
}
|
||||
|
||||
bool AnalyzerOptions::includeScopesInCFG() {
|
||||
return getBooleanOption(IncludeScopesInCFG,
|
||||
"cfg-scopes",
|
||||
/* Default = */ false);
|
||||
}
|
||||
|
||||
bool AnalyzerOptions::mayInlineCXXStandardLibrary() {
|
||||
return getBooleanOption(InlineCXXStandardLibrary,
|
||||
"c++-stdlib-inlining",
|
||||
/*Default=*/true);
|
||||
}
|
||||
|
||||
bool AnalyzerOptions::mayInlineTemplateFunctions() {
|
||||
return getBooleanOption(InlineTemplateFunctions,
|
||||
"c++-template-inlining",
|
||||
/*Default=*/true);
|
||||
}
|
||||
|
||||
bool AnalyzerOptions::mayInlineCXXAllocator() {
|
||||
return getBooleanOption(InlineCXXAllocator,
|
||||
"c++-allocator-inlining",
|
||||
/*Default=*/true);
|
||||
}
|
||||
|
||||
bool AnalyzerOptions::mayInlineCXXContainerMethods() {
|
||||
return getBooleanOption(InlineCXXContainerMethods,
|
||||
"c++-container-inlining",
|
||||
/*Default=*/false);
|
||||
}
|
||||
|
||||
bool AnalyzerOptions::mayInlineCXXSharedPtrDtor() {
|
||||
return getBooleanOption(InlineCXXSharedPtrDtor,
|
||||
"c++-shared_ptr-inlining",
|
||||
/*Default=*/false);
|
||||
}
|
||||
|
||||
bool AnalyzerOptions::mayInlineCXXTemporaryDtors() {
|
||||
return getBooleanOption(InlineCXXTemporaryDtors,
|
||||
"c++-temp-dtor-inlining",
|
||||
/*Default=*/true);
|
||||
}
|
||||
|
||||
bool AnalyzerOptions::mayInlineObjCMethod() {
|
||||
return getBooleanOption(ObjCInliningMode,
|
||||
"objc-inlining",
|
||||
/* Default = */ true);
|
||||
}
|
||||
|
||||
bool AnalyzerOptions::shouldSuppressNullReturnPaths() {
|
||||
return getBooleanOption(SuppressNullReturnPaths,
|
||||
"suppress-null-return-paths",
|
||||
/* Default = */ true);
|
||||
}
|
||||
|
||||
bool AnalyzerOptions::shouldAvoidSuppressingNullArgumentPaths() {
|
||||
return getBooleanOption(AvoidSuppressingNullArgumentPaths,
|
||||
"avoid-suppressing-null-argument-paths",
|
||||
/* Default = */ false);
|
||||
}
|
||||
|
||||
bool AnalyzerOptions::shouldSuppressInlinedDefensiveChecks() {
|
||||
return getBooleanOption(SuppressInlinedDefensiveChecks,
|
||||
"suppress-inlined-defensive-checks",
|
||||
/* Default = */ true);
|
||||
}
|
||||
|
||||
bool AnalyzerOptions::shouldSuppressFromCXXStandardLibrary() {
|
||||
return getBooleanOption(SuppressFromCXXStandardLibrary,
|
||||
"suppress-c++-stdlib",
|
||||
/* Default = */ true);
|
||||
}
|
||||
|
||||
bool AnalyzerOptions::shouldCrosscheckWithZ3() {
|
||||
return getBooleanOption(CrosscheckWithZ3,
|
||||
"crosscheck-with-z3",
|
||||
/* Default = */ false);
|
||||
}
|
||||
|
||||
bool AnalyzerOptions::shouldReportIssuesInMainSourceFile() {
|
||||
return getBooleanOption(ReportIssuesInMainSourceFile,
|
||||
"report-in-main-source-file",
|
||||
/* Default = */ false);
|
||||
}
|
||||
|
||||
|
||||
bool AnalyzerOptions::shouldWriteStableReportFilename() {
|
||||
return getBooleanOption(StableReportFilename,
|
||||
"stable-report-filename",
|
||||
/* Default = */ false);
|
||||
}
|
||||
|
||||
bool AnalyzerOptions::shouldSerializeStats() {
|
||||
return getBooleanOption(SerializeStats,
|
||||
"serialize-stats",
|
||||
/* Default = */ false);
|
||||
}
|
||||
|
||||
bool AnalyzerOptions::shouldElideConstructors() {
|
||||
return getBooleanOption(ElideConstructors,
|
||||
"elide-constructors",
|
||||
/* Default = */ true);
|
||||
}
|
||||
|
||||
int AnalyzerOptions::getOptionAsInteger(StringRef Name, int DefaultVal,
|
||||
const CheckerBase *C,
|
||||
bool SearchInParents) {
|
||||
|
@ -361,130 +226,45 @@ StringRef AnalyzerOptions::getOptionAsString(Optional<StringRef> &V,
|
|||
return V.getValue();
|
||||
}
|
||||
|
||||
unsigned AnalyzerOptions::getAlwaysInlineSize() {
|
||||
if (!AlwaysInlineSize.hasValue())
|
||||
AlwaysInlineSize = getOptionAsInteger("ipa-always-inline-size", 3);
|
||||
return AlwaysInlineSize.getValue();
|
||||
static bool getOption(AnalyzerOptions &A, Optional<bool> &V, StringRef Name,
|
||||
bool DefaultVal) {
|
||||
return A.getBooleanOption(V, Name, DefaultVal);
|
||||
}
|
||||
|
||||
unsigned AnalyzerOptions::getMaxInlinableSize() {
|
||||
if (!MaxInlinableSize.hasValue()) {
|
||||
int DefaultValue = 0;
|
||||
UserModeKind HighLevelMode = getUserMode();
|
||||
switch (HighLevelMode) {
|
||||
case UMK_Shallow:
|
||||
DefaultValue = 4;
|
||||
break;
|
||||
case UMK_Deep:
|
||||
DefaultValue = 100;
|
||||
break;
|
||||
}
|
||||
|
||||
MaxInlinableSize = getOptionAsInteger("max-inlinable-size", DefaultValue);
|
||||
}
|
||||
return MaxInlinableSize.getValue();
|
||||
static unsigned getOption(AnalyzerOptions &A, Optional<unsigned> &V,
|
||||
StringRef Name, unsigned DefaultVal) {
|
||||
return A.getOptionAsUInt(V, Name, DefaultVal);
|
||||
}
|
||||
|
||||
unsigned AnalyzerOptions::getGraphTrimInterval() {
|
||||
if (!GraphTrimInterval.hasValue())
|
||||
GraphTrimInterval = getOptionAsInteger("graph-trim-interval", 1000);
|
||||
return GraphTrimInterval.getValue();
|
||||
static StringRef getOption(AnalyzerOptions &A, Optional<StringRef> &V,
|
||||
StringRef Name, StringRef DefaultVal) {
|
||||
return A.getOptionAsString(V, Name, DefaultVal);
|
||||
}
|
||||
|
||||
unsigned AnalyzerOptions::getMaxSymbolComplexity() {
|
||||
if (!MaxSymbolComplexity.hasValue())
|
||||
MaxSymbolComplexity = getOptionAsInteger("max-symbol-complexity", 35);
|
||||
return MaxSymbolComplexity.getValue();
|
||||
#define ANALYZER_OPTION_GEN_FN(TYPE, NAME, CMDFLAG, DESC, DEFAULT_VAL, \
|
||||
CREATE_FN) \
|
||||
TYPE AnalyzerOptions::CREATE_FN() { \
|
||||
return getOption(*this, NAME, CMDFLAG, DEFAULT_VAL); \
|
||||
}
|
||||
|
||||
unsigned AnalyzerOptions::getMaxTimesInlineLarge() {
|
||||
if (!MaxTimesInlineLarge.hasValue())
|
||||
MaxTimesInlineLarge = getOptionAsInteger("max-times-inline-large", 32);
|
||||
return MaxTimesInlineLarge.getValue();
|
||||
#define ANALYZER_OPTION_GEN_FN_DEPENDS_ON_USER_MODE( \
|
||||
TYPE, NAME, CMDFLAG, DESC, SHALLOW_VAL, DEEP_VAL, CREATE_FN) \
|
||||
TYPE AnalyzerOptions::CREATE_FN() { \
|
||||
switch (getUserMode()) { \
|
||||
case UMK_Shallow: \
|
||||
return getOption(*this, NAME, CMDFLAG, SHALLOW_VAL); \
|
||||
case UMK_Deep: \
|
||||
return getOption(*this, NAME, CMDFLAG, DEEP_VAL); \
|
||||
} \
|
||||
\
|
||||
llvm_unreachable("Unknown usermode!"); \
|
||||
return {}; \
|
||||
}
|
||||
|
||||
unsigned AnalyzerOptions::getMinCFGSizeTreatFunctionsAsLarge() {
|
||||
if (!MinCFGSizeTreatFunctionsAsLarge.hasValue())
|
||||
MinCFGSizeTreatFunctionsAsLarge = getOptionAsInteger(
|
||||
"min-cfg-size-treat-functions-as-large", 14);
|
||||
return MinCFGSizeTreatFunctionsAsLarge.getValue();
|
||||
}
|
||||
#include "clang/StaticAnalyzer/Core/AnalyzerOptions.def"
|
||||
|
||||
unsigned AnalyzerOptions::getMaxNodesPerTopLevelFunction() {
|
||||
if (!MaxNodesPerTopLevelFunction.hasValue()) {
|
||||
int DefaultValue = 0;
|
||||
UserModeKind HighLevelMode = getUserMode();
|
||||
switch (HighLevelMode) {
|
||||
case UMK_Shallow:
|
||||
DefaultValue = 75000;
|
||||
break;
|
||||
case UMK_Deep:
|
||||
DefaultValue = 225000;
|
||||
break;
|
||||
}
|
||||
MaxNodesPerTopLevelFunction = getOptionAsInteger("max-nodes", DefaultValue);
|
||||
}
|
||||
return MaxNodesPerTopLevelFunction.getValue();
|
||||
}
|
||||
|
||||
bool AnalyzerOptions::shouldSynthesizeBodies() {
|
||||
return getBooleanOption("faux-bodies", true);
|
||||
}
|
||||
|
||||
bool AnalyzerOptions::shouldPrunePaths() {
|
||||
return getBooleanOption("prune-paths", true);
|
||||
}
|
||||
|
||||
bool AnalyzerOptions::shouldConditionalizeStaticInitializers() {
|
||||
return getBooleanOption("cfg-conditional-static-initializers", true);
|
||||
}
|
||||
|
||||
bool AnalyzerOptions::shouldInlineLambdas() {
|
||||
if (!InlineLambdas.hasValue())
|
||||
InlineLambdas = getBooleanOption("inline-lambdas", /*Default=*/true);
|
||||
return InlineLambdas.getValue();
|
||||
}
|
||||
|
||||
bool AnalyzerOptions::shouldWidenLoops() {
|
||||
if (!WidenLoops.hasValue())
|
||||
WidenLoops = getBooleanOption("widen-loops", /*Default=*/false);
|
||||
return WidenLoops.getValue();
|
||||
}
|
||||
|
||||
bool AnalyzerOptions::shouldUnrollLoops() {
|
||||
if (!UnrollLoops.hasValue())
|
||||
UnrollLoops = getBooleanOption("unroll-loops", /*Default=*/false);
|
||||
return UnrollLoops.getValue();
|
||||
}
|
||||
|
||||
bool AnalyzerOptions::shouldDisplayNotesAsEvents() {
|
||||
if (!DisplayNotesAsEvents.hasValue())
|
||||
DisplayNotesAsEvents =
|
||||
getBooleanOption("notes-as-events", /*Default=*/false);
|
||||
return DisplayNotesAsEvents.getValue();
|
||||
}
|
||||
|
||||
bool AnalyzerOptions::shouldDisplayMacroExpansions() {
|
||||
if (!DisplayMacroExpansions.hasValue())
|
||||
DisplayMacroExpansions =
|
||||
getBooleanOption("expand-macros", /*Default=*/false);
|
||||
return DisplayMacroExpansions.getValue();
|
||||
}
|
||||
|
||||
bool AnalyzerOptions::shouldAggressivelySimplifyBinaryOperation() {
|
||||
if (!AggressiveBinaryOperationSimplification.hasValue())
|
||||
AggressiveBinaryOperationSimplification =
|
||||
getBooleanOption("aggressive-binary-operation-simplification",
|
||||
/*Default=*/false);
|
||||
return AggressiveBinaryOperationSimplification.getValue();
|
||||
}
|
||||
|
||||
bool AnalyzerOptions::shouldEagerlyAssume() {
|
||||
if (!EagerlyAssumeBinOpBifurcation.hasValue())
|
||||
EagerlyAssumeBinOpBifurcation =
|
||||
getBooleanOption("eagerly-assume", true);
|
||||
return EagerlyAssumeBinOpBifurcation.getValue();
|
||||
}
|
||||
#undef ANALYZER_OPTION_GEN_FN_DEPENDS_ON_USER_MODE
|
||||
#undef ANALYZER_OPTION_WITH_FN
|
||||
|
||||
StringRef AnalyzerOptions::getCTUDir() {
|
||||
if (!CTUDir.hasValue()) {
|
||||
|
@ -494,30 +274,3 @@ StringRef AnalyzerOptions::getCTUDir() {
|
|||
}
|
||||
return CTUDir.getValue();
|
||||
}
|
||||
|
||||
bool AnalyzerOptions::naiveCTUEnabled() {
|
||||
if (!NaiveCTU.hasValue()) {
|
||||
NaiveCTU = getBooleanOption("experimental-enable-naive-ctu-analysis",
|
||||
/*Default=*/false);
|
||||
}
|
||||
return NaiveCTU.getValue();
|
||||
}
|
||||
|
||||
unsigned AnalyzerOptions::getRegionStoreSmallStructLimit() {
|
||||
if (!RegionStoreSmallStructLimit.hasValue())
|
||||
RegionStoreSmallStructLimit =
|
||||
getOptionAsInteger("region-store-small-struct-limit", 2);
|
||||
return RegionStoreSmallStructLimit.getValue();
|
||||
}
|
||||
|
||||
StringRef AnalyzerOptions::getCTUIndexName() {
|
||||
if (!CTUIndexName.hasValue())
|
||||
CTUIndexName = getOptionAsString("ctu-index-name", "externalFnMap.txt");
|
||||
return CTUIndexName.getValue();
|
||||
}
|
||||
|
||||
StringRef AnalyzerOptions::getModelPath() {
|
||||
if (!ModelPath.hasValue())
|
||||
ModelPath = getOptionAsString("model-path", "");
|
||||
return ModelPath.getValue();
|
||||
}
|
||||
|
|
|
@ -56,17 +56,17 @@ STATISTIC(NumPathsExplored,
|
|||
static std::unique_ptr<WorkList> generateWorkList(AnalyzerOptions &Opts,
|
||||
SubEngine &subengine) {
|
||||
switch (Opts.getExplorationStrategy()) {
|
||||
case AnalyzerOptions::ExplorationStrategyKind::DFS:
|
||||
case ExplorationStrategyKind::DFS:
|
||||
return WorkList::makeDFS();
|
||||
case AnalyzerOptions::ExplorationStrategyKind::BFS:
|
||||
case ExplorationStrategyKind::BFS:
|
||||
return WorkList::makeBFS();
|
||||
case AnalyzerOptions::ExplorationStrategyKind::BFSBlockDFSContents:
|
||||
case ExplorationStrategyKind::BFSBlockDFSContents:
|
||||
return WorkList::makeBFSBlockDFSContents();
|
||||
case AnalyzerOptions::ExplorationStrategyKind::UnexploredFirst:
|
||||
case ExplorationStrategyKind::UnexploredFirst:
|
||||
return WorkList::makeUnexploredFirst();
|
||||
case AnalyzerOptions::ExplorationStrategyKind::UnexploredFirstQueue:
|
||||
case ExplorationStrategyKind::UnexploredFirstQueue:
|
||||
return WorkList::makeUnexploredFirstPriorityQueue();
|
||||
case AnalyzerOptions::ExplorationStrategyKind::UnexploredFirstLocationQueue:
|
||||
case ExplorationStrategyKind::UnexploredFirstLocationQueue:
|
||||
return WorkList::makeUnexploredFirstPriorityLocationQueue();
|
||||
}
|
||||
llvm_unreachable("Unknown AnalyzerOptions::ExplorationStrategyKind");
|
||||
|
|
Loading…
Reference in New Issue