mirror of git://gcc.gnu.org/git/gcc.git
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
This commit is contained in:
parent
594ef205ae
commit
74cf9664e8
|
|
@ -1,5 +1,18 @@
|
||||||
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
|
||||||
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()
|
||||||
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()
|
||||||
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()
|
||||||
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 @@
|
||||||
|
|
||||||
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" }
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue