[clang] Bb/reland expose astcontext to checker ctors (PR #128369)

Balazs Benics via cfe-commits cfe-commits at lists.llvm.org
Sat Feb 22 12:02:00 PST 2025


https://github.com/steakhal created https://github.com/llvm/llvm-project/pull/128369

Reapply "[analyzer] Delay the checker constructions after parsing" (#128350)
    
This reverts commit db836edf47f36ed04cab919a7a2c4414f4d0d7e6, as-is.

Depends on #128368

>From 6fd30233a570ace5ccf3f04f649ddd37bd4149b2 Mon Sep 17 00:00:00 2001
From: Balazs Benics <benicsbalazs at gmail.com>
Date: Sat, 22 Feb 2025 20:50:31 +0100
Subject: [PATCH 1/2] [analyzer] Clean up slightly the messed up ownership
 model of the analyzer

Well, yes. It's not pretty.
At least after this we would have a bit more unique pointers than before.

This is for fixing the memory leak diagnosed by:
https://lab.llvm.org/buildbot/#/builders/24/builds/5580

And that caused the revert of #127409.

After these uptrs that patch can re-land finally.
---
 .../clang/Analysis/AnalysisDeclContext.h      |  2 +-
 .../Core/BugReporter/BugReporter.h            | 24 +++++++++++--------
 .../Core/PathDiagnosticConsumers.h            |  3 ++-
 .../Core/PathSensitive/AnalysisManager.h      |  7 +++---
 .../Frontend/AnalysisConsumer.h               |  3 ++-
 clang/lib/Analysis/AnalysisDeclContext.cpp    |  4 ++--
 .../StaticAnalyzer/Core/AnalysisManager.cpp   | 23 +++++++-----------
 clang/lib/StaticAnalyzer/Core/BugReporter.cpp | 22 ++++++++---------
 .../StaticAnalyzer/Core/HTMLDiagnostics.cpp   |  6 +++--
 .../StaticAnalyzer/Core/PlistDiagnostics.cpp  | 12 +++++-----
 .../StaticAnalyzer/Core/SarifDiagnostics.cpp  |  5 ++--
 .../Frontend/AnalysisConsumer.cpp             | 21 ++++++++--------
 .../BugReportInterestingnessTest.cpp          |  6 +++--
 .../StaticAnalyzer/CheckerRegistration.h      |  4 ++--
 clang/unittests/StaticAnalyzer/Reusables.h    |  7 +++---
 15 files changed, 77 insertions(+), 72 deletions(-)

diff --git a/clang/include/clang/Analysis/AnalysisDeclContext.h b/clang/include/clang/Analysis/AnalysisDeclContext.h
index a517a4e757c9f..ced4bb8595bea 100644
--- a/clang/include/clang/Analysis/AnalysisDeclContext.h
+++ b/clang/include/clang/Analysis/AnalysisDeclContext.h
@@ -451,7 +451,7 @@ class AnalysisDeclContextManager {
       bool synthesizeBodies = false, bool addStaticInitBranches = false,
       bool addCXXNewAllocator = true, bool addRichCXXConstructors = true,
       bool markElidedCXXConstructors = true, bool addVirtualBaseBranches = true,
-      CodeInjector *injector = nullptr);
+      std::unique_ptr<CodeInjector> injector = nullptr);
 
   AnalysisDeclContext *getContext(const Decl *D);
 
diff --git a/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h b/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h
index 7563d8bbd1d27..8e1d25b3eefa1 100644
--- a/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h
+++ b/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h
@@ -570,7 +570,8 @@ class BugReporterData {
 public:
   virtual ~BugReporterData() = default;
 
-  virtual ArrayRef<PathDiagnosticConsumer*> getPathDiagnosticConsumers() = 0;
+  virtual ArrayRef<std::unique_ptr<PathDiagnosticConsumer>>
+  getPathDiagnosticConsumers() = 0;
   virtual ASTContext &getASTContext() = 0;
   virtual SourceManager &getSourceManager() = 0;
   virtual AnalyzerOptions &getAnalyzerOptions() = 0;
@@ -608,7 +609,8 @@ class BugReporter {
   /// Generate and flush diagnostics for all bug reports.
   void FlushReports();
 
-  ArrayRef<PathDiagnosticConsumer*> getPathDiagnosticConsumers() {
+  ArrayRef<std::unique_ptr<PathDiagnosticConsumer>>
+  getPathDiagnosticConsumers() {
     return D.getPathDiagnosticConsumers();
   }
 
@@ -670,9 +672,10 @@ class BugReporter {
 protected:
   /// Generate the diagnostics for the given bug report.
   virtual std::unique_ptr<DiagnosticForConsumerMapTy>
-  generateDiagnosticForConsumerMap(BugReport *exampleReport,
-                                   ArrayRef<PathDiagnosticConsumer *> consumers,
-                                   ArrayRef<BugReport *> bugReports);
+  generateDiagnosticForConsumerMap(
+      BugReport *exampleReport,
+      ArrayRef<std::unique_ptr<PathDiagnosticConsumer>> consumers,
+      ArrayRef<BugReport *> bugReports);
 };
 
 /// GRBugReporter is used for generating path-sensitive reports.
@@ -684,10 +687,11 @@ class PathSensitiveBugReporter final : public BugReporter {
       SmallVectorImpl<BugReport *> &bugReports) override;
 
   /// Generate the diagnostics for the given bug report.
-  std::unique_ptr<DiagnosticForConsumerMapTy>
-  generateDiagnosticForConsumerMap(BugReport *exampleReport,
-                                   ArrayRef<PathDiagnosticConsumer *> consumers,
-                                   ArrayRef<BugReport *> bugReports) override;
+  std::unique_ptr<DiagnosticForConsumerMapTy> generateDiagnosticForConsumerMap(
+      BugReport *exampleReport,
+      ArrayRef<std::unique_ptr<PathDiagnosticConsumer>> consumers,
+      ArrayRef<BugReport *> bugReports) override;
+
 public:
   PathSensitiveBugReporter(BugReporterData& d, ExprEngine& eng)
       : BugReporter(d), Eng(eng) {}
@@ -706,7 +710,7 @@ class PathSensitiveBugReporter final : public BugReporter {
   /// Iterates through the bug reports within a single equivalence class,
   /// stops at a first non-invalidated report.
   std::unique_ptr<DiagnosticForConsumerMapTy> generatePathDiagnostics(
-      ArrayRef<PathDiagnosticConsumer *> consumers,
+      ArrayRef<std::unique_ptr<PathDiagnosticConsumer>> consumers,
       ArrayRef<PathSensitiveBugReport *> &bugReports);
 
   void emitReport(std::unique_ptr<BugReport> R) override;
diff --git a/clang/include/clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h b/clang/include/clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h
index 88a9d76f24887..9fafd6acaa2ac 100644
--- a/clang/include/clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h
+++ b/clang/include/clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h
@@ -30,7 +30,8 @@ class CrossTranslationUnitContext;
 namespace ento {
 
 class PathDiagnosticConsumer;
-typedef std::vector<PathDiagnosticConsumer*> PathDiagnosticConsumers;
+using PathDiagnosticConsumers =
+    std::vector<std::unique_ptr<PathDiagnosticConsumer>>;
 
 #define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATEFN)                    \
   void CREATEFN(PathDiagnosticConsumerOptions Diagopts,                        \
diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h
index c76e9c0326afe..e3cf1bac83ad0 100644
--- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h
+++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h
@@ -47,11 +47,11 @@ class AnalysisManager : public BugReporterData {
   AnalyzerOptions &options;
 
   AnalysisManager(ASTContext &ctx, Preprocessor &PP,
-                  const PathDiagnosticConsumers &Consumers,
+                  PathDiagnosticConsumers Consumers,
                   StoreManagerCreator storemgr,
                   ConstraintManagerCreator constraintmgr,
                   CheckerManager *checkerMgr, AnalyzerOptions &Options,
-                  CodeInjector *injector = nullptr);
+                  std::unique_ptr<CodeInjector> injector = nullptr);
 
   ~AnalysisManager() override;
 
@@ -91,7 +91,8 @@ class AnalysisManager : public BugReporterData {
     return LangOpts;
   }
 
-  ArrayRef<PathDiagnosticConsumer*> getPathDiagnosticConsumers() override {
+  ArrayRef<std::unique_ptr<PathDiagnosticConsumer>>
+  getPathDiagnosticConsumers() override {
     return PathConsumers;
   }
 
diff --git a/clang/include/clang/StaticAnalyzer/Frontend/AnalysisConsumer.h b/clang/include/clang/StaticAnalyzer/Frontend/AnalysisConsumer.h
index f3b1c1f206459..2163d66466c1c 100644
--- a/clang/include/clang/StaticAnalyzer/Frontend/AnalysisConsumer.h
+++ b/clang/include/clang/StaticAnalyzer/Frontend/AnalysisConsumer.h
@@ -29,7 +29,8 @@ class CheckerRegistry;
 
 class AnalysisASTConsumer : public ASTConsumer {
 public:
-  virtual void AddDiagnosticConsumer(PathDiagnosticConsumer *Consumer) = 0;
+  virtual void
+  AddDiagnosticConsumer(std::unique_ptr<PathDiagnosticConsumer> Consumer) = 0;
 
   /// This method allows registering statically linked custom checkers that are
   /// not a part of the Clang tree. It employs the same mechanism that is used
diff --git a/clang/lib/Analysis/AnalysisDeclContext.cpp b/clang/lib/Analysis/AnalysisDeclContext.cpp
index d3a1a993711fb..d0b663bd94580 100644
--- a/clang/lib/Analysis/AnalysisDeclContext.cpp
+++ b/clang/lib/Analysis/AnalysisDeclContext.cpp
@@ -71,8 +71,8 @@ AnalysisDeclContextManager::AnalysisDeclContextManager(
     bool addLoopExit, bool addScopes, bool synthesizeBodies,
     bool addStaticInitBranch, bool addCXXNewAllocator,
     bool addRichCXXConstructors, bool markElidedCXXConstructors,
-    bool addVirtualBaseBranches, CodeInjector *injector)
-    : Injector(injector), FunctionBodyFarm(ASTCtx, injector),
+    bool addVirtualBaseBranches, std::unique_ptr<CodeInjector> injector)
+    : Injector(std::move(injector)), FunctionBodyFarm(ASTCtx, Injector.get()),
       SynthesizeBodies(synthesizeBodies) {
   cfgBuildOptions.PruneTriviallyFalseEdges = !useUnoptimizedCFG;
   cfgBuildOptions.AddImplicitDtors = addImplicitDtors;
diff --git a/clang/lib/StaticAnalyzer/Core/AnalysisManager.cpp b/clang/lib/StaticAnalyzer/Core/AnalysisManager.cpp
index f9750db7b5017..8a16716f951b8 100644
--- a/clang/lib/StaticAnalyzer/Core/AnalysisManager.cpp
+++ b/clang/lib/StaticAnalyzer/Core/AnalysisManager.cpp
@@ -14,32 +14,28 @@ using namespace ento;
 void AnalysisManager::anchor() { }
 
 AnalysisManager::AnalysisManager(ASTContext &ASTCtx, Preprocessor &PP,
-                                 const PathDiagnosticConsumers &PDC,
+                                 PathDiagnosticConsumers PDC,
                                  StoreManagerCreator storemgr,
                                  ConstraintManagerCreator constraintmgr,
                                  CheckerManager *checkerMgr,
                                  AnalyzerOptions &Options,
-                                 CodeInjector *injector)
+                                 std::unique_ptr<CodeInjector> injector)
     : AnaCtxMgr(
           ASTCtx, Options.UnoptimizedCFG,
           Options.ShouldIncludeImplicitDtorsInCFG,
-          /*addInitializers=*/true,
-          Options.ShouldIncludeTemporaryDtorsInCFG,
+          /*addInitializers=*/true, Options.ShouldIncludeTemporaryDtorsInCFG,
           Options.ShouldIncludeLifetimeInCFG,
           // Adding LoopExit elements to the CFG is a requirement for loop
           // unrolling.
-          Options.ShouldIncludeLoopExitInCFG ||
-            Options.ShouldUnrollLoops,
-          Options.ShouldIncludeScopesInCFG,
-          Options.ShouldSynthesizeBodies,
+          Options.ShouldIncludeLoopExitInCFG || Options.ShouldUnrollLoops,
+          Options.ShouldIncludeScopesInCFG, Options.ShouldSynthesizeBodies,
           Options.ShouldConditionalizeStaticInitializers,
           /*addCXXNewAllocator=*/true,
           Options.ShouldIncludeRichConstructorsInCFG,
           Options.ShouldElideConstructors,
-          /*addVirtualBaseBranches=*/true,
-          injector),
+          /*addVirtualBaseBranches=*/true, std::move(injector)),
       Ctx(ASTCtx), PP(PP), LangOpts(ASTCtx.getLangOpts()),
-      PathConsumers(PDC), CreateStoreMgr(storemgr),
+      PathConsumers(std::move(PDC)), CreateStoreMgr(storemgr),
       CreateConstraintMgr(constraintmgr), CheckerMgr(checkerMgr),
       options(Options) {
   AnaCtxMgr.getCFGBuildOptions().setAllAlwaysAdd();
@@ -50,14 +46,11 @@ AnalysisManager::AnalysisManager(ASTContext &ASTCtx, Preprocessor &PP,
 
 AnalysisManager::~AnalysisManager() {
   FlushDiagnostics();
-  for (PathDiagnosticConsumer *Consumer : PathConsumers) {
-    delete Consumer;
-  }
 }
 
 void AnalysisManager::FlushDiagnostics() {
   PathDiagnosticConsumer::FilesMade filesMade;
-  for (PathDiagnosticConsumer *Consumer : PathConsumers) {
+  for (const auto &Consumer : PathConsumers) {
     Consumer->FlushDiagnostics(&filesMade);
   }
 }
diff --git a/clang/lib/StaticAnalyzer/Core/BugReporter.cpp b/clang/lib/StaticAnalyzer/Core/BugReporter.cpp
index 13677ed341d0c..7101b1eb2c7f5 100644
--- a/clang/lib/StaticAnalyzer/Core/BugReporter.cpp
+++ b/clang/lib/StaticAnalyzer/Core/BugReporter.cpp
@@ -2958,7 +2958,7 @@ std::optional<PathDiagnosticBuilder> PathDiagnosticBuilder::findValidReport(
 
 std::unique_ptr<DiagnosticForConsumerMapTy>
 PathSensitiveBugReporter::generatePathDiagnostics(
-    ArrayRef<PathDiagnosticConsumer *> consumers,
+    ArrayRef<std::unique_ptr<PathDiagnosticConsumer>> consumers,
     ArrayRef<PathSensitiveBugReport *> &bugReports) {
   assert(!bugReports.empty());
 
@@ -2968,9 +2968,9 @@ PathSensitiveBugReporter::generatePathDiagnostics(
       PathDiagnosticBuilder::findValidReport(bugReports, *this);
 
   if (PDB) {
-    for (PathDiagnosticConsumer *PC : consumers) {
-      if (std::unique_ptr<PathDiagnostic> PD = PDB->generate(PC)) {
-        (*Out)[PC] = std::move(PD);
+    for (const auto &PC : consumers) {
+      if (std::unique_ptr<PathDiagnostic> PD = PDB->generate(PC.get())) {
+        (*Out)[PC.get()] = std::move(PD);
       }
     }
   }
@@ -3164,7 +3164,7 @@ void BugReporter::FlushReport(BugReportEquivClass &EQ) {
       return;
   }
 
-  ArrayRef<PathDiagnosticConsumer*> Consumers = getPathDiagnosticConsumers();
+  ArrayRef Consumers = getPathDiagnosticConsumers();
   std::unique_ptr<DiagnosticForConsumerMapTy> Diagnostics =
       generateDiagnosticForConsumerMap(report, Consumers, bugReports);
 
@@ -3298,12 +3298,13 @@ findExecutedLines(const SourceManager &SM, const ExplodedNode *N) {
 
 std::unique_ptr<DiagnosticForConsumerMapTy>
 BugReporter::generateDiagnosticForConsumerMap(
-    BugReport *exampleReport, ArrayRef<PathDiagnosticConsumer *> consumers,
+    BugReport *exampleReport,
+    ArrayRef<std::unique_ptr<PathDiagnosticConsumer>> consumers,
     ArrayRef<BugReport *> bugReports) {
   auto *basicReport = cast<BasicBugReport>(exampleReport);
   auto Out = std::make_unique<DiagnosticForConsumerMapTy>();
-  for (auto *Consumer : consumers)
-    (*Out)[Consumer] =
+  for (const auto &Consumer : consumers)
+    (*Out)[Consumer.get()] =
         generateDiagnosticForBasicReport(basicReport, AnalysisEntryPoint);
   return Out;
 }
@@ -3371,11 +3372,10 @@ static void resetDiagnosticLocationToMainFile(PathDiagnostic &PD) {
   }
 }
 
-
-
 std::unique_ptr<DiagnosticForConsumerMapTy>
 PathSensitiveBugReporter::generateDiagnosticForConsumerMap(
-    BugReport *exampleReport, ArrayRef<PathDiagnosticConsumer *> consumers,
+    BugReport *exampleReport,
+    ArrayRef<std::unique_ptr<PathDiagnosticConsumer>> consumers,
     ArrayRef<BugReport *> bugReports) {
   std::vector<BasicBugReport *> BasicBugReports;
   std::vector<PathSensitiveBugReport *> PathSensitiveBugReports;
diff --git a/clang/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp b/clang/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp
index 5c0df8808c272..21d99a359ca80 100644
--- a/clang/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp
+++ b/clang/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp
@@ -193,7 +193,8 @@ void ento::createHTMLDiagnosticConsumer(
   if (OutputDir.empty())
     return;
 
-  C.push_back(new HTMLDiagnostics(std::move(DiagOpts), OutputDir, PP, true));
+  C.emplace_back(std::make_unique<HTMLDiagnostics>(std::move(DiagOpts),
+                                                   OutputDir, PP, true));
 }
 
 void ento::createHTMLSingleFileDiagnosticConsumer(
@@ -208,7 +209,8 @@ void ento::createHTMLSingleFileDiagnosticConsumer(
   if (OutputDir.empty())
     return;
 
-  C.push_back(new HTMLDiagnostics(std::move(DiagOpts), OutputDir, PP, false));
+  C.emplace_back(std::make_unique<HTMLDiagnostics>(std::move(DiagOpts),
+                                                   OutputDir, PP, false));
 }
 
 void ento::createPlistHTMLDiagnosticConsumer(
diff --git a/clang/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp b/clang/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp
index d806d970acf8d..2ab248f9aa6d9 100644
--- a/clang/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp
+++ b/clang/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp
@@ -541,9 +541,9 @@ void ento::createPlistDiagnosticConsumer(
   if (OutputFile.empty())
     return;
 
-  C.push_back(new PlistDiagnostics(DiagOpts, OutputFile, PP, CTU,
-                                   MacroExpansions,
-                                   /*supportsMultipleFiles=*/false));
+  C.push_back(std::make_unique<PlistDiagnostics>(
+      DiagOpts, OutputFile, PP, CTU, MacroExpansions,
+      /*supportsMultipleFiles=*/false));
   createTextMinimalPathDiagnosticConsumer(std::move(DiagOpts), C, OutputFile,
                                           PP, CTU, MacroExpansions);
 }
@@ -558,9 +558,9 @@ void ento::createPlistMultiFileDiagnosticConsumer(
   if (OutputFile.empty())
     return;
 
-  C.push_back(new PlistDiagnostics(DiagOpts, OutputFile, PP, CTU,
-                                   MacroExpansions,
-                                   /*supportsMultipleFiles=*/true));
+  C.push_back(std::make_unique<PlistDiagnostics>(
+      DiagOpts, OutputFile, PP, CTU, MacroExpansions,
+      /*supportsMultipleFiles=*/true));
   createTextMinimalPathDiagnosticConsumer(std::move(DiagOpts), C, OutputFile,
                                           PP, CTU, MacroExpansions);
 }
diff --git a/clang/lib/StaticAnalyzer/Core/SarifDiagnostics.cpp b/clang/lib/StaticAnalyzer/Core/SarifDiagnostics.cpp
index fab520098f13e..cae6e872a7df5 100644
--- a/clang/lib/StaticAnalyzer/Core/SarifDiagnostics.cpp
+++ b/clang/lib/StaticAnalyzer/Core/SarifDiagnostics.cpp
@@ -23,6 +23,7 @@
 #include "llvm/Support/ConvertUTF.h"
 #include "llvm/Support/JSON.h"
 #include "llvm/Support/Path.h"
+#include <memory>
 
 using namespace llvm;
 using namespace clang;
@@ -60,8 +61,8 @@ void ento::createSarifDiagnosticConsumer(
   if (Output.empty())
     return;
 
-  C.push_back(
-      new SarifDiagnostics(Output, PP.getLangOpts(), PP.getSourceManager()));
+  C.push_back(std::make_unique<SarifDiagnostics>(Output, PP.getLangOpts(),
+                                                 PP.getSourceManager()));
   createTextMinimalPathDiagnosticConsumer(std::move(DiagOpts), C, Output, PP,
                                           CTU, MacroExpansions);
 }
diff --git a/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp b/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
index 189d7d6bede8e..8a4bb35925e2c 100644
--- a/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
+++ b/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
@@ -90,7 +90,7 @@ class AnalysisConsumer : public AnalysisASTConsumer,
   const std::string OutDir;
   AnalyzerOptions &Opts;
   ArrayRef<std::string> Plugins;
-  CodeInjector *Injector;
+  std::unique_ptr<CodeInjector> Injector;
   cross_tu::CrossTranslationUnitContext CTU;
 
   /// Stores the declarations from the local translation unit.
@@ -123,10 +123,10 @@ class AnalysisConsumer : public AnalysisASTConsumer,
 
   AnalysisConsumer(CompilerInstance &CI, const std::string &outdir,
                    AnalyzerOptions &opts, ArrayRef<std::string> plugins,
-                   CodeInjector *injector)
+                   std::unique_ptr<CodeInjector> injector)
       : RecVisitorMode(0), RecVisitorBR(nullptr), Ctx(nullptr),
-        PP(CI.getPreprocessor()), OutDir(outdir), Opts(opts),
-        Plugins(plugins), Injector(injector), CTU(CI),
+        PP(CI.getPreprocessor()), OutDir(outdir), Opts(opts), Plugins(plugins),
+        Injector(std::move(injector)), CTU(CI),
         MacroExpansions(CI.getLangOpts()) {
     DigestAnalyzerOptions();
     if (Opts.AnalyzerDisplayProgress || Opts.PrintStats ||
@@ -229,9 +229,9 @@ class AnalysisConsumer : public AnalysisASTConsumer,
     checkerMgr = std::make_unique<CheckerManager>(*Ctx, Opts, PP, Plugins,
                                                   CheckerRegistrationFns);
 
-    Mgr = std::make_unique<AnalysisManager>(*Ctx, PP, PathConsumers,
-                                            CreateStoreMgr, CreateConstraintMgr,
-                                            checkerMgr.get(), Opts, Injector);
+    Mgr = std::make_unique<AnalysisManager>(
+        *Ctx, PP, std::move(PathConsumers), CreateStoreMgr, CreateConstraintMgr,
+        checkerMgr.get(), Opts, std::move(Injector));
   }
 
   /// Store the top level decls in the set to be processed later on.
@@ -342,8 +342,9 @@ class AnalysisConsumer : public AnalysisASTConsumer,
     return true;
   }
 
-  void AddDiagnosticConsumer(PathDiagnosticConsumer *Consumer) override {
-    PathConsumers.push_back(Consumer);
+  void AddDiagnosticConsumer(
+      std::unique_ptr<PathDiagnosticConsumer> Consumer) override {
+    PathConsumers.push_back(std::move(Consumer));
   }
 
   void AddCheckerRegistrationFn(std::function<void(CheckerRegistry&)> Fn) override {
@@ -794,5 +795,5 @@ ento::CreateAnalysisConsumer(CompilerInstance &CI) {
   return std::make_unique<AnalysisConsumer>(
       CI, CI.getFrontendOpts().OutputFile, analyzerOpts,
       CI.getFrontendOpts().Plugins,
-      hasModelPath ? new ModelInjector(CI) : nullptr);
+      hasModelPath ? std::make_unique<ModelInjector>(CI) : nullptr);
 }
diff --git a/clang/unittests/StaticAnalyzer/BugReportInterestingnessTest.cpp b/clang/unittests/StaticAnalyzer/BugReportInterestingnessTest.cpp
index 70a58026da95f..0ef63b049621e 100644
--- a/clang/unittests/StaticAnalyzer/BugReportInterestingnessTest.cpp
+++ b/clang/unittests/StaticAnalyzer/BugReportInterestingnessTest.cpp
@@ -19,6 +19,7 @@
 #include "clang/StaticAnalyzer/Frontend/CheckerRegistry.h"
 #include "clang/Tooling/Tooling.h"
 #include "gtest/gtest.h"
+#include <memory>
 
 using namespace clang;
 using namespace ento;
@@ -114,8 +115,9 @@ class TestAction : public ASTFrontendAction {
                                                  StringRef File) override {
     std::unique_ptr<AnalysisASTConsumer> AnalysisConsumer =
         CreateAnalysisConsumer(Compiler);
-    AnalysisConsumer->AddDiagnosticConsumer(new VerifyPathDiagnosticConsumer(
-        std::move(ExpectedDiags), Compiler.getSourceManager()));
+    AnalysisConsumer->AddDiagnosticConsumer(
+        std::make_unique<VerifyPathDiagnosticConsumer>(
+            std::move(ExpectedDiags), Compiler.getSourceManager()));
     AnalysisConsumer->AddCheckerRegistrationFn([](CheckerRegistry &Registry) {
       Registry.addChecker<InterestingnessTestChecker>("test.Interestingness",
                                                       "Description", "");
diff --git a/clang/unittests/StaticAnalyzer/CheckerRegistration.h b/clang/unittests/StaticAnalyzer/CheckerRegistration.h
index 82646167ba545..c4c6e7a9a896d 100644
--- a/clang/unittests/StaticAnalyzer/CheckerRegistration.h
+++ b/clang/unittests/StaticAnalyzer/CheckerRegistration.h
@@ -95,10 +95,10 @@ template <AddCheckerFn... Fns> class TestAction : public ASTFrontendAction {
         CreateAnalysisConsumer(Compiler);
     if (OnlyEmitWarnings)
       AnalysisConsumer->AddDiagnosticConsumer(
-          new OnlyWarningsDiagConsumer(DiagsOutput));
+          std::make_unique<OnlyWarningsDiagConsumer>(DiagsOutput));
     else
       AnalysisConsumer->AddDiagnosticConsumer(
-          new PathDiagConsumer(DiagsOutput));
+          std::make_unique<PathDiagConsumer>(DiagsOutput));
     addChecker<Fns...>(*AnalysisConsumer, Compiler.getAnalyzerOpts());
     return std::move(AnalysisConsumer);
   }
diff --git a/clang/unittests/StaticAnalyzer/Reusables.h b/clang/unittests/StaticAnalyzer/Reusables.h
index 5bd62a3e68047..367ef52414370 100644
--- a/clang/unittests/StaticAnalyzer/Reusables.h
+++ b/clang/unittests/StaticAnalyzer/Reusables.h
@@ -59,10 +59,9 @@ class ExprEngineConsumer : public ASTConsumer {
   ExprEngineConsumer(CompilerInstance &C)
       : C(C),
         ChkMgr(C.getASTContext(), C.getAnalyzerOpts(), C.getPreprocessor()),
-        CTU(C), Consumers(),
-        AMgr(C.getASTContext(), C.getPreprocessor(), Consumers,
-             CreateRegionStoreManager, CreateRangeConstraintManager, &ChkMgr,
-             C.getAnalyzerOpts()),
+        CTU(C), AMgr(C.getASTContext(), C.getPreprocessor(), {},
+                     CreateRegionStoreManager, CreateRangeConstraintManager,
+                     &ChkMgr, C.getAnalyzerOpts()),
         VisitedCallees(), FS(),
         Eng(CTU, AMgr, &VisitedCallees, &FS, ExprEngine::Inline_Regular) {}
 };

>From ea932d93a47e6747f50768fc232d2c9e9375b6da Mon Sep 17 00:00:00 2001
From: Balazs Benics <benicsbalazs at gmail.com>
Date: Sat, 22 Feb 2025 12:07:23 +0100
Subject: [PATCH 2/2] Reapply "[analyzer] Delay the checker constructions after
 parsing" (#128350)

This reverts commit db836edf47f36ed04cab919a7a2c4414f4d0d7e6.
---
 .../Checkers/UnixAPIChecker.cpp               | 61 ++++++++++---------
 .../Frontend/AnalysisConsumer.cpp             | 18 +++---
 2 files changed, 40 insertions(+), 39 deletions(-)

diff --git a/clang/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp
index da2d16ca9b5dd..10dfa73cc522d 100644
--- a/clang/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp
@@ -40,17 +40,28 @@ enum class OpenVariant {
   OpenAt
 };
 
+static std::optional<int> getCreateFlagValue(const ASTContext &Ctx,
+                                             const Preprocessor &PP) {
+  std::optional<int> MacroVal = tryExpandAsInteger("O_CREAT", PP);
+  if (MacroVal.has_value())
+    return MacroVal;
+
+  // If we failed, fall-back to known values.
+  if (Ctx.getTargetInfo().getTriple().getVendor() == llvm::Triple::Apple)
+    return {0x0200};
+  return MacroVal;
+}
+
 namespace {
 
-class UnixAPIMisuseChecker
-    : public Checker<check::PreCall, check::ASTDecl<TranslationUnitDecl>> {
+class UnixAPIMisuseChecker : public Checker<check::PreCall> {
   const BugType BT_open{this, "Improper use of 'open'", categories::UnixAPI};
   const BugType BT_getline{this, "Improper use of getdelim",
                            categories::UnixAPI};
   const BugType BT_pthreadOnce{this, "Improper use of 'pthread_once'",
                                categories::UnixAPI};
   const BugType BT_ArgumentNull{this, "NULL pointer", categories::UnixAPI};
-  mutable std::optional<uint64_t> Val_O_CREAT;
+  const std::optional<int> Val_O_CREAT;
 
   ProgramStateRef
   EnsurePtrNotNull(SVal PtrVal, const Expr *PtrExpr, CheckerContext &C,
@@ -63,6 +74,9 @@ class UnixAPIMisuseChecker
       const Expr *SizePtrExpr, CheckerContext &C, ProgramStateRef State) const;
 
 public:
+  UnixAPIMisuseChecker(const ASTContext &Ctx, const Preprocessor &PP)
+      : Val_O_CREAT(getCreateFlagValue(Ctx, PP)) {}
+
   void checkASTDecl(const TranslationUnitDecl *TU, AnalysisManager &Mgr,
                     BugReporter &BR) const;
 
@@ -134,20 +148,6 @@ ProgramStateRef UnixAPIMisuseChecker::EnsurePtrNotNull(
   return PtrNotNull;
 }
 
-void UnixAPIMisuseChecker::checkASTDecl(const TranslationUnitDecl *TU,
-                                        AnalysisManager &Mgr,
-                                        BugReporter &) const {
-  // The definition of O_CREAT is platform specific.
-  // Try to get the macro value from the preprocessor.
-  Val_O_CREAT = tryExpandAsInteger("O_CREAT", Mgr.getPreprocessor());
-  // If we failed, fall-back to known values.
-  if (!Val_O_CREAT) {
-    if (TU->getASTContext().getTargetInfo().getTriple().getVendor() ==
-        llvm::Triple::Apple)
-      Val_O_CREAT = 0x0200;
-  }
-}
-
 //===----------------------------------------------------------------------===//
 // "open" (man 2 open)
 //===----------------------------------------------------------------------===/
@@ -262,7 +262,7 @@ void UnixAPIMisuseChecker::CheckOpenVariant(CheckerContext &C,
     return;
   }
 
-  if (!Val_O_CREAT) {
+  if (!Val_O_CREAT.has_value()) {
     return;
   }
 
@@ -276,7 +276,7 @@ void UnixAPIMisuseChecker::CheckOpenVariant(CheckerContext &C,
   }
   NonLoc oflags = V.castAs<NonLoc>();
   NonLoc ocreateFlag = C.getSValBuilder()
-                           .makeIntVal(*Val_O_CREAT, oflagsEx->getType())
+                           .makeIntVal(Val_O_CREAT.value(), oflagsEx->getType())
                            .castAs<NonLoc>();
   SVal maskedFlagsUC = C.getSValBuilder().evalBinOpNN(state, BO_And,
                                                       oflags, ocreateFlag,
@@ -621,14 +621,17 @@ void UnixAPIPortabilityChecker::checkPreStmt(const CallExpr *CE,
 // Registration.
 //===----------------------------------------------------------------------===//
 
-#define REGISTER_CHECKER(CHECKERNAME)                                          \
-  void ento::register##CHECKERNAME(CheckerManager &mgr) {                      \
-    mgr.registerChecker<CHECKERNAME>();                                        \
-  }                                                                            \
-                                                                               \
-  bool ento::shouldRegister##CHECKERNAME(const CheckerManager &mgr) {          \
-    return true;                                                               \
-  }
+void ento::registerUnixAPIMisuseChecker(CheckerManager &Mgr) {
+  Mgr.registerChecker<UnixAPIMisuseChecker>(Mgr.getASTContext(),
+                                            Mgr.getPreprocessor());
+}
+bool ento::shouldRegisterUnixAPIMisuseChecker(const CheckerManager &Mgr) {
+  return true;
+}
 
-REGISTER_CHECKER(UnixAPIMisuseChecker)
-REGISTER_CHECKER(UnixAPIPortabilityChecker)
+void ento::registerUnixAPIPortabilityChecker(CheckerManager &Mgr) {
+  Mgr.registerChecker<UnixAPIPortabilityChecker>();
+}
+bool ento::shouldRegisterUnixAPIPortabilityChecker(const CheckerManager &Mgr) {
+  return true;
+}
diff --git a/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp b/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
index 8a4bb35925e2c..6f49860a41d10 100644
--- a/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
+++ b/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
@@ -224,16 +224,6 @@ class AnalysisConsumer : public AnalysisASTConsumer,
     }
   }
 
-  void Initialize(ASTContext &Context) override {
-    Ctx = &Context;
-    checkerMgr = std::make_unique<CheckerManager>(*Ctx, Opts, PP, Plugins,
-                                                  CheckerRegistrationFns);
-
-    Mgr = std::make_unique<AnalysisManager>(
-        *Ctx, PP, std::move(PathConsumers), CreateStoreMgr, CreateConstraintMgr,
-        checkerMgr.get(), Opts, std::move(Injector));
-  }
-
   /// Store the top level decls in the set to be processed later on.
   /// (Doing this pre-processing avoids deserialization of data from PCH.)
   bool HandleTopLevelDecl(DeclGroupRef D) override;
@@ -616,6 +606,14 @@ void AnalysisConsumer::HandleTranslationUnit(ASTContext &C) {
   if (Diags.hasErrorOccurred() || Diags.hasFatalErrorOccurred())
     return;
 
+  Ctx = &C;
+  checkerMgr = std::make_unique<CheckerManager>(*Ctx, Opts, PP, Plugins,
+                                                CheckerRegistrationFns);
+
+  Mgr = std::make_unique<AnalysisManager>(
+      *Ctx, PP, std::move(PathConsumers), CreateStoreMgr, CreateConstraintMgr,
+      checkerMgr.get(), Opts, std::move(Injector));
+
   // Explicitly destroy the PathDiagnosticConsumer.  This will flush its output.
   // FIXME: This should be replaced with something that doesn't rely on
   // side-effects in PathDiagnosticConsumer's destructor. This is required when



More information about the cfe-commits mailing list