263 lines · cpp
1// RUN: %clang_cc1 -triple arm64-apple-macosx -fsyntax-only -verify %s -std=c++26 -Wno-ext-cxx-type-aware-allocators -fexceptions -fcxx-exceptions -fsized-deallocation -faligned-allocation -Wno-non-c-typedef-for-linkage -DDEFAULT_DELETE=12// RUN: %clang_cc1 -triple arm64-apple-macosx -fsyntax-only -verify %s -std=c++26 -Wno-ext-cxx-type-aware-allocators -fexceptions -fcxx-exceptions -fno-sized-deallocation -faligned-allocation -Wno-non-c-typedef-for-linkage -DDEFAULT_DELETE=03// RUN: %clang_cc1 -triple arm64-apple-macosx -fsyntax-only -verify %s -std=c++26 -Wno-ext-cxx-type-aware-allocators -fexceptions -fcxx-exceptions -fsized-deallocation -fno-aligned-allocation -Wno-non-c-typedef-for-linkage -DDEFAULT_DELETE=14// RUN: %clang_cc1 -triple arm64-apple-macosx -fsyntax-only -verify %s -std=c++26 -Wno-ext-cxx-type-aware-allocators -fexceptions -fcxx-exceptions -fno-sized-deallocation -fno-aligned-allocation -Wno-non-c-typedef-for-linkage -DDEFAULT_DELETE=05 6namespace std {7 template <class T> struct type_identity {};8 enum class align_val_t : __SIZE_TYPE__ {};9}10 11static_assert(__has_extension(cxx_type_aware_allocators), "Verifying the type aware extension flag is set");12 13using size_t = __SIZE_TYPE__;14 15void *operator new(size_t); // #default_operator_new16 17#if DEFAULT_DELETE==018void operator delete(void*) noexcept; // #default_operator_delete19#elif DEFAULT_DELETE==120void operator delete(void*, size_t) noexcept; // #default_operator_delete21#elif DEFAULT_DELETE==222void operator delete(void*, std::align_val_t) noexcept; // #default_operator_delete23#elif DEFAULT_DELETE==324void operator delete(void*, size_t, std::align_val_t) noexcept; // #default_operator_delete25#endif26 27struct Invalid1 {28 // expected-error@-1 {{declaration of type aware 'operator new' in 'Invalid1' must have matching type aware 'operator delete'}}29 void *operator new(std::type_identity<Invalid1>, size_t, std::align_val_t);30 // expected-note@-1 {{unmatched type aware 'operator new' declared here}}31};32struct Invalid2 {33 // expected-error@-1 {{declaration of type aware 'operator new' in 'Invalid2' must have matching type aware 'operator delete'}}34 template <class T> void *operator new(std::type_identity<T>, size_t, std::align_val_t); // #Invalid2_new35 // expected-note@-1 {{unmatched type aware 'operator new' declared here}}36};37struct Invalid3 {38 // expected-error@-1 {{declaration of type aware 'operator delete' in 'Invalid3' must have matching type aware 'operator new'}}39 void operator delete(std::type_identity<Invalid3>, void*, size_t, std::align_val_t);40 // expected-note@-1 {{unmatched type aware 'operator delete' declared here}}41};42struct Invalid4 {43 // expected-error@-1 {{declaration of type aware 'operator delete' in 'Invalid4' must have matching type aware 'operator new'}}44 template <class T> void operator delete(std::type_identity<T>, void*, size_t, std::align_val_t); // #Invalid4_delete45 // expected-note@-1 {{unmatched type aware 'operator delete' declared here}}46};47struct Invalid5 {48 // expected-error@-1 {{declaration of type aware 'operator new[]' in 'Invalid5' must have matching type aware 'operator delete[]'}}49 void *operator new[](std::type_identity<Invalid5>, size_t, std::align_val_t);50 // expected-note@-1 {{unmatched type aware 'operator new[]' declared here}}51};52struct Invalid6 {53 // expected-error@-1 {{declaration of type aware 'operator new[]' in 'Invalid6' must have matching type aware 'operator delete[]'}}54 template <class T> void *operator new[](std::type_identity<T>, size_t, std::align_val_t);55 // expected-note@-1 {{unmatched type aware 'operator new[]' declared here}}56};57struct Invalid7 {58 // expected-error@-1 {{declaration of type aware 'operator delete[]' in 'Invalid7' must have matching type aware 'operator new[]'}}59 void operator delete[](std::type_identity<Invalid7>, void*, size_t, std::align_val_t);60 // expected-note@-1 {{unmatched type aware 'operator delete[]' declared here}}61};62struct Invalid8 {63 // expected-error@-1 {{declaration of type aware 'operator delete[]' in 'Invalid8' must have matching type aware 'operator new[]'}}64 template <class T> void operator delete[](std::type_identity<T>, void*, size_t, std::align_val_t);65 // expected-note@-1 {{unmatched type aware 'operator delete[]' declared here}}66};67 68// Invalid9 and Invalid10 will ensure we report the correct owner for the69// resolved, but unmatched, new and delete70struct Invalid9: Invalid2 {};71struct Invalid10: Invalid4 {};72// Invalid11 inherits a "matching" new and delete pair (so no inheritance ambiguity)73// but the resolved operators are from different scopes74struct Invalid11 : Invalid2, Invalid4 {};75struct Invalid12 : Invalid2, Invalid4 {76 using Invalid2::operator new;77 using Invalid4::operator delete;78};79 80struct TestClass1 {81 void *operator new(std::type_identity<TestClass1>, size_t, std::align_val_t); // #TestClass1_new82 void operator delete(std::type_identity<int>, void *, size_t, std::align_val_t); // #TestClass1_delete83};84 85struct TestClass2 {86 void *operator new(std::type_identity<int>, size_t, std::align_val_t); // #TestClass2_new87 void operator delete(std::type_identity<TestClass2>, void *, size_t, std::align_val_t); // #TestClass2_delete88};89 90void basic_tests() {91 TestClass1 * tc1 = new TestClass1;92 delete tc1;93 // expected-error@-1 {{no suitable member 'operator delete' in 'TestClass1'}}94 // expected-note@#TestClass1_delete {{member 'operator delete' declared here}}95 TestClass2 * tc2 = new TestClass2;96 // expected-error@-1 {{no matching function for call to 'operator new'}}97 delete tc2;98 Invalid9 * i9 = new Invalid9;99 // expected-error@-1 {{type aware 'operator new' requires a matching type aware 'operator delete' to be declared in the same scope}}100 // expected-note@#Invalid2_new {{type aware 'operator new' declared here in 'Invalid2'}}101 delete i9;102 Invalid10 * i10 = new Invalid10;103 // expected-error@-1 {{type aware 'operator delete' requires a matching type aware 'operator new' to be declared in the same scope}}104 // expected-note@#Invalid4_delete {{type aware 'operator delete' declared here in 'Invalid4'}}105 // expected-note@#default_operator_new {{non-type aware 'operator new' declared here in the global namespace}}106 delete i10;107 Invalid11 * i11 = new Invalid11;108 // expected-error@-1 {{type aware 'operator new' requires a matching type aware 'operator delete' to be declared in the same scope}}109 // expected-note@#Invalid2_new {{type aware 'operator new' declared here in 'Invalid2'}}110 // expected-note@#Invalid4_delete {{type aware 'operator delete' declared here in 'Invalid4'}}111 delete i11;112 Invalid12 * i12 = new Invalid12;113 // expected-error@-1 {{type aware 'operator new' requires a matching type aware 'operator delete' to be declared in the same scope}}114 // expected-note@#Invalid2_new {{type aware 'operator new' declared here in 'Invalid2'}}115 // expected-note@#Invalid4_delete {{type aware 'operator delete' declared here in 'Invalid4'}}116 delete i12;117}118 119struct Baseclass1 {120 void *operator new(std::type_identity<Baseclass1>, size_t, std::align_val_t);121 void operator delete(std::type_identity<Baseclass1>, void *, size_t, std::align_val_t); // #Baseclass1_delete122};123 124struct Subclass1 : Baseclass1 {125 Subclass1();126};127 128struct Baseclass2 {129 template <class T> void *operator new(std::type_identity<T>, size_t, std::align_val_t);130 void operator delete(std::type_identity<Baseclass2>, void *, size_t, std::align_val_t); // #Baseclass2_delete131};132 133struct Subclass2 : Baseclass2 {134 Subclass2();135};136 137struct Baseclass3 {138 template <class T> void *operator new(std::type_identity<T>, size_t, std::align_val_t);139 template <class T> void operator delete(std::type_identity<T>, void *, size_t, std::align_val_t);140};141 142struct Subclass3_1 : Baseclass3 {143 Subclass3_1();144 void *operator new(std::type_identity<int>, size_t, std::align_val_t);145 template <class T> void operator delete(std::type_identity<T>, void *, size_t, std::align_val_t);146};147 148struct Subclass3_2 : Baseclass3 {149 Subclass3_2();150 template <class T> void *operator new(std::type_identity<T>, size_t, std::align_val_t);151 void operator delete(std::type_identity<int>, void *, size_t, std::align_val_t); // #Subclass3_2_delete152};153 154 155void test_subclasses() {156 Subclass1 * sc1 = new Subclass1;157 // expected-error@-1 {{no matching function for call to 'operator new'}}158 delete sc1;159 // expected-error@-1 {{no suitable member 'operator delete' in 'Subclass1'}}160 // expected-note@#Baseclass1_delete {{member 'operator delete' declared here}}161 Subclass2 * sc2 = new Subclass2;162 delete sc2;163 // expected-error@-1 {{no suitable member 'operator delete' in 'Subclass2'}}164 // expected-note@#Baseclass2_delete {{member 'operator delete' declared here}}165 Subclass3_1 * sc3_1 = new Subclass3_1;166 // expected-error@-1 {{no matching function for call to 'operator new'}}167 delete sc3_1;168 Subclass3_2 * sc3_2 = new Subclass3_2;169 delete sc3_2;170 // expected-error@-1 {{no suitable member 'operator delete' in 'Subclass3_2'}}171 // expected-note@#Subclass3_2_delete {{member 'operator delete' declared here}}172}173 174template <class A, class B> constexpr bool same_type_v = false;175template <class A> constexpr bool same_type_v<A, A> = true;176 177template <class T> struct InvalidConstrainedOperator {178 template <class U> void *operator new(std::type_identity<U>, size_t, std::align_val_t);179 template <class U> requires (same_type_v<T, int>) void operator delete(std::type_identity<U>, void *, size_t, std::align_val_t); // #InvalidConstrainedOperator_delete180};181 182struct Context;183template <class T> struct InvalidConstrainedCleanup {184 template <class U> void *operator new(std::type_identity<U>, size_t, std::align_val_t, Context&); // #InvalidConstrainedCleanup_placement_new185 template <class U> requires (same_type_v<T, int>) void operator delete(std::type_identity<U>, void *, size_t, std::align_val_t, Context&); // #InvalidConstrainedCleanup_delete186 template <class U> void operator delete(std::type_identity<U>, void *, size_t, std::align_val_t);187};188 189void test_incompatible_constrained_operators(Context &Ctx) {190 InvalidConstrainedOperator<int> *ico1 = new InvalidConstrainedOperator<int>;191 delete ico1;192 InvalidConstrainedOperator<float> *ico2 = new InvalidConstrainedOperator<float>;193 delete ico2;194 // expected-error@-1 {{no suitable member 'operator delete' in 'InvalidConstrainedOperator<float>'}}195 // expected-note@#InvalidConstrainedOperator_delete {{member 'operator delete' declared here}}196 InvalidConstrainedCleanup<int> *icc1 = new (Ctx) InvalidConstrainedCleanup<int>;197 delete icc1;198 InvalidConstrainedCleanup<float> *icc2 = new (Ctx) InvalidConstrainedCleanup<float>;199 // expected-error@-1 {{type aware 'operator new' requires a matching type aware placement 'operator delete' to be declared in the same scope}}200 // expected-note@#InvalidConstrainedCleanup_placement_new {{type aware 'operator new' declared here in 'InvalidConstrainedCleanup<float>'}}201 delete icc2;202}203 204typedef struct {205 // expected-error@-1 {{declaration of type aware 'operator new' in '(unnamed struct}}206 // expected-note@#AnonymousClass1_new {{unmatched type aware 'operator new' declared here}}207 template <class T> void *operator new(std::type_identity<T>, size_t, std::align_val_t); // #AnonymousClass1_new208} AnonymousClass1;209 210typedef struct {211 // expected-error@-1 {{declaration of type aware 'operator delete' in '(unnamed struct}}212 template <class T> void operator delete(std::type_identity<T>, void*, size_t, std::align_val_t); // #AnonymousClass2_delete213} AnonymousClass2;214 215typedef struct {216 template <class T> void *operator new(std::type_identity<T>, size_t, std::align_val_t);217 template <class T> void operator delete(std::type_identity<T>, void*, size_t, std::align_val_t);218} AnonymousClass3;219 220using AnonymousClass4 = struct {};221using AnonymousClass5 = struct {};222using AnonymousClass6 = struct {};223using AnonymousClass7 = struct {224 // expected-error@-1 {{declaration of type aware 'operator new' in}}225 // expected-note@#AnonymousClass7_new {{unmatched type aware 'operator new' declared here}}226 template <class T> void *operator new(std::type_identity<T>, size_t, std::align_val_t, Context&); // #AnonymousClass7_new227};228 229 230void *operator new(std::type_identity<AnonymousClass4>, size_t, std::align_val_t); // #AnonymousClass4_new231void operator delete(std::type_identity<AnonymousClass5>, void*, size_t, std::align_val_t); // #AnonymousClass5_delete232void *operator new(std::type_identity<AnonymousClass6>, size_t, std::align_val_t, Context&); // #AnonymousClass6_placement_new233void operator delete(std::type_identity<AnonymousClass6>, void*, size_t, std::align_val_t);234void test_anonymous_types(Context &Ctx) {235 AnonymousClass1 *ac1 = new AnonymousClass1;236 // expected-error@-1 {{type aware 'operator new' requires a matching type aware 'operator delete' to be declared in the same scope}}237 // expected-note@#AnonymousClass1_new {{type aware 'operator new' declared here in 'AnonymousClass1'}}238 239 delete ac1;240 AnonymousClass2 *ac2 = new AnonymousClass2;241 // expected-error@-1 {{type aware 'operator delete' requires a matching type aware 'operator new' to be declared in the same scope}}242 // expected-note@#AnonymousClass2_delete {{unmatched type aware 'operator delete' declared here}}243 // expected-note@#AnonymousClass2_delete {{type aware 'operator delete' declared here in 'AnonymousClass2'}}244 // expected-note@#default_operator_new {{non-type aware 'operator new' declared here in the global namespace}}245 246 delete ac2;247 AnonymousClass3 *ac3 = new AnonymousClass3;248 delete ac3;249 AnonymousClass4 *ac4 = new AnonymousClass4;250 // expected-error@-1 {{type aware 'operator new' requires a matching type aware 'operator delete' to be declared in the same scope}}251 // expected-note@#AnonymousClass4_new {{type aware 'operator new' declared here in the global namespace}}252 delete ac4;253 AnonymousClass5 *ac5 = new AnonymousClass5;254 // expected-error@-1 {{type aware 'operator delete' requires a matching type aware 'operator new' to be declared in the same scope}}255 // expected-note@#AnonymousClass5_delete {{type aware 'operator delete' declared here}}256 // expected-note@#default_operator_new {{non-type aware 'operator new' declared here in the global namespace}}257 delete ac5;258 AnonymousClass6 *ac6 = new (Ctx) AnonymousClass6;259 // expected-error@-1 {{type aware 'operator new' requires a matching type aware placement 'operator delete' to be declared in the same scope}}260 // expected-note@#AnonymousClass6_placement_new {{type aware 'operator new' declared here in the global namespace}}261 // expected-note@#default_operator_delete {{non-type aware 'operator delete' declared here in the global namespace}}262 delete ac6;263}