AnalyzerOptions.cpp 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. //===- AnalyzerOptions.cpp - Analysis Engine Options ----------------------===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. //
  9. // This file contains special accessors for analyzer configuration options
  10. // with string representations.
  11. //
  12. //===----------------------------------------------------------------------===//
  13. #include "clang/StaticAnalyzer/Core/AnalyzerOptions.h"
  14. #include "clang/StaticAnalyzer/Core/Checker.h"
  15. #include "llvm/ADT/SmallString.h"
  16. #include "llvm/ADT/StringSwitch.h"
  17. #include "llvm/ADT/StringRef.h"
  18. #include "llvm/ADT/Twine.h"
  19. #include "llvm/Support/ErrorHandling.h"
  20. #include "llvm/Support/FileSystem.h"
  21. #include "llvm/Support/FormattedStream.h"
  22. #include "llvm/Support/raw_ostream.h"
  23. #include <cassert>
  24. #include <cstddef>
  25. #include <utility>
  26. #include <vector>
  27. using namespace clang;
  28. using namespace ento;
  29. using namespace llvm;
  30. void AnalyzerOptions::printFormattedEntry(
  31. llvm::raw_ostream &Out,
  32. std::pair<StringRef, StringRef> EntryDescPair,
  33. size_t InitialPad, size_t EntryWidth, size_t MinLineWidth) {
  34. llvm::formatted_raw_ostream FOut(Out);
  35. const size_t PadForDesc = InitialPad + EntryWidth;
  36. FOut.PadToColumn(InitialPad) << EntryDescPair.first;
  37. // If the buffer's length is greater than PadForDesc, print a newline.
  38. if (FOut.getColumn() > PadForDesc)
  39. FOut << '\n';
  40. FOut.PadToColumn(PadForDesc);
  41. if (MinLineWidth == 0) {
  42. FOut << EntryDescPair.second;
  43. return;
  44. }
  45. for (char C : EntryDescPair.second) {
  46. if (FOut.getColumn() > MinLineWidth && C == ' ') {
  47. FOut << '\n';
  48. FOut.PadToColumn(PadForDesc);
  49. continue;
  50. }
  51. FOut << C;
  52. }
  53. }
  54. ExplorationStrategyKind
  55. AnalyzerOptions::getExplorationStrategy() const {
  56. auto K =
  57. llvm::StringSwitch<llvm::Optional<ExplorationStrategyKind>>(
  58. ExplorationStrategy)
  59. .Case("dfs", ExplorationStrategyKind::DFS)
  60. .Case("bfs", ExplorationStrategyKind::BFS)
  61. .Case("unexplored_first",
  62. ExplorationStrategyKind::UnexploredFirst)
  63. .Case("unexplored_first_queue",
  64. ExplorationStrategyKind::UnexploredFirstQueue)
  65. .Case("unexplored_first_location_queue",
  66. ExplorationStrategyKind::UnexploredFirstLocationQueue)
  67. .Case("bfs_block_dfs_contents",
  68. ExplorationStrategyKind::BFSBlockDFSContents)
  69. .Default(None);
  70. assert(K.hasValue() && "User mode is invalid.");
  71. return K.getValue();
  72. }
  73. IPAKind AnalyzerOptions::getIPAMode() const {
  74. auto K = llvm::StringSwitch<llvm::Optional<IPAKind>>(IPAMode)
  75. .Case("none", IPAK_None)
  76. .Case("basic-inlining", IPAK_BasicInlining)
  77. .Case("inlining", IPAK_Inlining)
  78. .Case("dynamic", IPAK_DynamicDispatch)
  79. .Case("dynamic-bifurcate", IPAK_DynamicDispatchBifurcate)
  80. .Default(None);
  81. assert(K.hasValue() && "IPA Mode is invalid.");
  82. return K.getValue();
  83. }
  84. bool
  85. AnalyzerOptions::mayInlineCXXMemberFunction(
  86. CXXInlineableMemberKind Param) const {
  87. if (getIPAMode() < IPAK_Inlining)
  88. return false;
  89. auto K =
  90. llvm::StringSwitch<llvm::Optional<CXXInlineableMemberKind>>(
  91. CXXMemberInliningMode)
  92. .Case("constructors", CIMK_Constructors)
  93. .Case("destructors", CIMK_Destructors)
  94. .Case("methods", CIMK_MemberFunctions)
  95. .Case("none", CIMK_None)
  96. .Default(None);
  97. assert(K.hasValue() && "Invalid c++ member function inlining mode.");
  98. return *K >= Param;
  99. }
  100. StringRef AnalyzerOptions::getCheckerStringOption(StringRef CheckerName,
  101. StringRef OptionName,
  102. bool SearchInParents) const {
  103. assert(!CheckerName.empty() &&
  104. "Empty checker name! Make sure the checker object (including it's "
  105. "bases!) if fully initialized before calling this function!");
  106. ConfigTable::const_iterator E = Config.end();
  107. do {
  108. ConfigTable::const_iterator I =
  109. Config.find((Twine(CheckerName) + ":" + OptionName).str());
  110. if (I != E)
  111. return StringRef(I->getValue());
  112. size_t Pos = CheckerName.rfind('.');
  113. if (Pos == StringRef::npos)
  114. break;
  115. CheckerName = CheckerName.substr(0, Pos);
  116. } while (!CheckerName.empty() && SearchInParents);
  117. llvm_unreachable("Unknown checker option! Did you call getChecker*Option "
  118. "with incorrect parameters? User input must've been "
  119. "verified by CheckerRegistry.");
  120. return "";
  121. }
  122. StringRef AnalyzerOptions::getCheckerStringOption(const ento::CheckerBase *C,
  123. StringRef OptionName,
  124. bool SearchInParents) const {
  125. return getCheckerStringOption(
  126. C->getTagDescription(), OptionName, SearchInParents);
  127. }
  128. bool AnalyzerOptions::getCheckerBooleanOption(StringRef CheckerName,
  129. StringRef OptionName,
  130. bool SearchInParents) const {
  131. auto Ret = llvm::StringSwitch<llvm::Optional<bool>>(
  132. getCheckerStringOption(CheckerName, OptionName,
  133. SearchInParents))
  134. .Case("true", true)
  135. .Case("false", false)
  136. .Default(None);
  137. assert(Ret &&
  138. "This option should be either 'true' or 'false', and should've been "
  139. "validated by CheckerRegistry!");
  140. return *Ret;
  141. }
  142. bool AnalyzerOptions::getCheckerBooleanOption(const ento::CheckerBase *C,
  143. StringRef OptionName,
  144. bool SearchInParents) const {
  145. return getCheckerBooleanOption(
  146. C->getTagDescription(), OptionName, SearchInParents);
  147. }
  148. int AnalyzerOptions::getCheckerIntegerOption(StringRef CheckerName,
  149. StringRef OptionName,
  150. bool SearchInParents) const {
  151. int Ret = 0;
  152. bool HasFailed = getCheckerStringOption(CheckerName, OptionName,
  153. SearchInParents)
  154. .getAsInteger(0, Ret);
  155. assert(!HasFailed &&
  156. "This option should be numeric, and should've been validated by "
  157. "CheckerRegistry!");
  158. (void)HasFailed;
  159. return Ret;
  160. }
  161. int AnalyzerOptions::getCheckerIntegerOption(const ento::CheckerBase *C,
  162. StringRef OptionName,
  163. bool SearchInParents) const {
  164. return getCheckerIntegerOption(
  165. C->getTagDescription(), OptionName, SearchInParents);
  166. }