Skip to content

Commit ae02e89

Browse files
committed
P0722R3: Implement library support for destroying delete
Summary: This provides the `std::destroying_delete_t` declaration in C++2a and after. (Even when the compiler doesn't support the language feature). However, the feature test macro `__cpp_lib_destroying_delete` is only defined when we have both language support and C++2a. Reviewers: ldionne, ckennelly, serge-sans-paille, EricWF Reviewed By: EricWF Subscribers: dexonsmith, riccibruno, christof, jwakely, jdoerfert, mclow.lists, ldionne, libcxx-commits Differential Revision: https://reviews.llvm.org/D55840 llvm-svn: 361572
1 parent ffafdb9 commit ae02e89

File tree

7 files changed

+98
-9
lines changed

7 files changed

+98
-9
lines changed

libcxx/docs/FeatureTestMacroTable.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ Status
182182
------------------------------------------------- -----------------
183183
``__cpp_lib_constexpr_swap_algorithms`` *unimplemented*
184184
------------------------------------------------- -----------------
185-
``__cpp_lib_destroying_delete`` *unimplemented*
185+
``__cpp_lib_destroying_delete`` ``201806L``
186186
------------------------------------------------- -----------------
187187
``__cpp_lib_erase_if`` ``201811L``
188188
------------------------------------------------- -----------------

libcxx/include/new

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,12 @@ public:
3333
};
3434
3535
enum class align_val_t : size_t {}; // C++17
36+
37+
struct destroying_delete_t { // C++20
38+
explicit destroying_delete_t() = default;
39+
};
40+
inline constexpr destroying_delete_t destroying_delete{}; // C++20
41+
3642
struct nothrow_t {};
3743
extern const nothrow_t nothrow;
3844
typedef void (*new_handler)();
@@ -158,6 +164,15 @@ enum align_val_t { __zero = 0, __max = (size_t)-1 };
158164
#endif
159165
#endif
160166

167+
#if _LIBCPP_STD_VER > 17
168+
// Enable the declaration even if the compiler doesn't support the language
169+
// feature.
170+
struct destroying_delete_t {
171+
explicit destroying_delete_t() = default;
172+
};
173+
_LIBCPP_INLINE_VAR constexpr destroying_delete_t destroying_delete{};
174+
#endif // _LIBCPP_STD_VER > 17
175+
161176
} // std
162177

163178
#if defined(_LIBCPP_CXX03_LANG)

libcxx/include/version

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,9 @@ __cpp_lib_void_t 201411L <type_traits>
220220
// # define __cpp_lib_concepts 201806L
221221
// # define __cpp_lib_constexpr_misc 201811L
222222
// # define __cpp_lib_constexpr_swap_algorithms 201806L
223-
// # define __cpp_lib_destroying_delete 201806L
223+
# if _LIBCPP_STD_VER > 17 && defined(__cpp_impl_destroying_delete) && __cpp_impl_destroying_delete >= 201806L
224+
# define __cpp_lib_destroying_delete 201806L
225+
# endif
224226
# define __cpp_lib_erase_if 201811L
225227
// # define __cpp_lib_generic_unordered_lookup 201811L
226228
# define __cpp_lib_interpolate 201902L
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// The LLVM Compiler Infrastructure
4+
//
5+
// This file is dual licensed under the MIT and the University of Illinois Open
6+
// Source Licenses. See LICENSE.TXT for details.
7+
//
8+
//===----------------------------------------------------------------------===//
9+
10+
// struct destroying_delete_t {
11+
// explicit destroying_delete_t() = default;
12+
// };
13+
// inline constexpr destroying_delete_t destroying_delete{};
14+
15+
// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17
16+
17+
#include <new>
18+
19+
#include <cassert>
20+
#include "test_macros.h"
21+
22+
struct A {
23+
void *data;
24+
A();
25+
~A();
26+
27+
static A* New();
28+
void operator delete(A*, std::destroying_delete_t);
29+
};
30+
31+
bool A_constructed = false;
32+
bool A_destroyed = false;
33+
bool A_destroying_deleted = false;
34+
35+
A::A() {
36+
A_constructed = true;
37+
}
38+
39+
A::~A() {
40+
A_destroyed = true;
41+
}
42+
43+
A* A::New() {
44+
return new(::operator new(sizeof(A))) A();
45+
}
46+
47+
void A::operator delete(A* a, std::destroying_delete_t) {
48+
A_destroying_deleted = true;
49+
::operator delete(a);
50+
}
51+
52+
#ifndef __cpp_lib_destroying_delete
53+
#error "Expected __cpp_lib_destroying_delete to be defined"
54+
#elif __cpp_lib_destroying_delete < 201806L
55+
#error "Unexpected value of __cpp_lib_destroying_delete"
56+
#endif
57+
58+
int main() {
59+
// Ensure that we call the destroying delete and not the destructor.
60+
A* ap = A::New();
61+
assert(A_constructed);
62+
delete ap;
63+
assert(!A_destroyed);
64+
assert(A_destroying_deleted);
65+
}

libcxx/test/std/language.support/support.limits/support.limits.general/new.version.pass.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -72,16 +72,16 @@
7272

7373
#elif TEST_STD_VER > 17
7474

75-
# if !defined(_LIBCPP_VERSION)
75+
# if TEST_STD_VER > 17 && defined(__cpp_impl_destroying_delete) && __cpp_impl_destroying_delete >= 201806L
7676
# ifndef __cpp_lib_destroying_delete
7777
# error "__cpp_lib_destroying_delete should be defined in c++2a"
7878
# endif
7979
# if __cpp_lib_destroying_delete != 201806L
8080
# error "__cpp_lib_destroying_delete should have the value 201806L in c++2a"
8181
# endif
82-
# else // _LIBCPP_VERSION
82+
# else
8383
# ifdef __cpp_lib_destroying_delete
84-
# error "__cpp_lib_destroying_delete should not be defined because it is unimplemented in libc++!"
84+
# error "__cpp_lib_destroying_delete should not be defined when TEST_STD_VER > 17 && defined(__cpp_impl_destroying_delete) && __cpp_impl_destroying_delete >= 201806L is not defined!"
8585
# endif
8686
# endif
8787

libcxx/test/std/language.support/support.limits/support.limits.general/version.version.pass.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1662,16 +1662,16 @@
16621662
# endif
16631663
# endif
16641664

1665-
# if !defined(_LIBCPP_VERSION)
1665+
# if TEST_STD_VER > 17 && defined(__cpp_impl_destroying_delete) && __cpp_impl_destroying_delete >= 201806L
16661666
# ifndef __cpp_lib_destroying_delete
16671667
# error "__cpp_lib_destroying_delete should be defined in c++2a"
16681668
# endif
16691669
# if __cpp_lib_destroying_delete != 201806L
16701670
# error "__cpp_lib_destroying_delete should have the value 201806L in c++2a"
16711671
# endif
1672-
# else // _LIBCPP_VERSION
1672+
# else
16731673
# ifdef __cpp_lib_destroying_delete
1674-
# error "__cpp_lib_destroying_delete should not be defined because it is unimplemented in libc++!"
1674+
# error "__cpp_lib_destroying_delete should not be defined when TEST_STD_VER > 17 && defined(__cpp_impl_destroying_delete) && __cpp_impl_destroying_delete >= 201806L is not defined!"
16751675
# endif
16761676
# endif
16771677

libcxx/utils/generate_feature_test_macro_components.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -483,7 +483,14 @@ def add_version_header(tc):
483483
"c++2a": 201806L,
484484
},
485485
"headers": ["new"],
486-
"unimplemented": True,
486+
"depends":
487+
"TEST_STD_VER > 17"
488+
" && defined(__cpp_impl_destroying_delete)"
489+
" && __cpp_impl_destroying_delete >= 201806L",
490+
"internal_depends":
491+
"_LIBCPP_STD_VER > 17"
492+
" && defined(__cpp_impl_destroying_delete)"
493+
" && __cpp_impl_destroying_delete >= 201806L",
487494
},
488495
{"name": "__cpp_lib_three_way_comparison",
489496
"values": {

0 commit comments

Comments
 (0)