AnalyzerOptions.cpp 8.9 KB

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