diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp')
-rw-r--r-- | contrib/llvm/tools/clang/lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp | 108 |
1 files changed, 88 insertions, 20 deletions
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp index d7edc7e..a59fcad 100644 --- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp +++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp @@ -13,53 +13,121 @@ #include "clang/StaticAnalyzer/Frontend/CheckerRegistration.h" #include "clang/StaticAnalyzer/Frontend/FrontendActions.h" -#include "../Checkers/ClangSACheckerProvider.h" +#include "clang/StaticAnalyzer/Checkers/ClangCheckers.h" #include "clang/StaticAnalyzer/Core/CheckerManager.h" -#include "clang/StaticAnalyzer/Core/CheckerProvider.h" +#include "clang/StaticAnalyzer/Core/CheckerOptInfo.h" +#include "clang/StaticAnalyzer/Core/CheckerRegistry.h" #include "clang/Frontend/AnalyzerOptions.h" #include "clang/Frontend/FrontendDiagnostic.h" #include "clang/Basic/Diagnostic.h" +#include "llvm/Support/DynamicLibrary.h" +#include "llvm/Support/Path.h" #include "llvm/Support/raw_ostream.h" #include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/SmallVector.h" using namespace clang; using namespace ento; +using llvm::sys::DynamicLibrary; -CheckerManager *ento::registerCheckers(const AnalyzerOptions &opts, - const LangOptions &langOpts, - Diagnostic &diags) { +namespace { +class ClangCheckerRegistry : public CheckerRegistry { + typedef void (*RegisterCheckersFn)(CheckerRegistry &); + + static bool isCompatibleAPIVersion(const char *versionString); + static void warnIncompatible(DiagnosticsEngine *diags, StringRef pluginPath, + const char *pluginAPIVersion); + +public: + ClangCheckerRegistry(ArrayRef<std::string> plugins, + DiagnosticsEngine *diags = 0); +}; + +} // end anonymous namespace + +ClangCheckerRegistry::ClangCheckerRegistry(ArrayRef<std::string> plugins, + DiagnosticsEngine *diags) { + registerBuiltinCheckers(*this); + + for (ArrayRef<std::string>::iterator i = plugins.begin(), e = plugins.end(); + i != e; ++i) { + // Get access to the plugin. + DynamicLibrary lib = DynamicLibrary::getPermanentLibrary(i->c_str()); + + // See if it's compatible with this build of clang. + const char *pluginAPIVersion = + (const char *) lib.getAddressOfSymbol("clang_analyzerAPIVersionString"); + if (!isCompatibleAPIVersion(pluginAPIVersion)) { + warnIncompatible(diags, *i, pluginAPIVersion); + continue; + } + + // Register its checkers. + RegisterCheckersFn registerPluginCheckers = + (RegisterCheckersFn) (intptr_t) lib.getAddressOfSymbol( + "clang_registerCheckers"); + if (registerPluginCheckers) + registerPluginCheckers(*this); + } +} + +bool ClangCheckerRegistry::isCompatibleAPIVersion(const char *versionString) { + // If the version string is null, it's not an analyzer plugin. + if (versionString == 0) + return false; + + // For now, none of the static analyzer API is considered stable. + // Versions must match exactly. + if (strcmp(versionString, CLANG_ANALYZER_API_VERSION_STRING) == 0) + return true; + + return false; +} + +void ClangCheckerRegistry::warnIncompatible(DiagnosticsEngine *diags, + StringRef pluginPath, + const char *pluginAPIVersion) { + if (!diags) + return; + if (!pluginAPIVersion) + return; + + diags->Report(diag::warn_incompatible_analyzer_plugin_api) + << llvm::sys::path::filename(pluginPath); + diags->Report(diag::note_incompatible_analyzer_plugin_api) + << CLANG_ANALYZER_API_VERSION_STRING + << pluginAPIVersion; +} + + +CheckerManager *ento::createCheckerManager(const AnalyzerOptions &opts, + const LangOptions &langOpts, + ArrayRef<std::string> plugins, + DiagnosticsEngine &diags) { llvm::OwningPtr<CheckerManager> checkerMgr(new CheckerManager(langOpts)); - llvm::SmallVector<CheckerOptInfo, 8> checkerOpts; + SmallVector<CheckerOptInfo, 8> checkerOpts; for (unsigned i = 0, e = opts.CheckersControlList.size(); i != e; ++i) { const std::pair<std::string, bool> &opt = opts.CheckersControlList[i]; checkerOpts.push_back(CheckerOptInfo(opt.first.c_str(), opt.second)); } - llvm::OwningPtr<CheckerProvider> provider(createClangSACheckerProvider()); - provider->registerCheckers(*checkerMgr, - checkerOpts.data(), checkerOpts.size()); - - // FIXME: Load CheckerProviders from plugins. - + ClangCheckerRegistry allCheckers(plugins, &diags); + allCheckers.initializeManager(*checkerMgr, checkerOpts); checkerMgr->finishedCheckerRegistration(); for (unsigned i = 0, e = checkerOpts.size(); i != e; ++i) { if (checkerOpts[i].isUnclaimed()) - diags.Report(diag::warn_unkwown_analyzer_checker) + diags.Report(diag::warn_unknown_analyzer_checker) << checkerOpts[i].getName(); } return checkerMgr.take(); } -void ento::printCheckerHelp(llvm::raw_ostream &OS) { - OS << "OVERVIEW: Clang Static Analyzer Checkers List\n"; - OS << '\n'; - - llvm::OwningPtr<CheckerProvider> provider(createClangSACheckerProvider()); - provider->printHelp(OS); +void ento::printCheckerHelp(raw_ostream &out, ArrayRef<std::string> plugins) { + out << "OVERVIEW: Clang Static Analyzer Checkers List\n\n"; + out << "USAGE: -analyzer-checker <CHECKER or PACKAGE,...>\n\n"; - // FIXME: Load CheckerProviders from plugins. + ClangCheckerRegistry(plugins).printHelp(out); } |