clang  8.0.0svn
CheckerRegistry.cpp
Go to the documentation of this file.
1 //===- CheckerRegistry.cpp - Maintains all available checkers -------------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
11 #include "clang/Basic/Diagnostic.h"
12 #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/raw_ostream.h"
22 #include <algorithm>
23 #include <cstddef>
24 #include <tuple>
25 
26 using namespace clang;
27 using namespace ento;
28 
29 static const char PackageSeparator = '.';
30 
31 using CheckerInfoSet = llvm::SetVector<const CheckerRegistry::CheckerInfo *>;
32 
33 static bool checkerNameLT(const CheckerRegistry::CheckerInfo &a,
34  const CheckerRegistry::CheckerInfo &b) {
35  return a.FullName < b.FullName;
36 }
37 
38 static bool isInPackage(const CheckerRegistry::CheckerInfo &checker,
39  StringRef packageName) {
40  // Does the checker's full name have the package as a prefix?
41  if (!checker.FullName.startswith(packageName))
42  return false;
43 
44  // Is the package actually just the name of a specific checker?
45  if (checker.FullName.size() == packageName.size())
46  return true;
47 
48  // Is the checker in the package (or a subpackage)?
49  if (checker.FullName[packageName.size()] == PackageSeparator)
50  return true;
51 
52  return false;
53 }
54 
56  const llvm::StringMap<size_t> &packageSizes,
57  CheckerOptInfo &opt, CheckerInfoSet &collected) {
58  // Use a binary search to find the possible start of the package.
59  CheckerRegistry::CheckerInfo packageInfo(nullptr, opt.getName(), "");
60  auto end = checkers.cend();
61  auto i = std::lower_bound(checkers.cbegin(), end, packageInfo, checkerNameLT);
62 
63  // If we didn't even find a possible package, give up.
64  if (i == end)
65  return;
66 
67  // If what we found doesn't actually start the package, give up.
68  if (!isInPackage(*i, opt.getName()))
69  return;
70 
71  // There is at least one checker in the package; claim the option.
72  opt.claim();
73 
74  // See how large the package is.
75  // If the package doesn't exist, assume the option refers to a single checker.
76  size_t size = 1;
77  llvm::StringMap<size_t>::const_iterator packageSize =
78  packageSizes.find(opt.getName());
79  if (packageSize != packageSizes.end())
80  size = packageSize->getValue();
81 
82  // Step through all the checkers in the package.
83  for (auto checkEnd = i+size; i != checkEnd; ++i)
84  if (opt.isEnabled())
85  collected.insert(&*i);
86  else
87  collected.remove(&*i);
88 }
89 
90 void CheckerRegistry::addChecker(InitializationFunction fn, StringRef name,
91  StringRef desc) {
92  Checkers.push_back(CheckerInfo(fn, name, desc));
93 
94  // Record the presence of the checker in its packages.
95  StringRef packageName, leafName;
96  std::tie(packageName, leafName) = name.rsplit(PackageSeparator);
97  while (!leafName.empty()) {
98  Packages[packageName] += 1;
99  std::tie(packageName, leafName) = packageName.rsplit(PackageSeparator);
100  }
101 }
102 
103 void CheckerRegistry::initializeManager(CheckerManager &checkerMgr,
104  SmallVectorImpl<CheckerOptInfo> &opts) const {
105  // Sort checkers for efficient collection.
106  llvm::sort(Checkers.begin(), Checkers.end(), checkerNameLT);
107 
108  // Collect checkers enabled by the options.
109  CheckerInfoSet enabledCheckers;
110  for (auto &i : opts)
111  collectCheckers(Checkers, Packages, i, enabledCheckers);
112 
113  // Initialize the CheckerManager with all enabled checkers.
114  for (const auto *i :enabledCheckers) {
115  checkerMgr.setCurrentCheckName(CheckName(i->FullName));
116  i->Initialize(checkerMgr);
117  }
118 }
119 
121  DiagnosticsEngine &diags) const {
122  for (const auto &config : opts.Config) {
123  size_t pos = config.getKey().find(':');
124  if (pos == StringRef::npos)
125  continue;
126 
127  bool hasChecker = false;
128  StringRef checkerName = config.getKey().substr(0, pos);
129  for (const auto &checker : Checkers) {
130  if (checker.FullName.startswith(checkerName) &&
131  (checker.FullName.size() == pos || checker.FullName[pos] == '.')) {
132  hasChecker = true;
133  break;
134  }
135  }
136  if (!hasChecker)
137  diags.Report(diag::err_unknown_analyzer_checker) << checkerName;
138  }
139 }
140 
141 void CheckerRegistry::printHelp(raw_ostream &out,
142  size_t maxNameChars) const {
143  // FIXME: Alphabetical sort puts 'experimental' in the middle.
144  // Would it be better to name it '~experimental' or something else
145  // that's ASCIIbetically last?
146  llvm::sort(Checkers.begin(), Checkers.end(), checkerNameLT);
147 
148  // FIXME: Print available packages.
149 
150  out << "CHECKERS:\n";
151 
152  // Find the maximum option length.
153  size_t optionFieldWidth = 0;
154  for (const auto &i : Checkers) {
155  // Limit the amount of padding we are willing to give up for alignment.
156  // Package.Name Description [Hidden]
157  size_t nameLength = i.FullName.size();
158  if (nameLength <= maxNameChars)
159  optionFieldWidth = std::max(optionFieldWidth, nameLength);
160  }
161 
162  const size_t initialPad = 2;
163  for (const auto &i : Checkers) {
164  out.indent(initialPad) << i.FullName;
165 
166  int pad = optionFieldWidth - i.FullName.size();
167 
168  // Break on long option names.
169  if (pad < 0) {
170  out << '\n';
171  pad = optionFieldWidth + initialPad;
172  }
173  out.indent(pad + 2) << i.Desc;
174 
175  out << '\n';
176  }
177 }
178 
180  raw_ostream &out, SmallVectorImpl<CheckerOptInfo> &opts) const {
181  llvm::sort(Checkers.begin(), Checkers.end(), checkerNameLT);
182 
183  // Collect checkers enabled by the options.
184  CheckerInfoSet enabledCheckers;
185  for (auto &i : opts)
186  collectCheckers(Checkers, Packages, i, enabledCheckers);
187 
188  for (const auto *i : enabledCheckers)
189  out << i->FullName << '\n';
190 }
void validateCheckerOptions(const AnalyzerOptions &opts, DiagnosticsEngine &diags) const
Check if every option corresponds to a specific checker or package.
static void collectCheckers(const CheckerRegistry::CheckerInfoList &checkers, const llvm::StringMap< size_t > &packageSizes, CheckerOptInfo &opt, CheckerInfoSet &collected)
static const char PackageSeparator
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
Definition: Diagnostic.h:1294
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
Defines the Diagnostic-related interfaces.
void addChecker(InitializationFunction fn, StringRef fullName, StringRef desc)
Adds a checker to the registry.
void printList(raw_ostream &out, SmallVectorImpl< CheckerOptInfo > &opts) const
ConfigTable Config
A key-value table of use-specified configuration values.
Dataflow Directional Tag Classes.
static bool checkerNameLT(const CheckerRegistry::CheckerInfo &a, const CheckerRegistry::CheckerInfo &b)
std::vector< CheckerInfo > CheckerInfoList
llvm::SetVector< const CheckerRegistry::CheckerInfo * > CheckerInfoSet
void printHelp(raw_ostream &out, size_t maxNameChars=30) const
Prints the name and description of all checkers in this registry.
__DEVICE__ int max(int __a, int __b)
static bool isInPackage(const CheckerRegistry::CheckerInfo &checker, StringRef packageName)