clang  6.0.0svn
CheckerRegistry.cpp
Go to the documentation of this file.
1 //===--- CheckerRegistry.cpp - Maintains all available checkers -*- C++ -*-===//
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"
15 #include "llvm/ADT/SetVector.h"
16 #include "llvm/Support/raw_ostream.h"
17 
18 using namespace clang;
19 using namespace ento;
20 
21 static const char PackageSeparator = '.';
22 typedef llvm::SetVector<const CheckerRegistry::CheckerInfo *> CheckerInfoSet;
23 
24 
27  return a.FullName < b.FullName;
28 }
29 
30 static bool isInPackage(const CheckerRegistry::CheckerInfo &checker,
31  StringRef packageName) {
32  // Does the checker's full name have the package as a prefix?
33  if (!checker.FullName.startswith(packageName))
34  return false;
35 
36  // Is the package actually just the name of a specific checker?
37  if (checker.FullName.size() == packageName.size())
38  return true;
39 
40  // Is the checker in the package (or a subpackage)?
41  if (checker.FullName[packageName.size()] == PackageSeparator)
42  return true;
43 
44  return false;
45 }
46 
48  const llvm::StringMap<size_t> &packageSizes,
49  CheckerOptInfo &opt, CheckerInfoSet &collected) {
50  // Use a binary search to find the possible start of the package.
51  CheckerRegistry::CheckerInfo packageInfo(nullptr, opt.getName(), "");
52  auto end = checkers.cend();
53  CheckerRegistry::CheckerInfoList::const_iterator i =
54  std::lower_bound(checkers.cbegin(), end, packageInfo, checkerNameLT);
55 
56  // If we didn't even find a possible package, give up.
57  if (i == end)
58  return;
59 
60  // If what we found doesn't actually start the package, give up.
61  if (!isInPackage(*i, opt.getName()))
62  return;
63 
64  // There is at least one checker in the package; claim the option.
65  opt.claim();
66 
67  // See how large the package is.
68  // If the package doesn't exist, assume the option refers to a single checker.
69  size_t size = 1;
70  llvm::StringMap<size_t>::const_iterator packageSize =
71  packageSizes.find(opt.getName());
72  if (packageSize != packageSizes.end())
73  size = packageSize->getValue();
74 
75  // Step through all the checkers in the package.
76  for (auto checkEnd = i+size; i != checkEnd; ++i) {
77  if (opt.isEnabled())
78  collected.insert(&*i);
79  else
80  collected.remove(&*i);
81  }
82 }
83 
84 void CheckerRegistry::addChecker(InitializationFunction fn, StringRef name,
85  StringRef desc) {
86  Checkers.push_back(CheckerInfo(fn, name, desc));
87 
88  // Record the presence of the checker in its packages.
89  StringRef packageName, leafName;
90  std::tie(packageName, leafName) = name.rsplit(PackageSeparator);
91  while (!leafName.empty()) {
92  Packages[packageName] += 1;
93  std::tie(packageName, leafName) = packageName.rsplit(PackageSeparator);
94  }
95 }
96 
97 void CheckerRegistry::initializeManager(CheckerManager &checkerMgr,
98  SmallVectorImpl<CheckerOptInfo> &opts) const {
99  // Sort checkers for efficient collection.
100  std::sort(Checkers.begin(), Checkers.end(), checkerNameLT);
101 
102  // Collect checkers enabled by the options.
103  CheckerInfoSet enabledCheckers;
105  i = opts.begin(), e = opts.end(); i != e; ++i) {
106  collectCheckers(Checkers, Packages, *i, enabledCheckers);
107  }
108 
109  // Initialize the CheckerManager with all enabled checkers.
110  for (CheckerInfoSet::iterator
111  i = enabledCheckers.begin(), e = enabledCheckers.end(); i != e; ++i) {
112  checkerMgr.setCurrentCheckName(CheckName((*i)->FullName));
113  (*i)->Initialize(checkerMgr);
114  }
115 }
116 
118  DiagnosticsEngine &diags) const {
119  for (auto &config : opts.Config) {
120  size_t pos = config.getKey().find(':');
121  if (pos == StringRef::npos)
122  continue;
123 
124  bool hasChecker = false;
125  StringRef checkerName = config.getKey().substr(0, pos);
126  for (auto &checker : Checkers) {
127  if (checker.FullName.startswith(checkerName) &&
128  (checker.FullName.size() == pos || checker.FullName[pos] == '.')) {
129  hasChecker = true;
130  break;
131  }
132  }
133  if (!hasChecker) {
134  diags.Report(diag::err_unknown_analyzer_checker) << checkerName;
135  }
136  }
137 }
138 
139 void CheckerRegistry::printHelp(raw_ostream &out,
140  size_t maxNameChars) const {
141  // FIXME: Alphabetical sort puts 'experimental' in the middle.
142  // Would it be better to name it '~experimental' or something else
143  // that's ASCIIbetically last?
144  std::sort(Checkers.begin(), Checkers.end(), checkerNameLT);
145 
146  // FIXME: Print available packages.
147 
148  out << "CHECKERS:\n";
149 
150  // Find the maximum option length.
151  size_t optionFieldWidth = 0;
152  for (CheckerInfoList::const_iterator i = Checkers.begin(), e = Checkers.end();
153  i != e; ++i) {
154  // Limit the amount of padding we are willing to give up for alignment.
155  // Package.Name Description [Hidden]
156  size_t nameLength = i->FullName.size();
157  if (nameLength <= maxNameChars)
158  optionFieldWidth = std::max(optionFieldWidth, nameLength);
159  }
160 
161  const size_t initialPad = 2;
162  for (CheckerInfoList::const_iterator i = Checkers.begin(), e = Checkers.end();
163  i != e; ++i) {
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  std::sort(Checkers.begin(), Checkers.end(), checkerNameLT);
182 
183  // Collect checkers enabled by the options.
184  CheckerInfoSet enabledCheckers;
185  for (SmallVectorImpl<CheckerOptInfo>::iterator i = opts.begin(),
186  e = opts.end();
187  i != e; ++i) {
188  collectCheckers(Checkers, Packages, *i, enabledCheckers);
189  }
190 
191  for (CheckerInfoSet::const_iterator i = enabledCheckers.begin(),
192  e = enabledCheckers.end();
193  i != e; ++i) {
194  out << (*i)->FullName << '\n';
195  }
196 }
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)
StringRef getName() const
static const char PackageSeparator
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
Definition: Diagnostic.h:1207
Represents a request to include or exclude a checker or package from a specific analysis run...
llvm::SetVector< const CheckerRegistry::CheckerInfo * > CheckerInfoSet
void addChecker(InitializationFunction fn, StringRef fullName, StringRef desc)
Adds a checker to the registry.
void setCurrentCheckName(CheckName name)
Concrete class used by the front-end to report problems and issues.
Definition: Diagnostic.h:147
Defines the Diagnostic-related interfaces.
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)
char __ovld __cnfn max(char x, char y)
Returns y if x < y, otherwise it returns x.
void printHelp(raw_ostream &out, size_t maxNameChars=30) const
Prints the name and description of all checkers in this registry.
static bool isInPackage(const CheckerRegistry::CheckerInfo &checker, StringRef packageName)
std::vector< CheckerInfo > CheckerInfoList