https://github.com/ziqingluo-90 updated 
https://github.com/llvm/llvm-project/pull/206600

>From f6a06234bc653a58a648821989592e6255944c72 Mon Sep 17 00:00:00 2001
From: Ziqing Luo <[email protected]>
Date: Mon, 29 Jun 2026 15:00:54 -0700
Subject: [PATCH 1/2] [SSAF][Extractor][Do not merge] Extract operator
 new/delete overload entities that shall retain their types

This commit creates an extractor for operator new/delete overloads.

Overloads of operator new shall retain their void* return type,
regardless of whether they are propagated by unsafe buffers. The same
applies to the parameters of operator delete overloads.

Therefore, clang-reforge eventually need this information.

rdar://179151541
---
 .../OperatorNewDeletePointers.h               |  56 ++++
 .../BuiltinAnchorSources.def                  |   1 +
 .../Analyses/CMakeLists.txt                   |   1 +
 .../OperatorNewDeletePointersExtractor.cpp    | 119 ++++++++
 .../Analyses/SSAFAnalysesCommon.h             |  14 +-
 ...OperatorNewDeletePointersExtractorTest.cpp | 260 ++++++++++++++++++
 .../ScalableStaticAnalysis/CMakeLists.txt     |   1 +
 7 files changed, 447 insertions(+), 5 deletions(-)
 create mode 100644 
clang/include/clang/ScalableStaticAnalysis/Analyses/OperatorNewDelete/OperatorNewDeletePointers.h
 create mode 100644 
clang/lib/ScalableStaticAnalysis/Analyses/OperatorNewDelete/OperatorNewDeletePointersExtractor.cpp
 create mode 100644 
clang/unittests/ScalableStaticAnalysis/Analyses/OperatorNewDelete/OperatorNewDeletePointersExtractorTest.cpp

diff --git 
a/clang/include/clang/ScalableStaticAnalysis/Analyses/OperatorNewDelete/OperatorNewDeletePointers.h
 
b/clang/include/clang/ScalableStaticAnalysis/Analyses/OperatorNewDelete/OperatorNewDeletePointers.h
new file mode 100644
index 0000000000000..8c030e2a582ba
--- /dev/null
+++ 
b/clang/include/clang/ScalableStaticAnalysis/Analyses/OperatorNewDelete/OperatorNewDeletePointers.h
@@ -0,0 +1,56 @@
+//===- OperatorNewDeletePointers.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
+//
+//===----------------------------------------------------------------------===//
+//
+// Declares data structures for analysis that identifies pointer entities in
+// operator new/delete overloads that must have a 'void*' type
+//
+//===----------------------------------------------------------------------===//
+#ifndef 
LLVM_CLANG_SCALABLESTATICANALYSIS_ANALYSES_OPERATORNEWDELETE_OPERATORNEWDELETEPOINTERS_H
+#define 
LLVM_CLANG_SCALABLESTATICANALYSIS_ANALYSES_OPERATORNEWDELETE_OPERATORNEWDELETEPOINTERS_H
+
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityId.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/SummaryName.h"
+#include "clang/ScalableStaticAnalysis/Core/TUSummary/EntitySummary.h"
+#include "llvm/ADT/StringRef.h"
+#include <set>
+
+namespace clang::ssaf {
+
+/// OperatorNewDeletePointersEntitySummary collects the following entities in a
+/// contributor:
+///  - return entities of operator new overloads;
+///  - the parameter (optionally the 2nd)  of operator new overloads
+///    representing the pointer to a memory area to initialize the object at;
+///  - the first parameter of operator delete overloads representing the 
pointer
+///    to a memory block to deallocate or a null pointer;
+///  - the parameter (optionally the 2nd)  of operator delete overloads
+///    representing the pointer used as the placement parameter in the matching
+///    placement new.
+struct OperatorNewDeletePointersEntitySummary final : public EntitySummary {
+  static constexpr llvm::StringLiteral Name = "OperatorNewDeletePointers";
+
+  static SummaryName summaryName() { return SummaryName(Name.str()); }
+
+  SummaryName getSummaryName() const override { return summaryName(); }
+
+  std::set<EntityId> Entities;
+
+  bool operator==(const OperatorNewDeletePointersEntitySummary &Other) const {
+    return Entities == Other.Entities;
+  }
+
+  bool operator==(const std::set<EntityId> &OtherEntities) const {
+    return Entities == OtherEntities;
+  }
+
+  bool empty() const { return Entities.empty(); }
+};
+
+} // namespace clang::ssaf
+
+#endif // 
LLVM_CLANG_SCALABLESTATICANALYSIS_ANALYSES_OPERATORNEWDELETE_OPERATORNEWDELETEPOINTERS_H
diff --git 
a/clang/include/clang/ScalableStaticAnalysis/BuiltinAnchorSources.def 
b/clang/include/clang/ScalableStaticAnalysis/BuiltinAnchorSources.def
index ba4944ea984cb..57b70f37cf61d 100644
--- a/clang/include/clang/ScalableStaticAnalysis/BuiltinAnchorSources.def
+++ b/clang/include/clang/ScalableStaticAnalysis/BuiltinAnchorSources.def
@@ -20,6 +20,7 @@ ANCHOR(AnalysisRegistryAnchorSource)
 ANCHOR(CallGraphExtractorAnchorSource)
 ANCHOR(CallGraphJSONFormatAnchorSource)
 ANCHOR(JSONFormatAnchorSource)
+ANCHOR(OperatorNewDeletePointersExtractorAnchorSource)
 ANCHOR(PointerFlowAnalysisAnchorSource)
 ANCHOR(PointerFlowExtractorAnchorSource)
 ANCHOR(PointerFlowJSONFormatAnchorSource)
diff --git a/clang/lib/ScalableStaticAnalysis/Analyses/CMakeLists.txt 
b/clang/lib/ScalableStaticAnalysis/Analyses/CMakeLists.txt
index dc72eb6d645d5..e1d14d13c2156 100644
--- a/clang/lib/ScalableStaticAnalysis/Analyses/CMakeLists.txt
+++ b/clang/lib/ScalableStaticAnalysis/Analyses/CMakeLists.txt
@@ -8,6 +8,7 @@ add_clang_library(clangScalableStaticAnalysisAnalyses
   CallGraph/CallGraphJSONFormat.cpp
   EntityPointerLevel/EntityPointerLevel.cpp
   EntityPointerLevel/EntityPointerLevelFormat.cpp
+  OperatorNewDelete/OperatorNewDeletePointersExtractor.cpp
   PointerFlow/PointerFlow.cpp
   PointerFlow/PointerFlowAnalysis.cpp
   PointerFlow/PointerFlowExtractor.cpp
diff --git 
a/clang/lib/ScalableStaticAnalysis/Analyses/OperatorNewDelete/OperatorNewDeletePointersExtractor.cpp
 
b/clang/lib/ScalableStaticAnalysis/Analyses/OperatorNewDelete/OperatorNewDeletePointersExtractor.cpp
new file mode 100644
index 0000000000000..8b08805418a8e
--- /dev/null
+++ 
b/clang/lib/ScalableStaticAnalysis/Analyses/OperatorNewDelete/OperatorNewDeletePointersExtractor.cpp
@@ -0,0 +1,119 @@
+//===- OperatorNewDeletePointersExtractor.cpp 
-----------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+//
+// Extractor implementation for extracting from user-provided operator
+// new/delete overloadings:
+//  1 return entities of operator new overloads;
+//  2 the parameter (optionally the 2nd)  of operator new overloads
+//    representing the pointer to a memory area to initialize the object at;
+//  3 the first parameter of operator delete overloads representing the pointer
+//    to a memory block to deallocate or a null pointer;
+//  4 the parameter (optionally the 2nd)  of operator delete overloads
+//    representing the pointer used as the placement parameter in the matching
+//    placement new.
+//
+//===----------------------------------------------------------------------===//
+
+#include "../SSAFAnalysesCommon.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/Type.h"
+#include "clang/Basic/OperatorKinds.h"
+#include 
"clang/ScalableStaticAnalysis/Analyses/OperatorNewDelete/OperatorNewDeletePointers.h"
+#include "clang/ScalableStaticAnalysis/Core/TUSummary/ExtractorRegistry.h"
+#include "clang/ScalableStaticAnalysis/Core/TUSummary/TUSummaryExtractor.h"
+#include "llvm/ADT/StringRef.h"
+#include <memory>
+#include <optional>
+#include <vector>
+
+using namespace clang;
+using namespace ssaf;
+
+namespace {
+
+class OperatorNewDeletePointersExtractor final : public TUSummaryExtractor {
+public:
+  using TUSummaryExtractor::TUSummaryExtractor;
+
+private:
+  void HandleTranslationUnit(ASTContext &Ctx) override;
+
+  std::unique_ptr<OperatorNewDeletePointersEntitySummary>
+  extractEntitySummary(const std::vector<const NamedDecl *> &Decls);
+};
+
+void OperatorNewDeletePointersExtractor::HandleTranslationUnit(
+    ASTContext &Ctx) {
+  extractAndAddSummaries(
+      *this, SummaryBuilder, Ctx,
+      [&](const std::vector<const NamedDecl *> &Decls) {
+        return extractEntitySummary(Decls);
+      },
+      OperatorNewDeletePointersEntitySummary::Name);
+}
+
+std::unique_ptr<OperatorNewDeletePointersEntitySummary>
+OperatorNewDeletePointersExtractor::extractEntitySummary(
+    const std::vector<const NamedDecl *> &ContributorDecls) {
+  auto Summary = std::make_unique<OperatorNewDeletePointersEntitySummary>();
+
+  for (const NamedDecl *Decl : ContributorDecls) {
+    auto Matcher = [&Summary, this](const DynTypedNode &Node) {
+      const auto *FD = Node.get<FunctionDecl>();
+
+      if (!FD)
+        return;
+
+      OverloadedOperatorKind OO = FD->getOverloadedOperator();
+
+      switch (OO) {
+      case OO_New:
+      case OO_Array_New:
+        // Extract case 1:
+        if (auto Id = addEntityForReturn(FD))
+          Summary->Entities.insert(*Id);
+        break;
+      case OO_Delete:
+      case OO_Array_Delete:
+        // Extract case 3; ignore ill-formed ones (first param not a pointer).
+        if (!FD->getNumParams() || !hasPtrOrArrType(FD->getParamDecl(0)))
+          return;
+        if (auto Id = addEntity(FD->getParamDecl(0)))
+          Summary->Entities.insert(*Id);
+        break;
+      default:
+        return;
+      };
+      // Extract case 2 & 4: only `operator new(size_t, void*)` and
+      // `operator delete(void*, void*)` are standard-defined with a void* 2nd
+      // param; for user-defined 3+ param overloads the 2nd param type is
+      // unconstrained, so we conservatively skip them.
+      if (FD->getNumParams() == 2 && hasPtrOrArrType(FD->getParamDecl(1))) {
+        if (auto Id = addEntity(FD->getParamDecl(1)))
+          Summary->Entities.insert(*Id);
+      }
+    };
+    findMatchesIn(Decl, Matcher);
+  }
+  return Summary;
+}
+
+} // namespace
+
+namespace clang::ssaf {
+// NOLINTNEXTLINE(misc-use-internal-linkage)
+volatile int OperatorNewDeletePointersExtractorAnchorSource = 0;
+} // namespace clang::ssaf
+
+static TUSummaryExtractorRegistry::Add<OperatorNewDeletePointersExtractor>
+    RegisterOperatorNewDeletePointersExtractor(
+        OperatorNewDeletePointersEntitySummary::Name,
+        "Extract pointer entities in operator new/delete overloads that must "
+        "have a 'void*' type");
diff --git a/clang/lib/ScalableStaticAnalysis/Analyses/SSAFAnalysesCommon.h 
b/clang/lib/ScalableStaticAnalysis/Analyses/SSAFAnalysesCommon.h
index 674ccfcc58313..90780a1d0cbc7 100644
--- a/clang/lib/ScalableStaticAnalysis/Analyses/SSAFAnalysesCommon.h
+++ b/clang/lib/ScalableStaticAnalysis/Analyses/SSAFAnalysesCommon.h
@@ -109,10 +109,14 @@ void extractAndAddSummaries(TUSummaryExtractor &Extractor,
       Contributors;
   findContributors(Ctx, Contributors);
   for (const auto &[Cano, Decls] : Contributors) {
+    assert(Decls.size() > 0 && !Decls[0]->isImplicit() &&
+           "guaranteed by 'findContributors'");
+    const NamedDecl *Rep = Cano->isImplicit() ? Decls[0] : Cano;
+
     // Templates are skipped, but their instantiations are handled. The idea
     // is that we can conclude facts about a template through all of its
     // instantiations.
-    if (Cano->isTemplated())
+    if (Rep->isTemplated())
       continue;
 
     auto Summary = ExtractFn(Decls);
@@ -120,13 +124,13 @@ void extractAndAddSummaries(TUSummaryExtractor &Extractor,
     if (Summary->empty())
       continue;
 
-    if (auto Id = Extractor.addEntity(Cano)) {
+    if (auto Id = Extractor.addEntity(Rep)) {
       if (!Builder.addSummary(*Id, std::move(Summary)).second)
         logWarningFromError(makeErrAtNode(
-            Ctx, Cano, "dropping duplicate %s summary for entity %s",
-            ExtractorName, Cano->getNameAsString().c_str()));
+            Ctx, Rep, "dropping duplicate %s summary for entity %s",
+            ExtractorName, Rep->getNameAsString().c_str()));
     } else
-      logWarningFromError(makeEntityNameErr(Ctx, Cano));
+      logWarningFromError(makeEntityNameErr(Ctx, Rep));
   }
 }
 
diff --git 
a/clang/unittests/ScalableStaticAnalysis/Analyses/OperatorNewDelete/OperatorNewDeletePointersExtractorTest.cpp
 
b/clang/unittests/ScalableStaticAnalysis/Analyses/OperatorNewDelete/OperatorNewDeletePointersExtractorTest.cpp
new file mode 100644
index 0000000000000..5e1b3d9c720d0
--- /dev/null
+++ 
b/clang/unittests/ScalableStaticAnalysis/Analyses/OperatorNewDelete/OperatorNewDeletePointersExtractorTest.cpp
@@ -0,0 +1,260 @@
+//===- OperatorNewDeletePointersExtractorTest.cpp 
-------------------------===//
+//
+// 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 "FindDecl.h"
+#include "TestFixture.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Decl.h"
+#include "clang/Frontend/ASTUnit.h"
+#include "clang/Frontend/SSAFOptions.h"
+#include 
"clang/ScalableStaticAnalysis/Analyses/OperatorNewDelete/OperatorNewDeletePointers.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityId.h"
+#include "clang/ScalableStaticAnalysis/Core/TUSummary/ExtractorRegistry.h"
+#include "clang/ScalableStaticAnalysis/Core/TUSummary/TUSummary.h"
+#include "clang/ScalableStaticAnalysis/Core/TUSummary/TUSummaryBuilder.h"
+#include "clang/ScalableStaticAnalysis/Core/TUSummary/TUSummaryExtractor.h"
+#include "clang/Tooling/Tooling.h"
+#include "gtest/gtest.h"
+#include <memory>
+#include <optional>
+
+using namespace clang;
+using namespace ssaf;
+
+namespace {
+
+/// Look up the \p SummaryT entity summary for the contributor named
+/// \p ContributorName.
+///
+/// \tparam SummaryT   The concrete EntitySummary subtype to return.
+/// \tparam ContributorT  The NamedDecl subtype to search for (defaults to
+///                    FunctionDecl).
+/// \tparam TUSummaryDataT  The type of the TUSummary data map, deduced from
+///                    the \p TUSummaryData argument.
+///
+/// Returns null without emitting a failure when no summary was recorded for
+/// the entity — that is a valid outcome in tests that assert absence.
+/// Emits ADD_FAILURE and returns null when the decl or its EntityId cannot
+/// be resolved, as those indicate test-infrastructure errors.
+template <typename SummaryT, typename ContributorT = FunctionDecl,
+          typename TUSummaryDataT>
+const SummaryT *getEntitySummary(llvm::StringRef ContributorName,
+                                 ASTContext &Ctx, TUSummaryExtractor 
&Extractor,
+                                 const TUSummaryDataT &TUSummaryData) {
+  const ContributorT *D = findDeclByName<ContributorT>(ContributorName, Ctx);
+
+  if (!D) {
+    ADD_FAILURE() << "failed to find decl '" << ContributorName << "'";
+    return nullptr;
+  }
+
+  std::optional<EntityId> Id = Extractor.addEntity(D);
+
+  if (!Id) {
+    ADD_FAILURE() << "failed to get EntityId for '" << ContributorName << "'";
+    return nullptr;
+  }
+  auto SumIt = TUSummaryData.find(SummaryT::summaryName());
+
+  if (SumIt == TUSummaryData.end())
+    return nullptr;
+
+  auto EntIt = SumIt->second.find(*Id);
+
+  if (EntIt == SumIt->second.end())
+    return nullptr;
+  return static_cast<const SummaryT *>(EntIt->second.get());
+}
+
+class OperatorNewDeletePointersExtractorTest : public ssaf::TestFixture {
+protected:
+  SSAFOptions Opts;
+  TUSummary TUSum;
+  TUSummaryBuilder Builder;
+  std::unique_ptr<TUSummaryExtractor> Extractor;
+  std::unique_ptr<ASTUnit> AST;
+
+  OperatorNewDeletePointersExtractorTest()
+      : TUSum(llvm::Triple("arm64-apple-macosx"),
+              BuildNamespace(BuildNamespaceKind::CompilationUnit, "Mock.cpp")),
+        Builder(TUSum, Opts), Extractor(nullptr) {}
+
+  bool setUpTest(llvm::StringRef Code) {
+    AST = tooling::buildASTFromCodeWithArgs(Code, {"-std=c++20"});
+    if (!AST) {
+      ADD_FAILURE() << "failed to build AST";
+      return false;
+    }
+    for (auto &E : TUSummaryExtractorRegistry::entries()) {
+      if (E.getName() == OperatorNewDeletePointersEntitySummary::Name) {
+        Extractor = E.instantiate(Builder);
+        break;
+      }
+    }
+    if (!Extractor) {
+      ADD_FAILURE() << "failed to find OperatorNewDeletePointersExtractor";
+      return false;
+    }
+    Extractor->HandleTranslationUnit(AST->getASTContext());
+    return true;
+  }
+
+  const OperatorNewDeletePointersEntitySummary *
+  getEntitySummary(llvm::StringRef FnName) {
+    return ::getEntitySummary<OperatorNewDeletePointersEntitySummary>(
+        FnName, AST->getASTContext(), *Extractor, getData(TUSum));
+  }
+
+  std::optional<EntityId> getEntityId(llvm::StringRef Name) {
+    if (const auto *D = findDeclByName(Name, AST->getASTContext()))
+      return Extractor->addEntity(D);
+    return std::nullopt;
+  }
+
+  std::optional<EntityId> getEntityIdForReturn(llvm::StringRef FnName) {
+    if (const FunctionDecl *FD = findFnByName(FnName, AST->getASTContext()))
+      return Extractor->addEntityForReturn(FD);
+    return std::nullopt;
+  }
+};
+
+//===----------------------------------------------------------------------===//
+// Registration sanity
+//===----------------------------------------------------------------------===//
+
+TEST(OperatorNewDeletePointersExtractorRegistration, ExtractorRegistered) {
+  EXPECT_TRUE(isTUSummaryExtractorRegistered(
+      OperatorNewDeletePointersEntitySummary::Name));
+}
+
+//===----------------------------------------------------------------------===//
+// Extractor cases
+//===----------------------------------------------------------------------===//
+
+TEST_F(OperatorNewDeletePointersExtractorTest, FreeOperatorDelete) {
+  ASSERT_TRUE(setUpTest(R"cpp(
+    void operator delete(void *ptr) noexcept;
+    void operator delete(void *ptr) noexcept { (void)ptr; }
+  )cpp"));
+
+  const auto *S = getEntitySummary("operator delete");
+
+  ASSERT_TRUE(S);
+
+  auto PtrId = getEntityId("ptr");
+
+  ASSERT_TRUE(PtrId);
+
+  EXPECT_EQ(*S, std::set{*PtrId});
+}
+
+TEST_F(OperatorNewDeletePointersExtractorTest, MemberOperatorDelete) {
+  ASSERT_TRUE(setUpTest(R"cpp(
+    class T {
+    public:
+      void operator delete(void *p) noexcept { (void)p; }
+    };
+  )cpp"));
+
+  const auto *S = getEntitySummary("operator delete");
+
+  ASSERT_TRUE(S);
+
+  auto PId = getEntityId("p");
+  ASSERT_TRUE(PId);
+
+  EXPECT_EQ(*S, std::set{*PId});
+}
+
+TEST_F(OperatorNewDeletePointersExtractorTest, OperatorDeleteArray) {
+  ASSERT_TRUE(setUpTest(R"cpp(
+    void operator delete[](void *p) noexcept;
+    void operator delete[](void *p) noexcept { (void)p; }
+  )cpp"));
+
+  const auto *S = getEntitySummary("operator delete[]");
+
+  ASSERT_TRUE(S);
+
+  auto PId = getEntityId("p");
+
+  ASSERT_TRUE(PId);
+  EXPECT_EQ(*S, std::set{*PId});
+}
+
+TEST_F(OperatorNewDeletePointersExtractorTest, OperatorNew) {
+  ASSERT_TRUE(setUpTest(R"cpp(
+    typedef unsigned long size_t;
+    void *operator new(size_t size);
+    void *operator new(size_t size) { (void)size; return nullptr; }
+  )cpp"));
+
+  const auto *S = getEntitySummary("operator new");
+
+  ASSERT_TRUE(S);
+
+  auto RetId = getEntityIdForReturn("operator new");
+
+  ASSERT_TRUE(RetId);
+  EXPECT_EQ(*S, std::set{*RetId});
+}
+
+TEST_F(OperatorNewDeletePointersExtractorTest, PlacementNew) {
+  ASSERT_TRUE(setUpTest(R"cpp(
+    typedef unsigned long size_t;
+    void *operator new(size_t size, void *placement) noexcept;
+    void *operator new(size_t size, void *placement) noexcept {
+      (void)size; return placement;
+    }
+  )cpp"));
+
+  const auto *S = getEntitySummary("operator new");
+
+  ASSERT_TRUE(S);
+
+  auto PlacementId = getEntityId("placement");
+  auto RetId = getEntityIdForReturn("operator new");
+
+  ASSERT_TRUE(PlacementId);
+  ASSERT_TRUE(RetId);
+  EXPECT_EQ(*S, (std::set{*PlacementId, *RetId}));
+}
+
+TEST_F(OperatorNewDeletePointersExtractorTest, PlacementDelete) {
+  ASSERT_TRUE(setUpTest(R"cpp(
+    void operator delete(void *ptr, void *placement) noexcept;
+    void operator delete(void *ptr, void *placement) noexcept {
+      (void)ptr; (void)placement;
+    }
+  )cpp"));
+
+  const auto *S = getEntitySummary("operator delete");
+
+  ASSERT_TRUE(S);
+
+  auto PtrId = getEntityId("ptr");
+  auto PlacementId = getEntityId("placement");
+
+  ASSERT_TRUE(PtrId);
+  ASSERT_TRUE(PlacementId);
+  EXPECT_EQ(*S, (std::set{*PtrId, *PlacementId}));
+}
+
+TEST_F(OperatorNewDeletePointersExtractorTest, NoOperatorNewOrDeleteSummary) {
+  ASSERT_TRUE(setUpTest(R"cpp(
+    class T { int x; };
+  )cpp"));
+
+  auto &TUData = getData(TUSum);
+  auto TUSummariesIter =
+      TUData.find(OperatorNewDeletePointersEntitySummary::summaryName());
+
+  ASSERT_EQ(TUSummariesIter, TUData.end());
+}
+
+} // namespace
diff --git a/clang/unittests/ScalableStaticAnalysis/CMakeLists.txt 
b/clang/unittests/ScalableStaticAnalysis/CMakeLists.txt
index 387f03dc76fc6..528840804bdd9 100644
--- a/clang/unittests/ScalableStaticAnalysis/CMakeLists.txt
+++ b/clang/unittests/ScalableStaticAnalysis/CMakeLists.txt
@@ -2,6 +2,7 @@ add_distinct_clang_unittest(ClangScalableAnalysisTests
   Analyses/PointerFlow/PointerFlowTest.cpp
   Analyses/PointerFlow/PointerFlowWPATest.cpp
   Analyses/CallGraph/CallGraphExtractorTest.cpp
+  Analyses/OperatorNewDelete/OperatorNewDeletePointersExtractorTest.cpp
   Analyses/UnsafeBufferUsage/UnsafeBufferUsageTest.cpp
   Analyses/UnsafeBufferUsage/UnsafeBufferUsageWPATest.cpp
   ASTEntityMappingTest.cpp

>From 0b7062ec57739f7e8b7442df10c91e7382e9dead Mon Sep 17 00:00:00 2001
From: Ziqing Luo <[email protected]>
Date: Mon, 29 Jun 2026 17:49:33 -0700
Subject: [PATCH 2/2] fix build issue

---
 .../lib/ScalableStaticAnalysis/Analyses/SSAFAnalysesCommon.h  | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/clang/lib/ScalableStaticAnalysis/Analyses/SSAFAnalysesCommon.h 
b/clang/lib/ScalableStaticAnalysis/Analyses/SSAFAnalysesCommon.h
index 90780a1d0cbc7..ef28503d49d65 100644
--- a/clang/lib/ScalableStaticAnalysis/Analyses/SSAFAnalysesCommon.h
+++ b/clang/lib/ScalableStaticAnalysis/Analyses/SSAFAnalysesCommon.h
@@ -104,7 +104,7 @@ template <typename ExtractorFnT>
 void extractAndAddSummaries(TUSummaryExtractor &Extractor,
                             TUSummaryBuilder &Builder, ASTContext &Ctx,
                             ExtractorFnT ExtractFn,
-                            const char *ExtractorName = "") {
+                            llvm::StringRef ExtractorName = {}) {
   llvm::DenseMap<const NamedDecl *, std::vector<const NamedDecl *>>
       Contributors;
   findContributors(Ctx, Contributors);
@@ -128,7 +128,7 @@ void extractAndAddSummaries(TUSummaryExtractor &Extractor,
       if (!Builder.addSummary(*Id, std::move(Summary)).second)
         logWarningFromError(makeErrAtNode(
             Ctx, Rep, "dropping duplicate %s summary for entity %s",
-            ExtractorName, Rep->getNameAsString().c_str()));
+            ExtractorName.data(), Rep->getNameAsString().c_str()));
     } else
       logWarningFromError(makeEntityNameErr(Ctx, Rep));
   }

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to