199 lines · cpp
1// RUN: %clang_cc1 -std=c++2a -fexceptions -verify %s2// RUN: %clang_cc1 -std=c++2a -verify %s3 4namespace 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 16void operator delete(void*, std::destroying_delete_t); // ok, just a placement delete17 18struct A;19void operator delete(A*, std::destroying_delete_t); // expected-error {{1st parameter of 'operator delete' must have type 'void *'}}20 21struct 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 {{1st parameter of destroying 'operator delete' must have type 'A *'}}31 32 void operator delete(void*, std::size_t);33};34 35void delete_A(A *a) { delete a; }36 37namespace 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 51namespace 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 exceptions65 // are enabled. Otherwise we don't bother doing the lookup.66#ifdef __EXCEPTIONS67 // expected-error@+2 {{attempt to use a deleted function}}68#endif69 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 108namespace 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; // ok114 }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 127namespace 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 'templated::D<T> *'}}142 };143}144 145namespace 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 we153 // 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 171namespace delete_from_new {172 struct A {173 A(); // might throw174 void operator delete(A *, std::destroying_delete_t) = delete;175 };176 struct B {177 B(); // might throw178 void operator delete(void *) = delete; // #member-delete-from-new179 void operator delete(B *, std::destroying_delete_t) = delete;180 };181 void f() {182 new A; // calls ::operator delete183 new B; // calls B::operator delete184#ifdef __EXCEPTIONS185 // expected-error@-2 {{attempt to use a deleted function}}186 // expected-note@#member-delete-from-new {{deleted here}}187#endif188 }189}190 191namespace GH96191 {192 struct S {};193 struct T {194 void operator delete(S) { } // expected-error {{1st parameter of 'operator delete' must have type 'void *'}}195 };196 197 void foo(T *t) { delete t; }198}199