CheckerRegistration.cpp revision 55fc873017f10f6f566b182b70f6fc22aefa3464
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/OwningPtr.h" 2455fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "llvm/ADT/SmallVector.h" 2577a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rose#include "llvm/Support/DynamicLibrary.h" 26a8fd0bc069275d8e7bc9fa72c2d93a76302e5e48Jordy Rose#include "llvm/Support/Path.h" 27116f3640daee424dfcdbe55e80be5a67476be4b0Argyrios Kyrtzidis#include "llvm/Support/raw_ostream.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); 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, 43d6471f7c1921c7802804ce3ff6fe9768310f72b9David Blaikie DiagnosticsEngine *diags = 0); 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. 7677a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rose if (versionString == 0) 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 10308b86531ade68727c56918f162816075b87c864aJordy RoseCheckerManager *ento::createCheckerManager(const AnalyzerOptions &opts, 10408b86531ade68727c56918f162816075b87c864aJordy Rose const LangOptions &langOpts, 10508b86531ade68727c56918f162816075b87c864aJordy Rose ArrayRef<std::string> plugins, 106d6471f7c1921c7802804ce3ff6fe9768310f72b9David Blaikie DiagnosticsEngine &diags) { 1076f42b62b6194f53bcbc349f5d17388e1936535d7Dylan Noblesmith OwningPtr<CheckerManager> checkerMgr(new CheckerManager(langOpts)); 10843dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis 1095f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner SmallVector<CheckerOptInfo, 8> checkerOpts; 11043dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis for (unsigned i = 0, e = opts.CheckersControlList.size(); i != e; ++i) { 11143dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis const std::pair<std::string, bool> &opt = opts.CheckersControlList[i]; 11243dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis checkerOpts.push_back(CheckerOptInfo(opt.first.c_str(), opt.second)); 11343dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis } 11443dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis 115a8fd0bc069275d8e7bc9fa72c2d93a76302e5e48Jordy Rose ClangCheckerRegistry allCheckers(plugins, &diags); 116a8fd0bc069275d8e7bc9fa72c2d93a76302e5e48Jordy Rose allCheckers.initializeManager(*checkerMgr, checkerOpts); 117deb6447d0029bdb122397fafb5fa2a4e76f2e555Argyrios Kyrtzidis checkerMgr->finishedCheckerRegistration(); 118deb6447d0029bdb122397fafb5fa2a4e76f2e555Argyrios Kyrtzidis 11943dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis for (unsigned i = 0, e = checkerOpts.size(); i != e; ++i) { 12043dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis if (checkerOpts[i].isUnclaimed()) 121c0a43777ef48f6f07123b52d4e54b637d5e2d01cTed Kremenek diags.Report(diag::err_unknown_analyzer_checker) 12243dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis << checkerOpts[i].getName(); 12343dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis } 12443dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis 12543dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis return checkerMgr.take(); 12643dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis} 127116f3640daee424dfcdbe55e80be5a67476be4b0Argyrios Kyrtzidis 12808b86531ade68727c56918f162816075b87c864aJordy Rosevoid ento::printCheckerHelp(raw_ostream &out, ArrayRef<std::string> plugins) { 12908b86531ade68727c56918f162816075b87c864aJordy Rose out << "OVERVIEW: Clang Static Analyzer Checkers List\n\n"; 13008b86531ade68727c56918f162816075b87c864aJordy Rose out << "USAGE: -analyzer-checker <CHECKER or PACKAGE,...>\n\n"; 131116f3640daee424dfcdbe55e80be5a67476be4b0Argyrios Kyrtzidis 13277a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rose ClangCheckerRegistry(plugins).printHelp(out); 133116f3640daee424dfcdbe55e80be5a67476be4b0Argyrios Kyrtzidis} 134