[clang] [clang] make it possible to disable c++26 type aware allocators (PR #138372)

Oliver Hunt via cfe-commits cfe-commits at lists.llvm.org
Fri May 2 18:54:42 PDT 2025


https://github.com/ojhunt created https://github.com/llvm/llvm-project/pull/138372

Per the feedback from the Clang Area Team, this PR makes P2719 only on by default when targeting C++26, and adds a flag to explicitly enable or disable support.

>From ce3630845859d8771ec112c1c091134953bac7c5 Mon Sep 17 00:00:00 2001
From: Oliver Hunt <oliver at apple.com>
Date: Fri, 2 May 2025 18:15:57 -0700
Subject: [PATCH] [clang] make it possible to disable c++26 type aware
 allocators

Per the feedback from the Clang Area Team, this PR makes P2719
only on by default when targeting C++26, and adds a flag to
explicitly enable or disable support.
---
 clang/docs/ReleaseNotes.rst                   |  2 +
 .../clang/Basic/DiagnosticSemaKinds.td        |  3 +
 clang/include/clang/Basic/LangOptions.def     |  1 +
 clang/include/clang/Driver/Options.td         |  6 ++
 clang/lib/CodeGen/CGExprCXX.cpp               |  1 +
 clang/lib/Driver/ToolChains/Clang.cpp         |  5 +
 clang/lib/Frontend/InitPreprocessor.cpp       |  3 +-
 clang/lib/Sema/SemaDeclCXX.cpp                | 99 +++++++++++--------
 clang/lib/Sema/SemaExprCXX.cpp                |  4 +-
 .../test/CodeGenCXX/type-aware-allocators.cpp | 10 +-
 .../test/CodeGenCXX/type-aware-coroutines.cpp |  2 +-
 .../type-aware-placement-operators.cpp        |  8 +-
 ...pe-aware-destroying-new-and-delete-pch.cpp |  4 +-
 clang/test/SemaCXX/type-aware-coroutines.cpp  | 19 +++-
 ...are-new-delete-basic-free-declarations.cpp | 74 ++++++++++++--
 ...new-delete-basic-in-class-declarations.cpp | 58 +++++++++--
 16 files changed, 227 insertions(+), 72 deletions(-)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 4bd9d904e1ea9..53fb4e640a351 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -110,6 +110,8 @@ C++2c Feature Support
 - Implemented `P0963R3 Structured binding declaration as a condition <https://wg21.link/P0963R3>`_.
 
 - Implemented `P2719R4 Type-aware allocation and deallocation functions <https://wg21.link/P2719>`_.
+  This is enabled by default when targeting C++2c, and can be enabled or disabled by
+  the ``-fcxx-type-aware-allocators`` and ``-fno-cxx-type-aware-allocators`` options.
 
 C++23 Feature Support
 ^^^^^^^^^^^^^^^^^^^^^
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index e5a7cdc14a737..eb28f0ce9c8fd 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -9956,6 +9956,9 @@ def warn_cxx26_type_aware_allocators : Warning<
 def err_type_aware_allocator_missing_matching_operator : Error<
   "declaration of type aware %0 in %1 must have matching type aware %2"
 >;
+def err_type_aware_allocators_disabled
+    : Error<"type aware %0 declared but type aware allocator support is "
+            "disabled. Pass -fcxx-type-aware-allocators to enable it">;
 def note_unmatched_type_aware_allocator_declared : Note<
   "unmatched type aware %0 declared here">;
 def err_mismatching_type_aware_cleanup_deallocator : Error<
diff --git a/clang/include/clang/Basic/LangOptions.def b/clang/include/clang/Basic/LangOptions.def
index 930c1c06d1a76..7dc817119c9ac 100644
--- a/clang/include/clang/Basic/LangOptions.def
+++ b/clang/include/clang/Basic/LangOptions.def
@@ -314,6 +314,7 @@ LANGOPT(SizedDeallocation , 1, 0, "sized deallocation")
 LANGOPT(AlignedAllocation , 1, 0, "aligned allocation")
 LANGOPT(AlignedAllocationUnavailable, 1, 0, "aligned allocation functions are unavailable")
 LANGOPT(NewAlignOverride  , 32, 0, "maximum alignment guaranteed by '::operator new(size_t)'")
+LANGOPT(CXXTypeAwareAllocators, 1, 0, "type aware allocators")
 BENIGN_LANGOPT(ModulesCodegen , 1, 0, "Modules code generation")
 BENIGN_LANGOPT(ModulesDebugInfo , 1, 0, "Modules debug info")
 BENIGN_LANGOPT(ElideConstructors , 1, 1, "C++ copy constructor elision")
diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index 736088a70d189..cea63f2636152 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -3539,6 +3539,12 @@ def : Separate<["-"], "fnew-alignment">, Alias<fnew_alignment_EQ>;
 def : Flag<["-"], "faligned-new">, Alias<faligned_allocation>;
 def : Flag<["-"], "fno-aligned-new">, Alias<fno_aligned_allocation>;
 def faligned_new_EQ : Joined<["-"], "faligned-new=">;
+defm cxx_type_aware_allocators
+    : BoolFOption<"cxx-type-aware-allocators",
+                  LangOpts<"CXXTypeAwareAllocators">, Default<cpp26.KeyPath>,
+                  PosFlag<SetTrue, [], [],
+                          "Enable support for C++26's type aware allocators">,
+                  NegFlag<SetFalse>, BothFlags<[], [ClangOption, CC1Option]>>;
 
 def fobjc_legacy_dispatch : Flag<["-"], "fobjc-legacy-dispatch">, Group<f_Group>;
 def fobjc_new_property : Flag<["-"], "fobjc-new-property">, Group<clang_ignored_f_Group>;
diff --git a/clang/lib/CodeGen/CGExprCXX.cpp b/clang/lib/CodeGen/CGExprCXX.cpp
index 3e8c42d5a6f4b..eaa513313e182 100644
--- a/clang/lib/CodeGen/CGExprCXX.cpp
+++ b/clang/lib/CodeGen/CGExprCXX.cpp
@@ -1487,6 +1487,7 @@ namespace {
       TypeAwareAllocationMode TypeAwareDeallocation =
           TypeAwareAllocationMode::No;
       if (OperatorDelete->isTypeAwareOperatorNewOrDelete()) {
+        assert(CGF.getLangOpts().CXXTypeAwareAllocators);
         TypeAwareDeallocation = TypeAwareAllocationMode::Yes;
         QualType SpecializedTypeIdentity = FPT->getParamType(0);
         ++FirstNonTypeArg;
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp
index 6dabf9d842b7b..d2788a0973ed4 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -7516,6 +7516,11 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
   Args.addLastArg(CmdArgs, options::OPT_fsized_deallocation,
                   options::OPT_fno_sized_deallocation);
 
+  // -fcxx-type-aware-allocators is on by default in C++26 onwards and otherwise
+  // off by default.
+  Args.addLastArg(CmdArgs, options::OPT_fcxx_type_aware_allocators,
+                  options::OPT_fno_cxx_type_aware_allocators);
+
   // -faligned-allocation is on by default in C++17 onwards and otherwise off
   // by default.
   if (Arg *A = Args.getLastArg(options::OPT_faligned_allocation,
diff --git a/clang/lib/Frontend/InitPreprocessor.cpp b/clang/lib/Frontend/InitPreprocessor.cpp
index 1f297f228fc1b..6d95c7d0e4c4e 100644
--- a/clang/lib/Frontend/InitPreprocessor.cpp
+++ b/clang/lib/Frontend/InitPreprocessor.cpp
@@ -778,7 +778,8 @@ static void InitializeCPlusPlusFeatureTestMacros(const LangOptions &LangOpts,
   Builder.defineMacro("__cpp_impl_destroying_delete", "201806L");
 
   // TODO: Final number?
-  Builder.defineMacro("__cpp_type_aware_allocators", "202500L");
+  if (LangOpts.CXXTypeAwareAllocators)
+    Builder.defineMacro("__cpp_type_aware_allocators", "202500L");
 }
 
 /// InitializeOpenCLFeatureTestMacros - Define OpenCL macros based on target
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 22e21524c54be..a574508e18a05 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -7326,47 +7326,50 @@ void Sema::CheckCompletedCXXClass(Scope *S, CXXRecordDecl *Record) {
       checkCUDADeviceBuiltinTextureClassTemplate(*this, Record);
   }
 
-  llvm::SmallDenseMap<OverloadedOperatorKind,
-                      llvm::SmallVector<const FunctionDecl *, 2>, 4>
-      TypeAwareDecls{{OO_New, {}},
-                     {OO_Array_New, {}},
-                     {OO_Delete, {}},
-                     {OO_Array_New, {}}};
-  for (auto *D : Record->decls()) {
-    const FunctionDecl *FnDecl = D->getAsFunction();
-    if (!FnDecl || !FnDecl->isTypeAwareOperatorNewOrDelete())
-      continue;
-    assert(FnDecl->getDeclName().isAnyOperatorNewOrDelete());
-    TypeAwareDecls[FnDecl->getOverloadedOperator()].push_back(FnDecl);
-  }
-  auto CheckMismatchedTypeAwareAllocators =
-      [this, &TypeAwareDecls, Record](OverloadedOperatorKind NewKind,
-                                      OverloadedOperatorKind DeleteKind) {
-        auto &NewDecls = TypeAwareDecls[NewKind];
-        auto &DeleteDecls = TypeAwareDecls[DeleteKind];
-        if (NewDecls.empty() == DeleteDecls.empty())
-          return;
-        DeclarationName FoundOperator =
-            Context.DeclarationNames.getCXXOperatorName(
-                NewDecls.empty() ? DeleteKind : NewKind);
-        DeclarationName MissingOperator =
-            Context.DeclarationNames.getCXXOperatorName(
-                NewDecls.empty() ? NewKind : DeleteKind);
-        Diag(Record->getLocation(),
-             diag::err_type_aware_allocator_missing_matching_operator)
-            << FoundOperator << Context.getRecordType(Record)
-            << MissingOperator;
-        for (auto MD : NewDecls)
-          Diag(MD->getLocation(),
-               diag::note_unmatched_type_aware_allocator_declared)
-              << MD;
-        for (auto MD : DeleteDecls)
-          Diag(MD->getLocation(),
-               diag::note_unmatched_type_aware_allocator_declared)
-              << MD;
-      };
-  CheckMismatchedTypeAwareAllocators(OO_New, OO_Delete);
-  CheckMismatchedTypeAwareAllocators(OO_Array_New, OO_Array_Delete);
+  if (getLangOpts().CXXTypeAwareAllocators) {
+    llvm::SmallDenseMap<OverloadedOperatorKind,
+                        llvm::SmallVector<const FunctionDecl *, 2>, 4>
+        TypeAwareDecls{{OO_New, {}},
+                       {OO_Array_New, {}},
+                       {OO_Delete, {}},
+                       {OO_Array_New, {}}};
+    for (auto *D : Record->decls()) {
+      const FunctionDecl *FnDecl = D->getAsFunction();
+      if (!FnDecl || !FnDecl->isTypeAwareOperatorNewOrDelete())
+        continue;
+      assert(FnDecl->getDeclName().isAnyOperatorNewOrDelete());
+      TypeAwareDecls[FnDecl->getOverloadedOperator()].push_back(FnDecl);
+    }
+
+    auto CheckMismatchedTypeAwareAllocators =
+        [this, &TypeAwareDecls, Record](OverloadedOperatorKind NewKind,
+                                        OverloadedOperatorKind DeleteKind) {
+          auto &NewDecls = TypeAwareDecls[NewKind];
+          auto &DeleteDecls = TypeAwareDecls[DeleteKind];
+          if (NewDecls.empty() == DeleteDecls.empty())
+            return;
+          DeclarationName FoundOperator =
+              Context.DeclarationNames.getCXXOperatorName(
+                  NewDecls.empty() ? DeleteKind : NewKind);
+          DeclarationName MissingOperator =
+              Context.DeclarationNames.getCXXOperatorName(
+                  NewDecls.empty() ? NewKind : DeleteKind);
+          Diag(Record->getLocation(),
+               diag::err_type_aware_allocator_missing_matching_operator)
+              << FoundOperator << Context.getRecordType(Record)
+              << MissingOperator;
+          for (auto MD : NewDecls)
+            Diag(MD->getLocation(),
+                 diag::note_unmatched_type_aware_allocator_declared)
+                << MD;
+          for (auto MD : DeleteDecls)
+            Diag(MD->getLocation(),
+                 diag::note_unmatched_type_aware_allocator_declared)
+                << MD;
+        };
+    CheckMismatchedTypeAwareAllocators(OO_New, OO_Delete);
+    CheckMismatchedTypeAwareAllocators(OO_Array_New, OO_Array_Delete);
+  }
 }
 
 /// Look up the special member function that would be called by a special
@@ -16439,7 +16442,8 @@ bool Sema::CompleteConstructorCall(CXXConstructorDecl *Constructor,
 
 TypeAwareAllocationMode Sema::ShouldUseTypeAwareOperatorNewOrDelete() const {
   bool SeenTypedOperators = Context.hasSeenTypeAwareOperatorNewOrDelete();
-  return typeAwareAllocationModeFromBool(SeenTypedOperators);
+  return typeAwareAllocationModeFromBool(getLangOpts().CXXTypeAwareAllocators &&
+                                         SeenTypedOperators);
 }
 
 FunctionDecl *
@@ -16587,6 +16591,11 @@ static inline bool CheckOperatorNewDeleteTypes(
   unsigned MinimumMandatoryArgumentCount = 1;
   unsigned SizeParameterIndex = 0;
   if (IsPotentiallyTypeAware) {
+    if (!SemaRef.getLangOpts().CXXTypeAwareAllocators)
+      return SemaRef.Diag(FnDecl->getLocation(),
+                          diag::err_type_aware_allocators_disabled)
+             << FnDecl->getDeclName();
+
     // We don't emit this diagnosis for template instantiations as we will
     // have already emitted it for the original template declaration.
     if (!FnDecl->isTemplateInstantiation()) {
@@ -16699,7 +16708,7 @@ static inline bool CheckOperatorNewDeleteTypes(
     return true;
 
   FnDecl->setIsTypeAwareOperatorNewOrDelete();
-  return MalformedTypeIdentity;
+  return MalformedTypeIdentity || !SemaRef.getLangOpts().CXXTypeAwareAllocators;
 }
 
 static bool CheckOperatorNewDeclaration(Sema &SemaRef, FunctionDecl *FnDecl) {
@@ -16746,6 +16755,10 @@ CheckOperatorDeleteDeclaration(Sema &SemaRef, FunctionDecl *FnDecl) {
   // pile of incorrect parameter type errors.
   if (MD && IsPotentiallyTypeAwareOperatorNewOrDelete(
                 SemaRef, MD, /*WasMalformed=*/nullptr)) {
+    if (!SemaRef.getLangOpts().CXXTypeAwareAllocators)
+      return SemaRef.Diag(FnDecl->getLocation(),
+                          diag::err_type_aware_allocators_disabled)
+             << FnDecl->getDeclName();
     QualType AddressParamType =
         SemaRef.Context.getCanonicalType(MD->getParamDecl(1)->getType());
     if (AddressParamType != SemaRef.Context.VoidPtrTy &&
diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index 235ea1529b0b8..ee01411729cd8 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -1768,7 +1768,7 @@ namespace {
       // A function template declaration is only a usual deallocation function
       // if it is a typed delete.
       if (!FD) {
-        if (AllocType.isNull())
+        if (AllocType.isNull() || !S.getLangOpts().CXXTypeAwareAllocators)
           return;
         auto *FTD = dyn_cast<FunctionTemplateDecl>(Found->getUnderlyingDecl());
         if (!FTD)
@@ -1786,7 +1786,7 @@ namespace {
         // type being deallocated, or if the type-identity parameter of the
         // deallocation function does not match the constructed type_identity
         // specialization we reject the declaration.
-        if (AllocType.isNull()) {
+        if (AllocType.isNull() || !S.getLangOpts().CXXTypeAwareAllocators) {
           FD = nullptr;
           return;
         }
diff --git a/clang/test/CodeGenCXX/type-aware-allocators.cpp b/clang/test/CodeGenCXX/type-aware-allocators.cpp
index cce9197ed0d12..7b49f1537db8a 100644
--- a/clang/test/CodeGenCXX/type-aware-allocators.cpp
+++ b/clang/test/CodeGenCXX/type-aware-allocators.cpp
@@ -1,14 +1,14 @@
-// RUN: %clang_cc1 %s -triple arm64-apple-macosx    -fsized-deallocation    -faligned-allocation -emit-llvm -fcxx-exceptions -fexceptions -std=c++23 -o - -Wno-c++26-extensions | FileCheck --check-prefixes=CHECK,CHECK_SIZED_ALIGNED  %s
-// RUN: %clang_cc1 %s -triple arm64-apple-macosx -fno-sized-deallocation    -faligned-allocation -emit-llvm -fcxx-exceptions -fexceptions -std=c++23 -o - -Wno-c++26-extensions | FileCheck --check-prefixes=CHECK,CHECK_NO_SIZE_ALIGNED %s
-// RUN: %clang_cc1 %s -triple arm64-apple-macosx -fno-sized-deallocation -fno-aligned-allocation -emit-llvm -fcxx-exceptions -fexceptions -std=c++23 -o - -Wno-c++26-extensions | FileCheck --check-prefixes=CHECK,CHECK_NO_SIZE_NO_ALIGN %s
-// RUN: %clang_cc1 %s -triple arm64-apple-macosx    -fsized-deallocation -fno-aligned-allocation -emit-llvm -fcxx-exceptions -fexceptions -std=c++23 -o - -Wno-c++26-extensions | FileCheck --check-prefixes=CHECK,CHECK_SIZED_NO_ALIGN %s
+// RUN: %clang_cc1 %s -triple arm64-apple-macosx -fcxx-type-aware-allocators    -fsized-deallocation    -faligned-allocation -emit-llvm -fcxx-exceptions -fexceptions -std=c++23 -o - -Wno-c++26-extensions | FileCheck --check-prefixes=CHECK,CHECK_SIZED_ALIGNED  %s
+// RUN: %clang_cc1 %s -triple arm64-apple-macosx -fcxx-type-aware-allocators -fno-sized-deallocation    -faligned-allocation -emit-llvm -fcxx-exceptions -fexceptions -std=c++23 -o - -Wno-c++26-extensions | FileCheck --check-prefixes=CHECK,CHECK_NO_SIZE_ALIGNED %s
+// RUN: %clang_cc1 %s -triple arm64-apple-macosx -fcxx-type-aware-allocators -fno-sized-deallocation -fno-aligned-allocation -emit-llvm -fcxx-exceptions -fexceptions -std=c++23 -o - -Wno-c++26-extensions | FileCheck --check-prefixes=CHECK,CHECK_NO_SIZE_NO_ALIGN %s
+// RUN: %clang_cc1 %s -triple arm64-apple-macosx -fcxx-type-aware-allocators    -fsized-deallocation -fno-aligned-allocation -emit-llvm -fcxx-exceptions -fexceptions -std=c++23 -o - -Wno-c++26-extensions | FileCheck --check-prefixes=CHECK,CHECK_SIZED_NO_ALIGN %s
+
 // Test default behaviour with c++26
 // RUN: %clang_cc1 %s -triple arm64-apple-macosx    -fsized-deallocation    -faligned-allocation -emit-llvm -fcxx-exceptions -fexceptions -std=c++26 -o -  | FileCheck --check-prefixes=CHECK,CHECK_SIZED_ALIGNED  %s
 // RUN: %clang_cc1 %s -triple arm64-apple-macosx -fno-sized-deallocation    -faligned-allocation -emit-llvm -fcxx-exceptions -fexceptions -std=c++26 -o -  | FileCheck --check-prefixes=CHECK,CHECK_NO_SIZE_ALIGNED %s
 // RUN: %clang_cc1 %s -triple arm64-apple-macosx -fno-sized-deallocation -fno-aligned-allocation -emit-llvm -fcxx-exceptions -fexceptions -std=c++26 -o -  | FileCheck --check-prefixes=CHECK,CHECK_NO_SIZE_NO_ALIGN %s
 // RUN: %clang_cc1 %s -triple arm64-apple-macosx    -fsized-deallocation -fno-aligned-allocation -emit-llvm -fcxx-exceptions -fexceptions -std=c++26 -o -  | FileCheck --check-prefixes=CHECK,CHECK_SIZED_NO_ALIGN %s
 
-
 namespace std {
   template <class T> struct type_identity {
     typedef T type;
diff --git a/clang/test/CodeGenCXX/type-aware-coroutines.cpp b/clang/test/CodeGenCXX/type-aware-coroutines.cpp
index 0a19079d987e9..5ac314dbb5e2f 100644
--- a/clang/test/CodeGenCXX/type-aware-coroutines.cpp
+++ b/clang/test/CodeGenCXX/type-aware-coroutines.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -triple arm64-apple-macosx  %s -std=c++23 -fcoroutines -fexceptions -emit-llvm  -Wno-coro-type-aware-allocation-function -o - | FileCheck %s
+// RUN: %clang_cc1 -triple arm64-apple-macosx  %s -std=c++23 -fcxx-type-aware-allocators -fcoroutines -fexceptions -emit-llvm  -Wno-coro-type-aware-allocation-function -o - | FileCheck %s
 // RUN: %clang_cc1 -triple arm64-apple-macosx  %s -std=c++26 -fcoroutines -fexceptions -emit-llvm  -Wno-coro-type-aware-allocation-function -o - | FileCheck %s
 
 #include "Inputs/std-coroutine.h"
diff --git a/clang/test/CodeGenCXX/type-aware-placement-operators.cpp b/clang/test/CodeGenCXX/type-aware-placement-operators.cpp
index 858db62ffcfb0..ec34b1077b749 100644
--- a/clang/test/CodeGenCXX/type-aware-placement-operators.cpp
+++ b/clang/test/CodeGenCXX/type-aware-placement-operators.cpp
@@ -1,7 +1,7 @@
-// RUN: %clang_cc1 %s -triple arm64-apple-macosx -emit-llvm -fcxx-exceptions -fexceptions -std=c++23    -fsized-deallocation    -faligned-allocation -o - | FileCheck %s
-// RUN: %clang_cc1 %s -triple arm64-apple-macosx -emit-llvm -fcxx-exceptions -fexceptions -std=c++23 -fno-sized-deallocation    -faligned-allocation -o - | FileCheck %s
-// RUN: %clang_cc1 %s -triple arm64-apple-macosx -emit-llvm -fcxx-exceptions -fexceptions -std=c++23    -fsized-deallocation -fno-aligned-allocation -o - | FileCheck %s
-// RUN: %clang_cc1 %s -triple arm64-apple-macosx -emit-llvm -fcxx-exceptions -fexceptions -std=c++23 -fno-aligned-allocation -fno-sized-deallocation -o - | FileCheck %s
+// RUN: %clang_cc1 %s -triple arm64-apple-macosx -emit-llvm -fcxx-exceptions -fexceptions -std=c++23 -fcxx-type-aware-allocators    -fsized-deallocation    -faligned-allocation -o - | FileCheck %s
+// RUN: %clang_cc1 %s -triple arm64-apple-macosx -emit-llvm -fcxx-exceptions -fexceptions -std=c++23 -fcxx-type-aware-allocators -fno-sized-deallocation    -faligned-allocation -o - | FileCheck %s
+// RUN: %clang_cc1 %s -triple arm64-apple-macosx -emit-llvm -fcxx-exceptions -fexceptions -std=c++23 -fcxx-type-aware-allocators    -fsized-deallocation -fno-aligned-allocation -o - | FileCheck %s
+// RUN: %clang_cc1 %s -triple arm64-apple-macosx -emit-llvm -fcxx-exceptions -fexceptions -std=c++23 -fcxx-type-aware-allocators -fno-aligned-allocation -fno-sized-deallocation -o - | FileCheck %s
 
 namespace std {
   template <class T> struct type_identity {};
diff --git a/clang/test/PCH/type-aware-destroying-new-and-delete-pch.cpp b/clang/test/PCH/type-aware-destroying-new-and-delete-pch.cpp
index d8f7f5dd50c78..b542b03b8b4fb 100644
--- a/clang/test/PCH/type-aware-destroying-new-and-delete-pch.cpp
+++ b/clang/test/PCH/type-aware-destroying-new-and-delete-pch.cpp
@@ -5,8 +5,8 @@
 // RUN: %clang_cc1 -x c++ -std=c++26 -emit-pch -o %t %S/Inputs/type_aware_destroying_new_delete.h
 // RUN: %clang_cc1 -x c++ -std=c++26 -include-pch %t -emit-llvm -o - %s 
 
-// RUN: %clang_cc1 -x c++ -std=c++11 -emit-pch -fpch-instantiate-templates -o %t %S/Inputs/type_aware_destroying_new_delete.h
-// RUN: %clang_cc1 -x c++ -std=c++11 -include-pch %t -emit-llvm -o - %s
+// RUN: %clang_cc1 -x c++ -std=c++11 -fcxx-type-aware-allocators -emit-pch -fpch-instantiate-templates -o %t %S/Inputs/type_aware_destroying_new_delete.h
+// RUN: %clang_cc1 -x c++ -std=c++11 -fcxx-type-aware-allocators -include-pch %t -emit-llvm -o - %s
 
 
 static void call_in_pch_function(void) {
diff --git a/clang/test/SemaCXX/type-aware-coroutines.cpp b/clang/test/SemaCXX/type-aware-coroutines.cpp
index a54d37c47dbd9..3ec3d3953db45 100644
--- a/clang/test/SemaCXX/type-aware-coroutines.cpp
+++ b/clang/test/SemaCXX/type-aware-coroutines.cpp
@@ -1,4 +1,6 @@
-// RUN: %clang_cc1 -triple arm64-apple-macosx -fsyntax-only -verify %s -std=c++26 -fcoroutines -fexceptions -Wall -Wpedantic
+// RUN: %clang_cc1 -triple arm64-apple-macosx -fsyntax-only -verify %s -std=c++26 -fcoroutines                                -fexceptions -Wall -Wpedantic
+// Type aware allocators disabled
+// RUN: %clang_cc1 -triple arm64-apple-macosx -fsyntax-only -verify=no_type_aware %s -std=c++26 -fcoroutines -fno-cxx-type-aware-allocators -fexceptions -Wall -Wpedantic
 
 
 #include "Inputs/std-coroutine.h"
@@ -16,9 +18,13 @@ struct Allocator {};
 struct resumable {
   struct promise_type {
     void *operator new(std::type_identity<promise_type>, std::size_t sz, std::align_val_t, int); // #resumable_tan1
+    // no_type_aware-error at -1 {{type aware 'operator new' declared but type aware allocator support is disabled. Pass -fcxx-type-aware-allocators to enable it}}
     void *operator new(std::type_identity<promise_type>, std::size_t sz, std::align_val_t, float); // #resumable_tan2
+    // no_type_aware-error at -1 {{type aware 'operator new' declared but type aware allocator support is disabled. Pass -fcxx-type-aware-allocators to enable it}}
     void operator delete(std::type_identity<promise_type>, void *, std::size_t sz, std::align_val_t); // #resumable_tad1
+    // no_type_aware-error at -1 {{type aware 'operator delete' declared but type aware allocator support is disabled. Pass -fcxx-type-aware-allocators to enable it}}
     template <typename T> void operator delete(std::type_identity<T>, void *, std::size_t sz, std::align_val_t) = delete; // #resumable_tad2
+    // no_type_aware-error at -1 {{type aware 'operator delete' declared but type aware allocator support is disabled. Pass -fcxx-type-aware-allocators to enable it}}
 
     resumable get_return_object() { return {}; }
     auto initial_suspend() { return std::suspend_always(); }
@@ -32,7 +38,9 @@ struct resumable {
 struct resumable2 {
   struct promise_type {
     template <typename... Args> void *operator new(std::type_identity<promise_type>, std::size_t sz, std::align_val_t, Args...); // #resumable2_tan1
+    // no_type_aware-error at -1 {{type aware 'operator new' declared but type aware allocator support is disabled. Pass -fcxx-type-aware-allocators to enable it}}
     void operator delete(std::type_identity<promise_type>, void *, std::size_t sz, std::align_val_t); // #resumable2_tad2
+    // no_type_aware-error at -1 {{type aware 'operator delete' declared but type aware allocator support is disabled. Pass -fcxx-type-aware-allocators to enable it}}
 
     resumable2 get_return_object() { return {}; }
     auto initial_suspend() { return std::suspend_always(); }
@@ -50,6 +58,7 @@ struct resumable3 {
   // expected-note@#resumable3_tan {{unmatched type aware 'operator new' declared here}}
     void *operator new(std::size_t sz, float);
     void *operator new(std::type_identity<promise_type>, std::size_t sz, std::align_val_t, float); // #resumable3_tan
+    // no_type_aware-error at -1 {{type aware 'operator new' declared but type aware allocator support is disabled. Pass -fcxx-type-aware-allocators to enable it}}
     void operator delete(void *);
 
     resumable3 get_return_object() { return {}; }
@@ -66,6 +75,7 @@ struct resumable4 {
     // expected-note@#resumable4_tad {{unmatched type aware 'operator delete' declared here}}
     void *operator new(std::size_t sz, float);
     template <typename T> void operator delete(std::type_identity<T>, void *, std::size_t, std::align_val_t); // #resumable4_tad
+    // no_type_aware-error at -1 {{type aware 'operator delete' declared but type aware allocator support is disabled. Pass -fcxx-type-aware-allocators to enable it}}
 
     resumable4 get_return_object() { return {}; }
     auto initial_suspend() { return std::suspend_always(); }
@@ -82,6 +92,7 @@ struct resumable5 {
     void *operator new(std::size_t sz, float);
     void operator delete(void *);
     template <typename T> void operator delete(std::type_identity<T>, void *, std::size_t, std::align_val_t); // #resumable5_tad
+    // no_type_aware-error at -1 {{type aware 'operator delete' declared but type aware allocator support is disabled. Pass -fcxx-type-aware-allocators to enable it}}
 
     resumable5 get_return_object() { return {}; }
     auto initial_suspend() { return std::suspend_always(); }
@@ -97,6 +108,7 @@ resumable f1(int) {
   // expected-note at -2 {{type aware 'operator new' will not be used for coroutine allocation}}
   // expected-note@#resumable_tan1 {{type aware 'operator new' declared here}}
   // expected-note@#resumable_tan2 {{type aware 'operator new' declared here}}
+  // no_type_aware-error at -5 {{'operator new' provided by 'std::coroutine_traits<resumable, int>::promise_type' (aka 'resumable::promise_type') is not usable with the function signature of 'f1'}}
   co_return;
 }
 
@@ -105,6 +117,7 @@ resumable f2(float) {
   // expected-note at -2 {{type aware 'operator new' will not be used for coroutine allocation}}
   // expected-note@#resumable_tan1 {{type aware 'operator new' declared here}}
   // expected-note@#resumable_tan2 {{type aware 'operator new' declared here}}
+  // no_type_aware-error at -5 {{'operator new' provided by 'std::coroutine_traits<resumable, float>::promise_type' (aka 'resumable::promise_type') is not usable with the function signature of 'f2'}}
   co_return;
 }
 
@@ -112,6 +125,7 @@ resumable2 f3(int, float, const char*, Allocator) {
   // expected-error at -1 {{'operator new' provided by 'std::coroutine_traits<resumable2, int, float, const char *, Allocator>::promise_type' (aka 'resumable2::promise_type') is not usable with the function signature of 'f3'}}
   // expected-note at -2 {{type aware 'operator new' will not be used for coroutine allocation}}
   // expected-note@#resumable2_tan1 {{type aware 'operator new' declared here}}
+  // no_type_aware-error at -4 {{'operator new' provided by 'std::coroutine_traits<resumable2, int, float, const char *, Allocator>::promise_type' (aka 'resumable2::promise_type') is not usable with the function signature of 'f3'}}
   co_yield 1;
   co_return;
 }
@@ -121,6 +135,7 @@ resumable f4(int n = 10) {
   // expected-note at -2 {{type aware 'operator new' will not be used for coroutine allocation}}
   // expected-note@#resumable_tan1 {{type aware 'operator new' declared here}}
   // expected-note@#resumable_tan2 {{type aware 'operator new' declared here}}
+  // no_type_aware-error at -5 {{'operator new' provided by 'std::coroutine_traits<resumable, int>::promise_type' (aka 'resumable::promise_type') is not usable with the function signature of 'f4'}}
   for (int i = 0; i < n; i++)
     co_yield i;
 }
@@ -135,6 +150,8 @@ resumable4 f6(float) {
   // expected-warning at -2 {{type aware 'operator delete' will not be used for coroutine allocation}}
   // expected-note@#resumable4_tad {{type aware 'operator delete' declared here}}
   // expected-note@#resumable4_tad {{member 'operator delete' declared here}}
+  // no_type_aware-error at -5 {{no suitable member 'operator delete' in 'promise_type'}}
+  // no_type_aware-note@#resumable4_tad {{member 'operator delete' declared here}}
   co_return;
 }
 
diff --git a/clang/test/SemaCXX/type-aware-new-delete-basic-free-declarations.cpp b/clang/test/SemaCXX/type-aware-new-delete-basic-free-declarations.cpp
index c85b92718479a..8cdcac3b05907 100644
--- a/clang/test/SemaCXX/type-aware-new-delete-basic-free-declarations.cpp
+++ b/clang/test/SemaCXX/type-aware-new-delete-basic-free-declarations.cpp
@@ -1,7 +1,18 @@
-// RUN: %clang_cc1 -triple arm64-apple-macosx -fsyntax-only -verify %s          -std=c++26    -fsized-deallocation    -faligned-allocation
-// RUN: %clang_cc1 -triple arm64-apple-macosx -fsyntax-only -verify %s          -std=c++26 -fno-sized-deallocation    -faligned-allocation
-// RUN: %clang_cc1 -triple arm64-apple-macosx -fsyntax-only -verify %s          -std=c++26 -fno-sized-deallocation -fno-aligned-allocation
-// RUN: %clang_cc1 -triple arm64-apple-macosx -fsyntax-only -verify %s          -std=c++26    -fsized-deallocation -fno-aligned-allocation
+// RUN: %clang_cc1 -triple arm64-apple-macosx -fsyntax-only -verify=expected,both        %s -std=c++26    -fsized-deallocation    -faligned-allocation
+// RUN: %clang_cc1 -triple arm64-apple-macosx -fsyntax-only -verify=expected,both        %s -std=c++26 -fno-sized-deallocation    -faligned-allocation
+// RUN: %clang_cc1 -triple arm64-apple-macosx -fsyntax-only -verify=expected,both        %s -std=c++26 -fno-sized-deallocation -fno-aligned-allocation
+// RUN: %clang_cc1 -triple arm64-apple-macosx -fsyntax-only -verify=expected,both        %s -std=c++26    -fsized-deallocation -fno-aligned-allocation
+// RUN: %clang_cc1 -triple arm64-apple-macosx -fsyntax-only -verify=no_taa_disabled,both %s -std=c++26 -fno-cxx-type-aware-allocators -DNO_TYPE_AWARE_ALLOCATORS
+
+#ifdef NO_TYPE_AWARE_ALLOCATORS
+#ifdef __cpp_type_aware_allocators
+#error __cpp_type_aware_allocators erroneously defined
+#endif
+#else
+#ifndef __cpp_type_aware_allocators
+#error __cpp_type_aware_allocators should be defined
+#endif
+#endif
 
 namespace std {
   template <class T> struct type_identity {};
@@ -16,32 +27,46 @@ template <typename T> struct TemplateTestType {};
 
 // Valid free declarations
 void *operator new(std::type_identity<int>, size_t, std::align_val_t); // #1
+// no_taa_disabled-error at -1 {{type aware 'operator new' declared but type aware allocator support is disabled. Pass -fcxx-type-aware-allocators to enable it}}
 void *operator new(std::type_identity<int>, size_t, std::align_val_t, TestType&); // #2
+// no_taa_disabled-error at -1 {{type aware 'operator new' declared but type aware allocator support is disabled. Pass -fcxx-type-aware-allocators to enable it}}
 template <typename T> void *operator new(std::type_identity<T>, size_t, std::align_val_t); // #3
+// no_taa_disabled-error at -1 {{type aware 'operator new' declared but type aware allocator support is disabled. Pass -fcxx-type-aware-allocators to enable it}}
 template <typename T> void *operator new(std::type_identity<T>, size_t, std::align_val_t, TestType&); // #4
+// no_taa_disabled-error at -1 {{type aware 'operator new' declared but type aware allocator support is disabled. Pass -fcxx-type-aware-allocators to enable it}}
 template <typename T> void *operator new(std::type_identity<TemplateTestType<T>>, size_t, std::align_val_t, TestType&); // #5
+// no_taa_disabled-error at -1 {{type aware 'operator new' declared but type aware allocator support is disabled. Pass -fcxx-type-aware-allocators to enable it}}
 template <typename T, typename U> void *operator new(std::type_identity<T>, size_t, std::align_val_t, TemplateTestType<U>&); // #6
+// no_taa_disabled-error at -1 {{type aware 'operator new' declared but type aware allocator support is disabled. Pass -fcxx-type-aware-allocators to enable it}}
 template <template <typename> class T> void *operator new(std::type_identity<T<int>>, size_t, std::align_val_t); // #7
+// no_taa_disabled-error at -1 {{type aware 'operator new' declared but type aware allocator support is disabled. Pass -fcxx-type-aware-allocators to enable it}}
 
 void operator delete(std::type_identity<int>, void *, size_t, std::align_val_t); // #8
+// no_taa_disabled-error at -1 {{type aware 'operator delete' declared but type aware allocator support is disabled. Pass -fcxx-type-aware-allocators to enable it}}
 template <typename T> void operator delete(std::type_identity<T>, void *, size_t, std::align_val_t); // #9
+// no_taa_disabled-error at -1 {{type aware 'operator delete' declared but type aware allocator support is disabled. Pass -fcxx-type-aware-allocators to enable it}}
 template <typename T> void operator delete(std::type_identity<TemplateTestType<T>>, void *, size_t, std::align_val_t); // #10
+// no_taa_disabled-error at -1 {{type aware 'operator delete' declared but type aware allocator support is disabled. Pass -fcxx-type-aware-allocators to enable it}}
 template <template <typename> class T> void operator delete(std::type_identity<T<int>>, void *, size_t, std::align_val_t); // #11
+// no_taa_disabled-error at -1 {{type aware 'operator delete' declared but type aware allocator support is disabled. Pass -fcxx-type-aware-allocators to enable it}}
 
 typedef std::type_identity<float> TypeIdentityAlias1;
 void *operator new(TypeIdentityAlias1, size_t, std::align_val_t); // #12
+// no_taa_disabled-error at -1 {{type aware 'operator new' declared but type aware allocator support is disabled. Pass -fcxx-type-aware-allocators to enable it}}
 
 using TypeIdentityAlias2 = std::type_identity<double>;
 void *operator new(TypeIdentityAlias2, size_t, std::align_val_t); // #13
+// no_taa_disabled-error at -1 {{type aware 'operator new' declared but type aware allocator support is disabled. Pass -fcxx-type-aware-allocators to enable it}}
 
 template <typename T> using TypeIdentityAlias3 = std::type_identity<T>;
 template <typename T> void *operator new(TypeIdentityAlias3<T>, size_t, std::align_val_t); // #14
+// no_taa_disabled-error at -1 {{type aware 'operator new' declared but type aware allocator support is disabled. Pass -fcxx-type-aware-allocators to enable it}}
 
 template <typename T> void *operator new(T, size_t, std::align_val_t);
-// expected-error at -1 {{'operator new' cannot take a dependent type as its 1st parameter}}
+// both-error at -1 {{'operator new' cannot take a dependent type as its 1st parameter}}
 
 template <typename T> void operator delete(T, void*, size_t, std::align_val_t);
-// expected-error at -1 {{'operator delete' cannot take a dependent type as its 1st parameter}}
+// both-error at -1 {{'operator delete' cannot take a dependent type as its 1st parameter}}
 
 template <typename T> struct S {
   typedef std::type_identity<T> type_identity;
@@ -51,43 +76,60 @@ template <typename T> struct S {
 };
 
 template <typename T> void *operator new(typename S<T>::type_identity, size_t, std::align_val_t);
-// expected-error at -1 {{'operator new' cannot take a dependent type as its 1st parameter}}
+// both-error at -1 {{'operator new' cannot take a dependent type as its 1st parameter}}
 
 // Invalid type aware declarations
 void *operator new(std::type_identity<int>, size_t); 
 // expected-error at -1 {{type aware 'operator new' must have at least three parameters}}
+// no_taa_disabled-error at -2 {{type aware 'operator new' declared but type aware allocator support is disabled. Pass -fcxx-type-aware-allocators to enable it}}
 void *operator new(std::type_identity<int>, size_t, TestType&);
 // expected-error at -1 {{type aware 'operator new' takes type std::align_val_t ('std::align_val_t') as 3rd parameter}}
+// no_taa_disabled-error at -2 {{type aware 'operator new' declared but type aware allocator support is disabled. Pass -fcxx-type-aware-allocators to enable it}}
 void operator delete(std::type_identity<int>, void *);
 // expected-error at -1 {{type aware 'operator delete' must have at least four parameters}}
+// no_taa_disabled-error at -2 {{type aware 'operator delete' declared but type aware allocator support is disabled. Pass -fcxx-type-aware-allocators to enable it}}
 void operator delete(std::type_identity<int>, void *, size_t);
 // expected-error at -1 {{type aware 'operator delete' must have at least four parameters}}
+// no_taa_disabled-error at -2 {{type aware 'operator delete' declared but type aware allocator support is disabled. Pass -fcxx-type-aware-allocators to enable it}}
 void operator delete(std::type_identity<int>, void *, std::align_val_t);
 // expected-error at -1 {{type aware 'operator delete' must have at least four parameters}}
+// no_taa_disabled-error at -2 {{type aware 'operator delete' declared but type aware allocator support is disabled. Pass -fcxx-type-aware-allocators to enable it}}
 template <typename T> void operator delete(std::type_identity<T>, void *);
 // expected-error at -1 {{type aware 'operator delete' must have at least four parameters}}
+// no_taa_disabled-error at -2 {{type aware 'operator delete' declared but type aware allocator support is disabled. Pass -fcxx-type-aware-allocators to enable it}}
 template <typename T> void operator delete(std::type_identity<T>, void *, std::align_val_t);
 // expected-error at -1 {{type aware 'operator delete' must have at least four parameters}}
+// no_taa_disabled-error at -2 {{type aware 'operator delete' declared but type aware allocator support is disabled. Pass -fcxx-type-aware-allocators to enable it}}
 template <typename T> void operator delete(std::type_identity<T>, void *, size_t);
 // expected-error at -1 {{type aware 'operator delete' must have at least four parameters}}
+// no_taa_disabled-error at -2 {{type aware 'operator delete' declared but type aware allocator support is disabled. Pass -fcxx-type-aware-allocators to enable it}}
 template <typename T, typename U> void *operator new(std::type_identity<T>, U);
 // expected-error at -1 {{type aware 'operator new' must have at least three parameters}}
+// no_taa_disabled-error at -2 {{type aware 'operator new' declared but type aware allocator support is disabled. Pass -fcxx-type-aware-allocators to enable it}}
 template <typename T, typename U> void operator delete(std::type_identity<T>, U, size_t, std::align_val_t);
 // expected-error at -1 {{type aware 'operator delete' cannot take a dependent type as its 2nd parameter; use 'void *' instead}}
+// no_taa_disabled-error at -2 {{type aware 'operator delete' declared but type aware allocator support is disabled. Pass -fcxx-type-aware-allocators to enable it}}
 template <typename T, typename U> void operator delete(std::type_identity<T>, void *, U, std::align_val_t);
 // expected-error at -1 {{type aware 'operator delete' cannot take a dependent type as its 3rd parameter; use 'unsigned long' instead}}
+// no_taa_disabled-error at -2 {{type aware 'operator delete' declared but type aware allocator support is disabled. Pass -fcxx-type-aware-allocators to enable it}}
 template <typename T, typename U> void operator delete(std::type_identity<T>, void *, size_t, U);
 // expected-error at -1 {{type aware 'operator delete' cannot take a dependent type as its 4th parameter; use 'std::align_val_t' instead}}
+// no_taa_disabled-error at -2 {{type aware 'operator delete' declared but type aware allocator support is disabled. Pass -fcxx-type-aware-allocators to enable it}}
 template <typename U> void *operator new(std::type_identity<int>, typename S<U>::size_ty, std::align_val_t);
 // expected-error at -1 {{type aware 'operator new' cannot take a dependent type as its 2nd parameter; use size_t ('unsigned long') instead}}
+// no_taa_disabled-error at -2 {{type aware 'operator new' declared but type aware allocator support is disabled. Pass -fcxx-type-aware-allocators to enable it}}
 template <typename U> void operator delete(std::type_identity<int>, typename S<U>::ptr_ty, size_t, std::align_val_t);
 // expected-error at -1 {{type aware 'operator delete' cannot take a dependent type as its 2nd parameter; use 'void *' instead}}
+// no_taa_disabled-error at -2 {{type aware 'operator delete' declared but type aware allocator support is disabled. Pass -fcxx-type-aware-allocators to enable it}}
 template <typename T, typename U> void *operator new(std::type_identity<T>, typename S<U>::size_ty, std::align_val_t);
 // expected-error at -1 {{type aware 'operator new' cannot take a dependent type as its 2nd parameter; use size_t ('unsigned long') instead}}
+// no_taa_disabled-error at -2 {{type aware 'operator new' declared but type aware allocator support is disabled. Pass -fcxx-type-aware-allocators to enable it}}
 template <typename T, typename U> void operator delete(std::type_identity<T>, typename S<U>::ptr_ty, size_t, std::align_val_t);
 // expected-error at -1 {{type aware 'operator delete' cannot take a dependent type as its 2nd parameter; use 'void *' instead}}
+// no_taa_disabled-error at -2 {{type aware 'operator delete' declared but type aware allocator support is disabled. Pass -fcxx-type-aware-allocators to enable it}}
 template <typename T, typename U> void operator delete(std::type_identity<T>, void *, size_t, typename S<U>::align_val_ty);
 // expected-error at -1 {{type aware 'operator delete' cannot take a dependent type as its 4th parameter; use 'std::align_val_t' instead}}
+// no_taa_disabled-error at -2 {{type aware 'operator delete' declared but type aware allocator support is disabled. Pass -fcxx-type-aware-allocators to enable it}}
 
 template <typename T> using Alias = T;
 template <typename T> using TypeIdentityAlias = std::type_identity<T>;
@@ -95,25 +137,43 @@ typedef std::type_identity<double> TypedefAlias;
 using UsingAlias = std::type_identity<float>;
 void *operator new(Alias<size_t>, std::align_val_t);
 template <typename T> void *operator new(Alias<std::type_identity<T>>, Alias<size_t>, std::align_val_t);
+// no_taa_disabled-error at -1 {{type aware 'operator new' declared but type aware allocator support is disabled. Pass -fcxx-type-aware-allocators to enable it}}
 void *operator new(Alias<std::type_identity<int>>, size_t, std::align_val_t);
+// no_taa_disabled-error at -1 {{type aware 'operator new' declared but type aware allocator support is disabled. Pass -fcxx-type-aware-allocators to enable it}}
 template <typename T> void operator delete(Alias<std::type_identity<T>>, void *, size_t, std::align_val_t);
+// no_taa_disabled-error at -1 {{type aware 'operator delete' declared but type aware allocator support is disabled. Pass -fcxx-type-aware-allocators to enable it}}
 void operator delete(Alias<std::type_identity<int>>, void *, size_t, std::align_val_t);
+// no_taa_disabled-error at -1 {{type aware 'operator delete' declared but type aware allocator support is disabled. Pass -fcxx-type-aware-allocators to enable it}}
 
 template <typename T> void *operator new(TypeIdentityAlias<T>, size_t, std::align_val_t);
+// no_taa_disabled-error at -1 {{type aware 'operator new' declared but type aware allocator support is disabled. Pass -fcxx-type-aware-allocators to enable it}}
 void *operator new(TypeIdentityAlias<int>, size_t, std::align_val_t);
+// no_taa_disabled-error at -1 {{type aware 'operator new' declared but type aware allocator support is disabled. Pass -fcxx-type-aware-allocators to enable it}}
 template <typename T> void operator delete(TypeIdentityAlias<T>, void *, size_t, std::align_val_t);
+// no_taa_disabled-error at -1 {{type aware 'operator delete' declared but type aware allocator support is disabled. Pass -fcxx-type-aware-allocators to enable it}}
 void operator delete(TypeIdentityAlias<int>, void *, size_t, std::align_val_t);
+// no_taa_disabled-error at -1 {{type aware 'operator delete' declared but type aware allocator support is disabled. Pass -fcxx-type-aware-allocators to enable it}}
 
 template <typename T> void *operator new(TypedefAlias, size_t, std::align_val_t);
+// no_taa_disabled-error at -1 {{type aware 'operator new' declared but type aware allocator support is disabled. Pass -fcxx-type-aware-allocators to enable it}}
 void *operator new(TypedefAlias, size_t, std::align_val_t);
+// no_taa_disabled-error at -1 {{type aware 'operator new' declared but type aware allocator support is disabled. Pass -fcxx-type-aware-allocators to enable it}}
 template <typename T> void operator delete(TypedefAlias, void *, size_t, std::align_val_t);
+// no_taa_disabled-error at -1 {{type aware 'operator delete' declared but type aware allocator support is disabled. Pass -fcxx-type-aware-allocators to enable it}}
 void operator delete(TypedefAlias, void *, size_t, std::align_val_t);
+// no_taa_disabled-error at -1 {{type aware 'operator delete' declared but type aware allocator support is disabled. Pass -fcxx-type-aware-allocators to enable it}}
 
 template <typename T> void *operator new(UsingAlias, size_t, std::align_val_t);
+// no_taa_disabled-error at -1 {{type aware 'operator new' declared but type aware allocator support is disabled. Pass -fcxx-type-aware-allocators to enable it}}
 void *operator new(UsingAlias, size_t, std::align_val_t);
+// no_taa_disabled-error at -1 {{type aware 'operator new' declared but type aware allocator support is disabled. Pass -fcxx-type-aware-allocators to enable it}}
 template <typename T> void operator delete(UsingAlias, void *, size_t, std::align_val_t);
+// no_taa_disabled-error at -1 {{type aware 'operator delete' declared but type aware allocator support is disabled. Pass -fcxx-type-aware-allocators to enable it}}
 void operator delete(UsingAlias, void *, size_t, std::align_val_t);
+// no_taa_disabled-error at -1 {{type aware 'operator delete' declared but type aware allocator support is disabled. Pass -fcxx-type-aware-allocators to enable it}}
 
 class ForwardDecl;
 void *operator new(std::type_identity<ForwardDecl>, size_t, std::align_val_t);
+// no_taa_disabled-error at -1 {{type aware 'operator new' declared but type aware allocator support is disabled. Pass -fcxx-type-aware-allocators to enable it}}
 void operator delete(std::type_identity<ForwardDecl>, void*, size_t, std::align_val_t);
+// no_taa_disabled-error at -1 {{type aware 'operator delete' declared but type aware allocator support is disabled. Pass -fcxx-type-aware-allocators to enable it}}
diff --git a/clang/test/SemaCXX/type-aware-new-delete-basic-in-class-declarations.cpp b/clang/test/SemaCXX/type-aware-new-delete-basic-in-class-declarations.cpp
index 34bd1d4206be1..8db1e291b9ae0 100644
--- a/clang/test/SemaCXX/type-aware-new-delete-basic-in-class-declarations.cpp
+++ b/clang/test/SemaCXX/type-aware-new-delete-basic-in-class-declarations.cpp
@@ -1,6 +1,7 @@
-// RUN: %clang_cc1 -triple arm64-apple-macosx -fsyntax-only -verify=expected,precxx26 %s           -std=c++23
+// RUN: %clang_cc1 -triple arm64-apple-macosx -fsyntax-only -verify=expected,precxx26 %s           -std=c++23 -fcxx-type-aware-allocators
 // RUN: %clang_cc1 -triple arm64-apple-macosx -fsyntax-only -verify %s                             -std=c++26
-
+// RUN: %clang_cc1 -triple arm64-apple-macosx -fsyntax-only -verify=no_type_aware %s               -std=c++23 -Wno-c++26-extensions
+// RUN: %clang_cc1 -triple arm64-apple-macosx -fsyntax-only -verify=no_type_aware %s               -std=c++26 -fno-cxx-type-aware-allocators
 namespace std {
   template <class T> struct type_identity {};
   enum class align_val_t : __SIZE_TYPE__ {};
@@ -12,49 +13,61 @@ using size_t = __SIZE_TYPE__;
 // Basic valid declarations
 struct S {
   void *operator new(std::type_identity<S>, size_t, std::align_val_t); // #1
+  // no_type_aware-error@#1 {{type aware 'operator new' declared but type aware allocator support is disabled. Pass -fcxx-type-aware-allocators to enable it}}
   void operator delete(std::type_identity<S>, void *, size_t, std::align_val_t); // #2
   // precxx26-warning@#1 {{type aware allocators are a C++2c extension}}
   // precxx26-warning@#2 {{type aware allocators are a C++2c extension}}
+  // no_type_aware-error@#2 {{type aware 'operator delete' declared but type aware allocator support is disabled. Pass -fcxx-type-aware-allocators to enable it}}
   void operator delete(S *, std::destroying_delete_t);
 };
 
 template <typename T> struct S2 {
   void *operator new(std::type_identity<S2<T>>, size_t, std::align_val_t); // #3
+  // no_type_aware-error@#3 {{type aware 'operator new' declared but type aware allocator support is disabled. Pass -fcxx-type-aware-allocators to enable it}}
   void operator delete(std::type_identity<S2<T>>, void *, size_t, std::align_val_t); // #4
   // precxx26-warning@#3 {{type aware allocators are a C++2c extension}}
   // precxx26-warning@#4 {{type aware allocators are a C++2c extension}}
+  // no_type_aware-error@#4 {{type aware 'operator delete' declared but type aware allocator support is disabled. Pass -fcxx-type-aware-allocators to enable it}}
   void operator delete(S2 *, std::destroying_delete_t);
 };
 
 struct S3 {
   template <typename T> void *operator new(std::type_identity<T>, size_t, std::align_val_t); // #5
+  // no_type_aware-error@#5 {{type aware 'operator new' declared but type aware allocator support is disabled. Pass -fcxx-type-aware-allocators to enable it}}
   template <typename T> void operator delete(std::type_identity<T>, void *, size_t, std::align_val_t); // #6
   // precxx26-warning@#5 {{type aware allocators are a C++2c extension}}
   // precxx26-warning@#6 {{type aware allocators are a C++2c extension}}
+  // no_type_aware-error@#6 {{type aware 'operator delete' declared but type aware allocator support is disabled. Pass -fcxx-type-aware-allocators to enable it}}
   void operator delete(S3 *, std::destroying_delete_t);
 };
 
 struct S4 {
   template <typename T> void *operator new(std::type_identity<T>, size_t, std::align_val_t); // #7
+  // no_type_aware-error@#7 {{type aware 'operator new' declared but type aware allocator support is disabled. Pass -fcxx-type-aware-allocators to enable it}}
   template <typename T> void operator delete(std::type_identity<T>, void *, size_t, std::align_val_t); // #8
+  // no_type_aware-error@#8 {{type aware 'operator delete' declared but type aware allocator support is disabled. Pass -fcxx-type-aware-allocators to enable it}}
   template <typename T> void operator delete(std::type_identity<T>, S4 *, std::destroying_delete_t, size_t, std::align_val_t); // #9
   // precxx26-warning@#7 {{type aware allocators are a C++2c extension}}
   // precxx26-warning@#8 {{type aware allocators are a C++2c extension}}
   // expected-error@#9 {{destroying delete is not permitted to be type aware}}
+  // no_type_aware-error@#9 {{type aware 'operator delete' declared but type aware allocator support is disabled. Pass -fcxx-type-aware-allocators to enable it}}
 };
 
 struct S5 {
   template <typename T> void operator delete(std::type_identity<T>, T *, size_t, std::align_val_t); // #10
   // expected-error@#10 {{type aware 'operator delete' cannot take a dependent type as its 2nd parameter}}
+  // no_type_aware-error@#10 {{type aware 'operator delete' declared but type aware allocator support is disabled. Pass -fcxx-type-aware-allocators to enable it}}
   // precxx26-warning@#10 {{type aware allocators are a C++2c extension}}
 };
 
 struct S6 {
   template <typename T> void *operator new(std::type_identity<S6>, T, std::align_val_t); // #11
   // expected-error@#11 {{type aware 'operator new' cannot take a dependent type as its 2nd parameter}}
+  // no_type_aware-error@#11 {{type aware 'operator new' declared but type aware allocator support is disabled. Pass -fcxx-type-aware-allocators to enable it}}
   // precxx26-warning@#11 {{type aware allocators are a C++2c extension}}
   template <typename T> void operator delete(std::type_identity<S6>, T, size_t, std::align_val_t); // #12
   // expected-error@#12 {{type aware 'operator delete' cannot take a dependent type as its 2nd parameter}}
+  // no_type_aware-error@#12 {{type aware 'operator delete' declared but type aware allocator support is disabled. Pass -fcxx-type-aware-allocators to enable it}}
   // precxx26-warning@#12 {{type aware allocators are a C++2c extension}}
 };
 
@@ -62,30 +75,38 @@ template <typename U>
 struct S7 {
   template <typename T> void *operator new(std::type_identity<T>, U, std::align_val_t); // #13
   // expected-error@#13 {{type aware 'operator new' cannot take a dependent type as its 2nd parameter;}}
+  // no_type_aware-error@#13 {{type aware 'operator new' declared but type aware allocator support is disabled. Pass -fcxx-type-aware-allocators to enable it}}
   // precxx26-warning@#13 {{type aware allocators are a C++2c extension}}
   template <typename T> void operator delete(std::type_identity<T>, U, size_t, std::align_val_t); // #14
   // expected-error@#14 {{type aware 'operator delete' cannot take a dependent type as its 2nd parameter;}}
+  // no_type_aware-error@#14 {{type aware 'operator delete' declared but type aware allocator support is disabled. Pass -fcxx-type-aware-allocators to enable it}}
   // precxx26-warning@#14 {{type aware allocators are a C++2c extension}}
   template <typename T> void operator delete(std::type_identity<T>, S7 *, std::destroying_delete_t, U, std::align_val_t); // #15
   // expected-error@#15 {{destroying delete is not permitted to be type aware}}
+  // no_type_aware-error@#15 {{type aware 'operator delete' declared but type aware allocator support is disabled. Pass -fcxx-type-aware-allocators to enable it}}
   void operator delete(S7 *, std::destroying_delete_t, U); // #16
 };
 
 void f() {
   S7<int> s;
   // expected-note at -1 {{in instantiation of template class 'S7<int>' requested here}}
+  // no_type_aware-note at -2 {{in instantiation of template class 'S7<int>' requested here}}
   // expected-error@#16 {{destroying operator delete can have only an optional size and optional alignment parameter}}
+  // no_type_aware-error@#16 {{destroying operator delete can have only an optional size and optional alignment parameter}}
 }
 
 struct S8 {
   template <typename T, typename U> void *operator new(std::type_identity<T>, U, std::align_val_t); // #17
   // expected-error@#17 {{type aware 'operator new' cannot take a dependent type as its 2nd parameter;}}
+  // no_type_aware-error@#17 {{type aware 'operator new' declared but type aware allocator support is disabled. Pass -fcxx-type-aware-allocators to enable it}}
   // precxx26-warning@#17 {{type aware allocators are a C++2c extension}}
   template <typename T, typename U> void operator delete(std::type_identity<T>, U, size_t, std::align_val_t); // #18
   // expected-error@#18 {{type aware 'operator delete' cannot take a dependent type as its 2nd parameter;}}
+  // no_type_aware-error@#18 {{type aware 'operator delete' declared but type aware allocator support is disabled. Pass -fcxx-type-aware-allocators to enable it}}
   // precxx26-warning@#18 {{type aware allocators are a C++2c extension}}
   template <typename T, typename U> void operator delete(std::type_identity<T>, S8 *, std::destroying_delete_t, U, std::align_val_t); // #19
   // expected-error@#19 {{destroying delete is not permitted to be type aware}}
+  // no_type_aware-error@#19 {{type aware 'operator delete' declared but type aware allocator support is disabled. Pass -fcxx-type-aware-allocators to enable it}}
 };
 
 template <typename T> using Alias = T;
@@ -93,58 +114,83 @@ template <typename T> using TypeIdentityAlias = std::type_identity<T>;
 typedef std::type_identity<double> TypedefAlias;
 using UsingAlias = std::type_identity<float>;
 struct S9 {
-  void *operator new(Alias<size_t>, std::align_val_t);
+  void *operator new(Alias<size_t>, std::align_val_t); // #S9_typed_new
   template <typename T> void *operator new(Alias<std::type_identity<T>>, Alias<size_t>, std::align_val_t); // #20
   // precxx26-warning@#20 {{type aware allocators are a C++2c extension}}
+  // no_type_aware-error at -2 {{type aware 'operator new' declared but type aware allocator support is disabled. Pass -fcxx-type-aware-allocators to enable it}}
   void *operator new(Alias<std::type_identity<int>>, size_t, std::align_val_t);
   // precxx26-warning at -1 {{type aware allocators are a C++2c extension}}
+  // no_type_aware-error at -2 {{type aware 'operator new' declared but type aware allocator support is disabled. Pass -fcxx-type-aware-allocators to enable it}}
   template <typename T> void operator delete(Alias<std::type_identity<T>>, void *, size_t, std::align_val_t); // #21
   // precxx26-warning@#21{{type aware allocators are a C++2c extension}}
-  void operator delete(Alias<std::type_identity<int>>, void *, size_t, std::align_val_t);
+  // no_type_aware-error@#21 {{type aware 'operator delete' declared but type aware allocator support is disabled. Pass -fcxx-type-aware-allocators to enable it}}
+  void operator delete(Alias<std::type_identity<int>>, void *, size_t, std::align_val_t); // #S9_typed_delete
   // precxx26-warning at -1 {{type aware allocators are a C++2c extension}}
+  // no_type_aware-error at -2 {{type aware 'operator delete' declared but type aware allocator support is disabled. Pass -fcxx-type-aware-allocators to enable it}}
 };
 struct S10 {
   template <typename T> void *operator new(TypeIdentityAlias<T>, size_t, std::align_val_t); // #22
   // precxx26-warning@#22 {{type aware allocators are a C++2c extension}}
+  // no_type_aware-error at -2 {{type aware 'operator new' declared but type aware allocator support is disabled. Pass -fcxx-type-aware-allocators to enable it}}
   void *operator new(TypeIdentityAlias<int>, size_t, std::align_val_t);
   // precxx26-warning at -1 {{type aware allocators are a C++2c extension}}
+  // no_type_aware-error at -2 {{type aware 'operator new' declared but type aware allocator support is disabled. Pass -fcxx-type-aware-allocators to enable it}}
   template <typename T> void operator delete(TypeIdentityAlias<T>, void *, size_t, std::align_val_t); // #23
+  // precxx26-warning@#23 {{type aware allocators are a C++2c extension}}
+  // no_type_aware-error@#23 {{type aware 'operator delete' declared but type aware allocator support is disabled. Pass -fcxx-type-aware-allocators to enable it}}
+  void operator delete(TypeIdentityAlias<int>, void *, size_t, std::align_val_t); // #S10_typed_delete
   // precxx26-warning at -1 {{type aware allocators are a C++2c extension}}
-  void operator delete(TypeIdentityAlias<int>, void *, size_t, std::align_val_t);
-  // precxx26-warning at -1 {{type aware allocators are a C++2c extension}}
+  // no_type_aware-error at -2 {{type aware 'operator delete' declared but type aware allocator support is disabled. Pass -fcxx-type-aware-allocators to enable it}}
 };
 
 void test() {
   S9 *s9 = new S9;
+  // no_type_aware-error at -1 {{no matching function for call to 'operator new'}}
+  // no_type_aware-note@#S9_typed_new {{candidate function not viable: requires 2 arguments, but 1 was provided}}
   delete s9;
+  // no_type_aware-error at -1 {{no suitable member 'operator delete' in 'S9'}}
+  // no_type_aware-note@#S9_typed_delete {{member 'operator delete' declared here}}
   S10 *s10 = new S10;
+  // no_type_aware-error at -1 {{no matching function for call to 'operator new'}}
   delete s10;
+  // no_type_aware-error at -1 {{no suitable member 'operator delete' in 'S10'}}
+  // no_type_aware-note@#S10_typed_delete {{member 'operator delete' declared here}}
 }
 
 struct S11 {
   template <typename T> void *operator new(TypedefAlias, size_t, std::align_val_t);
   // precxx26-warning at -1 {{type aware allocators are a C++2c extension}}
+  // no_type_aware-error at -2 {{type aware 'operator new' declared but type aware allocator support is disabled. Pass -fcxx-type-aware-allocators to enable it}}
   void *operator new(TypedefAlias, size_t, std::align_val_t);
   // precxx26-warning at -1 {{type aware allocators are a C++2c extension}}
+  // no_type_aware-error at -2 {{type aware 'operator new' declared but type aware allocator support is disabled. Pass -fcxx-type-aware-allocators to enable it}}
   template <typename T> void operator delete(TypedefAlias, void *, size_t, std::align_val_t);
   // precxx26-warning at -1 {{type aware allocators are a C++2c extension}}
+  // no_type_aware-error at -2 {{type aware 'operator delete' declared but type aware allocator support is disabled. Pass -fcxx-type-aware-allocators to enable it}}
   void operator delete(TypedefAlias, void *, size_t, std::align_val_t);
   // precxx26-warning at -1 {{type aware allocators are a C++2c extension}}
+  // no_type_aware-error at -2 {{type aware 'operator delete' declared but type aware allocator support is disabled. Pass -fcxx-type-aware-allocators to enable it}}
 };
 struct S12 {
   template <typename T> void *operator new(UsingAlias, size_t, std::align_val_t);
   // precxx26-warning at -1 {{type aware allocators are a C++2c extension}}
+  // no_type_aware-error at -2 {{type aware 'operator new' declared but type aware allocator support is disabled. Pass -fcxx-type-aware-allocators to enable it}}
   void *operator new(UsingAlias, size_t, std::align_val_t);
   // precxx26-warning at -1 {{type aware allocators are a C++2c extension}}
+  // no_type_aware-error at -2 {{type aware 'operator new' declared but type aware allocator support is disabled. Pass -fcxx-type-aware-allocators to enable it}}
   template <typename T> void operator delete(UsingAlias, void *, size_t, std::align_val_t);
   // precxx26-warning at -1 {{type aware allocators are a C++2c extension}}
+  // no_type_aware-error at -2 {{type aware 'operator delete' declared but type aware allocator support is disabled. Pass -fcxx-type-aware-allocators to enable it}}
   void operator delete(UsingAlias, void *, size_t, std::align_val_t);
   // precxx26-warning at -1 {{type aware allocators are a C++2c extension}}
+  // no_type_aware-error at -2 {{type aware 'operator delete' declared but type aware allocator support is disabled. Pass -fcxx-type-aware-allocators to enable it}}
 };
 
 struct S13 {
   void *operator new(std::type_identity<S13>, size_t, std::align_val_t);
   // precxx26-warning at -1 {{type aware allocators are a C++2c extension}}
+  // no_type_aware-error at -2 {{type aware 'operator new' declared but type aware allocator support is disabled. Pass -fcxx-type-aware-allocators to enable it}}
   void operator delete(std::type_identity<S13>, void*, size_t, std::align_val_t);
   // precxx26-warning at -1 {{type aware allocators are a C++2c extension}}
+  // no_type_aware-error at -2 {{type aware 'operator delete' declared but type aware allocator support is disabled. Pass -fcxx-type-aware-allocators to enable it}}
 };



More information about the cfe-commits mailing list