AnalyzerOptions.cpp 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  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 = 0;
  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. "methods").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::mayInlineObjCMethod() {
  116. return getBooleanOption(ObjCInliningMode,
  117. "objc-inlining",
  118. /* Default = */ true);
  119. }
  120. bool AnalyzerOptions::shouldSuppressNullReturnPaths() {
  121. return getBooleanOption(SuppressNullReturnPaths,
  122. "suppress-null-return-paths",
  123. /* Default = */ true);
  124. }
  125. bool AnalyzerOptions::shouldAvoidSuppressingNullArgumentPaths() {
  126. return getBooleanOption(AvoidSuppressingNullArgumentPaths,
  127. "avoid-suppressing-null-argument-paths",
  128. /* Default = */ false);
  129. }
  130. int AnalyzerOptions::getOptionAsInteger(StringRef Name, int DefaultVal) {
  131. SmallString<10> StrBuf;
  132. llvm::raw_svector_ostream OS(StrBuf);
  133. OS << DefaultVal;
  134. StringRef V(Config.GetOrCreateValue(Name, OS.str()).getValue());
  135. int Res = DefaultVal;
  136. bool b = V.getAsInteger(10, Res);
  137. assert(!b && "analyzer-config option should be numeric");
  138. (void) b;
  139. return Res;
  140. }
  141. unsigned AnalyzerOptions::getAlwaysInlineSize() {
  142. if (!AlwaysInlineSize.hasValue())
  143. AlwaysInlineSize = getOptionAsInteger("ipa-always-inline-size", 3);
  144. return AlwaysInlineSize.getValue();
  145. }
  146. unsigned AnalyzerOptions::getMaxInlinableSize() {
  147. if (!MaxInlinableSize.hasValue()) {
  148. int DefaultValue = 0;
  149. UserModeKind HighLevelMode = getUserMode();
  150. switch (HighLevelMode) {
  151. default:
  152. llvm_unreachable("Invalid mode.");
  153. case UMK_Shallow:
  154. DefaultValue = 4;
  155. break;
  156. case UMK_Deep:
  157. DefaultValue = 50;
  158. break;
  159. }
  160. MaxInlinableSize = getOptionAsInteger("max-inlinable-size", DefaultValue);
  161. }
  162. return MaxInlinableSize.getValue();
  163. }
  164. unsigned AnalyzerOptions::getGraphTrimInterval() {
  165. if (!GraphTrimInterval.hasValue())
  166. GraphTrimInterval = getOptionAsInteger("graph-trim-interval", 1000);
  167. return GraphTrimInterval.getValue();
  168. }
  169. unsigned AnalyzerOptions::getMaxTimesInlineLarge() {
  170. if (!MaxTimesInlineLarge.hasValue())
  171. MaxTimesInlineLarge = getOptionAsInteger("max-times-inline-large", 32);
  172. return MaxTimesInlineLarge.getValue();
  173. }
  174. unsigned AnalyzerOptions::getMaxNodesPerTopLevelFunction() {
  175. if (!MaxNodesPerTopLevelFunction.hasValue()) {
  176. int DefaultValue = 0;
  177. UserModeKind HighLevelMode = getUserMode();
  178. switch (HighLevelMode) {
  179. default:
  180. llvm_unreachable("Invalid mode.");
  181. case UMK_Shallow:
  182. DefaultValue = 75000;
  183. break;
  184. case UMK_Deep:
  185. DefaultValue = 150000;
  186. break;
  187. }
  188. MaxNodesPerTopLevelFunction = getOptionAsInteger("max-nodes", DefaultValue);
  189. }
  190. return MaxNodesPerTopLevelFunction.getValue();
  191. }
  192. bool AnalyzerOptions::shouldSynthesizeBodies() {
  193. return getBooleanOption("faux-bodies", true);
  194. }
  195. bool AnalyzerOptions::shouldPrunePaths() {
  196. return getBooleanOption("prune-paths", true);
  197. }