This revision was automatically updated to reflect the committed changes.
Closed by commit rGb6cbe6cb0399: [analyzer][NFC] Move the data structures from 
CheckerRegistry to the Core… (authored by Szelethus).
Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D82585/new/

https://reviews.llvm.org/D82585

Files:
  clang/include/clang/StaticAnalyzer/Core/CheckerManager.h
  clang/include/clang/StaticAnalyzer/Core/CheckerRegistryData.h
  clang/include/clang/StaticAnalyzer/Frontend/CheckerRegistry.h
  clang/lib/StaticAnalyzer/Core/CMakeLists.txt
  clang/lib/StaticAnalyzer/Core/CheckerRegistryData.cpp
  clang/lib/StaticAnalyzer/Core/Environment.cpp
  clang/lib/StaticAnalyzer/Frontend/AnalyzerHelpFlags.cpp
  clang/lib/StaticAnalyzer/Frontend/CheckerRegistry.cpp
  clang/lib/StaticAnalyzer/Frontend/CreateCheckerManager.cpp
  clang/unittests/StaticAnalyzer/RegisterCustomCheckersTest.cpp

Index: clang/unittests/StaticAnalyzer/RegisterCustomCheckersTest.cpp
===================================================================
--- clang/unittests/StaticAnalyzer/RegisterCustomCheckersTest.cpp
+++ clang/unittests/StaticAnalyzer/RegisterCustomCheckersTest.cpp
@@ -11,6 +11,7 @@
 #include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
 #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
 #include "clang/StaticAnalyzer/Core/Checker.h"
+#include "clang/StaticAnalyzer/Core/CheckerRegistryData.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
 #include "clang/StaticAnalyzer/Frontend/AnalysisConsumer.h"
@@ -100,7 +101,7 @@
     llvm::raw_svector_ostream OS(Buf);
     C.getAnalysisManager()
         .getCheckerManager()
-        ->getCheckerRegistry()
+        ->getCheckerRegistryData()
         .printEnabledCheckerList(OS);
     // Strip a newline off.
     auto R =
Index: clang/lib/StaticAnalyzer/Frontend/CreateCheckerManager.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Frontend/CreateCheckerManager.cpp
+++ clang/lib/StaticAnalyzer/Frontend/CreateCheckerManager.cpp
@@ -23,11 +23,11 @@
     ArrayRef<std::function<void(CheckerRegistry &)>> checkerRegistrationFns)
     : Context(&Context), LangOpts(Context.getLangOpts()), AOptions(AOptions),
       PP(&PP), Diags(Context.getDiagnostics()),
-      Registry(
-          std::make_unique<CheckerRegistry>(plugins, Context.getDiagnostics(),
-                                            AOptions, checkerRegistrationFns)) {
-  Registry->initializeRegistry(*this);
-  Registry->initializeManager(*this);
+      RegistryData(std::make_unique<CheckerRegistryData>()) {
+  CheckerRegistry Registry(*RegistryData, plugins, Context.getDiagnostics(),
+                           AOptions, checkerRegistrationFns);
+  Registry.initializeRegistry(*this);
+  Registry.initializeManager(*this);
   finishedCheckerRegistration();
 }
 
@@ -36,8 +36,9 @@
                                DiagnosticsEngine &Diags,
                                ArrayRef<std::string> plugins)
     : LangOpts(LangOpts), AOptions(AOptions), Diags(Diags),
-      Registry(std::make_unique<CheckerRegistry>(plugins, Diags, AOptions)) {
-  Registry->initializeRegistry(*this);
+      RegistryData(std::make_unique<CheckerRegistryData>()) {
+  CheckerRegistry Registry(*RegistryData, plugins, Diags, AOptions, {});
+  Registry.initializeRegistry(*this);
 }
 
 CheckerManager::~CheckerManager() {
Index: clang/lib/StaticAnalyzer/Frontend/CheckerRegistry.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Frontend/CheckerRegistry.cpp
+++ clang/lib/StaticAnalyzer/Frontend/CheckerRegistry.cpp
@@ -25,14 +25,13 @@
 
 using namespace clang;
 using namespace ento;
+using namespace checker_registry;
 using llvm::sys::DynamicLibrary;
 
 //===----------------------------------------------------------------------===//
 // Utilities.
 //===----------------------------------------------------------------------===//
 
-using RegisterCheckersFn = void (*)(CheckerRegistry &);
-
 static bool isCompatibleAPIVersion(const char *VersionString) {
   // If the version string is null, its not an analyzer plugin.
   if (!VersionString)
@@ -43,140 +42,17 @@
   return strcmp(VersionString, CLANG_ANALYZER_API_VERSION_STRING) == 0;
 }
 
-namespace {
-template <class T> struct FullNameLT {
-  bool operator()(const T &Lhs, const T &Rhs) {
-    return Lhs.FullName < Rhs.FullName;
-  }
-};
-
-using PackageNameLT = FullNameLT<CheckerRegistry::PackageInfo>;
-using CheckerNameLT = FullNameLT<CheckerRegistry::CheckerInfo>;
-} // end of anonymous namespace
-
-template <class CheckerOrPackageInfoList>
-static std::conditional_t<std::is_const<CheckerOrPackageInfoList>::value,
-                          typename CheckerOrPackageInfoList::const_iterator,
-                          typename CheckerOrPackageInfoList::iterator>
-binaryFind(CheckerOrPackageInfoList &Collection, StringRef FullName) {
-
-  using CheckerOrPackage = typename CheckerOrPackageInfoList::value_type;
-  using CheckerOrPackageFullNameLT = FullNameLT<CheckerOrPackage>;
-
-  assert(llvm::is_sorted(Collection, CheckerOrPackageFullNameLT{}) &&
-         "In order to efficiently gather checkers/packages, this function "
-         "expects them to be already sorted!");
-
-  return llvm::lower_bound(Collection, CheckerOrPackage(FullName),
-                           CheckerOrPackageFullNameLT{});
-}
-
 static constexpr char PackageSeparator = '.';
 
-static bool isInPackage(const CheckerRegistry::CheckerInfo &Checker,
-                        StringRef PackageName) {
-  // Does the checker's full name have the package as a prefix?
-  if (!Checker.FullName.startswith(PackageName))
-    return false;
-
-  // Is the package actually just the name of a specific checker?
-  if (Checker.FullName.size() == PackageName.size())
-    return true;
-
-  // Is the checker in the package (or a subpackage)?
-  if (Checker.FullName[PackageName.size()] == PackageSeparator)
-    return true;
-
-  return false;
-}
-
-//===----------------------------------------------------------------------===//
-// Methods of CmdLineOption, PackageInfo and CheckerInfo.
-//===----------------------------------------------------------------------===//
-
-LLVM_DUMP_METHOD void
-CheckerRegistry::CmdLineOption::dumpToStream(llvm::raw_ostream &Out) const {
-  // The description can be just checked in Checkers.inc, the point here is to
-  // debug whether we succeeded in parsing it.
-  Out << OptionName << " (" << OptionType << ", "
-      << (IsHidden ? "hidden, " : "") << DevelopmentStatus << ") default: \""
-      << DefaultValStr;
-}
-
-static StringRef toString(CheckerRegistry::StateFromCmdLine Kind) {
-  switch (Kind) {
-  case CheckerRegistry::StateFromCmdLine::State_Disabled:
-    return "Disabled";
-  case CheckerRegistry::StateFromCmdLine::State_Enabled:
-    return "Enabled";
-  case CheckerRegistry::StateFromCmdLine::State_Unspecified:
-    return "Unspecified";
-  }
-  llvm_unreachable("Unhandled CheckerRegistry::StateFromCmdLine enum");
-}
-
-LLVM_DUMP_METHOD void
-CheckerRegistry::CheckerInfo::dumpToStream(llvm::raw_ostream &Out) const {
-  // The description can be just checked in Checkers.inc, the point here is to
-  // debug whether we succeeded in parsing it. Same with documentation uri.
-  Out << FullName << " (" << toString(State) << (IsHidden ? ", hidden" : "")
-      << ")\n";
-  Out << "  Options:\n";
-  for (const CmdLineOption &Option : CmdLineOptions) {
-    Out << "    ";
-    Option.dumpToStream(Out);
-    Out << '\n';
-  }
-  Out << "  Dependencies:\n";
-  for (const CheckerInfo *Dependency : Dependencies) {
-    Out << "  " << Dependency->FullName << '\n';
-  }
-  Out << "  Weak dependencies:\n";
-  for (const CheckerInfo *Dependency : WeakDependencies) {
-    Out << "    " << Dependency->FullName << '\n';
-  }
-}
-
-LLVM_DUMP_METHOD void
-CheckerRegistry::PackageInfo::dumpToStream(llvm::raw_ostream &Out) const {
-  Out << FullName << "\n";
-  Out << "  Options:\n";
-  for (const CmdLineOption &Option : CmdLineOptions) {
-    Out << "    ";
-    Option.dumpToStream(Out);
-    Out << '\n';
-  }
-}
-
 //===----------------------------------------------------------------------===//
 // Methods of CheckerRegistry.
 //===----------------------------------------------------------------------===//
 
-CheckerRegistry::CheckerInfoListRange
-CheckerRegistry::getMutableCheckersForCmdLineArg(StringRef CmdLineArg) {
-  auto It = binaryFind(Checkers, CmdLineArg);
-
-  if (!isInPackage(*It, CmdLineArg))
-    return {Checkers.end(), Checkers.end()};
-
-  // See how large the package is.
-  // If the package doesn't exist, assume the option refers to a single
-  // checker.
-  size_t Size = 1;
-  llvm::StringMap<size_t>::const_iterator PackageSize =
-      PackageSizes.find(CmdLineArg);
-
-  if (PackageSize != PackageSizes.end())
-    Size = PackageSize->getValue();
-
-  return {It, It + Size};
-}
-
 CheckerRegistry::CheckerRegistry(
-    ArrayRef<std::string> Plugins, DiagnosticsEngine &Diags,
-    AnalyzerOptions &AnOpts,
+    CheckerRegistryData &Data, ArrayRef<std::string> Plugins,
+    DiagnosticsEngine &Diags, AnalyzerOptions &AnOpts,
     ArrayRef<std::function<void(CheckerRegistry &)>> CheckerRegistrationFns)
-    : Diags(Diags), AnOpts(AnOpts) {
+    : Data(Data), Diags(Diags), AnOpts(AnOpts) {
 
   // Register builtin checkers.
 #define GET_CHECKERS
@@ -216,9 +92,10 @@
       continue;
     }
 
+    using RegisterPluginCheckerFn = void (*)(CheckerRegistry &);
     // Register its checkers.
-    RegisterCheckersFn RegisterPluginCheckers =
-        reinterpret_cast<RegisterCheckersFn>(
+    RegisterPluginCheckerFn RegisterPluginCheckers =
+        reinterpret_cast<RegisterPluginCheckerFn>(
             Lib.getAddressOfSymbol("clang_registerCheckers"));
     if (RegisterPluginCheckers)
       RegisterPluginCheckers(*this);
@@ -235,8 +112,8 @@
   // 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(Packages, PackageNameLT{});
-  llvm::sort(Checkers, CheckerNameLT{});
+  llvm::sort(Data.Packages, checker_registry::PackageNameLT{});
+  llvm::sort(Data.Checkers, checker_registry::CheckerNameLT{});
 
 #define GET_CHECKER_DEPENDENCIES
 
@@ -274,8 +151,8 @@
   resolveDependencies<false>();
 
 #ifndef NDEBUG
-  for (auto &DepPair : Dependencies) {
-    for (auto &WeakDepPair : WeakDependencies) {
+  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.
@@ -295,7 +172,7 @@
   // command line.
   for (const std::pair<std::string, bool> &Opt : AnOpts.CheckersAndPackages) {
     CheckerInfoListRange CheckerForCmdLineArg =
-        getMutableCheckersForCmdLineArg(Opt.first);
+        Data.getMutableCheckersForCmdLineArg(Opt.first);
 
     if (CheckerForCmdLineArg.begin() == CheckerForCmdLineArg.end()) {
       Diags.Report(diag::err_unknown_analyzer_checker_or_package) << Opt.first;
@@ -315,19 +192,16 @@
 //===----------------------------------------------------------------------===//
 
 template <typename IsEnabledFn>
-static bool
-collectStrongDependencies(const CheckerRegistry::ConstCheckerInfoList &Deps,
-                          const CheckerManager &Mgr,
-                          CheckerRegistry::CheckerInfoSet &Ret,
-                          IsEnabledFn IsEnabled);
+static bool collectStrongDependencies(const ConstCheckerInfoList &Deps,
+                                      const CheckerManager &Mgr,
+                                      CheckerInfoSet &Ret,
+                                      IsEnabledFn IsEnabled);
 
-/// Collects weak dependencies in \p enabledCheckers.
+/// Collects weak dependencies in \p enabledData.Checkers.
 template <typename IsEnabledFn>
-static void
-collectWeakDependencies(const CheckerRegistry::ConstCheckerInfoList &Deps,
-                        const CheckerManager &Mgr,
-                        CheckerRegistry::CheckerInfoSet &Ret,
-                        IsEnabledFn IsEnabled);
+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
@@ -338,7 +212,7 @@
   auto IsEnabledFromCmdLine = [&](const CheckerInfo *Checker) {
     return !Checker->isDisabled(Mgr);
   };
-  for (const CheckerInfo &Checker : Checkers) {
+  for (const CheckerInfo &Checker : Data.Checkers) {
     if (!Checker.isEnabled(Mgr))
       continue;
 
@@ -362,7 +236,7 @@
   auto IsEnabled = [&](const CheckerInfo *Checker) {
     return llvm::is_contained(Tmp, Checker);
   };
-  for (const CheckerInfo &Checker : Checkers) {
+  for (const CheckerInfo &Checker : Data.Checkers) {
     if (!Checker.isEnabled(Mgr))
       continue;
 
@@ -378,19 +252,18 @@
     }
 
     // Note that set_union also preserves the order of insertion.
-    EnabledCheckers.set_union(Deps);
-    EnabledCheckers.insert(&Checker);
+    Data.EnabledCheckers.set_union(Deps);
+    Data.EnabledCheckers.insert(&Checker);
   }
 }
 
 template <typename IsEnabledFn>
-static bool
-collectStrongDependencies(const CheckerRegistry::ConstCheckerInfoList &Deps,
-                          const CheckerManager &Mgr,
-                          CheckerRegistry::CheckerInfoSet &Ret,
-                          IsEnabledFn IsEnabled) {
+static bool collectStrongDependencies(const ConstCheckerInfoList &Deps,
+                                      const CheckerManager &Mgr,
+                                      CheckerInfoSet &Ret,
+                                      IsEnabledFn IsEnabled) {
 
-  for (const CheckerRegistry::CheckerInfo *Dependency : Deps) {
+  for (const CheckerInfo *Dependency : Deps) {
     if (!IsEnabled(Dependency))
       return false;
 
@@ -405,13 +278,12 @@
 }
 
 template <typename IsEnabledFn>
-static void
-collectWeakDependencies(const CheckerRegistry::ConstCheckerInfoList &WeakDeps,
-                        const CheckerManager &Mgr,
-                        CheckerRegistry::CheckerInfoSet &Ret,
-                        IsEnabledFn IsEnabled) {
+static void collectWeakDependencies(const ConstCheckerInfoList &WeakDeps,
+                                    const CheckerManager &Mgr,
+                                    CheckerInfoSet &Ret,
+                                    IsEnabledFn IsEnabled) {
 
-  for (const CheckerRegistry::CheckerInfo *Dependency : WeakDeps) {
+  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);
@@ -425,15 +297,16 @@
 
 template <bool IsWeak> void CheckerRegistry::resolveDependencies() {
   for (const std::pair<StringRef, StringRef> &Entry :
-       (IsWeak ? WeakDependencies : Dependencies)) {
+       (IsWeak ? Data.WeakDependencies : Data.Dependencies)) {
 
-    auto CheckerIt = binaryFind(Checkers, Entry.first);
-    assert(CheckerIt != Checkers.end() && CheckerIt->FullName == Entry.first &&
+    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(Checkers, Entry.second);
-    assert(DependencyIt != Checkers.end() &&
+    auto DependencyIt = binaryFind(Data.Checkers, Entry.second);
+    assert(DependencyIt != Data.Checkers.end() &&
            DependencyIt->FullName == Entry.second &&
            "Failed to find the dependency of a checker!");
 
@@ -445,12 +318,12 @@
 }
 
 void CheckerRegistry::addDependency(StringRef FullName, StringRef Dependency) {
-  Dependencies.emplace_back(FullName, Dependency);
+  Data.Dependencies.emplace_back(FullName, Dependency);
 }
 
 void CheckerRegistry::addWeakDependency(StringRef FullName,
                                         StringRef Dependency) {
-  WeakDependencies.emplace_back(FullName, Dependency);
+  Data.WeakDependencies.emplace_back(FullName, Dependency);
 }
 
 //===----------------------------------------------------------------------===//
@@ -459,8 +332,7 @@
 
 /// 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 CheckerRegistry::CmdLineOption &Option,
+static void insertAndValidate(StringRef FullName, const CmdLineOption &Option,
                               AnalyzerOptions &AnOpts,
                               DiagnosticsEngine &Diags) {
 
@@ -509,10 +381,10 @@
 }
 
 template <class T>
-static void
-insertOptionToCollection(StringRef FullName, T &Collection,
-                         const CheckerRegistry::CmdLineOption &Option,
-                         AnalyzerOptions &AnOpts, DiagnosticsEngine &Diags) {
+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 "
@@ -525,20 +397,20 @@
 
 void CheckerRegistry::resolveCheckerAndPackageOptions() {
   for (const std::pair<StringRef, CmdLineOption> &CheckerOptEntry :
-       CheckerOptions) {
-    insertOptionToCollection(CheckerOptEntry.first, Checkers,
+       Data.CheckerOptions) {
+    insertOptionToCollection(CheckerOptEntry.first, Data.Checkers,
                              CheckerOptEntry.second, AnOpts, Diags);
   }
 
   for (const std::pair<StringRef, CmdLineOption> &PackageOptEntry :
-       PackageOptions) {
-    insertOptionToCollection(PackageOptEntry.first, Packages,
+       Data.PackageOptions) {
+    insertOptionToCollection(PackageOptEntry.first, Data.Packages,
                              PackageOptEntry.second, AnOpts, Diags);
   }
 }
 
 void CheckerRegistry::addPackage(StringRef FullName) {
-  Packages.emplace_back(PackageInfo(FullName));
+  Data.Packages.emplace_back(PackageInfo(FullName));
 }
 
 void CheckerRegistry::addPackageOption(StringRef OptionType,
@@ -548,22 +420,22 @@
                                        StringRef Description,
                                        StringRef DevelopmentStatus,
                                        bool IsHidden) {
-  PackageOptions.emplace_back(
+  Data.PackageOptions.emplace_back(
       PackageFullName, CmdLineOption{OptionType, OptionName, DefaultValStr,
                                      Description, DevelopmentStatus, IsHidden});
 }
 
-void CheckerRegistry::addChecker(InitializationFunction Rfn,
+void CheckerRegistry::addChecker(RegisterCheckerFn Rfn,
                                  ShouldRegisterFunction Sfn, StringRef Name,
                                  StringRef Desc, StringRef DocsUri,
                                  bool IsHidden) {
-  Checkers.emplace_back(Rfn, Sfn, Name, Desc, DocsUri, 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()) {
-    PackageSizes[PackageName] += 1;
+    Data.PackageSizes[PackageName] += 1;
     std::tie(PackageName, LeafName) = PackageName.rsplit(PackageSeparator);
   }
 }
@@ -575,29 +447,28 @@
                                        StringRef Description,
                                        StringRef DevelopmentStatus,
                                        bool IsHidden) {
-  CheckerOptions.emplace_back(
+  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 : EnabledCheckers) {
+  for (const auto *Checker : Data.EnabledCheckers) {
     CheckerMgr.setCurrentCheckerName(CheckerNameRef(Checker->FullName));
     Checker->Initialize(CheckerMgr);
   }
 }
 
-static void
-isOptionContainedIn(const CheckerRegistry::CmdLineOptionList &OptionList,
-                    StringRef SuppliedChecker, StringRef SuppliedOption,
-                    const AnalyzerOptions &AnOpts, DiagnosticsEngine &Diags) {
+static void isOptionContainedIn(const CmdLineOptionList &OptionList,
+                                StringRef SuppliedChecker,
+                                StringRef SuppliedOption,
+                                const AnalyzerOptions &AnOpts,
+                                DiagnosticsEngine &Diags) {
 
   if (!AnOpts.ShouldEmitErrorsOnInvalidConfigValue)
     return;
 
-  using CmdLineOption = CheckerRegistry::CmdLineOption;
-
   auto SameOptName = [SuppliedOption](const CmdLineOption &Opt) {
     return Opt.OptionName == SuppliedOption;
   };
@@ -631,16 +502,16 @@
     // 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(Checkers, CheckerInfo(SuppliedCheckerOrPackage));
-    if (CheckerIt != Checkers.end()) {
+        llvm::find(Data.Checkers, CheckerInfo(SuppliedCheckerOrPackage));
+    if (CheckerIt != Data.Checkers.end()) {
       isOptionContainedIn(CheckerIt->CmdLineOptions, SuppliedCheckerOrPackage,
                           SuppliedOption, AnOpts, Diags);
       continue;
     }
 
     const auto *PackageIt =
-        llvm::find(Packages, PackageInfo(SuppliedCheckerOrPackage));
-    if (PackageIt != Packages.end()) {
+        llvm::find(Data.Packages, PackageInfo(SuppliedCheckerOrPackage));
+    if (PackageIt != Data.Packages.end()) {
       isOptionContainedIn(PackageIt->CmdLineOptions, SuppliedCheckerOrPackage,
                           SuppliedOption, AnOpts, Diags);
       continue;
@@ -651,122 +522,3 @@
   }
 }
 
-//===----------------------------------------------------------------------===//
-// Printing functions.
-//===----------------------------------------------------------------------===//
-
-void CheckerRegistry::printCheckerWithDescList(raw_ostream &Out,
-                                               size_t MaxNameChars) const {
-  // FIXME: Print available packages.
-
-  Out << "CHECKERS:\n";
-
-  // Find the maximum option length.
-  size_t OptionFieldWidth = 0;
-  for (const auto &Checker : Checkers) {
-    // Limit the amount of padding we are willing to give up for alignment.
-    //   Package.Name     Description  [Hidden]
-    size_t NameLength = Checker.FullName.size();
-    if (NameLength <= MaxNameChars)
-      OptionFieldWidth = std::max(OptionFieldWidth, NameLength);
-  }
-
-  const size_t InitialPad = 2;
-
-  auto Print = [=](llvm::raw_ostream &Out, const CheckerInfo &Checker,
-                   StringRef Description) {
-    AnalyzerOptions::printFormattedEntry(Out, {Checker.FullName, Description},
-                                         InitialPad, OptionFieldWidth);
-    Out << '\n';
-  };
-
-  for (const auto &Checker : Checkers) {
-    // The order of this if branches is significant, we wouldn't like to display
-    // developer checkers even in the alpha output. For example,
-    // alpha.cplusplus.IteratorModeling is a modeling checker, hence it's hidden
-    // by default, and users (even when the user is a developer of an alpha
-    // checker) shouldn't normally tinker with whether they should be enabled.
-
-    if (Checker.IsHidden) {
-      if (AnOpts.ShowCheckerHelpDeveloper)
-        Print(Out, Checker, Checker.Desc);
-      continue;
-    }
-
-    if (Checker.FullName.startswith("alpha")) {
-      if (AnOpts.ShowCheckerHelpAlpha)
-        Print(Out, Checker,
-              ("(Enable only for development!) " + Checker.Desc).str());
-      continue;
-    }
-
-    if (AnOpts.ShowCheckerHelp)
-        Print(Out, Checker, Checker.Desc);
-  }
-}
-
-void CheckerRegistry::printEnabledCheckerList(raw_ostream &Out) const {
-  for (const auto *i : EnabledCheckers)
-    Out << i->FullName << '\n';
-}
-
-void CheckerRegistry::printCheckerOptionList(raw_ostream &Out) const {
-  Out << "OVERVIEW: Clang Static Analyzer Checker and Package Option List\n\n";
-  Out << "USAGE: -analyzer-config <OPTION1=VALUE,OPTION2=VALUE,...>\n\n";
-  Out << "       -analyzer-config OPTION1=VALUE, -analyzer-config "
-         "OPTION2=VALUE, ...\n\n";
-  Out << "OPTIONS:\n\n";
-
-  std::multimap<StringRef, const CmdLineOption &> OptionMap;
-
-  for (const CheckerInfo &Checker : Checkers) {
-    for (const CmdLineOption &Option : Checker.CmdLineOptions) {
-      OptionMap.insert({Checker.FullName, Option});
-    }
-  }
-
-  for (const PackageInfo &Package : Packages) {
-    for (const CmdLineOption &Option : Package.CmdLineOptions) {
-      OptionMap.insert({Package.FullName, Option});
-    }
-  }
-
-  auto Print = [] (llvm::raw_ostream &Out, StringRef FullOption, StringRef Desc) {
-    AnalyzerOptions::printFormattedEntry(Out, {FullOption, Desc},
-                                         /*InitialPad*/ 2,
-                                         /*EntryWidth*/ 50,
-                                         /*MinLineWidth*/ 90);
-    Out << "\n\n";
-  };
-  for (const std::pair<const StringRef, const CmdLineOption &> &Entry :
-       OptionMap) {
-    const CmdLineOption &Option = Entry.second;
-    std::string FullOption = (Entry.first + ":" + Option.OptionName).str();
-
-    std::string Desc =
-        ("(" + Option.OptionType + ") " + Option.Description + " (default: " +
-         (Option.DefaultValStr.empty() ? "\"\"" : Option.DefaultValStr) + ")")
-            .str();
-
-    // The list of these if branches is significant, we wouldn't like to
-    // display hidden alpha checker options for
-    // -analyzer-checker-option-help-alpha.
-
-    if (Option.IsHidden) {
-      if (AnOpts.ShowCheckerOptionDeveloperList)
-        Print(Out, FullOption, Desc);
-      continue;
-    }
-
-    if (Option.DevelopmentStatus == "alpha" ||
-        Entry.first.startswith("alpha")) {
-      if (AnOpts.ShowCheckerOptionAlphaList)
-        Print(Out, FullOption,
-              llvm::Twine("(Enable only for development!) " + Desc).str());
-      continue;
-    }
-
-    if (AnOpts.ShowCheckerOptionList)
-      Print(Out, FullOption, Desc);
-  }
-}
Index: clang/lib/StaticAnalyzer/Frontend/AnalyzerHelpFlags.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Frontend/AnalyzerHelpFlags.cpp
+++ clang/lib/StaticAnalyzer/Frontend/AnalyzerHelpFlags.cpp
@@ -33,7 +33,8 @@
       *CI.getAnalyzerOpts(), CI.getLangOpts(), CI.getDiagnostics(),
       CI.getFrontendOpts().Plugins);
 
-  CheckerMgr->getCheckerRegistry().printCheckerWithDescList(out);
+  CheckerMgr->getCheckerRegistryData().printCheckerWithDescList(
+      *CI.getAnalyzerOpts(), out);
 }
 
 void ento::printEnabledCheckerList(raw_ostream &out, CompilerInstance &CI) {
@@ -43,7 +44,7 @@
       *CI.getAnalyzerOpts(), CI.getLangOpts(), CI.getDiagnostics(),
       CI.getFrontendOpts().Plugins);
 
-  CheckerMgr->getCheckerRegistry().printEnabledCheckerList(out);
+  CheckerMgr->getCheckerRegistryData().printEnabledCheckerList(out);
 }
 
 void ento::printCheckerConfigList(raw_ostream &out, CompilerInstance &CI) {
@@ -52,7 +53,8 @@
       *CI.getAnalyzerOpts(), CI.getLangOpts(), CI.getDiagnostics(),
       CI.getFrontendOpts().Plugins);
 
-  CheckerMgr->getCheckerRegistry().printCheckerOptionList(out);
+  CheckerMgr->getCheckerRegistryData().printCheckerOptionList(
+      *CI.getAnalyzerOpts(), out);
 }
 
 void ento::printAnalyzerConfigList(raw_ostream &out) {
Index: clang/lib/StaticAnalyzer/Core/Environment.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Core/Environment.cpp
+++ clang/lib/StaticAnalyzer/Core/Environment.cpp
@@ -183,12 +183,18 @@
              F.getTreeFactory());
 
   // Iterate over the block-expr bindings.
-  for (Environment::iterator I = Env.begin(), E = Env.end();
-       I != E; ++I) {
+  for (Environment::iterator I = Env.begin(), E = Env.end(); I != E; ++I) {
     const EnvironmentEntry &BlkExpr = I.getKey();
     const SVal &X = I.getData();
 
-    if (SymReaper.isLive(BlkExpr.getStmt(), BlkExpr.getLocationContext())) {
+    const bool IsBlkExprLive =
+        SymReaper.isLive(BlkExpr.getStmt(), BlkExpr.getLocationContext());
+
+    assert((isa<Expr>(BlkExpr.getStmt()) || !IsBlkExprLive) &&
+           "Only Exprs can be live, LivenessAnalysis argues about the liveness "
+           "of *values*!");
+
+    if (IsBlkExprLive) {
       // Copy the binding to the new map.
       EBMapRef = EBMapRef.add(BlkExpr, X);
 
Index: clang/lib/StaticAnalyzer/Core/CheckerRegistryData.cpp
===================================================================
--- /dev/null
+++ clang/lib/StaticAnalyzer/Core/CheckerRegistryData.cpp
@@ -0,0 +1,233 @@
+//===- CheckerRegistry.h - Maintains all available checkers -----*- C++ -*-===//
+//
+// 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/Core/CheckerRegistryData.h"
+#include "clang/StaticAnalyzer/Core/AnalyzerOptions.h"
+#include "llvm/ADT/Twine.h"
+#include <map>
+
+using namespace clang;
+using namespace ento;
+
+//===----------------------------------------------------------------------===//
+// Methods of CmdLineOption, PackageInfo and CheckerInfo.
+//===----------------------------------------------------------------------===//
+
+LLVM_DUMP_METHOD void
+CmdLineOption::dumpToStream(llvm::raw_ostream &Out) const {
+  // The description can be just checked in Checkers.inc, the point here is to
+  // debug whether we succeeded in parsing it.
+  Out << OptionName << " (" << OptionType << ", "
+      << (IsHidden ? "hidden, " : "") << DevelopmentStatus << ") default: \""
+      << DefaultValStr;
+}
+
+static StringRef toString(StateFromCmdLine Kind) {
+  switch (Kind) {
+  case StateFromCmdLine::State_Disabled:
+    return "Disabled";
+  case StateFromCmdLine::State_Enabled:
+    return "Enabled";
+  case StateFromCmdLine::State_Unspecified:
+    return "Unspecified";
+  }
+  llvm_unreachable("Unhandled StateFromCmdLine enum");
+}
+
+LLVM_DUMP_METHOD void CheckerInfo::dumpToStream(llvm::raw_ostream &Out) const {
+  // The description can be just checked in Checkers.inc, the point here is to
+  // debug whether we succeeded in parsing it. Same with documentation uri.
+  Out << FullName << " (" << toString(State) << (IsHidden ? ", hidden" : "")
+      << ")\n";
+  Out << "  Options:\n";
+  for (const CmdLineOption &Option : CmdLineOptions) {
+    Out << "    ";
+    Option.dumpToStream(Out);
+    Out << '\n';
+  }
+  Out << "  Dependencies:\n";
+  for (const CheckerInfo *Dependency : Dependencies) {
+    Out << "  " << Dependency->FullName << '\n';
+  }
+  Out << "  Weak dependencies:\n";
+  for (const CheckerInfo *Dependency : WeakDependencies) {
+    Out << "    " << Dependency->FullName << '\n';
+  }
+}
+
+LLVM_DUMP_METHOD void PackageInfo::dumpToStream(llvm::raw_ostream &Out) const {
+  Out << FullName << "\n";
+  Out << "  Options:\n";
+  for (const CmdLineOption &Option : CmdLineOptions) {
+    Out << "    ";
+    Option.dumpToStream(Out);
+    Out << '\n';
+  }
+}
+
+static constexpr char PackageSeparator = '.';
+
+static bool isInPackage(const CheckerInfo &Checker, StringRef PackageName) {
+  // Does the checker's full name have the package as a prefix?
+  if (!Checker.FullName.startswith(PackageName))
+    return false;
+
+  // Is the package actually just the name of a specific checker?
+  if (Checker.FullName.size() == PackageName.size())
+    return true;
+
+  // Is the checker in the package (or a subpackage)?
+  if (Checker.FullName[PackageName.size()] == PackageSeparator)
+    return true;
+
+  return false;
+}
+
+CheckerInfoListRange
+CheckerRegistryData::getMutableCheckersForCmdLineArg(StringRef CmdLineArg) {
+  auto It = checker_registry::binaryFind(Checkers, CmdLineArg);
+
+  if (!isInPackage(*It, CmdLineArg))
+    return {Checkers.end(), Checkers.end()};
+
+  // See how large the package is.
+  // If the package doesn't exist, assume the option refers to a single
+  // checker.
+  size_t Size = 1;
+  llvm::StringMap<size_t>::const_iterator PackageSize =
+      PackageSizes.find(CmdLineArg);
+
+  if (PackageSize != PackageSizes.end())
+    Size = PackageSize->getValue();
+
+  return {It, It + Size};
+}
+//===----------------------------------------------------------------------===//
+// Printing functions.
+//===----------------------------------------------------------------------===//
+
+void CheckerRegistryData::printCheckerWithDescList(
+    const AnalyzerOptions &AnOpts, raw_ostream &Out,
+    size_t MaxNameChars) const {
+  // FIXME: Print available packages.
+
+  Out << "CHECKERS:\n";
+
+  // Find the maximum option length.
+  size_t OptionFieldWidth = 0;
+  for (const auto &Checker : Checkers) {
+    // Limit the amount of padding we are willing to give up for alignment.
+    //   Package.Name     Description  [Hidden]
+    size_t NameLength = Checker.FullName.size();
+    if (NameLength <= MaxNameChars)
+      OptionFieldWidth = std::max(OptionFieldWidth, NameLength);
+  }
+
+  const size_t InitialPad = 2;
+
+  auto Print = [=](llvm::raw_ostream &Out, const CheckerInfo &Checker,
+                   StringRef Description) {
+    AnalyzerOptions::printFormattedEntry(Out, {Checker.FullName, Description},
+                                         InitialPad, OptionFieldWidth);
+    Out << '\n';
+  };
+
+  for (const auto &Checker : Checkers) {
+    // The order of this if branches is significant, we wouldn't like to display
+    // developer checkers even in the alpha output. For example,
+    // alpha.cplusplus.IteratorModeling is a modeling checker, hence it's hidden
+    // by default, and users (even when the user is a developer of an alpha
+    // checker) shouldn't normally tinker with whether they should be enabled.
+
+    if (Checker.IsHidden) {
+      if (AnOpts.ShowCheckerHelpDeveloper)
+        Print(Out, Checker, Checker.Desc);
+      continue;
+    }
+
+    if (Checker.FullName.startswith("alpha")) {
+      if (AnOpts.ShowCheckerHelpAlpha)
+        Print(Out, Checker,
+              ("(Enable only for development!) " + Checker.Desc).str());
+      continue;
+    }
+
+    if (AnOpts.ShowCheckerHelp)
+      Print(Out, Checker, Checker.Desc);
+  }
+}
+
+void CheckerRegistryData::printEnabledCheckerList(raw_ostream &Out) const {
+  for (const auto *i : EnabledCheckers)
+    Out << i->FullName << '\n';
+}
+
+void CheckerRegistryData::printCheckerOptionList(const AnalyzerOptions &AnOpts,
+                                                 raw_ostream &Out) const {
+  Out << "OVERVIEW: Clang Static Analyzer Checker and Package Option List\n\n";
+  Out << "USAGE: -analyzer-config <OPTION1=VALUE,OPTION2=VALUE,...>\n\n";
+  Out << "       -analyzer-config OPTION1=VALUE, -analyzer-config "
+         "OPTION2=VALUE, ...\n\n";
+  Out << "OPTIONS:\n\n";
+
+  // It's usually ill-advised to use multimap, but clang will terminate after
+  // this function.
+  std::multimap<StringRef, const CmdLineOption &> OptionMap;
+
+  for (const CheckerInfo &Checker : Checkers) {
+    for (const CmdLineOption &Option : Checker.CmdLineOptions) {
+      OptionMap.insert({Checker.FullName, Option});
+    }
+  }
+
+  for (const PackageInfo &Package : Packages) {
+    for (const CmdLineOption &Option : Package.CmdLineOptions) {
+      OptionMap.insert({Package.FullName, Option});
+    }
+  }
+
+  auto Print = [](llvm::raw_ostream &Out, StringRef FullOption,
+                  StringRef Desc) {
+    AnalyzerOptions::printFormattedEntry(Out, {FullOption, Desc},
+                                         /*InitialPad*/ 2,
+                                         /*EntryWidth*/ 50,
+                                         /*MinLineWidth*/ 90);
+    Out << "\n\n";
+  };
+  for (const std::pair<const StringRef, const CmdLineOption &> &Entry :
+       OptionMap) {
+    const CmdLineOption &Option = Entry.second;
+    std::string FullOption = (Entry.first + ":" + Option.OptionName).str();
+
+    std::string Desc =
+        ("(" + Option.OptionType + ") " + Option.Description + " (default: " +
+         (Option.DefaultValStr.empty() ? "\"\"" : Option.DefaultValStr) + ")")
+            .str();
+
+    // The list of these if branches is significant, we wouldn't like to
+    // display hidden alpha checker options for
+    // -analyzer-checker-option-help-alpha.
+
+    if (Option.IsHidden) {
+      if (AnOpts.ShowCheckerOptionDeveloperList)
+        Print(Out, FullOption, Desc);
+      continue;
+    }
+
+    if (Option.DevelopmentStatus == "alpha" ||
+        Entry.first.startswith("alpha")) {
+      if (AnOpts.ShowCheckerOptionAlphaList)
+        Print(Out, FullOption,
+              llvm::Twine("(Enable only for development!) " + Desc).str());
+      continue;
+    }
+
+    if (AnOpts.ShowCheckerOptionList)
+      Print(Out, FullOption, Desc);
+  }
+}
Index: clang/lib/StaticAnalyzer/Core/CMakeLists.txt
===================================================================
--- clang/lib/StaticAnalyzer/Core/CMakeLists.txt
+++ clang/lib/StaticAnalyzer/Core/CMakeLists.txt
@@ -16,6 +16,7 @@
   CheckerContext.cpp
   CheckerHelpers.cpp
   CheckerManager.cpp
+  CheckerRegistryData.cpp
   CommonBugCategories.cpp
   ConstraintManager.cpp
   CoreEngine.cpp
Index: clang/include/clang/StaticAnalyzer/Frontend/CheckerRegistry.h
===================================================================
--- clang/include/clang/StaticAnalyzer/Frontend/CheckerRegistry.h
+++ clang/include/clang/StaticAnalyzer/Frontend/CheckerRegistry.h
@@ -5,17 +5,22 @@
 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 //
 //===----------------------------------------------------------------------===//
+//
+// Contains the logic for parsing the TableGen file Checkers.td, and parsing the
+// specific invocation of the analyzer (which checker/package is enabled, values
+// of their options, etc). This is in the frontend library because checker
+// registry functions are called from here but are defined in the dependent
+// library libStaticAnalyzerCheckers, but the actual data structure that holds
+// the parsed information is in the Core library.
+//
+//===----------------------------------------------------------------------===//
 
-#ifndef LLVM_CLANG_STATICANALYZER_CORE_CHECKERREGISTRY_H
-#define LLVM_CLANG_STATICANALYZER_CORE_CHECKERREGISTRY_H
+#ifndef LLVM_CLANG_STATICANALYZER_FRONTEND_CHECKERREGISTRY_H
+#define LLVM_CLANG_STATICANALYZER_FRONTEND_CHECKERREGISTRY_H
 
 #include "clang/Basic/LLVM.h"
-#include "llvm/ADT/SetVector.h"
-#include "llvm/ADT/StringMap.h"
+#include "clang/StaticAnalyzer/Core/CheckerRegistryData.h"
 #include "llvm/ADT/StringRef.h"
-#include "llvm/Support/raw_ostream.h"
-#include <cstddef>
-#include <vector>
 
 // FIXME: move this information to an HTML file in docs/.
 // At the very least, a checker plugin is a dynamic library that exports
@@ -83,143 +88,16 @@
 /// "core.builtin", or the full name "core.builtin.NoReturnFunctionChecker".
 class CheckerRegistry {
 public:
-  CheckerRegistry(ArrayRef<std::string> plugins, DiagnosticsEngine &diags,
-                  AnalyzerOptions &AnOpts,
+  CheckerRegistry(CheckerRegistryData &Data, ArrayRef<std::string> Plugins,
+                  DiagnosticsEngine &Diags, AnalyzerOptions &AnOpts,
                   ArrayRef<std::function<void(CheckerRegistry &)>>
-                      checkerRegistrationFns = {});
+                      CheckerRegistrationFns = {});
 
   /// Collects all enabled checkers in the field EnabledCheckers. It preserves
   /// the order of insertion, as dependencies have to be enabled before the
   /// checkers that depend on them.
   void initializeRegistry(const CheckerManager &Mgr);
 
-  /// Initialization functions perform any necessary setup for a checker.
-  /// They should include a call to CheckerManager::registerChecker.
-  using InitializationFunction = void (*)(CheckerManager &);
-  using ShouldRegisterFunction = bool (*)(const CheckerManager &);
-
-  /// Specifies a command line option. It may either belong to a checker or a
-  /// package.
-  struct CmdLineOption {
-    StringRef OptionType;
-    StringRef OptionName;
-    StringRef DefaultValStr;
-    StringRef Description;
-    StringRef DevelopmentStatus;
-    bool IsHidden;
-
-    CmdLineOption(StringRef OptionType, StringRef OptionName,
-                  StringRef DefaultValStr, StringRef Description,
-                  StringRef DevelopmentStatus, bool IsHidden)
-        : OptionType(OptionType), OptionName(OptionName),
-          DefaultValStr(DefaultValStr), Description(Description),
-          DevelopmentStatus(DevelopmentStatus), IsHidden(IsHidden) {
-
-      assert((OptionType == "bool" || OptionType == "string" ||
-              OptionType == "int") &&
-             "Unknown command line option type!");
-
-      assert((OptionType != "bool" ||
-              (DefaultValStr == "true" || DefaultValStr == "false")) &&
-             "Invalid value for boolean command line option! Maybe incorrect "
-             "parameters to the addCheckerOption or addPackageOption method?");
-
-      int Tmp;
-      assert((OptionType != "int" || !DefaultValStr.getAsInteger(0, Tmp)) &&
-             "Invalid value for integer command line option! Maybe incorrect "
-             "parameters to the addCheckerOption or addPackageOption method?");
-      (void)Tmp;
-
-      assert((DevelopmentStatus == "alpha" || DevelopmentStatus == "beta" ||
-              DevelopmentStatus == "released") &&
-             "Invalid development status!");
-    }
-
-    LLVM_DUMP_METHOD void dump() const { dumpToStream(llvm::errs()); }
-    LLVM_DUMP_METHOD void dumpToStream(llvm::raw_ostream &Out) const;
-  };
-
-  using CmdLineOptionList = llvm::SmallVector<CmdLineOption, 0>;
-
-  struct CheckerInfo;
-
-  using CheckerInfoList = std::vector<CheckerInfo>;
-  using CheckerInfoListRange = llvm::iterator_range<CheckerInfoList::iterator>;
-  using ConstCheckerInfoList = llvm::SmallVector<const CheckerInfo *, 0>;
-  using CheckerInfoSet = llvm::SetVector<const CheckerInfo *>;
-
-  /// Specifies a checker. Note that this isn't what we call a checker object,
-  /// it merely contains everything required to create one.
-  struct CheckerInfo {
-    enum class StateFromCmdLine {
-      // This checker wasn't explicitly enabled or disabled.
-      State_Unspecified,
-      // This checker was explicitly disabled.
-      State_Disabled,
-      // This checker was explicitly enabled.
-      State_Enabled
-    };
-
-    InitializationFunction Initialize = nullptr;
-    ShouldRegisterFunction ShouldRegister = nullptr;
-    StringRef FullName;
-    StringRef Desc;
-    StringRef DocumentationUri;
-    CmdLineOptionList CmdLineOptions;
-    bool IsHidden = false;
-    StateFromCmdLine State = StateFromCmdLine::State_Unspecified;
-
-    ConstCheckerInfoList Dependencies;
-    ConstCheckerInfoList WeakDependencies;
-
-    bool isEnabled(const CheckerManager &mgr) const {
-      return State == StateFromCmdLine::State_Enabled && ShouldRegister(mgr);
-    }
-
-    bool isDisabled(const CheckerManager &mgr) const {
-      return State == StateFromCmdLine::State_Disabled || !ShouldRegister(mgr);
-    }
-
-    // Since each checker must have a different full name, we can identify
-    // CheckerInfo objects by them.
-    bool operator==(const CheckerInfo &Rhs) const {
-      return FullName == Rhs.FullName;
-    }
-
-    CheckerInfo(InitializationFunction Fn, ShouldRegisterFunction sfn,
-                StringRef Name, StringRef Desc, StringRef DocsUri,
-                bool IsHidden)
-        : Initialize(Fn), ShouldRegister(sfn), FullName(Name), Desc(Desc),
-          DocumentationUri(DocsUri), IsHidden(IsHidden) {}
-
-    // Used for lower_bound.
-    explicit CheckerInfo(StringRef FullName) : FullName(FullName) {}
-
-    LLVM_DUMP_METHOD void dump() const { dumpToStream(llvm::errs()); }
-    LLVM_DUMP_METHOD void dumpToStream(llvm::raw_ostream &Out) const;
-  };
-
-  using StateFromCmdLine = CheckerInfo::StateFromCmdLine;
-
-  /// Specifies a package. Each package option is implicitly an option for all
-  /// checkers within the package.
-  struct PackageInfo {
-    StringRef FullName;
-    CmdLineOptionList CmdLineOptions;
-
-    // Since each package must have a different full name, we can identify
-    // CheckerInfo objects by them.
-    bool operator==(const PackageInfo &Rhs) const {
-      return FullName == Rhs.FullName;
-    }
-
-    explicit PackageInfo(StringRef FullName) : FullName(FullName) {}
-
-    LLVM_DUMP_METHOD void dump() const { dumpToStream(llvm::errs()); }
-    LLVM_DUMP_METHOD void dumpToStream(llvm::raw_ostream &Out) const;
-  };
-
-  using PackageInfoList = llvm::SmallVector<PackageInfo, 0>;
 
 private:
   /// Default initialization function for checkers -- since CheckerManager
@@ -237,7 +115,7 @@
 public:
   /// Adds a checker to the registry. Use this non-templated overload when your
   /// checker requires custom initialization.
-  void addChecker(InitializationFunction Fn, ShouldRegisterFunction sfn,
+  void addChecker(RegisterCheckerFn Fn, ShouldRegisterFunction sfn,
                   StringRef FullName, StringRef Desc, StringRef DocsUri,
                   bool IsHidden);
 
@@ -305,46 +183,17 @@
   /// Check if every option corresponds to a specific checker or package.
   void validateCheckerOptions() const;
 
-  /// Prints the name and description of all checkers in this registry.
-  /// This output is not intended to be machine-parseable.
-  void printCheckerWithDescList(raw_ostream &Out,
-                                size_t MaxNameChars = 30) const;
-  void printEnabledCheckerList(raw_ostream &Out) const;
-  void printCheckerOptionList(raw_ostream &Out) const;
-
 private:
-  /// Return an iterator range of mutable CheckerInfos \p CmdLineArg applies to.
-  /// For example, it'll return the checkers for the core package, if
-  /// \p CmdLineArg is "core".
-  CheckerInfoListRange getMutableCheckersForCmdLineArg(StringRef CmdLineArg);
-
-  CheckerInfoList Checkers;
-  PackageInfoList Packages;
-  /// Used for couting how many checkers belong to a certain package in the
-  /// \c Checkers field. For convenience purposes.
-  llvm::StringMap<size_t> PackageSizes;
-
-  /// Contains all (Dependendent checker, Dependency) pairs. We need this, as
-  /// we'll resolve dependencies after all checkers were added first.
-  llvm::SmallVector<std::pair<StringRef, StringRef>, 0> Dependencies;
-  llvm::SmallVector<std::pair<StringRef, StringRef>, 0> WeakDependencies;
-
   template <bool IsWeak> void resolveDependencies();
-
-  /// Contains all (FullName, CmdLineOption) pairs. Similarly to dependencies,
-  /// we only modify the actual CheckerInfo and PackageInfo objects once all
-  /// of them have been added.
-  llvm::SmallVector<std::pair<StringRef, CmdLineOption>, 0> PackageOptions;
-  llvm::SmallVector<std::pair<StringRef, CmdLineOption>, 0> CheckerOptions;
-
   void resolveCheckerAndPackageOptions();
 
+  CheckerRegistryData &Data;
+
   DiagnosticsEngine &Diags;
   AnalyzerOptions &AnOpts;
-  CheckerInfoSet EnabledCheckers;
 };
 
 } // namespace ento
 } // namespace clang
 
-#endif // LLVM_CLANG_STATICANALYZER_CORE_CHECKERREGISTRY_H
+#endif // LLVM_CLANG_STATICANALYZER_FRONTEND_CHECKERREGISTRY_H
Index: clang/include/clang/StaticAnalyzer/Core/CheckerRegistryData.h
===================================================================
--- /dev/null
+++ clang/include/clang/StaticAnalyzer/Core/CheckerRegistryData.h
@@ -0,0 +1,226 @@
+//===- CheckerRegistryData.h ------------------------------------*- C++ -*-===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains the data structures to which the TableGen file Checkers.td
+// maps to, as well as what was parsed from the the specific invocation (whether
+// a checker/package is enabled, their options values, etc).
+//
+// The parsing of the invocation is done by CheckerRegistry, which is found in
+// the Frontend library. This allows the Core and Checkers libraries to utilize
+// this information, such as enforcing rules on checker dependency bug emission,
+// ensuring all checker options were queried, etc.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_STATICANALYZER_CORE_CHECKERREGISTRYDATA_H
+#define LLVM_CLANG_STATICANALYZER_CORE_CHECKERREGISTRYDATA_H
+
+#include "clang/Basic/LLVM.h"
+#include "llvm/ADT/SetVector.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/raw_ostream.h"
+
+namespace clang {
+
+class AnalyzerOptions;
+
+namespace ento {
+
+class CheckerManager;
+
+/// Initialization functions perform any necessary setup for a checker.
+/// They should include a call to CheckerManager::registerChecker.
+using RegisterCheckerFn = void (*)(CheckerManager &);
+using ShouldRegisterFunction = bool (*)(const CheckerManager &);
+
+/// Specifies a command line option. It may either belong to a checker or a
+/// package.
+struct CmdLineOption {
+  StringRef OptionType;
+  StringRef OptionName;
+  StringRef DefaultValStr;
+  StringRef Description;
+  StringRef DevelopmentStatus;
+  bool IsHidden;
+
+  CmdLineOption(StringRef OptionType, StringRef OptionName,
+                StringRef DefaultValStr, StringRef Description,
+                StringRef DevelopmentStatus, bool IsHidden)
+      : OptionType(OptionType), OptionName(OptionName),
+        DefaultValStr(DefaultValStr), Description(Description),
+        DevelopmentStatus(DevelopmentStatus), IsHidden(IsHidden) {
+
+    assert((OptionType == "bool" || OptionType == "string" ||
+            OptionType == "int") &&
+           "Unknown command line option type!");
+
+    assert((OptionType != "bool" ||
+            (DefaultValStr == "true" || DefaultValStr == "false")) &&
+           "Invalid value for boolean command line option! Maybe incorrect "
+           "parameters to the addCheckerOption or addPackageOption method?");
+
+    int Tmp;
+    assert((OptionType != "int" || !DefaultValStr.getAsInteger(0, Tmp)) &&
+           "Invalid value for integer command line option! Maybe incorrect "
+           "parameters to the addCheckerOption or addPackageOption method?");
+    (void)Tmp;
+
+    assert((DevelopmentStatus == "alpha" || DevelopmentStatus == "beta" ||
+            DevelopmentStatus == "released") &&
+           "Invalid development status!");
+  }
+
+  LLVM_DUMP_METHOD void dump() const { dumpToStream(llvm::errs()); }
+  LLVM_DUMP_METHOD void dumpToStream(llvm::raw_ostream &Out) const;
+};
+
+using CmdLineOptionList = llvm::SmallVector<CmdLineOption, 0>;
+
+struct CheckerInfo;
+
+using CheckerInfoList = std::vector<CheckerInfo>;
+using CheckerInfoListRange = llvm::iterator_range<CheckerInfoList::iterator>;
+using ConstCheckerInfoList = llvm::SmallVector<const CheckerInfo *, 0>;
+using CheckerInfoSet = llvm::SetVector<const CheckerInfo *>;
+
+/// Specifies a checker. Note that this isn't what we call a checker object,
+/// it merely contains everything required to create one.
+struct CheckerInfo {
+  enum class StateFromCmdLine {
+    // This checker wasn't explicitly enabled or disabled.
+    State_Unspecified,
+    // This checker was explicitly disabled.
+    State_Disabled,
+    // This checker was explicitly enabled.
+    State_Enabled
+  };
+
+  RegisterCheckerFn Initialize = nullptr;
+  ShouldRegisterFunction ShouldRegister = nullptr;
+  StringRef FullName;
+  StringRef Desc;
+  StringRef DocumentationUri;
+  CmdLineOptionList CmdLineOptions;
+  bool IsHidden = false;
+  StateFromCmdLine State = StateFromCmdLine::State_Unspecified;
+
+  ConstCheckerInfoList Dependencies;
+  ConstCheckerInfoList WeakDependencies;
+
+  bool isEnabled(const CheckerManager &mgr) const {
+    return State == StateFromCmdLine::State_Enabled && ShouldRegister(mgr);
+  }
+
+  bool isDisabled(const CheckerManager &mgr) const {
+    return State == StateFromCmdLine::State_Disabled || !ShouldRegister(mgr);
+  }
+
+  // Since each checker must have a different full name, we can identify
+  // CheckerInfo objects by them.
+  bool operator==(const CheckerInfo &Rhs) const {
+    return FullName == Rhs.FullName;
+  }
+
+  CheckerInfo(RegisterCheckerFn Fn, ShouldRegisterFunction sfn, StringRef Name,
+              StringRef Desc, StringRef DocsUri, bool IsHidden)
+      : Initialize(Fn), ShouldRegister(sfn), FullName(Name), Desc(Desc),
+        DocumentationUri(DocsUri), IsHidden(IsHidden) {}
+
+  // Used for lower_bound.
+  explicit CheckerInfo(StringRef FullName) : FullName(FullName) {}
+
+  LLVM_DUMP_METHOD void dump() const { dumpToStream(llvm::errs()); }
+  LLVM_DUMP_METHOD void dumpToStream(llvm::raw_ostream &Out) const;
+};
+
+using StateFromCmdLine = CheckerInfo::StateFromCmdLine;
+
+/// Specifies a package. Each package option is implicitly an option for all
+/// checkers within the package.
+struct PackageInfo {
+  StringRef FullName;
+  CmdLineOptionList CmdLineOptions;
+
+  // Since each package must have a different full name, we can identify
+  // CheckerInfo objects by them.
+  bool operator==(const PackageInfo &Rhs) const {
+    return FullName == Rhs.FullName;
+  }
+
+  explicit PackageInfo(StringRef FullName) : FullName(FullName) {}
+
+  LLVM_DUMP_METHOD void dump() const { dumpToStream(llvm::errs()); }
+  LLVM_DUMP_METHOD void dumpToStream(llvm::raw_ostream &Out) const;
+};
+
+using PackageInfoList = llvm::SmallVector<PackageInfo, 0>;
+
+namespace checker_registry {
+
+template <class T> struct FullNameLT {
+  bool operator()(const T &Lhs, const T &Rhs) {
+    return Lhs.FullName < Rhs.FullName;
+  }
+};
+
+using PackageNameLT = FullNameLT<PackageInfo>;
+using CheckerNameLT = FullNameLT<CheckerInfo>;
+
+template <class CheckerOrPackageInfoList>
+std::conditional_t<std::is_const<CheckerOrPackageInfoList>::value,
+                   typename CheckerOrPackageInfoList::const_iterator,
+                   typename CheckerOrPackageInfoList::iterator>
+binaryFind(CheckerOrPackageInfoList &Collection, StringRef FullName) {
+
+  using CheckerOrPackage = typename CheckerOrPackageInfoList::value_type;
+  using CheckerOrPackageFullNameLT = FullNameLT<CheckerOrPackage>;
+
+  assert(llvm::is_sorted(Collection, CheckerOrPackageFullNameLT{}) &&
+         "In order to efficiently gather checkers/packages, this function "
+         "expects them to be already sorted!");
+
+  return llvm::lower_bound(Collection, CheckerOrPackage(FullName),
+                           CheckerOrPackageFullNameLT{});
+}
+} // namespace checker_registry
+
+struct CheckerRegistryData {
+public:
+  CheckerInfoSet EnabledCheckers;
+
+  CheckerInfoList Checkers;
+  PackageInfoList Packages;
+  /// Used for counting how many checkers belong to a certain package in the
+  /// \c Checkers field. For convenience purposes.
+  llvm::StringMap<size_t> PackageSizes;
+
+  /// Contains all (FullName, CmdLineOption) pairs. Similarly to dependencies,
+  /// we only modify the actual CheckerInfo and PackageInfo objects once all
+  /// of them have been added.
+  llvm::SmallVector<std::pair<StringRef, CmdLineOption>, 0> PackageOptions;
+  llvm::SmallVector<std::pair<StringRef, CmdLineOption>, 0> CheckerOptions;
+
+  llvm::SmallVector<std::pair<StringRef, StringRef>, 0> Dependencies;
+  llvm::SmallVector<std::pair<StringRef, StringRef>, 0> WeakDependencies;
+
+  CheckerInfoListRange getMutableCheckersForCmdLineArg(StringRef CmdLineArg);
+
+  /// Prints the name and description of all checkers in this registry.
+  /// This output is not intended to be machine-parseable.
+  void printCheckerWithDescList(const AnalyzerOptions &AnOpts, raw_ostream &Out,
+                                size_t MaxNameChars = 30) const;
+  void printEnabledCheckerList(raw_ostream &Out) const;
+  void printCheckerOptionList(const AnalyzerOptions &AnOpts,
+                              raw_ostream &Out) const;
+};
+
+} // namespace ento
+} // namespace clang
+
+#endif // LLVM_CLANG_STATICANALYZER_CORE_CHECKERREGISTRYDATA_H
Index: clang/include/clang/StaticAnalyzer/Core/CheckerManager.h
===================================================================
--- clang/include/clang/StaticAnalyzer/Core/CheckerManager.h
+++ clang/include/clang/StaticAnalyzer/Core/CheckerManager.h
@@ -43,6 +43,7 @@
 class CheckerBase;
 class CheckerContext;
 class CheckerRegistry;
+struct CheckerRegistryData;
 class ExplodedGraph;
 class ExplodedNode;
 class ExplodedNodeSet;
@@ -130,7 +131,7 @@
   const Preprocessor *PP = nullptr;
   CheckerNameRef CurrentCheckerName;
   DiagnosticsEngine &Diags;
-  std::unique_ptr<CheckerRegistry> Registry;
+  std::unique_ptr<CheckerRegistryData> RegistryData;
 
 public:
   // These constructors are defined in the Frontend library, because
@@ -152,8 +153,8 @@
       : CheckerManager(Context, AOptions, PP, {}, {}) {}
 
   /// Constructs a CheckerManager without requiring an AST. No checker
-  /// registration will take place. Only useful for retrieving the
-  /// CheckerRegistry and print for help flags where the AST is unavalaible.
+  /// registration will take place. Only useful when one needs to print the
+  /// help flags through CheckerRegistryData, and the AST is unavalaible.
   CheckerManager(AnalyzerOptions &AOptions, const LangOptions &LangOpts,
                  DiagnosticsEngine &Diags, ArrayRef<std::string> plugins);
 
@@ -172,7 +173,9 @@
     assert(PP);
     return *PP;
   }
-  const CheckerRegistry &getCheckerRegistry() const { return *Registry; }
+  const CheckerRegistryData &getCheckerRegistryData() const {
+    return *RegistryData;
+  }
   DiagnosticsEngine &getDiagnostics() const { return Diags; }
   ASTContext &getASTContext() const {
     assert(Context);
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to