[clang] 2aac0c4 - Reland "[analyzer][NFC] Tie CheckerRegistry to CheckerManager, allow CheckerManager to be constructed for non-analysis purposes"
Kirstóf Umann via cfe-commits
cfe-commits at lists.llvm.org
Thu Mar 26 08:16:28 PDT 2020
Author: Kristóf Umann
Date: 2020-03-26T16:12:38+01:00
New Revision: 2aac0c47aed8d1eff7ab6d858173c532b881d948
URL: https://github.com/llvm/llvm-project/commit/2aac0c47aed8d1eff7ab6d858173c532b881d948
DIFF: https://github.com/llvm/llvm-project/commit/2aac0c47aed8d1eff7ab6d858173c532b881d948.diff
LOG: Reland "[analyzer][NFC] Tie CheckerRegistry to CheckerManager, allow CheckerManager to be constructed for non-analysis purposes"
Originally commited in rG57b8a407493c34c3680e7e1e4cb82e097f43744a, but
it broke the modules bot. This is solved by putting the contructors of
the CheckerManager class to the Frontend library.
Differential Revision: https://reviews.llvm.org/D75360
Added:
clang/include/clang/StaticAnalyzer/Frontend/AnalyzerHelpFlags.h
clang/lib/StaticAnalyzer/Frontend/AnalyzerHelpFlags.cpp
clang/lib/StaticAnalyzer/Frontend/CreateCheckerManager.cpp
Modified:
clang/include/clang/StaticAnalyzer/Core/CheckerManager.h
clang/include/clang/StaticAnalyzer/Frontend/AnalysisConsumer.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/CMakeLists.txt
clang/lib/StaticAnalyzer/Frontend/CheckerRegistry.cpp
Removed:
clang/include/clang/StaticAnalyzer/Frontend/CheckerRegistration.h
clang/lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp
################################################################################
diff --git a/clang/include/clang/StaticAnalyzer/Core/CheckerManager.h b/clang/include/clang/StaticAnalyzer/Core/CheckerManager.h
index 4454d7603b27..4635ca35736a 100644
--- a/clang/include/clang/StaticAnalyzer/Core/CheckerManager.h
+++ b/clang/include/clang/StaticAnalyzer/Core/CheckerManager.h
@@ -14,6 +14,7 @@
#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"
@@ -121,14 +122,36 @@ enum class ObjCMessageVisitKind {
};
class CheckerManager {
- ASTContext &Context;
+ ASTContext *Context;
const LangOptions LangOpts;
AnalyzerOptions &AOptions;
CheckerNameRef CurrentCheckerName;
+ DiagnosticsEngine &Diags;
+ std::unique_ptr<CheckerRegistry> Registry;
public:
+ // These constructors are defined in the Frontend library, because
+ // CheckerRegistry, a crucial component of the initialization is in there.
+ // CheckerRegistry cannot be moved to the Core library, because the checker
+ // registration functions are defined in the Checkers library, and the library
+ // dependencies look like this: Core -> Checkers -> Frontend.
+
+ CheckerManager(
+ ASTContext &Context, AnalyzerOptions &AOptions,
+ ArrayRef<std::string> plugins,
+ ArrayRef<std::function<void(CheckerRegistry &)>> checkerRegistrationFns);
+
+ /// 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);
~CheckerManager();
@@ -141,7 +164,12 @@ class CheckerManager {
const LangOptions &getLangOpts() const { return LangOpts; }
AnalyzerOptions &getAnalyzerOptions() const { return AOptions; }
- ASTContext &getASTContext() const { return Context; }
+ const CheckerRegistry &getCheckerRegistry() const { return *Registry; }
+ DiagnosticsEngine &getDiagnostics() const { return Diags; }
+ ASTContext &getASTContext() const {
+ assert(Context);
+ return *Context;
+ }
/// Emits an error through a DiagnosticsEngine about an invalid user supplied
/// checker option value.
diff --git a/clang/include/clang/StaticAnalyzer/Frontend/AnalysisConsumer.h b/clang/include/clang/StaticAnalyzer/Frontend/AnalysisConsumer.h
index 2d24e6a9586b..bcc29a60ad70 100644
--- a/clang/include/clang/StaticAnalyzer/Frontend/AnalysisConsumer.h
+++ b/clang/include/clang/StaticAnalyzer/Frontend/AnalysisConsumer.h
@@ -55,7 +55,7 @@ class AnalysisASTConsumer : public ASTConsumer {
std::unique_ptr<AnalysisASTConsumer>
CreateAnalysisConsumer(CompilerInstance &CI);
-} // end GR namespace
+} // namespace ento
} // end clang namespace
diff --git a/clang/include/clang/StaticAnalyzer/Frontend/AnalyzerHelpFlags.h b/clang/include/clang/StaticAnalyzer/Frontend/AnalyzerHelpFlags.h
new file mode 100644
index 000000000000..a30c241e1350
--- /dev/null
+++ b/clang/include/clang/StaticAnalyzer/Frontend/AnalyzerHelpFlags.h
@@ -0,0 +1,30 @@
+//===-- AnalyzerHelpFlags.h - Query functions for --help flags --*- 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_ANALYZERHELPFLAGS_H
+#define LLVM_CLANG_STATICANALYZER_FRONTEND_ANALYZERHELPFLAGS_H
+
+namespace llvm {
+class raw_ostream;
+} // namespace llvm
+
+namespace clang {
+
+class CompilerInstance;
+
+namespace ento {
+
+void printCheckerHelp(llvm::raw_ostream &OS, CompilerInstance &CI);
+void printEnabledCheckerList(llvm::raw_ostream &OS, CompilerInstance &CI);
+void printAnalyzerConfigList(llvm::raw_ostream &OS);
+void printCheckerConfigList(llvm::raw_ostream &OS, CompilerInstance &CI);
+
+} // namespace ento
+} // namespace clang
+
+#endif
diff --git a/clang/include/clang/StaticAnalyzer/Frontend/CheckerRegistration.h b/clang/include/clang/StaticAnalyzer/Frontend/CheckerRegistration.h
deleted file mode 100644
index 52a534499002..000000000000
--- a/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
diff --git a/clang/include/clang/StaticAnalyzer/Frontend/CheckerRegistry.h b/clang/include/clang/StaticAnalyzer/Frontend/CheckerRegistry.h
index 8830542f27d8..dde2409ed72c 100644
--- a/clang/include/clang/StaticAnalyzer/Frontend/CheckerRegistry.h
+++ b/clang/include/clang/StaticAnalyzer/Frontend/CheckerRegistry.h
@@ -10,7 +10,6 @@
#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"
@@ -74,6 +73,8 @@ class LangOptions;
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.
@@ -83,10 +84,15 @@ namespace ento {
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,14 +211,20 @@ class CheckerRegistry {
using PackageInfoList = llvm::SmallVector<PackageInfo, 0>;
- template <typename T> static void addToCheckerMgr(CheckerManager &mgr) {
- mgr.registerChecker<T>();
+private:
+ /// Default initialization function for checkers -- since CheckerManager
+ /// includes this header, we need to make it a template parameter, and since
+ /// the checker must be a template parameter as well, we can't put this in the
+ /// cpp file.
+ template <typename MGR, typename T> static void initializeManager(MGR &mgr) {
+ mgr.template registerChecker<T>();
}
- static bool returnTrue(const LangOptions &LO) {
+ template <typename T> static bool returnTrue(const LangOptions &) {
return true;
}
+public:
/// Adds a checker to the registry. Use this non-templated overload when your
/// checker requires custom initialization.
void addChecker(InitializationFunction Fn, ShouldRegisterFunction sfn,
@@ -221,13 +233,16 @@ class CheckerRegistry {
/// Adds a checker to the registry. Use this templated overload when your
/// checker does not require any custom initialization.
+ /// This function isn't really needed and probably causes more headaches than
+ /// the tiny convenience that it provides, but external plugins might use it,
+ /// and there isn't a strong incentive to remove it.
template <class T>
void addChecker(StringRef FullName, StringRef Desc, StringRef DocsUri,
bool IsHidden = false) {
// Avoid MSVC's Compiler Error C2276:
// http://msdn.microsoft.com/en-us/library/850cstw1(v=VS.80).aspx
- addChecker(&CheckerRegistry::addToCheckerMgr<T>,
- &CheckerRegistry::returnTrue, 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
@@ -263,7 +278,7 @@ class CheckerRegistry {
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
@@ -283,11 +298,6 @@ class CheckerRegistry {
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".
@@ -314,7 +324,7 @@ class CheckerRegistry {
DiagnosticsEngine &Diags;
AnalyzerOptions &AnOpts;
- const LangOptions &LangOpts;
+ CheckerInfoSet EnabledCheckers;
};
} // namespace ento
diff --git a/clang/include/clang/StaticAnalyzer/Frontend/FrontendActions.h b/clang/include/clang/StaticAnalyzer/Frontend/FrontendActions.h
index 878b65a1b143..6b6a395a1884 100644
--- a/clang/include/clang/StaticAnalyzer/Frontend/FrontendActions.h
+++ b/clang/include/clang/StaticAnalyzer/Frontend/FrontendActions.h
@@ -51,22 +51,7 @@ class ParseModelFileAction : public ASTFrontendAction {
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
diff --git a/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp b/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
index 70735ab2d7b2..ab7a1e32e301 100644
--- a/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
+++ b/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
@@ -23,6 +23,7 @@
#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"
@@ -243,35 +244,24 @@ bool ExecuteCompilerInvocation(CompilerInstance *Clang) {
// 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;
}
diff --git a/clang/lib/StaticAnalyzer/Core/CheckerManager.cpp b/clang/lib/StaticAnalyzer/Core/CheckerManager.cpp
index ce5e4a46d3e2..17c66cd23279 100644
--- a/clang/lib/StaticAnalyzer/Core/CheckerManager.cpp
+++ b/clang/lib/StaticAnalyzer/Core/CheckerManager.cpp
@@ -64,10 +64,9 @@ void CheckerManager::reportInvalidCheckerOptionValue(
const CheckerBase *C, StringRef OptionName,
StringRef ExpectedValueDesc) const {
- 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;
}
//===----------------------------------------------------------------------===//
@@ -903,8 +902,3 @@ CheckerManager::getCachedStmtCheckersFor(const Stmt *S, bool isPreVisit) {
Checkers.push_back(Info.CheckFn);
return Checkers;
}
-
-CheckerManager::~CheckerManager() {
- for (const auto &CheckerDtor : CheckerDtors)
- CheckerDtor();
-}
diff --git a/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp b/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
index 2e3aa0669061..6c123521e5f8 100644
--- a/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
+++ b/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
@@ -33,7 +33,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"
@@ -209,8 +208,8 @@ class AnalysisConsumer : public AnalysisASTConsumer,
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,
diff --git a/clang/lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp b/clang/lib/StaticAnalyzer/Frontend/AnalyzerHelpFlags.cpp
similarity index 69%
rename from clang/lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp
rename to clang/lib/StaticAnalyzer/Frontend/AnalyzerHelpFlags.cpp
index f4f06e32cd1d..d589e69bdf34 100644
--- a/clang/lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp
+++ b/clang/lib/StaticAnalyzer/Frontend/AnalyzerHelpFlags.cpp
@@ -10,8 +10,9 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/StaticAnalyzer/Frontend/CheckerRegistration.h"
+#include "clang/StaticAnalyzer/Frontend/AnalyzerHelpFlags.h"
#include "clang/Basic/Diagnostic.h"
+#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/FrontendDiagnostic.h"
#include "clang/StaticAnalyzer/Core/AnalyzerOptions.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
@@ -24,53 +25,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) {
diff --git a/clang/lib/StaticAnalyzer/Frontend/CMakeLists.txt b/clang/lib/StaticAnalyzer/Frontend/CMakeLists.txt
index 5e7dd8f18cd7..0c100a121f77 100644
--- a/clang/lib/StaticAnalyzer/Frontend/CMakeLists.txt
+++ b/clang/lib/StaticAnalyzer/Frontend/CMakeLists.txt
@@ -6,14 +6,16 @@ set(LLVM_LINK_COMPONENTS
add_clang_library(clangStaticAnalyzerFrontend
AnalysisConsumer.cpp
- CheckerRegistration.cpp
+ AnalyzerHelpFlags.cpp
CheckerRegistry.cpp
+ CreateCheckerManager.cpp
FrontendActions.cpp
ModelConsumer.cpp
ModelInjector.cpp
LINK_LIBS
clangAST
+ clangASTMatchers
clangAnalysis
clangBasic
clangCrossTU
diff --git a/clang/lib/StaticAnalyzer/Frontend/CheckerRegistry.cpp b/clang/lib/StaticAnalyzer/Frontend/CheckerRegistry.cpp
index 4af204474494..db09ca4e625e 100644
--- a/clang/lib/StaticAnalyzer/Frontend/CheckerRegistry.cpp
+++ b/clang/lib/StaticAnalyzer/Frontend/CheckerRegistry.cpp
@@ -109,9 +109,9 @@ CheckerRegistry::getMutableCheckersForCmdLineArg(StringRef CmdLineArg) {
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 @@ CheckerRegistry::CheckerRegistry(
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 @@ CheckerRegistry::CheckerRegistry(
: 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 @@ collectDependencies(const CheckerRegistry::CheckerInfo &checker,
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 @@ collectDependenciesImpl(const CheckerRegistry::ConstCheckerInfoList &Deps,
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 @@ void CheckerRegistry::resolveDependencies() {
CheckerIt->Dependencies.emplace_back(&*DependencyIt);
}
-
- Dependencies.clear();
}
void CheckerRegistry::addDependency(StringRef FullName, StringRef Dependency) {
@@ -378,14 +381,12 @@ void CheckerRegistry::resolveCheckerAndPackageOptions() {
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::addCheckerOption(StringRef OptionType,
}
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 @@ void CheckerRegistry::validateCheckerOptions() const {
}
}
+//===----------------------------------------------------------------------===//
+// Printing functions.
+//===----------------------------------------------------------------------===//
+
void CheckerRegistry::printCheckerWithDescList(raw_ostream &Out,
size_t MaxNameChars) const {
// FIXME: Print available packages.
@@ -556,9 +558,6 @@ void CheckerRegistry::printCheckerWithDescList(raw_ostream &Out,
}
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';
}
diff --git a/clang/lib/StaticAnalyzer/Frontend/CreateCheckerManager.cpp b/clang/lib/StaticAnalyzer/Frontend/CreateCheckerManager.cpp
new file mode 100644
index 000000000000..f93e328c47b2
--- /dev/null
+++ b/clang/lib/StaticAnalyzer/Frontend/CreateCheckerManager.cpp
@@ -0,0 +1,52 @@
+//===- CheckerManager.h - Static Analyzer Checker Manager -------*- 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
+//
+//===----------------------------------------------------------------------===//
+//
+// Defines the Static Analyzer Checker Manager.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Frontend/CheckerRegistry.h"
+#include <memory>
+
+namespace clang {
+namespace ento {
+
+CheckerManager::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(
+ std::make_unique<CheckerRegistry>(plugins, Context.getDiagnostics(),
+ AOptions, checkerRegistrationFns)) {
+ Registry->initializeRegistry(*this);
+ Registry->initializeManager(*this);
+ finishedCheckerRegistration();
+}
+
+/// 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::CheckerManager(AnalyzerOptions &AOptions,
+ const LangOptions &LangOpts,
+ DiagnosticsEngine &Diags,
+ ArrayRef<std::string> plugins)
+ : LangOpts(LangOpts), AOptions(AOptions), Diags(Diags),
+ Registry(std::make_unique<CheckerRegistry>(plugins, Diags, AOptions)) {
+ Registry->initializeRegistry(*this);
+}
+
+CheckerManager::~CheckerManager() {
+ for (const auto &CheckerDtor : CheckerDtors)
+ CheckerDtor();
+}
+
+} // namespace ento
+} // namespace clang
More information about the cfe-commits
mailing list