CheckerRegistration.cpp revision 5705a40c7ec62f1a903bf26e1e6a7f91b5b98ba3
118a1444b4f1e6a0948fd38fa0de382d86cfe04deBernhard Rosenkränzer//===--- CheckerRegistration.cpp - Registration for the Analyzer Checkers -===// 218a1444b4f1e6a0948fd38fa0de382d86cfe04deBernhard Rosenkränzer// 318a1444b4f1e6a0948fd38fa0de382d86cfe04deBernhard Rosenkränzer// The LLVM Compiler Infrastructure 418a1444b4f1e6a0948fd38fa0de382d86cfe04deBernhard Rosenkränzer// 518a1444b4f1e6a0948fd38fa0de382d86cfe04deBernhard Rosenkränzer// This file is distributed under the University of Illinois Open Source 618a1444b4f1e6a0948fd38fa0de382d86cfe04deBernhard Rosenkränzer// License. See LICENSE.TXT for details. 718a1444b4f1e6a0948fd38fa0de382d86cfe04deBernhard Rosenkränzer// 8e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall//===----------------------------------------------------------------------===// 9e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall// 1018a1444b4f1e6a0948fd38fa0de382d86cfe04deBernhard Rosenkränzer// Defines the registration function for the analyzer checkers. 11e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall// 12e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall//===----------------------------------------------------------------------===// 13e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 14e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#include "clang/StaticAnalyzer/Frontend/CheckerRegistration.h" 15e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#include "clang/StaticAnalyzer/Frontend/FrontendActions.h" 16e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#include "clang/StaticAnalyzer/Checkers/ClangCheckers.h" 17e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#include "clang/StaticAnalyzer/Core/CheckerManager.h" 18e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#include "clang/StaticAnalyzer/Core/CheckerOptInfo.h" 19e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#include "clang/StaticAnalyzer/Core/CheckerRegistry.h" 20e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#include "clang/StaticAnalyzer/AnalyzerOptions.h" 21e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#include "clang/Frontend/FrontendDiagnostic.h" 22e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#include "clang/Basic/Diagnostic.h" 23e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#include "llvm/Support/DynamicLibrary.h" 24e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#include "llvm/Support/Path.h" 25e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#include "llvm/Support/raw_ostream.h" 26e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#include "llvm/ADT/OwningPtr.h" 27e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#include "llvm/ADT/SmallVector.h" 28e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 29e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallusing namespace clang; 30e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallusing namespace ento; 31e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallusing llvm::sys::DynamicLibrary; 32e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 33e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallnamespace { 34e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallclass ClangCheckerRegistry : public CheckerRegistry { 35e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall typedef void (*RegisterCheckersFn)(CheckerRegistry &); 36e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 37e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall static bool isCompatibleAPIVersion(const char *versionString); 38e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall static void warnIncompatible(DiagnosticsEngine *diags, StringRef pluginPath, 39e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall const char *pluginAPIVersion); 40e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 41e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallpublic: 42e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ClangCheckerRegistry(ArrayRef<std::string> plugins, 43e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall DiagnosticsEngine *diags = 0); 44e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall}; 45e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 46e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall} // end anonymous namespace 47e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 48e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP AbgrallClangCheckerRegistry::ClangCheckerRegistry(ArrayRef<std::string> plugins, 49e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall DiagnosticsEngine *diags) { 50e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall registerBuiltinCheckers(*this); 51e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 52e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall for (ArrayRef<std::string>::iterator i = plugins.begin(), e = plugins.end(); 53e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall i != e; ++i) { 54e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall // Get access to the plugin. 55e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall DynamicLibrary lib = DynamicLibrary::getPermanentLibrary(i->c_str()); 56e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 57e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall // See if it's compatible with this build of clang. 58e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall const char *pluginAPIVersion = 59e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall (const char *) lib.getAddressOfSymbol("clang_analyzerAPIVersionString"); 60e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (!isCompatibleAPIVersion(pluginAPIVersion)) { 61e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall warnIncompatible(diags, *i, pluginAPIVersion); 62e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall continue; 63e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 64e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 65e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall // Register its checkers. 66e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall RegisterCheckersFn registerPluginCheckers = 67e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall (RegisterCheckersFn) (intptr_t) lib.getAddressOfSymbol( 68e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall "clang_registerCheckers"); 69e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (registerPluginCheckers) 70e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall registerPluginCheckers(*this); 71e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 72e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall} 73e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 74e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallbool ClangCheckerRegistry::isCompatibleAPIVersion(const char *versionString) { 75e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall // If the version string is null, it's not an analyzer plugin. 76e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (versionString == 0) 77e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return false; 78e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 79e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall // For now, none of the static analyzer API is considered stable. 80e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall // Versions must match exactly. 81e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (strcmp(versionString, CLANG_ANALYZER_API_VERSION_STRING) == 0) 82e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return true; 83e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 84e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return false; 85e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall} 86e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 87e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallvoid ClangCheckerRegistry::warnIncompatible(DiagnosticsEngine *diags, 88e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall StringRef pluginPath, 89e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall const char *pluginAPIVersion) { 90e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (!diags) 91e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return; 92e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (!pluginAPIVersion) 93e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return; 94e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 95e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall diags->Report(diag::warn_incompatible_analyzer_plugin_api) 96e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall << llvm::sys::path::filename(pluginPath); 97e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall diags->Report(diag::note_incompatible_analyzer_plugin_api) 98e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall << CLANG_ANALYZER_API_VERSION_STRING 99e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall << pluginAPIVersion; 100e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall} 101e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 102e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 103e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP AbgrallCheckerManager *ento::createCheckerManager(const AnalyzerOptions &opts, 104e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall const LangOptions &langOpts, 105e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ArrayRef<std::string> plugins, 106e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall DiagnosticsEngine &diags) { 107e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall OwningPtr<CheckerManager> checkerMgr(new CheckerManager(langOpts)); 108e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 109e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall SmallVector<CheckerOptInfo, 8> checkerOpts; 110e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall for (unsigned i = 0, e = opts.CheckersControlList.size(); i != e; ++i) { 111e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall const std::pair<std::string, bool> &opt = opts.CheckersControlList[i]; 112e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall checkerOpts.push_back(CheckerOptInfo(opt.first.c_str(), opt.second)); 113e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 114e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 115e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ClangCheckerRegistry allCheckers(plugins, &diags); 116e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall allCheckers.initializeManager(*checkerMgr, checkerOpts); 117e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall checkerMgr->finishedCheckerRegistration(); 118e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 119e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall for (unsigned i = 0, e = checkerOpts.size(); i != e; ++i) { 120e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (checkerOpts[i].isUnclaimed()) 121e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall diags.Report(diag::err_unknown_analyzer_checker) 122e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall << checkerOpts[i].getName(); 123e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 124e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 125e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return checkerMgr.take(); 126e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall} 127e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 128e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallvoid ento::printCheckerHelp(raw_ostream &out, ArrayRef<std::string> plugins) { 129e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall out << "OVERVIEW: Clang Static Analyzer Checkers List\n\n"; 130e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall out << "USAGE: -analyzer-checker <CHECKER or PACKAGE,...>\n\n"; 131e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 132e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ClangCheckerRegistry(plugins).printHelp(out); 133e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall} 134e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall