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