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