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"
12 #include "llvm/ADT/SetVector.h"
13 #include "llvm/Support/raw_ostream.h"
15 using namespace clang;
18 static const char PackageSeparator = '.';
19 typedef llvm::SetVector<const CheckerRegistry::CheckerInfo *> CheckerInfoSet;
22 static bool checkerNameLT(const CheckerRegistry::CheckerInfo &a,
23 const CheckerRegistry::CheckerInfo &b) {
24 return a.FullName < b.FullName;
27 static bool isInPackage(const CheckerRegistry::CheckerInfo &checker,
28 StringRef packageName) {
29 // Does the checker's full name have the package as a prefix?
30 if (!checker.FullName.startswith(packageName))
33 // Is the package actually just the name of a specific checker?
34 if (checker.FullName.size() == packageName.size())
37 // Is the checker in the package (or a subpackage)?
38 if (checker.FullName[packageName.size()] == PackageSeparator)
44 static void collectCheckers(const CheckerRegistry::CheckerInfoList &checkers,
45 const llvm::StringMap<size_t> &packageSizes,
46 CheckerOptInfo &opt, CheckerInfoSet &collected) {
47 // Use a binary search to find the possible start of the package.
48 CheckerRegistry::CheckerInfo packageInfo(NULL, opt.getName(), "");
49 CheckerRegistry::CheckerInfoList::const_iterator e = checkers.end();
50 CheckerRegistry::CheckerInfoList::const_iterator i =
51 std::lower_bound(checkers.begin(), e, packageInfo, checkerNameLT);
53 // If we didn't even find a possible package, give up.
57 // If what we found doesn't actually start the package, give up.
58 if (!isInPackage(*i, opt.getName()))
61 // There is at least one checker in the package; claim the option.
64 // See how large the package is.
65 // If the package doesn't exist, assume the option refers to a single checker.
67 llvm::StringMap<size_t>::const_iterator packageSize =
68 packageSizes.find(opt.getName());
69 if (packageSize != packageSizes.end())
70 size = packageSize->getValue();
72 // Step through all the checkers in the package.
73 for (e = i+size; i != e; ++i) {
75 collected.insert(&*i);
77 collected.remove(&*i);
81 void CheckerRegistry::addChecker(InitializationFunction fn, StringRef name,
83 Checkers.push_back(CheckerInfo(fn, name, desc));
85 // Record the presence of the checker in its packages.
86 StringRef packageName, leafName;
87 llvm::tie(packageName, leafName) = name.rsplit(PackageSeparator);
88 while (!leafName.empty()) {
89 Packages[packageName] += 1;
90 llvm::tie(packageName, leafName) = packageName.rsplit(PackageSeparator);
94 void CheckerRegistry::initializeManager(CheckerManager &checkerMgr,
95 SmallVectorImpl<CheckerOptInfo> &opts) const {
96 // Sort checkers for efficient collection.
97 std::sort(Checkers.begin(), Checkers.end(), checkerNameLT);
99 // Collect checkers enabled by the options.
100 CheckerInfoSet enabledCheckers;
101 for (SmallVectorImpl<CheckerOptInfo>::iterator
102 i = opts.begin(), e = opts.end(); i != e; ++i) {
103 collectCheckers(Checkers, Packages, *i, enabledCheckers);
106 // Initialize the CheckerManager with all enabled checkers.
107 for (CheckerInfoSet::iterator
108 i = enabledCheckers.begin(), e = enabledCheckers.end(); i != e; ++i) {
109 (*i)->Initialize(checkerMgr);
113 void CheckerRegistry::printHelp(raw_ostream &out,
114 size_t maxNameChars) const {
115 // FIXME: Alphabetical sort puts 'experimental' in the middle.
116 // Would it be better to name it '~experimental' or something else
117 // that's ASCIIbetically last?
118 std::sort(Checkers.begin(), Checkers.end(), checkerNameLT);
120 // FIXME: Print available packages.
122 out << "CHECKERS:\n";
124 // Find the maximum option length.
125 size_t optionFieldWidth = 0;
126 for (CheckerInfoList::const_iterator i = Checkers.begin(), e = Checkers.end();
128 // Limit the amount of padding we are willing to give up for alignment.
129 // Package.Name Description [Hidden]
130 size_t nameLength = i->FullName.size();
131 if (nameLength <= maxNameChars)
132 optionFieldWidth = std::max(optionFieldWidth, nameLength);
135 const size_t initialPad = 2;
136 for (CheckerInfoList::const_iterator i = Checkers.begin(), e = Checkers.end();
138 out.indent(initialPad) << i->FullName;
140 int pad = optionFieldWidth - i->FullName.size();
142 // Break on long option names.
145 pad = optionFieldWidth + initialPad;
147 out.indent(pad + 2) << i->Desc;