This patch started when I noticed that it's not possibly to construct a shared_ptr<T> from unique_ptr<T[], D>, then I discovered we don't use D::pointer if it exists, and there were a number of other non-conformance issues with our std::unique_ptr<T[], D>. I ended up fixing them by implementing Geoffrey's proposed resolution for LWG issue 2118, which isn't official yet but is better than what we had before so is a step in the right direction, even if it ends up needing further revision when 2118 is resolved.
* include/std/functional (_Require): Move to ... * include/std/type_traits (_Require): ... here. * include/bits/shared_ptr_base.h (__shared_count::_S_create_from_up): Handle unique_ptr for arrays or with custom pointer types. (__shared_ptr::__shared_ptr(unique_ptr<_Tp1, _Del>&&): Likewise. * include/bits/unique_ptr.h (unique_ptr<_Tp[], _Dp>): Use _Dp::pointer if defined. Implement proposed resolution of LWG 2118. * testsuite/20_util/shared_ptr/cons/unique_ptr_array.cc: New. * testsuite/20_util/unique_ptr/assign/cv_qual.cc: New. * testsuite/20_util/unique_ptr/cons/array_convertible_neg.cc: New. * testsuite/20_util/unique_ptr/cons/convertible_neg.cc: New. * testsuite/20_util/unique_ptr/cons/cv_qual.cc: New. * testsuite/20_util/unique_ptr/modifiers/cv_qual.cc: New. * testsuite/20_util/unique_ptr/requirements/pointer_type_array.cc: New. * testsuite/20_util/shared_ptr/cons/unique_ptr.cc: Adjust comments. * testsuite/20_util/unique_ptr/cons/pointer_array_convertible_neg.cc: Likewise. * testsuite/20_util/unique_ptr/requirements/pointer_type.cc: Likewise. * testsuite/20_util/bind/ref_neg.cc: Adjust dg-error line number. * testsuite/20_util/declval/requirements/1_neg.cc: Likewise. * testsuite/20_util/default_delete/48631_neg.cc: Likewise. * testsuite/20_util/shared_ptr/cons/43820_neg.cc: Likewise. * testsuite/20_util/unique_ptr/assign/48635_neg.cc: Likewise. * testsuite/20_util/unique_ptr/modifiers/reset_neg.cc: Adjust dg-error text. * testsuite/20_util/unique_ptr/cons/ptr_deleter_neg.cc: Use different instantiations so static_assert fails for each. Thanks to Geoffrey and Lawrence for input and test cases. Tested x86_64-linux, committed to trunk.
commit 907290c8077e6757c56fc64c9160c4bdaea86b90 Author: Jonathan Wakely <jwakely....@gmail.com> Date: Thu Dec 20 17:57:33 2012 +0000 * include/std/functional (_Require): Move to ... * include/std/type_traits (_Require): ... here. * include/bits/shared_ptr_base.h (__shared_count::_S_create_from_up): Handle unique_ptr for arrays or with custom pointer types. (__shared_ptr::__shared_ptr(unique_ptr<_Tp1, _Del>&&): Likewise. * include/bits/unique_ptr.h (unique_ptr<_Tp[], _Dp>): Use _Dp::pointer if defined. Implement proposed resolution of LWG 2118. * testsuite/20_util/shared_ptr/cons/unique_ptr_array.cc: New. * testsuite/20_util/unique_ptr/assign/cv_qual.cc: New. * testsuite/20_util/unique_ptr/cons/array_convertible_neg.cc: New. * testsuite/20_util/unique_ptr/cons/convertible_neg.cc: New. * testsuite/20_util/unique_ptr/cons/cv_qual.cc: New. * testsuite/20_util/unique_ptr/modifiers/cv_qual.cc: New. * testsuite/20_util/unique_ptr/requirements/pointer_type_array.cc: New. * testsuite/20_util/shared_ptr/cons/unique_ptr.cc: Adjust comments. * testsuite/20_util/unique_ptr/cons/pointer_array_convertible_neg.cc: Likewise. * testsuite/20_util/unique_ptr/requirements/pointer_type.cc: Likewise. * testsuite/20_util/bind/ref_neg.cc: Adjust dg-error line number. * testsuite/20_util/declval/requirements/1_neg.cc: Likewise. * testsuite/20_util/default_delete/48631_neg.cc: Likewise. * testsuite/20_util/shared_ptr/cons/43820_neg.cc: Likewise. * testsuite/20_util/unique_ptr/assign/48635_neg.cc: Likewise. * testsuite/20_util/unique_ptr/modifiers/reset_neg.cc: Adjust dg-error text. * testsuite/20_util/unique_ptr/cons/ptr_deleter_neg.cc: Use different instantiations so static_assert fails for each. diff --git a/libstdc++-v3/include/bits/shared_ptr_base.h b/libstdc++-v3/include/bits/shared_ptr_base.h index ead3728..9d9fecb 100644 --- a/libstdc++-v3/include/bits/shared_ptr_base.h +++ b/libstdc++-v3/include/bits/shared_ptr_base.h @@ -616,7 +616,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _S_create_from_up(std::unique_ptr<_Tp, _Del>&& __r, typename std::enable_if<!std::is_reference<_Del>::value>::type* = 0) { - return new _Sp_counted_deleter<_Tp*, _Del, std::allocator<void>, + typedef typename unique_ptr<_Tp, _Del>::pointer _Ptr; + return new _Sp_counted_deleter<_Ptr, _Del, std::allocator<void>, _Lp>(__r.get(), __r.get_deleter()); } @@ -625,9 +626,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _S_create_from_up(std::unique_ptr<_Tp, _Del>&& __r, typename std::enable_if<std::is_reference<_Del>::value>::type* = 0) { + typedef typename unique_ptr<_Tp, _Del>::pointer _Ptr; typedef typename std::remove_reference<_Del>::type _Del1; typedef std::reference_wrapper<_Del1> _Del2; - return new _Sp_counted_deleter<_Tp*, _Del2, std::allocator<void>, + return new _Sp_counted_deleter<_Ptr, _Del2, std::allocator<void>, _Lp>(__r.get(), std::ref(__r.get_deleter())); } @@ -846,7 +848,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION : _M_ptr(__r.get()), _M_refcount() { __glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>) - _Tp1* __tmp = __r.get(); + auto __tmp = std::__addressof(*__r.get()); _M_refcount = __shared_count<_Lp>(std::move(__r)); __enable_shared_from_this_helper(_M_refcount, __tmp, __tmp); } diff --git a/libstdc++-v3/include/bits/unique_ptr.h b/libstdc++-v3/include/bits/unique_ptr.h index 37eae25..e17a4dc 100644 --- a/libstdc++-v3/include/bits/unique_ptr.h +++ b/libstdc++-v3/include/bits/unique_ptr.h @@ -56,7 +56,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION constexpr default_delete() noexcept = default; template<typename _Up, typename = typename - std::enable_if<std::is_convertible<_Up*, _Tp*>::value>::type> + enable_if<is_convertible<_Up*, _Tp*>::value>::type> default_delete(const default_delete<_Up>&) noexcept { } void @@ -74,8 +74,23 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<typename _Tp> struct default_delete<_Tp[]> { + private: + template<typename _Up> + using __remove_cv = typename remove_cv<_Up>::type; + + // Like is_base_of<_Tp, _Up> but false if unqualified types are the same + template<typename _Up> + using __is_derived_Tp + = __and_< is_base_of<_Tp, _Up>, + __not_<is_same<__remove_cv<_Tp>, __remove_cv<_Up>>> >; + + public: constexpr default_delete() noexcept = default; + template<typename _Up, typename = typename + enable_if<!__is_derived_Tp<_Up>::value>::type> + default_delete(const default_delete<_Up[]>&) noexcept { } + void operator()(_Tp* __ptr) const { @@ -84,7 +99,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION delete [] __ptr; } - template<typename _Up> void operator()(_Up*) const = delete; + template<typename _Up> + typename enable_if<__is_derived_Tp<_Up>::value>::type + operator()(_Up*) const = delete; }; /// 20.7.1.2 unique_ptr for single objects. @@ -103,7 +120,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION typedef typename remove_reference<_Dp>::type _Del; public: - typedef decltype( __test<_Del>(0)) type; + typedef decltype(__test<_Del>(0)) type; }; typedef std::tuple<typename _Pointer::type, _Dp> __tuple_type; @@ -117,54 +134,45 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // Constructors. constexpr unique_ptr() noexcept : _M_t() - { static_assert(!std::is_pointer<deleter_type>::value, + { static_assert(!is_pointer<deleter_type>::value, "constructed with null function pointer deleter"); } explicit unique_ptr(pointer __p) noexcept : _M_t(__p, deleter_type()) - { static_assert(!std::is_pointer<deleter_type>::value, + { static_assert(!is_pointer<deleter_type>::value, "constructed with null function pointer deleter"); } unique_ptr(pointer __p, - typename std::conditional<std::is_reference<deleter_type>::value, + typename conditional<is_reference<deleter_type>::value, deleter_type, const deleter_type&>::type __d) noexcept : _M_t(__p, __d) { } unique_ptr(pointer __p, - typename std::remove_reference<deleter_type>::type&& __d) noexcept + typename remove_reference<deleter_type>::type&& __d) noexcept : _M_t(std::move(__p), std::move(__d)) { static_assert(!std::is_reference<deleter_type>::value, "rvalue deleter bound to reference"); } - constexpr unique_ptr(nullptr_t) noexcept - : _M_t() - { static_assert(!std::is_pointer<deleter_type>::value, - "constructed with null function pointer deleter"); } + constexpr unique_ptr(nullptr_t) noexcept : unique_ptr() { } // Move constructors. unique_ptr(unique_ptr&& __u) noexcept : _M_t(__u.release(), std::forward<deleter_type>(__u.get_deleter())) { } - template<typename _Up, typename _Ep, typename = typename - std::enable_if - <std::is_convertible<typename unique_ptr<_Up, _Ep>::pointer, - pointer>::value - && !std::is_array<_Up>::value - && ((std::is_reference<_Dp>::value - && std::is_same<_Ep, _Dp>::value) - || (!std::is_reference<_Dp>::value - && std::is_convertible<_Ep, _Dp>::value))> - ::type> + template<typename _Up, typename _Ep, typename = _Require< + is_convertible<typename unique_ptr<_Up, _Ep>::pointer, pointer>, + __not_<is_array<_Up>>, + typename conditional<is_reference<_Dp>::value, + is_same<_Ep, _Dp>, + is_convertible<_Ep, _Dp>>::type>> unique_ptr(unique_ptr<_Up, _Ep>&& __u) noexcept : _M_t(__u.release(), std::forward<_Ep>(__u.get_deleter())) { } #if _GLIBCXX_USE_DEPRECATED - template<typename _Up, typename = typename - std::enable_if<std::is_convertible<_Up*, _Tp*>::value - && std::is_same<_Dp, - default_delete<_Tp>>::value>::type> + template<typename _Up, typename = _Require< + is_convertible<_Up*, _Tp*>, is_same<_Dp, default_delete<_Tp>>>> unique_ptr(auto_ptr<_Up>&& __u) noexcept; #endif @@ -186,12 +194,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return *this; } - template<typename _Up, typename _Ep, typename = typename - std::enable_if - <std::is_convertible<typename unique_ptr<_Up, _Ep>::pointer, - pointer>::value - && !std::is_array<_Up>::value>::type> - unique_ptr& + template<typename _Up, typename _Ep> + typename enable_if< __and_< + is_convertible<typename unique_ptr<_Up, _Ep>::pointer, pointer>, + __not_<is_array<_Up>> + >::value, + unique_ptr&>::type operator=(unique_ptr<_Up, _Ep>&& __u) noexcept { reset(__u.release()); @@ -207,7 +215,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } // Observers. - typename std::add_lvalue_reference<element_type>::type + typename add_lvalue_reference<element_type>::type operator*() const { _GLIBCXX_DEBUG_ASSERT(get() != pointer()); @@ -273,11 +281,47 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<typename _Tp, typename _Dp> class unique_ptr<_Tp[], _Dp> { - typedef std::tuple<_Tp*, _Dp> __tuple_type; - __tuple_type _M_t; + // use SFINAE to determine whether _Del::pointer exists + class _Pointer + { + template<typename _Up> + static typename _Up::pointer __test(typename _Up::pointer*); + + template<typename _Up> + static _Tp* __test(...); + + typedef typename remove_reference<_Dp>::type _Del; + + public: + typedef decltype(__test<_Del>(0)) type; + }; + + typedef std::tuple<typename _Pointer::type, _Dp> __tuple_type; + __tuple_type _M_t; + + template<typename _Up> + using __remove_cv = typename remove_cv<_Up>::type; + + // like is_base_of<_Tp, _Up> but false if unqualified types are the same + template<typename _Up> + using __is_derived_Tp + = __and_< is_base_of<_Tp, _Up>, + __not_<is_same<__remove_cv<_Tp>, __remove_cv<_Up>>> >; + + template<typename _Up, typename _Ep, + typename _Tp_pointer = typename _Pointer::type, + typename _Up_pointer = typename unique_ptr<_Up, _Ep>::pointer> + using __safe_conversion = __and_< + is_convertible<_Up_pointer, _Tp_pointer>, + is_array<_Up>, + __or_<__not_<is_pointer<_Up_pointer>>, + __not_<is_pointer<_Tp_pointer>>, + __not_<__is_derived_Tp<typename remove_extent<_Up>::type>> + > + >; public: - typedef _Tp* pointer; + typedef typename _Pointer::type pointer; typedef _Tp element_type; typedef _Dp deleter_type; @@ -285,35 +329,42 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION constexpr unique_ptr() noexcept : _M_t() { static_assert(!std::is_pointer<deleter_type>::value, - "constructed with null function pointer deleter"); } + "constructed with null function pointer deleter"); } explicit unique_ptr(pointer __p) noexcept : _M_t(__p, deleter_type()) - { static_assert(!std::is_pointer<deleter_type>::value, - "constructed with null function pointer deleter"); } + { static_assert(!is_pointer<deleter_type>::value, + "constructed with null function pointer deleter"); } + + template<typename _Up, typename = _Require<is_pointer<pointer>, + is_convertible<_Up*, pointer>, __is_derived_Tp<_Up>>> + explicit + unique_ptr(_Up* __p) = delete; unique_ptr(pointer __p, - typename std::conditional<std::is_reference<deleter_type>::value, + typename conditional<is_reference<deleter_type>::value, deleter_type, const deleter_type&>::type __d) noexcept : _M_t(__p, __d) { } unique_ptr(pointer __p, typename - std::remove_reference<deleter_type>::type && __d) noexcept + remove_reference<deleter_type>::type&& __d) noexcept : _M_t(std::move(__p), std::move(__d)) - { static_assert(!std::is_reference<deleter_type>::value, + { static_assert(!is_reference<deleter_type>::value, "rvalue deleter bound to reference"); } - constexpr unique_ptr(nullptr_t) noexcept - : _M_t() - { static_assert(!std::is_pointer<deleter_type>::value, - "constructed with null function pointer deleter"); } - - // Move constructors. + // Move constructor. unique_ptr(unique_ptr&& __u) noexcept : _M_t(__u.release(), std::forward<deleter_type>(__u.get_deleter())) { } - template<typename _Up, typename _Ep> + constexpr unique_ptr(nullptr_t) noexcept : unique_ptr() { } + + template<typename _Up, typename _Ep, + typename = _Require<__safe_conversion<_Up, _Ep>, + typename conditional<is_reference<_Dp>::value, + is_same<_Ep, _Dp>, + is_convertible<_Ep, _Dp>>::type + >> unique_ptr(unique_ptr<_Up, _Ep>&& __u) noexcept : _M_t(__u.release(), std::forward<_Ep>(__u.get_deleter())) { } @@ -337,7 +388,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } template<typename _Up, typename _Ep> - unique_ptr& + typename + enable_if<__safe_conversion<_Up, _Ep>::value, unique_ptr&>::type operator=(unique_ptr<_Up, _Ep>&& __u) noexcept { reset(__u.release()); @@ -385,26 +437,21 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } void - reset(pointer __p = pointer()) noexcept - { - using std::swap; - swap(std::get<0>(_M_t), __p); - if (__p != nullptr) - get_deleter()(__p); - } + reset() noexcept + { reset(pointer()); } void - reset(nullptr_t) noexcept + reset(pointer __p) noexcept { - pointer __p = get(); - std::get<0>(_M_t) = pointer(); + using std::swap; + swap(std::get<0>(_M_t), __p); if (__p != nullptr) get_deleter()(__p); } - // DR 821. - template<typename _Up> - void reset(_Up) = delete; + template<typename _Up, typename = _Require<is_pointer<pointer>, + is_convertible<_Up*, pointer>, __is_derived_Tp<_Up>>> + void reset(_Up*) = delete; void swap(unique_ptr& __u) noexcept @@ -418,23 +465,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION unique_ptr& operator=(const unique_ptr&) = delete; // Disable construction from convertible pointer types. - // (N2315 - 20.7.1.3.1) - template<typename _Up> + template<typename _Up, typename = _Require<is_pointer<pointer>, + is_convertible<_Up*, pointer>, __is_derived_Tp<_Up>>> unique_ptr(_Up*, typename - std::conditional<std::is_reference<deleter_type>::value, - deleter_type, const deleter_type&>::type, - typename std::enable_if<std::is_convertible<_Up*, - pointer>::value>::type* = 0) = delete; - - template<typename _Up> - unique_ptr(_Up*, typename std::remove_reference<deleter_type>::type&&, - typename std::enable_if<std::is_convertible<_Up*, - pointer>::value>::type* = 0) = delete; + conditional<is_reference<deleter_type>::value, + deleter_type, const deleter_type&>::type) = delete; - template<typename _Up> - explicit - unique_ptr(_Up*, typename std::enable_if<std::is_convertible<_Up*, - pointer>::value>::type* = 0) = delete; + template<typename _Up, typename = _Require<is_pointer<pointer>, + is_convertible<_Up*, pointer>, __is_derived_Tp<_Up>>> + unique_ptr(_Up*, typename + remove_reference<deleter_type>::type&&) = delete; }; template<typename _Tp, typename _Dp> diff --git a/libstdc++-v3/include/std/functional b/libstdc++-v3/include/std/functional index 604481b..3ec2e1e 100644 --- a/libstdc++-v3/include/std/functional +++ b/libstdc++-v3/include/std/functional @@ -501,9 +501,6 @@ _GLIBCXX_HAS_NESTED_TYPE(result_type) // @} group functors - template<typename... _Cond> - using _Require = typename enable_if<__and_<_Cond...>::value>::type; - template<typename... _Types> struct _Pack : integral_constant<size_t, sizeof...(_Types)> { }; diff --git a/libstdc++-v3/include/std/type_traits b/libstdc++-v3/include/std/type_traits index cd7d728..e274727 100644 --- a/libstdc++-v3/include/std/type_traits +++ b/libstdc++-v3/include/std/type_traits @@ -1771,6 +1771,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION struct enable_if<true, _Tp> { typedef _Tp type; }; + template<typename... _Cond> + using _Require = typename enable_if<__and_<_Cond...>::value>::type; // Primary template. /// Define a member typedef @c type to one of two argument types. diff --git a/libstdc++-v3/testsuite/20_util/bind/ref_neg.cc b/libstdc++-v3/testsuite/20_util/bind/ref_neg.cc index bae0a86..9854176 100644 --- a/libstdc++-v3/testsuite/20_util/bind/ref_neg.cc +++ b/libstdc++-v3/testsuite/20_util/bind/ref_neg.cc @@ -30,10 +30,10 @@ void test01() { const int dummy = 0; std::bind(&inc, _1)(0); // { dg-error "no match" } - // { dg-error "rvalue|const" "" { target *-*-* } 1349 } - // { dg-error "rvalue|const" "" { target *-*-* } 1363 } - // { dg-error "rvalue|const" "" { target *-*-* } 1377 } - // { dg-error "rvalue|const" "" { target *-*-* } 1391 } + // { dg-error "rvalue|const" "" { target *-*-* } 1346 } + // { dg-error "rvalue|const" "" { target *-*-* } 1360 } + // { dg-error "rvalue|const" "" { target *-*-* } 1374 } + // { dg-error "rvalue|const" "" { target *-*-* } 1388 } std::bind(&inc, std::ref(dummy))(); // { dg-error "no match" } } diff --git a/libstdc++-v3/testsuite/20_util/declval/requirements/1_neg.cc b/libstdc++-v3/testsuite/20_util/declval/requirements/1_neg.cc index 91d3553..015f39e 100644 --- a/libstdc++-v3/testsuite/20_util/declval/requirements/1_neg.cc +++ b/libstdc++-v3/testsuite/20_util/declval/requirements/1_neg.cc @@ -19,7 +19,7 @@ // with this library; see the file COPYING3. If not see // <http://www.gnu.org/licenses/>. -// { dg-error "static assertion failed" "" { target *-*-* } 1869 } +// { dg-error "static assertion failed" "" { target *-*-* } 1871 } #include <utility> diff --git a/libstdc++-v3/testsuite/20_util/default_delete/48631_neg.cc b/libstdc++-v3/testsuite/20_util/default_delete/48631_neg.cc index a9bba97..fa2e3d1 100644 --- a/libstdc++-v3/testsuite/20_util/default_delete/48631_neg.cc +++ b/libstdc++-v3/testsuite/20_util/default_delete/48631_neg.cc @@ -27,4 +27,4 @@ struct D : B { }; D d; std::default_delete<B[]> db; typedef decltype(db(&d)) type; // { dg-error "use of deleted function" } -// { dg-error "declared here" "" { target *-*-* } 87 } +// { dg-error "declared here" "" { target *-*-* } 104 } diff --git a/libstdc++-v3/testsuite/20_util/shared_ptr/cons/43820_neg.cc b/libstdc++-v3/testsuite/20_util/shared_ptr/cons/43820_neg.cc index 179932f..380861c 100644 --- a/libstdc++-v3/testsuite/20_util/shared_ptr/cons/43820_neg.cc +++ b/libstdc++-v3/testsuite/20_util/shared_ptr/cons/43820_neg.cc @@ -32,7 +32,7 @@ void test01() { X* px = 0; std::shared_ptr<X> p1(px); // { dg-error "here" } - // { dg-error "incomplete" "" { target *-*-* } 769 } + // { dg-error "incomplete" "" { target *-*-* } 771 } std::shared_ptr<X> p9(ap()); // { dg-error "here" } // { dg-error "incomplete" "" { target *-*-* } 307 } diff --git a/libstdc++-v3/testsuite/20_util/shared_ptr/cons/unique_ptr.cc b/libstdc++-v3/testsuite/20_util/shared_ptr/cons/unique_ptr.cc index cfca90d..d6a25a0 100644 --- a/libstdc++-v3/testsuite/20_util/shared_ptr/cons/unique_ptr.cc +++ b/libstdc++-v3/testsuite/20_util/shared_ptr/cons/unique_ptr.cc @@ -1,6 +1,6 @@ -// { dg-options "-std=gnu++0x" } +// { dg-options "-std=gnu++11" } -// Copyright (C) 2008, 2009 Free Software Foundation +// Copyright (C) 2008-2012 Free Software Foundation // // 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 @@ -17,14 +17,14 @@ // with this library; see the file COPYING3. If not see // <http://www.gnu.org/licenses/>. -// 20.7.12.2 Template class shared_ptr [util.smartptr.shared] +// 20.7.2.2 Class template shared_ptr [util.smartptr.shared] #include <memory> #include <testsuite_hooks.h> struct A { }; -// 20.7.12.2.1 shared_ptr constructors [util.smartptr.shared.const] +// 20.7.2.2.1 shared_ptr constructors [util.smartptr.shared.const] // Construction from unique_ptr int diff --git a/libstdc++-v3/testsuite/20_util/shared_ptr/cons/unique_ptr_array.cc b/libstdc++-v3/testsuite/20_util/shared_ptr/cons/unique_ptr_array.cc new file mode 100644 index 0000000..dc07920 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/shared_ptr/cons/unique_ptr_array.cc @@ -0,0 +1,59 @@ +// { dg-options "-std=gnu++11" } + +// Copyright (C) 2012 Free Software Foundation +// +// 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/>. + +// 20.7.2.2 Class template shared_ptr [util.smartptr.shared] + +#include <memory> +#include <testsuite_hooks.h> + +int destroyed = 0; + +struct A : std::enable_shared_from_this<A> +{ + ~A() { ++destroyed; } +}; + +// 20.7.2.2.1 shared_ptr constructors [util.smartptr.shared.const] + +// Construction from unique_ptr<A[]> +int +test01() +{ + bool test __attribute__((unused)) = true; + + std::unique_ptr<A[]> up(new A[2]); + std::shared_ptr<A> sp(std::move(up)); + VERIFY( up.get() == 0 ); + VERIFY( sp.get() != 0 ); + VERIFY( sp.use_count() == 1 ); + + VERIFY( sp->shared_from_this() != nullptr ); + + sp.reset(); + VERIFY( destroyed == 2 ); + + return 0; +} + +int +main() +{ + test01(); + return 0; +} diff --git a/libstdc++-v3/testsuite/20_util/unique_ptr/assign/48635_neg.cc b/libstdc++-v3/testsuite/20_util/unique_ptr/assign/48635_neg.cc index 3a4f9b4..624c225 100644 --- a/libstdc++-v3/testsuite/20_util/unique_ptr/assign/48635_neg.cc +++ b/libstdc++-v3/testsuite/20_util/unique_ptr/assign/48635_neg.cc @@ -41,10 +41,10 @@ void f() std::unique_ptr<int, B&> ub(nullptr, b); std::unique_ptr<int, D&> ud(nullptr, d); ub = std::move(ud); -// { dg-error "use of deleted function" "" { target *-*-* } 198 } +// { dg-error "use of deleted function" "" { target *-*-* } 206 } std::unique_ptr<int[], B&> uba(nullptr, b); std::unique_ptr<int[], D&> uda(nullptr, d); uba = std::move(uda); -// { dg-error "use of deleted function" "" { target *-*-* } 344 } +// { dg-error "use of deleted function" "" { target *-*-* } 396 } } 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 new file mode 100644 index 0000000..1b47a9f --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/unique_ptr/assign/cv_qual.cc @@ -0,0 +1,89 @@ +// { dg-options "-std=gnu++11" } +// { dg-do compile } + +// Copyright (C) 2012 Free Software Foundation +// +// 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/>. + +// 20.7.1 Class template unique_ptr [unique.ptr] + +#include <memory> + +struct A { virtual ~A() = default; }; + +struct B : A { }; + +// Assignment from objects with different cv-qualification + +void +test01() +{ + std::unique_ptr<A> upA; + + std::unique_ptr<const A> cA; + cA = std::move(upA); + std::unique_ptr<volatile A> vA; + vA = std::move(upA); + std::unique_ptr<const volatile A> cvA; + cvA = std::move(upA); +} + +void +test02() +{ + std::unique_ptr<B> upB; + + std::unique_ptr<const A> cA; + cA = std::move(upB); + std::unique_ptr<volatile A> vA; + vA = std::move(upB); + std::unique_ptr<const volatile A> cvA; + cvA = std::move(upB); +} + +void +test03() +{ + std::unique_ptr<A[]> upA; + + std::unique_ptr<const A[]> cA; + cA = std::move(upA); + std::unique_ptr<volatile A[]> vA; + vA = std::move(upA); + 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() +{ + // Allow conversions from user-defined pointer-like types + std::unique_ptr<B[], deleter<A_pointer>> p; + std::unique_ptr<A[], deleter<A*>> upA; + upA = std::move(p); +} diff --git a/libstdc++-v3/testsuite/20_util/unique_ptr/cons/array_convertible_neg.cc b/libstdc++-v3/testsuite/20_util/unique_ptr/cons/array_convertible_neg.cc new file mode 100644 index 0000000..15a1f31 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/unique_ptr/cons/array_convertible_neg.cc @@ -0,0 +1,58 @@ +// { dg-do compile } +// { dg-options "-std=gnu++11" } + +// Copyright (C) 2012 Free Software Foundation +// +// 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/>. + +#include <memory> + +struct A +{ +}; + +struct B : A +{ + virtual ~B() { } +}; + +// 20.7.1.3 unique_ptr for array objects [unique.ptr.runtime] + +struct D +{ + template<typename T> + void operator()(const T* p) const { delete[] p; } +}; + +// Conversion from different type of unique_ptr<T[], D> +void +test01() +{ + std::unique_ptr<B[], D> b(new B[1]); + std::unique_ptr<A[], D> a(std::move(b)); //{ dg-error "no matching function" } + a = std::move(b); //{ dg-error "no match" } +} + +// Conversion from non-array form of unique_ptr +void +test02() +{ + std::unique_ptr<A> nonarray(new A); + std::unique_ptr<A[]> array(std::move(nonarray)); //{ dg-error "no matching function" } + array = std::move(nonarray); //{ dg-error "no match" } +} + +// { dg-prune-output "include" } diff --git a/libstdc++-v3/testsuite/20_util/unique_ptr/cons/convertible_neg.cc b/libstdc++-v3/testsuite/20_util/unique_ptr/cons/convertible_neg.cc new file mode 100644 index 0000000..5e6591d --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/unique_ptr/cons/convertible_neg.cc @@ -0,0 +1,38 @@ +// { dg-do compile } +// { dg-options "-std=gnu++11" } + +// Copyright (C) 2012 Free Software Foundation +// +// 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/>. + +#include <memory> + +struct A +{ +}; + +// 20.7.1.3 unique_ptr for array objects [unique.ptr.runtime] + +// Conversion to non-array form of unique_ptr +void +test01() +{ + std::unique_ptr<A[]> array(new A[1]); + std::unique_ptr<A> nonarray(std::move(array)); //{ dg-error "no matching function" } + nonarray = std::move(array); //{ dg-error "no match" } +} + +// { dg-prune-output "include" } diff --git a/libstdc++-v3/testsuite/20_util/unique_ptr/cons/cv_qual.cc b/libstdc++-v3/testsuite/20_util/unique_ptr/cons/cv_qual.cc new file mode 100644 index 0000000..c1d3dad --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/unique_ptr/cons/cv_qual.cc @@ -0,0 +1,115 @@ +// { dg-options "-std=gnu++11" } +// { dg-do compile } + +// Copyright (C) 2012 Free Software Foundation +// +// 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/>. + +// 20.7.1 Class template unique_ptr [unique.ptr] + +#include <memory> + +struct A { virtual ~A() = default; }; + +struct B : A { }; + +// Construction from objects with different cv-qualification + +void +test01() +{ + std::unique_ptr<const A> cA(new A); + std::unique_ptr<volatile A> vA(new A); + std::unique_ptr<const volatile A> cvA(new A); +} + +void +test02() +{ + std::unique_ptr<const A> cB(new B); + std::unique_ptr<volatile A> vB(new B); + std::unique_ptr<const volatile A> cvB(new B); +} + +void +test03() +{ + std::unique_ptr<A> upA; + + std::unique_ptr<const A> cA(std::move(upA)); + std::unique_ptr<volatile A> vA(std::move(upA)); + std::unique_ptr<const volatile A> cvA(std::move(upA)); +} + +void +test04() +{ + std::unique_ptr<B> upB; + + std::unique_ptr<const A> cA(std::move(upB)); + std::unique_ptr<volatile A> vA(std::move(upB)); + std::unique_ptr<const volatile A> cvA(std::move(upB)); +} + +void +test05() +{ + std::unique_ptr<const A[]> cA(new A[1]); + std::unique_ptr<volatile A[]> vA(new A[1]); + std::unique_ptr<const volatile A[]> cvA(new A[1]); +} + +void +test06() +{ + std::unique_ptr<A[]> upA; + + std::unique_ptr<const A[]> cA(std::move(upA)); + std::unique_ptr<volatile A[]> vA(std::move(upA)); + std::unique_ptr<const volatile A[]> cvA(std::move(upA)); +} + +struct A_pointer { operator A*() const { return nullptr; } }; + +void +test07() +{ + // Allow conversions from user-defined pointer-like types + A_pointer p; + std::unique_ptr<A[]> upA(p); + std::unique_ptr<const A[]> cA(p); + std::unique_ptr<volatile A[]> vA(p); + std::unique_ptr<const volatile A[]> cvA(p); +} + +template<typename T> +struct deleter +{ + deleter() = default; + template<typename U> + deleter(const deleter<U>) { } + typedef T pointer; + void operator()(T) const { } +}; + +void +test08() +{ + // Allow conversions from user-defined pointer-like types + std::unique_ptr<B[], deleter<A_pointer>> p; + std::unique_ptr<A[], deleter<A*>> upA(std::move(p)); +} + diff --git a/libstdc++-v3/testsuite/20_util/unique_ptr/cons/pointer_array_convertible_neg.cc b/libstdc++-v3/testsuite/20_util/unique_ptr/cons/pointer_array_convertible_neg.cc index 2a4a89b..42f1eca 100644 --- a/libstdc++-v3/testsuite/20_util/unique_ptr/cons/pointer_array_convertible_neg.cc +++ b/libstdc++-v3/testsuite/20_util/unique_ptr/cons/pointer_array_convertible_neg.cc @@ -1,7 +1,7 @@ // { dg-do compile } -// { dg-options "-std=gnu++0x" } +// { dg-options "-std=gnu++11" } -// Copyright (C) 2008, 2009 Free Software Foundation +// Copyright (C) 2008-2012 Free Software Foundation // // 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 @@ -29,7 +29,7 @@ struct B : A virtual ~B() { } }; -// 20.4.5.1 unique_ptr constructors [unique.ptr.cons] +// 20.7.1.3.1 unique_ptr constructors [unique.ptr.runtime.ctor] // Construction from pointer of derived type void diff --git a/libstdc++-v3/testsuite/20_util/unique_ptr/cons/ptr_deleter_neg.cc b/libstdc++-v3/testsuite/20_util/unique_ptr/cons/ptr_deleter_neg.cc index 312ecbe..e2be105 100644 --- a/libstdc++-v3/testsuite/20_util/unique_ptr/cons/ptr_deleter_neg.cc +++ b/libstdc++-v3/testsuite/20_util/unique_ptr/cons/ptr_deleter_neg.cc @@ -1,7 +1,7 @@ // { dg-options "-std=gnu++0x" } // { dg-do compile } -// Copyright (C) 2010 Free Software Foundation +// Copyright (C) 2010-2012 Free Software Foundation // // 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 @@ -18,10 +18,9 @@ // with this library; see the file COPYING3. If not see // <http://www.gnu.org/licenses/>. -// 20.6.11 Template class unique_ptr [unique.ptr] +// 20.7.1 Class template unique_ptr [unique.ptr] #include <memory> -#include <testsuite_hooks.h> using std::unique_ptr; @@ -30,9 +29,9 @@ using std::unique_ptr; void test01() { - unique_ptr<int, void(*)(int*)> p1; // { dg-error "here" } + unique_ptr<long, void(*)(long*)> p1; // { dg-error "here" } - unique_ptr<int, void(*)(int*)> p2(nullptr); // { dg-error "here" } + unique_ptr<short, void(*)(short*)> p2(nullptr); // { dg-error "here" } unique_ptr<int, void(*)(int*)> p3(new int); // { dg-error "here" } } @@ -40,9 +39,9 @@ test01() void test02() { - unique_ptr<int[], void(*)(int*)> p1; // { dg-error "here" } + unique_ptr<long[], void(*)(long*)> p1; // { dg-error "here" } - unique_ptr<int[], void(*)(int*)> p2(nullptr); // { dg-error "here" } + unique_ptr<short[], void(*)(short*)> p2(nullptr); // { dg-error "here" } unique_ptr<int[], void(*)(int*)> p3(new int[1]); // { dg-error "here" } } 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 new file mode 100644 index 0000000..c5afa7e --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/unique_ptr/modifiers/cv_qual.cc @@ -0,0 +1,79 @@ +// { dg-options "-std=gnu++11" } +// { dg-do compile } + +// Copyright (C) 2012 Free Software Foundation +// +// 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/>. + +// 20.7.1 Class template unique_ptr [unique.ptr] + +#include <memory> + +struct A { virtual ~A() = default; }; + +struct B : A { }; + +// Construction from objects with different cv-qualification + +void +test01() +{ + std::unique_ptr<const A> cA; + cA.reset(new A); + std::unique_ptr<volatile A> vA; + vA.reset(new A); + std::unique_ptr<const volatile A> cvA; + cvA.reset(new A); +} + +void +test02() +{ + std::unique_ptr<const A> cB; + cB.reset(new B); + std::unique_ptr<volatile A> vB; + vB.reset(new B); + std::unique_ptr<const volatile A> cvB; + cvB.reset(new B); +} + +void +test03() +{ + std::unique_ptr<const A[]> cA; + cA.reset(new A[1]); + std::unique_ptr<volatile A[]> vA; + vA.reset(new A[1]); + std::unique_ptr<const volatile A[]> cvA; + cvA.reset(new A[1]); +} + +struct A_pointer { operator A*() const { return nullptr; } }; + +void +test07() +{ + // Allow conversions from user-defined pointer-like types + A_pointer p; + std::unique_ptr<A[]> upA; + upA.reset(p); + std::unique_ptr<const A[]> cA; + cA.reset(p); + std::unique_ptr<volatile A[]> vA; + vA.reset(p); + std::unique_ptr<const volatile A[]> cvA; + cvA.reset(p); +} 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 29bb57d..2f5e639 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 @@ -1,7 +1,7 @@ // { dg-do compile } // { dg-options "-std=gnu++0x" } -// Copyright (C) 2008, 2009, 2010 Free Software Foundation +// Copyright (C) 2008-2012 Free Software Foundation // // 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 @@ -32,7 +32,7 @@ struct B : A void test01() { std::unique_ptr<B[]> up; - up.reset(new A[3]); // { dg-error "deleted" } + up.reset(new A[3]); // { dg-error "invalid conversion" } } // { dg-prune-output "include" } diff --git a/libstdc++-v3/testsuite/20_util/unique_ptr/requirements/pointer_type.cc b/libstdc++-v3/testsuite/20_util/unique_ptr/requirements/pointer_type.cc index 55f28ca..ee2105d 100644 --- a/libstdc++-v3/testsuite/20_util/unique_ptr/requirements/pointer_type.cc +++ b/libstdc++-v3/testsuite/20_util/unique_ptr/requirements/pointer_type.cc @@ -1,7 +1,7 @@ // { dg-do compile } -// { dg-options "-std=gnu++0x" } +// { dg-options "-std=gnu++11" } -// Copyright (C) 2010, 2011 Free Software Foundation +// Copyright (C) 2010-2012 Free Software Foundation // // 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 @@ -18,10 +18,9 @@ // with this library; see the file COPYING3. If not see // <http://www.gnu.org/licenses/>. -// 20.6.11 Template class unique_ptr [unique.ptr.single] +// 20.7.1.2 unique_ptr for single objects [unique.ptr.single] #include <memory> -#include <testsuite_hooks.h> struct A { diff --git a/libstdc++-v3/testsuite/20_util/unique_ptr/requirements/pointer_type_array.cc b/libstdc++-v3/testsuite/20_util/unique_ptr/requirements/pointer_type_array.cc new file mode 100644 index 0000000..0f1a8e5 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/unique_ptr/requirements/pointer_type_array.cc @@ -0,0 +1,49 @@ +// { dg-do compile } +// { dg-options "-std=gnu++11" } + +// Copyright (C) 2010-2012 Free Software Foundation +// +// 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/>. + +// 20.7.1.3 unique_ptr for array objects [unique.ptr.runtime] + +#include <memory> + +struct A +{ + void operator()(void*) const { } +}; + +struct B +{ + typedef char* pointer; + void operator()(pointer) const { } +}; + +int main() +{ + typedef std::unique_ptr<int[]> up; + typedef std::unique_ptr<int[], A> upA; + typedef std::unique_ptr<int[], B> upB; + typedef std::unique_ptr<int[], A&> upAr; + typedef std::unique_ptr<int[], B&> upBr; + + static_assert( std::is_same< up::pointer, int*>::value, "" ); + static_assert( std::is_same< upA::pointer, int*>::value, "" ); + static_assert( std::is_same< upB::pointer, char*>::value, "" ); + static_assert( std::is_same< upAr::pointer, int*>::value, "" ); + static_assert( std::is_same< upBr::pointer, char*>::value, "" ); +}