Szelethus created this revision.
Szelethus added reviewers: NoQ, xazax.hun, baloghadamsoftware, rnkovacs, 
balazske, martong, dcoughlin.
Szelethus added a project: clang.
Herald added subscribers: cfe-commits, steakhal, Charusso, gamesh411, dkrupp, 
donat.nagy, mikhail.ramalho, a.sidorin, szepet, whisperity, mgorny.

Its been a while since my `CheckerRegistry` related patches landed, allow me to 
refresh your memory:

- During compilation, TblGen turns 
`clang/include/clang/StaticAnalyzer/Checkers/Checkers.td` into `(build 
directory)/tools/clang/include/clang/StaticAnalyzer/Checkers/Checkers.inc`. 
This is a file that contains the full name of the checkers, their options, etc.
- The class that is responsible for parsing this file is `CheckerRegistry`. The 
job of this class is to establish what checkers are available for the analyzer 
(even from plugins and statically linked but non-tblgen generated files!), and 
calculate which ones should be turned on according to the analyzer's invocation.
- `CheckerManager` is the class that is responsible for the construction and 
storage of checkers. This process works by first creating a `CheckerRegistry` 
object, and passing itself to 
`CheckerRegistry::initializeManager(CheckerManager&)`, which will call the 
checker registry functions (for example `registerMallocChecker`) on it.

The big problem here is that these two classes lie in two different libraries, 
so their interaction is pretty awkward. This used to be far worse, but I 
refactored much of it, which made things better but nowhere near perfect.

---

This patch changes how the above mentioned two classes interact. 
`CheckerRegistry` is mainly used by `CheckerManager`, and they are so 
intertwined, it makes a lot of sense to turn in into a field, instead of a 
one-time local variable. This has additional benefits: much of the information 
that `CheckerRegistry` conveniently holds is no longer thrown away right after 
the analyzer's initialization, and opens the possibility to pass 
`CheckerManager` in the `shouldRegister*` function rather then `LangOptions` 
(D75271 <https://reviews.llvm.org/D75271>).

There are a few problems with this. `CheckerManager` isn't the only user, when 
we honor help flags like `-analyzer-checker-help`, we only have access to a 
`CompilerInstance` class, that is before the point of parsing the AST. 
`CheckerManager` makes little sense without `ASTContext`, so I made some 
changes and added new constructors to make it constructible for the use of help 
flags.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D75360

Files:
  clang/include/clang/StaticAnalyzer/Core/CheckerManager.h
  clang/include/clang/StaticAnalyzer/Frontend/AnalysisConsumer.h
  clang/include/clang/StaticAnalyzer/Frontend/CheckerRegistration.h
  clang/include/clang/StaticAnalyzer/Frontend/CheckerRegistry.h
  clang/include/clang/StaticAnalyzer/Frontend/FrontendActions.h
  clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
  clang/lib/StaticAnalyzer/Core/CheckerManager.cpp
  clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
  clang/lib/StaticAnalyzer/Frontend/AnalyzerHelpFlags.cpp
  clang/lib/StaticAnalyzer/Frontend/CMakeLists.txt
  clang/lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp
  clang/lib/StaticAnalyzer/Frontend/CheckerRegistry.cpp

Index: clang/lib/StaticAnalyzer/Frontend/CheckerRegistry.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Frontend/CheckerRegistry.cpp
+++ clang/lib/StaticAnalyzer/Frontend/CheckerRegistry.cpp
@@ -109,9 +109,9 @@
 
 CheckerRegistry::CheckerRegistry(
     ArrayRef<std::string> Plugins, DiagnosticsEngine &Diags,
-    AnalyzerOptions &AnOpts, const LangOptions &LangOpts,
+    AnalyzerOptions &AnOpts,
     ArrayRef<std::function<void(CheckerRegistry &)>> CheckerRegistrationFns)
-    : Diags(Diags), AnOpts(AnOpts), LangOpts(LangOpts) {
+    : Diags(Diags), AnOpts(AnOpts) {
 
   // Register builtin checkers.
 #define GET_CHECKERS
@@ -179,12 +179,16 @@
   addDependency(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 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);
+#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
@@ -213,24 +217,53 @@
                                  : StateFromCmdLine::State_Disabled;
     }
   }
+  validateCheckerOptions();
+}
+
+/// Collects dependenies in \p enabledCheckers. Return None on failure.
+LLVM_NODISCARD
+static llvm::Optional<CheckerRegistry::CheckerInfoSet>
+collectDependencies(const CheckerRegistry::CheckerInfo &checker,
+                    const CheckerManager &Mgr);
+
+void CheckerRegistry::initializeRegistry(const CheckerManager &Mgr) {
+  for (const CheckerInfo &Checker : Checkers) {
+    if (!Checker.isEnabled(Mgr.getLangOpts()))
+      continue;
+
+    // Recursively enable its dependencies.
+    llvm::Optional<CheckerInfoSet> Deps = collectDependencies(Checker, Mgr);
+
+    if (!Deps) {
+      // 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.
+    EnabledCheckers.set_union(*Deps);
+
+    // Enable the checker.
+    EnabledCheckers.insert(&Checker);
+  }
 }
 
 /// Collects dependencies in \p ret, returns false on failure.
 static bool
 collectDependenciesImpl(const CheckerRegistry::ConstCheckerInfoList &Deps,
-                        const LangOptions &LO,
+                        const CheckerManager &Mgr,
                         CheckerRegistry::CheckerInfoSet &Ret);
 
 /// Collects dependenies in \p enabledCheckers. Return None on failure.
 LLVM_NODISCARD
 static llvm::Optional<CheckerRegistry::CheckerInfoSet>
 collectDependencies(const CheckerRegistry::CheckerInfo &checker,
-                    const LangOptions &LO) {
+                    const CheckerManager &Mgr) {
 
   CheckerRegistry::CheckerInfoSet Ret;
   // Add dependencies to the enabled checkers only if all of them can be
   // enabled.
-  if (!collectDependenciesImpl(checker.Dependencies, LO, Ret))
+  if (!collectDependenciesImpl(checker.Dependencies, Mgr, Ret))
     return None;
 
   return Ret;
@@ -238,16 +271,16 @@
 
 static bool
 collectDependenciesImpl(const CheckerRegistry::ConstCheckerInfoList &Deps,
-                        const LangOptions &LO,
+                        const CheckerManager &Mgr,
                         CheckerRegistry::CheckerInfoSet &Ret) {
 
   for (const CheckerRegistry::CheckerInfo *Dependency : Deps) {
 
-    if (Dependency->isDisabled(LO))
+    if (Dependency->isDisabled(Mgr.getLangOpts()))
       return false;
 
     // Collect dependencies recursively.
-    if (!collectDependenciesImpl(Dependency->Dependencies, LO, Ret))
+    if (!collectDependenciesImpl(Dependency->Dependencies, Mgr, Ret))
       return false;
 
     Ret.insert(Dependency);
@@ -256,34 +289,6 @@
   return true;
 }
 
-CheckerRegistry::CheckerInfoSet CheckerRegistry::getEnabledCheckers() const {
-
-  CheckerInfoSet EnabledCheckers;
-
-  for (const CheckerInfo &Checker : Checkers) {
-    if (!Checker.isEnabled(LangOpts))
-      continue;
-
-    // Recursively enable its dependencies.
-    llvm::Optional<CheckerInfoSet> Deps =
-        collectDependencies(Checker, LangOpts);
-
-    if (!Deps) {
-      // 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.
-    EnabledCheckers.set_union(*Deps);
-
-    // Enable the checker.
-    EnabledCheckers.insert(&Checker);
-  }
-
-  return EnabledCheckers;
-}
-
 void CheckerRegistry::resolveDependencies() {
   for (const std::pair<StringRef, StringRef> &Entry : Dependencies) {
     auto CheckerIt = binaryFind(Checkers, Entry.first);
@@ -298,8 +303,6 @@
 
     CheckerIt->Dependencies.emplace_back(&*DependencyIt);
   }
-
-  Dependencies.clear();
 }
 
 void CheckerRegistry::addDependency(StringRef FullName, StringRef Dependency) {
@@ -378,14 +381,12 @@
     insertOptionToCollection(CheckerOptEntry.first, Checkers,
                              CheckerOptEntry.second, AnOpts, Diags);
   }
-  CheckerOptions.clear();
 
   for (const std::pair<StringRef, CmdLineOption> &PackageOptEntry :
        PackageOptions) {
     insertOptionToCollection(PackageOptEntry.first, Packages,
                              PackageOptEntry.second, AnOpts, Diags);
   }
-  PackageOptions.clear();
 }
 
 void CheckerRegistry::addPackage(StringRef FullName) {
@@ -432,11 +433,8 @@
 }
 
 void CheckerRegistry::initializeManager(CheckerManager &CheckerMgr) const {
-  // Collect checkers enabled by the options.
-  CheckerInfoSet enabledCheckers = getEnabledCheckers();
-
   // Initialize the CheckerManager with all enabled checkers.
-  for (const auto *Checker : enabledCheckers) {
+  for (const auto *Checker : EnabledCheckers) {
     CheckerMgr.setCurrentCheckerName(CheckerNameRef(Checker->FullName));
     Checker->Initialize(CheckerMgr);
   }
@@ -505,6 +503,10 @@
   }
 }
 
+//===----------------------------------------------------------------------===//
+// Printing functions.
+//===----------------------------------------------------------------------===//
+
 void CheckerRegistry::printCheckerWithDescList(raw_ostream &Out,
                                                size_t MaxNameChars) const {
   // FIXME: Print available packages.
@@ -556,9 +558,6 @@
 }
 
 void CheckerRegistry::printEnabledCheckerList(raw_ostream &Out) const {
-  // Collect checkers enabled by the options.
-  CheckerInfoSet EnabledCheckers = getEnabledCheckers();
-
   for (const auto *i : EnabledCheckers)
     Out << i->FullName << '\n';
 }
Index: clang/lib/StaticAnalyzer/Frontend/CMakeLists.txt
===================================================================
--- clang/lib/StaticAnalyzer/Frontend/CMakeLists.txt
+++ clang/lib/StaticAnalyzer/Frontend/CMakeLists.txt
@@ -6,7 +6,7 @@
 
 add_clang_library(clangStaticAnalyzerFrontend
   AnalysisConsumer.cpp
-  CheckerRegistration.cpp
+  AnalyzerHelpFlags.cpp
   CheckerRegistry.cpp
   FrontendActions.cpp
   ModelConsumer.cpp
Index: clang/lib/StaticAnalyzer/Frontend/AnalyzerHelpFlags.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Frontend/AnalyzerHelpFlags.cpp
+++ clang/lib/StaticAnalyzer/Frontend/AnalyzerHelpFlags.cpp
@@ -10,7 +10,7 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "clang/StaticAnalyzer/Frontend/CheckerRegistration.h"
+#include "clang/StaticAnalyzer/Frontend/AnalyzerHelpFlags.h"
 #include "clang/Basic/Diagnostic.h"
 #include "clang/Frontend/FrontendDiagnostic.h"
 #include "clang/StaticAnalyzer/Core/AnalyzerOptions.h"
@@ -24,53 +24,34 @@
 using namespace clang;
 using namespace ento;
 
-std::unique_ptr<CheckerManager> ento::createCheckerManager(
-    ASTContext &context,
-    AnalyzerOptions &opts,
-    ArrayRef<std::string> plugins,
-    ArrayRef<std::function<void(CheckerRegistry &)>> checkerRegistrationFns,
-    DiagnosticsEngine &diags) {
-  auto checkerMgr = std::make_unique<CheckerManager>(context, opts);
-
-  CheckerRegistry allCheckers(plugins, diags, opts, context.getLangOpts(),
-                              checkerRegistrationFns);
-
-  allCheckers.initializeManager(*checkerMgr);
-  allCheckers.validateCheckerOptions();
-  checkerMgr->finishedCheckerRegistration();
-
-  return checkerMgr;
-}
-
-void ento::printCheckerHelp(raw_ostream &out, ArrayRef<std::string> plugins,
-                            AnalyzerOptions &anopts,
-                            DiagnosticsEngine &diags,
-                            const LangOptions &langOpts) {
+void ento::printCheckerHelp(raw_ostream &out, CompilerInstance &CI) {
   out << "OVERVIEW: Clang Static Analyzer Checkers List\n\n";
   out << "USAGE: -analyzer-checker <CHECKER or PACKAGE,...>\n\n";
 
-  CheckerRegistry(plugins, diags, anopts, langOpts)
-      .printCheckerWithDescList(out);
+  auto CheckerMgr = std::make_unique<CheckerManager>(
+      *CI.getAnalyzerOpts(), CI.getLangOpts(), CI.getDiagnostics(),
+      CI.getFrontendOpts().Plugins);
+
+  CheckerMgr->getCheckerRegistry().printCheckerWithDescList(out);
 }
 
-void ento::printEnabledCheckerList(raw_ostream &out,
-                                   ArrayRef<std::string> plugins,
-                                   AnalyzerOptions &anopts,
-                                   DiagnosticsEngine &diags,
-                                   const LangOptions &langOpts) {
+void ento::printEnabledCheckerList(raw_ostream &out, CompilerInstance &CI) {
   out << "OVERVIEW: Clang Static Analyzer Enabled Checkers List\n\n";
 
-  CheckerRegistry(plugins, diags, anopts, langOpts)
-      .printEnabledCheckerList(out);
+  auto CheckerMgr = std::make_unique<CheckerManager>(
+      *CI.getAnalyzerOpts(), CI.getLangOpts(), CI.getDiagnostics(),
+      CI.getFrontendOpts().Plugins);
+
+  CheckerMgr->getCheckerRegistry().printEnabledCheckerList(out);
 }
 
-void ento::printCheckerConfigList(raw_ostream &OS,
-                                  ArrayRef<std::string> plugins,
-                                  AnalyzerOptions &opts,
-                                  DiagnosticsEngine &diags,
-                                  const LangOptions &LangOpts) {
-  CheckerRegistry(plugins, diags, opts, LangOpts)
-      .printCheckerOptionList(OS);
+void ento::printCheckerConfigList(raw_ostream &out, CompilerInstance &CI) {
+
+  auto CheckerMgr = std::make_unique<CheckerManager>(
+      *CI.getAnalyzerOpts(), CI.getLangOpts(), CI.getDiagnostics(),
+      CI.getFrontendOpts().Plugins);
+
+  CheckerMgr->getCheckerRegistry().printCheckerOptionList(out);
 }
 
 void ento::printAnalyzerConfigList(raw_ostream &out) {
Index: clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
+++ clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
@@ -32,7 +32,6 @@
 #include "clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
-#include "clang/StaticAnalyzer/Frontend/CheckerRegistration.h"
 #include "llvm/ADT/PostOrderIterator.h"
 #include "llvm/ADT/Statistic.h"
 #include "llvm/Support/FileSystem.h"
@@ -333,8 +332,8 @@
 
   void Initialize(ASTContext &Context) override {
     Ctx = &Context;
-    checkerMgr = createCheckerManager(
-        *Ctx, *Opts, Plugins, CheckerRegistrationFns, PP.getDiagnostics());
+    checkerMgr = std::make_unique<CheckerManager>(*Ctx, *Opts, Plugins,
+                                                  CheckerRegistrationFns);
 
     Mgr = std::make_unique<AnalysisManager>(*Ctx, PP, PathConsumers,
                                             CreateStoreMgr, CreateConstraintMgr,
Index: clang/lib/StaticAnalyzer/Core/CheckerManager.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Core/CheckerManager.cpp
+++ clang/lib/StaticAnalyzer/Core/CheckerManager.cpp
@@ -63,10 +63,9 @@
 void CheckerManager::reportInvalidCheckerOptionValue(
     const CheckerBase *C, StringRef OptionName, StringRef ExpectedValueDesc) {
 
-  Context.getDiagnostics()
-      .Report(diag::err_analyzer_checker_option_invalid_input)
-          << (llvm::Twine() + C->getTagDescription() + ":" + OptionName).str()
-          << ExpectedValueDesc;
+  getDiagnostics().Report(diag::err_analyzer_checker_option_invalid_input)
+      << (llvm::Twine() + C->getTagDescription() + ":" + OptionName).str()
+      << ExpectedValueDesc;
 }
 
 //===----------------------------------------------------------------------===//
Index: clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
===================================================================
--- clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
+++ clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
@@ -23,12 +23,14 @@
 #include "clang/Frontend/Utils.h"
 #include "clang/FrontendTool/Utils.h"
 #include "clang/Rewrite/Frontend/FrontendActions.h"
+#include "clang/StaticAnalyzer/Frontend/AnalyzerHelpFlags.h"
 #include "clang/StaticAnalyzer/Frontend/FrontendActions.h"
 #include "llvm/Option/OptTable.h"
 #include "llvm/Option/Option.h"
 #include "llvm/Support/BuryPointer.h"
 #include "llvm/Support/DynamicLibrary.h"
 #include "llvm/Support/ErrorHandling.h"
+#include <memory>
 using namespace clang;
 using namespace llvm::opt;
 
@@ -243,35 +245,24 @@
   // These should happen AFTER plugins have been loaded!
 
   AnalyzerOptions &AnOpts = *Clang->getAnalyzerOpts();
+
   // Honor -analyzer-checker-help and -analyzer-checker-help-hidden.
   if (AnOpts.ShowCheckerHelp || AnOpts.ShowCheckerHelpAlpha ||
       AnOpts.ShowCheckerHelpDeveloper) {
-    ento::printCheckerHelp(llvm::outs(),
-                           Clang->getFrontendOpts().Plugins,
-                           AnOpts,
-                           Clang->getDiagnostics(),
-                           Clang->getLangOpts());
+    ento::printCheckerHelp(llvm::outs(), *Clang);
     return true;
   }
 
   // Honor -analyzer-checker-option-help.
   if (AnOpts.ShowCheckerOptionList || AnOpts.ShowCheckerOptionAlphaList ||
       AnOpts.ShowCheckerOptionDeveloperList) {
-    ento::printCheckerConfigList(llvm::outs(),
-                                 Clang->getFrontendOpts().Plugins,
-                                 *Clang->getAnalyzerOpts(),
-                                 Clang->getDiagnostics(),
-                                 Clang->getLangOpts());
+    ento::printCheckerConfigList(llvm::outs(), *Clang);
     return true;
   }
 
   // Honor -analyzer-list-enabled-checkers.
   if (AnOpts.ShowEnabledCheckerList) {
-    ento::printEnabledCheckerList(llvm::outs(),
-                                  Clang->getFrontendOpts().Plugins,
-                                  AnOpts,
-                                  Clang->getDiagnostics(),
-                                  Clang->getLangOpts());
+    ento::printEnabledCheckerList(llvm::outs(), *Clang);
     return true;
   }
 
Index: clang/include/clang/StaticAnalyzer/Frontend/FrontendActions.h
===================================================================
--- clang/include/clang/StaticAnalyzer/Frontend/FrontendActions.h
+++ clang/include/clang/StaticAnalyzer/Frontend/FrontendActions.h
@@ -51,22 +51,7 @@
   llvm::StringMap<Stmt *> &Bodies;
 };
 
-void printCheckerHelp(raw_ostream &OS,
-                      ArrayRef<std::string> plugins,
-                      AnalyzerOptions &opts,
-                      DiagnosticsEngine &diags,
-                      const LangOptions &LangOpts);
-void printEnabledCheckerList(raw_ostream &OS, ArrayRef<std::string> plugins,
-                             AnalyzerOptions &opts,
-                             DiagnosticsEngine &diags,
-                             const LangOptions &LangOpts);
-void printAnalyzerConfigList(raw_ostream &OS);
-void printCheckerConfigList(raw_ostream &OS, ArrayRef<std::string> plugins,
-                            AnalyzerOptions &opts,
-                            DiagnosticsEngine &diags,
-                            const LangOptions &LangOpts);
-
-} // end GR namespace
+} // namespace ento
 
 } // end namespace clang
 
Index: clang/include/clang/StaticAnalyzer/Frontend/CheckerRegistry.h
===================================================================
--- clang/include/clang/StaticAnalyzer/Frontend/CheckerRegistry.h
+++ clang/include/clang/StaticAnalyzer/Frontend/CheckerRegistry.h
@@ -10,7 +10,7 @@
 #define LLVM_CLANG_STATICANALYZER_CORE_CHECKERREGISTRY_H
 
 #include "clang/Basic/LLVM.h"
-#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "llvm/ADT/SetVector.h"
 #include "llvm/ADT/StringMap.h"
 #include "llvm/ADT/StringRef.h"
 #include <cstddef>
@@ -73,6 +73,8 @@
 
 namespace ento {
 
+class CheckerManager;
+
 /// Manages a set of available checkers for running a static analysis.
 /// The checkers are organized into packages by full name, where including
 /// a package will recursively include all subpackages and checkers within it.
@@ -82,10 +84,15 @@
 class CheckerRegistry {
 public:
   CheckerRegistry(ArrayRef<std::string> plugins, DiagnosticsEngine &diags,
-                  AnalyzerOptions &AnOpts, const LangOptions &LangOpts,
+                  AnalyzerOptions &AnOpts,
                   ArrayRef<std::function<void(CheckerRegistry &)>>
                       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 &);
@@ -205,11 +212,11 @@
   using PackageInfoList = llvm::SmallVector<PackageInfo, 0>;
 
 private:
-  template <typename T> static void initializeManager(CheckerManager &mgr) {
-    mgr.registerChecker<T>();
+  template <typename MGR, typename T> static void initializeManager(MGR &mgr) {
+    mgr.template registerChecker<T>();
   }
 
-  template <typename T> static bool returnTrue(const LangOptions &LO) {
+  template <typename T> static bool returnTrue(const LangOptions &) {
     return true;
   }
 
@@ -227,9 +234,8 @@
                   bool IsHidden = false) {
     // Avoid MSVC's Compiler Error C2276:
     // http://msdn.microsoft.com/en-us/library/850cstw1(v=VS.80).aspx
-    addChecker(&CheckerRegistry::initializeManager<T>,
-               &CheckerRegistry::returnTrue<T>, FullName, Desc, DocsUri,
-               IsHidden);
+    addChecker(&initializeManager<CheckerManager, T>, &returnTrue<T>, FullName,
+               Desc, DocsUri, IsHidden);
   }
 
   /// Makes the checker with the full name \p fullName depends on the checker
@@ -265,7 +271,7 @@
   void addPackageOption(StringRef OptionType, StringRef PackageFullName,
                         StringRef OptionName, StringRef DefaultValStr,
                         StringRef Description, StringRef DevelopmentStatus,
-                         bool IsHidden = false);
+                        bool IsHidden = false);
 
   // FIXME: This *really* should be added to the frontend flag descriptions.
   /// Initializes a CheckerManager by calling the initialization functions for
@@ -285,11 +291,6 @@
   void printCheckerOptionList(raw_ostream &Out) const;
 
 private:
-  /// Collect all enabled checkers. The returned container preserves the order
-  /// of insertion, as dependencies have to be enabled before the checkers that
-  /// depend on them.
-  CheckerInfoSet getEnabledCheckers() const;
-
   /// 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".
@@ -316,7 +317,7 @@
 
   DiagnosticsEngine &Diags;
   AnalyzerOptions &AnOpts;
-  const LangOptions &LangOpts;
+  CheckerInfoSet EnabledCheckers;
 };
 
 } // namespace ento
Index: clang/include/clang/StaticAnalyzer/Frontend/CheckerRegistration.h
===================================================================
--- clang/include/clang/StaticAnalyzer/Frontend/CheckerRegistration.h
+++ /dev/null
@@ -1,38 +0,0 @@
-//===-- CheckerRegistration.h - Checker Registration Function ---*- 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
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_STATICANALYZER_FRONTEND_CHECKERREGISTRATION_H
-#define LLVM_CLANG_STATICANALYZER_FRONTEND_CHECKERREGISTRATION_H
-
-#include "clang/AST/ASTContext.h"
-#include "clang/Basic/LLVM.h"
-#include <functional>
-#include <memory>
-#include <string>
-
-namespace clang {
-  class AnalyzerOptions;
-  class LangOptions;
-  class DiagnosticsEngine;
-
-namespace ento {
-  class CheckerManager;
-  class CheckerRegistry;
-
-  std::unique_ptr<CheckerManager> createCheckerManager(
-      ASTContext &context,
-      AnalyzerOptions &opts,
-      ArrayRef<std::string> plugins,
-      ArrayRef<std::function<void(CheckerRegistry &)>> checkerRegistrationFns,
-      DiagnosticsEngine &diags);
-
-} // end ento namespace
-
-} // end namespace clang
-
-#endif
Index: clang/include/clang/StaticAnalyzer/Frontend/AnalysisConsumer.h
===================================================================
--- clang/include/clang/StaticAnalyzer/Frontend/AnalysisConsumer.h
+++ clang/include/clang/StaticAnalyzer/Frontend/AnalysisConsumer.h
@@ -55,7 +55,7 @@
 std::unique_ptr<AnalysisASTConsumer>
 CreateAnalysisConsumer(CompilerInstance &CI);
 
-} // end GR namespace
+} // namespace ento
 
 } // end clang namespace
 
Index: clang/include/clang/StaticAnalyzer/Core/CheckerManager.h
===================================================================
--- clang/include/clang/StaticAnalyzer/Core/CheckerManager.h
+++ clang/include/clang/StaticAnalyzer/Core/CheckerManager.h
@@ -14,9 +14,11 @@
 #define LLVM_CLANG_STATICANALYZER_CORE_CHECKERMANAGER_H
 
 #include "clang/Analysis/ProgramPoint.h"
+#include "clang/Basic/Diagnostic.h"
 #include "clang/Basic/LangOptions.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/Store.h"
+#include "clang/StaticAnalyzer/Frontend/CheckerRegistry.h"
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/SmallVector.h"
@@ -40,7 +42,6 @@
 class CallEvent;
 class CheckerBase;
 class CheckerContext;
-class CheckerRegistry;
 class ExplodedGraph;
 class ExplodedNode;
 class ExplodedNodeSet;
@@ -121,14 +122,42 @@
 };
 
 class CheckerManager {
-  ASTContext &Context;
+  ASTContext *Context;
   const LangOptions LangOpts;
   AnalyzerOptions &AOptions;
   CheckerNameRef CurrentCheckerName;
+  DiagnosticsEngine &Diags;
+  CheckerRegistry Registry;
 
 public:
+  CheckerManager(
+      ASTContext &Context, AnalyzerOptions &AOptions,
+      ArrayRef<std::string> plugins,
+      ArrayRef<std::function<void(CheckerRegistry &)>> checkerRegistrationFns)
+      : Context(&Context), LangOpts(Context.getLangOpts()), AOptions(AOptions),
+        Diags(Context.getDiagnostics()),
+        Registry(plugins, Context.getDiagnostics(), AOptions,
+                 checkerRegistrationFns) {
+    Registry.initializeRegistry(*this);
+    Registry.initializeManager(*this);
+    finishedCheckerRegistration();
+  }
+
+  /// Constructs a CheckerManager that ignores all non TblGen-generated
+  /// checkers. Useful for unit testing, unless the checker infrastructure
+  /// itself is tested.
   CheckerManager(ASTContext &Context, AnalyzerOptions &AOptions)
-      : Context(Context), LangOpts(Context.getLangOpts()), AOptions(AOptions) {}
+      : CheckerManager(Context, AOptions, {}, {}) {}
+
+  /// 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.
+  CheckerManager(AnalyzerOptions &AOptions, const LangOptions &LangOpts,
+                 DiagnosticsEngine &Diags, ArrayRef<std::string> plugins)
+      : LangOpts(LangOpts), AOptions(AOptions), Diags(Diags),
+        Registry(plugins, Diags, AOptions) {
+    Registry.initializeRegistry(*this);
+  }
 
   ~CheckerManager();
 
@@ -141,7 +170,12 @@
 
   const LangOptions &getLangOpts() const { return LangOpts; }
   AnalyzerOptions &getAnalyzerOptions() { return AOptions; }
-  ASTContext &getASTContext() { return Context; }
+  ASTContext &getASTContext() {
+    assert(Context);
+    return *Context;
+  }
+  const CheckerRegistry &getCheckerRegistry() { return Registry; }
+  DiagnosticsEngine &getDiagnostics() { return Diags; }
 
   /// Emits an error through a DiagnosticsEngine about an invalid user supplied
   /// checker option value.
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to