//===- CheckerRegistry.cpp - Maintains all available checkers -------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "clang/StaticAnalyzer/Frontend/CheckerRegistry.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/LLVM.h"
#include "clang/Driver/DriverDiagnostic.h"
#include "clang/Frontend/FrontendDiagnostic.h"
#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
#include "clang/StaticAnalyzer/Core/AnalyzerOptions.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/DynamicLibrary.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>

using namespace clang;
using namespace ento;
using namespace checker_registry;
using llvm::sys::DynamicLibrary;

//===----------------------------------------------------------------------===//
// Utilities.
//===----------------------------------------------------------------------===//

static bool isCompatibleAPIVersion(const char *VersionString) {
  // If the version string is null, its not an analyzer plugin.
  if (!VersionString)
    return false;

  // For now, none of the static analyzer API is considered stable.
  // Versions must match exactly.
  return strcmp(VersionString, CLANG_ANALYZER_API_VERSION_STRING) == 0;
}

static constexpr char PackageSeparator = '.';

//===----------------------------------------------------------------------===//
// Methods of CheckerRegistry.
//===----------------------------------------------------------------------===//

CheckerRegistry::CheckerRegistry(
    CheckerRegistryData &Data, ArrayRef<std::string> Plugins,
    DiagnosticsEngine &Diags, AnalyzerOptions &AnOpts,
    ArrayRef<std::function<void(CheckerRegistry &)>> CheckerRegistrationFns)
    : Data(Data), Diags(Diags), AnOpts(AnOpts) {

  // Register builtin checkers.
#define GET_CHECKERS
#define CHECKER(FULLNAME, CLASS, HELPTEXT, DOC_URI, IS_HIDDEN)                 \
  addChecker(register##CLASS, shouldRegister##CLASS, FULLNAME, HELPTEXT,       \
             DOC_URI, IS_HIDDEN);

#define GET_PACKAGES
#define PACKAGE(FULLNAME) addPackage(FULLNAME);

#include "clang/StaticAnalyzer/Checkers/Checkers.inc"
#undef CHECKER
#undef GET_CHECKERS
#undef PACKAGE
#undef GET_PACKAGES

  // Register checkers from plugins.
  for (const std::string &Plugin : Plugins) {
    // Get access to the plugin.
    std::string ErrorMsg;
    DynamicLibrary Lib =
        DynamicLibrary::getPermanentLibrary(Plugin.c_str(), &ErrorMsg);
    if (!Lib.isValid()) {
      Diags.Report(diag::err_fe_unable_to_load_plugin) << Plugin << ErrorMsg;
      continue;
    }

    // See if its compatible with this build of clang.
    const char *PluginAPIVersion = static_cast<const char *>(
        Lib.getAddressOfSymbol("clang_analyzerAPIVersionString"));

    if (!isCompatibleAPIVersion(PluginAPIVersion)) {
      Diags.Report(diag::warn_incompatible_analyzer_plugin_api)
          << llvm::sys::path::filename(Plugin);
      Diags.Report(diag::note_incompatible_analyzer_plugin_api)
          << CLANG_ANALYZER_API_VERSION_STRING << PluginAPIVersion;
      continue;
    }

    using RegisterPluginCheckerFn = void (*)(CheckerRegistry &);
    // Register its checkers.
    RegisterPluginCheckerFn RegisterPluginCheckers =
        reinterpret_cast<RegisterPluginCheckerFn>(
            Lib.getAddressOfSymbol("clang_registerCheckers"));
    if (RegisterPluginCheckers)
      RegisterPluginCheckers(*this);
  }

  // Register statically linked checkers, that aren't generated from the tblgen
  // file, but rather passed their registry function as a parameter in
  // checkerRegistrationFns.

  for (const auto &Fn : CheckerRegistrationFns)
    Fn(*this);

  // Sort checkers for efficient collection.
  // FIXME: Alphabetical sort puts 'experimental' in the middle.
  // Would it be better to name it '~experimental' or something else
  // that's ASCIIbetically last?
  llvm::sort(Data.Packages, checker_registry::PackageNameLT{});
  llvm::sort(Data.Checkers, checker_registry::CheckerNameLT{});

#define GET_CHECKER_DEPENDENCIES

#define CHECKER_DEPENDENCY(FULLNAME, DEPENDENCY)                               \
  addDependency(FULLNAME, DEPENDENCY);

#define GET_CHECKER_WEAK_DEPENDENCIES

#define CHECKER_WEAK_DEPENDENCY(FULLNAME, DEPENDENCY)                          \
  addWeakDependency(FULLNAME, DEPENDENCY);

#define GET_CHECKER_OPTIONS
#define CHECKER_OPTION(TYPE, FULLNAME, CMDFLAG, DESC, DEFAULT_VAL,             \
                       DEVELOPMENT_STATUS, IS_HIDDEN)                          \
  addCheckerOption(TYPE, FULLNAME, CMDFLAG, DEFAULT_VAL, DESC,                 \
                   DEVELOPMENT_STATUS, IS_HIDDEN);

#define GET_PACKAGE_OPTIONS
#define PACKAGE_OPTION(TYPE, FULLNAME, CMDFLAG, DESC, DEFAULT_VAL,             \
                       DEVELOPMENT_STATUS, IS_HIDDEN)                          \
  addPackageOption(TYPE, FULLNAME, CMDFLAG, DEFAULT_VAL, DESC,                 \
                   DEVELOPMENT_STATUS, IS_HIDDEN);

#include "clang/StaticAnalyzer/Checkers/Checkers.inc"
#undef CHECKER_DEPENDENCY
#undef GET_CHECKER_DEPENDENCIES
#undef CHECKER_WEAK_DEPENDENCY
#undef GET_CHECKER_WEAK_DEPENDENCIES
#undef CHECKER_OPTION
#undef GET_CHECKER_OPTIONS
#undef PACKAGE_OPTION
#undef GET_PACKAGE_OPTIONS

  resolveDependencies<true>();
  resolveDependencies<false>();

#ifndef NDEBUG
  for (auto &DepPair : Data.Dependencies) {
    for (auto &WeakDepPair : Data.WeakDependencies) {
      // Some assertions to enforce that strong dependencies are relations in
      // between purely modeling checkers, and weak dependencies are about
      // diagnostics.
      assert(WeakDepPair != DepPair &&
             "A checker cannot strong and weak depend on the same checker!");
      assert(WeakDepPair.first != DepPair.second &&
             "A strong dependency mustn't have weak dependencies!");
      assert(WeakDepPair.second != DepPair.second &&
             "A strong dependency mustn't be a weak dependency as well!");
    }
  }
#endif

  resolveCheckerAndPackageOptions();

  // Parse '-analyzer-checker' and '-analyzer-disable-checker' options from the
  // command line.
  for (const std::pair<std::string, bool> &Opt : AnOpts.CheckersAndPackages) {
    CheckerInfoListRange CheckerForCmdLineArg =
        Data.getMutableCheckersForCmdLineArg(Opt.first);

    if (CheckerForCmdLineArg.begin() == CheckerForCmdLineArg.end()) {
      Diags.Report(diag::err_unknown_analyzer_checker_or_package) << Opt.first;
      Diags.Report(diag::note_suggest_disabling_all_checkers);
    }

    for (CheckerInfo &checker : CheckerForCmdLineArg) {
      checker.State = Opt.second ? StateFromCmdLine::State_Enabled
                                 : StateFromCmdLine::State_Disabled;
    }
  }
  validateCheckerOptions();
}

//===----------------------------------------------------------------------===//
// Dependency resolving.
//===----------------------------------------------------------------------===//

template <typename IsEnabledFn>
static bool collectStrongDependencies(const ConstCheckerInfoList &Deps,
                                      const CheckerManager &Mgr,
                                      CheckerInfoSet &Ret,
                                      IsEnabledFn IsEnabled);

/// Collects weak dependencies in \p enabledData.Checkers.
template <typename IsEnabledFn>
static void collectWeakDependencies(const ConstCheckerInfoList &Deps,
                                    const CheckerManager &Mgr,
                                    CheckerInfoSet &Ret, IsEnabledFn IsEnabled);

void CheckerRegistry::initializeRegistry(const CheckerManager &Mgr) {
  // First, we calculate the list of enabled checkers as specified by the
  // invocation. Weak dependencies will not enable their unspecified strong
  // depenencies, but its only after resolving strong dependencies for all
  // checkers when we know whether they will be enabled.
  CheckerInfoSet Tmp;
  auto IsEnabledFromCmdLine = [&](const CheckerInfo *Checker) {
    return !Checker->isDisabled(Mgr);
  };
  for (const CheckerInfo &Checker : Data.Checkers) {
    if (!Checker.isEnabled(Mgr))
      continue;

    CheckerInfoSet Deps;
    if (!collectStrongDependencies(Checker.Dependencies, Mgr, Deps,
                                   IsEnabledFromCmdLine)) {
      // If we failed to enable any of the dependencies, don't enable this
      // checker.
      continue;
    }

    Tmp.insert(Deps.begin(), Deps.end());

    // Enable the checker.
    Tmp.insert(&Checker);
  }

  // Calculate enabled checkers with the correct registration order. As this is
  // done recursively, its arguably cheaper, but for sure less error prone to
  // recalculate from scratch.
  auto IsEnabled = [&](const CheckerInfo *Checker) {
    return llvm::is_contained(Tmp, Checker);
  };
  for (const CheckerInfo &Checker : Data.Checkers) {
    if (!Checker.isEnabled(Mgr))
      continue;

    CheckerInfoSet Deps;

    collectWeakDependencies(Checker.WeakDependencies, Mgr, Deps, IsEnabled);

    if (!collectStrongDependencies(Checker.Dependencies, Mgr, Deps,
                                   IsEnabledFromCmdLine)) {
      // If we failed to enable any of the dependencies, don't enable this
      // checker.
      continue;
    }

    // Note that set_union also preserves the order of insertion.
    Data.EnabledCheckers.set_union(Deps);
    Data.EnabledCheckers.insert(&Checker);
  }
}

template <typename IsEnabledFn>
static bool collectStrongDependencies(const ConstCheckerInfoList &Deps,
                                      const CheckerManager &Mgr,
                                      CheckerInfoSet &Ret,
                                      IsEnabledFn IsEnabled) {

  for (const CheckerInfo *Dependency : Deps) {
    if (!IsEnabled(Dependency))
      return false;

    // Collect dependencies recursively.
    if (!collectStrongDependencies(Dependency->Dependencies, Mgr, Ret,
                                   IsEnabled))
      return false;
    Ret.insert(Dependency);
  }

  return true;
}

template <typename IsEnabledFn>
static void collectWeakDependencies(const ConstCheckerInfoList &WeakDeps,
                                    const CheckerManager &Mgr,
                                    CheckerInfoSet &Ret,
                                    IsEnabledFn IsEnabled) {

  for (const CheckerInfo *Dependency : WeakDeps) {
    // Don't enable this checker if strong dependencies are unsatisfied, but
    // assume that weak dependencies are transitive.
    collectWeakDependencies(Dependency->WeakDependencies, Mgr, Ret, IsEnabled);

    if (IsEnabled(Dependency) &&
        collectStrongDependencies(Dependency->Dependencies, Mgr, Ret,
                                  IsEnabled))
      Ret.insert(Dependency);
  }
}

template <bool IsWeak> void CheckerRegistry::resolveDependencies() {
  for (const std::pair<StringRef, StringRef> &Entry :
       (IsWeak ? Data.WeakDependencies : Data.Dependencies)) {

    auto CheckerIt = binaryFind(Data.Checkers, Entry.first);
    assert(CheckerIt != Data.Checkers.end() &&
           CheckerIt->FullName == Entry.first &&
           "Failed to find the checker while attempting to set up its "
           "dependencies!");

    auto DependencyIt = binaryFind(Data.Checkers, Entry.second);
    assert(DependencyIt != Data.Checkers.end() &&
           DependencyIt->FullName == Entry.second &&
           "Failed to find the dependency of a checker!");

    // We do allow diagnostics from unit test/example dependency checkers.
    assert((DependencyIt->FullName.startswith("test") ||
            DependencyIt->FullName.startswith("example") || IsWeak ||
            DependencyIt->IsHidden) &&
           "Strong dependencies are modeling checkers, and as such "
           "non-user facing! Mark them hidden in Checkers.td!");

    if (IsWeak)
      CheckerIt->WeakDependencies.emplace_back(&*DependencyIt);
    else
      CheckerIt->Dependencies.emplace_back(&*DependencyIt);
  }
}

void CheckerRegistry::addDependency(StringRef FullName, StringRef Dependency) {
  Data.Dependencies.emplace_back(FullName, Dependency);
}

void CheckerRegistry::addWeakDependency(StringRef FullName,
                                        StringRef Dependency) {
  Data.WeakDependencies.emplace_back(FullName, Dependency);
}

//===----------------------------------------------------------------------===//
// Checker option resolving and validating.
//===----------------------------------------------------------------------===//

/// Insert the checker/package option to AnalyzerOptions' config table, and
/// validate it, if the user supplied it on the command line.
static void insertAndValidate(StringRef FullName, const CmdLineOption &Option,
                              AnalyzerOptions &AnOpts,
                              DiagnosticsEngine &Diags) {

  std::string FullOption = (FullName + ":" + Option.OptionName).str();

  auto It =
      AnOpts.Config.insert({FullOption, std::string(Option.DefaultValStr)});

  // Insertation was successful -- CmdLineOption's constructor will validate
  // whether values received from plugins or TableGen files are correct.
  if (It.second)
    return;

  // Insertion failed, the user supplied this package/checker option on the
  // command line. If the supplied value is invalid, we'll restore the option
  // to it's default value, and if we're in non-compatibility mode, we'll also
  // emit an error.

  StringRef SuppliedValue = It.first->getValue();

  if (Option.OptionType == "bool") {
    if (SuppliedValue != "true" && SuppliedValue != "false") {
      if (AnOpts.ShouldEmitErrorsOnInvalidConfigValue) {
        Diags.Report(diag::err_analyzer_checker_option_invalid_input)
            << FullOption << "a boolean value";
      }

      It.first->setValue(std::string(Option.DefaultValStr));
    }
    return;
  }

  if (Option.OptionType == "int") {
    int Tmp;
    bool HasFailed = SuppliedValue.getAsInteger(0, Tmp);
    if (HasFailed) {
      if (AnOpts.ShouldEmitErrorsOnInvalidConfigValue) {
        Diags.Report(diag::err_analyzer_checker_option_invalid_input)
            << FullOption << "an integer value";
      }

      It.first->setValue(std::string(Option.DefaultValStr));
    }
    return;
  }
}

template <class T>
static void insertOptionToCollection(StringRef FullName, T &Collection,
                                     const CmdLineOption &Option,
                                     AnalyzerOptions &AnOpts,
                                     DiagnosticsEngine &Diags) {
  auto It = binaryFind(Collection, FullName);
  assert(It != Collection.end() &&
         "Failed to find the checker while attempting to add a command line "
         "option to it!");

  insertAndValidate(FullName, Option, AnOpts, Diags);

  It->CmdLineOptions.emplace_back(Option);
}

void CheckerRegistry::resolveCheckerAndPackageOptions() {
  for (const std::pair<StringRef, CmdLineOption> &CheckerOptEntry :
       Data.CheckerOptions) {
    insertOptionToCollection(CheckerOptEntry.first, Data.Checkers,
                             CheckerOptEntry.second, AnOpts, Diags);
  }

  for (const std::pair<StringRef, CmdLineOption> &PackageOptEntry :
       Data.PackageOptions) {
    insertOptionToCollection(PackageOptEntry.first, Data.Packages,
                             PackageOptEntry.second, AnOpts, Diags);
  }
}

void CheckerRegistry::addPackage(StringRef FullName) {
  Data.Packages.emplace_back(PackageInfo(FullName));
}

void CheckerRegistry::addPackageOption(StringRef OptionType,
                                       StringRef PackageFullName,
                                       StringRef OptionName,
                                       StringRef DefaultValStr,
                                       StringRef Description,
                                       StringRef DevelopmentStatus,
                                       bool IsHidden) {
  Data.PackageOptions.emplace_back(
      PackageFullName, CmdLineOption{OptionType, OptionName, DefaultValStr,
                                     Description, DevelopmentStatus, IsHidden});
}

void CheckerRegistry::addChecker(RegisterCheckerFn Rfn,
                                 ShouldRegisterFunction Sfn, StringRef Name,
                                 StringRef Desc, StringRef DocsUri,
                                 bool IsHidden) {
  Data.Checkers.emplace_back(Rfn, Sfn, Name, Desc, DocsUri, IsHidden);

  // Record the presence of the checker in its packages.
  StringRef PackageName, LeafName;
  std::tie(PackageName, LeafName) = Name.rsplit(PackageSeparator);
  while (!LeafName.empty()) {
    Data.PackageSizes[PackageName] += 1;
    std::tie(PackageName, LeafName) = PackageName.rsplit(PackageSeparator);
  }
}

void CheckerRegistry::addCheckerOption(StringRef OptionType,
                                       StringRef CheckerFullName,
                                       StringRef OptionName,
                                       StringRef DefaultValStr,
                                       StringRef Description,
                                       StringRef DevelopmentStatus,
                                       bool IsHidden) {
  Data.CheckerOptions.emplace_back(
      CheckerFullName, CmdLineOption{OptionType, OptionName, DefaultValStr,
                                     Description, DevelopmentStatus, IsHidden});
}

void CheckerRegistry::initializeManager(CheckerManager &CheckerMgr) const {
  // Initialize the CheckerManager with all enabled checkers.
  for (const auto *Checker : Data.EnabledCheckers) {
    CheckerMgr.setCurrentCheckerName(CheckerNameRef(Checker->FullName));
    Checker->Initialize(CheckerMgr);
  }
}

static void isOptionContainedIn(const CmdLineOptionList &OptionList,
                                StringRef SuppliedChecker,
                                StringRef SuppliedOption,
                                const AnalyzerOptions &AnOpts,
                                DiagnosticsEngine &Diags) {

  if (!AnOpts.ShouldEmitErrorsOnInvalidConfigValue)
    return;

  auto SameOptName = [SuppliedOption](const CmdLineOption &Opt) {
    return Opt.OptionName == SuppliedOption;
  };

  const auto *OptionIt = llvm::find_if(OptionList, SameOptName);

  if (OptionIt == OptionList.end()) {
    Diags.Report(diag::err_analyzer_checker_option_unknown)
        << SuppliedChecker << SuppliedOption;
    return;
  }
}

void CheckerRegistry::validateCheckerOptions() const {
  for (const auto &Config : AnOpts.Config) {

    StringRef SuppliedCheckerOrPackage;
    StringRef SuppliedOption;
    std::tie(SuppliedCheckerOrPackage, SuppliedOption) =
        Config.getKey().split(':');

    if (SuppliedOption.empty())
      continue;

    // AnalyzerOptions' config table contains the user input, so an entry could
    // look like this:
    //
    //   cor:NoFalsePositives=true
    //
    // Since lower_bound would look for the first element *not less* than "cor",
    // it would return with an iterator to the first checker in the core, so we
    // we really have to use find here, which uses operator==.
    auto CheckerIt =
        llvm::find(Data.Checkers, CheckerInfo(SuppliedCheckerOrPackage));
    if (CheckerIt != Data.Checkers.end()) {
      isOptionContainedIn(CheckerIt->CmdLineOptions, SuppliedCheckerOrPackage,
                          SuppliedOption, AnOpts, Diags);
      continue;
    }

    const auto *PackageIt =
        llvm::find(Data.Packages, PackageInfo(SuppliedCheckerOrPackage));
    if (PackageIt != Data.Packages.end()) {
      isOptionContainedIn(PackageIt->CmdLineOptions, SuppliedCheckerOrPackage,
                          SuppliedOption, AnOpts, Diags);
      continue;
    }

    Diags.Report(diag::err_unknown_analyzer_checker_or_package)
        << SuppliedCheckerOrPackage;
  }
}

