1 // RUN: %clang_cc1 -std=c++20 -verify %s
3 using size_t = decltype(sizeof(0));
5 enum class align_val_t
: size_t {};
6 struct destroying_delete_t
{
7 explicit destroying_delete_t() = default;
10 inline constexpr destroying_delete_t destroying_delete
{};
13 // Aligned version is preferred over unaligned version,
14 // unsized version is preferred over sized version.
15 template<unsigned Align
>
16 struct alignas(Align
) A
{
17 void operator delete(void*);
18 void operator delete(void*, std::align_val_t
) = delete; // expected-note {{here}}
20 void operator delete(void*, size_t) = delete;
21 void operator delete(void*, size_t, std::align_val_t
) = delete;
23 void f(A
<__STDCPP_DEFAULT_NEW_ALIGNMENT__
> *p
) { delete p
; }
24 void f(A
<__STDCPP_DEFAULT_NEW_ALIGNMENT__
* 2> *p
) { delete p
; } // expected-error {{deleted}}
26 template<unsigned Align
>
27 struct alignas(Align
) B
{
28 void operator delete(void*, size_t);
29 void operator delete(void*, size_t, std::align_val_t
) = delete; // expected-note {{here}}
31 void f(B
<__STDCPP_DEFAULT_NEW_ALIGNMENT__
> *p
) { delete p
; }
32 void f(B
<__STDCPP_DEFAULT_NEW_ALIGNMENT__
* 2> *p
) { delete p
; } // expected-error {{deleted}}
34 // Ensure that a deleted destructor is acceptable when the selected overload
35 // for operator delete is a destroying delete. See the comments in GH118660.
38 void operator delete(S
*, std::destroying_delete_t
) noexcept
{}
42 void operator delete(T
*, std::destroying_delete_t
) noexcept
{}
47 void foo(S
*s
, T
*t
) {
48 delete s
; // Was rejected, is intended to be accepted.
49 delete t
; // Was rejected, is intended to be accepted.
52 // However, if the destructor is virtual, then it has to be accessible because
53 // the behavior depends on which operator delete is selected and that is based
54 // on the dynamic type of the pointer.
56 virtual ~U() = delete; // expected-note {{here}}
57 void operator delete(U
*, std::destroying_delete_t
) noexcept
{}
61 void operator delete(V
*, std::destroying_delete_t
) noexcept
{}
63 virtual ~V(); // expected-note {{here}}
66 void bar(U
*u
, V
*v
) {
67 // Both should be rejected because they have virtual destructors.
68 delete u
; // expected-error {{attempt to use a deleted function}}
69 delete v
; // expected-error {{calling a private destructor of class 'V'}}