Commit 84870b6b by Jonathan Wakely Committed by Jonathan Wakely

Fix std::experimental::shared_ptr SFINAE constraints

	* include/experimental/bits/shared_ptr.h
	(__shared_ptr<__libfund_v1<_Tp, false>, _Lp>::_Compatible): Just use
	is_convertible for non-array specialization.
	(__shared_ptr<__libfund_v1<_Tp, false>, _Lp>::_UniqCompatible): New
	constraint for conversions from unique_ptr.
	(__shared_ptr<__libfund_v1<_Tp, false>, _Lp>::__shared_ptr): Constrain.
	(__shared_ptr<__libfund_v1<_Tp, false>, _Lp>::reset): Likewise.
	(__sp_compatible_v): New variable template for trait.
	(__sp_is_constructible): New trait to check shared_ptr constraints.
	(__sp_is_constructible_v): New variable template for trait.
	(__shared_ptr<__libfund_v1<_Tp, true>, _Lp>::_SafeConv): New
	constraint for construction/reset, using __sp_is_constructible_v.
	(__shared_ptr<__libfund_v1<_Tp, true>, _Lp>::_UniqCompatible): New
	constraint for conversions from unique_ptr.
	(__shared_ptr<__libfund_v1<_Tp, true>, _Lp>::__shared_ptr): Constrain.
	(__shared_ptr<__libfund_v1<_Tp, true>, _Lp>::reset): Likewise.
	(shared_ptr::_SafeConv): Constraint for checking constructors.
	(shared_ptr(Tp1*), shared_ptr(_Tp1, _Deleter))
	(shared_ptr(_Tp1, _Deleter, _Alloc)): Constrain with _SafeConv.
	(shared_ptr(const weak_ptr<_Tp1>&)): Constrain with _Compatible.
	(shared_ptr(auto_ptr<_Tp1>&&)): Fix, remove TODO.
	* testsuite/experimental/memory/shared_ptr/cons/pointer_ctor.cc:
	Remove tests using invalid conversions.
	* testsuite/experimental/memory/shared_ptr/cons/pointer_ctor_neg.cc:
	New test.
	* testsuite/experimental/memory/shared_ptr/cons/torture.cc: New test.
	* testsuite/experimental/memory/shared_ptr/modifiers/reset.cc: Remove
	tests using invalid conversions.
	* testsuite/experimental/memory/shared_ptr/modifiers/reset_neg.cc: New
	test.
	* testsuite/experimental/memory/shared_ptr/observers/use_count.cc:
	Remove tests using invalid conversions.

From-SVN: r241331
parent e182393e
2016-10-19 Jonathan Wakely <jwakely@redhat.com>
* include/experimental/bits/shared_ptr.h
(__shared_ptr<__libfund_v1<_Tp, false>, _Lp>::_Compatible): Just use
is_convertible for non-array specialization.
(__shared_ptr<__libfund_v1<_Tp, false>, _Lp>::_UniqCompatible): New
constraint for conversions from unique_ptr.
(__shared_ptr<__libfund_v1<_Tp, false>, _Lp>::__shared_ptr): Constrain.
(__shared_ptr<__libfund_v1<_Tp, false>, _Lp>::reset): Likewise.
(__sp_compatible_v): New variable template for trait.
(__sp_is_constructible): New trait to check shared_ptr constraints.
(__sp_is_constructible_v): New variable template for trait.
(__shared_ptr<__libfund_v1<_Tp, true>, _Lp>::_SafeConv): New
constraint for construction/reset, using __sp_is_constructible_v.
(__shared_ptr<__libfund_v1<_Tp, true>, _Lp>::_UniqCompatible): New
constraint for conversions from unique_ptr.
(__shared_ptr<__libfund_v1<_Tp, true>, _Lp>::__shared_ptr): Constrain.
(__shared_ptr<__libfund_v1<_Tp, true>, _Lp>::reset): Likewise.
(shared_ptr::_SafeConv): Constraint for checking constructors.
(shared_ptr(Tp1*), shared_ptr(_Tp1, _Deleter))
(shared_ptr(_Tp1, _Deleter, _Alloc)): Constrain with _SafeConv.
(shared_ptr(const weak_ptr<_Tp1>&)): Constrain with _Compatible.
(shared_ptr(auto_ptr<_Tp1>&&)): Fix, remove TODO.
* testsuite/experimental/memory/shared_ptr/cons/pointer_ctor.cc:
Remove tests using invalid conversions.
* testsuite/experimental/memory/shared_ptr/cons/pointer_ctor_neg.cc:
New test.
* testsuite/experimental/memory/shared_ptr/cons/torture.cc: New test.
* testsuite/experimental/memory/shared_ptr/modifiers/reset.cc: Remove
tests using invalid conversions.
* testsuite/experimental/memory/shared_ptr/modifiers/reset_neg.cc: New
test.
* testsuite/experimental/memory/shared_ptr/observers/use_count.cc:
Remove tests using invalid conversions.
PR libstdc++/77990
* include/bits/unique_ptr.h (__uniq_ptr_impl): New type to
encapsulate implementation details.
......
......@@ -23,40 +23,35 @@
#include <testsuite_hooks.h>
struct A { };
struct B : A { };
// 8.2.1.1 shared_ptr constructors [memory.smartptr.shared.const]
// Construction from pointer
int
void
test01()
{
A * const a = 0;
A * const a = new A;
std::experimental::shared_ptr<A> p(a);
VERIFY( p.get() == 0 );
VERIFY( p.get() == a );
VERIFY( p.use_count() == 1 );
return 0;
}
int
void
test02()
{
A * const a = new A[5];
std::experimental::shared_ptr<A[5]> p(a);
VERIFY( p.get() == a );
VERIFY( p.use_count() == 1 );
return 0;
}
int
void
test03()
{
B * const b = new B[5];
std::experimental::shared_ptr<A[5]> p(b);
VERIFY( p.get() == b );
A * const a = new A[5];
std::experimental::shared_ptr<A[]> p(a);
VERIFY( p.get() == a );
VERIFY( p.use_count() == 1 );
return 0;
}
int
......
// { dg-do compile { target c++14 } }
// Copyright (C) 2016 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
// terms of the GNU General Public License as published by the
// Free Software Foundation; either version 3, or (at your option)
// any later version.
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License along
// with this library; see the file COPYING3. If not see
// <http://www.gnu.org/licenses/>.
// 8.2.1 Class template shared_ptr [memory.smartptr.shared]
#include <experimental/memory>
struct A { };
struct B : A { };
struct C { };
struct D { void operator()(B* p) const { delete[] p; } };
// 8.2.1.1 shared_ptr constructors [memory.smartptr.shared.const]
// Construction from pointer
void
test01()
{
C * const c = nullptr;
std::experimental::shared_ptr<A> p(c); // { dg-error "no match" }
}
void
test02()
{
B * const b = nullptr;
std::experimental::shared_ptr<A[5]> p(b); // { dg-error "no match" }
}
void
test03()
{
B * const b = nullptr;
std::experimental::shared_ptr<A[]> p(b); // { dg-error "no match" }
}
// { dg-do compile { target c++14 } }
// Copyright (C) 2016 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
// terms of the GNU General Public License as published by the
// Free Software Foundation; either version 3, or (at your option)
// any later version.
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License along
// with this library; see the file COPYING3. If not see
// <http://www.gnu.org/licenses/>.
// 8.2.1 Class template shared_ptr [memory.smartptr.shared]
#include <experimental/memory>
using namespace std::experimental;
static_assert( !is_constructible_v<shared_ptr<int>, void*>,
"can query constructibility without forming invalid type void[]");
static_assert( !is_constructible_v<shared_ptr<int[2]>, void*>,
"can query constructibility without forming invalid type void[]");
static_assert( !is_constructible_v<shared_ptr<int[]>, void*>,
"can query constructibility without forming invalid type void[]");
static_assert( !is_constructible_v<shared_ptr<int>, void()>,
"can query constructibility without forming invalid type void()[]");
static_assert( !is_constructible_v<shared_ptr<int[2]>, void()>,
"can query constructibility without forming invalid type void()[]");
static_assert( !is_constructible_v<shared_ptr<int[]>, void()>,
"can query constructibility without forming invalid type void()[]");
static_assert( !is_constructible_v<shared_ptr<int>, void()>,
"can query constructibility without forming invalid type void(*)()[]");
static_assert( !is_constructible_v<shared_ptr<int[2]>, void()>,
"can query constructibility without forming invalid type void(*)()[]");
static_assert( !is_constructible_v<shared_ptr<int[]>, void()>,
"can query constructibility without forming invalid type void(*)()[]");
using A = int[];
static_assert( !is_constructible_v<shared_ptr<int>, A*>,
"can query constructibility without forming invalid type int[][]");
static_assert( !is_constructible_v<shared_ptr<int[2]>, A*>,
"can query constructibility without forming invalid type int[][]");
static_assert( !is_constructible_v<shared_ptr<int[]>, A*>,
"can query constructibility without forming invalid type int[][]");
......@@ -26,17 +26,17 @@ int destroyed = 0;
struct A : std::experimental::enable_shared_from_this<A>
{
~A() { ++destroyed; }
~A() { ++destroyed; }
};
// 8.2.1.1 shared_ptr constructors [memory.smartptr.shared.const]
// Construction from unique_ptr<A[]>
int
void
test01()
{
std::unique_ptr<A[]> up(new A[5]);
std::unique_ptr<A> up(new A);
std::experimental::shared_ptr<A> sp(std::move(up));
VERIFY( up.get() == 0 );
VERIFY( sp.get() != 0 );
......@@ -45,14 +45,28 @@ test01()
VERIFY( sp->shared_from_this() != nullptr );
sp.reset();
VERIFY( destroyed == 5 );
VERIFY( destroyed == 1 );
destroyed = 0;
}
return 0;
void
test02()
{
std::unique_ptr<A[]> up(new A[5]);
std::experimental::shared_ptr<A[]> sp(std::move(up));
VERIFY( up.get() == 0 );
VERIFY( sp.get() != 0 );
VERIFY( sp.use_count() == 1 );
VERIFY( sp[0].shared_from_this() != nullptr );
sp.reset();
VERIFY( destroyed == 5 );
}
int
main()
{
test01();
return 0;
test02();
}
......@@ -23,10 +23,9 @@
#include <testsuite_hooks.h>
struct A { };
struct B : A { };
struct D
{
void operator()(B* p) { delete [] p; ++delete_count; }
void operator()(A* p) { delete [] p; ++delete_count; }
static long delete_count;
};
long D::delete_count = 0;
......@@ -51,7 +50,7 @@ int
test02()
{
A * const a = new A[5];
B * const b = new B[5];
A * const b = new A[5];
std::experimental::shared_ptr<A[5]> p1(a);
std::experimental::shared_ptr<A[5]> p2(p1);
p1.reset(b);
......@@ -66,7 +65,7 @@ test03()
{
{
std::experimental::shared_ptr<A[5]> p1;
p1.reset(new B[5], D());
p1.reset(new A[5], D());
}
VERIFY( D::delete_count == 1 );
......
// { dg-do compile { target c++14 } }
// Copyright (C) 2016 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
// terms of the GNU General Public License as published by the
// Free Software Foundation; either version 3, or (at your option)
// any later version.
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License along
// with this library; see the file COPYING3. If not see
// <http://www.gnu.org/licenses/>.
// 8.2.1 Class template shared_ptr [memory.smartptr.shared]
#include <experimental/memory>
struct A { };
struct B : A { };
struct D
{
void operator()(A* p) { delete [] p; ++delete_count; }
static long delete_count;
};
long D::delete_count = 0;
// C++14 §20.8.2.2.4
// reset
void
test01()
{
std::experimental::shared_ptr<A[5]> p1(new A[5]);
p1.reset(new B[1]); // { dg-error "no matching function" }
p1.reset(new B[5], D()); // { dg-error "no matching function" }
using constA = const A;
p1.reset(new constA[5]); // { dg-error "no matching function" }
p1.reset(new constA[5], D()); // { dg-error "no matching function" }
}
......@@ -23,7 +23,6 @@
#include <testsuite_hooks.h>
struct A { };
struct B : A { };
// 8.2.1.2 shared_ptr observers [memory.smartptr.shared.obs]
......@@ -52,7 +51,7 @@ test03()
{
std::experimental::shared_ptr<A[5]> p1(new A[5]);
std::experimental::shared_ptr<A[5]> p2(p1);
p2.reset(new B[5]);
p2.reset(new A[5]);
VERIFY( p1.use_count() == 1 );
VERIFY( p2.use_count() == 1 );
}
......
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