clang API Documentation
00001 //===-- AnalyzerOptions.cpp - Analysis Engine Options -----------*- C++ -*-===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This file contains special accessors for analyzer configuration options 00011 // with string representations. 00012 // 00013 //===----------------------------------------------------------------------===// 00014 00015 #include "clang/StaticAnalyzer/Core/AnalyzerOptions.h" 00016 #include "llvm/ADT/SmallString.h" 00017 #include "llvm/ADT/StringSwitch.h" 00018 #include "llvm/Support/ErrorHandling.h" 00019 #include "llvm/Support/raw_ostream.h" 00020 00021 using namespace clang; 00022 using namespace llvm; 00023 00024 AnalyzerOptions::UserModeKind AnalyzerOptions::getUserMode() { 00025 if (UserMode == UMK_NotSet) { 00026 StringRef ModeStr(Config.GetOrCreateValue("mode", "deep").getValue()); 00027 UserMode = llvm::StringSwitch<UserModeKind>(ModeStr) 00028 .Case("shallow", UMK_Shallow) 00029 .Case("deep", UMK_Deep) 00030 .Default(UMK_NotSet); 00031 assert(UserMode != UMK_NotSet && "User mode is invalid."); 00032 } 00033 return UserMode; 00034 } 00035 00036 IPAKind AnalyzerOptions::getIPAMode() { 00037 if (IPAMode == IPAK_NotSet) { 00038 00039 // Use the User Mode to set the default IPA value. 00040 // Note, we have to add the string to the Config map for the ConfigDumper 00041 // checker to function properly. 00042 const char *DefaultIPA = nullptr; 00043 UserModeKind HighLevelMode = getUserMode(); 00044 if (HighLevelMode == UMK_Shallow) 00045 DefaultIPA = "inlining"; 00046 else if (HighLevelMode == UMK_Deep) 00047 DefaultIPA = "dynamic-bifurcate"; 00048 assert(DefaultIPA); 00049 00050 // Lookup the ipa configuration option, use the default from User Mode. 00051 StringRef ModeStr(Config.GetOrCreateValue("ipa", DefaultIPA).getValue()); 00052 IPAKind IPAConfig = llvm::StringSwitch<IPAKind>(ModeStr) 00053 .Case("none", IPAK_None) 00054 .Case("basic-inlining", IPAK_BasicInlining) 00055 .Case("inlining", IPAK_Inlining) 00056 .Case("dynamic", IPAK_DynamicDispatch) 00057 .Case("dynamic-bifurcate", IPAK_DynamicDispatchBifurcate) 00058 .Default(IPAK_NotSet); 00059 assert(IPAConfig != IPAK_NotSet && "IPA Mode is invalid."); 00060 00061 // Set the member variable. 00062 IPAMode = IPAConfig; 00063 } 00064 00065 return IPAMode; 00066 } 00067 00068 bool 00069 AnalyzerOptions::mayInlineCXXMemberFunction(CXXInlineableMemberKind K) { 00070 if (getIPAMode() < IPAK_Inlining) 00071 return false; 00072 00073 if (!CXXMemberInliningMode) { 00074 static const char *ModeKey = "c++-inlining"; 00075 00076 StringRef ModeStr(Config.GetOrCreateValue(ModeKey, 00077 "destructors").getValue()); 00078 00079 CXXInlineableMemberKind &MutableMode = 00080 const_cast<CXXInlineableMemberKind &>(CXXMemberInliningMode); 00081 00082 MutableMode = llvm::StringSwitch<CXXInlineableMemberKind>(ModeStr) 00083 .Case("constructors", CIMK_Constructors) 00084 .Case("destructors", CIMK_Destructors) 00085 .Case("none", CIMK_None) 00086 .Case("methods", CIMK_MemberFunctions) 00087 .Default(CXXInlineableMemberKind()); 00088 00089 if (!MutableMode) { 00090 // FIXME: We should emit a warning here about an unknown inlining kind, 00091 // but the AnalyzerOptions doesn't have access to a diagnostic engine. 00092 MutableMode = CIMK_None; 00093 } 00094 } 00095 00096 return CXXMemberInliningMode >= K; 00097 } 00098 00099 static StringRef toString(bool b) { return b ? "true" : "false"; } 00100 00101 bool AnalyzerOptions::getBooleanOption(StringRef Name, bool DefaultVal) { 00102 // FIXME: We should emit a warning here if the value is something other than 00103 // "true", "false", or the empty string (meaning the default value), 00104 // but the AnalyzerOptions doesn't have access to a diagnostic engine. 00105 StringRef V(Config.GetOrCreateValue(Name, toString(DefaultVal)).getValue()); 00106 return llvm::StringSwitch<bool>(V) 00107 .Case("true", true) 00108 .Case("false", false) 00109 .Default(DefaultVal); 00110 } 00111 00112 bool AnalyzerOptions::getBooleanOption(Optional<bool> &V, StringRef Name, 00113 bool DefaultVal) { 00114 if (!V.hasValue()) 00115 V = getBooleanOption(Name, DefaultVal); 00116 return V.getValue(); 00117 } 00118 00119 bool AnalyzerOptions::includeTemporaryDtorsInCFG() { 00120 return getBooleanOption(IncludeTemporaryDtorsInCFG, 00121 "cfg-temporary-dtors", 00122 /* Default = */ false); 00123 } 00124 00125 bool AnalyzerOptions::mayInlineCXXStandardLibrary() { 00126 return getBooleanOption(InlineCXXStandardLibrary, 00127 "c++-stdlib-inlining", 00128 /*Default=*/true); 00129 } 00130 00131 bool AnalyzerOptions::mayInlineTemplateFunctions() { 00132 return getBooleanOption(InlineTemplateFunctions, 00133 "c++-template-inlining", 00134 /*Default=*/true); 00135 } 00136 00137 bool AnalyzerOptions::mayInlineCXXAllocator() { 00138 return getBooleanOption(InlineCXXAllocator, 00139 "c++-allocator-inlining", 00140 /*Default=*/false); 00141 } 00142 00143 bool AnalyzerOptions::mayInlineCXXContainerMethods() { 00144 return getBooleanOption(InlineCXXContainerMethods, 00145 "c++-container-inlining", 00146 /*Default=*/false); 00147 } 00148 00149 bool AnalyzerOptions::mayInlineCXXSharedPtrDtor() { 00150 return getBooleanOption(InlineCXXSharedPtrDtor, 00151 "c++-shared_ptr-inlining", 00152 /*Default=*/false); 00153 } 00154 00155 00156 bool AnalyzerOptions::mayInlineObjCMethod() { 00157 return getBooleanOption(ObjCInliningMode, 00158 "objc-inlining", 00159 /* Default = */ true); 00160 } 00161 00162 bool AnalyzerOptions::shouldSuppressNullReturnPaths() { 00163 return getBooleanOption(SuppressNullReturnPaths, 00164 "suppress-null-return-paths", 00165 /* Default = */ true); 00166 } 00167 00168 bool AnalyzerOptions::shouldAvoidSuppressingNullArgumentPaths() { 00169 return getBooleanOption(AvoidSuppressingNullArgumentPaths, 00170 "avoid-suppressing-null-argument-paths", 00171 /* Default = */ false); 00172 } 00173 00174 bool AnalyzerOptions::shouldSuppressInlinedDefensiveChecks() { 00175 return getBooleanOption(SuppressInlinedDefensiveChecks, 00176 "suppress-inlined-defensive-checks", 00177 /* Default = */ true); 00178 } 00179 00180 bool AnalyzerOptions::shouldSuppressFromCXXStandardLibrary() { 00181 return getBooleanOption(SuppressFromCXXStandardLibrary, 00182 "suppress-c++-stdlib", 00183 /* Default = */ false); 00184 } 00185 00186 bool AnalyzerOptions::shouldReportIssuesInMainSourceFile() { 00187 return getBooleanOption(ReportIssuesInMainSourceFile, 00188 "report-in-main-source-file", 00189 /* Default = */ false); 00190 } 00191 00192 00193 bool AnalyzerOptions::shouldWriteStableReportFilename() { 00194 return getBooleanOption(StableReportFilename, 00195 "stable-report-filename", 00196 /* Default = */ false); 00197 } 00198 00199 int AnalyzerOptions::getOptionAsInteger(StringRef Name, int DefaultVal) { 00200 SmallString<10> StrBuf; 00201 llvm::raw_svector_ostream OS(StrBuf); 00202 OS << DefaultVal; 00203 00204 StringRef V(Config.GetOrCreateValue(Name, OS.str()).getValue()); 00205 int Res = DefaultVal; 00206 bool b = V.getAsInteger(10, Res); 00207 assert(!b && "analyzer-config option should be numeric"); 00208 (void) b; 00209 return Res; 00210 } 00211 00212 unsigned AnalyzerOptions::getAlwaysInlineSize() { 00213 if (!AlwaysInlineSize.hasValue()) 00214 AlwaysInlineSize = getOptionAsInteger("ipa-always-inline-size", 3); 00215 return AlwaysInlineSize.getValue(); 00216 } 00217 00218 unsigned AnalyzerOptions::getMaxInlinableSize() { 00219 if (!MaxInlinableSize.hasValue()) { 00220 00221 int DefaultValue = 0; 00222 UserModeKind HighLevelMode = getUserMode(); 00223 switch (HighLevelMode) { 00224 default: 00225 llvm_unreachable("Invalid mode."); 00226 case UMK_Shallow: 00227 DefaultValue = 4; 00228 break; 00229 case UMK_Deep: 00230 DefaultValue = 50; 00231 break; 00232 } 00233 00234 MaxInlinableSize = getOptionAsInteger("max-inlinable-size", DefaultValue); 00235 } 00236 return MaxInlinableSize.getValue(); 00237 } 00238 00239 unsigned AnalyzerOptions::getGraphTrimInterval() { 00240 if (!GraphTrimInterval.hasValue()) 00241 GraphTrimInterval = getOptionAsInteger("graph-trim-interval", 1000); 00242 return GraphTrimInterval.getValue(); 00243 } 00244 00245 unsigned AnalyzerOptions::getMaxTimesInlineLarge() { 00246 if (!MaxTimesInlineLarge.hasValue()) 00247 MaxTimesInlineLarge = getOptionAsInteger("max-times-inline-large", 32); 00248 return MaxTimesInlineLarge.getValue(); 00249 } 00250 00251 unsigned AnalyzerOptions::getMaxNodesPerTopLevelFunction() { 00252 if (!MaxNodesPerTopLevelFunction.hasValue()) { 00253 int DefaultValue = 0; 00254 UserModeKind HighLevelMode = getUserMode(); 00255 switch (HighLevelMode) { 00256 default: 00257 llvm_unreachable("Invalid mode."); 00258 case UMK_Shallow: 00259 DefaultValue = 75000; 00260 break; 00261 case UMK_Deep: 00262 DefaultValue = 150000; 00263 break; 00264 } 00265 MaxNodesPerTopLevelFunction = getOptionAsInteger("max-nodes", DefaultValue); 00266 } 00267 return MaxNodesPerTopLevelFunction.getValue(); 00268 } 00269 00270 bool AnalyzerOptions::shouldSynthesizeBodies() { 00271 return getBooleanOption("faux-bodies", true); 00272 } 00273 00274 bool AnalyzerOptions::shouldPrunePaths() { 00275 return getBooleanOption("prune-paths", true); 00276 } 00277 00278 bool AnalyzerOptions::shouldConditionalizeStaticInitializers() { 00279 return getBooleanOption("cfg-conditional-static-initializers", true); 00280 } 00281