1234949Sbapt//===-- AnalyzerOptions.cpp - Analysis Engine Options -----------*- C++ -*-===// 2234949Sbapt// 3234949Sbapt// The LLVM Compiler Infrastructure 4234949Sbapt// 5234949Sbapt// This file is distributed under the University of Illinois Open Source 6234949Sbapt// License. See LICENSE.TXT for details. 7234949Sbapt// 8234949Sbapt//===----------------------------------------------------------------------===// 9234949Sbapt// 10234949Sbapt// This file contains special accessors for analyzer configuration options 11234949Sbapt// with string representations. 12234949Sbapt// 13234949Sbapt//===----------------------------------------------------------------------===// 14234949Sbapt 15234949Sbapt#include "clang/StaticAnalyzer/Core/AnalyzerOptions.h" 16234949Sbapt#include "llvm/ADT/SmallString.h" 17234949Sbapt#include "llvm/ADT/StringSwitch.h" 18234949Sbapt#include "llvm/Support/ErrorHandling.h" 19234949Sbapt#include "llvm/Support/raw_ostream.h" 20234949Sbapt 21234949Sbaptusing namespace clang; 22234949Sbaptusing namespace llvm; 23234949Sbapt 24234949SbaptAnalyzerOptions::UserModeKind AnalyzerOptions::getUserMode() { 25234949Sbapt if (UserMode == UMK_NotSet) { 26234949Sbapt StringRef ModeStr(Config.GetOrCreateValue("mode", "deep").getValue()); 27234949Sbapt UserMode = llvm::StringSwitch<UserModeKind>(ModeStr) 28234949Sbapt .Case("shallow", UMK_Shallow) 29234949Sbapt .Case("deep", UMK_Deep) 30234949Sbapt .Default(UMK_NotSet); 31234949Sbapt assert(UserMode != UMK_NotSet && "User mode is invalid."); 32234949Sbapt } 33234949Sbapt return UserMode; 34234949Sbapt} 35234949Sbapt 36234949SbaptIPAKind AnalyzerOptions::getIPAMode() { 37234949Sbapt if (IPAMode == IPAK_NotSet) { 38234949Sbapt 39234949Sbapt // Use the User Mode to set the default IPA value. 40234949Sbapt // Note, we have to add the string to the Config map for the ConfigDumper 41234949Sbapt // checker to function properly. 42234949Sbapt const char *DefaultIPA = 0; 43234949Sbapt UserModeKind HighLevelMode = getUserMode(); 44234949Sbapt if (HighLevelMode == UMK_Shallow) 45234949Sbapt DefaultIPA = "inlining"; 46234949Sbapt else if (HighLevelMode == UMK_Deep) 47234949Sbapt DefaultIPA = "dynamic-bifurcate"; 48234949Sbapt assert(DefaultIPA); 49234949Sbapt 50234949Sbapt // Lookup the ipa configuration option, use the default from User Mode. 51234949Sbapt StringRef ModeStr(Config.GetOrCreateValue("ipa", DefaultIPA).getValue()); 52234949Sbapt IPAKind IPAConfig = llvm::StringSwitch<IPAKind>(ModeStr) 53234949Sbapt .Case("none", IPAK_None) 54234949Sbapt .Case("basic-inlining", IPAK_BasicInlining) 55234949Sbapt .Case("inlining", IPAK_Inlining) 56234949Sbapt .Case("dynamic", IPAK_DynamicDispatch) 57234949Sbapt .Case("dynamic-bifurcate", IPAK_DynamicDispatchBifurcate) 58234949Sbapt .Default(IPAK_NotSet); 59234949Sbapt assert(IPAConfig != IPAK_NotSet && "IPA Mode is invalid."); 60234949Sbapt 61234949Sbapt // Set the member variable. 62234949Sbapt IPAMode = IPAConfig; 63234949Sbapt } 64234949Sbapt 65234949Sbapt return IPAMode; 66234949Sbapt} 67234949Sbapt 68234949Sbaptbool 69234949SbaptAnalyzerOptions::mayInlineCXXMemberFunction(CXXInlineableMemberKind K) { 70234949Sbapt if (getIPAMode() < IPAK_Inlining) 71234949Sbapt return false; 72234949Sbapt 73234949Sbapt if (!CXXMemberInliningMode) { 74234949Sbapt static const char *ModeKey = "c++-inlining"; 75234949Sbapt 76234949Sbapt StringRef ModeStr(Config.GetOrCreateValue(ModeKey, 77234949Sbapt "destructors").getValue()); 78234949Sbapt 79234949Sbapt CXXInlineableMemberKind &MutableMode = 80234949Sbapt const_cast<CXXInlineableMemberKind &>(CXXMemberInliningMode); 81234949Sbapt 82234949Sbapt MutableMode = llvm::StringSwitch<CXXInlineableMemberKind>(ModeStr) 83234949Sbapt .Case("constructors", CIMK_Constructors) 84234949Sbapt .Case("destructors", CIMK_Destructors) 85234949Sbapt .Case("none", CIMK_None) 86234949Sbapt .Case("methods", CIMK_MemberFunctions) 87234949Sbapt .Default(CXXInlineableMemberKind()); 88234949Sbapt 89234949Sbapt if (!MutableMode) { 90234949Sbapt // FIXME: We should emit a warning here about an unknown inlining kind, 91234949Sbapt // but the AnalyzerOptions doesn't have access to a diagnostic engine. 92234949Sbapt MutableMode = CIMK_None; 93234949Sbapt } 94234949Sbapt } 95234949Sbapt 96234949Sbapt return CXXMemberInliningMode >= K; 97234949Sbapt} 98234949Sbapt 99234949Sbaptstatic StringRef toString(bool b) { return b ? "true" : "false"; } 100234949Sbapt 101234949Sbaptbool AnalyzerOptions::getBooleanOption(StringRef Name, bool DefaultVal) { 102234949Sbapt // FIXME: We should emit a warning here if the value is something other than 103234949Sbapt // "true", "false", or the empty string (meaning the default value), 104234949Sbapt // but the AnalyzerOptions doesn't have access to a diagnostic engine. 105234949Sbapt StringRef V(Config.GetOrCreateValue(Name, toString(DefaultVal)).getValue()); 106234949Sbapt return llvm::StringSwitch<bool>(V) 107234949Sbapt .Case("true", true) 108234949Sbapt .Case("false", false) 109234949Sbapt .Default(DefaultVal); 110234949Sbapt} 111234949Sbapt 112234949Sbaptbool AnalyzerOptions::getBooleanOption(Optional<bool> &V, StringRef Name, 113234949Sbapt bool DefaultVal) { 114234949Sbapt if (!V.hasValue()) 115234949Sbapt V = getBooleanOption(Name, DefaultVal); 116234949Sbapt return V.getValue(); 117234949Sbapt} 118234949Sbapt 119234949Sbaptbool AnalyzerOptions::includeTemporaryDtorsInCFG() { 120234949Sbapt return getBooleanOption(IncludeTemporaryDtorsInCFG, 121234949Sbapt "cfg-temporary-dtors", 122234949Sbapt /* Default = */ false); 123234949Sbapt} 124234949Sbapt 125234949Sbaptbool AnalyzerOptions::mayInlineCXXStandardLibrary() { 126234949Sbapt return getBooleanOption(InlineCXXStandardLibrary, 127234949Sbapt "c++-stdlib-inlining", 128234949Sbapt /*Default=*/true); 129234949Sbapt} 130234949Sbapt 131234949Sbaptbool AnalyzerOptions::mayInlineTemplateFunctions() { 132234949Sbapt return getBooleanOption(InlineTemplateFunctions, 133234949Sbapt "c++-template-inlining", 134234949Sbapt /*Default=*/true); 135234949Sbapt} 136234949Sbapt 137234949Sbaptbool AnalyzerOptions::mayInlineCXXContainerCtorsAndDtors() { 138234949Sbapt return getBooleanOption(InlineCXXContainerCtorsAndDtors, 139234949Sbapt "c++-container-inlining", 140234949Sbapt /*Default=*/false); 141234949Sbapt} 142234949Sbapt 143234949Sbaptbool AnalyzerOptions::mayInlineCXXSharedPtrDtor() { 144234949Sbapt return getBooleanOption(InlineCXXSharedPtrDtor, 145234949Sbapt "c++-shared_ptr-inlining", 146234949Sbapt /*Default=*/false); 147234949Sbapt} 148234949Sbapt 149234949Sbapt 150234949Sbaptbool AnalyzerOptions::mayInlineObjCMethod() { 151234949Sbapt return getBooleanOption(ObjCInliningMode, 152234949Sbapt "objc-inlining", 153234949Sbapt /* Default = */ true); 154234949Sbapt} 155234949Sbapt 156234949Sbaptbool AnalyzerOptions::shouldSuppressNullReturnPaths() { 157234949Sbapt return getBooleanOption(SuppressNullReturnPaths, 158234949Sbapt "suppress-null-return-paths", 159234949Sbapt /* Default = */ true); 160234949Sbapt} 161234949Sbapt 162234949Sbaptbool AnalyzerOptions::shouldAvoidSuppressingNullArgumentPaths() { 163234949Sbapt return getBooleanOption(AvoidSuppressingNullArgumentPaths, 164234949Sbapt "avoid-suppressing-null-argument-paths", 165234949Sbapt /* Default = */ false); 166234949Sbapt} 167234949Sbapt 168234949Sbaptbool AnalyzerOptions::shouldSuppressInlinedDefensiveChecks() { 169234949Sbapt return getBooleanOption(SuppressInlinedDefensiveChecks, 170234949Sbapt "suppress-inlined-defensive-checks", 171234949Sbapt /* Default = */ true); 172234949Sbapt} 173234949Sbapt 174234949Sbaptbool AnalyzerOptions::shouldSuppressFromCXXStandardLibrary() { 175234949Sbapt return getBooleanOption(SuppressFromCXXStandardLibrary, 176234949Sbapt "suppress-c++-stdlib", 177234949Sbapt /* Default = */ false); 178234949Sbapt} 179234949Sbapt 180234949Sbaptbool AnalyzerOptions::shouldReportIssuesInMainSourceFile() { 181234949Sbapt return getBooleanOption(ReportIssuesInMainSourceFile, 182234949Sbapt "report-in-main-source-file", 183234949Sbapt /* Default = */ false); 184234949Sbapt} 185234949Sbapt 186234949Sbaptint AnalyzerOptions::getOptionAsInteger(StringRef Name, int DefaultVal) { 187234949Sbapt SmallString<10> StrBuf; 188234949Sbapt llvm::raw_svector_ostream OS(StrBuf); 189234949Sbapt OS << DefaultVal; 190234949Sbapt 191234949Sbapt StringRef V(Config.GetOrCreateValue(Name, OS.str()).getValue()); 192234949Sbapt int Res = DefaultVal; 193234949Sbapt bool b = V.getAsInteger(10, Res); 194234949Sbapt assert(!b && "analyzer-config option should be numeric"); 195234949Sbapt (void) b; 196234949Sbapt return Res; 197234949Sbapt} 198234949Sbapt 199234949Sbaptunsigned AnalyzerOptions::getAlwaysInlineSize() { 200234949Sbapt if (!AlwaysInlineSize.hasValue()) 201234949Sbapt AlwaysInlineSize = getOptionAsInteger("ipa-always-inline-size", 3); 202234949Sbapt return AlwaysInlineSize.getValue(); 203234949Sbapt} 204234949Sbapt 205234949Sbaptunsigned AnalyzerOptions::getMaxInlinableSize() { 206234949Sbapt if (!MaxInlinableSize.hasValue()) { 207234949Sbapt 208234949Sbapt int DefaultValue = 0; 209234949Sbapt UserModeKind HighLevelMode = getUserMode(); 210234949Sbapt switch (HighLevelMode) { 211234949Sbapt default: 212234949Sbapt llvm_unreachable("Invalid mode."); 213234949Sbapt case UMK_Shallow: 214234949Sbapt DefaultValue = 4; 215234949Sbapt break; 216234949Sbapt case UMK_Deep: 217234949Sbapt DefaultValue = 50; 218234949Sbapt break; 219234949Sbapt } 220234949Sbapt 221234949Sbapt MaxInlinableSize = getOptionAsInteger("max-inlinable-size", DefaultValue); 222234949Sbapt } 223234949Sbapt return MaxInlinableSize.getValue(); 224234949Sbapt} 225234949Sbapt 226234949Sbaptunsigned AnalyzerOptions::getGraphTrimInterval() { 227234949Sbapt if (!GraphTrimInterval.hasValue()) 228234949Sbapt GraphTrimInterval = getOptionAsInteger("graph-trim-interval", 1000); 229234949Sbapt return GraphTrimInterval.getValue(); 230234949Sbapt} 231234949Sbapt 232234949Sbaptunsigned AnalyzerOptions::getMaxTimesInlineLarge() { 233234949Sbapt if (!MaxTimesInlineLarge.hasValue()) 234234949Sbapt MaxTimesInlineLarge = getOptionAsInteger("max-times-inline-large", 32); 235234949Sbapt return MaxTimesInlineLarge.getValue(); 236234949Sbapt} 237234949Sbapt 238234949Sbaptunsigned AnalyzerOptions::getMaxNodesPerTopLevelFunction() { 239234949Sbapt if (!MaxNodesPerTopLevelFunction.hasValue()) { 240234949Sbapt int DefaultValue = 0; 241234949Sbapt UserModeKind HighLevelMode = getUserMode(); 242234949Sbapt switch (HighLevelMode) { 243234949Sbapt default: 244234949Sbapt llvm_unreachable("Invalid mode."); 245234949Sbapt case UMK_Shallow: 246234949Sbapt DefaultValue = 75000; 247234949Sbapt break; 248234949Sbapt case UMK_Deep: 249234949Sbapt DefaultValue = 150000; 250234949Sbapt break; 251234949Sbapt } 252234949Sbapt MaxNodesPerTopLevelFunction = getOptionAsInteger("max-nodes", DefaultValue); 253234949Sbapt } 254234949Sbapt return MaxNodesPerTopLevelFunction.getValue(); 255234949Sbapt} 256234949Sbapt 257234949Sbaptbool AnalyzerOptions::shouldSynthesizeBodies() { 258234949Sbapt return getBooleanOption("faux-bodies", true); 259234949Sbapt} 260234949Sbapt 261234949Sbaptbool AnalyzerOptions::shouldPrunePaths() { 262234949Sbapt return getBooleanOption("prune-paths", true); 263234949Sbapt} 264234949Sbapt 265234949Sbaptbool AnalyzerOptions::shouldConditionalizeStaticInitializers() { 266234949Sbapt return getBooleanOption("cfg-conditional-static-initializers", true); 267234949Sbapt} 268234949Sbapt 269234949Sbapt