mirror of
https://github.com/llvm-mirror/libcxx.git
synced 2025-10-23 01:18:52 +08:00
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 git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@361572 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@@ -182,7 +182,7 @@ Status
|
|||||||
------------------------------------------------- -----------------
|
------------------------------------------------- -----------------
|
||||||
``__cpp_lib_constexpr_swap_algorithms`` *unimplemented*
|
``__cpp_lib_constexpr_swap_algorithms`` *unimplemented*
|
||||||
------------------------------------------------- -----------------
|
------------------------------------------------- -----------------
|
||||||
``__cpp_lib_destroying_delete`` *unimplemented*
|
``__cpp_lib_destroying_delete`` ``201806L``
|
||||||
------------------------------------------------- -----------------
|
------------------------------------------------- -----------------
|
||||||
``__cpp_lib_erase_if`` ``201811L``
|
``__cpp_lib_erase_if`` ``201811L``
|
||||||
------------------------------------------------- -----------------
|
------------------------------------------------- -----------------
|
||||||
|
15
include/new
15
include/new
@@ -33,6 +33,12 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
enum class align_val_t : size_t {}; // C++17
|
enum class align_val_t : size_t {}; // C++17
|
||||||
|
|
||||||
|
struct destroying_delete_t { // C++20
|
||||||
|
explicit destroying_delete_t() = default;
|
||||||
|
};
|
||||||
|
inline constexpr destroying_delete_t destroying_delete{}; // C++20
|
||||||
|
|
||||||
struct nothrow_t {};
|
struct nothrow_t {};
|
||||||
extern const nothrow_t nothrow;
|
extern const nothrow_t nothrow;
|
||||||
typedef void (*new_handler)();
|
typedef void (*new_handler)();
|
||||||
@@ -158,6 +164,15 @@ enum align_val_t { __zero = 0, __max = (size_t)-1 };
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if _LIBCPP_STD_VER > 17
|
||||||
|
// Enable the declaration even if the compiler doesn't support the language
|
||||||
|
// feature.
|
||||||
|
struct destroying_delete_t {
|
||||||
|
explicit destroying_delete_t() = default;
|
||||||
|
};
|
||||||
|
_LIBCPP_INLINE_VAR constexpr destroying_delete_t destroying_delete{};
|
||||||
|
#endif // _LIBCPP_STD_VER > 17
|
||||||
|
|
||||||
} // std
|
} // std
|
||||||
|
|
||||||
#if defined(_LIBCPP_CXX03_LANG)
|
#if defined(_LIBCPP_CXX03_LANG)
|
||||||
|
@@ -220,7 +220,9 @@ __cpp_lib_void_t 201411L <type_traits>
|
|||||||
// # define __cpp_lib_concepts 201806L
|
// # define __cpp_lib_concepts 201806L
|
||||||
// # define __cpp_lib_constexpr_misc 201811L
|
// # define __cpp_lib_constexpr_misc 201811L
|
||||||
// # define __cpp_lib_constexpr_swap_algorithms 201806L
|
// # define __cpp_lib_constexpr_swap_algorithms 201806L
|
||||||
// # define __cpp_lib_destroying_delete 201806L
|
# if _LIBCPP_STD_VER > 17 && defined(__cpp_impl_destroying_delete) && __cpp_impl_destroying_delete >= 201806L
|
||||||
|
# define __cpp_lib_destroying_delete 201806L
|
||||||
|
# endif
|
||||||
# define __cpp_lib_erase_if 201811L
|
# define __cpp_lib_erase_if 201811L
|
||||||
// # define __cpp_lib_generic_unordered_lookup 201811L
|
// # define __cpp_lib_generic_unordered_lookup 201811L
|
||||||
# define __cpp_lib_interpolate 201902L
|
# define __cpp_lib_interpolate 201902L
|
||||||
|
@@ -0,0 +1,65 @@
|
|||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// The LLVM Compiler Infrastructure
|
||||||
|
//
|
||||||
|
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||||
|
// Source Licenses. See LICENSE.TXT for details.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
// struct destroying_delete_t {
|
||||||
|
// explicit destroying_delete_t() = default;
|
||||||
|
// };
|
||||||
|
// inline constexpr destroying_delete_t destroying_delete{};
|
||||||
|
|
||||||
|
// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17
|
||||||
|
|
||||||
|
#include <new>
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
|
#include "test_macros.h"
|
||||||
|
|
||||||
|
struct A {
|
||||||
|
void *data;
|
||||||
|
A();
|
||||||
|
~A();
|
||||||
|
|
||||||
|
static A* New();
|
||||||
|
void operator delete(A*, std::destroying_delete_t);
|
||||||
|
};
|
||||||
|
|
||||||
|
bool A_constructed = false;
|
||||||
|
bool A_destroyed = false;
|
||||||
|
bool A_destroying_deleted = false;
|
||||||
|
|
||||||
|
A::A() {
|
||||||
|
A_constructed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
A::~A() {
|
||||||
|
A_destroyed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
A* A::New() {
|
||||||
|
return new(::operator new(sizeof(A))) A();
|
||||||
|
}
|
||||||
|
|
||||||
|
void A::operator delete(A* a, std::destroying_delete_t) {
|
||||||
|
A_destroying_deleted = true;
|
||||||
|
::operator delete(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef __cpp_lib_destroying_delete
|
||||||
|
#error "Expected __cpp_lib_destroying_delete to be defined"
|
||||||
|
#elif __cpp_lib_destroying_delete < 201806L
|
||||||
|
#error "Unexpected value of __cpp_lib_destroying_delete"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
// Ensure that we call the destroying delete and not the destructor.
|
||||||
|
A* ap = A::New();
|
||||||
|
assert(A_constructed);
|
||||||
|
delete ap;
|
||||||
|
assert(!A_destroyed);
|
||||||
|
assert(A_destroying_deleted);
|
||||||
|
}
|
@@ -72,16 +72,16 @@
|
|||||||
|
|
||||||
#elif TEST_STD_VER > 17
|
#elif TEST_STD_VER > 17
|
||||||
|
|
||||||
# if !defined(_LIBCPP_VERSION)
|
# if TEST_STD_VER > 17 && defined(__cpp_impl_destroying_delete) && __cpp_impl_destroying_delete >= 201806L
|
||||||
# ifndef __cpp_lib_destroying_delete
|
# ifndef __cpp_lib_destroying_delete
|
||||||
# error "__cpp_lib_destroying_delete should be defined in c++2a"
|
# error "__cpp_lib_destroying_delete should be defined in c++2a"
|
||||||
# endif
|
# endif
|
||||||
# if __cpp_lib_destroying_delete != 201806L
|
# if __cpp_lib_destroying_delete != 201806L
|
||||||
# error "__cpp_lib_destroying_delete should have the value 201806L in c++2a"
|
# error "__cpp_lib_destroying_delete should have the value 201806L in c++2a"
|
||||||
# endif
|
# endif
|
||||||
# else // _LIBCPP_VERSION
|
# else
|
||||||
# ifdef __cpp_lib_destroying_delete
|
# ifdef __cpp_lib_destroying_delete
|
||||||
# error "__cpp_lib_destroying_delete should not be defined because it is unimplemented in libc++!"
|
# 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!"
|
||||||
# endif
|
# endif
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
|
@@ -1662,16 +1662,16 @@
|
|||||||
# endif
|
# endif
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
# if !defined(_LIBCPP_VERSION)
|
# if TEST_STD_VER > 17 && defined(__cpp_impl_destroying_delete) && __cpp_impl_destroying_delete >= 201806L
|
||||||
# ifndef __cpp_lib_destroying_delete
|
# ifndef __cpp_lib_destroying_delete
|
||||||
# error "__cpp_lib_destroying_delete should be defined in c++2a"
|
# error "__cpp_lib_destroying_delete should be defined in c++2a"
|
||||||
# endif
|
# endif
|
||||||
# if __cpp_lib_destroying_delete != 201806L
|
# if __cpp_lib_destroying_delete != 201806L
|
||||||
# error "__cpp_lib_destroying_delete should have the value 201806L in c++2a"
|
# error "__cpp_lib_destroying_delete should have the value 201806L in c++2a"
|
||||||
# endif
|
# endif
|
||||||
# else // _LIBCPP_VERSION
|
# else
|
||||||
# ifdef __cpp_lib_destroying_delete
|
# ifdef __cpp_lib_destroying_delete
|
||||||
# error "__cpp_lib_destroying_delete should not be defined because it is unimplemented in libc++!"
|
# 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!"
|
||||||
# endif
|
# endif
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
|
@@ -483,7 +483,14 @@ feature_test_macros = sorted([ add_version_header(x) for x in [
|
|||||||
"c++2a": 201806L,
|
"c++2a": 201806L,
|
||||||
},
|
},
|
||||||
"headers": ["new"],
|
"headers": ["new"],
|
||||||
"unimplemented": True,
|
"depends":
|
||||||
|
"TEST_STD_VER > 17"
|
||||||
|
" && defined(__cpp_impl_destroying_delete)"
|
||||||
|
" && __cpp_impl_destroying_delete >= 201806L",
|
||||||
|
"internal_depends":
|
||||||
|
"_LIBCPP_STD_VER > 17"
|
||||||
|
" && defined(__cpp_impl_destroying_delete)"
|
||||||
|
" && __cpp_impl_destroying_delete >= 201806L",
|
||||||
},
|
},
|
||||||
{"name": "__cpp_lib_three_way_comparison",
|
{"name": "__cpp_lib_three_way_comparison",
|
||||||
"values": {
|
"values": {
|
||||||
|
Reference in New Issue
Block a user