1 // RUN: %clang_cc1 -fexceptions -std=c++2a -fsized-deallocation -fno-aligned-allocation -verify %s
2 // RUN: %clang_cc1 -fexceptions -std=c++17 -fsized-deallocation -fno-aligned-allocation -verify %s
3 // RUN: %clang_cc1 -fexceptions -std=c++14 -fsized-deallocation -faligned-allocation -DHAS_ALIGN -verify %s
4 // RUN: %clang_cc1 -fexceptions -std=c++11 -fsized-deallocation -faligned-allocation -DHAS_ALIGN -verify %s
5 
6 // Test that we handle aligned deallocation, sized deallocation, and destroying
7 // delete as usual deallocation functions even if they are used as extensions
8 // prior to C++17.
9 
10 namespace std {
11 using size_t = decltype(sizeof(0));
12 enum class align_val_t : size_t;
13 
14 struct destroying_delete_t {
15   struct __construct { explicit __construct() = default; };
destroying_delete_tstd::destroying_delete_t16   explicit destroying_delete_t(__construct) {}
17 };
18 
19 inline constexpr destroying_delete_t destroying_delete(destroying_delete_t::__construct());
20 }
21 
22 // FIXME: Should destroying delete really be on in all dialects by default?
23 struct A {
24   void operator delete(void*) = delete;
25   void operator delete(A*, std::destroying_delete_t) = delete; // expected-note {{deleted}}
26 };
ATest(A * a)27 void ATest(A* a) { delete a; } // expected-error {{deleted}}
28 
29 struct B {
30   void operator delete(void*) = delete; // expected-note {{deleted}}
31   void operator delete(void*, std::size_t) = delete;
32 };
BTest(B * b)33 void BTest(B *b) { delete b; }// expected-error {{deleted}}
34 
35 
36 struct alignas(128) C {
37 #ifndef HAS_ALIGN
38   // expected-note@+2 {{deleted}}
39 #endif
40   void operator delete(void*) = delete;
41 #ifdef HAS_ALIGN
42   // expected-note@+2 {{deleted}}
43 #endif
44   void operator delete(void*, std::align_val_t) = delete;
45 };
CTest(C * c)46 void CTest(C *c) { delete c; } // expected-error {{deleted}}
47 
48 struct D {
49   void operator delete(void*) = delete;
50   void operator delete(D*, std::destroying_delete_t) = delete; // expected-note {{deleted}}
51   void operator delete(D*, std::destroying_delete_t, std::size_t) = delete;
52   void operator delete(D*, std::destroying_delete_t, std::align_val_t) = delete;
53   void operator delete(D*, std::destroying_delete_t, std::size_t, std::align_val_t) = delete;
54 };
DTest(D * d)55 void DTest(D *d) { delete d; } // expected-error {{deleted}}
56 
57 struct alignas(128) E {
58   void operator delete(void*) = delete;
59   void operator delete(E*, std::destroying_delete_t) = delete;
60   void operator delete(E*, std::destroying_delete_t, std::size_t) = delete;
61   void operator delete(E*, std::destroying_delete_t, std::align_val_t) = delete;
62   void operator delete(E*, std::destroying_delete_t, std::size_t, std::align_val_t) = delete;
63 #ifdef HAS_ALIGN
64   // expected-note@-3 {{deleted}}
65 #else
66   // expected-note@-7 {{deleted}}
67 #endif
68 };
ETest(E * e)69 void ETest(E *e) { delete e; } // expected-error {{deleted}}
70