1218887Sdim//===--- CheckerRegistration.cpp - Registration for the Analyzer Checkers -===//
2218887Sdim//
3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4353358Sdim// See https://llvm.org/LICENSE.txt for license information.
5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6218887Sdim//
7218887Sdim//===----------------------------------------------------------------------===//
8218887Sdim//
9218887Sdim// Defines the registration function for the analyzer checkers.
10218887Sdim//
11218887Sdim//===----------------------------------------------------------------------===//
12218887Sdim
13218887Sdim#include "clang/StaticAnalyzer/Frontend/CheckerRegistration.h"
14249423Sdim#include "clang/Basic/Diagnostic.h"
15249423Sdim#include "clang/Frontend/FrontendDiagnostic.h"
16249423Sdim#include "clang/StaticAnalyzer/Core/AnalyzerOptions.h"
17218887Sdim#include "clang/StaticAnalyzer/Core/CheckerManager.h"
18344779Sdim#include "clang/StaticAnalyzer/Frontend/CheckerRegistry.h"
19249423Sdim#include "clang/StaticAnalyzer/Frontend/FrontendActions.h"
20249423Sdim#include "llvm/ADT/SmallVector.h"
21219077Sdim#include "llvm/Support/raw_ostream.h"
22276479Sdim#include <memory>
23218887Sdim
24218887Sdimusing namespace clang;
25218887Sdimusing namespace ento;
26218887Sdim
27341825Sdimstd::unique_ptr<CheckerManager> ento::createCheckerManager(
28344779Sdim    ASTContext &context,
29344779Sdim    AnalyzerOptions &opts,
30341825Sdim    ArrayRef<std::string> plugins,
31341825Sdim    ArrayRef<std::function<void(CheckerRegistry &)>> checkerRegistrationFns,
32341825Sdim    DiagnosticsEngine &diags) {
33360784Sdim  auto checkerMgr = std::make_unique<CheckerManager>(context, opts);
34218887Sdim
35353358Sdim  CheckerRegistry allCheckers(plugins, diags, opts, context.getLangOpts(),
36353358Sdim                              checkerRegistrationFns);
37218887Sdim
38353358Sdim  allCheckers.initializeManager(*checkerMgr);
39353358Sdim  allCheckers.validateCheckerOptions();
40221345Sdim  checkerMgr->finishedCheckerRegistration();
41221345Sdim
42288943Sdim  return checkerMgr;
43218887Sdim}
44219077Sdim
45344779Sdimvoid ento::printCheckerHelp(raw_ostream &out, ArrayRef<std::string> plugins,
46353358Sdim                            AnalyzerOptions &anopts,
47353358Sdim                            DiagnosticsEngine &diags,
48353358Sdim                            const LangOptions &langOpts) {
49226633Sdim  out << "OVERVIEW: Clang Static Analyzer Checkers List\n\n";
50226633Sdim  out << "USAGE: -analyzer-checker <CHECKER or PACKAGE,...>\n\n";
51219077Sdim
52353358Sdim  CheckerRegistry(plugins, diags, anopts, langOpts)
53353358Sdim      .printCheckerWithDescList(out);
54219077Sdim}
55314564Sdim
56314564Sdimvoid ento::printEnabledCheckerList(raw_ostream &out,
57314564Sdim                                   ArrayRef<std::string> plugins,
58353358Sdim                                   AnalyzerOptions &anopts,
59353358Sdim                                   DiagnosticsEngine &diags,
60353358Sdim                                   const LangOptions &langOpts) {
61314564Sdim  out << "OVERVIEW: Clang Static Analyzer Enabled Checkers List\n\n";
62314564Sdim
63353358Sdim  CheckerRegistry(plugins, diags, anopts, langOpts)
64353358Sdim      .printEnabledCheckerList(out);
65314564Sdim}
66344779Sdim
67353358Sdimvoid ento::printCheckerConfigList(raw_ostream &OS,
68353358Sdim                                  ArrayRef<std::string> plugins,
69353358Sdim                                  AnalyzerOptions &opts,
70353358Sdim                                  DiagnosticsEngine &diags,
71353358Sdim                                  const LangOptions &LangOpts) {
72353358Sdim  CheckerRegistry(plugins, diags, opts, LangOpts)
73353358Sdim      .printCheckerOptionList(OS);
74353358Sdim}
75353358Sdim
76344779Sdimvoid ento::printAnalyzerConfigList(raw_ostream &out) {
77360784Sdim  // FIXME: This message sounds scary, should be scary, but incorrectly states
78360784Sdim  // that all configs are super dangerous. In reality, many of them should be
79360784Sdim  // accessible to the user. We should create a user-facing subset of config
80360784Sdim  // options under a different frontend flag.
81360784Sdim  out << R"(
82360784SdimOVERVIEW: Clang Static Analyzer -analyzer-config Option List
83344779Sdim
84360784SdimThe following list of configurations are meant for development purposes only, as
85360784Sdimsome of the variables they define are set to result in the most optimal
86360784Sdimanalysis. Setting them to other values may drastically change how the analyzer
87360784Sdimbehaves, and may even result in instabilities, crashes!
88360784Sdim
89360784SdimUSAGE: -analyzer-config <OPTION1=VALUE,OPTION2=VALUE,...>
90360784Sdim       -analyzer-config OPTION1=VALUE, -analyzer-config OPTION2=VALUE, ...
91360784SdimOPTIONS:
92360784Sdim)";
93360784Sdim
94344779Sdim  using OptionAndDescriptionTy = std::pair<StringRef, std::string>;
95344779Sdim  OptionAndDescriptionTy PrintableOptions[] = {
96344779Sdim#define ANALYZER_OPTION(TYPE, NAME, CMDFLAG, DESC, DEFAULT_VAL)                \
97344779Sdim    {                                                                          \
98344779Sdim      CMDFLAG,                                                                 \
99344779Sdim      llvm::Twine(llvm::Twine() + "(" +                                        \
100344779Sdim                  (StringRef(#TYPE) == "StringRef" ? "string" : #TYPE ) +      \
101344779Sdim                  ") " DESC                                                    \
102344779Sdim                  " (default: " #DEFAULT_VAL ")").str()                        \
103344779Sdim    },
104344779Sdim
105344779Sdim#define ANALYZER_OPTION_DEPENDS_ON_USER_MODE(TYPE, NAME, CMDFLAG, DESC,        \
106344779Sdim                                             SHALLOW_VAL, DEEP_VAL)            \
107344779Sdim    {                                                                          \
108344779Sdim      CMDFLAG,                                                                 \
109344779Sdim      llvm::Twine(llvm::Twine() + "(" +                                        \
110344779Sdim                  (StringRef(#TYPE) == "StringRef" ? "string" : #TYPE ) +      \
111344779Sdim                  ") " DESC                                                    \
112344779Sdim                  " (default: " #SHALLOW_VAL " in shallow mode, " #DEEP_VAL    \
113344779Sdim                  " in deep mode)").str()                                      \
114344779Sdim    },
115344779Sdim#include "clang/StaticAnalyzer/Core/AnalyzerOptions.def"
116344779Sdim#undef ANALYZER_OPTION
117344779Sdim#undef ANALYZER_OPTION_DEPENDS_ON_USER_MODE
118344779Sdim  };
119344779Sdim
120344779Sdim  llvm::sort(PrintableOptions, [](const OptionAndDescriptionTy &LHS,
121344779Sdim                                  const OptionAndDescriptionTy &RHS) {
122344779Sdim    return LHS.first < RHS.first;
123344779Sdim  });
124344779Sdim
125344779Sdim  for (const auto &Pair : PrintableOptions) {
126353358Sdim    AnalyzerOptions::printFormattedEntry(out, Pair, /*InitialPad*/ 2,
127353358Sdim                                         /*EntryWidth*/ 30,
128353358Sdim                                         /*MinLineWidth*/ 70);
129353358Sdim    out << "\n\n";
130344779Sdim  }
131344779Sdim}
132