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