10
10
#include " clang/StaticAnalyzer/Frontend/CheckerRegistry.h"
11
11
#include " clang/Basic/Diagnostic.h"
12
12
#include " clang/Basic/LLVM.h"
13
+ #include " clang/Frontend/FrontendDiagnostic.h"
14
+ #include " clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
13
15
#include " clang/StaticAnalyzer/Core/CheckerManager.h"
14
16
#include " clang/StaticAnalyzer/Core/AnalyzerOptions.h"
15
17
#include " llvm/ADT/STLExtras.h"
16
18
#include " llvm/ADT/SetVector.h"
17
19
#include " llvm/ADT/StringMap.h"
18
20
#include " llvm/ADT/StringRef.h"
21
+ #include " llvm/Support/DynamicLibrary.h"
22
+ #include " llvm/Support/Path.h"
19
23
#include " llvm/Support/raw_ostream.h"
20
24
#include < algorithm>
21
25
22
26
using namespace clang ;
23
27
using namespace ento ;
28
+ using llvm::sys::DynamicLibrary;
29
+
30
+ using RegisterCheckersFn = void (*)(CheckerRegistry &);
31
+
32
+ static bool isCompatibleAPIVersion (const char *versionString) {
33
+ // If the version string is null, it's not an analyzer plugin.
34
+ if (!versionString)
35
+ return false ;
36
+
37
+ // For now, none of the static analyzer API is considered stable.
38
+ // Versions must match exactly.
39
+ return strcmp (versionString, CLANG_ANALYZER_API_VERSION_STRING) == 0 ;
40
+ }
41
+
42
+ CheckerRegistry::CheckerRegistry (ArrayRef<std::string> plugins,
43
+ DiagnosticsEngine &diags) : Diags(diags) {
44
+ #define GET_CHECKERS
45
+ #define CHECKER (FULLNAME, CLASS, HELPTEXT ) \
46
+ addChecker (register ##CLASS, FULLNAME, HELPTEXT);
47
+ #include " clang/StaticAnalyzer/Checkers/Checkers.inc"
48
+ #undef CHECKER
49
+ #undef GET_CHECKERS
50
+
51
+ for (ArrayRef<std::string>::iterator i = plugins.begin (), e = plugins.end ();
52
+ i != e; ++i) {
53
+ // Get access to the plugin.
54
+ std::string err;
55
+ DynamicLibrary lib = DynamicLibrary::getPermanentLibrary (i->c_str (), &err);
56
+ if (!lib.isValid ()) {
57
+ diags.Report (diag::err_fe_unable_to_load_plugin) << *i << err;
58
+ continue ;
59
+ }
60
+
61
+ // See if it's compatible with this build of clang.
62
+ const char *pluginAPIVersion =
63
+ (const char *) lib.getAddressOfSymbol (" clang_analyzerAPIVersionString" );
64
+ if (!isCompatibleAPIVersion (pluginAPIVersion)) {
65
+ Diags.Report (diag::warn_incompatible_analyzer_plugin_api)
66
+ << llvm::sys::path::filename (*i);
67
+ Diags.Report (diag::note_incompatible_analyzer_plugin_api)
68
+ << CLANG_ANALYZER_API_VERSION_STRING
69
+ << pluginAPIVersion;
70
+ continue ;
71
+ }
72
+
73
+ // Register its checkers.
74
+ RegisterCheckersFn registerPluginCheckers =
75
+ (RegisterCheckersFn) (intptr_t ) lib.getAddressOfSymbol (
76
+ " clang_registerCheckers" );
77
+ if (registerPluginCheckers)
78
+ registerPluginCheckers (*this );
79
+ }
80
+ }
24
81
25
82
static constexpr char PackageSeparator = ' .' ;
26
83
@@ -47,8 +104,7 @@ static bool isInPackage(const CheckerRegistry::CheckerInfo &checker,
47
104
}
48
105
49
106
CheckerRegistry::CheckerInfoSet CheckerRegistry::getEnabledCheckers (
50
- const AnalyzerOptions &Opts,
51
- DiagnosticsEngine &diags) const {
107
+ const AnalyzerOptions &Opts) const {
52
108
53
109
assert (std::is_sorted (Checkers.begin (), Checkers.end (), checkerNameLT) &&
54
110
" In order to efficiently gather checkers, this function expects them "
@@ -65,8 +121,8 @@ CheckerRegistry::CheckerInfoSet CheckerRegistry::getEnabledCheckers(
65
121
66
122
if (firstRelatedChecker == end ||
67
123
!isInPackage (*firstRelatedChecker, opt.first )) {
68
- diags .Report (diag::err_unknown_analyzer_checker) << opt.first ;
69
- diags .Report (diag::note_suggest_disabling_all_checkers);
124
+ Diags .Report (diag::err_unknown_analyzer_checker) << opt.first ;
125
+ Diags .Report (diag::note_suggest_disabling_all_checkers);
70
126
return {};
71
127
}
72
128
@@ -105,13 +161,12 @@ void CheckerRegistry::addChecker(InitializationFunction fn, StringRef name,
105
161
}
106
162
107
163
void CheckerRegistry::initializeManager (CheckerManager &checkerMgr,
108
- const AnalyzerOptions &Opts,
109
- DiagnosticsEngine &diags) const {
164
+ const AnalyzerOptions &Opts) const {
110
165
// Sort checkers for efficient collection.
111
166
llvm::sort (Checkers, checkerNameLT);
112
167
113
168
// Collect checkers enabled by the options.
114
- CheckerInfoSet enabledCheckers = getEnabledCheckers (Opts, diags );
169
+ CheckerInfoSet enabledCheckers = getEnabledCheckers (Opts);
115
170
116
171
// Initialize the CheckerManager with all enabled checkers.
117
172
for (const auto *i : enabledCheckers) {
@@ -120,8 +175,8 @@ void CheckerRegistry::initializeManager(CheckerManager &checkerMgr,
120
175
}
121
176
}
122
177
123
- void CheckerRegistry::validateCheckerOptions (const AnalyzerOptions &opts,
124
- DiagnosticsEngine &diags ) const {
178
+ void CheckerRegistry::validateCheckerOptions (
179
+ const AnalyzerOptions &opts ) const {
125
180
for (const auto &config : opts.Config ) {
126
181
size_t pos = config.getKey ().find (' :' );
127
182
if (pos == StringRef::npos)
@@ -137,7 +192,7 @@ void CheckerRegistry::validateCheckerOptions(const AnalyzerOptions &opts,
137
192
}
138
193
}
139
194
if (!hasChecker)
140
- diags .Report (diag::err_unknown_analyzer_checker) << checkerName;
195
+ Diags .Report (diag::err_unknown_analyzer_checker) << checkerName;
141
196
}
142
197
}
143
198
@@ -180,13 +235,12 @@ void CheckerRegistry::printHelp(raw_ostream &out,
180
235
}
181
236
182
237
void CheckerRegistry::printList (raw_ostream &out,
183
- const AnalyzerOptions &opts,
184
- DiagnosticsEngine &diags) const {
238
+ const AnalyzerOptions &opts) const {
185
239
// Sort checkers for efficient collection.
186
240
llvm::sort (Checkers, checkerNameLT);
187
241
188
242
// Collect checkers enabled by the options.
189
- CheckerInfoSet enabledCheckers = getEnabledCheckers (opts, diags );
243
+ CheckerInfoSet enabledCheckers = getEnabledCheckers (opts);
190
244
191
245
for (const auto *i : enabledCheckers)
192
246
out << i->FullName << ' \n ' ;
0 commit comments