Coverage Report

Created: 2020-09-22 08:39

/Users/buildslave/jenkins/workspace/coverage/llvm-project/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 namespace checker_registry;
29
using llvm::sys::DynamicLibrary;
30
31
//===----------------------------------------------------------------------===//
32
// Utilities.
33
//===----------------------------------------------------------------------===//
34
35
0
static bool isCompatibleAPIVersion(const char *VersionString) {
36
  // If the version string is null, its not an analyzer plugin.
37
0
  if (!VersionString)
38
0
    return false;
39
40
  // For now, none of the static analyzer API is considered stable.
41
  // Versions must match exactly.
42
0
  return strcmp(VersionString, CLANG_ANALYZER_API_VERSION_STRING) == 0;
43
0
}
44
45
static constexpr char PackageSeparator = '.';
46
47
//===----------------------------------------------------------------------===//
48
// Methods of CheckerRegistry.
49
//===----------------------------------------------------------------------===//
50
51
CheckerRegistry::CheckerRegistry(
52
    CheckerRegistryData &Data, ArrayRef<std::string> Plugins,
53
    DiagnosticsEngine &Diags, AnalyzerOptions &AnOpts,
54
    ArrayRef<std::function<void(CheckerRegistry &)>> CheckerRegistrationFns)
55
1.36k
    : Data(Data), Diags(Diags), AnOpts(AnOpts) {
56
57
  // Register builtin checkers.
58
1.36k
#define GET_CHECKERS
59
1.36k
#define CHECKER(FULLNAME, CLASS, HELPTEXT, DOC_URI, IS_HIDDEN)                 \
60
251k
  addChecker(register##CLASS, shouldRegister##CLASS, FULLNAME, HELPTEXT,       \
61
251k
             DOC_URI, IS_HIDDEN);
62
63
1.36k
#define GET_PACKAGES
64
66.9k
#define PACKAGE(FULLNAME) addPackage(FULLNAME);
65
66
1.36k
#include "clang/StaticAnalyzer/Checkers/Checkers.inc"
67
1.36k
#undef CHECKER
68
1.36k
#undef GET_CHECKERS
69
1.36k
#undef PACKAGE
70
1.36k
#undef GET_PACKAGES
71
72
  // Register checkers from plugins.
73
0
  for (const std::string &Plugin : Plugins) {
74
    // Get access to the plugin.
75
0
    std::string ErrorMsg;
76
0
    DynamicLibrary Lib =
77
0
        DynamicLibrary::getPermanentLibrary(Plugin.c_str(), &ErrorMsg);
78
0
    if (!Lib.isValid()) {
79
0
      Diags.Report(diag::err_fe_unable_to_load_plugin) << Plugin << ErrorMsg;
80
0
      continue;
81
0
    }
82
83
    // See if its compatible with this build of clang.
84
0
    const char *PluginAPIVersion = static_cast<const char *>(
85
0
        Lib.getAddressOfSymbol("clang_analyzerAPIVersionString"));
86
87
0
    if (!isCompatibleAPIVersion(PluginAPIVersion)) {
88
0
      Diags.Report(diag::warn_incompatible_analyzer_plugin_api)
89
0
          << llvm::sys::path::filename(Plugin);
90
0
      Diags.Report(diag::note_incompatible_analyzer_plugin_api)
91
0
          << CLANG_ANALYZER_API_VERSION_STRING << PluginAPIVersion;
92
0
      continue;
93
0
    }
94
95
0
    using RegisterPluginCheckerFn = void (*)(CheckerRegistry &);
96
    // Register its checkers.
97
0
    RegisterPluginCheckerFn RegisterPluginCheckers =
98
0
        reinterpret_cast<RegisterPluginCheckerFn>(
99
0
            Lib.getAddressOfSymbol("clang_registerCheckers"));
100
0
    if (RegisterPluginCheckers)
101
0
      RegisterPluginCheckers(*this);
102
0
  }
103
104
  // Register statically linked checkers, that aren't generated from the tblgen
105
  // file, but rather passed their registry function as a parameter in
106
  // checkerRegistrationFns.
107
108
1.36k
  for (const auto &Fn : CheckerRegistrationFns)
109
17
    Fn(*this);
110
111
  // Sort checkers for efficient collection.
112
  // FIXME: Alphabetical sort puts 'experimental' in the middle.
113
  // Would it be better to name it '~experimental' or something else
114
  // that's ASCIIbetically last?
115
1.36k
  llvm::sort(Data.Packages, checker_registry::PackageNameLT{});
116
1.36k
  llvm::sort(Data.Checkers, checker_registry::CheckerNameLT{});
117
118
1.36k
#define GET_CHECKER_DEPENDENCIES
119
120
1.36k
#define CHECKER_DEPENDENCY(FULLNAME, DEPENDENCY)                               \
121
83.3k
  addDependency(FULLNAME, DEPENDENCY);
122
123
1.36k
#define GET_CHECKER_WEAK_DEPENDENCIES
124
125
1.36k
#define CHECKER_WEAK_DEPENDENCY(FULLNAME, DEPENDENCY)                          \
126
4.09k
  addWeakDependency(FULLNAME, DEPENDENCY);
127
128
1.36k
#define GET_CHECKER_OPTIONS
129
1.36k
#define CHECKER_OPTION(TYPE, FULLNAME, CMDFLAG, DESC, DEFAULT_VAL,             \
130
1.36k
                       DEVELOPMENT_STATUS, IS_HIDDEN)                          \
131
77.8k
  addCheckerOption(TYPE, FULLNAME, CMDFLAG, DEFAULT_VAL, DESC,                 \
132
77.8k
                   DEVELOPMENT_STATUS, IS_HIDDEN);
133
134
1.36k
#define GET_PACKAGE_OPTIONS
135
1.36k
#define PACKAGE_OPTION(TYPE, FULLNAME, CMDFLAG, DESC, DEFAULT_VAL,             \
136
1.36k
                       DEVELOPMENT_STATUS, IS_HIDDEN)                          \
137
1.36k
  addPackageOption(TYPE, FULLNAME, CMDFLAG, DEFAULT_VAL, DESC,                 \
138
1.36k
                   DEVELOPMENT_STATUS, IS_HIDDEN);
139
140
1.36k
#include "clang/StaticAnalyzer/Checkers/Checkers.inc"
141
1.36k
#undef CHECKER_DEPENDENCY
142
1.36k
#undef GET_CHECKER_DEPENDENCIES
143
1.36k
#undef CHECKER_WEAK_DEPENDENCY
144
1.36k
#undef GET_CHECKER_WEAK_DEPENDENCIES
145
1.36k
#undef CHECKER_OPTION
146
1.36k
#undef GET_CHECKER_OPTIONS
147
1.36k
#undef PACKAGE_OPTION
148
1.36k
#undef GET_PACKAGE_OPTIONS
149
150
1.36k
  resolveDependencies<true>();
151
1.36k
  resolveDependencies<false>();
152
153
1.36k
#ifndef NDEBUG
154
83.3k
  for (auto &DepPair : Data.Dependencies) {
155
250k
    for (auto &WeakDepPair : Data.WeakDependencies) {
156
      // Some assertions to enforce that strong dependencies are relations in
157
      // between purely modeling checkers, and weak dependencies are about
158
      // diagnostics.
159
250k
      assert(WeakDepPair != DepPair &&
160
250k
             "A checker cannot strong and weak depend on the same checker!");
161
250k
      assert(WeakDepPair.first != DepPair.second &&
162
250k
             "A strong dependency mustn't have weak dependencies!");
163
250k
      assert(WeakDepPair.second != DepPair.second &&
164
250k
             "A strong dependency mustn't be a weak dependency as well!");
165
250k
    }
166
83.3k
  }
167
1.36k
#endif
168
169
1.36k
  resolveCheckerAndPackageOptions();
170
171
  // Parse '-analyzer-checker' and '-analyzer-disable-checker' options from the
172
  // command line.
173
2.77k
  for (const std::pair<std::string, bool> &Opt : AnOpts.CheckersAndPackages) {
174
2.77k
    CheckerInfoListRange CheckerForCmdLineArg =
175
2.77k
        Data.getMutableCheckersForCmdLineArg(Opt.first);
176
177
2.77k
    if (CheckerForCmdLineArg.begin() == CheckerForCmdLineArg.end()) {
178
1
      Diags.Report(diag::err_unknown_analyzer_checker_or_package) << Opt.first;
179
1
      Diags.Report(diag::note_suggest_disabling_all_checkers);
180
1
    }
181
182
24.3k
    for (CheckerInfo &checker : CheckerForCmdLineArg) {
183
24.2k
      checker.State = Opt.second ? StateFromCmdLine::State_Enabled
184
12
                                 : StateFromCmdLine::State_Disabled;
185
24.3k
    }
186
2.77k
  }
187
1.36k
  validateCheckerOptions();
188
1.36k
}
189
190
//===----------------------------------------------------------------------===//
191
// Dependency resolving.
192
//===----------------------------------------------------------------------===//
193
194
template <typename IsEnabledFn>
195
static bool collectStrongDependencies(const ConstCheckerInfoList &Deps,
196
                                      const CheckerManager &Mgr,
197
                                      CheckerInfoSet &Ret,
198
                                      IsEnabledFn IsEnabled);
199
200
/// Collects weak dependencies in \p enabledData.Checkers.
201
template <typename IsEnabledFn>
202
static void collectWeakDependencies(const ConstCheckerInfoList &Deps,
203
                                    const CheckerManager &Mgr,
204
                                    CheckerInfoSet &Ret, IsEnabledFn IsEnabled);
205
206
1.36k
void CheckerRegistry::initializeRegistry(const CheckerManager &Mgr) {
207
  // First, we calculate the list of enabled checkers as specified by the
208
  // invocation. Weak dependencies will not enable their unspecified strong
209
  // depenencies, but its only after resolving strong dependencies for all
210
  // checkers when we know whether they will be enabled.
211
1.36k
  CheckerInfoSet Tmp;
212
8.95k
  auto IsEnabledFromCmdLine = [&](const CheckerInfo *Checker) {
213
8.95k
    return !Checker->isDisabled(Mgr);
214
8.95k
  };
215
251k
  for (const CheckerInfo &Checker : Data.Checkers) {
216
251k
    if (!Checker.isEnabled(Mgr))
217
227k
      continue;
218
219
24.1k
    CheckerInfoSet Deps;
220
24.1k
    if (!collectStrongDependencies(Checker.Dependencies, Mgr, Deps,
221
5
                                   IsEnabledFromCmdLine)) {
222
      // If we failed to enable any of the dependencies, don't enable this
223
      // checker.
224
5
      continue;
225
5
    }
226
227
24.1k
    Tmp.insert(Deps.begin(), Deps.end());
228
229
    // Enable the checker.
230
24.1k
    Tmp.insert(&Checker);
231
24.1k
  }
232
233
  // Calculate enabled checkers with the correct registration order. As this is
234
  // done recursively, its arguably cheaper, but for sure less error prone to
235
  // recalculate from scratch.
236
61
  auto IsEnabled = [&](const CheckerInfo *Checker) {
237
61
    return llvm::is_contained(Tmp, Checker);
238
61
  };
239
251k
  for (const CheckerInfo &Checker : Data.Checkers) {
240
251k
    if (!Checker.isEnabled(Mgr))
241
227k
      continue;
242
243
24.1k
    CheckerInfoSet Deps;
244
245
24.1k
    collectWeakDependencies(Checker.WeakDependencies, Mgr, Deps, IsEnabled);
246
247
24.1k
    if (!collectStrongDependencies(Checker.Dependencies, Mgr, Deps,
248
5
                                   IsEnabledFromCmdLine)) {
249
      // If we failed to enable any of the dependencies, don't enable this
250
      // checker.
251
5
      continue;
252
5
    }
253
254
    // Note that set_union also preserves the order of insertion.
255
24.1k
    Data.EnabledCheckers.set_union(Deps);
256
24.1k
    Data.EnabledCheckers.insert(&Checker);
257
24.1k
  }
258
1.36k
}
259
260
template <typename IsEnabledFn>
261
static bool collectStrongDependencies(const ConstCheckerInfoList &Deps,
262
                                      const CheckerManager &Mgr,
263
                                      CheckerInfoSet &Ret,
264
57.3k
                                      IsEnabledFn IsEnabled) {
265
266
8.96k
  for (const CheckerInfo *Dependency : Deps) {
267
8.96k
    if (!IsEnabled(Dependency))
268
10
      return false;
269
270
    // Collect dependencies recursively.
271
8.95k
    if (!collectStrongDependencies(Dependency->Dependencies, Mgr, Ret,
272
8.95k
                                   IsEnabled))
273
4
      return false;
274
8.95k
    Ret.insert(Dependency);
275
8.95k
  }
276
277
57.2k
  return true;
278
57.3k
}
CheckerRegistry.cpp:bool collectStrongDependencies<clang::ento::CheckerRegistry::initializeRegistry(clang::ento::CheckerManager const&)::$_0>(llvm::SmallVector<clang::ento::CheckerInfo const*, 0u> const&, clang::ento::CheckerManager const&, llvm::SetVector<clang::ento::CheckerInfo const*, std::__1::vector<clang::ento::CheckerInfo const*, std::__1::allocator<clang::ento::CheckerInfo const*> >, llvm::DenseSet<clang::ento::CheckerInfo const*, llvm::DenseMapInfo<clang::ento::CheckerInfo const*> > >&, clang::ento::CheckerRegistry::initializeRegistry(clang::ento::CheckerManager const&)::$_0)
Line
Count
Source
264
57.2k
                                      IsEnabledFn IsEnabled) {
265
266
8.95k
  for (const CheckerInfo *Dependency : Deps) {
267
8.95k
    if (!IsEnabled(Dependency))
268
10
      return false;
269
270
    // Collect dependencies recursively.
271
8.94k
    if (!collectStrongDependencies(Dependency->Dependencies, Mgr, Ret,
272
8.94k
                                   IsEnabled))
273
4
      return false;
274
8.94k
    Ret.insert(Dependency);
275
8.94k
  }
276
277
57.2k
  return true;
278
57.2k
}
CheckerRegistry.cpp:bool collectStrongDependencies<clang::ento::CheckerRegistry::initializeRegistry(clang::ento::CheckerManager const&)::$_1>(llvm::SmallVector<clang::ento::CheckerInfo const*, 0u> const&, clang::ento::CheckerManager const&, llvm::SetVector<clang::ento::CheckerInfo const*, std::__1::vector<clang::ento::CheckerInfo const*, std::__1::allocator<clang::ento::CheckerInfo const*> >, llvm::DenseSet<clang::ento::CheckerInfo const*, llvm::DenseMapInfo<clang::ento::CheckerInfo const*> > >&, clang::ento::CheckerRegistry::initializeRegistry(clang::ento::CheckerManager const&)::$_1)
Line
Count
Source
264
50
                                      IsEnabledFn IsEnabled) {
265
266
13
  for (const CheckerInfo *Dependency : Deps) {
267
13
    if (!IsEnabled(Dependency))
268
0
      return false;
269
270
    // Collect dependencies recursively.
271
13
    if (!collectStrongDependencies(Dependency->Dependencies, Mgr, Ret,
272
13
                                   IsEnabled))
273
0
      return false;
274
13
    Ret.insert(Dependency);
275
13
  }
276
277
50
  return true;
278
50
}
279
280
template <typename IsEnabledFn>
281
static void collectWeakDependencies(const ConstCheckerInfoList &WeakDeps,
282
                                    const CheckerManager &Mgr,
283
                                    CheckerInfoSet &Ret,
284
24.2k
                                    IsEnabledFn IsEnabled) {
285
286
48
  for (const CheckerInfo *Dependency : WeakDeps) {
287
    // Don't enable this checker if strong dependencies are unsatisfied, but
288
    // assume that weak dependencies are transitive.
289
48
    collectWeakDependencies(Dependency->WeakDependencies, Mgr, Ret, IsEnabled);
290
291
48
    if (IsEnabled(Dependency) &&
292
37
        collectStrongDependencies(Dependency->Dependencies, Mgr, Ret,
293
37
                                  IsEnabled))
294
37
      Ret.insert(Dependency);
295
48
  }
296
24.2k
}
297
298
2.73k
template <bool IsWeak> void CheckerRegistry::resolveDependencies() {
299
2.73k
  for (const std::pair<StringRef, StringRef> &Entry :
300
87.4k
       (IsWeak ? 
Data.WeakDependencies1.36k
:
Data.Dependencies1.36k
)) {
301
302
87.4k
    auto CheckerIt = binaryFind(Data.Checkers, Entry.first);
303
87.4k
    assert(CheckerIt != Data.Checkers.end() &&
304
87.4k
           CheckerIt->FullName == Entry.first &&
305
87.4k
           "Failed to find the checker while attempting to set up its "
306
87.4k
           "dependencies!");
307
308
87.4k
    auto DependencyIt = binaryFind(Data.Checkers, Entry.second);
309
87.4k
    assert(DependencyIt != Data.Checkers.end() &&
310
87.4k
           DependencyIt->FullName == Entry.second &&
311
87.4k
           "Failed to find the dependency of a checker!");
312
313
    // We do allow diagnostics from unit test/example dependency checkers.
314
87.4k
    assert((DependencyIt->FullName.startswith("test") ||
315
87.4k
            DependencyIt->FullName.startswith("example") || IsWeak ||
316
87.4k
            DependencyIt->IsHidden) &&
317
87.4k
           "Strong dependencies are modeling checkers, and as such "
318
87.4k
           "non-user facing! Mark them hidden in Checkers.td!");
319
320
87.4k
    if (IsWeak)
321
4.11k
      CheckerIt->WeakDependencies.emplace_back(&*DependencyIt);
322
83.3k
    else
323
83.3k
      CheckerIt->Dependencies.emplace_back(&*DependencyIt);
324
87.4k
  }
325
2.73k
}
void clang::ento::CheckerRegistry::resolveDependencies<true>()
Line
Count
Source
298
1.36k
template <bool IsWeak> void CheckerRegistry::resolveDependencies() {
299
1.36k
  for (const std::pair<StringRef, StringRef> &Entry :
300
4.11k
       (IsWeak ? 
Data.WeakDependencies1.36k
:
Data.Dependencies0
)) {
301
302
4.11k
    auto CheckerIt = binaryFind(Data.Checkers, Entry.first);
303
4.11k
    assert(CheckerIt != Data.Checkers.end() &&
304
4.11k
           CheckerIt->FullName == Entry.first &&
305
4.11k
           "Failed to find the checker while attempting to set up its "
306
4.11k
           "dependencies!");
307
308
4.11k
    auto DependencyIt = binaryFind(Data.Checkers, Entry.second);
309
4.11k
    assert(DependencyIt != Data.Checkers.end() &&
310
4.11k
           DependencyIt->FullName == Entry.second &&
311
4.11k
           "Failed to find the dependency of a checker!");
312
313
    // We do allow diagnostics from unit test/example dependency checkers.
314
4.11k
    assert((DependencyIt->FullName.startswith("test") ||
315
4.11k
            DependencyIt->FullName.startswith("example") || IsWeak ||
316
4.11k
            DependencyIt->IsHidden) &&
317
4.11k
           "Strong dependencies are modeling checkers, and as such "
318
4.11k
           "non-user facing! Mark them hidden in Checkers.td!");
319
320
4.11k
    if (IsWeak)
321
4.11k
      CheckerIt->WeakDependencies.emplace_back(&*DependencyIt);
322
0
    else
323
0
      CheckerIt->Dependencies.emplace_back(&*DependencyIt);
324
4.11k
  }
325
1.36k
}
void clang::ento::CheckerRegistry::resolveDependencies<false>()
Line
Count
Source
298
1.36k
template <bool IsWeak> void CheckerRegistry::resolveDependencies() {
299
1.36k
  for (const std::pair<StringRef, StringRef> &Entry :
300
83.3k
       (IsWeak ? 
Data.WeakDependencies0
:
Data.Dependencies1.36k
)) {
301
302
83.3k
    auto CheckerIt = binaryFind(Data.Checkers, Entry.first);
303
83.3k
    assert(CheckerIt != Data.Checkers.end() &&
304
83.3k
           CheckerIt->FullName == Entry.first &&
305
83.3k
           "Failed to find the checker while attempting to set up its "
306
83.3k
           "dependencies!");
307
308
83.3k
    auto DependencyIt = binaryFind(Data.Checkers, Entry.second);
309
83.3k
    assert(DependencyIt != Data.Checkers.end() &&
310
83.3k
           DependencyIt->FullName == Entry.second &&
311
83.3k
           "Failed to find the dependency of a checker!");
312
313
    // We do allow diagnostics from unit test/example dependency checkers.
314
83.3k
    assert((DependencyIt->FullName.startswith("test") ||
315
83.3k
            DependencyIt->FullName.startswith("example") || IsWeak ||
316
83.3k
            DependencyIt->IsHidden) &&
317
83.3k
           "Strong dependencies are modeling checkers, and as such "
318
83.3k
           "non-user facing! Mark them hidden in Checkers.td!");
319
320
83.3k
    if (IsWeak)
321
0
      CheckerIt->WeakDependencies.emplace_back(&*DependencyIt);
322
83.3k
    else
323
83.3k
      CheckerIt->Dependencies.emplace_back(&*DependencyIt);
324
83.3k
  }
325
1.36k
}
326
327
83.3k
void CheckerRegistry::addDependency(StringRef FullName, StringRef Dependency) {
328
83.3k
  Data.Dependencies.emplace_back(FullName, Dependency);
329
83.3k
}
330
331
void CheckerRegistry::addWeakDependency(StringRef FullName,
332
4.11k
                                        StringRef Dependency) {
333
4.11k
  Data.WeakDependencies.emplace_back(FullName, Dependency);
334
4.11k
}
335
336
//===----------------------------------------------------------------------===//
337
// Checker option resolving and validating.
338
//===----------------------------------------------------------------------===//
339
340
/// Insert the checker/package option to AnalyzerOptions' config table, and
341
/// validate it, if the user supplied it on the command line.
342
static void insertAndValidate(StringRef FullName, const CmdLineOption &Option,
343
                              AnalyzerOptions &AnOpts,
344
79.2k
                              DiagnosticsEngine &Diags) {
345
346
79.2k
  std::string FullOption = (FullName + ":" + Option.OptionName).str();
347
348
79.2k
  auto It =
349
79.2k
      AnOpts.Config.insert({FullOption, std::string(Option.DefaultValStr)});
350
351
  // Insertation was successful -- CmdLineOption's constructor will validate
352
  // whether values received from plugins or TableGen files are correct.
353
79.2k
  if (It.second)
354
78.8k
    return;
355
356
  // Insertion failed, the user supplied this package/checker option on the
357
  // command line. If the supplied value is invalid, we'll restore the option
358
  // to it's default value, and if we're in non-compatibility mode, we'll also
359
  // emit an error.
360
361
331
  StringRef SuppliedValue = It.first->getValue();
362
363
331
  if (Option.OptionType == "bool") {
364
262
    if (SuppliedValue != "true" && 
SuppliedValue != "false"140
) {
365
4
      if (AnOpts.ShouldEmitErrorsOnInvalidConfigValue) {
366
2
        Diags.Report(diag::err_analyzer_checker_option_invalid_input)
367
2
            << FullOption << "a boolean value";
368
2
      }
369
370
4
      It.first->setValue(std::string(Option.DefaultValStr));
371
4
    }
372
262
    return;
373
262
  }
374
375
69
  if (Option.OptionType == "int") {
376
42
    int Tmp;
377
42
    bool HasFailed = SuppliedValue.getAsInteger(0, Tmp);
378
42
    if (HasFailed) {
379
3
      if (AnOpts.ShouldEmitErrorsOnInvalidConfigValue) {
380
1
        Diags.Report(diag::err_analyzer_checker_option_invalid_input)
381
1
            << FullOption << "an integer value";
382
1
      }
383
384
3
      It.first->setValue(std::string(Option.DefaultValStr));
385
3
    }
386
42
    return;
387
42
  }
388
69
}
389
390
template <class T>
391
static void insertOptionToCollection(StringRef FullName, T &Collection,
392
                                     const CmdLineOption &Option,
393
                                     AnalyzerOptions &AnOpts,
394
79.2k
                                     DiagnosticsEngine &Diags) {
395
79.2k
  auto It = binaryFind(Collection, FullName);
396
79.2k
  assert(It != Collection.end() &&
397
79.2k
         "Failed to find the checker while attempting to add a command line "
398
79.2k
         "option to it!");
399
400
79.2k
  insertAndValidate(FullName, Option, AnOpts, Diags);
401
402
79.2k
  It->CmdLineOptions.emplace_back(Option);
403
79.2k
}
CheckerRegistry.cpp:void insertOptionToCollection<std::__1::vector<clang::ento::CheckerInfo, std::__1::allocator<clang::ento::CheckerInfo> > >(llvm::StringRef, std::__1::vector<clang::ento::CheckerInfo, std::__1::allocator<clang::ento::CheckerInfo> >&, clang::ento::CmdLineOption const&, clang::AnalyzerOptions&, clang::DiagnosticsEngine&)
Line
Count
Source
394
77.8k
                                     DiagnosticsEngine &Diags) {
395
77.8k
  auto It = binaryFind(Collection, FullName);
396
77.8k
  assert(It != Collection.end() &&
397
77.8k
         "Failed to find the checker while attempting to add a command line "
398
77.8k
         "option to it!");
399
400
77.8k
  insertAndValidate(FullName, Option, AnOpts, Diags);
401
402
77.8k
  It->CmdLineOptions.emplace_back(Option);
403
77.8k
}
CheckerRegistry.cpp:void insertOptionToCollection<llvm::SmallVector<clang::ento::PackageInfo, 0u> >(llvm::StringRef, llvm::SmallVector<clang::ento::PackageInfo, 0u>&, clang::ento::CmdLineOption const&, clang::AnalyzerOptions&, clang::DiagnosticsEngine&)
Line
Count
Source
394
1.36k
                                     DiagnosticsEngine &Diags) {
395
1.36k
  auto It = binaryFind(Collection, FullName);
396
1.36k
  assert(It != Collection.end() &&
397
1.36k
         "Failed to find the checker while attempting to add a command line "
398
1.36k
         "option to it!");
399
400
1.36k
  insertAndValidate(FullName, Option, AnOpts, Diags);
401
402
1.36k
  It->CmdLineOptions.emplace_back(Option);
403
1.36k
}
404
405
1.36k
void CheckerRegistry::resolveCheckerAndPackageOptions() {
406
1.36k
  for (const std::pair<StringRef, CmdLineOption> &CheckerOptEntry :
407
77.8k
       Data.CheckerOptions) {
408
77.8k
    insertOptionToCollection(CheckerOptEntry.first, Data.Checkers,
409
77.8k
                             CheckerOptEntry.second, AnOpts, Diags);
410
77.8k
  }
411
412
1.36k
  for (const std::pair<StringRef, CmdLineOption> &PackageOptEntry :
413
1.36k
       Data.PackageOptions) {
414
1.36k
    insertOptionToCollection(PackageOptEntry.first, Data.Packages,
415
1.36k
                             PackageOptEntry.second, AnOpts, Diags);
416
1.36k
  }
417
1.36k
}
418
419
66.9k
void CheckerRegistry::addPackage(StringRef FullName) {
420
66.9k
  Data.Packages.emplace_back(PackageInfo(FullName));
421
66.9k
}
422
423
void CheckerRegistry::addPackageOption(StringRef OptionType,
424
                                       StringRef PackageFullName,
425
                                       StringRef OptionName,
426
                                       StringRef DefaultValStr,
427
                                       StringRef Description,
428
                                       StringRef DevelopmentStatus,
429
1.36k
                                       bool IsHidden) {
430
1.36k
  Data.PackageOptions.emplace_back(
431
1.36k
      PackageFullName, CmdLineOption{OptionType, OptionName, DefaultValStr,
432
1.36k
                                     Description, DevelopmentStatus, IsHidden});
433
1.36k
}
434
435
void CheckerRegistry::addChecker(RegisterCheckerFn Rfn,
436
                                 ShouldRegisterFunction Sfn, StringRef Name,
437
                                 StringRef Desc, StringRef DocsUri,
438
251k
                                 bool IsHidden) {
439
251k
  Data.Checkers.emplace_back(Rfn, Sfn, Name, Desc, DocsUri, IsHidden);
440
441
  // Record the presence of the checker in its packages.
442
251k
  StringRef PackageName, LeafName;
443
251k
  std::tie(PackageName, LeafName) = Name.rsplit(PackageSeparator);
444
679k
  while (!LeafName.empty()) {
445
427k
    Data.PackageSizes[PackageName] += 1;
446
427k
    std::tie(PackageName, LeafName) = PackageName.rsplit(PackageSeparator);
447
427k
  }
448
251k
}
449
450
void CheckerRegistry::addCheckerOption(StringRef OptionType,
451
                                       StringRef CheckerFullName,
452
                                       StringRef OptionName,
453
                                       StringRef DefaultValStr,
454
                                       StringRef Description,
455
                                       StringRef DevelopmentStatus,
456
77.8k
                                       bool IsHidden) {
457
77.8k
  Data.CheckerOptions.emplace_back(
458
77.8k
      CheckerFullName, CmdLineOption{OptionType, OptionName, DefaultValStr,
459
77.8k
                                     Description, DevelopmentStatus, IsHidden});
460
77.8k
}
461
462
1.34k
void CheckerRegistry::initializeManager(CheckerManager &CheckerMgr) const {
463
  // Initialize the CheckerManager with all enabled checkers.
464
24.6k
  for (const auto *Checker : Data.EnabledCheckers) {
465
24.6k
    CheckerMgr.setCurrentCheckerName(CheckerNameRef(Checker->FullName));
466
24.6k
    Checker->Initialize(CheckerMgr);
467
24.6k
  }
468
1.34k
}
469
470
static void isOptionContainedIn(const CmdLineOptionList &OptionList,
471
                                StringRef SuppliedChecker,
472
                                StringRef SuppliedOption,
473
                                const AnalyzerOptions &AnOpts,
474
79.2k
                                DiagnosticsEngine &Diags) {
475
476
79.2k
  if (!AnOpts.ShouldEmitErrorsOnInvalidConfigValue)
477
1.16k
    return;
478
479
479k
  
auto SameOptName = [SuppliedOption](const CmdLineOption &Opt) 78.0k
{
480
479k
    return Opt.OptionName == SuppliedOption;
481
479k
  };
482
483
78.0k
  const auto *OptionIt = llvm::find_if(OptionList, SameOptName);
484
485
78.0k
  if (OptionIt == OptionList.end()) {
486
1
    Diags.Report(diag::err_analyzer_checker_option_unknown)
487
1
        << SuppliedChecker << SuppliedOption;
488
1
    return;
489
1
  }
490
78.0k
}
491
492
1.36k
void CheckerRegistry::validateCheckerOptions() const {
493
159k
  for (const auto &Config : AnOpts.Config) {
494
495
159k
    StringRef SuppliedCheckerOrPackage;
496
159k
    StringRef SuppliedOption;
497
159k
    std::tie(SuppliedCheckerOrPackage, SuppliedOption) =
498
159k
        Config.getKey().split(':');
499
500
159k
    if (SuppliedOption.empty())
501
80.5k
      continue;
502
503
    // AnalyzerOptions' config table contains the user input, so an entry could
504
    // look like this:
505
    //
506
    //   cor:NoFalsePositives=true
507
    //
508
    // Since lower_bound would look for the first element *not less* than "cor",
509
    // it would return with an iterator to the first checker in the core, so we
510
    // we really have to use find here, which uses operator==.
511
79.2k
    auto CheckerIt =
512
79.2k
        llvm::find(Data.Checkers, CheckerInfo(SuppliedCheckerOrPackage));
513
79.2k
    if (CheckerIt != Data.Checkers.end()) {
514
77.8k
      isOptionContainedIn(CheckerIt->CmdLineOptions, SuppliedCheckerOrPackage,
515
77.8k
                          SuppliedOption, AnOpts, Diags);
516
77.8k
      continue;
517
77.8k
    }
518
519
1.37k
    const auto *PackageIt =
520
1.37k
        llvm::find(Data.Packages, PackageInfo(SuppliedCheckerOrPackage));
521
1.37k
    if (PackageIt != Data.Packages.end()) {
522
1.36k
      isOptionContainedIn(PackageIt->CmdLineOptions, SuppliedCheckerOrPackage,
523
1.36k
                          SuppliedOption, AnOpts, Diags);
524
1.36k
      continue;
525
1.36k
    }
526
527
8
    Diags.Report(diag::err_unknown_analyzer_checker_or_package)
528
8
        << SuppliedCheckerOrPackage;
529
8
  }
530
1.36k
}
531