1 // RUN: %clang_cc1 -std=c++2a -fexceptions -verify %s 2 // RUN: %clang_cc1 -std=c++2a -verify %s 3 4 namespace std { 5 using size_t = decltype(sizeof(0)); 6 enum class align_val_t : size_t; 7 8 struct destroying_delete_t { 9 struct __construct { explicit __construct() = default; }; 10 explicit destroying_delete_t(__construct) {} 11 }; 12 13 inline constexpr destroying_delete_t destroying_delete(destroying_delete_t::__construct()); 14 } 15 16 void operator delete(void*, std::destroying_delete_t); // ok, just a placement delete 17 18 struct A; 19 void operator delete(A*, std::destroying_delete_t); // expected-error {{first parameter of 'operator delete' must have type 'void *'}} 20 21 struct A { 22 void operator delete(A*, std::destroying_delete_t); 23 void operator delete(A*, std::destroying_delete_t, std::size_t); 24 void operator delete(A*, std::destroying_delete_t, std::align_val_t); 25 void operator delete(A*, std::destroying_delete_t, std::size_t, std::align_val_t); 26 void operator delete(A*, std::destroying_delete_t, int); // expected-error {{destroying operator delete can have only an optional size and optional alignment parameter}} 27 // FIXME: It's probably a language defect that we permit usual operator delete to be variadic. 28 void operator delete(A*, std::destroying_delete_t, std::size_t, ...); 29 30 void operator delete(struct X*, std::destroying_delete_t, std::size_t, ...); // expected-error {{first parameter of 'operator delete' must have type 'A *'}} 31 32 void operator delete(void*, std::size_t); 33 }; 34 35 void delete_A(A *a) { delete a; } 36 37 namespace convert_param { 38 struct A { 39 void operator delete( 40 A*, 41 std::destroying_delete_t); 42 }; 43 struct B : private A { using A::operator delete; }; // expected-note 2{{declared private here}} 44 struct C : B {}; 45 void delete_C(C *c) { delete c; } // expected-error {{cannot cast 'C' to its private base class 'A'}} 46 47 // expected-error@-7 {{cannot cast 'convert_param::D' to its private base class 'A'}} 48 struct D : B { virtual ~D() {} }; // expected-note {{while checking implicit 'delete this' for virtual destructor}} 49 } 50 51 namespace delete_selection { 52 struct B { 53 void operator delete(void*) = delete; 54 void operator delete(B *, std::destroying_delete_t) = delete; // expected-note {{deleted}} 55 }; 56 void delete_B(B *b) { delete b; } // expected-error {{deleted}} 57 58 struct C { 59 C(); 60 void *operator new(std::size_t); 61 void operator delete(void*) = delete; // expected-note 0-1 {{deleted here}} 62 void operator delete(C *, std::destroying_delete_t) = delete; 63 }; 64 // TODO: We only diagnose the use of a deleted operator delete when exceptions 65 // are enabled. Otherwise we don't bother doing the lookup. 66 #ifdef __EXCEPTIONS 67 // expected-error@+2 {{attempt to use a deleted function}} 68 #endif 69 C *new_C() { return new C; } 70 71 struct D { 72 void operator delete(D *, std::destroying_delete_t) = delete; // expected-note {{deleted}} 73 void operator delete(D *, std::destroying_delete_t, std::align_val_t) = delete; 74 }; 75 void delete_D(D *d) { delete d; } // expected-error {{deleted}} 76 77 struct alignas(__STDCPP_DEFAULT_NEW_ALIGNMENT__ * 2) E { 78 void operator delete(E *, std::destroying_delete_t) = delete; 79 void operator delete(E *, std::destroying_delete_t, std::align_val_t) = delete; // expected-note {{deleted}} 80 }; 81 void delete_E(E *e) { delete e; } // expected-error {{deleted}} 82 83 struct F { 84 void operator delete(F *, std::destroying_delete_t) = delete; // expected-note {{deleted}} 85 void operator delete(F *, std::destroying_delete_t, std::size_t) = delete; 86 }; 87 void delete_F(F *f) { delete f; } // expected-error {{deleted}} 88 89 struct G { 90 void operator delete(G *, std::destroying_delete_t, std::align_val_t) = delete; 91 void operator delete(G *, std::destroying_delete_t, std::size_t) = delete; // expected-note {{deleted}} 92 }; 93 void delete_G(G *g) { delete g; } // expected-error {{deleted}} 94 95 struct H { 96 void operator delete(H *, std::destroying_delete_t, std::align_val_t) = delete; // expected-note {{deleted}} 97 void operator delete(H *, std::destroying_delete_t, std::size_t, std::align_val_t) = delete; 98 }; 99 void delete_H(H *h) { delete h; } // expected-error {{deleted}} 100 101 struct alignas(__STDCPP_DEFAULT_NEW_ALIGNMENT__ * 2) I { 102 void operator delete(I *, std::destroying_delete_t, std::size_t) = delete; 103 void operator delete(I *, std::destroying_delete_t, std::size_t, std::align_val_t) = delete; // expected-note {{deleted}} 104 }; 105 void delete_I(I *i) { delete i; } // expected-error {{deleted}} 106 } 107 108 namespace first_param_conversion { 109 struct A { 110 void operator delete(A *, std::destroying_delete_t); 111 }; 112 void f(const volatile A *a) { 113 delete a; // ok 114 } 115 116 struct B { 117 void operator delete(B *, std::destroying_delete_t); 118 }; 119 struct C : B {}; 120 struct D : B {}; 121 struct E : C, D {}; 122 void g(E *e) { 123 delete e; // expected-error {{ambiguous conversion from derived class 'E' to base class 'B':}} 124 } 125 } 126 127 namespace templated { 128 template<typename T> using id_alias = T; 129 template<typename T> struct id_struct { using type = T; }; 130 131 template<typename T> struct A { 132 void operator delete(A *, std::destroying_delete_t); 133 }; 134 template<typename T> struct B { 135 void operator delete(B<T> *, std::destroying_delete_t); 136 }; 137 template<typename T> struct C { 138 void operator delete(id_alias<C> *, std::destroying_delete_t); 139 }; 140 template<typename T> struct D { 141 void operator delete(typename id_struct<D>::type *, std::destroying_delete_t); // expected-error {{use 'D<T> *'}} 142 }; 143 } 144 145 namespace dtor_access { 146 struct S { 147 void operator delete(S *p, std::destroying_delete_t); 148 private: 149 ~S(); 150 }; 151 152 // C++20 [expr.delete]p12 says this is ill-formed, but GCC accepts and we 153 // filed CWG2889 to resolve in the same way. 154 void f() { delete new S; } 155 156 struct T { 157 void operator delete(T *, std::destroying_delete_t); 158 protected: 159 virtual ~T(); // expected-note {{here}} 160 }; 161 162 struct U : T { 163 void operator delete(void *); 164 private: 165 ~U() override; 166 }; 167 168 void g() { delete (T *)new U; } // expected-error {{calling a protected destructor of class 'T'}} 169 } 170 171 namespace delete_from_new { 172 struct A { 173 A(); // might throw 174 void operator delete(A *, std::destroying_delete_t) = delete; 175 }; 176 struct B { 177 B(); // might throw 178 void operator delete(void *) = delete; // #member-delete-from-new 179 void operator delete(B *, std::destroying_delete_t) = delete; 180 }; 181 void f() { 182 new A; // calls ::operator delete 183 new B; // calls B::operator delete 184 #ifdef __EXCEPTIONS 185 // expected-error@-2 {{attempt to use a deleted function}} 186 // expected-note@#member-delete-from-new {{deleted here}} 187 #endif 188 } 189 } 190 191 namespace GH96191 { 192 struct S {}; 193 struct T { 194 void operator delete(S) { } // expected-error {{first parameter of 'operator delete' must have type 'void *'}} 195 }; 196 197 void foo(T *t) { delete t; } 198 } 199