17#include "llvm/ADT/STLExtras.h" 
   18#include "llvm/ADT/StringMap.h" 
   19#include "llvm/ADT/StringRef.h" 
   20#include "llvm/Support/DynamicLibrary.h" 
   21#include "llvm/Support/Path.h" 
   26using llvm::sys::DynamicLibrary;
 
   52    : Data(Data), Diags(Diags), AnOpts(AnOpts) {
 
   56#define CHECKER(FULLNAME, CLASS, HELPTEXT, DOC_URI, IS_HIDDEN)                 \ 
   57  addChecker(register##CLASS, shouldRegister##CLASS, FULLNAME, HELPTEXT,       \ 
   61#define PACKAGE(FULLNAME) addPackage(FULLNAME); 
   63#include "clang/StaticAnalyzer/Checkers/Checkers.inc" 
   70  for (
const std::string &Plugin : Plugins) {
 
   74        DynamicLibrary::getPermanentLibrary(Plugin.c_str(), &ErrorMsg);
 
   76      Diags.Report(diag::err_fe_unable_to_load_plugin) << Plugin << ErrorMsg;
 
   81    const char *PluginAPIVersion = 
static_cast<const char *
>(
 
   82        Lib.getAddressOfSymbol(
"clang_analyzerAPIVersionString"));
 
   85      Diags.Report(diag::warn_incompatible_analyzer_plugin_api)
 
   86          << llvm::sys::path::filename(Plugin);
 
   87      Diags.Report(diag::note_incompatible_analyzer_plugin_api)
 
   94    RegisterPluginCheckerFn RegisterPluginCheckers =
 
   95        reinterpret_cast<RegisterPluginCheckerFn
>(
 
   96            Lib.getAddressOfSymbol(
"clang_registerCheckers"));
 
   97    if (RegisterPluginCheckers)
 
   98      RegisterPluginCheckers(*
this);
 
  105  for (
const auto &Fn : CheckerRegistrationFns)
 
  115#define GET_CHECKER_DEPENDENCIES 
  117#define CHECKER_DEPENDENCY(FULLNAME, DEPENDENCY)                               \ 
  118  addDependency(FULLNAME, DEPENDENCY); 
  120#define GET_CHECKER_WEAK_DEPENDENCIES 
  122#define CHECKER_WEAK_DEPENDENCY(FULLNAME, DEPENDENCY)                          \ 
  123  addWeakDependency(FULLNAME, DEPENDENCY); 
  125#define GET_CHECKER_OPTIONS 
  126#define CHECKER_OPTION(TYPE, FULLNAME, CMDFLAG, DESC, DEFAULT_VAL,             \ 
  127                       DEVELOPMENT_STATUS, IS_HIDDEN)                          \ 
  128  addCheckerOption(TYPE, FULLNAME, CMDFLAG, DEFAULT_VAL, DESC,                 \ 
  129                   DEVELOPMENT_STATUS, IS_HIDDEN); 
  131#define GET_PACKAGE_OPTIONS 
  132#define PACKAGE_OPTION(TYPE, FULLNAME, CMDFLAG, DESC, DEFAULT_VAL,             \ 
  133                       DEVELOPMENT_STATUS, IS_HIDDEN)                          \ 
  134  addPackageOption(TYPE, FULLNAME, CMDFLAG, DEFAULT_VAL, DESC,                 \ 
  135                   DEVELOPMENT_STATUS, IS_HIDDEN); 
  137#include "clang/StaticAnalyzer/Checkers/Checkers.inc" 
  138#undef CHECKER_DEPENDENCY 
  139#undef GET_CHECKER_DEPENDENCIES 
  140#undef CHECKER_WEAK_DEPENDENCY 
  141#undef GET_CHECKER_WEAK_DEPENDENCIES 
  143#undef GET_CHECKER_OPTIONS 
  145#undef GET_PACKAGE_OPTIONS 
  147  resolveDependencies<true>();
 
  148  resolveDependencies<false>();
 
  151  for (
auto &DepPair : Data.Dependencies) {
 
  152    for (
auto &WeakDepPair : Data.WeakDependencies) {
 
  156      assert(WeakDepPair != DepPair &&
 
  157             "A checker cannot strong and weak depend on the same checker!");
 
  158      assert(WeakDepPair.first != DepPair.second &&
 
  159             "A strong dependency mustn't have weak dependencies!");
 
  160      assert(WeakDepPair.second != DepPair.second &&
 
  161             "A strong dependency mustn't be a weak dependency as well!");
 
  166  resolveCheckerAndPackageOptions();
 
  170  for (
const std::pair<std::string, bool> &Opt : AnOpts.CheckersAndPackages) {
 
  172        Data.getMutableCheckersForCmdLineArg(Opt.first);
 
  174    if (CheckerForCmdLineArg.begin() == CheckerForCmdLineArg.end()) {
 
  175      Diags.Report(diag::err_unknown_analyzer_checker_or_package) << Opt.first;
 
  176      Diags.Report(diag::note_suggest_disabling_all_checkers);
 
  179    for (
CheckerInfo &checker : CheckerForCmdLineArg) {
 
  180      checker.State = Opt.second ? StateFromCmdLine::State_Enabled
 
  181                                 : StateFromCmdLine::State_Disabled;
 
 
  191template <
typename IsEnabledFn>
 
  195                                      IsEnabledFn IsEnabled);
 
  198template <
typename IsEnabledFn>
 
  210    return !
Checker->isDisabled(Mgr);
 
  218                                   IsEnabledFromCmdLine)) {
 
  224    Tmp.insert_range(Deps);
 
  245                                   IsEnabledFromCmdLine)) {
 
  252    Data.EnabledCheckers.set_union(Deps);
 
  253    Data.EnabledCheckers.insert(&
Checker);
 
 
  257template <
typename IsEnabledFn>
 
  261                                      IsEnabledFn IsEnabled) {
 
  264    if (!IsEnabled(Dependency))
 
  271    Ret.insert(Dependency);
 
 
  277template <
typename IsEnabledFn>
 
  281                                    IsEnabledFn IsEnabled) {
 
  288    if (IsEnabled(Dependency) &&
 
  291      Ret.insert(Dependency);
 
 
  295template <
bool IsWeak> 
void CheckerRegistry::resolveDependencies() {
 
  296  for (
const std::pair<StringRef, StringRef> &Entry :
 
  297       (IsWeak ? Data.WeakDependencies : Data.Dependencies)) {
 
  299    auto CheckerIt = 
binaryFind(Data.Checkers, Entry.first);
 
  300    assert(CheckerIt != Data.Checkers.end() &&
 
  301           CheckerIt->FullName == Entry.first &&
 
  302           "Failed to find the checker while attempting to set up its " 
  305    auto DependencyIt = 
binaryFind(Data.Checkers, Entry.second);
 
  306    assert(DependencyIt != Data.Checkers.end() &&
 
  307           DependencyIt->FullName == Entry.second &&
 
  308           "Failed to find the dependency of a checker!");
 
  311    assert((DependencyIt->FullName.starts_with(
"test") ||
 
  312            DependencyIt->FullName.starts_with(
"example") || IsWeak ||
 
  313            DependencyIt->IsHidden) &&
 
  314           "Strong dependencies are modeling checkers, and as such " 
  315           "non-user facing! Mark them hidden in Checkers.td!");
 
  318      CheckerIt->WeakDependencies.emplace_back(&*DependencyIt);
 
  320      CheckerIt->Dependencies.emplace_back(&*DependencyIt);
 
  325  Data.Dependencies.emplace_back(FullName, Dependency);
 
 
  329                                        StringRef Dependency) {
 
  330  Data.WeakDependencies.emplace_back(FullName, Dependency);
 
 
  343  std::string FullOption = (FullName + 
":" + Option.
OptionName).str();
 
  358  StringRef SuppliedValue = It.first->getValue();
 
  361    if (SuppliedValue != 
"true" && SuppliedValue != 
"false") {
 
  363        Diags.
Report(diag::err_analyzer_checker_option_invalid_input)
 
  364            << FullOption << 
"a boolean value";
 
  374    bool HasFailed = SuppliedValue.getAsInteger(0, Tmp);
 
  377        Diags.
Report(diag::err_analyzer_checker_option_invalid_input)
 
  378            << FullOption << 
"an integer value";
 
 
  393  assert(It != Collection.end() &&
 
  394         "Failed to find the checker while attempting to add a command line " 
  399  It->CmdLineOptions.emplace_back(Option);
 
 
  402void CheckerRegistry::resolveCheckerAndPackageOptions() {
 
  403  for (
const std::pair<StringRef, CmdLineOption> &CheckerOptEntry :
 
  404       Data.CheckerOptions) {
 
  406                             CheckerOptEntry.second, AnOpts, Diags);
 
  409  for (
const std::pair<StringRef, CmdLineOption> &PackageOptEntry :
 
  410       Data.PackageOptions) {
 
  412                             PackageOptEntry.second, AnOpts, Diags);
 
  421                                       StringRef PackageFullName,
 
  422                                       StringRef OptionName,
 
  423                                       StringRef DefaultValStr,
 
  424                                       StringRef Description,
 
  425                                       StringRef DevelopmentStatus,
 
  427  Data.PackageOptions.emplace_back(
 
  428      PackageFullName, 
CmdLineOption{OptionType, OptionName, DefaultValStr,
 
  429                                     Description, DevelopmentStatus, IsHidden});
 
 
  434                                 StringRef Desc, StringRef DocsUri,
 
  436  Data.Checkers.emplace_back(Rfn, Sfn, Name, Desc, DocsUri, IsHidden);
 
  439  StringRef PackageName, LeafName;
 
  441  while (!LeafName.empty()) {
 
  442    Data.PackageSizes[PackageName] += 1;
 
 
  448                                       StringRef CheckerFullName,
 
  449                                       StringRef OptionName,
 
  450                                       StringRef DefaultValStr,
 
  451                                       StringRef Description,
 
  452                                       StringRef DevelopmentStatus,
 
  454  Data.CheckerOptions.emplace_back(
 
  455      CheckerFullName, 
CmdLineOption{OptionType, OptionName, DefaultValStr,
 
  456                                     Description, DevelopmentStatus, IsHidden});
 
 
  461  for (
const auto *
Checker : Data.EnabledCheckers) {
 
  463    Checker->Initialize(CheckerMgr);
 
 
  468                                StringRef SuppliedChecker,
 
  469                                StringRef SuppliedOption,
 
  476  auto SameOptName = [SuppliedOption](
const CmdLineOption &Opt) {
 
  477    return Opt.OptionName == SuppliedOption;
 
  480  if (llvm::none_of(OptionList, SameOptName)) {
 
  481    Diags.
Report(diag::err_analyzer_checker_option_unknown)
 
  482        << SuppliedChecker << SuppliedOption;
 
 
  488  for (
const auto &Config : AnOpts.Config) {
 
  490    StringRef SuppliedCheckerOrPackage;
 
  491    StringRef SuppliedOption;
 
  492    std::tie(SuppliedCheckerOrPackage, SuppliedOption) =
 
  493        Config.getKey().split(
':');
 
  495    if (SuppliedOption.empty())
 
  507        llvm::find(Data.Checkers, 
CheckerInfo(SuppliedCheckerOrPackage));
 
  508    if (CheckerIt != Data.Checkers.end()) {
 
  510                          SuppliedOption, AnOpts, Diags);
 
  514    const auto *PackageIt =
 
  515        llvm::find(Data.Packages, 
PackageInfo(SuppliedCheckerOrPackage));
 
  516    if (PackageIt != Data.Packages.end()) {
 
  518                          SuppliedOption, AnOpts, Diags);
 
  522    Diags.Report(diag::err_unknown_analyzer_checker_or_package)
 
  523        << SuppliedCheckerOrPackage;
 
 
Defines the Diagnostic-related interfaces.
static constexpr char PackageSeparator
static bool isCompatibleAPIVersion(const char *VersionString)
static void collectWeakDependencies(const ConstCheckerInfoList &Deps, const CheckerManager &Mgr, CheckerInfoSet &Ret, IsEnabledFn IsEnabled)
Collects weak dependencies in enabledData.Checkers.
static void insertAndValidate(StringRef FullName, const CmdLineOption &Option, AnalyzerOptions &AnOpts, DiagnosticsEngine &Diags)
Insert the checker/package option to AnalyzerOptions' config table, and validate it,...
static void isOptionContainedIn(const CmdLineOptionList &OptionList, StringRef SuppliedChecker, StringRef SuppliedOption, const AnalyzerOptions &AnOpts, DiagnosticsEngine &Diags)
static bool collectStrongDependencies(const ConstCheckerInfoList &Deps, const CheckerManager &Mgr, CheckerInfoSet &Ret, IsEnabledFn IsEnabled)
static void insertOptionToCollection(StringRef FullName, T &Collection, const CmdLineOption &Option, AnalyzerOptions &AnOpts, DiagnosticsEngine &Diags)
#define CLANG_ANALYZER_API_VERSION_STRING
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified.
Stores options for the analyzer from the command line.
ConfigTable Config
A key-value table of use-specified configuration values.
unsigned ShouldEmitErrorsOnInvalidConfigValue
Concrete class used by the front-end to report problems and issues.
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
void setCurrentCheckerName(CheckerNameRef name)
This wrapper is used to ensure that only StringRefs originating from the CheckerRegistry are used as ...
void addCheckerOption(StringRef OptionType, StringRef CheckerFullName, StringRef OptionName, StringRef DefaultValStr, StringRef Description, StringRef DevelopmentStatus, bool IsHidden=false)
Registers an option to a given checker.
void addWeakDependency(StringRef FullName, StringRef Dependency)
Makes the checker with the full name fullName weak depend on the checker called dependency.
void addPackageOption(StringRef OptionType, StringRef PackageFullName, StringRef OptionName, StringRef DefaultValStr, StringRef Description, StringRef DevelopmentStatus, bool IsHidden=false)
Registers an option to a given package.
void initializeRegistry(const CheckerManager &Mgr)
Collects all enabled checkers in the field EnabledCheckers.
void addChecker(RegisterCheckerFn Fn, ShouldRegisterFunction Sfn, StringRef FullName, StringRef Desc, StringRef DocsUri="NoDocsUri", bool IsHidden=false)
Adds a checker to the registry.
void addPackage(StringRef FullName)
Adds a package to the registry.
void validateCheckerOptions() const
Check if every option corresponds to a specific checker or package.
void addDependency(StringRef FullName, StringRef Dependency)
Makes the checker with the full name fullName depend on the checker called dependency.
CheckerRegistry(CheckerRegistryData &Data, ArrayRef< std::string > Plugins, DiagnosticsEngine &Diags, AnalyzerOptions &AnOpts, ArrayRef< std::function< void(CheckerRegistry &)> > CheckerRegistrationFns={})
Simple checker classes that implement one frontend (i.e.
FullNameLT< CheckerInfo > CheckerNameLT
std::conditional_t< std::is_const< CheckerOrPackageInfoList >::value, typename CheckerOrPackageInfoList::const_iterator, typename CheckerOrPackageInfoList::iterator > binaryFind(CheckerOrPackageInfoList &Collection, StringRef FullName)
FullNameLT< PackageInfo > PackageNameLT
void(*)(CheckerManager &) RegisterCheckerFn
Initialization functions perform any necessary setup for a checker.
llvm::iterator_range< CheckerInfoList::iterator > CheckerInfoListRange
llvm::SetVector< const CheckerInfo * > CheckerInfoSet
llvm::SmallVector< CmdLineOption, 0 > CmdLineOptionList
llvm::SmallVector< const CheckerInfo *, 0 > ConstCheckerInfoList
bool(*)(const CheckerManager &) ShouldRegisterFunction
The JSON file list parser is used to communicate input to InstallAPI.
const FunctionProtoType * T
int const char * function
Specifies a command line option.