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.setCurrentCheckerName(CheckerNameRef(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.
This wrapper is used to ensure that only StringRefs originating from the CheckerRegistry are used as ...
void addChecker(InitializationFunction Fn, ShouldRegisterFunction sfn, StringRef FullName, StringRef Desc, StringRef DocsUri, bool IsHidden)
Adds a checker to the registry.
void setCurrentCheckerName(CheckerNameRef name)
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
Definition: Diagnostic.h:1290
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...
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
static bool Ret(InterpState &S, CodePtr &PC, APValue &Result)
Definition: Interp.cpp:34
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