AnalyzerOptions.cpp revision 046e79a425bfa82b480b8a07ce11d96391fa0a9b
1bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant//===-- AnalyzerOptions.cpp - Analysis Engine Options -----------*- C++ -*-===// 2bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant// 3f5256e16dfc425c1d466f6308d4026d529ce9e0bHoward Hinnant// The LLVM Compiler Infrastructure 4bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant// 5b64f8b07c104c6cc986570ac8ee0ed16a9f23976Howard Hinnant// This file is distributed under the University of Illinois Open Source 6b64f8b07c104c6cc986570ac8ee0ed16a9f23976Howard Hinnant// License. See LICENSE.TXT for details. 7bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant// 8bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant//===----------------------------------------------------------------------===// 9bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant// 10bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant// This file contains special accessors for analyzer configuration options 11bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant// with string representations. 12eb564e76cc3904d811c981a50ecce0659f444cc9Howard Hinnant// 13eb564e76cc3904d811c981a50ecce0659f444cc9Howard Hinnant//===----------------------------------------------------------------------===// 14eb564e76cc3904d811c981a50ecce0659f444cc9Howard Hinnant 15eb564e76cc3904d811c981a50ecce0659f444cc9Howard Hinnant#include "clang/StaticAnalyzer/Core/AnalyzerOptions.h" 16eb564e76cc3904d811c981a50ecce0659f444cc9Howard Hinnant#include "llvm/ADT/SmallString.h" 17bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant#include "llvm/ADT/StringSwitch.h" 18bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant#include "llvm/Support/ErrorHandling.h" 19bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant#include "llvm/Support/raw_ostream.h" 20bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant 21bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnantusing namespace clang; 22bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnantusing namespace llvm; 2383e2c4d877fe2d7793868b1c6a5d9525a7c4d431Marshall Clow 24bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard HinnantAnalyzerOptions::UserModeKind AnalyzerOptions::getUserMode() { 25bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant if (UserMode == UMK_NotSet) { 26bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant StringRef ModeStr(Config.GetOrCreateValue("mode", "deep").getValue()); 27bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant UserMode = llvm::StringSwitch<UserModeKind>(ModeStr) 28bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant .Case("shallow", UMK_Shallow) 29bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant .Case("deep", UMK_Deep) 30bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant .Default(UMK_NotSet); 31bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant assert(UserMode != UMK_NotSet && "User mode is invalid."); 32bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant } 33bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant return UserMode; 34bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant} 35bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant 36bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard HinnantIPAKind AnalyzerOptions::getIPAMode() { 37bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant if (IPAMode == IPAK_NotSet) { 38bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant 39bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant // Use the User Mode to set the default IPA value. 40bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant // Note, we have to add the string to the Config map for the ConfigDumper 41bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant // checker to function properly. 42bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant const char *DefaultIPA = 0; 43bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant UserModeKind HighLevelMode = getUserMode(); 44bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant if (HighLevelMode == UMK_Shallow) 45bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant DefaultIPA = "inlining"; 46bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant else if (HighLevelMode == UMK_Deep) 47bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant DefaultIPA = "dynamic-bifurcate"; 48bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant assert(DefaultIPA); 49bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant 50bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant // Lookup the ipa configuration option, use the default from User Mode. 51bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant StringRef ModeStr(Config.GetOrCreateValue("ipa", DefaultIPA).getValue()); 52bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant IPAKind IPAConfig = llvm::StringSwitch<IPAKind>(ModeStr) 53bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant .Case("none", IPAK_None) 54bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant .Case("basic-inlining", IPAK_BasicInlining) 55bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant .Case("inlining", IPAK_Inlining) 56bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant .Case("dynamic", IPAK_DynamicDispatch) 57bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant .Case("dynamic-bifurcate", IPAK_DynamicDispatchBifurcate) 58bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant .Default(IPAK_NotSet); 59bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant assert(IPAConfig != IPAK_NotSet && "IPA Mode is invalid."); 60bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant 61bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant // Set the member variable. 62bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant IPAMode = IPAConfig; 63bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant } 64bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant 65bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant return IPAMode; 66bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant} 67bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant 68bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnantbool 69bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard HinnantAnalyzerOptions::mayInlineCXXMemberFunction(CXXInlineableMemberKind K) { 70bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant if (getIPAMode() < IPAK_Inlining) 71bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant return false; 72bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant 73bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant if (!CXXMemberInliningMode) { 74bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant static const char *ModeKey = "c++-inlining"; 75bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant 76bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant StringRef ModeStr(Config.GetOrCreateValue(ModeKey, 77bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant "destructors").getValue()); 78bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant 79bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant CXXInlineableMemberKind &MutableMode = 80bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant const_cast<CXXInlineableMemberKind &>(CXXMemberInliningMode); 81bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant 82bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant MutableMode = llvm::StringSwitch<CXXInlineableMemberKind>(ModeStr) 83bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant .Case("constructors", CIMK_Constructors) 84bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant .Case("destructors", CIMK_Destructors) 85bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant .Case("none", CIMK_None) 86bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant .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 = */ true); 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::mayInlineCXXContainerCtorsAndDtors() { 138 return getBooleanOption(InlineCXXContainerCtorsAndDtors, 139 "c++-container-inlining", 140 /*Default=*/false); 141} 142 143bool AnalyzerOptions::mayInlineCXXSharedPtrDtor() { 144 return getBooleanOption(InlineCXXSharedPtrDtor, 145 "c++-shared_ptr-inlining", 146 /*Default=*/false); 147} 148 149 150bool AnalyzerOptions::mayInlineObjCMethod() { 151 return getBooleanOption(ObjCInliningMode, 152 "objc-inlining", 153 /* Default = */ true); 154} 155 156bool AnalyzerOptions::shouldSuppressNullReturnPaths() { 157 return getBooleanOption(SuppressNullReturnPaths, 158 "suppress-null-return-paths", 159 /* Default = */ true); 160} 161 162bool AnalyzerOptions::shouldAvoidSuppressingNullArgumentPaths() { 163 return getBooleanOption(AvoidSuppressingNullArgumentPaths, 164 "avoid-suppressing-null-argument-paths", 165 /* Default = */ false); 166} 167 168bool AnalyzerOptions::shouldSuppressInlinedDefensiveChecks() { 169 return getBooleanOption(SuppressInlinedDefensiveChecks, 170 "suppress-inlined-defensive-checks", 171 /* Default = */ true); 172} 173 174bool AnalyzerOptions::shouldSuppressFromCXXStandardLibrary() { 175 return getBooleanOption(SuppressFromCXXStandardLibrary, 176 "suppress-c++-stdlib", 177 /* Default = */ false); 178} 179 180bool AnalyzerOptions::shouldReportIssuesInMainSourceFile() { 181 return getBooleanOption(ReportIssuesInMainSourceFile, 182 "report-in-main-source-file", 183 /* Default = */ false); 184} 185 186int AnalyzerOptions::getOptionAsInteger(StringRef Name, int DefaultVal) { 187 SmallString<10> StrBuf; 188 llvm::raw_svector_ostream OS(StrBuf); 189 OS << DefaultVal; 190 191 StringRef V(Config.GetOrCreateValue(Name, OS.str()).getValue()); 192 int Res = DefaultVal; 193 bool b = V.getAsInteger(10, Res); 194 assert(!b && "analyzer-config option should be numeric"); 195 (void) b; 196 return Res; 197} 198 199unsigned AnalyzerOptions::getAlwaysInlineSize() { 200 if (!AlwaysInlineSize.hasValue()) 201 AlwaysInlineSize = getOptionAsInteger("ipa-always-inline-size", 3); 202 return AlwaysInlineSize.getValue(); 203} 204 205unsigned AnalyzerOptions::getMaxInlinableSize() { 206 if (!MaxInlinableSize.hasValue()) { 207 208 int DefaultValue = 0; 209 UserModeKind HighLevelMode = getUserMode(); 210 switch (HighLevelMode) { 211 default: 212 llvm_unreachable("Invalid mode."); 213 case UMK_Shallow: 214 DefaultValue = 4; 215 break; 216 case UMK_Deep: 217 DefaultValue = 50; 218 break; 219 } 220 221 MaxInlinableSize = getOptionAsInteger("max-inlinable-size", DefaultValue); 222 } 223 return MaxInlinableSize.getValue(); 224} 225 226unsigned AnalyzerOptions::getGraphTrimInterval() { 227 if (!GraphTrimInterval.hasValue()) 228 GraphTrimInterval = getOptionAsInteger("graph-trim-interval", 1000); 229 return GraphTrimInterval.getValue(); 230} 231 232unsigned AnalyzerOptions::getMaxTimesInlineLarge() { 233 if (!MaxTimesInlineLarge.hasValue()) 234 MaxTimesInlineLarge = getOptionAsInteger("max-times-inline-large", 32); 235 return MaxTimesInlineLarge.getValue(); 236} 237 238unsigned AnalyzerOptions::getMaxNodesPerTopLevelFunction() { 239 if (!MaxNodesPerTopLevelFunction.hasValue()) { 240 int DefaultValue = 0; 241 UserModeKind HighLevelMode = getUserMode(); 242 switch (HighLevelMode) { 243 default: 244 llvm_unreachable("Invalid mode."); 245 case UMK_Shallow: 246 DefaultValue = 75000; 247 break; 248 case UMK_Deep: 249 DefaultValue = 150000; 250 break; 251 } 252 MaxNodesPerTopLevelFunction = getOptionAsInteger("max-nodes", DefaultValue); 253 } 254 return MaxNodesPerTopLevelFunction.getValue(); 255} 256 257bool AnalyzerOptions::shouldSynthesizeBodies() { 258 return getBooleanOption("faux-bodies", true); 259} 260 261bool AnalyzerOptions::shouldPrunePaths() { 262 return getBooleanOption("prune-paths", true); 263} 264 265bool AnalyzerOptions::shouldConditionalizeStaticInitializers() { 266 return getBooleanOption("cfg-conditional-static-initializers", true); 267} 268 269