CheckerRegistration.cpp revision 77a33a71701b59affb5337d9e2b57d69bc095c7d
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 = 5977a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rose (RegisterCheckersFn) lib.getAddressOfSymbol("clang_registerCheckers"); 6077a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rose if (registerPluginCheckers) 6177a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rose registerPluginCheckers(*this); 6277a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rose } 6308b86531ade68727c56918f162816075b87c864aJordy Rose} 6408b86531ade68727c56918f162816075b87c864aJordy Rose 6577a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rosebool ClangCheckerRegistry::isCompatibleAPIVersion(const char *versionString) { 6677a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rose // If the version string is null, it's not an analyzer plugin. 6777a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rose if (versionString == 0) 6877a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rose return false; 6977a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rose 7077a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rose // For now, none of the static analyzer API is considered stable. 7177a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rose // Versions must match exactly. 7277a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rose if (strcmp(versionString, CLANG_ANALYZER_API_VERSION_STRING) == 0) 7377a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rose return true; 7477a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rose 7577a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rose // FIXME: Should we emit a diagnostic if the version doesn't match? 7677a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rose return false; 7777a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rose} 7877a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rose 7977a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rose 8008b86531ade68727c56918f162816075b87c864aJordy RoseCheckerManager *ento::createCheckerManager(const AnalyzerOptions &opts, 8108b86531ade68727c56918f162816075b87c864aJordy Rose const LangOptions &langOpts, 8208b86531ade68727c56918f162816075b87c864aJordy Rose ArrayRef<std::string> plugins, 8308b86531ade68727c56918f162816075b87c864aJordy Rose Diagnostic &diags) { 842e471a3e476396be1ddca4ab8b9df721bcfc9437Argyrios Kyrtzidis llvm::OwningPtr<CheckerManager> checkerMgr(new CheckerManager(langOpts)); 8543dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis 865f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner SmallVector<CheckerOptInfo, 8> checkerOpts; 8743dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis for (unsigned i = 0, e = opts.CheckersControlList.size(); i != e; ++i) { 8843dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis const std::pair<std::string, bool> &opt = opts.CheckersControlList[i]; 8943dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis checkerOpts.push_back(CheckerOptInfo(opt.first.c_str(), opt.second)); 9043dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis } 9143dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis 9277a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rose ClangCheckerRegistry(plugins).initializeManager(*checkerMgr, checkerOpts); 93deb6447d0029bdb122397fafb5fa2a4e76f2e555Argyrios Kyrtzidis checkerMgr->finishedCheckerRegistration(); 94deb6447d0029bdb122397fafb5fa2a4e76f2e555Argyrios Kyrtzidis 9543dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis for (unsigned i = 0, e = checkerOpts.size(); i != e; ++i) { 9643dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis if (checkerOpts[i].isUnclaimed()) 9743dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis diags.Report(diag::warn_unkwown_analyzer_checker) 9843dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis << checkerOpts[i].getName(); 9943dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis } 10043dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis 10143dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis return checkerMgr.take(); 10243dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis} 103116f3640daee424dfcdbe55e80be5a67476be4b0Argyrios Kyrtzidis 10408b86531ade68727c56918f162816075b87c864aJordy Rosevoid ento::printCheckerHelp(raw_ostream &out, ArrayRef<std::string> plugins) { 10508b86531ade68727c56918f162816075b87c864aJordy Rose out << "OVERVIEW: Clang Static Analyzer Checkers List\n\n"; 10608b86531ade68727c56918f162816075b87c864aJordy Rose out << "USAGE: -analyzer-checker <CHECKER or PACKAGE,...>\n\n"; 107116f3640daee424dfcdbe55e80be5a67476be4b0Argyrios Kyrtzidis 10877a33a71701b59affb5337d9e2b57d69bc095c7dJordy Rose ClangCheckerRegistry(plugins).printHelp(out); 109116f3640daee424dfcdbe55e80be5a67476be4b0Argyrios Kyrtzidis} 110