Clang Project

clang_source_code/test/SemaCXX/cxx2a-destroying-delete.cpp
1// RUN: %clang_cc1 -std=c++2a -fexceptions -verify %s
2// RUN: %clang_cc1 -std=c++2a  -verify %s
3
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 delete
17
18struct A;
19void operator delete(A*, std::destroying_delete_t); // expected-error {{first 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 {{first parameter of '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 '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
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;
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
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; // 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