Coverage Report

Created: 2019-07-24 05:18

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