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