Index: include/new =================================================================== --- include/new +++ include/new @@ -34,6 +34,10 @@ }; enum class align_val_t : size_t {}; // C++17 +struct destroying_delete_t { + explicit destroying_delete_t() = default; +}; +inline constexpr destroying_delete_t destroying_delete{}; struct nothrow_t {}; extern const nothrow_t nothrow; typedef void (*new_handler)(); @@ -159,6 +163,15 @@ #endif #endif +#if defined(__cpp_impl_destroying_delete) && __cpp_impl_destroying_delete >= 201806L +#define __cpp_lib_destroying_delete 201806L + +struct destroying_delete_t { + explicit destroying_delete_t() = default; +}; +inline constexpr destroying_delete_t destroying_delete{}; +#endif + } // std #if defined(_LIBCPP_CXX03_LANG) Index: test/std/language.support/support.dynamic/destroying_delete_t.pass.cpp =================================================================== --- /dev/null +++ test/std/language.support/support.dynamic/destroying_delete_t.pass.cpp @@ -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 + +#include + +#include +#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); +}