Fix formatting after Module.h include adjustment, NFC
[lldb.git] / clang / include / clang / StaticAnalyzer / Frontend / CheckerRegistry.h
1 //===- CheckerRegistry.h - Maintains all available checkers -----*- C++ -*-===//
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 #ifndef LLVM_CLANG_STATICANALYZER_CORE_CHECKERREGISTRY_H
10 #define LLVM_CLANG_STATICANALYZER_CORE_CHECKERREGISTRY_H
11
12 #include "clang/Basic/LLVM.h"
13 #include "clang/StaticAnalyzer/Core/CheckerManager.h"
14 #include "llvm/ADT/SetVector.h"
15 #include "llvm/ADT/StringMap.h"
16 #include "llvm/ADT/StringRef.h"
17 #include <cstddef>
18 #include <vector>
19
20 // FIXME: move this information to an HTML file in docs/.
21 // At the very least, a checker plugin is a dynamic library that exports
22 // clang_analyzerAPIVersionString. This should be defined as follows:
23 //
24 //   extern "C"
25 //   const char clang_analyzerAPIVersionString[] =
26 //     CLANG_ANALYZER_API_VERSION_STRING;
27 //
28 // This is used to check whether the current version of the analyzer is known to
29 // be incompatible with a plugin. Plugins with incompatible version strings,
30 // or without a version string at all, will not be loaded.
31 //
32 // To add a custom checker to the analyzer, the plugin must also define the
33 // function clang_registerCheckers. For example:
34 //
35 //    extern "C"
36 //    void clang_registerCheckers (CheckerRegistry &registry) {
37 //      registry.addChecker<MainCallChecker>("example.MainCallChecker",
38 //        "Disallows calls to functions called main");
39 //    }
40 //
41 // The first method argument is the full name of the checker, including its
42 // enclosing package. By convention, the registered name of a checker is the
43 // name of the associated class (the template argument).
44 // The second method argument is a short human-readable description of the
45 // checker.
46 //
47 // The clang_registerCheckers function may add any number of checkers to the
48 // registry. If any checkers require additional initialization, use the three-
49 // argument form of CheckerRegistry::addChecker.
50 //
51 // To load a checker plugin, specify the full path to the dynamic library as
52 // the argument to the -load option in the cc1 frontend. You can then enable
53 // your custom checker using the -analyzer-checker:
54 //
55 //   clang -cc1 -load </path/to/plugin.dylib> -analyze
56 //     -analyzer-checker=<example.MainCallChecker>
57 //
58 // For a complete working example, see examples/analyzer-plugin.
59
60 #ifndef CLANG_ANALYZER_API_VERSION_STRING
61 // FIXME: The Clang version string is not particularly granular;
62 // the analyzer infrastructure can change a lot between releases.
63 // Unfortunately, this string has to be statically embedded in each plugin,
64 // so we can't just use the functions defined in Version.h.
65 #include "clang/Basic/Version.h"
66 #define CLANG_ANALYZER_API_VERSION_STRING CLANG_VERSION_STRING
67 #endif
68
69 namespace clang {
70
71 class AnalyzerOptions;
72 class DiagnosticsEngine;
73 class LangOptions;
74
75 namespace ento {
76
77 /// Manages a set of available checkers for running a static analysis.
78 /// The checkers are organized into packages by full name, where including
79 /// a package will recursively include all subpackages and checkers within it.
80 /// For example, the checker "core.builtin.NoReturnFunctionChecker" will be
81 /// included if initializeManager() is called with an option of "core",
82 /// "core.builtin", or the full name "core.builtin.NoReturnFunctionChecker".
83 class CheckerRegistry {
84 public:
85   CheckerRegistry(ArrayRef<std::string> plugins, DiagnosticsEngine &diags,
86                   AnalyzerOptions &AnOpts, const LangOptions &LangOpts,
87                   ArrayRef<std::function<void(CheckerRegistry &)>>
88                       checkerRegistrationFns = {});
89
90   /// Initialization functions perform any necessary setup for a checker.
91   /// They should include a call to CheckerManager::registerChecker.
92   using InitializationFunction = void (*)(CheckerManager &);
93   using ShouldRegisterFunction = bool (*)(const LangOptions &);
94
95   /// Specifies a command line option. It may either belong to a checker or a
96   /// package.
97   struct CmdLineOption {
98     StringRef OptionType;
99     StringRef OptionName;
100     StringRef DefaultValStr;
101     StringRef Description;
102     StringRef DevelopmentStatus;
103     bool IsHidden;
104
105     CmdLineOption(StringRef OptionType, StringRef OptionName,
106                   StringRef DefaultValStr, StringRef Description,
107                   StringRef DevelopmentStatus, bool IsHidden)
108         : OptionType(OptionType), OptionName(OptionName),
109           DefaultValStr(DefaultValStr), Description(Description),
110           DevelopmentStatus(DevelopmentStatus), IsHidden(IsHidden) {
111
112       assert((OptionType == "bool" || OptionType == "string" ||
113               OptionType == "int") &&
114              "Unknown command line option type!");
115
116       assert((OptionType != "bool" ||
117               (DefaultValStr == "true" || DefaultValStr == "false")) &&
118              "Invalid value for boolean command line option! Maybe incorrect "
119              "parameters to the addCheckerOption or addPackageOption method?");
120
121       int Tmp;
122       assert((OptionType != "int" || !DefaultValStr.getAsInteger(0, Tmp)) &&
123              "Invalid value for integer command line option! Maybe incorrect "
124              "parameters to the addCheckerOption or addPackageOption method?");
125       (void)Tmp;
126
127       assert((DevelopmentStatus == "alpha" || DevelopmentStatus == "beta" ||
128               DevelopmentStatus == "released") &&
129              "Invalid development status!");
130     }
131   };
132
133   using CmdLineOptionList = llvm::SmallVector<CmdLineOption, 0>;
134
135   struct CheckerInfo;
136
137   using CheckerInfoList = std::vector<CheckerInfo>;
138   using CheckerInfoListRange = llvm::iterator_range<CheckerInfoList::iterator>;
139   using ConstCheckerInfoList = llvm::SmallVector<const CheckerInfo *, 0>;
140   using CheckerInfoSet = llvm::SetVector<const CheckerInfo *>;
141
142   /// Specifies a checker. Note that this isn't what we call a checker object,
143   /// it merely contains everything required to create one.
144   struct CheckerInfo {
145     enum class StateFromCmdLine {
146       // This checker wasn't explicitly enabled or disabled.
147       State_Unspecified,
148       // This checker was explicitly disabled.
149       State_Disabled,
150       // This checker was explicitly enabled.
151       State_Enabled
152     };
153
154     InitializationFunction Initialize = nullptr;
155     ShouldRegisterFunction ShouldRegister = nullptr;
156     StringRef FullName;
157     StringRef Desc;
158     StringRef DocumentationUri;
159     CmdLineOptionList CmdLineOptions;
160     bool IsHidden = false;
161     StateFromCmdLine State = StateFromCmdLine::State_Unspecified;
162
163     ConstCheckerInfoList Dependencies;
164
165     bool isEnabled(const LangOptions &LO) const {
166       return State == StateFromCmdLine::State_Enabled && ShouldRegister(LO);
167     }
168
169     bool isDisabled(const LangOptions &LO) const {
170       return State == StateFromCmdLine::State_Disabled && ShouldRegister(LO);
171     }
172
173     // Since each checker must have a different full name, we can identify
174     // CheckerInfo objects by them.
175     bool operator==(const CheckerInfo &Rhs) const {
176       return FullName == Rhs.FullName;
177     }
178
179     CheckerInfo(InitializationFunction Fn, ShouldRegisterFunction sfn,
180                 StringRef Name, StringRef Desc, StringRef DocsUri,
181                 bool IsHidden)
182         : Initialize(Fn), ShouldRegister(sfn), FullName(Name), Desc(Desc),
183           DocumentationUri(DocsUri), IsHidden(IsHidden) {}
184
185     // Used for lower_bound.
186     explicit CheckerInfo(StringRef FullName) : FullName(FullName) {}
187   };
188
189   using StateFromCmdLine = CheckerInfo::StateFromCmdLine;
190
191   /// Specifies a package. Each package option is implicitly an option for all
192   /// checkers within the package.
193   struct PackageInfo {
194     StringRef FullName;
195     CmdLineOptionList CmdLineOptions;
196
197     // Since each package must have a different full name, we can identify
198     // CheckerInfo objects by them.
199     bool operator==(const PackageInfo &Rhs) const {
200       return FullName == Rhs.FullName;
201     }
202
203     explicit PackageInfo(StringRef FullName) : FullName(FullName) {}
204   };
205
206   using PackageInfoList = llvm::SmallVector<PackageInfo, 0>;
207
208   template <typename T> static void addToCheckerMgr(CheckerManager &mgr) {
209     mgr.registerChecker<T>();
210   }
211
212   static bool returnTrue(const LangOptions &LO) {
213     return true;
214   }
215
216   /// Adds a checker to the registry. Use this non-templated overload when your
217   /// checker requires custom initialization.
218   void addChecker(InitializationFunction Fn, ShouldRegisterFunction sfn,
219                   StringRef FullName, StringRef Desc, StringRef DocsUri,
220                   bool IsHidden);
221
222   /// Adds a checker to the registry. Use this templated overload when your
223   /// checker does not require any custom initialization.
224   template <class T>
225   void addChecker(StringRef FullName, StringRef Desc, StringRef DocsUri,
226                   bool IsHidden = false) {
227     // Avoid MSVC's Compiler Error C2276:
228     // http://msdn.microsoft.com/en-us/library/850cstw1(v=VS.80).aspx
229     addChecker(&CheckerRegistry::addToCheckerMgr<T>,
230                &CheckerRegistry::returnTrue, FullName, Desc, DocsUri, IsHidden);
231   }
232
233   /// Makes the checker with the full name \p fullName depends on the checker
234   /// called \p dependency.
235   void addDependency(StringRef FullName, StringRef Dependency);
236
237   /// Registers an option to a given checker. A checker option will always have
238   /// the following format:
239   ///   CheckerFullName:OptionName=Value
240   /// And can be specified from the command line like this:
241   ///   -analyzer-config CheckerFullName:OptionName=Value
242   ///
243   /// Options for unknown checkers, or unknown options for a given checker, or
244   /// invalid value types for that given option are reported as an error in
245   /// non-compatibility mode.
246   void addCheckerOption(StringRef OptionType, StringRef CheckerFullName,
247                         StringRef OptionName, StringRef DefaultValStr,
248                         StringRef Description, StringRef DevelopmentStatus,
249                         bool IsHidden = false);
250
251   /// Adds a package to the registry.
252   void addPackage(StringRef FullName);
253
254   /// Registers an option to a given package. A package option will always have
255   /// the following format:
256   ///   PackageFullName:OptionName=Value
257   /// And can be specified from the command line like this:
258   ///   -analyzer-config PackageFullName:OptionName=Value
259   ///
260   /// Options for unknown packages, or unknown options for a given package, or
261   /// invalid value types for that given option are reported as an error in
262   /// non-compatibility mode.
263   void addPackageOption(StringRef OptionType, StringRef PackageFullName,
264                         StringRef OptionName, StringRef DefaultValStr,
265                         StringRef Description, StringRef DevelopmentStatus,
266                          bool IsHidden = false);
267
268   // FIXME: This *really* should be added to the frontend flag descriptions.
269   /// Initializes a CheckerManager by calling the initialization functions for
270   /// all checkers specified by the given CheckerOptInfo list. The order of this
271   /// list is significant; later options can be used to reverse earlier ones.
272   /// This can be used to exclude certain checkers in an included package.
273   void initializeManager(CheckerManager &CheckerMgr) const;
274
275   /// Check if every option corresponds to a specific checker or package.
276   void validateCheckerOptions() const;
277
278   /// Prints the name and description of all checkers in this registry.
279   /// This output is not intended to be machine-parseable.
280   void printCheckerWithDescList(raw_ostream &Out,
281                                 size_t MaxNameChars = 30) const;
282   void printEnabledCheckerList(raw_ostream &Out) const;
283   void printCheckerOptionList(raw_ostream &Out) const;
284
285 private:
286   /// Collect all enabled checkers. The returned container preserves the order
287   /// of insertion, as dependencies have to be enabled before the checkers that
288   /// depend on them.
289   CheckerInfoSet getEnabledCheckers() const;
290
291   /// Return an iterator range of mutable CheckerInfos \p CmdLineArg applies to.
292   /// For example, it'll return the checkers for the core package, if
293   /// \p CmdLineArg is "core".
294   CheckerInfoListRange getMutableCheckersForCmdLineArg(StringRef CmdLineArg);
295
296   CheckerInfoList Checkers;
297   PackageInfoList Packages;
298   /// Used for couting how many checkers belong to a certain package in the
299   /// \c Checkers field. For convenience purposes.
300   llvm::StringMap<size_t> PackageSizes;
301
302   /// Contains all (Dependendent checker, Dependency) pairs. We need this, as
303   /// we'll resolve dependencies after all checkers were added first.
304   llvm::SmallVector<std::pair<StringRef, StringRef>, 0> Dependencies;
305   void resolveDependencies();
306
307   /// Contains all (FullName, CmdLineOption) pairs. Similarly to dependencies,
308   /// we only modify the actual CheckerInfo and PackageInfo objects once all
309   /// of them have been added.
310   llvm::SmallVector<std::pair<StringRef, CmdLineOption>, 0> PackageOptions;
311   llvm::SmallVector<std::pair<StringRef, CmdLineOption>, 0> CheckerOptions;
312
313   void resolveCheckerAndPackageOptions();
314
315   DiagnosticsEngine &Diags;
316   AnalyzerOptions &AnOpts;
317   const LangOptions &LangOpts;
318 };
319
320 } // namespace ento
321 } // namespace clang
322
323 #endif // LLVM_CLANG_STATICANALYZER_CORE_CHECKERREGISTRY_H