diff options
Diffstat (limited to 'lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp')
| -rw-r--r-- | lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp | 108 | 
1 files changed, 88 insertions, 20 deletions
diff --git a/lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp b/lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp index d7edc7e599df..a59fcad6f819 100644 --- a/lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp +++ b/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);  }  | 
