CheckerRegistration.cpp revision b7b0608c3aeee3eb9f14520eb7eff159b855a34b
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" 24a8fd0bc069275d8e7bc9fa72c2d93a76302e5e48Jordy Rose#include "llvm/Support/Path.h" 25116f3640daee424dfcdbe55e80be5a67476be4b0Argyrios Kyrtzidis#include "llvm/Support/raw_ostream.h" 2643dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis#include "llvm/ADT/OwningPtr.h" 2743dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis#include "llvm/ADT/SmallVector.h" 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); 38a8fd0bc069275d8e7bc9fa72c2d93a76302e5e48Jordy Rose static void warnIncompatible(Diagnostic *diags, StringRef pluginPath, 39a8fd0bc069275d8e7bc9fa72c2d93a76302e5e48Jordy Rose const char *pluginAPIVersion); 40a8fd0bc069275d8e7bc9fa72c2d93a76302e5e48Jordy Rose 41a8fd0bc069275d8e7bc9fa72c2d93a76302e5e48Jordy Rosepublic: 42a8fd0bc069275d8e7bc9fa72c2d93a76302e5e48Jordy Rose ClangCheckerRegistry(ArrayRef<std::string> plugins, Diagnostic *diags = 0); 4377a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rose}; 4477a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rose 4577a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rose} // end anonymous namespace 4677a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rose 47a8fd0bc069275d8e7bc9fa72c2d93a76302e5e48Jordy RoseClangCheckerRegistry::ClangCheckerRegistry(ArrayRef<std::string> plugins, 48a8fd0bc069275d8e7bc9fa72c2d93a76302e5e48Jordy Rose Diagnostic *diags) { 4977a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rose registerBuiltinCheckers(*this); 5077a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rose 5177a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rose for (ArrayRef<std::string>::iterator i = plugins.begin(), e = plugins.end(); 5277a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rose i != e; ++i) { 5377a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rose // Get access to the plugin. 5477a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rose DynamicLibrary lib = DynamicLibrary::getPermanentLibrary(i->c_str()); 5577a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rose 5677a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rose // See if it's compatible with this build of clang. 5777a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rose const char *pluginAPIVersion = 5877a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rose (const char *) lib.getAddressOfSymbol("clang_analyzerAPIVersionString"); 59a8fd0bc069275d8e7bc9fa72c2d93a76302e5e48Jordy Rose if (!isCompatibleAPIVersion(pluginAPIVersion)) { 60a8fd0bc069275d8e7bc9fa72c2d93a76302e5e48Jordy Rose warnIncompatible(diags, *i, pluginAPIVersion); 6177a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rose continue; 62a8fd0bc069275d8e7bc9fa72c2d93a76302e5e48Jordy Rose } 6377a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rose 6477a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rose // Register its checkers. 6577a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rose RegisterCheckersFn registerPluginCheckers = 666875325b6576ad6fa4fc457f251aaeccb8b3c724Benjamin Kramer (RegisterCheckersFn) (intptr_t) lib.getAddressOfSymbol( 676875325b6576ad6fa4fc457f251aaeccb8b3c724Benjamin Kramer "clang_registerCheckers"); 6877a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rose if (registerPluginCheckers) 6977a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rose registerPluginCheckers(*this); 7077a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rose } 7108b86531ade68727c56918f162816075b87c864aJordy Rose} 7208b86531ade68727c56918f162816075b87c864aJordy Rose 7377a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rosebool ClangCheckerRegistry::isCompatibleAPIVersion(const char *versionString) { 7477a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rose // If the version string is null, it's not an analyzer plugin. 7577a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rose if (versionString == 0) 7677a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rose return false; 7777a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rose 7877a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rose // For now, none of the static analyzer API is considered stable. 7977a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rose // Versions must match exactly. 8077a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rose if (strcmp(versionString, CLANG_ANALYZER_API_VERSION_STRING) == 0) 8177a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rose return true; 8277a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rose 8377a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rose return false; 8477a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rose} 8577a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rose 86a8fd0bc069275d8e7bc9fa72c2d93a76302e5e48Jordy Rosevoid ClangCheckerRegistry::warnIncompatible(Diagnostic *diags, 87a8fd0bc069275d8e7bc9fa72c2d93a76302e5e48Jordy Rose StringRef pluginPath, 88a8fd0bc069275d8e7bc9fa72c2d93a76302e5e48Jordy Rose const char *pluginAPIVersion) { 89a8fd0bc069275d8e7bc9fa72c2d93a76302e5e48Jordy Rose if (!diags) 90a8fd0bc069275d8e7bc9fa72c2d93a76302e5e48Jordy Rose return; 91a8fd0bc069275d8e7bc9fa72c2d93a76302e5e48Jordy Rose if (!pluginAPIVersion) 92a8fd0bc069275d8e7bc9fa72c2d93a76302e5e48Jordy Rose return; 93a8fd0bc069275d8e7bc9fa72c2d93a76302e5e48Jordy Rose 94a8fd0bc069275d8e7bc9fa72c2d93a76302e5e48Jordy Rose diags->Report(diag::warn_incompatible_analyzer_plugin_api) 95a8fd0bc069275d8e7bc9fa72c2d93a76302e5e48Jordy Rose << llvm::sys::path::filename(pluginPath); 96a8fd0bc069275d8e7bc9fa72c2d93a76302e5e48Jordy Rose diags->Report(diag::note_incompatible_analyzer_plugin_api) 97a8fd0bc069275d8e7bc9fa72c2d93a76302e5e48Jordy Rose << CLANG_ANALYZER_API_VERSION_STRING 98a8fd0bc069275d8e7bc9fa72c2d93a76302e5e48Jordy Rose << pluginAPIVersion; 99a8fd0bc069275d8e7bc9fa72c2d93a76302e5e48Jordy Rose} 100a8fd0bc069275d8e7bc9fa72c2d93a76302e5e48Jordy Rose 10177a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rose 10208b86531ade68727c56918f162816075b87c864aJordy RoseCheckerManager *ento::createCheckerManager(const AnalyzerOptions &opts, 10308b86531ade68727c56918f162816075b87c864aJordy Rose const LangOptions &langOpts, 10408b86531ade68727c56918f162816075b87c864aJordy Rose ArrayRef<std::string> plugins, 10508b86531ade68727c56918f162816075b87c864aJordy Rose Diagnostic &diags) { 1062e471a3e476396be1ddca4ab8b9df721bcfc9437Argyrios Kyrtzidis llvm::OwningPtr<CheckerManager> checkerMgr(new CheckerManager(langOpts)); 10743dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis 1085f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner SmallVector<CheckerOptInfo, 8> checkerOpts; 10943dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis for (unsigned i = 0, e = opts.CheckersControlList.size(); i != e; ++i) { 11043dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis const std::pair<std::string, bool> &opt = opts.CheckersControlList[i]; 11143dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis checkerOpts.push_back(CheckerOptInfo(opt.first.c_str(), opt.second)); 11243dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis } 11343dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis 114a8fd0bc069275d8e7bc9fa72c2d93a76302e5e48Jordy Rose ClangCheckerRegistry allCheckers(plugins, &diags); 115a8fd0bc069275d8e7bc9fa72c2d93a76302e5e48Jordy Rose allCheckers.initializeManager(*checkerMgr, checkerOpts); 116deb6447d0029bdb122397fafb5fa2a4e76f2e555Argyrios Kyrtzidis checkerMgr->finishedCheckerRegistration(); 117deb6447d0029bdb122397fafb5fa2a4e76f2e555Argyrios Kyrtzidis 11843dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis for (unsigned i = 0, e = checkerOpts.size(); i != e; ++i) { 11943dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis if (checkerOpts[i].isUnclaimed()) 120b7b0608c3aeee3eb9f14520eb7eff159b855a34bJordy Rose diags.Report(diag::warn_unknown_analyzer_checker) 12143dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis << checkerOpts[i].getName(); 12243dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis } 12343dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis 12443dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis return checkerMgr.take(); 12543dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis} 126116f3640daee424dfcdbe55e80be5a67476be4b0Argyrios Kyrtzidis 12708b86531ade68727c56918f162816075b87c864aJordy Rosevoid ento::printCheckerHelp(raw_ostream &out, ArrayRef<std::string> plugins) { 12808b86531ade68727c56918f162816075b87c864aJordy Rose out << "OVERVIEW: Clang Static Analyzer Checkers List\n\n"; 12908b86531ade68727c56918f162816075b87c864aJordy Rose out << "USAGE: -analyzer-checker <CHECKER or PACKAGE,...>\n\n"; 130116f3640daee424dfcdbe55e80be5a67476be4b0Argyrios Kyrtzidis 13177a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rose ClangCheckerRegistry(plugins).printHelp(out); 132116f3640daee424dfcdbe55e80be5a67476be4b0Argyrios Kyrtzidis} 133