From 74cf9664e8a767a329131413de2271a4aae7488a Mon Sep 17 00:00:00 2001 From: Jonathan Wakely Date: Mon, 17 Oct 2016 13:00:44 +0100 Subject: [PATCH] PR77987 Fix unique_ptr::reset(U) for T != U PR libstdc++/77987 * include/bits/unique_ptr.h (unique_ptr::reset(U)): Copy value to pointer of the correct type to swap, to support conversions allowed by LWG 2118 / N4089. * testsuite/20_util/unique_ptr/assign/assign_neg.cc: Move test for incompatible deleters from ... * testsuite/20_util/unique_ptr/assign/cv_qual.cc: ... here. * testsuite/20_util/unique_ptr/modifiers/cv_qual.cc: Move tests for incompatible pointers to ... * testsuite/20_util/unique_ptr/modifiers/reset_neg.cc: ... here. Move destructor definition to base class. Test for invalid derived-to-base conversion. From-SVN: r241235 --- libstdc++-v3/ChangeLog | 13 +++++++++ libstdc++-v3/include/bits/unique_ptr.h | 7 +++-- .../20_util/unique_ptr/assign/assign_neg.cc | 21 ++++++++++++++ .../20_util/unique_ptr/assign/cv_qual.cc | 23 --------------- .../20_util/unique_ptr/modifiers/cv_qual.cc | 11 -------- .../20_util/unique_ptr/modifiers/reset_neg.cc | 28 ++++++++++++++++--- 6 files changed, 62 insertions(+), 41 deletions(-) diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index b31c1dd331a..ed572815d64 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,5 +1,18 @@ 2016-10-17 Jonathan Wakely + PR libstdc++/77987 + * include/bits/unique_ptr.h (unique_ptr::reset(U)): Copy + value to pointer of the correct type to swap, to support conversions + allowed by LWG 2118 / N4089. + * testsuite/20_util/unique_ptr/assign/assign_neg.cc: Move test for + incompatible deleters from ... + * testsuite/20_util/unique_ptr/assign/cv_qual.cc: ... here. + * testsuite/20_util/unique_ptr/modifiers/cv_qual.cc: Move tests for + incompatible pointers to ... + * testsuite/20_util/unique_ptr/modifiers/reset_neg.cc: ... here. Move + destructor definition to base class. Test for invalid derived-to-base + conversion. + * doc/xml/manual/status_cxx2017.xml: Update status. * doc/html/*: Regenerate. * include/bits/deque.tcc (deque::emplace_front, deque::emplace_back): diff --git a/libstdc++-v3/include/bits/unique_ptr.h b/libstdc++-v3/include/bits/unique_ptr.h index 15ef8a89475..a36794d632e 100644 --- a/libstdc++-v3/include/bits/unique_ptr.h +++ b/libstdc++-v3/include/bits/unique_ptr.h @@ -610,10 +610,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION void reset(_Up __p) noexcept { + pointer __ptr = __p; using std::swap; - swap(std::get<0>(_M_t), __p); - if (__p != nullptr) - get_deleter()(__p); + swap(std::get<0>(_M_t), __ptr); + if (__ptr != nullptr) + get_deleter()(__ptr); } void reset(nullptr_t = nullptr) noexcept diff --git a/libstdc++-v3/testsuite/20_util/unique_ptr/assign/assign_neg.cc b/libstdc++-v3/testsuite/20_util/unique_ptr/assign/assign_neg.cc index 842b6ed7a86..9142e6146b4 100644 --- a/libstdc++-v3/testsuite/20_util/unique_ptr/assign/assign_neg.cc +++ b/libstdc++-v3/testsuite/20_util/unique_ptr/assign/assign_neg.cc @@ -48,4 +48,25 @@ test03() std::unique_ptr p2 = p1; // { dg-error "deleted" } } +struct base_pointer { operator base*() const { return nullptr; } }; + +template +struct deleter +{ + deleter() = default; + template + deleter(const deleter) { } + typedef T pointer; + void operator()(T) const { } +}; + +void +test04() +{ + // Disallow conversions from incompatible deleter + std::unique_ptr> p; + std::unique_ptr> upA; + upA = std::move(p); // { dg-error "no match" } +} + // { dg-prune-output "include" } diff --git a/libstdc++-v3/testsuite/20_util/unique_ptr/assign/cv_qual.cc b/libstdc++-v3/testsuite/20_util/unique_ptr/assign/cv_qual.cc index 793499dce4d..7add5a9c0a3 100644 --- a/libstdc++-v3/testsuite/20_util/unique_ptr/assign/cv_qual.cc +++ b/libstdc++-v3/testsuite/20_util/unique_ptr/assign/cv_qual.cc @@ -65,26 +65,3 @@ test03() std::unique_ptr cvA; cvA = std::move(upA); } - -struct A_pointer { operator A*() const { return nullptr; } }; - -template -struct deleter -{ - deleter() = default; - template - deleter(const deleter) { } - typedef T pointer; - void operator()(T) const { } -}; - -void -test04() -{ - // Disallow conversions from incompatible deleter - std::unique_ptr> p; - std::unique_ptr> upA; - upA = std::move(p); // { dg-error "no match" } - // { dg-error "no type" "" { target *-*-* } 537 } - // { dg-error "no matching function" "" { target *-*-* } 614 } -} diff --git a/libstdc++-v3/testsuite/20_util/unique_ptr/modifiers/cv_qual.cc b/libstdc++-v3/testsuite/20_util/unique_ptr/modifiers/cv_qual.cc index 02845635260..f92949b441e 100644 --- a/libstdc++-v3/testsuite/20_util/unique_ptr/modifiers/cv_qual.cc +++ b/libstdc++-v3/testsuite/20_util/unique_ptr/modifiers/cv_qual.cc @@ -86,15 +86,4 @@ test07() vA2.reset((A*)p); std::unique_ptr cvA2; cvA2.reset((A*)p); - // Disallow conversions from user-defined pointer-like types - // for the array version - std::unique_ptr upA3; - upA3.reset(p); // { dg-error "no matching function" } - std::unique_ptr cA3; - cA3.reset(p); // { dg-error "no matching function" } - std::unique_ptr vA3; - vA3.reset(p); // { dg-error "no matching function" } - std::unique_ptr cvA3; - cvA3.reset(p); // { dg-error "no matching function" } - // { dg-error "no matching function" "" { target *-*-* } 614 } } diff --git a/libstdc++-v3/testsuite/20_util/unique_ptr/modifiers/reset_neg.cc b/libstdc++-v3/testsuite/20_util/unique_ptr/modifiers/reset_neg.cc index d2ed03cafd9..cb5f2e6a1c5 100644 --- a/libstdc++-v3/testsuite/20_util/unique_ptr/modifiers/reset_neg.cc +++ b/libstdc++-v3/testsuite/20_util/unique_ptr/modifiers/reset_neg.cc @@ -21,17 +21,37 @@ struct A { + virtual ~A() { } }; struct B : A { - virtual ~B() { } }; -void test01() +void +test01() { std::unique_ptr up; - up.reset(new A[3]); // { dg-error "" } + up.reset(new A[3]); // { dg-error "no matching function" } + + std::unique_ptr up2; + up2.reset(new B[3]); // { dg-error "no matching function" } } -// { dg-prune-output "include" } +struct A_pointer { operator A*() const { return nullptr; } }; + +void +test02() +{ + A_pointer p; + // Disallow conversions from user-defined pointer-like types + // for the array version + std::unique_ptr upA3; + upA3.reset(p); // { dg-error "no matching function" } + std::unique_ptr cA3; + cA3.reset(p); // { dg-error "no matching function" } + std::unique_ptr vA3; + vA3.reset(p); // { dg-error "no matching function" } + std::unique_ptr cvA3; + cvA3.reset(p); // { dg-error "no matching function" } +} -- 2.30.2