Commit 74cf9664 by Jonathan Wakely Committed by Jonathan Wakely

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
parent 594ef205
2016-10-17 Jonathan Wakely <jwakely@redhat.com> 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/xml/manual/status_cxx2017.xml: Update status.
* doc/html/*: Regenerate. * doc/html/*: Regenerate.
* include/bits/deque.tcc (deque::emplace_front, deque::emplace_back): * include/bits/deque.tcc (deque::emplace_front, deque::emplace_back):
......
...@@ -610,10 +610,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -610,10 +610,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
void void
reset(_Up __p) noexcept reset(_Up __p) noexcept
{ {
pointer __ptr = __p;
using std::swap; using std::swap;
swap(std::get<0>(_M_t), __p); swap(std::get<0>(_M_t), __ptr);
if (__p != nullptr) if (__ptr != nullptr)
get_deleter()(__p); get_deleter()(__ptr);
} }
void reset(nullptr_t = nullptr) noexcept void reset(nullptr_t = nullptr) noexcept
......
...@@ -48,4 +48,25 @@ test03() ...@@ -48,4 +48,25 @@ test03()
std::unique_ptr<int[2]> p2 = p1; // { dg-error "deleted" } 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" } // { dg-prune-output "include" }
...@@ -65,26 +65,3 @@ test03() ...@@ -65,26 +65,3 @@ test03()
std::unique_ptr<const volatile A[]> cvA; std::unique_ptr<const volatile A[]> cvA;
cvA = std::move(upA); 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 }
}
...@@ -86,15 +86,4 @@ test07() ...@@ -86,15 +86,4 @@ test07()
vA2.reset((A*)p); vA2.reset((A*)p);
std::unique_ptr<const volatile A[]> cvA2; std::unique_ptr<const volatile A[]> cvA2;
cvA2.reset((A*)p); 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 }
} }
...@@ -21,17 +21,37 @@ ...@@ -21,17 +21,37 @@
struct A struct A
{ {
virtual ~A() { }
}; };
struct B : A struct B : A
{ {
virtual ~B() { }
}; };
void test01() void
test01()
{ {
std::unique_ptr<B[]> up; 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" }
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment