From: Jonathan Wakely Date: Wed, 19 Oct 2016 09:35:03 +0000 (+0100) Subject: Fix std::experimental::shared_ptr SFINAE constraints X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=84870b6bb2691cc4031b8408b41bbb6583526c0f;p=gcc.git 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 --- diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 378d8177bac..200a5bdbcda 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,5 +1,38 @@ 2016-10-19 Jonathan Wakely + * 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. diff --git a/libstdc++-v3/include/experimental/bits/shared_ptr.h b/libstdc++-v3/include/experimental/bits/shared_ptr.h index e0ec00c1c67..2e3da62c599 100644 --- a/libstdc++-v3/include/experimental/bits/shared_ptr.h +++ b/libstdc++-v3/include/experimental/bits/shared_ptr.h @@ -69,53 +69,48 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template ::value> struct __libfund_v1 { using type = _Tp; }; - // helper for _Compatible - template - struct __sp_compatible - : is_convertible<_From_type*, _To_type*>::type - { }; - - template - struct __sp_compatible<_Tp[_Nm], _Tp[]> - : true_type - { }; - - template - struct __sp_compatible<_Tp[_Nm], const _Tp[]> - : true_type - { }; - // Partial specialization for base class of experimental::shared_ptr // (i.e. the non-array form of experimental::shared_ptr) template class __shared_ptr<__libfund_v1<_Tp, false>, _Lp> : private __shared_ptr<_Tp, _Lp> { - template + // For non-arrays, Y* is compatible with T* if Y* is convertible to T*. + template using _Compatible - = enable_if_t<__sp_compatible<_Tp1, _Tp>::value, _Res>; + = enable_if_t, _Res>; + + template::pointer, + typename _Res = void> + using _UniqCompatible = enable_if_t< + experimental::is_convertible_v<_Yp*, _Tp*> + && experimental::is_convertible_v<_Ptr, _Tp*>, + _Res>; using _Base_type = __shared_ptr<_Tp>; - _Base_type& _M_get_base() { return *this;} - const _Base_type& _M_get_base() const { return *this;} + _Base_type& _M_get_base() { return *this; } + const _Base_type& _M_get_base() const { return *this; } public: using element_type = _Tp; constexpr __shared_ptr() noexcept = default; - template - explicit __shared_ptr(_Tp1* __p) + template> + explicit + __shared_ptr(_Tp1* __p) : _Base_type(__p) { } - template + template> __shared_ptr(_Tp1* __p, _Deleter __d) : _Base_type(__p, __d) { } - template + template> __shared_ptr(_Tp1* __p, _Deleter __d, _Alloc __a) : _Base_type(__p, __d, __a) { } @@ -152,21 +147,21 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION : _Base_type(std::move((__r._M_get_base()))) { } - template - explicit __shared_ptr(const __weak_ptr<__libfund_v1<_Tp1>, _Lp>& __r) + template> + explicit + __shared_ptr(const __weak_ptr<__libfund_v1<_Tp1>, _Lp>& __r) : _Base_type(__r._M_get_base()) { } - template::pointer>>> - __shared_ptr(std::unique_ptr<_Tp1, _Del>&& __r) - : _Base_type(std::move(__r)) - { } + template> + __shared_ptr(unique_ptr<_Tp1, _Del>&& __r) + : _Base_type(std::move(__r)) + { } #if _GLIBCXX_USE_DEPRECATED // Postcondition: use_count() == 1 and __r.get() == 0 - template + template> __shared_ptr(std::auto_ptr<_Tp1>&& __r) : _Base_type(std::move(__r)) { } @@ -180,7 +175,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { __shared_ptr(nullptr).swap(*this); } template - void + _Compatible<_Tp1> reset(_Tp1* __p) { _GLIBCXX_DEBUG_ASSERT(__p == 0 || __p != get()); @@ -188,12 +183,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } template - void + _Compatible<_Tp1> reset(_Tp1* __p, _Deleter __d) { __shared_ptr(__p, __d).swap(*this); } template - void + _Compatible<_Tp1> reset(_Tp1* __p, _Deleter __d, _Alloc __a) { __shared_ptr(__p, __d, std::move(__a)).swap(*this); } @@ -216,9 +211,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return *this; } - template - _Compatible<_Tp1, __shared_ptr&> - operator=(std::unique_ptr<_Tp1>&& __r) + template + _UniqCompatible<_Tp1, _Del, __shared_ptr&> + operator=(unique_ptr<_Tp1, _Del>&& __r) { _Base_type::operator=(std::move(__r)); return *this; @@ -282,6 +277,77 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION friend _Del* get_deleter(const __shared_ptr<_Tp1, _Lp1>&) noexcept; }; + // Helper traits for shared_ptr of array: + + // Trait that tests if Y* is compatible with T*, for shared_ptr purposes. + template + struct __sp_compatible + : is_convertible<_Yp*, _Tp*>::type + { }; + + template + struct __sp_compatible<_Tp[_Nm], _Tp[]> + : true_type + { }; + + template + struct __sp_compatible<_Tp[_Nm], const _Tp[]> + : true_type + { }; + + template + constexpr bool __sp_compatible_v + = __sp_compatible<_Yp, _Tp>::value; + + // Test conversion from Y(*)[N] to U(*)[N] without forming invalid type Y[N]. + template + struct __sp_is_constructible_arrN + : false_type + { }; + + template + struct __sp_is_constructible_arrN<_Up, _Nm, _Yp, __void_t<_Yp[_Nm]>> + : is_convertible<_Yp(*)[_Nm], _Up(*)[_Nm]>::type + { }; + + // Test conversion from Y(*)[] to U(*)[] without forming invalid type Y[]. + template + struct __sp_is_constructible_arr + : false_type + { }; + + template + struct __sp_is_constructible_arr<_Up, _Yp, __void_t<_Yp[]>> + : is_convertible<_Yp(*)[], _Up(*)[]>::type + { }; + + // Trait to check if shared_ptr can be constructed from Y*. + template + struct __sp_is_constructible; + + // When T is U[N], Y(*)[N] shall be convertible to T*; + template + struct __sp_is_constructible<_Up[_Nm], _Yp> + : __sp_is_constructible_arrN<_Up, _Nm, _Yp>::type + { }; + + // when T is U[], Y(*)[] shall be convertible to T*; + template + struct __sp_is_constructible<_Up[], _Yp> + : __sp_is_constructible_arr<_Up, _Yp>::type + { }; + + // otherwise, Y* shall be convertible to T*. + template + struct __sp_is_constructible + : is_convertible<_Yp*, _Tp*>::type + { }; + + template + constexpr bool __sp_is_constructible_v + = __sp_is_constructible<_Tp, _Yp>::value; + + // Partial specialization for base class of experimental::shared_ptr // and experimental::shared_ptr (i.e. the array forms). template @@ -299,31 +365,46 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { delete [] __p; } }; + // Constraint for constructing/resetting with a pointer of type _Yp*: + template + using _SafeConv = enable_if_t<__sp_is_constructible_v<_Tp, _Yp>>; + + // Constraint for constructing/assigning from smart_pointer<_Tp1>: template - using _Compatible - = enable_if_t<__sp_compatible<_Tp1, _Tp>::value, _Res>; + using _Compatible = enable_if_t<__sp_compatible_v<_Tp1, _Tp>, _Res>; + + // Constraint for constructing/assigning from unique_ptr<_Tp1, _Del>: + template::pointer, + typename _Res = void> + using _UniqCompatible = enable_if_t< + __sp_compatible_v<_Tp1, _Tp> + && experimental::is_convertible_v<_Ptr, element_type*>, + _Res>; using _Base_type = __shared_ptr; - _Base_type& _M_get_base() { return *this;} - const _Base_type& _M_get_base() const { return *this;} + _Base_type& _M_get_base() { return *this; } + const _Base_type& _M_get_base() const { return *this; } public: constexpr __shared_ptr() noexcept : _Base_type() { } - template - explicit __shared_ptr(_Tp1* __p) + template> + explicit + __shared_ptr(_Tp1* __p) : _Base_type(__p, _Array_deleter()) { } - template + template> __shared_ptr(_Tp1* __p, _Deleter __d) : _Base_type(__p, __d) { } - template + template> __shared_ptr(_Tp1* __p, _Deleter __d, _Alloc __a) : _Base_type(__p, __d, __a) { } @@ -360,22 +441,22 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION : _Base_type(std::move((__r._M_get_base()))) { } - template - explicit __shared_ptr(const __weak_ptr<__libfund_v1<_Tp1>, _Lp>& __r) + template> + explicit + __shared_ptr(const __weak_ptr<__libfund_v1<_Tp1>, _Lp>& __r) : _Base_type(__r._M_get_base()) { } - template::pointer>>> - __shared_ptr(std::unique_ptr<_Tp1, _Del>&& __r) - : _Base_type(std::move(__r)) - { } + template> + __shared_ptr(unique_ptr<_Tp1, _Del>&& __r) + : _Base_type(std::move(__r)) + { } #if _GLIBCXX_USE_DEPRECATED // Postcondition: use_count() == 1 and __r.get() == 0 - template - __shared_ptr(std::auto_ptr<_Tp1>&& __r) + template> + __shared_ptr(auto_ptr<_Tp1>&& __r) : _Base_type(std::move(__r)) { } #endif @@ -388,7 +469,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { __shared_ptr(nullptr).swap(*this); } template - void + _SafeConv<_Tp1> reset(_Tp1* __p) { _GLIBCXX_DEBUG_ASSERT(__p == 0 || __p != get()); @@ -396,12 +477,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } template - void + _SafeConv<_Tp1> reset(_Tp1* __p, _Deleter __d) { __shared_ptr(__p, __d).swap(*this); } template - void + _SafeConv<_Tp1> reset(_Tp1* __p, _Deleter __d, _Alloc __a) { __shared_ptr(__p, __d, std::move(__a)).swap(*this); } @@ -428,9 +509,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return *this; } - template - _Compatible<_Tp1, __shared_ptr&> - operator=(std::unique_ptr<_Tp1>&& __r) + template + _UniqCompatible<_Tp1, _Del, __shared_ptr&> + operator=(unique_ptr<_Tp1, _Del>&& __r) { _Base_type::operator=(std::move(__r)); return *this; @@ -439,7 +520,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #if _GLIBCXX_USE_DEPRECATED template _Compatible<_Tp1, __shared_ptr&> - operator=(std::auto_ptr<_Tp1>&& __r) + operator=(auto_ptr<_Tp1>&& __r) { _Base_type::operator=(std::move(__r)); return *this; @@ -501,11 +582,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { template using _Compatible - = enable_if_t<__sp_compatible<_Tp1, _Tp>::value, _Res>; + = enable_if_t<__sp_compatible_v<_Tp1, _Tp>, _Res>; using _Base_type = __weak_ptr>; - _Base_type& _M_get_base() { return *this;} + _Base_type& _M_get_base() { return *this; } const _Base_type& _M_get_base() const { return *this; } public: @@ -630,26 +711,43 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template class shared_ptr : public __shared_ptr<_Tp> { + using _Base_type = __shared_ptr<_Tp>; + + public: + using element_type = typename _Base_type::element_type; + + private: + // Constraint for construction from a pointer of type _Yp*: + template + using _SafeConv = enable_if_t<__sp_is_constructible_v<_Tp, _Yp>>; + template using _Compatible - = enable_if_t<__sp_compatible<_Tp1, _Tp>::value, _Res>; + = enable_if_t<__sp_compatible_v<_Tp1, _Tp>, _Res>; - using _Base_type = __shared_ptr<_Tp>; + template::pointer, + typename _Res = void> + using _UniqCompatible = enable_if_t< + __sp_compatible_v<_Tp1, _Tp> + && experimental::is_convertible_v<_Ptr, element_type*>, + _Res>; public: - using element_type = typename _Base_type::element_type; // 8.2.1.1, shared_ptr constructors constexpr shared_ptr() noexcept = default; - template - explicit shared_ptr(_Tp1* __p) : _Base_type(__p) { } + template> + explicit + shared_ptr(_Tp1* __p) : _Base_type(__p) { } - template + template> shared_ptr(_Tp1* __p, _Deleter __d) : _Base_type(__p, __d) { } - template + template> shared_ptr(_Tp1* __p, _Deleter __d, _Alloc __a) : _Base_type(__p, __d, __a) { } @@ -679,20 +777,20 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION shared_ptr(shared_ptr<_Tp1>&& __r) noexcept : _Base_type(std::move(__r)) { } - template - explicit shared_ptr(const weak_ptr<_Tp1>& __r) + template> + explicit + shared_ptr(const weak_ptr<_Tp1>& __r) : _Base_type(__r) { } #if _GLIBCXX_USE_DEPRECATED - template + template> shared_ptr(std::auto_ptr<_Tp1>&& __r) - : _Base_type() { } // TODO + : _Base_type(std::move(__r)) { } #endif - template::pointer>>> - shared_ptr(std::unique_ptr<_Tp1, _Del>&& __r) + template> + shared_ptr(unique_ptr<_Tp1, _Del>&& __r) : _Base_type(std::move(__r)) { } constexpr shared_ptr(nullptr_t __p) @@ -738,7 +836,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #endif template - _Compatible<_Tp1, shared_ptr&> + _UniqCompatible<_Tp1, _Del, shared_ptr&> operator=(unique_ptr<_Tp1, _Del>&& __r) { _Base_type::operator=(std::move(__r)); @@ -752,10 +850,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION private: template - shared_ptr(_Sp_make_shared_tag __tag, const _Alloc& __a, - _Args&&... __args) - : _Base_type(__tag, __a, std::forward<_Args>(__args)...) - { } + shared_ptr(_Sp_make_shared_tag __tag, const _Alloc& __a, + _Args&&... __args) + : _Base_type(__tag, __a, std::forward<_Args>(__args)...) + { } template friend shared_ptr<_Tp1> @@ -926,8 +1024,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION class weak_ptr : public __weak_ptr<_Tp> { template - using _Compatible - = enable_if_t<__sp_compatible<_Tp1, _Tp>::value, _Res>; + using _Compatible = enable_if_t<__sp_compatible_v<_Tp1, _Tp>, _Res>; using _Base_type = __weak_ptr<_Tp>; @@ -1147,6 +1244,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION shared_from_this() const { return shared_ptr(this->_M_weak_this); } + weak_ptr<_Tp> + weak_from_this() noexcept + { return _M_weak_this; } + + weak_ptr + weak_from_this() const noexcept + { return _M_weak_this; } + private: template void diff --git a/libstdc++-v3/testsuite/experimental/memory/shared_ptr/cons/pointer_ctor.cc b/libstdc++-v3/testsuite/experimental/memory/shared_ptr/cons/pointer_ctor.cc index 5a14f7cbb8b..1fff0225386 100644 --- a/libstdc++-v3/testsuite/experimental/memory/shared_ptr/cons/pointer_ctor.cc +++ b/libstdc++-v3/testsuite/experimental/memory/shared_ptr/cons/pointer_ctor.cc @@ -23,40 +23,35 @@ #include 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 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 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 p(b); - VERIFY( p.get() == b ); + A * const a = new A[5]; + std::experimental::shared_ptr p(a); + VERIFY( p.get() == a ); VERIFY( p.use_count() == 1 ); - - return 0; } int diff --git a/libstdc++-v3/testsuite/experimental/memory/shared_ptr/cons/pointer_ctor_neg.cc b/libstdc++-v3/testsuite/experimental/memory/shared_ptr/cons/pointer_ctor_neg.cc new file mode 100644 index 00000000000..8fcd40ce8f0 --- /dev/null +++ b/libstdc++-v3/testsuite/experimental/memory/shared_ptr/cons/pointer_ctor_neg.cc @@ -0,0 +1,51 @@ +// { 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 +// . + +// 8.2.1 Class template shared_ptr [memory.smartptr.shared] + +#include + +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 p(c); // { dg-error "no match" } +} + +void +test02() +{ + B * const b = nullptr; + std::experimental::shared_ptr p(b); // { dg-error "no match" } +} + +void +test03() +{ + B * const b = nullptr; + std::experimental::shared_ptr p(b); // { dg-error "no match" } +} diff --git a/libstdc++-v3/testsuite/experimental/memory/shared_ptr/cons/torture.cc b/libstdc++-v3/testsuite/experimental/memory/shared_ptr/cons/torture.cc new file mode 100644 index 00000000000..bade9d83dd4 --- /dev/null +++ b/libstdc++-v3/testsuite/experimental/memory/shared_ptr/cons/torture.cc @@ -0,0 +1,53 @@ +// { 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 +// . + +// 8.2.1 Class template shared_ptr [memory.smartptr.shared] + +#include + +using namespace std::experimental; + +static_assert( !is_constructible_v, void*>, + "can query constructibility without forming invalid type void[]"); +static_assert( !is_constructible_v, void*>, + "can query constructibility without forming invalid type void[]"); +static_assert( !is_constructible_v, void*>, + "can query constructibility without forming invalid type void[]"); + +static_assert( !is_constructible_v, void()>, + "can query constructibility without forming invalid type void()[]"); +static_assert( !is_constructible_v, void()>, + "can query constructibility without forming invalid type void()[]"); +static_assert( !is_constructible_v, void()>, + "can query constructibility without forming invalid type void()[]"); + +static_assert( !is_constructible_v, void()>, + "can query constructibility without forming invalid type void(*)()[]"); +static_assert( !is_constructible_v, void()>, + "can query constructibility without forming invalid type void(*)()[]"); +static_assert( !is_constructible_v, void()>, + "can query constructibility without forming invalid type void(*)()[]"); + +using A = int[]; +static_assert( !is_constructible_v, A*>, + "can query constructibility without forming invalid type int[][]"); +static_assert( !is_constructible_v, A*>, + "can query constructibility without forming invalid type int[][]"); +static_assert( !is_constructible_v, A*>, + "can query constructibility without forming invalid type int[][]"); diff --git a/libstdc++-v3/testsuite/experimental/memory/shared_ptr/cons/unique_ptr_ctor.cc b/libstdc++-v3/testsuite/experimental/memory/shared_ptr/cons/unique_ptr_ctor.cc index 5b4938b33ef..631212fc4cd 100644 --- a/libstdc++-v3/testsuite/experimental/memory/shared_ptr/cons/unique_ptr_ctor.cc +++ b/libstdc++-v3/testsuite/experimental/memory/shared_ptr/cons/unique_ptr_ctor.cc @@ -26,17 +26,17 @@ int destroyed = 0; struct A : std::experimental::enable_shared_from_this { - ~A() { ++destroyed; } + ~A() { ++destroyed; } }; // 8.2.1.1 shared_ptr constructors [memory.smartptr.shared.const] // Construction from unique_ptr -int +void test01() { - std::unique_ptr up(new A[5]); + std::unique_ptr up(new A); std::experimental::shared_ptr 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 up(new A[5]); + std::experimental::shared_ptr 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(); } diff --git a/libstdc++-v3/testsuite/experimental/memory/shared_ptr/modifiers/reset.cc b/libstdc++-v3/testsuite/experimental/memory/shared_ptr/modifiers/reset.cc index e0be63bea4d..8df0602f4f8 100644 --- a/libstdc++-v3/testsuite/experimental/memory/shared_ptr/modifiers/reset.cc +++ b/libstdc++-v3/testsuite/experimental/memory/shared_ptr/modifiers/reset.cc @@ -23,10 +23,9 @@ #include 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 p1(a); std::experimental::shared_ptr p2(p1); p1.reset(b); @@ -66,7 +65,7 @@ test03() { { std::experimental::shared_ptr p1; - p1.reset(new B[5], D()); + p1.reset(new A[5], D()); } VERIFY( D::delete_count == 1 ); diff --git a/libstdc++-v3/testsuite/experimental/memory/shared_ptr/modifiers/reset_neg.cc b/libstdc++-v3/testsuite/experimental/memory/shared_ptr/modifiers/reset_neg.cc new file mode 100644 index 00000000000..0332c4e7603 --- /dev/null +++ b/libstdc++-v3/testsuite/experimental/memory/shared_ptr/modifiers/reset_neg.cc @@ -0,0 +1,45 @@ +// { 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 +// . + +// 8.2.1 Class template shared_ptr [memory.smartptr.shared] + +#include + +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 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" } +} diff --git a/libstdc++-v3/testsuite/experimental/memory/shared_ptr/observers/use_count.cc b/libstdc++-v3/testsuite/experimental/memory/shared_ptr/observers/use_count.cc index b591a7e319c..a91a92a43b1 100644 --- a/libstdc++-v3/testsuite/experimental/memory/shared_ptr/observers/use_count.cc +++ b/libstdc++-v3/testsuite/experimental/memory/shared_ptr/observers/use_count.cc @@ -23,7 +23,6 @@ #include 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 p1(new A[5]); std::experimental::shared_ptr p2(p1); - p2.reset(new B[5]); + p2.reset(new A[5]); VERIFY( p1.use_count() == 1 ); VERIFY( p2.use_count() == 1 ); }