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