CheckerRegistration.cpp revision 6875325b6576ad6fa4fc457f251aaeccb8b3c724
143dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis//===--- CheckerRegistration.cpp - Registration for the Analyzer Checkers -===//
243dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis//
343dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis//                     The LLVM Compiler Infrastructure
443dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis//
543dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis// This file is distributed under the University of Illinois Open Source
643dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis// License. See LICENSE.TXT for details.
743dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis//
843dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis//===----------------------------------------------------------------------===//
943dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis//
1043dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis// Defines the registration function for the analyzer checkers.
1143dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis//
1243dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis//===----------------------------------------------------------------------===//
1343dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis
1427af04bcca46f8a3374586be1301477f9123f5e1Argyrios Kyrtzidis#include "clang/StaticAnalyzer/Frontend/CheckerRegistration.h"
15116f3640daee424dfcdbe55e80be5a67476be4b0Argyrios Kyrtzidis#include "clang/StaticAnalyzer/Frontend/FrontendActions.h"
1608b86531ade68727c56918f162816075b87c864aJordy Rose#include "clang/StaticAnalyzer/Checkers/ClangCheckers.h"
1743dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis#include "clang/StaticAnalyzer/Core/CheckerManager.h"
1808b86531ade68727c56918f162816075b87c864aJordy Rose#include "clang/StaticAnalyzer/Core/CheckerOptInfo.h"
1908b86531ade68727c56918f162816075b87c864aJordy Rose#include "clang/StaticAnalyzer/Core/CheckerRegistry.h"
2043dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis#include "clang/Frontend/AnalyzerOptions.h"
2143dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis#include "clang/Frontend/FrontendDiagnostic.h"
2243dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis#include "clang/Basic/Diagnostic.h"
2377a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rose#include "llvm/Support/DynamicLibrary.h"
24116f3640daee424dfcdbe55e80be5a67476be4b0Argyrios Kyrtzidis#include "llvm/Support/raw_ostream.h"
2543dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis#include "llvm/ADT/OwningPtr.h"
2643dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis#include "llvm/ADT/SmallVector.h"
2743dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis
2843dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidisusing namespace clang;
2943dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidisusing namespace ento;
3077a33a71701b59affb5337d9e2b57d69bc095c7dJordy Roseusing llvm::sys::DynamicLibrary;
3143dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis
3277a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rosenamespace {
3377a33a71701b59affb5337d9e2b57d69bc095c7dJordy Roseclass ClangCheckerRegistry : public CheckerRegistry {
3477a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rose  typedef void (*RegisterCheckersFn)(CheckerRegistry &);
3577a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rosepublic:
3677a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rose  ClangCheckerRegistry(ArrayRef<std::string> plugins);
3708b86531ade68727c56918f162816075b87c864aJordy Rose
3877a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rose  static bool isCompatibleAPIVersion(const char *versionString);
3977a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rose};
4077a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rose
4177a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rose} // end anonymous namespace
4277a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rose
4377a33a71701b59affb5337d9e2b57d69bc095c7dJordy RoseClangCheckerRegistry::ClangCheckerRegistry(ArrayRef<std::string> plugins) {
4477a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rose  registerBuiltinCheckers(*this);
4577a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rose
4677a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rose  for (ArrayRef<std::string>::iterator i = plugins.begin(), e = plugins.end();
4777a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rose       i != e; ++i) {
4877a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rose    // Get access to the plugin.
4977a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rose    DynamicLibrary lib = DynamicLibrary::getPermanentLibrary(i->c_str());
5077a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rose
5177a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rose    // See if it's compatible with this build of clang.
5277a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rose    const char *pluginAPIVersion =
5377a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rose      (const char *) lib.getAddressOfSymbol("clang_analyzerAPIVersionString");
5477a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rose    if (!isCompatibleAPIVersion(pluginAPIVersion))
5577a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rose      continue;
5677a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rose
5777a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rose    // Register its checkers.
5877a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rose    RegisterCheckersFn registerPluginCheckers =
596875325b6576ad6fa4fc457f251aaeccb8b3c724Benjamin Kramer      (RegisterCheckersFn) (intptr_t) lib.getAddressOfSymbol(
606875325b6576ad6fa4fc457f251aaeccb8b3c724Benjamin Kramer                                                      "clang_registerCheckers");
6177a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rose    if (registerPluginCheckers)
6277a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rose      registerPluginCheckers(*this);
6377a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rose  }
6408b86531ade68727c56918f162816075b87c864aJordy Rose}
6508b86531ade68727c56918f162816075b87c864aJordy Rose
6677a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rosebool ClangCheckerRegistry::isCompatibleAPIVersion(const char *versionString) {
6777a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rose  // If the version string is null, it's not an analyzer plugin.
6877a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rose  if (versionString == 0)
6977a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rose    return false;
7077a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rose
7177a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rose  // For now, none of the static analyzer API is considered stable.
7277a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rose  // Versions must match exactly.
7377a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rose  if (strcmp(versionString, CLANG_ANALYZER_API_VERSION_STRING) == 0)
7477a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rose    return true;
7577a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rose
7677a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rose  // FIXME: Should we emit a diagnostic if the version doesn't match?
7777a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rose  return false;
7877a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rose}
7977a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rose
8077a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rose
8108b86531ade68727c56918f162816075b87c864aJordy RoseCheckerManager *ento::createCheckerManager(const AnalyzerOptions &opts,
8208b86531ade68727c56918f162816075b87c864aJordy Rose                                           const LangOptions &langOpts,
8308b86531ade68727c56918f162816075b87c864aJordy Rose                                           ArrayRef<std::string> plugins,
8408b86531ade68727c56918f162816075b87c864aJordy Rose                                           Diagnostic &diags) {
852e471a3e476396be1ddca4ab8b9df721bcfc9437Argyrios Kyrtzidis  llvm::OwningPtr<CheckerManager> checkerMgr(new CheckerManager(langOpts));
8643dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis
875f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner  SmallVector<CheckerOptInfo, 8> checkerOpts;
8843dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis  for (unsigned i = 0, e = opts.CheckersControlList.size(); i != e; ++i) {
8943dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis    const std::pair<std::string, bool> &opt = opts.CheckersControlList[i];
9043dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis    checkerOpts.push_back(CheckerOptInfo(opt.first.c_str(), opt.second));
9143dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis  }
9243dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis
9377a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rose  ClangCheckerRegistry(plugins).initializeManager(*checkerMgr, checkerOpts);
94deb6447d0029bdb122397fafb5fa2a4e76f2e555Argyrios Kyrtzidis  checkerMgr->finishedCheckerRegistration();
95deb6447d0029bdb122397fafb5fa2a4e76f2e555Argyrios Kyrtzidis
9643dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis  for (unsigned i = 0, e = checkerOpts.size(); i != e; ++i) {
9743dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis    if (checkerOpts[i].isUnclaimed())
9843dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis      diags.Report(diag::warn_unkwown_analyzer_checker)
9943dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis          << checkerOpts[i].getName();
10043dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis  }
10143dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis
10243dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis  return checkerMgr.take();
10343dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis}
104116f3640daee424dfcdbe55e80be5a67476be4b0Argyrios Kyrtzidis
10508b86531ade68727c56918f162816075b87c864aJordy Rosevoid ento::printCheckerHelp(raw_ostream &out, ArrayRef<std::string> plugins) {
10608b86531ade68727c56918f162816075b87c864aJordy Rose  out << "OVERVIEW: Clang Static Analyzer Checkers List\n\n";
10708b86531ade68727c56918f162816075b87c864aJordy Rose  out << "USAGE: -analyzer-checker <CHECKER or PACKAGE,...>\n\n";
108116f3640daee424dfcdbe55e80be5a67476be4b0Argyrios Kyrtzidis
10977a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rose  ClangCheckerRegistry(plugins).printHelp(out);
110116f3640daee424dfcdbe55e80be5a67476be4b0Argyrios Kyrtzidis}
111