clang  10.0.0svn
CheckerRegistry.cpp
Go to the documentation of this file.
1 //===- CheckerRegistry.cpp - Maintains all available 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 
10 #include "clang/Basic/Diagnostic.h"
11 #include "clang/Basic/LLVM.h"
17 #include "llvm/ADT/STLExtras.h"
18 #include "llvm/ADT/SetVector.h"
19 #include "llvm/ADT/StringMap.h"
20 #include "llvm/ADT/StringRef.h"
21 #include "llvm/Support/DynamicLibrary.h"
22 #include "llvm/Support/Path.h"
23 #include "llvm/Support/raw_ostream.h"
24 #include <algorithm>
25 
26 using namespace clang;
27 using namespace ento;
28 using llvm::sys::DynamicLibrary;
29 
30 using RegisterCheckersFn = void (*)(CheckerRegistry &);
31 
32 static bool isCompatibleAPIVersion(const char *VersionString) {
33  // If the version string is null, its not an analyzer plugin.
34  if (!VersionString)
35  return false;
36 
37  // For now, none of the static analyzer API is considered stable.
38  // Versions must match exactly.
39  return strcmp(VersionString, CLANG_ANALYZER_API_VERSION_STRING) == 0;
40 }
41 
42 namespace {
43 template <class T> struct FullNameLT {
44  bool operator()(const T &Lhs, const T &Rhs) {
45  return Lhs.FullName < Rhs.FullName;
46  }
47 };
48 
49 using PackageNameLT = FullNameLT<CheckerRegistry::PackageInfo>;
50 using CheckerNameLT = FullNameLT<CheckerRegistry::CheckerInfo>;
51 } // end of anonymous namespace
52 
53 template <class CheckerOrPackageInfoList>
54 static
55  typename std::conditional<std::is_const<CheckerOrPackageInfoList>::value,
56  typename CheckerOrPackageInfoList::const_iterator,
57  typename CheckerOrPackageInfoList::iterator>::type
58  binaryFind(CheckerOrPackageInfoList &Collection, StringRef FullName) {
59 
60  using CheckerOrPackage = typename CheckerOrPackageInfoList::value_type;
61  using CheckerOrPackageFullNameLT = FullNameLT<CheckerOrPackage>;
62 
63  assert(std::is_sorted(Collection.begin(), Collection.end(),
64  CheckerOrPackageFullNameLT{}) &&
65  "In order to efficiently gather checkers/packages, this function "
66  "expects them to be already sorted!");
67 
68  return llvm::lower_bound(Collection, CheckerOrPackage(FullName),
69  CheckerOrPackageFullNameLT{});
70 }
71 
72 static constexpr char PackageSeparator = '.';
73 
74 static bool isInPackage(const CheckerRegistry::CheckerInfo &Checker,
75  StringRef PackageName) {
76  // Does the checker's full name have the package as a prefix?
77  if (!Checker.FullName.startswith(PackageName))
78  return false;
79 
80  // Is the package actually just the name of a specific checker?
81  if (Checker.FullName.size() == PackageName.size())
82  return true;
83 
84  // Is the checker in the package (or a subpackage)?
85  if (Checker.FullName[PackageName.size()] == PackageSeparator)
86  return true;
87 
88  return false;
89 }
90 
92 CheckerRegistry::getMutableCheckersForCmdLineArg(StringRef CmdLineArg) {
93  auto It = binaryFind(Checkers, CmdLineArg);
94 
95  if (!isInPackage(*It, CmdLineArg))
96  return {Checkers.end(), Checkers.end()};
97 
98  // See how large the package is.
99  // If the package doesn't exist, assume the option refers to a single
100  // checker.
101  size_t Size = 1;
102  llvm::StringMap<size_t>::const_iterator PackageSize =
103  PackageSizes.find(CmdLineArg);
104 
105  if (PackageSize != PackageSizes.end())
106  Size = PackageSize->getValue();
107 
108  return {It, It + Size};
109 }
110 
113  AnalyzerOptions &AnOpts, const LangOptions &LangOpts,
114  ArrayRef<std::function<void(CheckerRegistry &)>> CheckerRegistrationFns)
115  : Diags(Diags), AnOpts(AnOpts), LangOpts(LangOpts) {
116 
117  // Register builtin checkers.
118 #define GET_CHECKERS
119 #define CHECKER(FULLNAME, CLASS, HELPTEXT, DOC_URI, IS_HIDDEN) \
120  addChecker(register##CLASS, shouldRegister##CLASS, FULLNAME, HELPTEXT, \
121  DOC_URI, IS_HIDDEN);
122 
123 #define GET_PACKAGES
124 #define PACKAGE(FULLNAME) addPackage(FULLNAME);
125 
126 #include "clang/StaticAnalyzer/Checkers/Checkers.inc"
127 #undef CHECKER
128 #undef GET_CHECKERS
129 #undef PACKAGE
130 #undef GET_PACKAGES
131 
132  // Register checkers from plugins.
133  for (const std::string &Plugin : Plugins) {
134  // Get access to the plugin.
135  std::string ErrorMsg;
136  DynamicLibrary Lib =
137  DynamicLibrary::getPermanentLibrary(Plugin.c_str(), &ErrorMsg);
138  if (!Lib.isValid()) {
139  Diags.Report(diag::err_fe_unable_to_load_plugin) << Plugin << ErrorMsg;
140  continue;
141  }
142 
143  // See if its compatible with this build of clang.
144  const char *PluginAPIVersion = static_cast<const char *>(
145  Lib.getAddressOfSymbol("clang_analyzerAPIVersionString"));
146 
147  if (!isCompatibleAPIVersion(PluginAPIVersion)) {
148  Diags.Report(diag::warn_incompatible_analyzer_plugin_api)
149  << llvm::sys::path::filename(Plugin);
150  Diags.Report(diag::note_incompatible_analyzer_plugin_api)
151  << CLANG_ANALYZER_API_VERSION_STRING << PluginAPIVersion;
152  continue;
153  }
154 
155  // Register its checkers.
156  RegisterCheckersFn RegisterPluginCheckers =
157  reinterpret_cast<RegisterCheckersFn>(
158  Lib.getAddressOfSymbol("clang_registerCheckers"));
159  if (RegisterPluginCheckers)
160  RegisterPluginCheckers(*this);
161  }
162 
163  // Register statically linked checkers, that aren't generated from the tblgen
164  // file, but rather passed their registry function as a parameter in
165  // checkerRegistrationFns.
166 
167  for (const auto &Fn : CheckerRegistrationFns)
168  Fn(*this);
169 
170  // Sort checkers for efficient collection.
171  // FIXME: Alphabetical sort puts 'experimental' in the middle.
172  // Would it be better to name it '~experimental' or something else
173  // that's ASCIIbetically last?
174  llvm::sort(Packages, PackageNameLT{});
175  llvm::sort(Checkers, CheckerNameLT{});
176 
177 #define GET_CHECKER_DEPENDENCIES
178 
179 #define CHECKER_DEPENDENCY(FULLNAME, DEPENDENCY) \
180  addDependency(FULLNAME, DEPENDENCY);
181 
182 #define GET_CHECKER_OPTIONS
183 #define CHECKER_OPTION(TYPE, FULLNAME, CMDFLAG, DESC, DEFAULT_VAL, DEVELOPMENT_STATUS, IS_HIDDEN) \
184  addCheckerOption(TYPE, FULLNAME, CMDFLAG, DEFAULT_VAL, DESC, DEVELOPMENT_STATUS, IS_HIDDEN);
185 
186 #define GET_PACKAGE_OPTIONS
187 #define PACKAGE_OPTION(TYPE, FULLNAME, CMDFLAG, DESC, DEFAULT_VAL, DEVELOPMENT_STATUS, IS_HIDDEN) \
188  addPackageOption(TYPE, FULLNAME, CMDFLAG, DEFAULT_VAL, DESC, DEVELOPMENT_STATUS, IS_HIDDEN);
189 
190 #include "clang/StaticAnalyzer/Checkers/Checkers.inc"
191 #undef CHECKER_DEPENDENCY
192 #undef GET_CHECKER_DEPENDENCIES
193 #undef CHECKER_OPTION
194 #undef GET_CHECKER_OPTIONS
195 #undef PACKAGE_OPTION
196 #undef GET_PACKAGE_OPTIONS
197 
198  resolveDependencies();
199  resolveCheckerAndPackageOptions();
200 
201  // Parse '-analyzer-checker' and '-analyzer-disable-checker' options from the
202  // command line.
203  for (const std::pair<std::string, bool> &Opt : AnOpts.CheckersAndPackages) {
204  CheckerInfoListRange CheckerForCmdLineArg =
205  getMutableCheckersForCmdLineArg(Opt.first);
206 
207  if (CheckerForCmdLineArg.begin() == CheckerForCmdLineArg.end()) {
208  Diags.Report(diag::err_unknown_analyzer_checker_or_package) << Opt.first;
209  Diags.Report(diag::note_suggest_disabling_all_checkers);
210  }
211 
212  for (CheckerInfo &checker : CheckerForCmdLineArg) {
213  checker.State = Opt.second ? StateFromCmdLine::State_Enabled
215  }
216  }
217 }
218 
219 /// Collects dependencies in \p ret, returns false on failure.
220 static bool
222  const LangOptions &LO,
224 
225 /// Collects dependenies in \p enabledCheckers. Return None on failure.
226 LLVM_NODISCARD
228 collectDependencies(const CheckerRegistry::CheckerInfo &checker,
229  const LangOptions &LO) {
230 
232  // Add dependencies to the enabled checkers only if all of them can be
233  // enabled.
234  if (!collectDependenciesImpl(checker.Dependencies, LO, Ret))
235  return None;
236 
237  return Ret;
238 }
239 
240 static bool
242  const LangOptions &LO,
244 
245  for (const CheckerRegistry::CheckerInfo *Dependency : Deps) {
246 
247  if (Dependency->isDisabled(LO))
248  return false;
249 
250  // Collect dependencies recursively.
251  if (!collectDependenciesImpl(Dependency->Dependencies, LO, Ret))
252  return false;
253 
254  Ret.insert(Dependency);
255  }
256 
257  return true;
258 }
259 
260 CheckerRegistry::CheckerInfoSet CheckerRegistry::getEnabledCheckers() const {
261 
262  CheckerInfoSet EnabledCheckers;
263 
264  for (const CheckerInfo &Checker : Checkers) {
265  if (!Checker.isEnabled(LangOpts))
266  continue;
267 
268  // Recursively enable its dependencies.
270  collectDependencies(Checker, LangOpts);
271 
272  if (!Deps) {
273  // If we failed to enable any of the dependencies, don't enable this
274  // checker.
275  continue;
276  }
277 
278  // Note that set_union also preserves the order of insertion.
279  EnabledCheckers.set_union(*Deps);
280 
281  // Enable the checker.
282  EnabledCheckers.insert(&Checker);
283  }
284 
285  return EnabledCheckers;
286 }
287 
288 void CheckerRegistry::resolveDependencies() {
289  for (const std::pair<StringRef, StringRef> &Entry : Dependencies) {
290  auto CheckerIt = binaryFind(Checkers, Entry.first);
291  assert(CheckerIt != Checkers.end() && CheckerIt->FullName == Entry.first &&
292  "Failed to find the checker while attempting to set up its "
293  "dependencies!");
294 
295  auto DependencyIt = binaryFind(Checkers, Entry.second);
296  assert(DependencyIt != Checkers.end() &&
297  DependencyIt->FullName == Entry.second &&
298  "Failed to find the dependency of a checker!");
299 
300  CheckerIt->Dependencies.emplace_back(&*DependencyIt);
301  }
302 
303  Dependencies.clear();
304 }
305 
306 void CheckerRegistry::addDependency(StringRef FullName, StringRef Dependency) {
307  Dependencies.emplace_back(FullName, Dependency);
308 }
309 
310 /// Insert the checker/package option to AnalyzerOptions' config table, and
311 /// validate it, if the user supplied it on the command line.
312 static void insertAndValidate(StringRef FullName,
313  const CheckerRegistry::CmdLineOption &Option,
314  AnalyzerOptions &AnOpts,
315  DiagnosticsEngine &Diags) {
316 
317  std::string FullOption = (FullName + ":" + Option.OptionName).str();
318 
319  auto It = AnOpts.Config.insert({FullOption, Option.DefaultValStr});
320 
321  // Insertation was successful -- CmdLineOption's constructor will validate
322  // whether values received from plugins or TableGen files are correct.
323  if (It.second)
324  return;
325 
326  // Insertion failed, the user supplied this package/checker option on the
327  // command line. If the supplied value is invalid, we'll restore the option
328  // to it's default value, and if we're in non-compatibility mode, we'll also
329  // emit an error.
330 
331  StringRef SuppliedValue = It.first->getValue();
332 
333  if (Option.OptionType == "bool") {
334  if (SuppliedValue != "true" && SuppliedValue != "false") {
336  Diags.Report(diag::err_analyzer_checker_option_invalid_input)
337  << FullOption << "a boolean value";
338  }
339 
340  It.first->setValue(Option.DefaultValStr);
341  }
342  return;
343  }
344 
345  if (Option.OptionType == "int") {
346  int Tmp;
347  bool HasFailed = SuppliedValue.getAsInteger(0, Tmp);
348  if (HasFailed) {
350  Diags.Report(diag::err_analyzer_checker_option_invalid_input)
351  << FullOption << "an integer value";
352  }
353 
354  It.first->setValue(Option.DefaultValStr);
355  }
356  return;
357  }
358 }
359 
360 template <class T>
361 static void
362 insertOptionToCollection(StringRef FullName, T &Collection,
363  const CheckerRegistry::CmdLineOption &Option,
364  AnalyzerOptions &AnOpts, DiagnosticsEngine &Diags) {
365  auto It = binaryFind(Collection, FullName);
366  assert(It != Collection.end() &&
367  "Failed to find the checker while attempting to add a command line "
368  "option to it!");
369 
370  insertAndValidate(FullName, Option, AnOpts, Diags);
371 
372  It->CmdLineOptions.emplace_back(Option);
373 }
374 
375 void CheckerRegistry::resolveCheckerAndPackageOptions() {
376  for (const std::pair<StringRef, CmdLineOption> &CheckerOptEntry :
377  CheckerOptions) {
378  insertOptionToCollection(CheckerOptEntry.first, Checkers,
379  CheckerOptEntry.second, AnOpts, Diags);
380  }
381  CheckerOptions.clear();
382 
383  for (const std::pair<StringRef, CmdLineOption> &PackageOptEntry :
384  PackageOptions) {
385  insertOptionToCollection(PackageOptEntry.first, Packages,
386  PackageOptEntry.second, AnOpts, Diags);
387  }
388  PackageOptions.clear();
389 }
390 
391 void CheckerRegistry::addPackage(StringRef FullName) {
392  Packages.emplace_back(PackageInfo(FullName));
393 }
394 
395 void CheckerRegistry::addPackageOption(StringRef OptionType,
396  StringRef PackageFullName,
397  StringRef OptionName,
398  StringRef DefaultValStr,
399  StringRef Description,
400  StringRef DevelopmentStatus,
401  bool IsHidden) {
402  PackageOptions.emplace_back(
403  PackageFullName, CmdLineOption{OptionType, OptionName, DefaultValStr,
404  Description, DevelopmentStatus, IsHidden});
405 }
406 
408  ShouldRegisterFunction Sfn, StringRef Name,
409  StringRef Desc, StringRef DocsUri,
410  bool IsHidden) {
411  Checkers.emplace_back(Rfn, Sfn, Name, Desc, DocsUri, IsHidden);
412 
413  // Record the presence of the checker in its packages.
414  StringRef PackageName, LeafName;
415  std::tie(PackageName, LeafName) = Name.rsplit(PackageSeparator);
416  while (!LeafName.empty()) {
417  PackageSizes[PackageName] += 1;
418  std::tie(PackageName, LeafName) = PackageName.rsplit(PackageSeparator);
419  }
420 }
421 
422 void CheckerRegistry::addCheckerOption(StringRef OptionType,
423  StringRef CheckerFullName,
424  StringRef OptionName,
425  StringRef DefaultValStr,
426  StringRef Description,
427  StringRef DevelopmentStatus,
428  bool IsHidden) {
429  CheckerOptions.emplace_back(
430  CheckerFullName, CmdLineOption{OptionType, OptionName, DefaultValStr,
431  Description, DevelopmentStatus, IsHidden});
432 }
433 
434 void CheckerRegistry::initializeManager(CheckerManager &CheckerMgr) const {
435  // Collect checkers enabled by the options.
436  CheckerInfoSet enabledCheckers = getEnabledCheckers();
437 
438  // Initialize the CheckerManager with all enabled checkers.
439  for (const auto *Checker : enabledCheckers) {
440  CheckerMgr.setCurrentCheckName(CheckName(Checker->FullName));
441  Checker->Initialize(CheckerMgr);
442  }
443 }
444 
445 static void
447  StringRef SuppliedChecker, StringRef SuppliedOption,
448  const AnalyzerOptions &AnOpts, DiagnosticsEngine &Diags) {
449 
451  return;
452 
453  using CmdLineOption = CheckerRegistry::CmdLineOption;
454 
455  auto SameOptName = [SuppliedOption](const CmdLineOption &Opt) {
456  return Opt.OptionName == SuppliedOption;
457  };
458 
459  auto OptionIt = llvm::find_if(OptionList, SameOptName);
460 
461  if (OptionIt == OptionList.end()) {
462  Diags.Report(diag::err_analyzer_checker_option_unknown)
463  << SuppliedChecker << SuppliedOption;
464  return;
465  }
466 }
467 
469  for (const auto &Config : AnOpts.Config) {
470 
471  StringRef SuppliedCheckerOrPackage;
472  StringRef SuppliedOption;
473  std::tie(SuppliedCheckerOrPackage, SuppliedOption) =
474  Config.getKey().split(':');
475 
476  if (SuppliedOption.empty())
477  continue;
478 
479  // AnalyzerOptions' config table contains the user input, so an entry could
480  // look like this:
481  //
482  // cor:NoFalsePositives=true
483  //
484  // Since lower_bound would look for the first element *not less* than "cor",
485  // it would return with an iterator to the first checker in the core, so we
486  // we really have to use find here, which uses operator==.
487  auto CheckerIt =
488  llvm::find(Checkers, CheckerInfo(SuppliedCheckerOrPackage));
489  if (CheckerIt != Checkers.end()) {
490  isOptionContainedIn(CheckerIt->CmdLineOptions, SuppliedCheckerOrPackage,
491  SuppliedOption, AnOpts, Diags);
492  continue;
493  }
494 
495  auto PackageIt =
496  llvm::find(Packages, PackageInfo(SuppliedCheckerOrPackage));
497  if (PackageIt != Packages.end()) {
498  isOptionContainedIn(PackageIt->CmdLineOptions, SuppliedCheckerOrPackage,
499  SuppliedOption, AnOpts, Diags);
500  continue;
501  }
502 
503  Diags.Report(diag::err_unknown_analyzer_checker_or_package)
504  << SuppliedCheckerOrPackage;
505  }
506 }
507 
509  size_t MaxNameChars) const {
510  // FIXME: Print available packages.
511 
512  Out << "CHECKERS:\n";
513 
514  // Find the maximum option length.
515  size_t OptionFieldWidth = 0;
516  for (const auto &Checker : Checkers) {
517  // Limit the amount of padding we are willing to give up for alignment.
518  // Package.Name Description [Hidden]
519  size_t NameLength = Checker.FullName.size();
520  if (NameLength <= MaxNameChars)
521  OptionFieldWidth = std::max(OptionFieldWidth, NameLength);
522  }
523 
524  const size_t InitialPad = 2;
525 
526  auto Print = [=](llvm::raw_ostream &Out, const CheckerInfo &Checker,
527  StringRef Description) {
528  AnalyzerOptions::printFormattedEntry(Out, {Checker.FullName, Description},
529  InitialPad, OptionFieldWidth);
530  Out << '\n';
531  };
532 
533  for (const auto &Checker : Checkers) {
534  // The order of this if branches is significant, we wouldn't like to display
535  // developer checkers even in the alpha output. For example,
536  // alpha.cplusplus.IteratorModeling is a modeling checker, hence it's hidden
537  // by default, and users (even when the user is a developer of an alpha
538  // checker) shouldn't normally tinker with whether they should be enabled.
539 
540  if (Checker.IsHidden) {
541  if (AnOpts.ShowCheckerHelpDeveloper)
542  Print(Out, Checker, Checker.Desc);
543  continue;
544  }
545 
546  if (Checker.FullName.startswith("alpha")) {
547  if (AnOpts.ShowCheckerHelpAlpha)
548  Print(Out, Checker,
549  ("(Enable only for development!) " + Checker.Desc).str());
550  continue;
551  }
552 
553  if (AnOpts.ShowCheckerHelp)
554  Print(Out, Checker, Checker.Desc);
555  }
556 }
557 
558 void CheckerRegistry::printEnabledCheckerList(raw_ostream &Out) const {
559  // Collect checkers enabled by the options.
560  CheckerInfoSet EnabledCheckers = getEnabledCheckers();
561 
562  for (const auto *i : EnabledCheckers)
563  Out << i->FullName << '\n';
564 }
565 
566 void CheckerRegistry::printCheckerOptionList(raw_ostream &Out) const {
567  Out << "OVERVIEW: Clang Static Analyzer Checker and Package Option List\n\n";
568  Out << "USAGE: -analyzer-config <OPTION1=VALUE,OPTION2=VALUE,...>\n\n";
569  Out << " -analyzer-config OPTION1=VALUE, -analyzer-config "
570  "OPTION2=VALUE, ...\n\n";
571  Out << "OPTIONS:\n\n";
572 
573  std::multimap<StringRef, const CmdLineOption &> OptionMap;
574 
575  for (const CheckerInfo &Checker : Checkers) {
576  for (const CmdLineOption &Option : Checker.CmdLineOptions) {
577  OptionMap.insert({Checker.FullName, Option});
578  }
579  }
580 
581  for (const PackageInfo &Package : Packages) {
582  for (const CmdLineOption &Option : Package.CmdLineOptions) {
583  OptionMap.insert({Package.FullName, Option});
584  }
585  }
586 
587  auto Print = [] (llvm::raw_ostream &Out, StringRef FullOption, StringRef Desc) {
588  AnalyzerOptions::printFormattedEntry(Out, {FullOption, Desc},
589  /*InitialPad*/ 2,
590  /*EntryWidth*/ 50,
591  /*MinLineWidth*/ 90);
592  Out << "\n\n";
593  };
594  for (const std::pair<StringRef, const CmdLineOption &> &Entry : OptionMap) {
595  const CmdLineOption &Option = Entry.second;
596  std::string FullOption = (Entry.first + ":" + Option.OptionName).str();
597 
598  std::string Desc =
599  ("(" + Option.OptionType + ") " + Option.Description + " (default: " +
600  (Option.DefaultValStr.empty() ? "\"\"" : Option.DefaultValStr) + ")")
601  .str();
602 
603  // The list of these if branches is significant, we wouldn't like to
604  // display hidden alpha checker options for
605  // -analyzer-checker-option-help-alpha.
606 
607  if (Option.IsHidden) {
609  Print(Out, FullOption, Desc);
610  continue;
611  }
612 
613  if (Option.DevelopmentStatus == "alpha" ||
614  Entry.first.startswith("alpha")) {
615  if (AnOpts.ShowCheckerOptionAlphaList)
616  Print(Out, FullOption,
617  llvm::Twine("(Enable only for development!) " + Desc).str());
618  continue;
619  }
620 
621  if (AnOpts.ShowCheckerOptionList)
622  Print(Out, FullOption, Desc);
623  }
624 }
Manages a set of available checkers for running a static analysis.
void addChecker(InitializationFunction Fn, ShouldRegisterFunction sfn, StringRef FullName, StringRef Desc, StringRef DocsUri, bool IsHidden)
Adds a checker to the registry.
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
Definition: Diagnostic.h:1297
void addPackageOption(StringRef OptionType, StringRef PackageFullName, StringRef OptionName, StringRef DefaultValStr, StringRef Description, StringRef DevelopmentStatus, bool IsHidden=false)
Registers an option to a given package.
void printCheckerWithDescList(raw_ostream &Out, size_t MaxNameChars=30) const
Prints the name and description of all checkers in this registry.
void printEnabledCheckerList(raw_ostream &Out) const
#define CLANG_ANALYZER_API_VERSION_STRING
static bool isCompatibleAPIVersion(const char *VersionString)
static void printFormattedEntry(llvm::raw_ostream &Out, std::pair< StringRef, StringRef > EntryDescPair, size_t EntryWidth, size_t InitialPad, size_t MinLineWidth=0)
Convenience function for printing options or checkers and their description in a formatted manner...
__DEVICE__ int max(int __a, int __b)
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
Definition: LangOptions.h:49
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified...
void setCurrentCheckName(CheckName name)
Concrete class used by the front-end to report problems and issues.
Definition: Diagnostic.h:149
void addPackage(StringRef FullName)
Adds a package to the registry.
Defines the Diagnostic-related interfaces.
void(*)(CheckerRegistry &) RegisterCheckersFn
static void insertAndValidate(StringRef FullName, const CheckerRegistry::CmdLineOption &Option, AnalyzerOptions &AnOpts, DiagnosticsEngine &Diags)
Insert the checker/package option to AnalyzerOptions&#39; config table, and validate it, if the user supplied it on the command line.
static void insertOptionToCollection(StringRef FullName, T &Collection, const CheckerRegistry::CmdLineOption &Option, AnalyzerOptions &AnOpts, DiagnosticsEngine &Diags)
static LLVM_NODISCARD llvm::Optional< CheckerRegistry::CheckerInfoSet > collectDependencies(const CheckerRegistry::CheckerInfo &checker, const LangOptions &LO)
Collects dependenies in enabledCheckers. Return None on failure.
void addCheckerOption(StringRef OptionType, StringRef CheckerFullName, StringRef OptionName, StringRef DefaultValStr, StringRef Description, StringRef DevelopmentStatus, bool IsHidden=false)
Registers an option to a given checker.
static bool isInPackage(const CheckerRegistry::CheckerInfo &Checker, StringRef PackageName)
static void isOptionContainedIn(const CheckerRegistry::CmdLineOptionList &OptionList, StringRef SuppliedChecker, StringRef SuppliedOption, const AnalyzerOptions &AnOpts, DiagnosticsEngine &Diags)
llvm::SmallVector< const CheckerInfo *, 0 > ConstCheckerInfoList
bool(*)(const LangOptions &) ShouldRegisterFunction
ConfigTable Config
A key-value table of use-specified configuration values.
unsigned ShowCheckerOptionDeveloperList
std::vector< std::pair< std::string, bool > > CheckersAndPackages
Pairs of checker/package name and enable/disable.
void printCheckerOptionList(raw_ostream &Out) const
llvm::SmallVector< CmdLineOption, 0 > CmdLineOptionList
llvm::SetVector< const CheckerInfo * > CheckerInfoSet
Dataflow Directional Tag Classes.
llvm::iterator_range< CheckerInfoList::iterator > CheckerInfoListRange
void addDependency(StringRef FullName, StringRef Dependency)
Makes the checker with the full name fullName depends on the checker called dependency.
static bool collectDependenciesImpl(const CheckerRegistry::ConstCheckerInfoList &Deps, const LangOptions &LO, CheckerRegistry::CheckerInfoSet &Ret)
Collects dependencies in ret, returns false on failure.
void(*)(CheckerManager &) InitializationFunction
Initialization functions perform any necessary setup for a checker.
static std::conditional< std::is_const< CheckerOrPackageInfoList >::value, typename CheckerOrPackageInfoList::const_iterator, typename CheckerOrPackageInfoList::iterator >::type binaryFind(CheckerOrPackageInfoList &Collection, StringRef FullName)
CheckerRegistry(ArrayRef< std::string > plugins, DiagnosticsEngine &diags, AnalyzerOptions &AnOpts, const LangOptions &LangOpts, ArrayRef< std::function< void(CheckerRegistry &)>> checkerRegistrationFns={})
Stores options for the analyzer from the command line.
Specifies a command line option.
void validateCheckerOptions() const
Check if every option corresponds to a specific checker or package.
unsigned ShouldEmitErrorsOnInvalidConfigValue
static constexpr char PackageSeparator