From d686d56692911a2ab1d86745d6a6be43ba42f545 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Sat, 13 Mar 2021 00:16:33 -0800 Subject: [PATCH] Fix make_shared with throwing destructors --- stl/inc/memory | 26 +++++--- .../P0674R1_make_shared_for_arrays/test.cpp | 63 +++++++++++++++++++ 2 files changed, 82 insertions(+), 7 deletions(-) diff --git a/stl/inc/memory b/stl/inc/memory index 4fe7830d5df..f35574a2580 100644 --- a/stl/inc/memory +++ b/stl/inc/memory @@ -1145,6 +1145,12 @@ public: _Ref_count_resource(_Resource _Px, _Dx _Dt) : _Ref_count_base(), _Mypair(_One_then_variadic_args_t{}, _STD move(_Dt), _Px) {} +#ifdef __EDG__ // TRANSITION, VSO-1292293 + virtual ~_Ref_count_resource() noexcept override {} // TRANSITION, should be non-virtual +#else // ^^^ workaround / no workaround vvv + virtual ~_Ref_count_resource() noexcept override = default; // TRANSITION, should be non-virtual +#endif // ^^^ no workaround ^^^ + virtual void* _Get_deleter(const type_info& _Typeid) const noexcept override { #if _HAS_STATIC_RTTI if (_Typeid == typeid(_Dx)) { @@ -1178,6 +1184,12 @@ public: : _Ref_count_base(), _Mypair(_One_then_variadic_args_t{}, _STD move(_Dt), _One_then_variadic_args_t{}, _Ax, _Px) {} +#ifdef __EDG__ // TRANSITION, VSO-1292293 + virtual ~_Ref_count_resource_alloc() noexcept override {} // TRANSITION, should be non-virtual +#else // ^^^ workaround / no workaround vvv + virtual ~_Ref_count_resource_alloc() noexcept override = default; // TRANSITION, should be non-virtual +#endif // ^^^ no workaround ^^^ + virtual void* _Get_deleter(const type_info& _Typeid) const noexcept override { #if _HAS_STATIC_RTTI if (_Typeid == typeid(_Dx)) { @@ -2012,7 +2024,7 @@ public: } } - ~_Ref_count_obj2() { + virtual ~_Ref_count_obj2() noexcept override { // TRANSITION, should be non-virtual // nothing to do, _Storage._Value was already destroyed in _Destroy // N4849 [class.dtor]/7: @@ -2276,7 +2288,7 @@ private: _Wrap<_Element_type> _Storage; // flexible array must be last member }; - ~_Ref_count_unbounded_array() { + virtual ~_Ref_count_unbounded_array() noexcept override { // TRANSITION, should be non-virtual // nothing to do, _Ty is trivially destructible // See N4849 [class.dtor]/7. @@ -2324,7 +2336,7 @@ private: _Wrap<_Element_type> _Storage; // flexible array must be last member }; - ~_Ref_count_unbounded_array() { + virtual ~_Ref_count_unbounded_array() noexcept override { // TRANSITION, should be non-virtual // nothing to do, _Storage was already destroyed in _Destroy // See N4849 [class.dtor]/7. @@ -2363,7 +2375,7 @@ public: }; private: - ~_Ref_count_bounded_array() { + virtual ~_Ref_count_bounded_array() noexcept override { // TRANSITION, should be non-virtual // nothing to do, _Storage was already destroyed in _Destroy // See N4849 [class.dtor]/7. @@ -2449,7 +2461,7 @@ public: }; private: - ~_Ref_count_obj_alloc3() { + virtual ~_Ref_count_obj_alloc3() noexcept override { // TRANSITION, should be non-virtual // nothing to do; _Storage._Value already destroyed by _Destroy() // See N4849 [class.dtor]/7. @@ -2637,7 +2649,7 @@ private: _Wrap<_Element_type> _Storage; // flexible array must be last member }; - ~_Ref_count_unbounded_array_alloc() { + virtual ~_Ref_count_unbounded_array_alloc() noexcept override { // TRANSITION, should be non-virtual // nothing to do; _Storage._Value already destroyed by _Destroy() // See N4849 [class.dtor]/7. @@ -2698,7 +2710,7 @@ public: }; private: - ~_Ref_count_bounded_array_alloc() { + virtual ~_Ref_count_bounded_array_alloc() noexcept override { // TRANSITION, should be non-virtual // nothing to do; _Storage._Value already destroyed by _Destroy() // See N4849 [class.dtor]/7. diff --git a/tests/std/tests/P0674R1_make_shared_for_arrays/test.cpp b/tests/std/tests/P0674R1_make_shared_for_arrays/test.cpp index 0a9082fe926..f703ded4876 100644 --- a/tests/std/tests/P0674R1_make_shared_for_arrays/test.cpp +++ b/tests/std/tests/P0674R1_make_shared_for_arrays/test.cpp @@ -623,6 +623,67 @@ void test_allocate_shared_array_unknown_bounds() { } } +// Test GH-1733 ": error C2694 when calling make_shared on class with throwing destructor" +struct NontrivialThrowingDtor { + ~NontrivialThrowingDtor() noexcept(false) {} +}; +static_assert(!is_nothrow_destructible_v); +static_assert(!is_trivially_destructible_v); + +struct TrivialThrowingDtor { + ~TrivialThrowingDtor() noexcept(false) = default; +}; + +#ifndef __EDG__ // TRANSITION, VSO-1292292 +static_assert(!is_nothrow_destructible_v); +#endif // ^^^ no workaround ^^^ +static_assert(is_trivially_destructible_v); + +template +struct WeirdDeleter { + void operator()(T* const ptr) const { + delete ptr; + } + + ~WeirdDeleter() noexcept(false) {} +}; +static_assert(!is_nothrow_destructible_v>); + +void test_GH_1733() { + WeirdDeleter del; + allocator al; + + // _Ref_count + (void) shared_ptr{new NontrivialThrowingDtor}; + + // _Ref_count_resource + (void) shared_ptr{new NontrivialThrowingDtor, del}; + + // _Ref_count_resource_alloc + (void) shared_ptr{new NontrivialThrowingDtor, del, al}; + + // _Ref_count_obj2 + (void) make_shared(); + + // _Ref_count_obj_alloc3 + (void) allocate_shared(al); + + // _Ref_count_unbounded_array<_Ty, true> + (void) make_shared(10); + + // _Ref_count_unbounded_array<_Ty, false> + (void) make_shared(10); + + // _Ref_count_bounded_array + (void) make_shared(); + + // _Ref_count_unbounded_array_alloc + (void) allocate_shared(al, 10); + + // _Ref_count_bounded_array_alloc + (void) allocate_shared(al); +} + int main() { test_make_shared_not_array(); test_make_shared_array_known_bounds(); @@ -631,4 +692,6 @@ int main() { test_allocate_shared_not_array(); test_allocate_shared_array_known_bounds(); test_allocate_shared_array_unknown_bounds(); + + test_GH_1733(); }