2012-09-01 01:06:49 +08:00
|
|
|
//===-- AnalyzerOptions.cpp - Analysis Engine Options -----------*- C++ -*-===//
|
|
|
|
//
|
|
|
|
// 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"
|
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"
|
2012-10-03 04:31:56 +08:00
|
|
|
#include "llvm/Support/raw_ostream.h"
|
2012-09-01 01:06:49 +08:00
|
|
|
|
|
|
|
using namespace clang;
|
2012-09-11 06:37:19 +08:00
|
|
|
using namespace llvm;
|
2012-09-01 01:06:49 +08:00
|
|
|
|
2013-01-25 07:15:34 +08:00
|
|
|
AnalyzerOptions::UserModeKind AnalyzerOptions::getUserMode() {
|
|
|
|
if (UserMode == UMK_NotSet) {
|
|
|
|
StringRef ModeStr(Config.GetOrCreateValue("mode", "deep").getValue());
|
|
|
|
UserMode = llvm::StringSwitch<UserModeKind>(ModeStr)
|
|
|
|
.Case("shallow", UMK_Shallow)
|
|
|
|
.Case("deep", UMK_Deep)
|
|
|
|
.Default(UMK_NotSet);
|
2013-01-31 03:12:26 +08:00
|
|
|
assert(UserMode != UMK_NotSet && "User mode is invalid.");
|
2013-01-25 07:15:34 +08:00
|
|
|
}
|
|
|
|
return UserMode;
|
|
|
|
}
|
|
|
|
|
2013-01-25 07:15:30 +08:00
|
|
|
IPAKind AnalyzerOptions::getIPAMode() {
|
|
|
|
if (IPAMode == IPAK_NotSet) {
|
|
|
|
|
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.
|
|
|
|
const char *DefaultIPA = 0;
|
|
|
|
UserModeKind HighLevelMode = getUserMode();
|
|
|
|
if (HighLevelMode == UMK_Shallow)
|
|
|
|
DefaultIPA = "basic-inlining";
|
|
|
|
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.
|
2013-01-25 07:15:34 +08:00
|
|
|
StringRef ModeStr(Config.GetOrCreateValue("ipa", DefaultIPA).getValue());
|
2013-01-25 07:15:30 +08:00
|
|
|
IPAKind IPAConfig = llvm::StringSwitch<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(IPAK_NotSet);
|
2013-01-31 03:12:26 +08:00
|
|
|
assert(IPAConfig != IPAK_NotSet && "IPA Mode is invalid.");
|
2013-01-25 07:15:30 +08:00
|
|
|
|
|
|
|
// Set the member variable.
|
|
|
|
IPAMode = IPAConfig;
|
|
|
|
}
|
|
|
|
|
|
|
|
return IPAMode;
|
|
|
|
}
|
|
|
|
|
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) {
|
|
|
|
static const char *ModeKey = "c++-inlining";
|
2012-10-03 04:31:52 +08:00
|
|
|
|
|
|
|
StringRef ModeStr(Config.GetOrCreateValue(ModeKey,
|
|
|
|
"methods").getValue());
|
2012-09-01 01:06:49 +08:00
|
|
|
|
|
|
|
CXXInlineableMemberKind &MutableMode =
|
|
|
|
const_cast<CXXInlineableMemberKind &>(CXXMemberInliningMode);
|
|
|
|
|
|
|
|
MutableMode = llvm::StringSwitch<CXXInlineableMemberKind>(ModeStr)
|
|
|
|
.Case("constructors", CIMK_Constructors)
|
|
|
|
.Case("destructors", CIMK_Destructors)
|
|
|
|
.Case("none", CIMK_None)
|
|
|
|
.Case("methods", CIMK_MemberFunctions)
|
|
|
|
.Default(CXXInlineableMemberKind());
|
|
|
|
|
|
|
|
if (!MutableMode) {
|
|
|
|
// FIXME: We should emit a warning here about an unknown inlining kind,
|
|
|
|
// but the AnalyzerOptions doesn't have access to a diagnostic engine.
|
|
|
|
MutableMode = CIMK_None;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return CXXMemberInliningMode >= K;
|
|
|
|
}
|
[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"; }
|
|
|
|
|
|
|
|
bool AnalyzerOptions::getBooleanOption(StringRef Name, bool DefaultVal) {
|
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.
|
2012-10-02 02:28:19 +08:00
|
|
|
StringRef V(Config.GetOrCreateValue(Name, toString(DefaultVal)).getValue());
|
|
|
|
return llvm::StringSwitch<bool>(V)
|
|
|
|
.Case("true", true)
|
|
|
|
.Case("false", false)
|
|
|
|
.Default(DefaultVal);
|
2012-09-11 05:27:35 +08:00
|
|
|
}
|
|
|
|
|
2012-10-03 04:42:16 +08:00
|
|
|
bool AnalyzerOptions::getBooleanOption(llvm::Optional<bool> &V,
|
|
|
|
StringRef Name,
|
|
|
|
bool DefaultVal) {
|
|
|
|
if (!V.hasValue())
|
|
|
|
V = getBooleanOption(Name, DefaultVal);
|
|
|
|
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",
|
|
|
|
/* Default = */ false);
|
2012-09-11 05:27:35 +08:00
|
|
|
}
|
|
|
|
|
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
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2012-10-03 04:31:56 +08:00
|
|
|
int AnalyzerOptions::getOptionAsInteger(StringRef Name, int DefaultVal) {
|
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;
|
|
|
|
|
|
|
|
StringRef V(Config.GetOrCreateValue(Name, OS.str()).getValue());
|
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");
|
2012-10-03 05:50:18 +08:00
|
|
|
(void) b;
|
2012-09-11 06:37:19 +08:00
|
|
|
return Res;
|
|
|
|
}
|
|
|
|
|
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
|
|
|
|
2012-10-24 07:59:05 +08:00
|
|
|
unsigned AnalyzerOptions::getGraphTrimInterval() {
|
|
|
|
if (!GraphTrimInterval.hasValue())
|
|
|
|
GraphTrimInterval = getOptionAsInteger("graph-trim-interval", 1000);
|
|
|
|
return GraphTrimInterval.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();
|
|
|
|
}
|
|
|
|
|
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);
|
|
|
|
}
|