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; }; |
16 | 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 | }; |
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 | }; |
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 | }; |
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 | }; |
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 | }; |
69 | void ETest(E *e) { delete e; } // expected-error {{deleted}} |
70 | |