clang API Documentation
00001 //===--- CheckerRegistration.cpp - Registration for the Analyzer Checkers -===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // Defines the registration function for the analyzer checkers. 00011 // 00012 //===----------------------------------------------------------------------===// 00013 00014 #include "clang/StaticAnalyzer/Frontend/CheckerRegistration.h" 00015 #include "clang/Basic/Diagnostic.h" 00016 #include "clang/Frontend/FrontendDiagnostic.h" 00017 #include "clang/StaticAnalyzer/Checkers/ClangCheckers.h" 00018 #include "clang/StaticAnalyzer/Core/AnalyzerOptions.h" 00019 #include "clang/StaticAnalyzer/Core/CheckerManager.h" 00020 #include "clang/StaticAnalyzer/Core/CheckerOptInfo.h" 00021 #include "clang/StaticAnalyzer/Core/CheckerRegistry.h" 00022 #include "clang/StaticAnalyzer/Frontend/FrontendActions.h" 00023 #include "llvm/ADT/SmallVector.h" 00024 #include "llvm/Support/DynamicLibrary.h" 00025 #include "llvm/Support/Path.h" 00026 #include "llvm/Support/raw_ostream.h" 00027 #include <memory> 00028 00029 using namespace clang; 00030 using namespace ento; 00031 using llvm::sys::DynamicLibrary; 00032 00033 namespace { 00034 class ClangCheckerRegistry : public CheckerRegistry { 00035 typedef void (*RegisterCheckersFn)(CheckerRegistry &); 00036 00037 static bool isCompatibleAPIVersion(const char *versionString); 00038 static void warnIncompatible(DiagnosticsEngine *diags, StringRef pluginPath, 00039 const char *pluginAPIVersion); 00040 00041 public: 00042 ClangCheckerRegistry(ArrayRef<std::string> plugins, 00043 DiagnosticsEngine *diags = nullptr); 00044 }; 00045 00046 } // end anonymous namespace 00047 00048 ClangCheckerRegistry::ClangCheckerRegistry(ArrayRef<std::string> plugins, 00049 DiagnosticsEngine *diags) { 00050 registerBuiltinCheckers(*this); 00051 00052 for (ArrayRef<std::string>::iterator i = plugins.begin(), e = plugins.end(); 00053 i != e; ++i) { 00054 // Get access to the plugin. 00055 DynamicLibrary lib = DynamicLibrary::getPermanentLibrary(i->c_str()); 00056 00057 // See if it's compatible with this build of clang. 00058 const char *pluginAPIVersion = 00059 (const char *) lib.getAddressOfSymbol("clang_analyzerAPIVersionString"); 00060 if (!isCompatibleAPIVersion(pluginAPIVersion)) { 00061 warnIncompatible(diags, *i, pluginAPIVersion); 00062 continue; 00063 } 00064 00065 // Register its checkers. 00066 RegisterCheckersFn registerPluginCheckers = 00067 (RegisterCheckersFn) (intptr_t) lib.getAddressOfSymbol( 00068 "clang_registerCheckers"); 00069 if (registerPluginCheckers) 00070 registerPluginCheckers(*this); 00071 } 00072 } 00073 00074 bool ClangCheckerRegistry::isCompatibleAPIVersion(const char *versionString) { 00075 // If the version string is null, it's not an analyzer plugin. 00076 if (!versionString) 00077 return false; 00078 00079 // For now, none of the static analyzer API is considered stable. 00080 // Versions must match exactly. 00081 if (strcmp(versionString, CLANG_ANALYZER_API_VERSION_STRING) == 0) 00082 return true; 00083 00084 return false; 00085 } 00086 00087 void ClangCheckerRegistry::warnIncompatible(DiagnosticsEngine *diags, 00088 StringRef pluginPath, 00089 const char *pluginAPIVersion) { 00090 if (!diags) 00091 return; 00092 if (!pluginAPIVersion) 00093 return; 00094 00095 diags->Report(diag::warn_incompatible_analyzer_plugin_api) 00096 << llvm::sys::path::filename(pluginPath); 00097 diags->Report(diag::note_incompatible_analyzer_plugin_api) 00098 << CLANG_ANALYZER_API_VERSION_STRING 00099 << pluginAPIVersion; 00100 } 00101 00102 std::unique_ptr<CheckerManager> 00103 ento::createCheckerManager(AnalyzerOptions &opts, const LangOptions &langOpts, 00104 ArrayRef<std::string> plugins, 00105 DiagnosticsEngine &diags) { 00106 std::unique_ptr<CheckerManager> checkerMgr( 00107 new CheckerManager(langOpts, &opts)); 00108 00109 SmallVector<CheckerOptInfo, 8> checkerOpts; 00110 for (unsigned i = 0, e = opts.CheckersControlList.size(); i != e; ++i) { 00111 const std::pair<std::string, bool> &opt = opts.CheckersControlList[i]; 00112 checkerOpts.push_back(CheckerOptInfo(opt.first.c_str(), opt.second)); 00113 } 00114 00115 ClangCheckerRegistry allCheckers(plugins, &diags); 00116 allCheckers.initializeManager(*checkerMgr, checkerOpts); 00117 checkerMgr->finishedCheckerRegistration(); 00118 00119 for (unsigned i = 0, e = checkerOpts.size(); i != e; ++i) { 00120 if (checkerOpts[i].isUnclaimed()) { 00121 diags.Report(diag::err_unknown_analyzer_checker) 00122 << checkerOpts[i].getName(); 00123 diags.Report(diag::note_suggest_disabling_all_checkers); 00124 } 00125 00126 } 00127 00128 return std::move(checkerMgr); 00129 } 00130 00131 void ento::printCheckerHelp(raw_ostream &out, ArrayRef<std::string> plugins) { 00132 out << "OVERVIEW: Clang Static Analyzer Checkers List\n\n"; 00133 out << "USAGE: -analyzer-checker <CHECKER or PACKAGE,...>\n\n"; 00134 00135 ClangCheckerRegistry(plugins).printHelp(out); 00136 }