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 <oli...@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@-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@-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@-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@-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@-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@-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@-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@-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@-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@-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@-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@-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@-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@-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@-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@-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@-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@-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@-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@-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@-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@-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@-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@-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@-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@-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@-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@-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@-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@-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@-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@-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@-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@-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@-1 {{'operator new' cannot take a dependent type as its 1st parameter}} +// both-error@-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@-1 {{'operator delete' cannot take a dependent type as its 1st parameter}} +// both-error@-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@-1 {{'operator new' cannot take a dependent type as its 1st parameter}} +// both-error@-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@-1 {{type aware 'operator new' must have at least three parameters}} +// no_taa_disabled-error@-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@-1 {{type aware 'operator new' takes type std::align_val_t ('std::align_val_t') as 3rd parameter}} +// no_taa_disabled-error@-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@-1 {{type aware 'operator delete' must have at least four parameters}} +// no_taa_disabled-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(std::type_identity<int>, void *, size_t); // expected-error@-1 {{type aware 'operator delete' must have at least four parameters}} +// no_taa_disabled-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(std::type_identity<int>, void *, std::align_val_t); // expected-error@-1 {{type aware 'operator delete' must have at least four parameters}} +// no_taa_disabled-error@-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@-1 {{type aware 'operator delete' must have at least four parameters}} +// no_taa_disabled-error@-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@-1 {{type aware 'operator delete' must have at least four parameters}} +// no_taa_disabled-error@-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@-1 {{type aware 'operator delete' must have at least four parameters}} +// no_taa_disabled-error@-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@-1 {{type aware 'operator new' must have at least three parameters}} +// no_taa_disabled-error@-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@-1 {{type aware 'operator delete' cannot take a dependent type as its 2nd parameter; use 'void *' instead}} +// no_taa_disabled-error@-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@-1 {{type aware 'operator delete' cannot take a dependent type as its 3rd parameter; use 'unsigned long' instead}} +// no_taa_disabled-error@-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@-1 {{type aware 'operator delete' cannot take a dependent type as its 4th parameter; use 'std::align_val_t' instead}} +// no_taa_disabled-error@-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@-1 {{type aware 'operator new' cannot take a dependent type as its 2nd parameter; use size_t ('unsigned long') instead}} +// no_taa_disabled-error@-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@-1 {{type aware 'operator delete' cannot take a dependent type as its 2nd parameter; use 'void *' instead}} +// no_taa_disabled-error@-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@-1 {{type aware 'operator new' cannot take a dependent type as its 2nd parameter; use size_t ('unsigned long') instead}} +// no_taa_disabled-error@-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@-1 {{type aware 'operator delete' cannot take a dependent type as its 2nd parameter; use 'void *' instead}} +// no_taa_disabled-error@-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@-1 {{type aware 'operator delete' cannot take a dependent type as its 4th parameter; use 'std::align_val_t' instead}} +// no_taa_disabled-error@-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@-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@-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@-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@-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@-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@-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@-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@-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@-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@-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@-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@-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@-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@-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@-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@-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@-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@-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@-1 {{in instantiation of template class 'S7<int>' requested here}} + // no_type_aware-note@-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@-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@-1 {{type aware allocators are a C++2c extension}} + // no_type_aware-error@-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@-1 {{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}} }; 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@-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@-1 {{type aware allocators are a C++2c extension}} + // no_type_aware-error@-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@-1 {{type aware allocators are a C++2c extension}} - void operator delete(TypeIdentityAlias<int>, void *, size_t, std::align_val_t); - // precxx26-warning@-1 {{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 test() { S9 *s9 = new S9; + // no_type_aware-error@-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@-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@-1 {{no matching function for call to 'operator new'}} delete s10; + // no_type_aware-error@-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@-1 {{type aware allocators are a C++2c extension}} + // no_type_aware-error@-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@-1 {{type aware allocators are a C++2c extension}} + // no_type_aware-error@-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@-1 {{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(TypedefAlias, void *, size_t, std::align_val_t); // precxx26-warning@-1 {{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}} }; struct S12 { template <typename T> void *operator new(UsingAlias, size_t, std::align_val_t); // precxx26-warning@-1 {{type aware allocators are a C++2c extension}} + // no_type_aware-error@-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@-1 {{type aware allocators are a C++2c extension}} + // no_type_aware-error@-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@-1 {{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(UsingAlias, void *, size_t, std::align_val_t); // precxx26-warning@-1 {{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}} }; struct S13 { void *operator new(std::type_identity<S13>, size_t, std::align_val_t); // precxx26-warning@-1 {{type aware allocators are a C++2c extension}} + // no_type_aware-error@-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@-1 {{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}} }; _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits