CheckerRegistration.cpp revision 6bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89
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"
1555fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/Basic/Diagnostic.h"
1655fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/Frontend/FrontendDiagnostic.h"
1708b86531ade68727c56918f162816075b87c864aJordy Rose#include "clang/StaticAnalyzer/Checkers/ClangCheckers.h"
1855fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/StaticAnalyzer/Core/AnalyzerOptions.h"
1943dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis#include "clang/StaticAnalyzer/Core/CheckerManager.h"
2008b86531ade68727c56918f162816075b87c864aJordy Rose#include "clang/StaticAnalyzer/Core/CheckerOptInfo.h"
2108b86531ade68727c56918f162816075b87c864aJordy Rose#include "clang/StaticAnalyzer/Core/CheckerRegistry.h"
2255fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/StaticAnalyzer/Frontend/FrontendActions.h"
2355fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "llvm/ADT/SmallVector.h"
2477a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rose#include "llvm/Support/DynamicLibrary.h"
25a8fd0bc069275d8e7bc9fa72c2d93a76302e5e48Jordy Rose#include "llvm/Support/Path.h"
26116f3640daee424dfcdbe55e80be5a67476be4b0Argyrios Kyrtzidis#include "llvm/Support/raw_ostream.h"
27651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines#include <memory>
2843dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis
2943dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidisusing namespace clang;
3043dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidisusing namespace ento;
3177a33a71701b59affb5337d9e2b57d69bc095c7dJordy Roseusing llvm::sys::DynamicLibrary;
3243dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis
3377a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rosenamespace {
3477a33a71701b59affb5337d9e2b57d69bc095c7dJordy Roseclass ClangCheckerRegistry : public CheckerRegistry {
3577a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rose  typedef void (*RegisterCheckersFn)(CheckerRegistry &);
3608b86531ade68727c56918f162816075b87c864aJordy Rose
3777a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rose  static bool isCompatibleAPIVersion(const char *versionString);
38d6471f7c1921c7802804ce3ff6fe9768310f72b9David Blaikie  static void warnIncompatible(DiagnosticsEngine *diags, StringRef pluginPath,
39a8fd0bc069275d8e7bc9fa72c2d93a76302e5e48Jordy Rose                               const char *pluginAPIVersion);
40a8fd0bc069275d8e7bc9fa72c2d93a76302e5e48Jordy Rose
41a8fd0bc069275d8e7bc9fa72c2d93a76302e5e48Jordy Rosepublic:
42d6471f7c1921c7802804ce3ff6fe9768310f72b9David Blaikie  ClangCheckerRegistry(ArrayRef<std::string> plugins,
436bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines                       DiagnosticsEngine *diags = nullptr);
4477a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rose};
4577a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rose
4677a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rose} // end anonymous namespace
4777a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rose
48a8fd0bc069275d8e7bc9fa72c2d93a76302e5e48Jordy RoseClangCheckerRegistry::ClangCheckerRegistry(ArrayRef<std::string> plugins,
49d6471f7c1921c7802804ce3ff6fe9768310f72b9David Blaikie                                           DiagnosticsEngine *diags) {
5077a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rose  registerBuiltinCheckers(*this);
5177a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rose
5277a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rose  for (ArrayRef<std::string>::iterator i = plugins.begin(), e = plugins.end();
5377a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rose       i != e; ++i) {
5477a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rose    // Get access to the plugin.
5577a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rose    DynamicLibrary lib = DynamicLibrary::getPermanentLibrary(i->c_str());
5677a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rose
5777a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rose    // See if it's compatible with this build of clang.
5877a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rose    const char *pluginAPIVersion =
5977a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rose      (const char *) lib.getAddressOfSymbol("clang_analyzerAPIVersionString");
60a8fd0bc069275d8e7bc9fa72c2d93a76302e5e48Jordy Rose    if (!isCompatibleAPIVersion(pluginAPIVersion)) {
61a8fd0bc069275d8e7bc9fa72c2d93a76302e5e48Jordy Rose      warnIncompatible(diags, *i, pluginAPIVersion);
6277a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rose      continue;
63a8fd0bc069275d8e7bc9fa72c2d93a76302e5e48Jordy Rose    }
6477a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rose
6577a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rose    // Register its checkers.
6677a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rose    RegisterCheckersFn registerPluginCheckers =
676875325b6576ad6fa4fc457f251aaeccb8b3c724Benjamin Kramer      (RegisterCheckersFn) (intptr_t) lib.getAddressOfSymbol(
686875325b6576ad6fa4fc457f251aaeccb8b3c724Benjamin Kramer                                                      "clang_registerCheckers");
6977a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rose    if (registerPluginCheckers)
7077a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rose      registerPluginCheckers(*this);
7177a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rose  }
7208b86531ade68727c56918f162816075b87c864aJordy Rose}
7308b86531ade68727c56918f162816075b87c864aJordy Rose
7477a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rosebool ClangCheckerRegistry::isCompatibleAPIVersion(const char *versionString) {
7577a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rose  // If the version string is null, it's not an analyzer plugin.
766bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  if (!versionString)
7777a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rose    return false;
7877a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rose
7977a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rose  // For now, none of the static analyzer API is considered stable.
8077a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rose  // Versions must match exactly.
8177a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rose  if (strcmp(versionString, CLANG_ANALYZER_API_VERSION_STRING) == 0)
8277a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rose    return true;
8377a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rose
8477a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rose  return false;
8577a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rose}
8677a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rose
87d6471f7c1921c7802804ce3ff6fe9768310f72b9David Blaikievoid ClangCheckerRegistry::warnIncompatible(DiagnosticsEngine *diags,
88a8fd0bc069275d8e7bc9fa72c2d93a76302e5e48Jordy Rose                                            StringRef pluginPath,
89a8fd0bc069275d8e7bc9fa72c2d93a76302e5e48Jordy Rose                                            const char *pluginAPIVersion) {
90a8fd0bc069275d8e7bc9fa72c2d93a76302e5e48Jordy Rose  if (!diags)
91a8fd0bc069275d8e7bc9fa72c2d93a76302e5e48Jordy Rose    return;
92a8fd0bc069275d8e7bc9fa72c2d93a76302e5e48Jordy Rose  if (!pluginAPIVersion)
93a8fd0bc069275d8e7bc9fa72c2d93a76302e5e48Jordy Rose    return;
94a8fd0bc069275d8e7bc9fa72c2d93a76302e5e48Jordy Rose
95a8fd0bc069275d8e7bc9fa72c2d93a76302e5e48Jordy Rose  diags->Report(diag::warn_incompatible_analyzer_plugin_api)
96a8fd0bc069275d8e7bc9fa72c2d93a76302e5e48Jordy Rose      << llvm::sys::path::filename(pluginPath);
97a8fd0bc069275d8e7bc9fa72c2d93a76302e5e48Jordy Rose  diags->Report(diag::note_incompatible_analyzer_plugin_api)
98a8fd0bc069275d8e7bc9fa72c2d93a76302e5e48Jordy Rose      << CLANG_ANALYZER_API_VERSION_STRING
99a8fd0bc069275d8e7bc9fa72c2d93a76302e5e48Jordy Rose      << pluginAPIVersion;
100a8fd0bc069275d8e7bc9fa72c2d93a76302e5e48Jordy Rose}
101a8fd0bc069275d8e7bc9fa72c2d93a76302e5e48Jordy Rose
10277a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rose
1038dae128d16bf98759b7a678ce3eebb613bd17109Ted KremenekCheckerManager *ento::createCheckerManager(AnalyzerOptions &opts,
10408b86531ade68727c56918f162816075b87c864aJordy Rose                                           const LangOptions &langOpts,
10508b86531ade68727c56918f162816075b87c864aJordy Rose                                           ArrayRef<std::string> plugins,
106d6471f7c1921c7802804ce3ff6fe9768310f72b9David Blaikie                                           DiagnosticsEngine &diags) {
107651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  std::unique_ptr<CheckerManager> checkerMgr(
108651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      new CheckerManager(langOpts, &opts));
10943dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis
1105f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner  SmallVector<CheckerOptInfo, 8> checkerOpts;
11143dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis  for (unsigned i = 0, e = opts.CheckersControlList.size(); i != e; ++i) {
11243dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis    const std::pair<std::string, bool> &opt = opts.CheckersControlList[i];
11343dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis    checkerOpts.push_back(CheckerOptInfo(opt.first.c_str(), opt.second));
11443dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis  }
11543dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis
116a8fd0bc069275d8e7bc9fa72c2d93a76302e5e48Jordy Rose  ClangCheckerRegistry allCheckers(plugins, &diags);
117a8fd0bc069275d8e7bc9fa72c2d93a76302e5e48Jordy Rose  allCheckers.initializeManager(*checkerMgr, checkerOpts);
118deb6447d0029bdb122397fafb5fa2a4e76f2e555Argyrios Kyrtzidis  checkerMgr->finishedCheckerRegistration();
119deb6447d0029bdb122397fafb5fa2a4e76f2e555Argyrios Kyrtzidis
12043dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis  for (unsigned i = 0, e = checkerOpts.size(); i != e; ++i) {
12143dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis    if (checkerOpts[i].isUnclaimed())
122c0a43777ef48f6f07123b52d4e54b637d5e2d01cTed Kremenek      diags.Report(diag::err_unknown_analyzer_checker)
12343dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis          << checkerOpts[i].getName();
12443dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis  }
12543dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis
126651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  return checkerMgr.release();
12743dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis}
128116f3640daee424dfcdbe55e80be5a67476be4b0Argyrios Kyrtzidis
12908b86531ade68727c56918f162816075b87c864aJordy Rosevoid ento::printCheckerHelp(raw_ostream &out, ArrayRef<std::string> plugins) {
13008b86531ade68727c56918f162816075b87c864aJordy Rose  out << "OVERVIEW: Clang Static Analyzer Checkers List\n\n";
13108b86531ade68727c56918f162816075b87c864aJordy Rose  out << "USAGE: -analyzer-checker <CHECKER or PACKAGE,...>\n\n";
132116f3640daee424dfcdbe55e80be5a67476be4b0Argyrios Kyrtzidis
13377a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rose  ClangCheckerRegistry(plugins).printHelp(out);
134116f3640daee424dfcdbe55e80be5a67476be4b0Argyrios Kyrtzidis}
135