Clang Project

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