]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - contrib/llvm/tools/clang/lib/StaticAnalyzer/Core/CheckerRegistry.cpp
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / contrib / llvm / tools / clang / lib / StaticAnalyzer / Core / CheckerRegistry.cpp
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
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"
14
15 using namespace clang;
16 using namespace ento;
17
18 static const char PackageSeparator = '.';
19 typedef llvm::SetVector<const CheckerRegistry::CheckerInfo *> CheckerInfoSet;
20
21
22 static bool checkerNameLT(const CheckerRegistry::CheckerInfo &a,
23                           const CheckerRegistry::CheckerInfo &b) {
24   return a.FullName < b.FullName;
25 }
26
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))
31     return false;
32
33   // Is the package actually just the name of a specific checker?
34   if (checker.FullName.size() == packageName.size())
35     return true;
36
37   // Is the checker in the package (or a subpackage)?
38   if (checker.FullName[packageName.size()] == PackageSeparator)
39     return true;
40
41   return false;
42 }
43
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);
52
53   // If we didn't even find a possible package, give up.
54   if (i == e)
55     return;
56
57   // If what we found doesn't actually start the package, give up.
58   if (!isInPackage(*i, opt.getName()))
59     return;
60
61   // There is at least one checker in the package; claim the option.
62   opt.claim();
63
64   // See how large the package is.
65   // If the package doesn't exist, assume the option refers to a single checker.
66   size_t size = 1;
67   llvm::StringMap<size_t>::const_iterator packageSize =
68     packageSizes.find(opt.getName());
69   if (packageSize != packageSizes.end())
70     size = packageSize->getValue();
71
72   // Step through all the checkers in the package.
73   for (e = i+size; i != e; ++i) {
74     if (opt.isEnabled())
75       collected.insert(&*i);
76     else
77       collected.remove(&*i);
78   }
79 }
80
81 void CheckerRegistry::addChecker(InitializationFunction fn, StringRef name,
82                                  StringRef desc) {
83   Checkers.push_back(CheckerInfo(fn, name, desc));
84
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);
91   }
92 }
93
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);
98
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);
104   }
105
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);
110   }
111 }
112
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);
119
120   // FIXME: Print available packages.
121
122   out << "CHECKERS:\n";
123
124   // Find the maximum option length.
125   size_t optionFieldWidth = 0;
126   for (CheckerInfoList::const_iterator i = Checkers.begin(), e = Checkers.end();
127        i != e; ++i) {
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);
133   }
134
135   const size_t initialPad = 2;
136   for (CheckerInfoList::const_iterator i = Checkers.begin(), e = Checkers.end();
137        i != e; ++i) {
138     out.indent(initialPad) << i->FullName;
139
140     int pad = optionFieldWidth - i->FullName.size();
141
142     // Break on long option names.
143     if (pad < 0) {
144       out << '\n';
145       pad = optionFieldWidth + initialPad;
146     }
147     out.indent(pad + 2) << i->Desc;
148
149     out << '\n';
150   }
151 }