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