Coverage Report

Created: 2019-07-24 05:18

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/tools/clang/lib/StaticAnalyzer/Frontend/CheckerRegistry.cpp
Line
Count
Source (jump to first uncovered line)
1
//===- CheckerRegistry.cpp - Maintains all available checkers -------------===//
2
//
3
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
// See https://llvm.org/LICENSE.txt for license information.
5
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
//
7
//===----------------------------------------------------------------------===//
8
9
#include "clang/StaticAnalyzer/Frontend/CheckerRegistry.h"
10
#include "clang/Basic/Diagnostic.h"
11
#include "clang/Basic/LLVM.h"
12
#include "clang/Driver/DriverDiagnostic.h"
13
#include "clang/Frontend/FrontendDiagnostic.h"
14
#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
15
#include "clang/StaticAnalyzer/Core/AnalyzerOptions.h"
16
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
17
#include "llvm/ADT/STLExtras.h"
18
#include "llvm/ADT/SetVector.h"
19
#include "llvm/ADT/StringMap.h"
20
#include "llvm/ADT/StringRef.h"
21
#include "llvm/Support/DynamicLibrary.h"
22
#include "llvm/Support/Path.h"
23
#include "llvm/Support/raw_ostream.h"
24
#include <algorithm>
25
26
using namespace clang;
27
using namespace ento;
28
using llvm::sys::DynamicLibrary;
29
30
using RegisterCheckersFn = void (*)(CheckerRegistry &);
31
32
15
static bool isCompatibleAPIVersion(const char *VersionString) {
33
15
  // If the version string is null, its not an analyzer plugin.
34
15
  if (!VersionString)
35
0
    return false;
36
15
37
15
  // For now, none of the static analyzer API is considered stable.
38
15
  // Versions must match exactly.
39
15
  return strcmp(VersionString, CLANG_ANALYZER_API_VERSION_STRING) == 0;
40
15
}
41
42
namespace {
43
template <class T> struct FullNameLT {
44
2.21M
  bool operator()(const T &Lhs, const T &Rhs) {
45
2.21M
    return Lhs.FullName < Rhs.FullName;
46
2.21M
  }
CheckerRegistry.cpp:(anonymous namespace)::FullNameLT<clang::ento::CheckerRegistry::CheckerInfo>::operator()(clang::ento::CheckerRegistry::CheckerInfo const&, clang::ento::CheckerRegistry::CheckerInfo const&)
Line
Count
Source
44
2.00M
  bool operator()(const T &Lhs, const T &Rhs) {
45
2.00M
    return Lhs.FullName < Rhs.FullName;
46
2.00M
  }
CheckerRegistry.cpp:(anonymous namespace)::FullNameLT<clang::ento::CheckerRegistry::PackageInfo>::operator()(clang::ento::CheckerRegistry::PackageInfo const&, clang::ento::CheckerRegistry::PackageInfo const&)
Line
Count
Source
44
208k
  bool operator()(const T &Lhs, const T &Rhs) {
45
208k
    return Lhs.FullName < Rhs.FullName;
46
208k
  }
47
};
48
49
using PackageNameLT = FullNameLT<CheckerRegistry::PackageInfo>;
50
using CheckerNameLT = FullNameLT<CheckerRegistry::CheckerInfo>;
51
} // end of anonymous namespace
52
53
template <class CheckerOrPackageInfoList>
54
static
55
    typename std::conditional<std::is_const<CheckerOrPackageInfoList>::value,
56
                              typename CheckerOrPackageInfoList::const_iterator,
57
                              typename CheckerOrPackageInfoList::iterator>::type
58
120k
    binaryFind(CheckerOrPackageInfoList &Collection, StringRef FullName) {
59
120k
60
120k
  using CheckerOrPackage = typename CheckerOrPackageInfoList::value_type;
61
120k
  using CheckerOrPackageFullNameLT = FullNameLT<CheckerOrPackage>;
62
120k
63
120k
  assert(std::is_sorted(Collection.begin(), Collection.end(),
64
120k
                        CheckerOrPackageFullNameLT{}) &&
65
120k
         "In order to efficiently gather checkers/packages, this function "
66
120k
         "expects them to be already sorted!");
67
120k
68
120k
  return llvm::lower_bound(Collection, CheckerOrPackage(FullName),
69
120k
                           CheckerOrPackageFullNameLT{});
70
120k
}
CheckerRegistry.cpp:std::__1::conditional<std::is_const<std::__1::vector<clang::ento::CheckerRegistry::CheckerInfo, std::__1::allocator<clang::ento::CheckerRegistry::CheckerInfo> > >::value, std::__1::vector<clang::ento::CheckerRegistry::CheckerInfo, std::__1::allocator<clang::ento::CheckerRegistry::CheckerInfo> >::const_iterator, std::__1::vector<clang::ento::CheckerRegistry::CheckerInfo, std::__1::allocator<clang::ento::CheckerRegistry::CheckerInfo> >::iterator>::type binaryFind<std::__1::vector<clang::ento::CheckerRegistry::CheckerInfo, std::__1::allocator<clang::ento::CheckerRegistry::CheckerInfo> > >(std::__1::vector<clang::ento::CheckerRegistry::CheckerInfo, std::__1::allocator<clang::ento::CheckerRegistry::CheckerInfo> >&, llvm::StringRef)
Line
Count
Source
58
119k
    binaryFind(CheckerOrPackageInfoList &Collection, StringRef FullName) {
59
119k
60
119k
  using CheckerOrPackage = typename CheckerOrPackageInfoList::value_type;
61
119k
  using CheckerOrPackageFullNameLT = FullNameLT<CheckerOrPackage>;
62
119k
63
119k
  assert(std::is_sorted(Collection.begin(), Collection.end(),
64
119k
                        CheckerOrPackageFullNameLT{}) &&
65
119k
         "In order to efficiently gather checkers/packages, this function "
66
119k
         "expects them to be already sorted!");
67
119k
68
119k
  return llvm::lower_bound(Collection, CheckerOrPackage(FullName),
69
119k
                           CheckerOrPackageFullNameLT{});
70
119k
}
CheckerRegistry.cpp:std::__1::conditional<std::is_const<llvm::SmallVector<clang::ento::CheckerRegistry::PackageInfo, 0u> >::value, llvm::SmallVector<clang::ento::CheckerRegistry::PackageInfo, 0u>::const_iterator, llvm::SmallVector<clang::ento::CheckerRegistry::PackageInfo, 0u>::iterator>::type binaryFind<llvm::SmallVector<clang::ento::CheckerRegistry::PackageInfo, 0u> >(llvm::SmallVector<clang::ento::CheckerRegistry::PackageInfo, 0u>&, llvm::StringRef)
Line
Count
Source
58
930
    binaryFind(CheckerOrPackageInfoList &Collection, StringRef FullName) {
59
930
60
930
  using CheckerOrPackage = typename CheckerOrPackageInfoList::value_type;
61
930
  using CheckerOrPackageFullNameLT = FullNameLT<CheckerOrPackage>;
62
930
63
930
  assert(std::is_sorted(Collection.begin(), Collection.end(),
64
930
                        CheckerOrPackageFullNameLT{}) &&
65
930
         "In order to efficiently gather checkers/packages, this function "
66
930
         "expects them to be already sorted!");
67
930
68
930
  return llvm::lower_bound(Collection, CheckerOrPackage(FullName),
69
930
                           CheckerOrPackageFullNameLT{});
70
930
}
71
72
static constexpr char PackageSeparator = '.';
73
74
static bool isInPackage(const CheckerRegistry::CheckerInfo &Checker,
75
1.93k
                        StringRef PackageName) {
76
1.93k
  // Does the checker's full name have the package as a prefix?
77
1.93k
  if (!Checker.FullName.startswith(PackageName))
78
1
    return false;
79
1.93k
80
1.93k
  // Is the package actually just the name of a specific checker?
81
1.93k
  if (Checker.FullName.size() == PackageName.size())
82
984
    return true;
83
951
84
951
  // Is the checker in the package (or a subpackage)?
85
951
  if (Checker.FullName[PackageName.size()] == PackageSeparator)
86
951
    return true;
87
0
88
0
  return false;
89
0
}
90
91
CheckerRegistry::CheckerInfoListRange
92
1.93k
CheckerRegistry::getMutableCheckersForCmdLineArg(StringRef CmdLineArg) {
93
1.93k
  auto It = binaryFind(Checkers, CmdLineArg);
94
1.93k
95
1.93k
  if (!isInPackage(*It, CmdLineArg))
96
1
    return {Checkers.end(), Checkers.end()};
97
1.93k
98
1.93k
  // See how large the package is.
99
1.93k
  // If the package doesn't exist, assume the option refers to a single
100
1.93k
  // checker.
101
1.93k
  size_t Size = 1;
102
1.93k
  llvm::StringMap<size_t>::const_iterator PackageSize =
103
1.93k
      PackageSizes.find(CmdLineArg);
104
1.93k
105
1.93k
  if (PackageSize != PackageSizes.end())
106
951
    Size = PackageSize->getValue();
107
1.93k
108
1.93k
  return {It, It + Size};
109
1.93k
}
110
111
CheckerRegistry::CheckerRegistry(
112
    ArrayRef<std::string> Plugins, DiagnosticsEngine &Diags,
113
    AnalyzerOptions &AnOpts, const LangOptions &LangOpts,
114
    ArrayRef<std::function<void(CheckerRegistry &)>> CheckerRegistrationFns)
115
930
    : Diags(Diags), AnOpts(AnOpts), LangOpts(LangOpts) {
116
930
117
930
  // Register builtin checkers.
118
930
#define GET_CHECKERS
119
930
#define CHECKER(FULLNAME, CLASS, HELPTEXT, DOC_URI, IS_HIDDEN)                 \
120
152k
  addChecker(register##CLASS, shouldRegister##CLASS, FULLNAME, HELPTEXT,       \
121
152k
             DOC_URI, IS_HIDDEN);
122
930
123
930
#define GET_PACKAGES
124
39.0k
#define PACKAGE(FULLNAME) addPackage(FULLNAME);
125
930
126
930
#include "clang/StaticAnalyzer/Checkers/Checkers.inc"
127
930
#undef CHECKER
128
930
#undef GET_CHECKERS
129
930
#undef PACKAGE
130
930
#undef GET_PACKAGES
131
930
132
930
  // Register checkers from plugins.
133
930
  for (const std::string &Plugin : Plugins) {
134
15
    // Get access to the plugin.
135
15
    std::string ErrorMsg;
136
15
    DynamicLibrary Lib =
137
15
        DynamicLibrary::getPermanentLibrary(Plugin.c_str(), &ErrorMsg);
138
15
    if (!Lib.isValid()) {
139
0
      Diags.Report(diag::err_fe_unable_to_load_plugin) << Plugin << ErrorMsg;
140
0
      continue;
141
0
    }
142
15
143
15
    // See if its compatible with this build of clang.
144
15
    const char *PluginAPIVersion = static_cast<const char *>(
145
15
        Lib.getAddressOfSymbol("clang_analyzerAPIVersionString"));
146
15
147
15
    if (!isCompatibleAPIVersion(PluginAPIVersion)) {
148
0
      Diags.Report(diag::warn_incompatible_analyzer_plugin_api)
149
0
          << llvm::sys::path::filename(Plugin);
150
0
      Diags.Report(diag::note_incompatible_analyzer_plugin_api)
151
0
          << CLANG_ANALYZER_API_VERSION_STRING << PluginAPIVersion;
152
0
      continue;
153
0
    }
154
15
155
15
    // Register its checkers.
156
15
    RegisterCheckersFn RegisterPluginCheckers =
157
15
        reinterpret_cast<RegisterCheckersFn>(
158
15
            Lib.getAddressOfSymbol("clang_registerCheckers"));
159
15
    if (RegisterPluginCheckers)
160
15
      RegisterPluginCheckers(*this);
161
15
  }
162
930
163
930
  // Register statically linked checkers, that aren't generated from the tblgen
164
930
  // file, but rather passed their registry function as a parameter in
165
930
  // checkerRegistrationFns.
166
930
167
930
  for (const auto &Fn : CheckerRegistrationFns)
168
2
    Fn(*this);
169
930
170
930
  // Sort checkers for efficient collection.
171
930
  // FIXME: Alphabetical sort puts 'experimental' in the middle.
172
930
  // Would it be better to name it '~experimental' or something else
173
930
  // that's ASCIIbetically last?
174
930
  llvm::sort(Packages, PackageNameLT{});
175
930
  llvm::sort(Checkers, CheckerNameLT{});
176
930
177
930
#define GET_CHECKER_DEPENDENCIES
178
930
179
930
#define CHECKER_DEPENDENCY(FULLNAME, DEPENDENCY)                               \
180
42.7k
  addDependency(FULLNAME, DEPENDENCY);
181
930
182
930
#define GET_CHECKER_OPTIONS
183
930
#define CHECKER_OPTION(TYPE, FULLNAME, CMDFLAG, DESC, DEFAULT_VAL, DEVELOPMENT_STATUS, IS_HIDDEN)  \
184
31.6k
  addCheckerOption(TYPE, FULLNAME, CMDFLAG, DEFAULT_VAL, DESC, DEVELOPMENT_STATUS, IS_HIDDEN);
185
930
186
930
#define GET_PACKAGE_OPTIONS
187
930
#define PACKAGE_OPTION(TYPE, FULLNAME, CMDFLAG, DESC, DEFAULT_VAL, DEVELOPMENT_STATUS, IS_HIDDEN)  \
188
930
  addPackageOption(TYPE, FULLNAME, CMDFLAG, DEFAULT_VAL, DESC, DEVELOPMENT_STATUS, IS_HIDDEN);
189
930
190
930
#include "clang/StaticAnalyzer/Checkers/Checkers.inc"
191
930
#undef CHECKER_DEPENDENCY
192
930
#undef GET_CHECKER_DEPENDENCIES
193
930
#undef CHECKER_OPTION
194
930
#undef GET_CHECKER_OPTIONS
195
930
#undef PACKAGE_OPTION
196
930
#undef GET_PACKAGE_OPTIONS
197
930
198
930
  resolveDependencies();
199
930
  resolveCheckerAndPackageOptions();
200
930
201
930
  // Parse '-analyzer-checker' and '-analyzer-disable-checker' options from the
202
930
  // command line.
203
1.93k
  for (const std::pair<std::string, bool> &Opt : AnOpts.CheckersControlList) {
204
1.93k
    CheckerInfoListRange CheckerForCmdLineArg =
205
1.93k
        getMutableCheckersForCmdLineArg(Opt.first);
206
1.93k
207
1.93k
    if (CheckerForCmdLineArg.begin() == CheckerForCmdLineArg.end()) {
208
1
      Diags.Report(diag::err_unknown_analyzer_checker) << Opt.first;
209
1
      Diags.Report(diag::note_suggest_disabling_all_checkers);
210
1
    }
211
1.93k
212
15.0k
    for (CheckerInfo &checker : CheckerForCmdLineArg) {
213
15.0k
      checker.State = Opt.second ? 
StateFromCmdLine::State_Enabled15.0k
214
15.0k
                                 : 
StateFromCmdLine::State_Disabled10
;
215
15.0k
    }
216
1.93k
  }
217
930
}
218
219
/// Collects dependencies in \p ret, returns false on failure.
220
static bool
221
collectDependenciesImpl(const CheckerRegistry::ConstCheckerInfoList &Deps,
222
                        const LangOptions &LO,
223
                        CheckerRegistry::CheckerInfoSet &Ret);
224
225
/// Collects dependenies in \p enabledCheckers. Return None on failure.
226
LLVM_NODISCARD
227
static llvm::Optional<CheckerRegistry::CheckerInfoSet>
228
collectDependencies(const CheckerRegistry::CheckerInfo &checker,
229
14.9k
                    const LangOptions &LO) {
230
14.9k
231
14.9k
  CheckerRegistry::CheckerInfoSet Ret;
232
14.9k
  // Add dependencies to the enabled checkers only if all of them can be
233
14.9k
  // enabled.
234
14.9k
  if (!collectDependenciesImpl(checker.Dependencies, LO, Ret))
235
4
    return None;
236
14.9k
237
14.9k
  return Ret;
238
14.9k
}
239
240
static bool
241
collectDependenciesImpl(const CheckerRegistry::ConstCheckerInfoList &Deps,
242
                        const LangOptions &LO,
243
17.1k
                        CheckerRegistry::CheckerInfoSet &Ret) {
244
17.1k
245
17.1k
  for (const CheckerRegistry::CheckerInfo *Dependency : Deps) {
246
2.21k
247
2.21k
    if (Dependency->isDisabled(LO))
248
4
      return false;
249
2.20k
250
2.20k
    // Collect dependencies recursively.
251
2.20k
    if (!collectDependenciesImpl(Dependency->Dependencies, LO, Ret))
252
0
      return false;
253
2.20k
254
2.20k
    Ret.insert(Dependency);
255
2.20k
  }
256
17.1k
257
17.1k
  
return true17.1k
;
258
17.1k
}
259
260
915
CheckerRegistry::CheckerInfoSet CheckerRegistry::getEnabledCheckers() const {
261
915
262
915
  CheckerInfoSet EnabledCheckers;
263
915
264
150k
  for (const CheckerInfo &Checker : Checkers) {
265
150k
    if (!Checker.isEnabled(LangOpts))
266
135k
      continue;
267
14.9k
268
14.9k
    // Recursively enable its dependencies.
269
14.9k
    llvm::Optional<CheckerInfoSet> Deps =
270
14.9k
        collectDependencies(Checker, LangOpts);
271
14.9k
272
14.9k
    if (!Deps) {
273
4
      // If we failed to enable any of the dependencies, don't enable this
274
4
      // checker.
275
4
      continue;
276
4
    }
277
14.9k
278
14.9k
    // Note that set_union also preserves the order of insertion.
279
14.9k
    EnabledCheckers.set_union(*Deps);
280
14.9k
281
14.9k
    // Enable the checker.
282
14.9k
    EnabledCheckers.insert(&Checker);
283
14.9k
  }
284
915
285
915
  return EnabledCheckers;
286
915
}
287
288
930
void CheckerRegistry::resolveDependencies() {
289
42.7k
  for (const std::pair<StringRef, StringRef> &Entry : Dependencies) {
290
42.7k
    auto CheckerIt = binaryFind(Checkers, Entry.first);
291
42.7k
    assert(CheckerIt != Checkers.end() && CheckerIt->FullName == Entry.first &&
292
42.7k
           "Failed to find the checker while attempting to set up its "
293
42.7k
           "dependencies!");
294
42.7k
295
42.7k
    auto DependencyIt = binaryFind(Checkers, Entry.second);
296
42.7k
    assert(DependencyIt != Checkers.end() &&
297
42.7k
           DependencyIt->FullName == Entry.second &&
298
42.7k
           "Failed to find the dependency of a checker!");
299
42.7k
300
42.7k
    CheckerIt->Dependencies.emplace_back(&*DependencyIt);
301
42.7k
  }
302
930
303
930
  Dependencies.clear();
304
930
}
305
306
42.7k
void CheckerRegistry::addDependency(StringRef FullName, StringRef Dependency) {
307
42.7k
  Dependencies.emplace_back(FullName, Dependency);
308
42.7k
}
309
310
/// Insert the checker/package option to AnalyzerOptions' config table, and
311
/// validate it, if the user supplied it on the command line.
312
static void insertAndValidate(StringRef FullName,
313
                              const CheckerRegistry::CmdLineOption &Option,
314
                              AnalyzerOptions &AnOpts,
315
32.5k
                              DiagnosticsEngine &Diags) {
316
32.5k
317
32.5k
  std::string FullOption = (FullName + ":" + Option.OptionName).str();
318
32.5k
319
32.5k
  auto It = AnOpts.Config.insert({FullOption, Option.DefaultValStr});
320
32.5k
321
32.5k
  // Insertation was successful -- CmdLineOption's constructor will validate
322
32.5k
  // whether values received from plugins or TableGen files are correct.
323
32.5k
  if (It.second)
324
32.2k
    return;
325
352
326
352
  // Insertion failed, the user supplied this package/checker option on the
327
352
  // command line. If the supplied value is invalid, we'll restore the option
328
352
  // to it's default value, and if we're in non-compatibility mode, we'll also
329
352
  // emit an error.
330
352
331
352
  StringRef SuppliedValue = It.first->getValue();
332
352
333
352
  if (Option.OptionType == "bool") {
334
256
    if (SuppliedValue != "true" && 
SuppliedValue != "false"191
) {
335
7
      if (AnOpts.ShouldEmitErrorsOnInvalidConfigValue) {
336
3
        Diags.Report(diag::err_analyzer_checker_option_invalid_input)
337
3
            << FullOption << "a boolean value";
338
3
      }
339
7
340
7
      It.first->setValue(Option.DefaultValStr);
341
7
    }
342
256
    return;
343
256
  }
344
96
345
96
  if (Option.OptionType == "int") {
346
62
    int Tmp;
347
62
    bool HasFailed = SuppliedValue.getAsInteger(0, Tmp);
348
62
    if (HasFailed) {
349
3
      if (AnOpts.ShouldEmitErrorsOnInvalidConfigValue) {
350
1
        Diags.Report(diag::err_analyzer_checker_option_invalid_input)
351
1
            << FullOption << "an integer value";
352
1
      }
353
3
354
3
      It.first->setValue(Option.DefaultValStr);
355
3
    }
356
62
    return;
357
62
  }
358
96
}
359
360
template <class T>
361
static void
362
insertOptionToCollection(StringRef FullName, T &Collection,
363
                         const CheckerRegistry::CmdLineOption &Option,
364
32.5k
                         AnalyzerOptions &AnOpts, DiagnosticsEngine &Diags) {
365
32.5k
  auto It = binaryFind(Collection, FullName);
366
32.5k
  assert(It != Collection.end() &&
367
32.5k
         "Failed to find the checker while attempting to add a command line "
368
32.5k
         "option to it!");
369
32.5k
370
32.5k
  insertAndValidate(FullName, Option, AnOpts, Diags);
371
32.5k
372
32.5k
  It->CmdLineOptions.emplace_back(Option);
373
32.5k
}
CheckerRegistry.cpp:void insertOptionToCollection<std::__1::vector<clang::ento::CheckerRegistry::CheckerInfo, std::__1::allocator<clang::ento::CheckerRegistry::CheckerInfo> > >(llvm::StringRef, std::__1::vector<clang::ento::CheckerRegistry::CheckerInfo, std::__1::allocator<clang::ento::CheckerRegistry::CheckerInfo> >&, clang::ento::CheckerRegistry::CmdLineOption const&, clang::AnalyzerOptions&, clang::DiagnosticsEngine&)
Line
Count
Source
364
31.6k
                         AnalyzerOptions &AnOpts, DiagnosticsEngine &Diags) {
365
31.6k
  auto It = binaryFind(Collection, FullName);
366
31.6k
  assert(It != Collection.end() &&
367
31.6k
         "Failed to find the checker while attempting to add a command line "
368
31.6k
         "option to it!");
369
31.6k
370
31.6k
  insertAndValidate(FullName, Option, AnOpts, Diags);
371
31.6k
372
31.6k
  It->CmdLineOptions.emplace_back(Option);
373
31.6k
}
CheckerRegistry.cpp:void insertOptionToCollection<llvm::SmallVector<clang::ento::CheckerRegistry::PackageInfo, 0u> >(llvm::StringRef, llvm::SmallVector<clang::ento::CheckerRegistry::PackageInfo, 0u>&, clang::ento::CheckerRegistry::CmdLineOption const&, clang::AnalyzerOptions&, clang::DiagnosticsEngine&)
Line
Count
Source
364
930
                         AnalyzerOptions &AnOpts, DiagnosticsEngine &Diags) {
365
930
  auto It = binaryFind(Collection, FullName);
366
930
  assert(It != Collection.end() &&
367
930
         "Failed to find the checker while attempting to add a command line "
368
930
         "option to it!");
369
930
370
930
  insertAndValidate(FullName, Option, AnOpts, Diags);
371
930
372
930
  It->CmdLineOptions.emplace_back(Option);
373
930
}
374
375
930
void CheckerRegistry::resolveCheckerAndPackageOptions() {
376
930
  for (const std::pair<StringRef, CmdLineOption> &CheckerOptEntry :
377
31.6k
       CheckerOptions) {
378
31.6k
    insertOptionToCollection(CheckerOptEntry.first, Checkers,
379
31.6k
                             CheckerOptEntry.second, AnOpts, Diags);
380
31.6k
  }
381
930
  CheckerOptions.clear();
382
930
383
930
  for (const std::pair<StringRef, CmdLineOption> &PackageOptEntry :
384
930
       PackageOptions) {
385
930
    insertOptionToCollection(PackageOptEntry.first, Packages,
386
930
                             PackageOptEntry.second, AnOpts, Diags);
387
930
  }
388
930
  PackageOptions.clear();
389
930
}
390
391
39.0k
void CheckerRegistry::addPackage(StringRef FullName) {
392
39.0k
  Packages.emplace_back(PackageInfo(FullName));
393
39.0k
}
394
395
void CheckerRegistry::addPackageOption(StringRef OptionType,
396
                                       StringRef PackageFullName,
397
                                       StringRef OptionName,
398
                                       StringRef DefaultValStr,
399
                                       StringRef Description,
400
                                       StringRef DevelopmentStatus,
401
930
                                       bool IsHidden) {
402
930
  PackageOptions.emplace_back(
403
930
      PackageFullName, CmdLineOption{OptionType, OptionName, DefaultValStr,
404
930
                                     Description, DevelopmentStatus, IsHidden});
405
930
}
406
407
void CheckerRegistry::addChecker(InitializationFunction Rfn,
408
                                 ShouldRegisterFunction Sfn, StringRef Name,
409
                                 StringRef Desc, StringRef DocsUri,
410
152k
                                 bool IsHidden) {
411
152k
  Checkers.emplace_back(Rfn, Sfn, Name, Desc, DocsUri, IsHidden);
412
152k
413
152k
  // Record the presence of the checker in its packages.
414
152k
  StringRef PackageName, LeafName;
415
152k
  std::tie(PackageName, LeafName) = Name.rsplit(PackageSeparator);
416
416k
  while (!LeafName.empty()) {
417
264k
    PackageSizes[PackageName] += 1;
418
264k
    std::tie(PackageName, LeafName) = PackageName.rsplit(PackageSeparator);
419
264k
  }
420
152k
}
421
422
void CheckerRegistry::addCheckerOption(StringRef OptionType,
423
                                       StringRef CheckerFullName,
424
                                       StringRef OptionName,
425
                                       StringRef DefaultValStr,
426
                                       StringRef Description,
427
                                       StringRef DevelopmentStatus,
428
31.6k
                                       bool IsHidden) {
429
31.6k
  CheckerOptions.emplace_back(
430
31.6k
      CheckerFullName, CmdLineOption{OptionType, OptionName, DefaultValStr,
431
31.6k
                                     Description, DevelopmentStatus, IsHidden});
432
31.6k
}
433
434
910
void CheckerRegistry::initializeManager(CheckerManager &CheckerMgr) const {
435
910
  // Collect checkers enabled by the options.
436
910
  CheckerInfoSet enabledCheckers = getEnabledCheckers();
437
910
438
910
  // Initialize the CheckerManager with all enabled checkers.
439
15.3k
  for (const auto *Checker : enabledCheckers) {
440
15.3k
    CheckerMgr.setCurrentCheckName(CheckName(Checker->FullName));
441
15.3k
    Checker->Initialize(CheckerMgr);
442
15.3k
  }
443
910
}
444
445
static void
446
isOptionContainedIn(const CheckerRegistry::CmdLineOptionList &OptionList,
447
                    StringRef SuppliedChecker, StringRef SuppliedOption,
448
31.8k
                    const AnalyzerOptions &AnOpts, DiagnosticsEngine &Diags) {
449
31.8k
450
31.8k
  if (!AnOpts.ShouldEmitErrorsOnInvalidConfigValue)
451
670
    return;
452
31.1k
453
31.1k
  using CmdLineOption = CheckerRegistry::CmdLineOption;
454
31.1k
455
151k
  auto SameOptName = [SuppliedOption](const CmdLineOption &Opt) {
456
151k
    return Opt.OptionName == SuppliedOption;
457
151k
  };
458
31.1k
459
31.1k
  auto OptionIt = llvm::find_if(OptionList, SameOptName);
460
31.1k
461
31.1k
  if (OptionIt == OptionList.end()) {
462
2
    Diags.Report(diag::err_analyzer_checker_option_unknown)
463
2
        << SuppliedChecker << SuppliedOption;
464
2
    return;
465
2
  }
466
31.1k
}
467
468
910
void CheckerRegistry::validateCheckerOptions() const {
469
80.1k
  for (const auto &Config : AnOpts.Config) {
470
80.1k
471
80.1k
    StringRef SuppliedChecker;
472
80.1k
    StringRef SuppliedOption;
473
80.1k
    std::tie(SuppliedChecker, SuppliedOption) = Config.getKey().split(':');
474
80.1k
475
80.1k
    if (SuppliedOption.empty())
476
48.2k
      continue;
477
31.8k
478
31.8k
    // AnalyzerOptions' config table contains the user input, so an entry could
479
31.8k
    // look like this:
480
31.8k
    //
481
31.8k
    //   cor:NoFalsePositives=true
482
31.8k
    //
483
31.8k
    // Since lower_bound would look for the first element *not less* than "cor",
484
31.8k
    // it would return with an iterator to the first checker in the core, so we
485
31.8k
    // we really have to use find here, which uses operator==.
486
31.8k
    auto CheckerIt = llvm::find(Checkers, CheckerInfo(SuppliedChecker));
487
31.8k
    if (CheckerIt != Checkers.end()) {
488
30.9k
      isOptionContainedIn(CheckerIt->CmdLineOptions, SuppliedChecker,
489
30.9k
                          SuppliedOption, AnOpts, Diags);
490
30.9k
      continue;
491
30.9k
    }
492
918
493
918
    auto PackageIt = llvm::find(Packages, PackageInfo(SuppliedChecker));
494
918
    if (PackageIt != Packages.end()) {
495
910
      isOptionContainedIn(PackageIt->CmdLineOptions, SuppliedChecker,
496
910
                          SuppliedOption, AnOpts, Diags);
497
910
      continue;
498
910
    }
499
8
500
8
    Diags.Report(diag::err_unknown_analyzer_checker) << SuppliedChecker;
501
8
  }
502
910
}
503
504
void CheckerRegistry::printCheckerWithDescList(raw_ostream &Out,
505
7
                                               size_t MaxNameChars) const {
506
7
  // FIXME: Print available packages.
507
7
508
7
  Out << "CHECKERS:\n";
509
7
510
7
  // Find the maximum option length.
511
7
  size_t OptionFieldWidth = 0;
512
1.14k
  for (const auto &Checker : Checkers) {
513
1.14k
    // Limit the amount of padding we are willing to give up for alignment.
514
1.14k
    //   Package.Name     Description  [Hidden]
515
1.14k
    size_t NameLength = Checker.FullName.size();
516
1.14k
    if (NameLength <= MaxNameChars)
517
868
      OptionFieldWidth = std::max(OptionFieldWidth, NameLength);
518
1.14k
  }
519
7
520
7
  const size_t InitialPad = 2;
521
7
522
7
  auto Print = [=](llvm::raw_ostream &Out, const CheckerInfo &Checker,
523
656
                   StringRef Description) {
524
656
    AnalyzerOptions::printFormattedEntry(Out, {Checker.FullName, Description},
525
656
                                         InitialPad, OptionFieldWidth);
526
656
    Out << '\n';
527
656
  };
528
7
529
1.14k
  for (const auto &Checker : Checkers) {
530
1.14k
    // The order of this if branches is significant, we wouldn't like to display
531
1.14k
    // developer checkers even in the alpha output. For example,
532
1.14k
    // alpha.cplusplus.IteratorModeling is a modeling checker, hence it's hidden
533
1.14k
    // by default, and users (even when the user is a developer of an alpha
534
1.14k
    // checker) shouldn't normally tinker with whether they should be enabled.
535
1.14k
536
1.14k
    if (Checker.IsHidden) {
537
266
      if (AnOpts.ShowCheckerHelpDeveloper)
538
152
        Print(Out, Checker, Checker.Desc);
539
266
      continue;
540
266
    }
541
882
542
882
    if (Checker.FullName.startswith("alpha")) {
543
294
      if (AnOpts.ShowCheckerHelpAlpha)
544
168
        Print(Out, Checker,
545
168
              ("(Enable only for development!) " + Checker.Desc).str());
546
294
      continue;
547
294
    }
548
588
549
588
    if (AnOpts.ShowCheckerHelp)
550
336
        Print(Out, Checker, Checker.Desc);
551
588
  }
552
7
}
553
554
5
void CheckerRegistry::printEnabledCheckerList(raw_ostream &Out) const {
555
5
  // Collect checkers enabled by the options.
556
5
  CheckerInfoSet EnabledCheckers = getEnabledCheckers();
557
5
558
5
  for (const auto *i : EnabledCheckers)
559
21
    Out << i->FullName << '\n';
560
5
}
561
562
8
void CheckerRegistry::printCheckerOptionList(raw_ostream &Out) const {
563
8
  Out << "OVERVIEW: Clang Static Analyzer Checker and Package Option List\n\n";
564
8
  Out << "USAGE: -analyzer-config <OPTION1=VALUE,OPTION2=VALUE,...>\n\n";
565
8
  Out << "       -analyzer-config OPTION1=VALUE, -analyzer-config "
566
8
         "OPTION2=VALUE, ...\n\n";
567
8
  Out << "OPTIONS:\n\n";
568
8
569
8
  std::multimap<StringRef, const CmdLineOption &> OptionMap;
570
8
571
1.31k
  for (const CheckerInfo &Checker : Checkers) {
572
1.31k
    for (const CmdLineOption &Option : Checker.CmdLineOptions) {
573
273
      OptionMap.insert({Checker.FullName, Option});
574
273
    }
575
1.31k
  }
576
8
577
336
  for (const PackageInfo &Package : Packages) {
578
336
    for (const CmdLineOption &Option : Package.CmdLineOptions) {
579
8
      OptionMap.insert({Package.FullName, Option});
580
8
    }
581
336
  }
582
8
583
149
  auto Print = [] (llvm::raw_ostream &Out, StringRef FullOption, StringRef Desc) {
584
149
    AnalyzerOptions::printFormattedEntry(Out, {FullOption, Desc},
585
149
                                         /*InitialPad*/ 2,
586
149
                                         /*EntryWidth*/ 50,
587
149
                                         /*MinLineWidth*/ 90);
588
149
    Out << "\n\n";
589
149
  };
590
281
  for (const std::pair<StringRef, const CmdLineOption &> &Entry : OptionMap) {
591
281
    const CmdLineOption &Option = Entry.second;
592
281
    std::string FullOption = (Entry.first + ":" + Option.OptionName).str();
593
281
594
281
    std::string Desc =
595
281
        ("(" + Option.OptionType + ") " + Option.Description + " (default: " +
596
281
         (Option.DefaultValStr.empty() ? 
"\"\""0
: Option.DefaultValStr) + ")")
597
281
            .str();
598
281
599
281
    // The list of these if branches is significant, we wouldn't like to
600
281
    // display hidden alpha checker options for
601
281
    // -analyzer-checker-option-help-alpha.
602
281
603
281
    if (Option.IsHidden) {
604
152
      if (AnOpts.ShowCheckerOptionDeveloperList)
605
76
        Print(Out, FullOption, Desc);
606
152
      continue;
607
152
    }
608
129
609
129
    if (Option.DevelopmentStatus == "alpha" ||
610
129
        
Entry.first.startswith("alpha")105
) {
611
64
      if (AnOpts.ShowCheckerOptionAlphaList)
612
32
        Print(Out, FullOption,
613
32
              llvm::Twine("(Enable only for development!) " + Desc).str());
614
64
      continue;
615
64
    }
616
65
617
65
    if (AnOpts.ShowCheckerOptionList)
618
41
      Print(Out, FullOption, Desc);
619
65
  }
620
8
}