CheckerRegistration.cpp revision 234353
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" 15219077Sdim#include "clang/StaticAnalyzer/Frontend/FrontendActions.h" 16226633Sdim#include "clang/StaticAnalyzer/Checkers/ClangCheckers.h" 17218887Sdim#include "clang/StaticAnalyzer/Core/CheckerManager.h" 18226633Sdim#include "clang/StaticAnalyzer/Core/CheckerOptInfo.h" 19226633Sdim#include "clang/StaticAnalyzer/Core/CheckerRegistry.h" 20218887Sdim#include "clang/Frontend/AnalyzerOptions.h" 21218887Sdim#include "clang/Frontend/FrontendDiagnostic.h" 22218887Sdim#include "clang/Basic/Diagnostic.h" 23226633Sdim#include "llvm/Support/DynamicLibrary.h" 24226633Sdim#include "llvm/Support/Path.h" 25219077Sdim#include "llvm/Support/raw_ostream.h" 26218887Sdim#include "llvm/ADT/OwningPtr.h" 27218887Sdim#include "llvm/ADT/SmallVector.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 103226633SdimCheckerManager *ento::createCheckerManager(const AnalyzerOptions &opts, 104226633Sdim const LangOptions &langOpts, 105226633Sdim ArrayRef<std::string> plugins, 106226633Sdim DiagnosticsEngine &diags) { 107234353Sdim OwningPtr<CheckerManager> checkerMgr(new CheckerManager(langOpts)); 108218887Sdim 109226633Sdim SmallVector<CheckerOptInfo, 8> checkerOpts; 110218887Sdim for (unsigned i = 0, e = opts.CheckersControlList.size(); i != e; ++i) { 111218887Sdim const std::pair<std::string, bool> &opt = opts.CheckersControlList[i]; 112218887Sdim checkerOpts.push_back(CheckerOptInfo(opt.first.c_str(), opt.second)); 113218887Sdim } 114218887Sdim 115226633Sdim ClangCheckerRegistry allCheckers(plugins, &diags); 116226633Sdim allCheckers.initializeManager(*checkerMgr, checkerOpts); 117221345Sdim checkerMgr->finishedCheckerRegistration(); 118221345Sdim 119218887Sdim for (unsigned i = 0, e = checkerOpts.size(); i != e; ++i) { 120218887Sdim if (checkerOpts[i].isUnclaimed()) 121226633Sdim diags.Report(diag::warn_unknown_analyzer_checker) 122218887Sdim << checkerOpts[i].getName(); 123218887Sdim } 124218887Sdim 125218887Sdim return checkerMgr.take(); 126218887Sdim} 127219077Sdim 128226633Sdimvoid ento::printCheckerHelp(raw_ostream &out, ArrayRef<std::string> plugins) { 129226633Sdim out << "OVERVIEW: Clang Static Analyzer Checkers List\n\n"; 130226633Sdim out << "USAGE: -analyzer-checker <CHECKER or PACKAGE,...>\n\n"; 131219077Sdim 132226633Sdim ClangCheckerRegistry(plugins).printHelp(out); 133219077Sdim} 134