clang API Documentation

AnalyzerOptions.cpp
Go to the documentation of this file.
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