Author: Oliver Hunt
Date: 2025-05-05T22:39:17-07:00
New Revision: f1985d583d283fc662c94ef39feeb58bed19ac2c

URL: 
https://github.com/llvm/llvm-project/commit/f1985d583d283fc662c94ef39feeb58bed19ac2c
DIFF: 
https://github.com/llvm/llvm-project/commit/f1985d583d283fc662c94ef39feeb58bed19ac2c.diff

LOG: [clang] Ensure type aware allocators handle transparent decl contexts 
(#138616)

We were testing the immediate DeclContext for found new and delete
operators, which is incorrect if the declarations are contained by a
transparent decl as can be induced with extern or export statements.

Added: 
    clang/test/SemaCXX/type-aware-new-delete-transparent-contexts.cpp

Modified: 
    clang/lib/Sema/SemaExprCXX.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index 235ea1529b0b8..5bfd608afba04 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -3070,10 +3070,16 @@ bool Sema::FindAllocationFunctions(
     Filter.done();
   }
 
+  auto GetRedeclContext = [](Decl *D) {
+    return D->getDeclContext()->getRedeclContext();
+  };
+
+  DeclContext *OperatorNewContext = GetRedeclContext(OperatorNew);
+
   bool FoundGlobalDelete = FoundDelete.empty();
   bool IsClassScopedTypeAwareNew =
       isTypeAwareAllocation(IAP.PassTypeIdentity) &&
-      OperatorNew->getDeclContext()->isRecord();
+      OperatorNewContext->isRecord();
   auto DiagnoseMissingTypeAwareCleanupOperator = [&](bool IsPlacementOperator) 
{
     assert(isTypeAwareAllocation(IAP.PassTypeIdentity));
     if (Diagnose) {
@@ -3081,7 +3087,7 @@ bool Sema::FindAllocationFunctions(
           << OperatorNew->getDeclName() << IsPlacementOperator << DeleteName;
       Diag(OperatorNew->getLocation(), diag::note_type_aware_operator_declared)
           << OperatorNew->isTypeAwareOperatorNewOrDelete()
-          << OperatorNew->getDeclName() << OperatorNew->getDeclContext();
+          << OperatorNew->getDeclName() << OperatorNewContext;
     }
   };
   if (IsClassScopedTypeAwareNew && FoundDelete.empty()) {
@@ -3224,6 +3230,7 @@ bool Sema::FindAllocationFunctions(
   //   deallocation function will be called.
   if (Matches.size() == 1) {
     OperatorDelete = Matches[0].second;
+    DeclContext *OperatorDeleteContext = GetRedeclContext(OperatorDelete);
     bool FoundTypeAwareOperator =
         OperatorDelete->isTypeAwareOperatorNewOrDelete() ||
         OperatorNew->isTypeAwareOperatorNewOrDelete();
@@ -3231,8 +3238,7 @@ bool Sema::FindAllocationFunctions(
       bool MismatchedTypeAwareness =
           OperatorDelete->isTypeAwareOperatorNewOrDelete() !=
           OperatorNew->isTypeAwareOperatorNewOrDelete();
-      bool MismatchedContext =
-          OperatorDelete->getDeclContext() != OperatorNew->getDeclContext();
+      bool MismatchedContext = OperatorDeleteContext != OperatorNewContext;
       if (MismatchedTypeAwareness || MismatchedContext) {
         FunctionDecl *Operators[] = {OperatorDelete, OperatorNew};
         bool TypeAwareOperatorIndex =
@@ -3241,16 +3247,15 @@ bool Sema::FindAllocationFunctions(
             << Operators[TypeAwareOperatorIndex]->getDeclName()
             << isPlacementNew
             << Operators[!TypeAwareOperatorIndex]->getDeclName()
-            << Operators[TypeAwareOperatorIndex]->getDeclContext();
+            << GetRedeclContext(Operators[TypeAwareOperatorIndex]);
         Diag(OperatorNew->getLocation(),
              diag::note_type_aware_operator_declared)
             << OperatorNew->isTypeAwareOperatorNewOrDelete()
-            << OperatorNew->getDeclName() << OperatorNew->getDeclContext();
+            << OperatorNew->getDeclName() << OperatorNewContext;
         Diag(OperatorDelete->getLocation(),
              diag::note_type_aware_operator_declared)
             << OperatorDelete->isTypeAwareOperatorNewOrDelete()
-            << OperatorDelete->getDeclName()
-            << OperatorDelete->getDeclContext();
+            << OperatorDelete->getDeclName() << OperatorDeleteContext;
       }
     }
 

diff  --git a/clang/test/SemaCXX/type-aware-new-delete-transparent-contexts.cpp 
b/clang/test/SemaCXX/type-aware-new-delete-transparent-contexts.cpp
new file mode 100644
index 0000000000000..7c0b967a3c03f
--- /dev/null
+++ b/clang/test/SemaCXX/type-aware-new-delete-transparent-contexts.cpp
@@ -0,0 +1,43 @@
+// RUN: %clang_cc1  -fsyntax-only -verify %s -std=c++26 -fexceptions 
-DTRANSPARENT_DECL=0
+// RUN: %clang_cc1  -fsyntax-only -verify %s -std=c++26 -fexceptions 
-DTRANSPARENT_DECL=1
+// RUN: %clang_cc1  -fsyntax-only -verify %s -std=c++26 -fexceptions 
-DTRANSPARENT_DECL=2
+
+// expected-no-diagnostics
+#if TRANSPARENT_DECL==2
+export module Testing;
+#endif
+
+namespace std {
+  template <class T> struct type_identity {};
+  using size_t = __SIZE_TYPE__;
+  enum class align_val_t : size_t {};
+  struct destroying_delete_t { explicit destroying_delete_t() = default; };
+}
+
+#if TRANSPARENT_DECL==0
+#define BEGIN_TRANSPARENT_DECL extern "C" {
+#define END_TRANSPARENT_DECL }
+#elif TRANSPARENT_DECL==1
+#define BEGIN_TRANSPARENT_DECL extern "C++" {
+#define END_TRANSPARENT_DECL }
+#elif TRANSPARENT_DECL==2
+#define BEGIN_TRANSPARENT_DECL export {
+#define END_TRANSPARENT_DECL }
+#else
+#error unexpected decl kind
+#endif
+
+BEGIN_TRANSPARENT_DECL
+  void *operator new(std::type_identity<int>, std::size_t, std::align_val_t);
+  void operator delete[](std::type_identity<int>, void*, std::size_t, 
std::align_val_t);
+END_TRANSPARENT_DECL
+
+void *operator new[](std::type_identity<int>, std::size_t, std::align_val_t);
+void operator delete(std::type_identity<int>, void*, std::size_t, 
std::align_val_t);
+
+void foo() {
+  int *iptr = new int;
+  delete iptr;
+  int *iarray = new int[5];
+  delete [] iarray;
+}


        
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to