2018-03-07 08:17:48 +08:00
|
|
|
//===- AnalyzerOptions.cpp - Analysis Engine Options ----------------------===//
|
2012-09-01 01:06:49 +08:00
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
// This file contains special accessors for analyzer configuration options
|
|
|
|
// with string representations.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "clang/StaticAnalyzer/Core/AnalyzerOptions.h"
|
2015-03-05 01:59:34 +08:00
|
|
|
#include "clang/StaticAnalyzer/Core/Checker.h"
|
2012-10-03 04:31:56 +08:00
|
|
|
#include "llvm/ADT/SmallString.h"
|
2012-12-04 17:13:33 +08:00
|
|
|
#include "llvm/ADT/StringSwitch.h"
|
2018-03-07 08:17:48 +08:00
|
|
|
#include "llvm/ADT/StringRef.h"
|
|
|
|
#include "llvm/ADT/Twine.h"
|
2013-01-31 03:12:39 +08:00
|
|
|
#include "llvm/Support/ErrorHandling.h"
|
2018-03-07 08:17:48 +08:00
|
|
|
#include "llvm/Support/FileSystem.h"
|
2012-10-03 04:31:56 +08:00
|
|
|
#include "llvm/Support/raw_ostream.h"
|
2018-03-07 08:17:48 +08:00
|
|
|
#include <cassert>
|
|
|
|
#include <cstddef>
|
|
|
|
#include <utility>
|
|
|
|
#include <vector>
|
2012-09-01 01:06:49 +08:00
|
|
|
|
|
|
|
using namespace clang;
|
2015-03-05 01:59:34 +08:00
|
|
|
using namespace ento;
|
2012-09-11 06:37:19 +08:00
|
|
|
using namespace llvm;
|
2012-09-01 01:06:49 +08:00
|
|
|
|
2016-11-08 15:23:32 +08:00
|
|
|
std::vector<StringRef>
|
|
|
|
AnalyzerOptions::getRegisteredCheckers(bool IncludeExperimental /* = false */) {
|
|
|
|
static const StringRef StaticAnalyzerChecks[] = {
|
|
|
|
#define GET_CHECKERS
|
|
|
|
#define CHECKER(FULLNAME, CLASS, DESCFILE, HELPTEXT, GROUPINDEX, HIDDEN) \
|
|
|
|
FULLNAME,
|
|
|
|
#include "clang/StaticAnalyzer/Checkers/Checkers.inc"
|
|
|
|
#undef CHECKER
|
|
|
|
#undef GET_CHECKERS
|
|
|
|
};
|
|
|
|
std::vector<StringRef> Result;
|
|
|
|
for (StringRef CheckName : StaticAnalyzerChecks) {
|
|
|
|
if (!CheckName.startswith("debug.") &&
|
|
|
|
(IncludeExperimental || !CheckName.startswith("alpha.")))
|
|
|
|
Result.push_back(CheckName);
|
|
|
|
}
|
|
|
|
return Result;
|
|
|
|
}
|
|
|
|
|
2013-01-25 07:15:34 +08:00
|
|
|
AnalyzerOptions::UserModeKind AnalyzerOptions::getUserMode() {
|
2018-10-22 02:19:32 +08:00
|
|
|
if (!UserMode.hasValue()) {
|
|
|
|
StringRef ModeStr = getOptionAsString("mode", "deep");
|
|
|
|
UserMode = llvm::StringSwitch<llvm::Optional<UserModeKind>>(ModeStr)
|
2013-01-25 07:15:34 +08:00
|
|
|
.Case("shallow", UMK_Shallow)
|
|
|
|
.Case("deep", UMK_Deep)
|
2018-10-22 02:19:32 +08:00
|
|
|
.Default(None);
|
|
|
|
assert(UserMode.getValue() && "User mode is invalid.");
|
2013-01-25 07:15:34 +08:00
|
|
|
}
|
2018-10-22 02:19:32 +08:00
|
|
|
return UserMode.getValue();
|
2013-01-25 07:15:34 +08:00
|
|
|
}
|
|
|
|
|
2018-02-02 10:01:55 +08:00
|
|
|
AnalyzerOptions::ExplorationStrategyKind
|
|
|
|
AnalyzerOptions::getExplorationStrategy() {
|
2018-10-22 02:19:32 +08:00
|
|
|
if (!ExplorationStrategy.hasValue()) {
|
|
|
|
StringRef StratStr = getOptionAsString("exploration_strategy",
|
|
|
|
"unexplored_first_queue");
|
2018-02-13 06:39:57 +08:00
|
|
|
ExplorationStrategy =
|
2018-10-22 02:19:32 +08:00
|
|
|
llvm::StringSwitch<llvm::Optional<ExplorationStrategyKind>>(StratStr)
|
2018-02-13 06:39:57 +08:00
|
|
|
.Case("dfs", ExplorationStrategyKind::DFS)
|
|
|
|
.Case("bfs", ExplorationStrategyKind::BFS)
|
|
|
|
.Case("unexplored_first",
|
|
|
|
ExplorationStrategyKind::UnexploredFirst)
|
2018-02-27 06:14:18 +08:00
|
|
|
.Case("unexplored_first_queue",
|
|
|
|
ExplorationStrategyKind::UnexploredFirstQueue)
|
2018-10-12 06:59:59 +08:00
|
|
|
.Case("unexplored_first_location_queue",
|
|
|
|
ExplorationStrategyKind::UnexploredFirstLocationQueue)
|
2018-02-13 06:39:57 +08:00
|
|
|
.Case("bfs_block_dfs_contents",
|
|
|
|
ExplorationStrategyKind::BFSBlockDFSContents)
|
2018-10-22 02:19:32 +08:00
|
|
|
.Default(None);
|
|
|
|
assert(ExplorationStrategy.hasValue() &&
|
2018-02-13 06:39:57 +08:00
|
|
|
"User mode is invalid.");
|
2018-02-02 10:01:55 +08:00
|
|
|
}
|
2018-10-22 02:19:32 +08:00
|
|
|
return ExplorationStrategy.getValue();
|
2018-02-02 10:01:55 +08:00
|
|
|
}
|
|
|
|
|
2013-01-25 07:15:30 +08:00
|
|
|
IPAKind AnalyzerOptions::getIPAMode() {
|
2018-10-22 02:19:32 +08:00
|
|
|
if (!IPAMode.hasValue()) {
|
2013-01-25 07:15:34 +08:00
|
|
|
// 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.
|
2014-05-27 10:45:47 +08:00
|
|
|
const char *DefaultIPA = nullptr;
|
2013-01-25 07:15:34 +08:00
|
|
|
UserModeKind HighLevelMode = getUserMode();
|
|
|
|
if (HighLevelMode == UMK_Shallow)
|
2013-01-31 03:12:39 +08:00
|
|
|
DefaultIPA = "inlining";
|
2013-01-25 07:15:34 +08:00
|
|
|
else if (HighLevelMode == UMK_Deep)
|
|
|
|
DefaultIPA = "dynamic-bifurcate";
|
|
|
|
assert(DefaultIPA);
|
|
|
|
|
2013-01-25 07:15:30 +08:00
|
|
|
// Lookup the ipa configuration option, use the default from User Mode.
|
2018-10-22 02:19:32 +08:00
|
|
|
StringRef ModeStr = getOptionAsString("ipa", DefaultIPA);
|
|
|
|
IPAMode = llvm::StringSwitch<llvm::Optional<IPAKind>>(ModeStr)
|
2013-01-25 07:15:30 +08:00
|
|
|
.Case("none", IPAK_None)
|
|
|
|
.Case("basic-inlining", IPAK_BasicInlining)
|
|
|
|
.Case("inlining", IPAK_Inlining)
|
|
|
|
.Case("dynamic", IPAK_DynamicDispatch)
|
|
|
|
.Case("dynamic-bifurcate", IPAK_DynamicDispatchBifurcate)
|
2018-10-22 02:19:32 +08:00
|
|
|
.Default(None);
|
|
|
|
assert(IPAMode.hasValue() && "IPA Mode is invalid.");
|
2013-01-25 07:15:30 +08:00
|
|
|
}
|
2015-09-08 11:50:52 +08:00
|
|
|
|
2018-10-22 02:19:32 +08:00
|
|
|
return IPAMode.getValue();
|
2013-01-25 07:15:30 +08:00
|
|
|
}
|
|
|
|
|
2012-09-01 01:06:49 +08:00
|
|
|
bool
|
2012-10-03 04:31:52 +08:00
|
|
|
AnalyzerOptions::mayInlineCXXMemberFunction(CXXInlineableMemberKind K) {
|
2013-01-25 07:15:30 +08:00
|
|
|
if (getIPAMode() < IPAK_Inlining)
|
2012-09-01 01:06:49 +08:00
|
|
|
return false;
|
|
|
|
|
|
|
|
if (!CXXMemberInliningMode) {
|
2018-10-22 02:19:32 +08:00
|
|
|
StringRef ModeStr = getOptionAsString("c++-inlining", "destructors");
|
2012-09-01 01:06:49 +08:00
|
|
|
|
2018-10-22 02:19:32 +08:00
|
|
|
CXXMemberInliningMode =
|
|
|
|
llvm::StringSwitch<llvm::Optional<CXXInlineableMemberKind>>(ModeStr)
|
2012-09-01 01:06:49 +08:00
|
|
|
.Case("constructors", CIMK_Constructors)
|
|
|
|
.Case("destructors", CIMK_Destructors)
|
|
|
|
.Case("methods", CIMK_MemberFunctions)
|
2018-10-22 02:19:32 +08:00
|
|
|
.Case("none", CIMK_None)
|
|
|
|
.Default(None);
|
2012-09-01 01:06:49 +08:00
|
|
|
|
2018-10-22 02:19:32 +08:00
|
|
|
assert(CXXMemberInliningMode.hasValue() &&
|
|
|
|
"Invalid c++ member function inlining mode.");
|
2012-09-01 01:06:49 +08:00
|
|
|
}
|
|
|
|
|
2018-10-22 02:19:32 +08:00
|
|
|
return *CXXMemberInliningMode >= K;
|
2012-09-01 01:06:49 +08:00
|
|
|
}
|
[analyzer] Always include destructors in the analysis CFG.
While destructors will continue to not be inlined (unless the analyzer
config option 'c++-inlining' is set to 'destructors'), leaving them out
of the CFG is an incomplete model of the behavior of an object, and
can cause false positive warnings (like PR13751, now working).
Destructors for temporaries are still not on by default, since
(a) we haven't actually checked this code to be sure it's fully correct
(in particular, we probably need to be very careful with regard to
lifetime-extension when a temporary is bound to a reference,
C++11 [class.temporary]p5), and
(b) ExprEngine doesn't actually do anything when it sees a temporary
destructor in the CFG -- not even invalidate the object region.
To enable temporary destructors, set the 'cfg-temporary-dtors' analyzer
config option to '1'. The old -cfg-add-implicit-dtors cc1 option, which
controlled all implicit destructors, has been removed.
llvm-svn: 163264
2012-09-06 06:55:23 +08:00
|
|
|
|
2012-10-02 02:28:19 +08:00
|
|
|
static StringRef toString(bool b) { return b ? "true" : "false"; }
|
|
|
|
|
2015-03-05 01:59:34 +08:00
|
|
|
StringRef AnalyzerOptions::getCheckerOption(StringRef CheckerName,
|
|
|
|
StringRef OptionName,
|
|
|
|
StringRef Default,
|
|
|
|
bool SearchInParents) {
|
|
|
|
// Search for a package option if the option for the checker is not specified
|
|
|
|
// and search in parents is enabled.
|
|
|
|
ConfigTable::const_iterator E = Config.end();
|
|
|
|
do {
|
|
|
|
ConfigTable::const_iterator I =
|
|
|
|
Config.find((Twine(CheckerName) + ":" + OptionName).str());
|
|
|
|
if (I != E)
|
|
|
|
return StringRef(I->getValue());
|
|
|
|
size_t Pos = CheckerName.rfind('.');
|
|
|
|
if (Pos == StringRef::npos)
|
|
|
|
return Default;
|
|
|
|
CheckerName = CheckerName.substr(0, Pos);
|
|
|
|
} while (!CheckerName.empty() && SearchInParents);
|
|
|
|
return Default;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool AnalyzerOptions::getBooleanOption(StringRef Name, bool DefaultVal,
|
|
|
|
const CheckerBase *C,
|
|
|
|
bool SearchInParents) {
|
2012-09-11 05:27:35 +08:00
|
|
|
// 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.
|
2015-03-05 01:59:34 +08:00
|
|
|
StringRef Default = toString(DefaultVal);
|
2014-11-19 11:06:06 +08:00
|
|
|
StringRef V =
|
2015-03-05 01:59:34 +08:00
|
|
|
C ? getCheckerOption(C->getTagDescription(), Name, Default,
|
|
|
|
SearchInParents)
|
2018-10-22 02:19:32 +08:00
|
|
|
: getOptionAsString(Name, Default);
|
2012-10-02 02:28:19 +08:00
|
|
|
return llvm::StringSwitch<bool>(V)
|
|
|
|
.Case("true", true)
|
|
|
|
.Case("false", false)
|
|
|
|
.Default(DefaultVal);
|
2012-09-11 05:27:35 +08:00
|
|
|
}
|
|
|
|
|
2013-02-21 06:23:23 +08:00
|
|
|
bool AnalyzerOptions::getBooleanOption(Optional<bool> &V, StringRef Name,
|
2015-03-05 01:59:34 +08:00
|
|
|
bool DefaultVal, const CheckerBase *C,
|
|
|
|
bool SearchInParents) {
|
2012-10-03 04:42:16 +08:00
|
|
|
if (!V.hasValue())
|
2015-03-05 01:59:34 +08:00
|
|
|
V = getBooleanOption(Name, DefaultVal, C, SearchInParents);
|
2012-10-03 04:42:16 +08:00
|
|
|
return V.getValue();
|
|
|
|
}
|
|
|
|
|
2012-10-02 02:28:19 +08:00
|
|
|
bool AnalyzerOptions::includeTemporaryDtorsInCFG() {
|
2012-10-03 04:42:16 +08:00
|
|
|
return getBooleanOption(IncludeTemporaryDtorsInCFG,
|
|
|
|
"cfg-temporary-dtors",
|
2018-03-02 02:53:13 +08:00
|
|
|
/* Default = */ true);
|
2012-09-11 05:27:35 +08:00
|
|
|
}
|
|
|
|
|
2017-07-12 15:04:19 +08:00
|
|
|
bool AnalyzerOptions::includeImplicitDtorsInCFG() {
|
|
|
|
return getBooleanOption(IncludeImplicitDtorsInCFG,
|
|
|
|
"cfg-implicit-dtors",
|
|
|
|
/* Default = */ true);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool AnalyzerOptions::includeLifetimeInCFG() {
|
|
|
|
return getBooleanOption(IncludeLifetimeInCFG, "cfg-lifetime",
|
|
|
|
/* Default = */ false);
|
|
|
|
}
|
|
|
|
|
2017-08-19 19:19:16 +08:00
|
|
|
bool AnalyzerOptions::includeLoopExitInCFG() {
|
|
|
|
return getBooleanOption(IncludeLoopExitInCFG, "cfg-loopexit",
|
[CFG] Add extra context to C++ constructor statement elements.
This patch adds a new CFGStmt sub-class, CFGConstructor, which replaces
the regular CFGStmt with CXXConstructExpr in it whenever the CFG has additional
information to provide regarding what sort of object is being constructed.
It is useful for figuring out what memory is initialized in client of the
CFG such as the Static Analyzer, which do not operate by recursive AST
traversal, but instead rely on the CFG to provide all the information when they
need it. Otherwise, the statement that triggers the construction and defines
what memory is being initialized would normally occur after the
construct-expression, and the client would need to peek to the next CFG element
or use statement parent map to understand the necessary facts about
the construct-expression.
As a proof of concept, CFGConstructors are added for new-expressions
and the respective test cases are provided to demonstrate how it works.
For now, the only additional data contained in the CFGConstructor element is
the "trigger statement", such as new-expression, which is the parent of the
constructor. It will be significantly expanded in later commits. The additional
data is organized as an auxiliary structure - the "construction context",
which is allocated separately from the CFGElement.
Differential Revision: https://reviews.llvm.org/D42672
llvm-svn: 324668
2018-02-09 06:58:15 +08:00
|
|
|
/* Default = */ false);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool AnalyzerOptions::includeRichConstructorsInCFG() {
|
|
|
|
return getBooleanOption(IncludeRichConstructorsInCFG,
|
|
|
|
"cfg-rich-constructors",
|
|
|
|
/* Default = */ true);
|
2017-08-19 19:19:16 +08:00
|
|
|
}
|
|
|
|
|
2018-03-12 20:26:15 +08:00
|
|
|
bool AnalyzerOptions::includeScopesInCFG() {
|
|
|
|
return getBooleanOption(IncludeScopesInCFG,
|
|
|
|
"cfg-scopes",
|
|
|
|
/* Default = */ false);
|
|
|
|
}
|
|
|
|
|
2012-10-02 02:28:19 +08:00
|
|
|
bool AnalyzerOptions::mayInlineCXXStandardLibrary() {
|
2012-10-03 04:42:16 +08:00
|
|
|
return getBooleanOption(InlineCXXStandardLibrary,
|
|
|
|
"c++-stdlib-inlining",
|
|
|
|
/*Default=*/true);
|
2012-09-11 05:27:35 +08:00
|
|
|
}
|
|
|
|
|
2012-10-02 02:28:19 +08:00
|
|
|
bool AnalyzerOptions::mayInlineTemplateFunctions() {
|
2012-10-03 04:42:16 +08:00
|
|
|
return getBooleanOption(InlineTemplateFunctions,
|
|
|
|
"c++-template-inlining",
|
|
|
|
/*Default=*/true);
|
[analyzer] Always include destructors in the analysis CFG.
While destructors will continue to not be inlined (unless the analyzer
config option 'c++-inlining' is set to 'destructors'), leaving them out
of the CFG is an incomplete model of the behavior of an object, and
can cause false positive warnings (like PR13751, now working).
Destructors for temporaries are still not on by default, since
(a) we haven't actually checked this code to be sure it's fully correct
(in particular, we probably need to be very careful with regard to
lifetime-extension when a temporary is bound to a reference,
C++11 [class.temporary]p5), and
(b) ExprEngine doesn't actually do anything when it sees a temporary
destructor in the CFG -- not even invalidate the object region.
To enable temporary destructors, set the 'cfg-temporary-dtors' analyzer
config option to '1'. The old -cfg-add-implicit-dtors cc1 option, which
controlled all implicit destructors, has been removed.
llvm-svn: 163264
2012-09-06 06:55:23 +08:00
|
|
|
}
|
2012-09-11 06:37:19 +08:00
|
|
|
|
2014-02-11 10:21:06 +08:00
|
|
|
bool AnalyzerOptions::mayInlineCXXAllocator() {
|
|
|
|
return getBooleanOption(InlineCXXAllocator,
|
|
|
|
"c++-allocator-inlining",
|
2018-01-25 04:59:40 +08:00
|
|
|
/*Default=*/true);
|
2014-02-11 10:21:06 +08:00
|
|
|
}
|
|
|
|
|
2014-06-27 09:03:05 +08:00
|
|
|
bool AnalyzerOptions::mayInlineCXXContainerMethods() {
|
|
|
|
return getBooleanOption(InlineCXXContainerMethods,
|
2013-04-02 08:26:35 +08:00
|
|
|
"c++-container-inlining",
|
|
|
|
/*Default=*/false);
|
|
|
|
}
|
|
|
|
|
2013-05-17 10:16:49 +08:00
|
|
|
bool AnalyzerOptions::mayInlineCXXSharedPtrDtor() {
|
|
|
|
return getBooleanOption(InlineCXXSharedPtrDtor,
|
|
|
|
"c++-shared_ptr-inlining",
|
|
|
|
/*Default=*/false);
|
|
|
|
}
|
|
|
|
|
2018-02-16 03:17:44 +08:00
|
|
|
bool AnalyzerOptions::mayInlineCXXTemporaryDtors() {
|
|
|
|
return getBooleanOption(InlineCXXTemporaryDtors,
|
|
|
|
"c++-temp-dtor-inlining",
|
2018-03-23 06:05:53 +08:00
|
|
|
/*Default=*/true);
|
2018-02-16 03:17:44 +08:00
|
|
|
}
|
2013-04-02 08:26:35 +08:00
|
|
|
|
2012-10-02 02:28:19 +08:00
|
|
|
bool AnalyzerOptions::mayInlineObjCMethod() {
|
2012-10-03 04:42:16 +08:00
|
|
|
return getBooleanOption(ObjCInliningMode,
|
|
|
|
"objc-inlining",
|
|
|
|
/* Default = */ true);
|
2012-09-11 06:56:41 +08:00
|
|
|
}
|
|
|
|
|
2013-01-26 09:28:09 +08:00
|
|
|
bool AnalyzerOptions::shouldSuppressNullReturnPaths() {
|
|
|
|
return getBooleanOption(SuppressNullReturnPaths,
|
2012-10-03 04:42:16 +08:00
|
|
|
"suppress-null-return-paths",
|
|
|
|
/* Default = */ true);
|
2012-09-22 09:25:06 +08:00
|
|
|
}
|
|
|
|
|
2012-10-30 01:31:59 +08:00
|
|
|
bool AnalyzerOptions::shouldAvoidSuppressingNullArgumentPaths() {
|
|
|
|
return getBooleanOption(AvoidSuppressingNullArgumentPaths,
|
|
|
|
"avoid-suppressing-null-argument-paths",
|
|
|
|
/* Default = */ false);
|
|
|
|
}
|
|
|
|
|
2013-03-07 04:25:59 +08:00
|
|
|
bool AnalyzerOptions::shouldSuppressInlinedDefensiveChecks() {
|
|
|
|
return getBooleanOption(SuppressInlinedDefensiveChecks,
|
|
|
|
"suppress-inlined-defensive-checks",
|
|
|
|
/* Default = */ true);
|
|
|
|
}
|
|
|
|
|
2013-04-02 08:26:15 +08:00
|
|
|
bool AnalyzerOptions::shouldSuppressFromCXXStandardLibrary() {
|
|
|
|
return getBooleanOption(SuppressFromCXXStandardLibrary,
|
|
|
|
"suppress-c++-stdlib",
|
2017-03-10 08:33:19 +08:00
|
|
|
/* Default = */ true);
|
2013-04-02 08:26:15 +08:00
|
|
|
}
|
|
|
|
|
[analyzer] False positive refutation with Z3
Summary: This is a prototype of a bug reporter visitor that invalidates bug reports by re-checking constraints of certain states on the bug path using the Z3 constraint manager backend. The functionality is available under the `crosscheck-with-z3` analyzer config flag.
Reviewers: george.karpenkov, NoQ, dcoughlin, rnkovacs
Reviewed By: george.karpenkov
Subscribers: rnkovacs, NoQ, george.karpenkov, dcoughlin, xbolva00, ddcc, mikhail.ramalho, MTC, fhahn, whisperity, baloghadamsoftware, szepet, a.sidorin, gsd, dkrupp, xazax.hun, cfe-commits
Differential Revision: https://reviews.llvm.org/D45517
llvm-svn: 333903
2018-06-04 22:40:44 +08:00
|
|
|
bool AnalyzerOptions::shouldCrosscheckWithZ3() {
|
|
|
|
return getBooleanOption(CrosscheckWithZ3,
|
|
|
|
"crosscheck-with-z3",
|
|
|
|
/* Default = */ false);
|
|
|
|
}
|
|
|
|
|
2013-05-17 06:30:45 +08:00
|
|
|
bool AnalyzerOptions::shouldReportIssuesInMainSourceFile() {
|
|
|
|
return getBooleanOption(ReportIssuesInMainSourceFile,
|
|
|
|
"report-in-main-source-file",
|
|
|
|
/* Default = */ false);
|
|
|
|
}
|
|
|
|
|
2014-06-14 16:45:32 +08:00
|
|
|
|
|
|
|
bool AnalyzerOptions::shouldWriteStableReportFilename() {
|
|
|
|
return getBooleanOption(StableReportFilename,
|
|
|
|
"stable-report-filename",
|
|
|
|
/* Default = */ false);
|
|
|
|
}
|
|
|
|
|
2018-02-10 09:49:20 +08:00
|
|
|
bool AnalyzerOptions::shouldSerializeStats() {
|
|
|
|
return getBooleanOption(SerializeStats,
|
|
|
|
"serialize-stats",
|
|
|
|
/* Default = */ false);
|
|
|
|
}
|
|
|
|
|
2018-06-28 08:04:54 +08:00
|
|
|
bool AnalyzerOptions::shouldElideConstructors() {
|
|
|
|
return getBooleanOption(ElideConstructors,
|
|
|
|
"elide-constructors",
|
|
|
|
/* Default = */ true);
|
|
|
|
}
|
|
|
|
|
2015-03-05 01:59:34 +08:00
|
|
|
int AnalyzerOptions::getOptionAsInteger(StringRef Name, int DefaultVal,
|
|
|
|
const CheckerBase *C,
|
|
|
|
bool SearchInParents) {
|
2013-01-13 03:30:44 +08:00
|
|
|
SmallString<10> StrBuf;
|
2012-10-03 04:31:56 +08:00
|
|
|
llvm::raw_svector_ostream OS(StrBuf);
|
|
|
|
OS << DefaultVal;
|
2014-11-19 13:48:40 +08:00
|
|
|
|
2015-03-05 01:59:34 +08:00
|
|
|
StringRef V = C ? getCheckerOption(C->getTagDescription(), Name, OS.str(),
|
|
|
|
SearchInParents)
|
2018-10-22 02:19:32 +08:00
|
|
|
: getOptionAsString(Name, OS.str());
|
2015-03-05 01:59:34 +08:00
|
|
|
|
2012-09-11 06:37:19 +08:00
|
|
|
int Res = DefaultVal;
|
2012-10-03 04:31:56 +08:00
|
|
|
bool b = V.getAsInteger(10, Res);
|
|
|
|
assert(!b && "analyzer-config option should be numeric");
|
2015-03-05 01:59:34 +08:00
|
|
|
(void)b;
|
2012-09-11 06:37:19 +08:00
|
|
|
return Res;
|
|
|
|
}
|
|
|
|
|
2018-10-22 02:19:32 +08:00
|
|
|
unsigned AnalyzerOptions::getOptionAsUInt(Optional<unsigned> &V, StringRef Name,
|
|
|
|
unsigned DefaultVal,
|
|
|
|
const CheckerBase *C,
|
|
|
|
bool SearchInParents) {
|
|
|
|
if (!V.hasValue())
|
|
|
|
V = getOptionAsInteger(Name, DefaultVal, C, SearchInParents);
|
|
|
|
return V.getValue();
|
|
|
|
}
|
|
|
|
|
2015-03-05 01:59:34 +08:00
|
|
|
StringRef AnalyzerOptions::getOptionAsString(StringRef Name,
|
|
|
|
StringRef DefaultVal,
|
|
|
|
const CheckerBase *C,
|
|
|
|
bool SearchInParents) {
|
|
|
|
return C ? getCheckerOption(C->getTagDescription(), Name, DefaultVal,
|
|
|
|
SearchInParents)
|
|
|
|
: StringRef(
|
|
|
|
Config.insert(std::make_pair(Name, DefaultVal)).first->second);
|
|
|
|
}
|
|
|
|
|
2018-10-22 02:19:32 +08:00
|
|
|
StringRef AnalyzerOptions::getOptionAsString(Optional<StringRef> &V,
|
|
|
|
StringRef Name,
|
|
|
|
StringRef DefaultVal,
|
|
|
|
const ento::CheckerBase *C,
|
|
|
|
bool SearchInParents) {
|
|
|
|
if (!V.hasValue())
|
|
|
|
V = getOptionAsString(Name, DefaultVal, C, SearchInParents);
|
|
|
|
return V.getValue();
|
|
|
|
}
|
|
|
|
|
2012-10-03 04:31:56 +08:00
|
|
|
unsigned AnalyzerOptions::getAlwaysInlineSize() {
|
|
|
|
if (!AlwaysInlineSize.hasValue())
|
|
|
|
AlwaysInlineSize = getOptionAsInteger("ipa-always-inline-size", 3);
|
2012-09-11 06:37:19 +08:00
|
|
|
return AlwaysInlineSize.getValue();
|
|
|
|
}
|
2012-09-21 08:09:11 +08:00
|
|
|
|
2013-01-31 03:12:36 +08:00
|
|
|
unsigned AnalyzerOptions::getMaxInlinableSize() {
|
2013-01-31 03:12:39 +08:00
|
|
|
if (!MaxInlinableSize.hasValue()) {
|
|
|
|
int DefaultValue = 0;
|
|
|
|
UserModeKind HighLevelMode = getUserMode();
|
|
|
|
switch (HighLevelMode) {
|
|
|
|
case UMK_Shallow:
|
|
|
|
DefaultValue = 4;
|
|
|
|
break;
|
|
|
|
case UMK_Deep:
|
2017-06-21 19:29:35 +08:00
|
|
|
DefaultValue = 100;
|
2013-01-31 03:12:39 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
MaxInlinableSize = getOptionAsInteger("max-inlinable-size", DefaultValue);
|
|
|
|
}
|
2013-01-31 03:12:36 +08:00
|
|
|
return MaxInlinableSize.getValue();
|
|
|
|
}
|
|
|
|
|
2012-10-24 07:59:05 +08:00
|
|
|
unsigned AnalyzerOptions::getGraphTrimInterval() {
|
|
|
|
if (!GraphTrimInterval.hasValue())
|
|
|
|
GraphTrimInterval = getOptionAsInteger("graph-trim-interval", 1000);
|
|
|
|
return GraphTrimInterval.getValue();
|
|
|
|
}
|
|
|
|
|
2018-07-10 21:46:05 +08:00
|
|
|
unsigned AnalyzerOptions::getMaxSymbolComplexity() {
|
|
|
|
if (!MaxSymbolComplexity.hasValue())
|
2018-07-20 01:03:12 +08:00
|
|
|
MaxSymbolComplexity = getOptionAsInteger("max-symbol-complexity", 35);
|
2018-07-10 21:46:05 +08:00
|
|
|
return MaxSymbolComplexity.getValue();
|
|
|
|
}
|
|
|
|
|
2012-12-18 04:08:51 +08:00
|
|
|
unsigned AnalyzerOptions::getMaxTimesInlineLarge() {
|
|
|
|
if (!MaxTimesInlineLarge.hasValue())
|
|
|
|
MaxTimesInlineLarge = getOptionAsInteger("max-times-inline-large", 32);
|
|
|
|
return MaxTimesInlineLarge.getValue();
|
|
|
|
}
|
|
|
|
|
2015-09-12 04:14:05 +08:00
|
|
|
unsigned AnalyzerOptions::getMinCFGSizeTreatFunctionsAsLarge() {
|
|
|
|
if (!MinCFGSizeTreatFunctionsAsLarge.hasValue())
|
|
|
|
MinCFGSizeTreatFunctionsAsLarge = getOptionAsInteger(
|
|
|
|
"min-cfg-size-treat-functions-as-large", 14);
|
|
|
|
return MinCFGSizeTreatFunctionsAsLarge.getValue();
|
|
|
|
}
|
|
|
|
|
2013-01-31 03:12:39 +08:00
|
|
|
unsigned AnalyzerOptions::getMaxNodesPerTopLevelFunction() {
|
|
|
|
if (!MaxNodesPerTopLevelFunction.hasValue()) {
|
|
|
|
int DefaultValue = 0;
|
|
|
|
UserModeKind HighLevelMode = getUserMode();
|
|
|
|
switch (HighLevelMode) {
|
|
|
|
case UMK_Shallow:
|
|
|
|
DefaultValue = 75000;
|
|
|
|
break;
|
|
|
|
case UMK_Deep:
|
2017-06-21 19:29:35 +08:00
|
|
|
DefaultValue = 225000;
|
2013-01-31 03:12:39 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
MaxNodesPerTopLevelFunction = getOptionAsInteger("max-nodes", DefaultValue);
|
|
|
|
}
|
|
|
|
return MaxNodesPerTopLevelFunction.getValue();
|
|
|
|
}
|
|
|
|
|
2012-10-02 02:28:19 +08:00
|
|
|
bool AnalyzerOptions::shouldSynthesizeBodies() {
|
2012-09-22 01:55:34 +08:00
|
|
|
return getBooleanOption("faux-bodies", true);
|
2012-09-21 08:09:11 +08:00
|
|
|
}
|
2013-01-26 09:28:15 +08:00
|
|
|
|
|
|
|
bool AnalyzerOptions::shouldPrunePaths() {
|
|
|
|
return getBooleanOption("prune-paths", true);
|
|
|
|
}
|
2013-03-29 08:09:22 +08:00
|
|
|
|
|
|
|
bool AnalyzerOptions::shouldConditionalizeStaticInitializers() {
|
2013-03-29 08:09:28 +08:00
|
|
|
return getBooleanOption("cfg-conditional-static-initializers", true);
|
2013-03-29 08:09:22 +08:00
|
|
|
}
|
2015-09-12 00:55:01 +08:00
|
|
|
|
|
|
|
bool AnalyzerOptions::shouldInlineLambdas() {
|
2015-09-12 05:19:39 +08:00
|
|
|
if (!InlineLambdas.hasValue())
|
|
|
|
InlineLambdas = getBooleanOption("inline-lambdas", /*Default=*/true);
|
|
|
|
return InlineLambdas.getValue();
|
2015-09-12 00:55:01 +08:00
|
|
|
}
|
2015-10-30 23:23:57 +08:00
|
|
|
|
|
|
|
bool AnalyzerOptions::shouldWidenLoops() {
|
|
|
|
if (!WidenLoops.hasValue())
|
|
|
|
WidenLoops = getBooleanOption("widen-loops", /*Default=*/false);
|
|
|
|
return WidenLoops.getValue();
|
|
|
|
}
|
2016-10-08 03:25:10 +08:00
|
|
|
|
2017-07-26 03:23:23 +08:00
|
|
|
bool AnalyzerOptions::shouldUnrollLoops() {
|
|
|
|
if (!UnrollLoops.hasValue())
|
|
|
|
UnrollLoops = getBooleanOption("unroll-loops", /*Default=*/false);
|
|
|
|
return UnrollLoops.getValue();
|
|
|
|
}
|
|
|
|
|
2016-10-08 03:25:10 +08:00
|
|
|
bool AnalyzerOptions::shouldDisplayNotesAsEvents() {
|
|
|
|
if (!DisplayNotesAsEvents.hasValue())
|
|
|
|
DisplayNotesAsEvents =
|
|
|
|
getBooleanOption("notes-as-events", /*Default=*/false);
|
|
|
|
return DisplayNotesAsEvents.getValue();
|
|
|
|
}
|
2018-03-01 22:54:16 +08:00
|
|
|
|
2018-07-23 18:50:20 +08:00
|
|
|
bool AnalyzerOptions::shouldAggressivelySimplifyBinaryOperation() {
|
|
|
|
if (!AggressiveBinaryOperationSimplification.hasValue())
|
|
|
|
AggressiveBinaryOperationSimplification =
|
|
|
|
getBooleanOption("aggressive-binary-operation-simplification",
|
2018-04-11 14:21:12 +08:00
|
|
|
/*Default=*/false);
|
2018-07-23 18:50:20 +08:00
|
|
|
return AggressiveBinaryOperationSimplification.getValue();
|
2018-04-11 14:21:12 +08:00
|
|
|
}
|
|
|
|
|
2018-08-30 04:29:17 +08:00
|
|
|
bool AnalyzerOptions::shouldEagerlyAssume() {
|
|
|
|
if (!EagerlyAssumeBinOpBifurcation.hasValue())
|
|
|
|
EagerlyAssumeBinOpBifurcation =
|
|
|
|
getBooleanOption("eagerly-assume", true);
|
|
|
|
return EagerlyAssumeBinOpBifurcation.getValue();
|
|
|
|
}
|
|
|
|
|
2018-03-01 22:54:16 +08:00
|
|
|
StringRef AnalyzerOptions::getCTUDir() {
|
|
|
|
if (!CTUDir.hasValue()) {
|
|
|
|
CTUDir = getOptionAsString("ctu-dir", "");
|
|
|
|
if (!llvm::sys::fs::is_directory(*CTUDir))
|
|
|
|
CTUDir = "";
|
|
|
|
}
|
|
|
|
return CTUDir.getValue();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool AnalyzerOptions::naiveCTUEnabled() {
|
|
|
|
if (!NaiveCTU.hasValue()) {
|
|
|
|
NaiveCTU = getBooleanOption("experimental-enable-naive-ctu-analysis",
|
|
|
|
/*Default=*/false);
|
|
|
|
}
|
|
|
|
return NaiveCTU.getValue();
|
|
|
|
}
|
|
|
|
|
|
|
|
StringRef AnalyzerOptions::getCTUIndexName() {
|
|
|
|
if (!CTUIndexName.hasValue())
|
|
|
|
CTUIndexName = getOptionAsString("ctu-index-name", "externalFnMap.txt");
|
|
|
|
return CTUIndexName.getValue();
|
|
|
|
}
|