CheckerRegistry.cpp revision 557a3829ebe0e36785b9a7679dc19dc67dbc7639
108b86531ade68727c56918f162816075b87c864aJordy Rose//===--- CheckerRegistry.cpp - Maintains all available checkers -*- C++ -*-===// 208b86531ade68727c56918f162816075b87c864aJordy Rose// 308b86531ade68727c56918f162816075b87c864aJordy Rose// The LLVM Compiler Infrastructure 408b86531ade68727c56918f162816075b87c864aJordy Rose// 508b86531ade68727c56918f162816075b87c864aJordy Rose// This file is distributed under the University of Illinois Open Source 608b86531ade68727c56918f162816075b87c864aJordy Rose// License. See LICENSE.TXT for details. 708b86531ade68727c56918f162816075b87c864aJordy Rose// 808b86531ade68727c56918f162816075b87c864aJordy Rose//===----------------------------------------------------------------------===// 908b86531ade68727c56918f162816075b87c864aJordy Rose 1008b86531ade68727c56918f162816075b87c864aJordy Rose#include "clang/StaticAnalyzer/Core/CheckerRegistry.h" 1108b86531ade68727c56918f162816075b87c864aJordy Rose#include "clang/StaticAnalyzer/Core/CheckerOptInfo.h" 12557a3829ebe0e36785b9a7679dc19dc67dbc7639Anna Zaks#include "llvm/ADT/SetVector.h" 1308b86531ade68727c56918f162816075b87c864aJordy Rose 1408b86531ade68727c56918f162816075b87c864aJordy Roseusing namespace clang; 1508b86531ade68727c56918f162816075b87c864aJordy Roseusing namespace ento; 1608b86531ade68727c56918f162816075b87c864aJordy Rose 1708b86531ade68727c56918f162816075b87c864aJordy Rosestatic const char PackageSeparator = '.'; 18557a3829ebe0e36785b9a7679dc19dc67dbc7639Anna Zakstypedef llvm::SetVector<const CheckerRegistry::CheckerInfo *> CheckerInfoSet; 1908b86531ade68727c56918f162816075b87c864aJordy Rose 2008b86531ade68727c56918f162816075b87c864aJordy Rose 2108b86531ade68727c56918f162816075b87c864aJordy Rosestatic bool checkerNameLT(const CheckerRegistry::CheckerInfo &a, 2208b86531ade68727c56918f162816075b87c864aJordy Rose const CheckerRegistry::CheckerInfo &b) { 2308b86531ade68727c56918f162816075b87c864aJordy Rose return a.FullName < b.FullName; 2408b86531ade68727c56918f162816075b87c864aJordy Rose} 2508b86531ade68727c56918f162816075b87c864aJordy Rose 2608b86531ade68727c56918f162816075b87c864aJordy Rosestatic bool isInPackage(const CheckerRegistry::CheckerInfo &checker, 2708b86531ade68727c56918f162816075b87c864aJordy Rose StringRef packageName) { 2808b86531ade68727c56918f162816075b87c864aJordy Rose // Does the checker's full name have the package as a prefix? 2908b86531ade68727c56918f162816075b87c864aJordy Rose if (!checker.FullName.startswith(packageName)) 3008b86531ade68727c56918f162816075b87c864aJordy Rose return false; 3108b86531ade68727c56918f162816075b87c864aJordy Rose 3208b86531ade68727c56918f162816075b87c864aJordy Rose // Is the package actually just the name of a specific checker? 3308b86531ade68727c56918f162816075b87c864aJordy Rose if (checker.FullName.size() == packageName.size()) 3408b86531ade68727c56918f162816075b87c864aJordy Rose return true; 3508b86531ade68727c56918f162816075b87c864aJordy Rose 3608b86531ade68727c56918f162816075b87c864aJordy Rose // Is the checker in the package (or a subpackage)? 3708b86531ade68727c56918f162816075b87c864aJordy Rose if (checker.FullName[packageName.size()] == PackageSeparator) 3808b86531ade68727c56918f162816075b87c864aJordy Rose return true; 3908b86531ade68727c56918f162816075b87c864aJordy Rose 4008b86531ade68727c56918f162816075b87c864aJordy Rose return false; 4108b86531ade68727c56918f162816075b87c864aJordy Rose} 4208b86531ade68727c56918f162816075b87c864aJordy Rose 4308b86531ade68727c56918f162816075b87c864aJordy Rosestatic void collectCheckers(const CheckerRegistry::CheckerInfoList &checkers, 4408b86531ade68727c56918f162816075b87c864aJordy Rose const llvm::StringMap<size_t> &packageSizes, 4508b86531ade68727c56918f162816075b87c864aJordy Rose CheckerOptInfo &opt, CheckerInfoSet &collected) { 4608b86531ade68727c56918f162816075b87c864aJordy Rose // Use a binary search to find the possible start of the package. 4708b86531ade68727c56918f162816075b87c864aJordy Rose CheckerRegistry::CheckerInfo packageInfo(NULL, opt.getName(), ""); 4808b86531ade68727c56918f162816075b87c864aJordy Rose CheckerRegistry::CheckerInfoList::const_iterator e = checkers.end(); 4908b86531ade68727c56918f162816075b87c864aJordy Rose CheckerRegistry::CheckerInfoList::const_iterator i = 5008b86531ade68727c56918f162816075b87c864aJordy Rose std::lower_bound(checkers.begin(), e, packageInfo, checkerNameLT); 5108b86531ade68727c56918f162816075b87c864aJordy Rose 5208b86531ade68727c56918f162816075b87c864aJordy Rose // If we didn't even find a possible package, give up. 5308b86531ade68727c56918f162816075b87c864aJordy Rose if (i == e) 5408b86531ade68727c56918f162816075b87c864aJordy Rose return; 5508b86531ade68727c56918f162816075b87c864aJordy Rose 5608b86531ade68727c56918f162816075b87c864aJordy Rose // If what we found doesn't actually start the package, give up. 5708b86531ade68727c56918f162816075b87c864aJordy Rose if (!isInPackage(*i, opt.getName())) 5808b86531ade68727c56918f162816075b87c864aJordy Rose return; 5908b86531ade68727c56918f162816075b87c864aJordy Rose 6008b86531ade68727c56918f162816075b87c864aJordy Rose // There is at least one checker in the package; claim the option. 6108b86531ade68727c56918f162816075b87c864aJordy Rose opt.claim(); 6208b86531ade68727c56918f162816075b87c864aJordy Rose 6308b86531ade68727c56918f162816075b87c864aJordy Rose // See how large the package is. 6408b86531ade68727c56918f162816075b87c864aJordy Rose // If the package doesn't exist, assume the option refers to a single checker. 6508b86531ade68727c56918f162816075b87c864aJordy Rose size_t size = 1; 6608b86531ade68727c56918f162816075b87c864aJordy Rose llvm::StringMap<size_t>::const_iterator packageSize = 6708b86531ade68727c56918f162816075b87c864aJordy Rose packageSizes.find(opt.getName()); 6808b86531ade68727c56918f162816075b87c864aJordy Rose if (packageSize != packageSizes.end()) 6908b86531ade68727c56918f162816075b87c864aJordy Rose size = packageSize->getValue(); 7008b86531ade68727c56918f162816075b87c864aJordy Rose 7108b86531ade68727c56918f162816075b87c864aJordy Rose // Step through all the checkers in the package. 7208b86531ade68727c56918f162816075b87c864aJordy Rose for (e = i+size; i != e; ++i) { 7308b86531ade68727c56918f162816075b87c864aJordy Rose if (opt.isEnabled()) 7408b86531ade68727c56918f162816075b87c864aJordy Rose collected.insert(&*i); 7508b86531ade68727c56918f162816075b87c864aJordy Rose else 76557a3829ebe0e36785b9a7679dc19dc67dbc7639Anna Zaks collected.remove(&*i); 7708b86531ade68727c56918f162816075b87c864aJordy Rose } 7808b86531ade68727c56918f162816075b87c864aJordy Rose} 7908b86531ade68727c56918f162816075b87c864aJordy Rose 8008b86531ade68727c56918f162816075b87c864aJordy Rosevoid CheckerRegistry::addChecker(InitializationFunction fn, StringRef name, 8108b86531ade68727c56918f162816075b87c864aJordy Rose StringRef desc) { 8208b86531ade68727c56918f162816075b87c864aJordy Rose Checkers.push_back(CheckerInfo(fn, name, desc)); 8308b86531ade68727c56918f162816075b87c864aJordy Rose 8408b86531ade68727c56918f162816075b87c864aJordy Rose // Record the presence of the checker in its packages. 8508b86531ade68727c56918f162816075b87c864aJordy Rose StringRef packageName, leafName; 8608b86531ade68727c56918f162816075b87c864aJordy Rose llvm::tie(packageName, leafName) = name.rsplit(PackageSeparator); 8708b86531ade68727c56918f162816075b87c864aJordy Rose while (!leafName.empty()) { 8808b86531ade68727c56918f162816075b87c864aJordy Rose Packages[packageName] += 1; 8908b86531ade68727c56918f162816075b87c864aJordy Rose llvm::tie(packageName, leafName) = packageName.rsplit(PackageSeparator); 9008b86531ade68727c56918f162816075b87c864aJordy Rose } 9108b86531ade68727c56918f162816075b87c864aJordy Rose} 9208b86531ade68727c56918f162816075b87c864aJordy Rose 9308b86531ade68727c56918f162816075b87c864aJordy Rosevoid CheckerRegistry::initializeManager(CheckerManager &checkerMgr, 9408b86531ade68727c56918f162816075b87c864aJordy Rose SmallVectorImpl<CheckerOptInfo> &opts) const { 9508b86531ade68727c56918f162816075b87c864aJordy Rose // Sort checkers for efficient collection. 9608b86531ade68727c56918f162816075b87c864aJordy Rose std::sort(Checkers.begin(), Checkers.end(), checkerNameLT); 9708b86531ade68727c56918f162816075b87c864aJordy Rose 9808b86531ade68727c56918f162816075b87c864aJordy Rose // Collect checkers enabled by the options. 9908b86531ade68727c56918f162816075b87c864aJordy Rose CheckerInfoSet enabledCheckers; 10008b86531ade68727c56918f162816075b87c864aJordy Rose for (SmallVectorImpl<CheckerOptInfo>::iterator 10108b86531ade68727c56918f162816075b87c864aJordy Rose i = opts.begin(), e = opts.end(); i != e; ++i) { 10208b86531ade68727c56918f162816075b87c864aJordy Rose collectCheckers(Checkers, Packages, *i, enabledCheckers); 10308b86531ade68727c56918f162816075b87c864aJordy Rose } 10408b86531ade68727c56918f162816075b87c864aJordy Rose 10508b86531ade68727c56918f162816075b87c864aJordy Rose // Initialize the CheckerManager with all enabled checkers. 10608b86531ade68727c56918f162816075b87c864aJordy Rose for (CheckerInfoSet::iterator 10708b86531ade68727c56918f162816075b87c864aJordy Rose i = enabledCheckers.begin(), e = enabledCheckers.end(); i != e; ++i) { 10808b86531ade68727c56918f162816075b87c864aJordy Rose (*i)->Initialize(checkerMgr); 10908b86531ade68727c56918f162816075b87c864aJordy Rose } 11008b86531ade68727c56918f162816075b87c864aJordy Rose} 11108b86531ade68727c56918f162816075b87c864aJordy Rose 11208b86531ade68727c56918f162816075b87c864aJordy Rosevoid CheckerRegistry::printHelp(llvm::raw_ostream &out, 11308b86531ade68727c56918f162816075b87c864aJordy Rose size_t maxNameChars) const { 11408b86531ade68727c56918f162816075b87c864aJordy Rose // FIXME: Alphabetical sort puts 'experimental' in the middle. 11508b86531ade68727c56918f162816075b87c864aJordy Rose // Would it be better to name it '~experimental' or something else 11608b86531ade68727c56918f162816075b87c864aJordy Rose // that's ASCIIbetically last? 11708b86531ade68727c56918f162816075b87c864aJordy Rose std::sort(Checkers.begin(), Checkers.end(), checkerNameLT); 11808b86531ade68727c56918f162816075b87c864aJordy Rose 11908b86531ade68727c56918f162816075b87c864aJordy Rose // FIXME: Print available packages. 12008b86531ade68727c56918f162816075b87c864aJordy Rose 12108b86531ade68727c56918f162816075b87c864aJordy Rose out << "CHECKERS:\n"; 12208b86531ade68727c56918f162816075b87c864aJordy Rose 12308b86531ade68727c56918f162816075b87c864aJordy Rose // Find the maximum option length. 12408b86531ade68727c56918f162816075b87c864aJordy Rose size_t optionFieldWidth = 0; 12508b86531ade68727c56918f162816075b87c864aJordy Rose for (CheckerInfoList::const_iterator i = Checkers.begin(), e = Checkers.end(); 12608b86531ade68727c56918f162816075b87c864aJordy Rose i != e; ++i) { 12708b86531ade68727c56918f162816075b87c864aJordy Rose // Limit the amount of padding we are willing to give up for alignment. 12808b86531ade68727c56918f162816075b87c864aJordy Rose // Package.Name Description [Hidden] 12908b86531ade68727c56918f162816075b87c864aJordy Rose size_t nameLength = i->FullName.size(); 13008b86531ade68727c56918f162816075b87c864aJordy Rose if (nameLength <= maxNameChars) 13108b86531ade68727c56918f162816075b87c864aJordy Rose optionFieldWidth = std::max(optionFieldWidth, nameLength); 13208b86531ade68727c56918f162816075b87c864aJordy Rose } 13308b86531ade68727c56918f162816075b87c864aJordy Rose 13408b86531ade68727c56918f162816075b87c864aJordy Rose const size_t initialPad = 2; 13508b86531ade68727c56918f162816075b87c864aJordy Rose for (CheckerInfoList::const_iterator i = Checkers.begin(), e = Checkers.end(); 13608b86531ade68727c56918f162816075b87c864aJordy Rose i != e; ++i) { 13708b86531ade68727c56918f162816075b87c864aJordy Rose out.indent(initialPad) << i->FullName; 13808b86531ade68727c56918f162816075b87c864aJordy Rose 13908b86531ade68727c56918f162816075b87c864aJordy Rose int pad = optionFieldWidth - i->FullName.size(); 14008b86531ade68727c56918f162816075b87c864aJordy Rose 14108b86531ade68727c56918f162816075b87c864aJordy Rose // Break on long option names. 14208b86531ade68727c56918f162816075b87c864aJordy Rose if (pad < 0) { 14308b86531ade68727c56918f162816075b87c864aJordy Rose out << '\n'; 14408b86531ade68727c56918f162816075b87c864aJordy Rose pad = optionFieldWidth + initialPad; 14508b86531ade68727c56918f162816075b87c864aJordy Rose } 14608b86531ade68727c56918f162816075b87c864aJordy Rose out.indent(pad + 2) << i->Desc; 14708b86531ade68727c56918f162816075b87c864aJordy Rose 14808b86531ade68727c56918f162816075b87c864aJordy Rose out << '\n'; 14908b86531ade68727c56918f162816075b87c864aJordy Rose } 15008b86531ade68727c56918f162816075b87c864aJordy Rose} 151