AnalyzerOptions.cpp revision 6bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89
1//===-- AnalyzerOptions.cpp - Analysis Engine Options -----------*- C++ -*-===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9// 10// This file contains special accessors for analyzer configuration options 11// with string representations. 12// 13//===----------------------------------------------------------------------===// 14 15#include "clang/StaticAnalyzer/Core/AnalyzerOptions.h" 16#include "llvm/ADT/SmallString.h" 17#include "llvm/ADT/StringSwitch.h" 18#include "llvm/Support/ErrorHandling.h" 19#include "llvm/Support/raw_ostream.h" 20 21using namespace clang; 22using namespace llvm; 23 24AnalyzerOptions::UserModeKind AnalyzerOptions::getUserMode() { 25 if (UserMode == UMK_NotSet) { 26 StringRef ModeStr(Config.GetOrCreateValue("mode", "deep").getValue()); 27 UserMode = llvm::StringSwitch<UserModeKind>(ModeStr) 28 .Case("shallow", UMK_Shallow) 29 .Case("deep", UMK_Deep) 30 .Default(UMK_NotSet); 31 assert(UserMode != UMK_NotSet && "User mode is invalid."); 32 } 33 return UserMode; 34} 35 36IPAKind AnalyzerOptions::getIPAMode() { 37 if (IPAMode == IPAK_NotSet) { 38 39 // Use the User Mode to set the default IPA value. 40 // Note, we have to add the string to the Config map for the ConfigDumper 41 // checker to function properly. 42 const char *DefaultIPA = nullptr; 43 UserModeKind HighLevelMode = getUserMode(); 44 if (HighLevelMode == UMK_Shallow) 45 DefaultIPA = "inlining"; 46 else if (HighLevelMode == UMK_Deep) 47 DefaultIPA = "dynamic-bifurcate"; 48 assert(DefaultIPA); 49 50 // Lookup the ipa configuration option, use the default from User Mode. 51 StringRef ModeStr(Config.GetOrCreateValue("ipa", DefaultIPA).getValue()); 52 IPAKind IPAConfig = llvm::StringSwitch<IPAKind>(ModeStr) 53 .Case("none", IPAK_None) 54 .Case("basic-inlining", IPAK_BasicInlining) 55 .Case("inlining", IPAK_Inlining) 56 .Case("dynamic", IPAK_DynamicDispatch) 57 .Case("dynamic-bifurcate", IPAK_DynamicDispatchBifurcate) 58 .Default(IPAK_NotSet); 59 assert(IPAConfig != IPAK_NotSet && "IPA Mode is invalid."); 60 61 // Set the member variable. 62 IPAMode = IPAConfig; 63 } 64 65 return IPAMode; 66} 67 68bool 69AnalyzerOptions::mayInlineCXXMemberFunction(CXXInlineableMemberKind K) { 70 if (getIPAMode() < IPAK_Inlining) 71 return false; 72 73 if (!CXXMemberInliningMode) { 74 static const char *ModeKey = "c++-inlining"; 75 76 StringRef ModeStr(Config.GetOrCreateValue(ModeKey, 77 "destructors").getValue()); 78 79 CXXInlineableMemberKind &MutableMode = 80 const_cast<CXXInlineableMemberKind &>(CXXMemberInliningMode); 81 82 MutableMode = llvm::StringSwitch<CXXInlineableMemberKind>(ModeStr) 83 .Case("constructors", CIMK_Constructors) 84 .Case("destructors", CIMK_Destructors) 85 .Case("none", CIMK_None) 86 .Case("methods", CIMK_MemberFunctions) 87 .Default(CXXInlineableMemberKind()); 88 89 if (!MutableMode) { 90 // FIXME: We should emit a warning here about an unknown inlining kind, 91 // but the AnalyzerOptions doesn't have access to a diagnostic engine. 92 MutableMode = CIMK_None; 93 } 94 } 95 96 return CXXMemberInliningMode >= K; 97} 98 99static StringRef toString(bool b) { return b ? "true" : "false"; } 100 101bool AnalyzerOptions::getBooleanOption(StringRef Name, bool DefaultVal) { 102 // FIXME: We should emit a warning here if the value is something other than 103 // "true", "false", or the empty string (meaning the default value), 104 // but the AnalyzerOptions doesn't have access to a diagnostic engine. 105 StringRef V(Config.GetOrCreateValue(Name, toString(DefaultVal)).getValue()); 106 return llvm::StringSwitch<bool>(V) 107 .Case("true", true) 108 .Case("false", false) 109 .Default(DefaultVal); 110} 111 112bool AnalyzerOptions::getBooleanOption(Optional<bool> &V, StringRef Name, 113 bool DefaultVal) { 114 if (!V.hasValue()) 115 V = getBooleanOption(Name, DefaultVal); 116 return V.getValue(); 117} 118 119bool AnalyzerOptions::includeTemporaryDtorsInCFG() { 120 return getBooleanOption(IncludeTemporaryDtorsInCFG, 121 "cfg-temporary-dtors", 122 /* Default = */ false); 123} 124 125bool AnalyzerOptions::mayInlineCXXStandardLibrary() { 126 return getBooleanOption(InlineCXXStandardLibrary, 127 "c++-stdlib-inlining", 128 /*Default=*/true); 129} 130 131bool AnalyzerOptions::mayInlineTemplateFunctions() { 132 return getBooleanOption(InlineTemplateFunctions, 133 "c++-template-inlining", 134 /*Default=*/true); 135} 136 137bool AnalyzerOptions::mayInlineCXXAllocator() { 138 return getBooleanOption(InlineCXXAllocator, 139 "c++-allocator-inlining", 140 /*Default=*/false); 141} 142 143bool AnalyzerOptions::mayInlineCXXContainerCtorsAndDtors() { 144 return getBooleanOption(InlineCXXContainerCtorsAndDtors, 145 "c++-container-inlining", 146 /*Default=*/false); 147} 148 149bool AnalyzerOptions::mayInlineCXXSharedPtrDtor() { 150 return getBooleanOption(InlineCXXSharedPtrDtor, 151 "c++-shared_ptr-inlining", 152 /*Default=*/false); 153} 154 155 156bool AnalyzerOptions::mayInlineObjCMethod() { 157 return getBooleanOption(ObjCInliningMode, 158 "objc-inlining", 159 /* Default = */ true); 160} 161 162bool AnalyzerOptions::shouldSuppressNullReturnPaths() { 163 return getBooleanOption(SuppressNullReturnPaths, 164 "suppress-null-return-paths", 165 /* Default = */ true); 166} 167 168bool AnalyzerOptions::shouldAvoidSuppressingNullArgumentPaths() { 169 return getBooleanOption(AvoidSuppressingNullArgumentPaths, 170 "avoid-suppressing-null-argument-paths", 171 /* Default = */ false); 172} 173 174bool AnalyzerOptions::shouldSuppressInlinedDefensiveChecks() { 175 return getBooleanOption(SuppressInlinedDefensiveChecks, 176 "suppress-inlined-defensive-checks", 177 /* Default = */ true); 178} 179 180bool AnalyzerOptions::shouldSuppressFromCXXStandardLibrary() { 181 return getBooleanOption(SuppressFromCXXStandardLibrary, 182 "suppress-c++-stdlib", 183 /* Default = */ false); 184} 185 186bool AnalyzerOptions::shouldReportIssuesInMainSourceFile() { 187 return getBooleanOption(ReportIssuesInMainSourceFile, 188 "report-in-main-source-file", 189 /* Default = */ false); 190} 191 192int AnalyzerOptions::getOptionAsInteger(StringRef Name, int DefaultVal) { 193 SmallString<10> StrBuf; 194 llvm::raw_svector_ostream OS(StrBuf); 195 OS << DefaultVal; 196 197 StringRef V(Config.GetOrCreateValue(Name, OS.str()).getValue()); 198 int Res = DefaultVal; 199 bool b = V.getAsInteger(10, Res); 200 assert(!b && "analyzer-config option should be numeric"); 201 (void) b; 202 return Res; 203} 204 205unsigned AnalyzerOptions::getAlwaysInlineSize() { 206 if (!AlwaysInlineSize.hasValue()) 207 AlwaysInlineSize = getOptionAsInteger("ipa-always-inline-size", 3); 208 return AlwaysInlineSize.getValue(); 209} 210 211unsigned AnalyzerOptions::getMaxInlinableSize() { 212 if (!MaxInlinableSize.hasValue()) { 213 214 int DefaultValue = 0; 215 UserModeKind HighLevelMode = getUserMode(); 216 switch (HighLevelMode) { 217 default: 218 llvm_unreachable("Invalid mode."); 219 case UMK_Shallow: 220 DefaultValue = 4; 221 break; 222 case UMK_Deep: 223 DefaultValue = 50; 224 break; 225 } 226 227 MaxInlinableSize = getOptionAsInteger("max-inlinable-size", DefaultValue); 228 } 229 return MaxInlinableSize.getValue(); 230} 231 232unsigned AnalyzerOptions::getGraphTrimInterval() { 233 if (!GraphTrimInterval.hasValue()) 234 GraphTrimInterval = getOptionAsInteger("graph-trim-interval", 1000); 235 return GraphTrimInterval.getValue(); 236} 237 238unsigned AnalyzerOptions::getMaxTimesInlineLarge() { 239 if (!MaxTimesInlineLarge.hasValue()) 240 MaxTimesInlineLarge = getOptionAsInteger("max-times-inline-large", 32); 241 return MaxTimesInlineLarge.getValue(); 242} 243 244unsigned AnalyzerOptions::getMaxNodesPerTopLevelFunction() { 245 if (!MaxNodesPerTopLevelFunction.hasValue()) { 246 int DefaultValue = 0; 247 UserModeKind HighLevelMode = getUserMode(); 248 switch (HighLevelMode) { 249 default: 250 llvm_unreachable("Invalid mode."); 251 case UMK_Shallow: 252 DefaultValue = 75000; 253 break; 254 case UMK_Deep: 255 DefaultValue = 150000; 256 break; 257 } 258 MaxNodesPerTopLevelFunction = getOptionAsInteger("max-nodes", DefaultValue); 259 } 260 return MaxNodesPerTopLevelFunction.getValue(); 261} 262 263bool AnalyzerOptions::shouldSynthesizeBodies() { 264 return getBooleanOption("faux-bodies", true); 265} 266 267bool AnalyzerOptions::shouldPrunePaths() { 268 return getBooleanOption("prune-paths", true); 269} 270 271bool AnalyzerOptions::shouldConditionalizeStaticInitializers() { 272 return getBooleanOption("cfg-conditional-static-initializers", true); 273} 274 275