Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 19 additions & 7 deletions stl/inc/memory
Original file line number Diff line number Diff line change
Expand Up @@ -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)) {
Expand Down Expand Up @@ -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)) {
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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.
Expand Down
63 changes: 63 additions & 0 deletions tests/std/tests/P0674R1_make_shared_for_arrays/test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -623,6 +623,67 @@ void test_allocate_shared_array_unknown_bounds() {
}
}

// Test GH-1733 "<memory>: error C2694 when calling make_shared on class with throwing destructor"
struct NontrivialThrowingDtor {
~NontrivialThrowingDtor() noexcept(false) {}
};
static_assert(!is_nothrow_destructible_v<NontrivialThrowingDtor>);
static_assert(!is_trivially_destructible_v<NontrivialThrowingDtor>);

struct TrivialThrowingDtor {
~TrivialThrowingDtor() noexcept(false) = default;
};

#ifndef __EDG__ // TRANSITION, VSO-1292292
static_assert(!is_nothrow_destructible_v<TrivialThrowingDtor>);
#endif // ^^^ no workaround ^^^
static_assert(is_trivially_destructible_v<TrivialThrowingDtor>);

template <class T>
struct WeirdDeleter {
void operator()(T* const ptr) const {
delete ptr;
}

~WeirdDeleter() noexcept(false) {}
};
static_assert(!is_nothrow_destructible_v<WeirdDeleter<int>>);

void test_GH_1733() {
WeirdDeleter<NontrivialThrowingDtor> del;
allocator<int> al;

// _Ref_count
(void) shared_ptr<NontrivialThrowingDtor>{new NontrivialThrowingDtor};

// _Ref_count_resource
(void) shared_ptr<NontrivialThrowingDtor>{new NontrivialThrowingDtor, del};

// _Ref_count_resource_alloc
(void) shared_ptr<NontrivialThrowingDtor>{new NontrivialThrowingDtor, del, al};

// _Ref_count_obj2
(void) make_shared<NontrivialThrowingDtor>();

// _Ref_count_obj_alloc3
(void) allocate_shared<NontrivialThrowingDtor>(al);

// _Ref_count_unbounded_array<_Ty, true>
(void) make_shared<TrivialThrowingDtor[]>(10);

// _Ref_count_unbounded_array<_Ty, false>
(void) make_shared<NontrivialThrowingDtor[]>(10);

// _Ref_count_bounded_array
(void) make_shared<NontrivialThrowingDtor[10]>();

// _Ref_count_unbounded_array_alloc
(void) allocate_shared<NontrivialThrowingDtor[]>(al, 10);

// _Ref_count_bounded_array_alloc
(void) allocate_shared<NontrivialThrowingDtor[10]>(al);
}

int main() {
test_make_shared_not_array();
test_make_shared_array_known_bounds();
Expand All @@ -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();
}