diff options
author | Jonathan Wakely <jwakely@redhat.com> | 2016-10-17 13:00:44 +0100 |
---|---|---|
committer | Jonathan Wakely <redi@gcc.gnu.org> | 2016-10-17 13:00:44 +0100 |
commit | 74cf9664e8a767a329131413de2271a4aae7488a (patch) | |
tree | 0ef4ef2ed5d22135910b345867ec3a81dc9c5f17 /libstdc++-v3 | |
parent | 594ef205ae28bdd8d32ff141b41cc08158b84552 (diff) | |
download | gcc-74cf9664e8a767a329131413de2271a4aae7488a.zip gcc-74cf9664e8a767a329131413de2271a4aae7488a.tar.gz gcc-74cf9664e8a767a329131413de2271a4aae7488a.tar.bz2 |
PR77987 Fix unique_ptr<T[], D>::reset(U) for T != U
PR libstdc++/77987
* include/bits/unique_ptr.h (unique_ptr<T[], D>::reset<U>(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
Diffstat (limited to 'libstdc++-v3')
6 files changed, 62 insertions, 41 deletions
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index b31c1dd..ed57281 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,5 +1,18 @@ 2016-10-17 Jonathan Wakely <jwakely@redhat.com> + PR libstdc++/77987 + * include/bits/unique_ptr.h (unique_ptr<T[], D>::reset<U>(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 15ef8a8..a36794d 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 842b6ed..9142e61 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<int[2]> p2 = p1; // { dg-error "deleted" } } +struct base_pointer { operator base*() const { return nullptr; } }; + +template<typename T> +struct deleter +{ + deleter() = default; + template<typename U> + deleter(const deleter<U>) { } + typedef T pointer; + void operator()(T) const { } +}; + +void +test04() +{ + // Disallow conversions from incompatible deleter + std::unique_ptr<derived[], deleter<base_pointer>> p; + std::unique_ptr<base[], deleter<base*>> 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 793499d..7add5a9 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<const volatile A[]> cvA; cvA = std::move(upA); } - -struct A_pointer { operator A*() const { return nullptr; } }; - -template<typename T> -struct deleter -{ - deleter() = default; - template<typename U> - deleter(const deleter<U>) { } - typedef T pointer; - void operator()(T) const { } -}; - -void -test04() -{ - // Disallow conversions from incompatible deleter - std::unique_ptr<B[], deleter<A_pointer>> p; - std::unique_ptr<A[], deleter<A*>> 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 0284563..f92949b 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<const volatile A[]> cvA2; cvA2.reset((A*)p); - // Disallow conversions from user-defined pointer-like types - // for the array version - std::unique_ptr<A[]> upA3; - upA3.reset(p); // { dg-error "no matching function" } - std::unique_ptr<const A[]> cA3; - cA3.reset(p); // { dg-error "no matching function" } - std::unique_ptr<volatile A[]> vA3; - vA3.reset(p); // { dg-error "no matching function" } - std::unique_ptr<const volatile A[]> 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 d2ed03c..cb5f2e6 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<B[]> up; - up.reset(new A[3]); // { dg-error "" } + up.reset(new A[3]); // { dg-error "no matching function" } + + std::unique_ptr<A[]> 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<A[]> upA3; + upA3.reset(p); // { dg-error "no matching function" } + std::unique_ptr<const A[]> cA3; + cA3.reset(p); // { dg-error "no matching function" } + std::unique_ptr<volatile A[]> vA3; + vA3.reset(p); // { dg-error "no matching function" } + std::unique_ptr<const volatile A[]> cvA3; + cvA3.reset(p); // { dg-error "no matching function" } +} |