CheckerRegistration.cpp revision 251662
1218887Sdim//===--- CheckerRegistration.cpp - Registration for the Analyzer Checkers -===// 2218887Sdim// 3218887Sdim// The LLVM Compiler Infrastructure 4218887Sdim// 5218887Sdim// This file is distributed under the University of Illinois Open Source 6218887Sdim// License. See LICENSE.TXT for details. 7218887Sdim// 8218887Sdim//===----------------------------------------------------------------------===// 9218887Sdim// 10218887Sdim// Defines the registration function for the analyzer checkers. 11218887Sdim// 12218887Sdim//===----------------------------------------------------------------------===// 13218887Sdim 14218887Sdim#include "clang/StaticAnalyzer/Frontend/CheckerRegistration.h" 15249423Sdim#include "clang/Basic/Diagnostic.h" 16249423Sdim#include "clang/Frontend/FrontendDiagnostic.h" 17226633Sdim#include "clang/StaticAnalyzer/Checkers/ClangCheckers.h" 18249423Sdim#include "clang/StaticAnalyzer/Core/AnalyzerOptions.h" 19218887Sdim#include "clang/StaticAnalyzer/Core/CheckerManager.h" 20226633Sdim#include "clang/StaticAnalyzer/Core/CheckerOptInfo.h" 21226633Sdim#include "clang/StaticAnalyzer/Core/CheckerRegistry.h" 22249423Sdim#include "clang/StaticAnalyzer/Frontend/FrontendActions.h" 23249423Sdim#include "llvm/ADT/OwningPtr.h" 24249423Sdim#include "llvm/ADT/SmallVector.h" 25226633Sdim#include "llvm/Support/DynamicLibrary.h" 26226633Sdim#include "llvm/Support/Path.h" 27219077Sdim#include "llvm/Support/raw_ostream.h" 28218887Sdim 29218887Sdimusing namespace clang; 30218887Sdimusing namespace ento; 31226633Sdimusing llvm::sys::DynamicLibrary; 32218887Sdim 33226633Sdimnamespace { 34226633Sdimclass ClangCheckerRegistry : public CheckerRegistry { 35226633Sdim typedef void (*RegisterCheckersFn)(CheckerRegistry &); 36226633Sdim 37226633Sdim static bool isCompatibleAPIVersion(const char *versionString); 38226633Sdim static void warnIncompatible(DiagnosticsEngine *diags, StringRef pluginPath, 39226633Sdim const char *pluginAPIVersion); 40226633Sdim 41226633Sdimpublic: 42226633Sdim ClangCheckerRegistry(ArrayRef<std::string> plugins, 43226633Sdim DiagnosticsEngine *diags = 0); 44226633Sdim}; 45226633Sdim 46226633Sdim} // end anonymous namespace 47226633Sdim 48226633SdimClangCheckerRegistry::ClangCheckerRegistry(ArrayRef<std::string> plugins, 49226633Sdim DiagnosticsEngine *diags) { 50226633Sdim registerBuiltinCheckers(*this); 51226633Sdim 52226633Sdim for (ArrayRef<std::string>::iterator i = plugins.begin(), e = plugins.end(); 53226633Sdim i != e; ++i) { 54226633Sdim // Get access to the plugin. 55226633Sdim DynamicLibrary lib = DynamicLibrary::getPermanentLibrary(i->c_str()); 56226633Sdim 57226633Sdim // See if it's compatible with this build of clang. 58226633Sdim const char *pluginAPIVersion = 59226633Sdim (const char *) lib.getAddressOfSymbol("clang_analyzerAPIVersionString"); 60226633Sdim if (!isCompatibleAPIVersion(pluginAPIVersion)) { 61226633Sdim warnIncompatible(diags, *i, pluginAPIVersion); 62226633Sdim continue; 63226633Sdim } 64226633Sdim 65226633Sdim // Register its checkers. 66226633Sdim RegisterCheckersFn registerPluginCheckers = 67226633Sdim (RegisterCheckersFn) (intptr_t) lib.getAddressOfSymbol( 68226633Sdim "clang_registerCheckers"); 69226633Sdim if (registerPluginCheckers) 70226633Sdim registerPluginCheckers(*this); 71226633Sdim } 72226633Sdim} 73226633Sdim 74226633Sdimbool ClangCheckerRegistry::isCompatibleAPIVersion(const char *versionString) { 75226633Sdim // If the version string is null, it's not an analyzer plugin. 76226633Sdim if (versionString == 0) 77226633Sdim return false; 78226633Sdim 79226633Sdim // For now, none of the static analyzer API is considered stable. 80226633Sdim // Versions must match exactly. 81226633Sdim if (strcmp(versionString, CLANG_ANALYZER_API_VERSION_STRING) == 0) 82226633Sdim return true; 83226633Sdim 84226633Sdim return false; 85226633Sdim} 86226633Sdim 87226633Sdimvoid ClangCheckerRegistry::warnIncompatible(DiagnosticsEngine *diags, 88226633Sdim StringRef pluginPath, 89226633Sdim const char *pluginAPIVersion) { 90226633Sdim if (!diags) 91226633Sdim return; 92226633Sdim if (!pluginAPIVersion) 93226633Sdim return; 94226633Sdim 95226633Sdim diags->Report(diag::warn_incompatible_analyzer_plugin_api) 96226633Sdim << llvm::sys::path::filename(pluginPath); 97226633Sdim diags->Report(diag::note_incompatible_analyzer_plugin_api) 98226633Sdim << CLANG_ANALYZER_API_VERSION_STRING 99226633Sdim << pluginAPIVersion; 100226633Sdim} 101226633Sdim 102226633Sdim 103251662SdimCheckerManager *ento::createCheckerManager(AnalyzerOptions &opts, 104226633Sdim const LangOptions &langOpts, 105226633Sdim ArrayRef<std::string> plugins, 106226633Sdim DiagnosticsEngine &diags) { 107251662Sdim OwningPtr<CheckerManager> checkerMgr(new CheckerManager(langOpts, 108251662Sdim &opts)); 109218887Sdim 110226633Sdim SmallVector<CheckerOptInfo, 8> checkerOpts; 111218887Sdim for (unsigned i = 0, e = opts.CheckersControlList.size(); i != e; ++i) { 112218887Sdim const std::pair<std::string, bool> &opt = opts.CheckersControlList[i]; 113218887Sdim checkerOpts.push_back(CheckerOptInfo(opt.first.c_str(), opt.second)); 114218887Sdim } 115218887Sdim 116226633Sdim ClangCheckerRegistry allCheckers(plugins, &diags); 117226633Sdim allCheckers.initializeManager(*checkerMgr, checkerOpts); 118221345Sdim checkerMgr->finishedCheckerRegistration(); 119221345Sdim 120218887Sdim for (unsigned i = 0, e = checkerOpts.size(); i != e; ++i) { 121218887Sdim if (checkerOpts[i].isUnclaimed()) 122239462Sdim diags.Report(diag::err_unknown_analyzer_checker) 123218887Sdim << checkerOpts[i].getName(); 124218887Sdim } 125218887Sdim 126218887Sdim return checkerMgr.take(); 127218887Sdim} 128219077Sdim 129226633Sdimvoid ento::printCheckerHelp(raw_ostream &out, ArrayRef<std::string> plugins) { 130226633Sdim out << "OVERVIEW: Clang Static Analyzer Checkers List\n\n"; 131226633Sdim out << "USAGE: -analyzer-checker <CHECKER or PACKAGE,...>\n\n"; 132219077Sdim 133226633Sdim ClangCheckerRegistry(plugins).printHelp(out); 134219077Sdim} 135