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 'convert_param::C' to its private base class 'convert_param::A'}} |
46 | |
47 | // expected-error@-7 {{cannot cast 'convert_param::D' to its private base class 'convert_param::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; |
62 | void operator delete(C *, std::destroying_delete_t) = delete; // expected-note 0-1 {{deleted here}} |
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 'first_param_conversion::E' to base class 'first_param_conversion::B':}} |
124 | } |
125 | } |
126 | |