xref: /minix3/external/bsd/llvm/dist/clang/lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
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