1 //===--- CheckerRegistry.cpp - Maintains all available checkers -*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #include "clang/StaticAnalyzer/Core/CheckerRegistry.h"
11 #include "clang/StaticAnalyzer/Core/CheckerOptInfo.h"
13 using namespace clang;
16 static const char PackageSeparator = '.';
17 typedef llvm::DenseSet<const CheckerRegistry::CheckerInfo *> CheckerInfoSet;
20 static bool checkerNameLT(const CheckerRegistry::CheckerInfo &a,
21 const CheckerRegistry::CheckerInfo &b) {
22 return a.FullName < b.FullName;
25 static bool isInPackage(const CheckerRegistry::CheckerInfo &checker,
26 StringRef packageName) {
27 // Does the checker's full name have the package as a prefix?
28 if (!checker.FullName.startswith(packageName))
31 // Is the package actually just the name of a specific checker?
32 if (checker.FullName.size() == packageName.size())
35 // Is the checker in the package (or a subpackage)?
36 if (checker.FullName[packageName.size()] == PackageSeparator)
42 static void collectCheckers(const CheckerRegistry::CheckerInfoList &checkers,
43 const llvm::StringMap<size_t> &packageSizes,
44 CheckerOptInfo &opt, CheckerInfoSet &collected) {
45 // Use a binary search to find the possible start of the package.
46 CheckerRegistry::CheckerInfo packageInfo(NULL, opt.getName(), "");
47 CheckerRegistry::CheckerInfoList::const_iterator e = checkers.end();
48 CheckerRegistry::CheckerInfoList::const_iterator i =
49 std::lower_bound(checkers.begin(), e, packageInfo, checkerNameLT);
51 // If we didn't even find a possible package, give up.
55 // If what we found doesn't actually start the package, give up.
56 if (!isInPackage(*i, opt.getName()))
59 // There is at least one checker in the package; claim the option.
62 // See how large the package is.
63 // If the package doesn't exist, assume the option refers to a single checker.
65 llvm::StringMap<size_t>::const_iterator packageSize =
66 packageSizes.find(opt.getName());
67 if (packageSize != packageSizes.end())
68 size = packageSize->getValue();
70 // Step through all the checkers in the package.
71 for (e = i+size; i != e; ++i) {
73 collected.insert(&*i);
79 void CheckerRegistry::addChecker(InitializationFunction fn, StringRef name,
81 Checkers.push_back(CheckerInfo(fn, name, desc));
83 // Record the presence of the checker in its packages.
84 StringRef packageName, leafName;
85 llvm::tie(packageName, leafName) = name.rsplit(PackageSeparator);
86 while (!leafName.empty()) {
87 Packages[packageName] += 1;
88 llvm::tie(packageName, leafName) = packageName.rsplit(PackageSeparator);
92 void CheckerRegistry::initializeManager(CheckerManager &checkerMgr,
93 SmallVectorImpl<CheckerOptInfo> &opts) const {
94 // Sort checkers for efficient collection.
95 std::sort(Checkers.begin(), Checkers.end(), checkerNameLT);
97 // Collect checkers enabled by the options.
98 CheckerInfoSet enabledCheckers;
99 for (SmallVectorImpl<CheckerOptInfo>::iterator
100 i = opts.begin(), e = opts.end(); i != e; ++i) {
101 collectCheckers(Checkers, Packages, *i, enabledCheckers);
104 // Initialize the CheckerManager with all enabled checkers.
105 for (CheckerInfoSet::iterator
106 i = enabledCheckers.begin(), e = enabledCheckers.end(); i != e; ++i) {
107 (*i)->Initialize(checkerMgr);
111 void CheckerRegistry::printHelp(llvm::raw_ostream &out,
112 size_t maxNameChars) const {
113 // FIXME: Alphabetical sort puts 'experimental' in the middle.
114 // Would it be better to name it '~experimental' or something else
115 // that's ASCIIbetically last?
116 std::sort(Checkers.begin(), Checkers.end(), checkerNameLT);
118 // FIXME: Print available packages.
120 out << "CHECKERS:\n";
122 // Find the maximum option length.
123 size_t optionFieldWidth = 0;
124 for (CheckerInfoList::const_iterator i = Checkers.begin(), e = Checkers.end();
126 // Limit the amount of padding we are willing to give up for alignment.
127 // Package.Name Description [Hidden]
128 size_t nameLength = i->FullName.size();
129 if (nameLength <= maxNameChars)
130 optionFieldWidth = std::max(optionFieldWidth, nameLength);
133 const size_t initialPad = 2;
134 for (CheckerInfoList::const_iterator i = Checkers.begin(), e = Checkers.end();
136 out.indent(initialPad) << i->FullName;
138 int pad = optionFieldWidth - i->FullName.size();
140 // Break on long option names.
143 pad = optionFieldWidth + initialPad;
145 out.indent(pad + 2) << i->Desc;