clang -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name CheckerRegistration.cpp -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-config-compatibility-mode=true -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -mrelocation-model pic -pic-level 2 -mthread-model posix -relaxed-aliasing -fmath-errno -masm-verbose -mconstructor-aliases -munwind-tables -fuse-init-array -target-cpu x86-64 -dwarf-column-info -debugger-tuning=gdb -momit-leaf-frame-pointer -ffunction-sections -fdata-sections -resource-dir /usr/lib/llvm-8/lib/clang/8.0.0 -D CLANG_VENDOR="Debian " -D _DEBUG -D _GNU_SOURCE -D __STDC_CONSTANT_MACROS -D __STDC_FORMAT_MACROS -D __STDC_LIMIT_MACROS -I /build/llvm-toolchain-snapshot-8~svn348900/build-llvm/tools/clang/lib/StaticAnalyzer/Frontend -I /build/llvm-toolchain-snapshot-8~svn348900/tools/clang/lib/StaticAnalyzer/Frontend -I /build/llvm-toolchain-snapshot-8~svn348900/tools/clang/include -I /build/llvm-toolchain-snapshot-8~svn348900/build-llvm/tools/clang/include -I /build/llvm-toolchain-snapshot-8~svn348900/build-llvm/include -I /build/llvm-toolchain-snapshot-8~svn348900/include -I /build/llvm-toolchain-snapshot-8~svn348900/build-llvm/tools/clang/lib/StaticAnalyzer/Frontend/../Checkers -U NDEBUG -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/c++/6.3.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/x86_64-linux-gnu/c++/6.3.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/x86_64-linux-gnu/c++/6.3.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/c++/6.3.0/backward -internal-isystem /usr/include/clang/8.0.0/include/ -internal-isystem /usr/local/include -internal-isystem /usr/lib/llvm-8/lib/clang/8.0.0/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-command-line-argument -Wno-unknown-warning-option -Wno-unused-parameter -Wwrite-strings -Wno-missing-field-initializers -Wno-long-long -Wno-maybe-uninitialized -Wno-comment -std=c++11 -fdeprecated-macro -fdebug-compilation-dir /build/llvm-toolchain-snapshot-8~svn348900/build-llvm/tools/clang/lib/StaticAnalyzer/Frontend -ferror-limit 19 -fmessage-length 0 -fvisibility-inlines-hidden -fobjc-runtime=gcc -fno-common -fdiagnostics-show-option -vectorize-loops -vectorize-slp -analyzer-output=html -analyzer-config stable-report-filename=true -o /tmp/scan-build-2018-12-12-042652-12204-1 -x c++ /build/llvm-toolchain-snapshot-8~svn348900/tools/clang/lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp -faddrsig
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | #include "clang/StaticAnalyzer/Frontend/CheckerRegistration.h" |
15 | #include "clang/Basic/Diagnostic.h" |
16 | #include "clang/Frontend/FrontendDiagnostic.h" |
17 | #include "clang/StaticAnalyzer/Checkers/ClangCheckers.h" |
18 | #include "clang/StaticAnalyzer/Core/AnalyzerOptions.h" |
19 | #include "clang/StaticAnalyzer/Core/CheckerManager.h" |
20 | #include "clang/StaticAnalyzer/Core/CheckerRegistry.h" |
21 | #include "clang/StaticAnalyzer/Frontend/FrontendActions.h" |
22 | #include "llvm/ADT/SmallVector.h" |
23 | #include "llvm/Support/DynamicLibrary.h" |
24 | #include "llvm/Support/FormattedStream.h" |
25 | #include "llvm/Support/Path.h" |
26 | #include "llvm/Support/raw_ostream.h" |
27 | #include <memory> |
28 | |
29 | using namespace clang; |
30 | using namespace ento; |
31 | using llvm::sys::DynamicLibrary; |
32 | |
33 | namespace { |
34 | class ClangCheckerRegistry : public CheckerRegistry { |
35 | typedef void (*RegisterCheckersFn)(CheckerRegistry &); |
36 | |
37 | static bool isCompatibleAPIVersion(const char *versionString); |
38 | static void warnIncompatible(DiagnosticsEngine *diags, StringRef pluginPath, |
39 | const char *pluginAPIVersion); |
40 | |
41 | public: |
42 | ClangCheckerRegistry(ArrayRef<std::string> plugins, |
43 | DiagnosticsEngine *diags = nullptr); |
44 | }; |
45 | |
46 | } |
47 | |
48 | ClangCheckerRegistry::ClangCheckerRegistry(ArrayRef<std::string> plugins, |
49 | DiagnosticsEngine *diags) { |
50 | registerBuiltinCheckers(*this); |
51 | |
52 | for (ArrayRef<std::string>::iterator i = plugins.begin(), e = plugins.end(); |
| 4 | | Loop condition is true. Entering loop body | |
|
53 | i != e; ++i) { |
| 3 | | Assuming 'i' is not equal to 'e' | |
|
54 | |
55 | std::string err; |
56 | DynamicLibrary lib = DynamicLibrary::getPermanentLibrary(i->c_str(), &err); |
57 | if (!lib.isValid()) { |
| |
58 | diags->Report(diag::err_fe_unable_to_load_plugin) << *i << err; |
| 6 | | Called C++ object pointer is null |
|
59 | continue; |
60 | } |
61 | |
62 | |
63 | const char *pluginAPIVersion = |
64 | (const char *) lib.getAddressOfSymbol("clang_analyzerAPIVersionString"); |
65 | if (!isCompatibleAPIVersion(pluginAPIVersion)) { |
66 | warnIncompatible(diags, *i, pluginAPIVersion); |
67 | continue; |
68 | } |
69 | |
70 | |
71 | RegisterCheckersFn registerPluginCheckers = |
72 | (RegisterCheckersFn) (intptr_t) lib.getAddressOfSymbol( |
73 | "clang_registerCheckers"); |
74 | if (registerPluginCheckers) |
75 | registerPluginCheckers(*this); |
76 | } |
77 | } |
78 | |
79 | bool ClangCheckerRegistry::isCompatibleAPIVersion(const char *versionString) { |
80 | |
81 | if (!versionString) |
82 | return false; |
83 | |
84 | |
85 | |
86 | return strcmp(versionString, CLANG_ANALYZER_API_VERSION_STRING"8.0.0") == 0; |
87 | } |
88 | |
89 | void ClangCheckerRegistry::warnIncompatible(DiagnosticsEngine *diags, |
90 | StringRef pluginPath, |
91 | const char *pluginAPIVersion) { |
92 | if (!diags) |
93 | return; |
94 | if (!pluginAPIVersion) |
95 | return; |
96 | |
97 | diags->Report(diag::warn_incompatible_analyzer_plugin_api) |
98 | << llvm::sys::path::filename(pluginPath); |
99 | diags->Report(diag::note_incompatible_analyzer_plugin_api) |
100 | << CLANG_ANALYZER_API_VERSION_STRING"8.0.0" |
101 | << pluginAPIVersion; |
102 | } |
103 | |
104 | std::unique_ptr<CheckerManager> ento::createCheckerManager( |
105 | ASTContext &context, |
106 | AnalyzerOptions &opts, |
107 | ArrayRef<std::string> plugins, |
108 | ArrayRef<std::function<void(CheckerRegistry &)>> checkerRegistrationFns, |
109 | DiagnosticsEngine &diags) { |
110 | auto checkerMgr = llvm::make_unique<CheckerManager>(context, opts); |
111 | |
112 | ClangCheckerRegistry allCheckers(plugins, &diags); |
113 | |
114 | for (const auto &Fn : checkerRegistrationFns) |
115 | Fn(allCheckers); |
116 | |
117 | allCheckers.initializeManager(*checkerMgr, opts, diags); |
118 | allCheckers.validateCheckerOptions(opts, diags); |
119 | checkerMgr->finishedCheckerRegistration(); |
120 | |
121 | return checkerMgr; |
122 | } |
123 | |
124 | void ento::printCheckerHelp(raw_ostream &out, ArrayRef<std::string> plugins) { |
125 | out << "OVERVIEW: Clang Static Analyzer Checkers List\n\n"; |
126 | out << "USAGE: -analyzer-checker <CHECKER or PACKAGE,...>\n\n"; |
127 | |
128 | ClangCheckerRegistry(plugins).printHelp(out); |
129 | } |
130 | |
131 | void ento::printEnabledCheckerList(raw_ostream &out, |
132 | ArrayRef<std::string> plugins, |
133 | const AnalyzerOptions &opts) { |
134 | out << "OVERVIEW: Clang Static Analyzer Enabled Checkers List\n\n"; |
135 | |
136 | ClangCheckerRegistry(plugins).printList(out, opts); |
| 1 | Passing null pointer value via 2nd parameter 'diags' | |
|
| 2 | | Calling constructor for 'ClangCheckerRegistry' | |
|
137 | } |
138 | |
139 | void ento::printAnalyzerConfigList(raw_ostream &out) { |
140 | out << "OVERVIEW: Clang Static Analyzer -analyzer-config Option List\n\n"; |
141 | out << "USAGE: clang -cc1 [CLANG_OPTIONS] -analyzer-config " |
142 | "<OPTION1=VALUE,OPTION2=VALUE,...>\n\n"; |
143 | out << " clang -cc1 [CLANG_OPTIONS] -analyzer-config OPTION1=VALUE, " |
144 | "-analyzer-config OPTION2=VALUE, ...\n\n"; |
145 | out << " clang [CLANG_OPTIONS] -Xclang -analyzer-config -Xclang" |
146 | "<OPTION1=VALUE,OPTION2=VALUE,...>\n\n"; |
147 | out << " clang [CLANG_OPTIONS] -Xclang -analyzer-config -Xclang " |
148 | "OPTION1=VALUE, -Xclang -analyzer-config -Xclang " |
149 | "OPTION2=VALUE, ...\n\n"; |
150 | out << "OPTIONS:\n\n"; |
151 | |
152 | using OptionAndDescriptionTy = std::pair<StringRef, std::string>; |
153 | OptionAndDescriptionTy PrintableOptions[] = { |
154 | #define ANALYZER_OPTION(TYPE, NAME, CMDFLAG, DESC, DEFAULT_VAL) \ |
155 | { \ |
156 | CMDFLAG, \ |
157 | llvm::Twine(llvm::Twine() + "(" + \ |
158 | (StringRef(#TYPE) == "StringRef" ? "string" : #TYPE ) + \ |
159 | ") " DESC \ |
160 | " (default: " #DEFAULT_VAL ")").str() \ |
161 | }, |
162 | |
163 | #define ANALYZER_OPTION_DEPENDS_ON_USER_MODE(TYPE, NAME, CMDFLAG, DESC, \ |
164 | SHALLOW_VAL, DEEP_VAL) \ |
165 | { \ |
166 | CMDFLAG, \ |
167 | llvm::Twine(llvm::Twine() + "(" + \ |
168 | (StringRef(#TYPE) == "StringRef" ? "string" : #TYPE ) + \ |
169 | ") " DESC \ |
170 | " (default: " #SHALLOW_VAL " in shallow mode, " #DEEP_VAL \ |
171 | " in deep mode)").str() \ |
172 | }, |
173 | #include "clang/StaticAnalyzer/Core/AnalyzerOptions.def" |
174 | #undef ANALYZER_OPTION |
175 | #undef ANALYZER_OPTION_DEPENDS_ON_USER_MODE |
176 | }; |
177 | |
178 | llvm::sort(PrintableOptions, [](const OptionAndDescriptionTy &LHS, |
179 | const OptionAndDescriptionTy &RHS) { |
180 | return LHS.first < RHS.first; |
181 | }); |
182 | |
183 | constexpr size_t MinLineWidth = 70; |
184 | constexpr size_t PadForOpt = 2; |
185 | constexpr size_t OptionWidth = 30; |
186 | constexpr size_t PadForDesc = PadForOpt + OptionWidth; |
187 | static_assert(MinLineWidth > PadForDesc, "MinLineWidth must be greater!"); |
188 | |
189 | llvm::formatted_raw_ostream FOut(out); |
190 | |
191 | for (const auto &Pair : PrintableOptions) { |
192 | FOut.PadToColumn(PadForOpt) << Pair.first; |
193 | |
194 | |
195 | if (FOut.getColumn() > PadForDesc) |
196 | FOut << '\n'; |
197 | |
198 | FOut.PadToColumn(PadForDesc); |
199 | |
200 | for (char C : Pair.second) { |
201 | if (FOut.getColumn() > MinLineWidth && C == ' ') { |
202 | FOut << '\n'; |
203 | FOut.PadToColumn(PadForDesc); |
204 | continue; |
205 | } |
206 | FOut << C; |
207 | } |
208 | FOut << "\n\n"; |
209 | } |
210 | } |