CheckerRegistration.cpp 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. //===--- CheckerRegistration.cpp - Registration for the Analyzer Checkers -===//
  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. // Defines the registration function for the analyzer checkers.
  10. //
  11. //===----------------------------------------------------------------------===//
  12. #include "clang/StaticAnalyzer/Frontend/CheckerRegistration.h"
  13. #include "clang/Basic/Diagnostic.h"
  14. #include "clang/Frontend/FrontendDiagnostic.h"
  15. #include "clang/StaticAnalyzer/Core/AnalyzerOptions.h"
  16. #include "clang/StaticAnalyzer/Core/CheckerManager.h"
  17. #include "clang/StaticAnalyzer/Frontend/CheckerRegistry.h"
  18. #include "clang/StaticAnalyzer/Frontend/FrontendActions.h"
  19. #include "llvm/ADT/SmallVector.h"
  20. #include "llvm/Support/FormattedStream.h"
  21. #include "llvm/Support/raw_ostream.h"
  22. #include <memory>
  23. using namespace clang;
  24. using namespace ento;
  25. std::unique_ptr<CheckerManager> ento::createCheckerManager(
  26. ASTContext &context,
  27. AnalyzerOptions &opts,
  28. ArrayRef<std::string> plugins,
  29. ArrayRef<std::function<void(CheckerRegistry &)>> checkerRegistrationFns,
  30. DiagnosticsEngine &diags) {
  31. auto checkerMgr = llvm::make_unique<CheckerManager>(context, opts);
  32. CheckerRegistry allCheckers(plugins, diags, opts, context.getLangOpts(),
  33. checkerRegistrationFns);
  34. allCheckers.initializeManager(*checkerMgr);
  35. allCheckers.validateCheckerOptions();
  36. checkerMgr->finishedCheckerRegistration();
  37. return checkerMgr;
  38. }
  39. void ento::printCheckerHelp(raw_ostream &out, ArrayRef<std::string> plugins,
  40. AnalyzerOptions &anopts,
  41. DiagnosticsEngine &diags,
  42. const LangOptions &langOpts) {
  43. out << "OVERVIEW: Clang Static Analyzer Checkers List\n\n";
  44. out << "USAGE: -analyzer-checker <CHECKER or PACKAGE,...>\n\n";
  45. CheckerRegistry(plugins, diags, anopts, langOpts).printHelp(out);
  46. }
  47. void ento::printEnabledCheckerList(raw_ostream &out,
  48. ArrayRef<std::string> plugins,
  49. AnalyzerOptions &anopts,
  50. DiagnosticsEngine &diags,
  51. const LangOptions &langOpts) {
  52. out << "OVERVIEW: Clang Static Analyzer Enabled Checkers List\n\n";
  53. CheckerRegistry(plugins, diags, anopts, langOpts).printList(out);
  54. }
  55. void ento::printAnalyzerConfigList(raw_ostream &out) {
  56. out << "OVERVIEW: Clang Static Analyzer -analyzer-config Option List\n\n";
  57. out << "USAGE: clang -cc1 [CLANG_OPTIONS] -analyzer-config "
  58. "<OPTION1=VALUE,OPTION2=VALUE,...>\n\n";
  59. out << " clang -cc1 [CLANG_OPTIONS] -analyzer-config OPTION1=VALUE, "
  60. "-analyzer-config OPTION2=VALUE, ...\n\n";
  61. out << " clang [CLANG_OPTIONS] -Xclang -analyzer-config -Xclang"
  62. "<OPTION1=VALUE,OPTION2=VALUE,...>\n\n";
  63. out << " clang [CLANG_OPTIONS] -Xclang -analyzer-config -Xclang "
  64. "OPTION1=VALUE, -Xclang -analyzer-config -Xclang "
  65. "OPTION2=VALUE, ...\n\n";
  66. out << "OPTIONS:\n\n";
  67. using OptionAndDescriptionTy = std::pair<StringRef, std::string>;
  68. OptionAndDescriptionTy PrintableOptions[] = {
  69. #define ANALYZER_OPTION(TYPE, NAME, CMDFLAG, DESC, DEFAULT_VAL) \
  70. { \
  71. CMDFLAG, \
  72. llvm::Twine(llvm::Twine() + "(" + \
  73. (StringRef(#TYPE) == "StringRef" ? "string" : #TYPE ) + \
  74. ") " DESC \
  75. " (default: " #DEFAULT_VAL ")").str() \
  76. },
  77. #define ANALYZER_OPTION_DEPENDS_ON_USER_MODE(TYPE, NAME, CMDFLAG, DESC, \
  78. SHALLOW_VAL, DEEP_VAL) \
  79. { \
  80. CMDFLAG, \
  81. llvm::Twine(llvm::Twine() + "(" + \
  82. (StringRef(#TYPE) == "StringRef" ? "string" : #TYPE ) + \
  83. ") " DESC \
  84. " (default: " #SHALLOW_VAL " in shallow mode, " #DEEP_VAL \
  85. " in deep mode)").str() \
  86. },
  87. #include "clang/StaticAnalyzer/Core/AnalyzerOptions.def"
  88. #undef ANALYZER_OPTION
  89. #undef ANALYZER_OPTION_DEPENDS_ON_USER_MODE
  90. };
  91. llvm::sort(PrintableOptions, [](const OptionAndDescriptionTy &LHS,
  92. const OptionAndDescriptionTy &RHS) {
  93. return LHS.first < RHS.first;
  94. });
  95. constexpr size_t MinLineWidth = 70;
  96. constexpr size_t PadForOpt = 2;
  97. constexpr size_t OptionWidth = 30;
  98. constexpr size_t PadForDesc = PadForOpt + OptionWidth;
  99. static_assert(MinLineWidth > PadForDesc, "MinLineWidth must be greater!");
  100. llvm::formatted_raw_ostream FOut(out);
  101. for (const auto &Pair : PrintableOptions) {
  102. FOut.PadToColumn(PadForOpt) << Pair.first;
  103. // If the buffer's length is greater then PadForDesc, print a newline.
  104. if (FOut.getColumn() > PadForDesc)
  105. FOut << '\n';
  106. FOut.PadToColumn(PadForDesc);
  107. for (char C : Pair.second) {
  108. if (FOut.getColumn() > MinLineWidth && C == ' ') {
  109. FOut << '\n';
  110. FOut.PadToColumn(PadForDesc);
  111. continue;
  112. }
  113. FOut << C;
  114. }
  115. FOut << "\n\n";
  116. }
  117. }