diff options
Diffstat (limited to 'lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp')
-rw-r--r-- | lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp | 60 |
1 files changed, 49 insertions, 11 deletions
diff --git a/lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp b/lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp index 8ed74a2267..922cd844bb 100644 --- a/lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp +++ b/lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp @@ -20,20 +20,63 @@ #include "clang/Frontend/AnalyzerOptions.h" #include "clang/Frontend/FrontendDiagnostic.h" #include "clang/Basic/Diagnostic.h" +#include "llvm/Support/DynamicLibrary.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; -static void registerCheckers(CheckerRegistry ®istry, - ArrayRef<std::string> plugins) { - registerBuiltinCheckers(registry); +namespace { +class ClangCheckerRegistry : public CheckerRegistry { + typedef void (*RegisterCheckersFn)(CheckerRegistry &); +public: + ClangCheckerRegistry(ArrayRef<std::string> plugins); - // FIXME: register plugins. + static bool isCompatibleAPIVersion(const char *versionString); +}; + +} // end anonymous namespace + +ClangCheckerRegistry::ClangCheckerRegistry(ArrayRef<std::string> plugins) { + 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)) + continue; + + // Register its checkers. + RegisterCheckersFn registerPluginCheckers = + (RegisterCheckersFn) 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; + + // FIXME: Should we emit a diagnostic if the version doesn't match? + return false; +} + + CheckerManager *ento::createCheckerManager(const AnalyzerOptions &opts, const LangOptions &langOpts, ArrayRef<std::string> plugins, @@ -46,10 +89,7 @@ CheckerManager *ento::createCheckerManager(const AnalyzerOptions &opts, checkerOpts.push_back(CheckerOptInfo(opt.first.c_str(), opt.second)); } - CheckerRegistry allCheckers; - registerCheckers(allCheckers, plugins); - allCheckers.initializeManager(*checkerMgr, checkerOpts); - + ClangCheckerRegistry(plugins).initializeManager(*checkerMgr, checkerOpts); checkerMgr->finishedCheckerRegistration(); for (unsigned i = 0, e = checkerOpts.size(); i != e; ++i) { @@ -65,7 +105,5 @@ 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"; - CheckerRegistry allCheckers; - registerCheckers(allCheckers, plugins); - allCheckers.printHelp(out); + ClangCheckerRegistry(plugins).printHelp(out); } |