mirror of git://gcc.gnu.org/git/gcc.git
Implement N4089 Safe conversions in unique_ptr<T[]> (LWG 2118) and N4366 LWG 2228...
2015-08-08 Ville Voutilainen <ville.voutilainen@gmail.com>
Implement N4089 Safe conversions in unique_ptr<T[]> (LWG 2118)
and N4366 LWG 2228: Missing SFINAE rule in unique_ptr
templated assignment
* include/bits/unique_ptr.h
(__remove_cv, __is_derived_Tp): Remove.
(default_delete::default_delete(const default_delete<_Up[]>)):
Constrain with array convertibility.
(default_delete::operator(_Up*)): Turn into a template,
constrain with array convertibility.
(__safe_conversion_up): New, single object version.
(unique_ptr(unique_ptr<_Up, _Ep>&&)): Constrain with deleter
convertibility.
(unique_ptr::operator=(unique_ptr<_Up, _Ep>&&)): Likewise, and add
is_assignable as a constraint.
(__safe_conversion_up): Array version, renamed from __safe_conversion,
updated to implement N4089.
(__safe_conversion_raw): New.
(unique_ptr(_Up)): Turn into a template, constrain with array
convertibility.
(unique_ptr(_Up,
typename conditional<is_reference<deleter_type>::value,
deleter_type, const deleter_type&>::type)): Likewise.
(unique_ptr(_Up, typename
remove_reference<deleter_type>::type&&)): Likewise.
(unique_ptr(unique_ptr<_Up, _Ep>&&)): Likewise.
(operator=(unique_ptr<_Up, _Ep>&&)): Likewise, and add
is_assignable as a constraint (array version).
(reset(_Up)): Turn into a template, constrain with array
convertibility.
(reset(nullptr_t)): New.
* testsuite/20_util/default_delete/48631_neg.cc: Adjust.
* testsuite/20_util/unique_ptr/assign/48635.cc: Likewise.
* testsuite/20_util/unique_ptr/assign/48635_neg.cc: Likewise.
* testsuite/20_util/unique_ptr/assign/cv_qual.cc: Likewise.
* testsuite/20_util/unique_ptr/cons/cv_qual.cc: Likewise.
* testsuite/20_util/unique_ptr/dr2228.cc: New.
* testsuite/20_util/unique_ptr/modifiers/cv_qual.cc: Adjust.
From-SVN: r226733
This commit is contained in:
parent
0d251765be
commit
f334456903
|
|
@ -1,3 +1,43 @@
|
||||||
|
2015-08-08 Ville Voutilainen <ville.voutilainen@gmail.com>
|
||||||
|
|
||||||
|
Implement N4089 Safe conversions in unique_ptr<T[]> (LWG 2118)
|
||||||
|
and N4366 LWG 2228: Missing SFINAE rule in unique_ptr
|
||||||
|
templated assignment
|
||||||
|
* include/bits/unique_ptr.h
|
||||||
|
(__remove_cv, __is_derived_Tp): Remove.
|
||||||
|
(default_delete::default_delete(const default_delete<_Up[]>)):
|
||||||
|
Constrain with array convertibility.
|
||||||
|
(default_delete::operator(_Up*)): Turn into a template,
|
||||||
|
constrain with array convertibility.
|
||||||
|
(__safe_conversion_up): New, single object version.
|
||||||
|
(unique_ptr(unique_ptr<_Up, _Ep>&&)): Constrain with deleter
|
||||||
|
convertibility.
|
||||||
|
(unique_ptr::operator=(unique_ptr<_Up, _Ep>&&)): Likewise, and add
|
||||||
|
is_assignable as a constraint.
|
||||||
|
(__safe_conversion_up): Array version, renamed from __safe_conversion,
|
||||||
|
updated to implement N4089.
|
||||||
|
(__safe_conversion_raw): New.
|
||||||
|
(unique_ptr(_Up)): Turn into a template, constrain with array
|
||||||
|
convertibility.
|
||||||
|
(unique_ptr(_Up,
|
||||||
|
typename conditional<is_reference<deleter_type>::value,
|
||||||
|
deleter_type, const deleter_type&>::type)): Likewise.
|
||||||
|
(unique_ptr(_Up, typename
|
||||||
|
remove_reference<deleter_type>::type&&)): Likewise.
|
||||||
|
(unique_ptr(unique_ptr<_Up, _Ep>&&)): Likewise.
|
||||||
|
(operator=(unique_ptr<_Up, _Ep>&&)): Likewise, and add
|
||||||
|
is_assignable as a constraint (array version).
|
||||||
|
(reset(_Up)): Turn into a template, constrain with array
|
||||||
|
convertibility.
|
||||||
|
(reset(nullptr_t)): New.
|
||||||
|
* testsuite/20_util/default_delete/48631_neg.cc: Adjust.
|
||||||
|
* testsuite/20_util/unique_ptr/assign/48635.cc: Likewise.
|
||||||
|
* testsuite/20_util/unique_ptr/assign/48635_neg.cc: Likewise.
|
||||||
|
* testsuite/20_util/unique_ptr/assign/cv_qual.cc: Likewise.
|
||||||
|
* testsuite/20_util/unique_ptr/cons/cv_qual.cc: Likewise.
|
||||||
|
* testsuite/20_util/unique_ptr/dr2228.cc: New.
|
||||||
|
* testsuite/20_util/unique_ptr/modifiers/cv_qual.cc: Adjust.
|
||||||
|
|
||||||
2015-08-05 Nikolai Bozhenov <n.bozhenov@samsung.com>
|
2015-08-05 Nikolai Bozhenov <n.bozhenov@samsung.com>
|
||||||
|
|
||||||
* testsuite/20_util/enable_shared_from_this/cons/constexpr.cc: Remove
|
* testsuite/20_util/enable_shared_from_this/cons/constexpr.cc: Remove
|
||||||
|
|
|
||||||
|
|
@ -83,16 +83,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
template<typename _Tp>
|
template<typename _Tp>
|
||||||
struct default_delete<_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:
|
public:
|
||||||
/// Default constructor
|
/// Default constructor
|
||||||
constexpr default_delete() noexcept = default;
|
constexpr default_delete() noexcept = default;
|
||||||
|
|
@ -107,21 +97,18 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
* pointer to the base type.
|
* pointer to the base type.
|
||||||
*/
|
*/
|
||||||
template<typename _Up, typename = typename
|
template<typename _Up, typename = typename
|
||||||
enable_if<!__is_derived_Tp<_Up>::value>::type>
|
enable_if<is_convertible<_Up(*)[], _Tp(*)[]>::value>::type>
|
||||||
default_delete(const default_delete<_Up[]>&) noexcept { }
|
default_delete(const default_delete<_Up[]>&) noexcept { }
|
||||||
|
|
||||||
/// Calls @c delete[] @p __ptr
|
/// Calls @c delete[] @p __ptr
|
||||||
void
|
template<typename _Up>
|
||||||
operator()(_Tp* __ptr) const
|
typename enable_if<is_convertible<_Up(*)[], _Tp(*)[]>::value>::type
|
||||||
|
operator()(_Up* __ptr) const
|
||||||
{
|
{
|
||||||
static_assert(sizeof(_Tp)>0,
|
static_assert(sizeof(_Tp)>0,
|
||||||
"can't delete pointer to incomplete type");
|
"can't delete pointer to incomplete type");
|
||||||
delete [] __ptr;
|
delete [] __ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
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.
|
/// 20.7.1.2 unique_ptr for single objects.
|
||||||
|
|
@ -151,6 +138,20 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
typedef _Tp element_type;
|
typedef _Tp element_type;
|
||||||
typedef _Dp deleter_type;
|
typedef _Dp deleter_type;
|
||||||
|
|
||||||
|
|
||||||
|
// helper template for detecting a safe conversion from another
|
||||||
|
// unique_ptr
|
||||||
|
template<typename _Up, typename _Ep>
|
||||||
|
using __safe_conversion_up = __and_<
|
||||||
|
is_convertible<typename unique_ptr<_Up, _Ep>::pointer, pointer>,
|
||||||
|
__not_<is_array<_Up>>,
|
||||||
|
__or_<__and_<is_reference<deleter_type>,
|
||||||
|
is_same<deleter_type, _Ep>>,
|
||||||
|
__and_<__not_<is_reference<deleter_type>>,
|
||||||
|
is_convertible<_Ep, deleter_type>>
|
||||||
|
>
|
||||||
|
>;
|
||||||
|
|
||||||
// Constructors.
|
// Constructors.
|
||||||
|
|
||||||
/// Default constructor, creates a unique_ptr that owns nothing.
|
/// Default constructor, creates a unique_ptr that owns nothing.
|
||||||
|
|
@ -212,8 +213,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
* and @p __u has a compatible deleter type.
|
* and @p __u has a compatible deleter type.
|
||||||
*/
|
*/
|
||||||
template<typename _Up, typename _Ep, typename = _Require<
|
template<typename _Up, typename _Ep, typename = _Require<
|
||||||
is_convertible<typename unique_ptr<_Up, _Ep>::pointer, pointer>,
|
__safe_conversion_up<_Up, _Ep>,
|
||||||
__not_<is_array<_Up>>,
|
|
||||||
typename conditional<is_reference<_Dp>::value,
|
typename conditional<is_reference<_Dp>::value,
|
||||||
is_same<_Ep, _Dp>,
|
is_same<_Ep, _Dp>,
|
||||||
is_convertible<_Ep, _Dp>>::type>>
|
is_convertible<_Ep, _Dp>>::type>>
|
||||||
|
|
@ -262,8 +262,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
*/
|
*/
|
||||||
template<typename _Up, typename _Ep>
|
template<typename _Up, typename _Ep>
|
||||||
typename enable_if< __and_<
|
typename enable_if< __and_<
|
||||||
is_convertible<typename unique_ptr<_Up, _Ep>::pointer, pointer>,
|
__safe_conversion_up<_Up, _Ep>,
|
||||||
__not_<is_array<_Up>>
|
is_assignable<deleter_type&, _Ep&&>
|
||||||
>::value,
|
>::value,
|
||||||
unique_ptr&>::type
|
unique_ptr&>::type
|
||||||
operator=(unique_ptr<_Up, _Ep>&& __u) noexcept
|
operator=(unique_ptr<_Up, _Ep>&& __u) noexcept
|
||||||
|
|
@ -391,23 +391,41 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
= __and_< is_base_of<_Tp, _Up>,
|
= __and_< is_base_of<_Tp, _Up>,
|
||||||
__not_<is_same<__remove_cv<_Tp>, __remove_cv<_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:
|
public:
|
||||||
typedef typename _Pointer::type pointer;
|
typedef typename _Pointer::type pointer;
|
||||||
typedef _Tp element_type;
|
typedef _Tp element_type;
|
||||||
typedef _Dp deleter_type;
|
typedef _Dp deleter_type;
|
||||||
|
|
||||||
|
// helper template for detecting a safe conversion from another
|
||||||
|
// unique_ptr
|
||||||
|
template<typename _Up, typename _Ep,
|
||||||
|
typename _Up_up = unique_ptr<_Up, _Ep>,
|
||||||
|
typename _Up_element_type = typename _Up_up::element_type>
|
||||||
|
using __safe_conversion_up = __and_<
|
||||||
|
is_array<_Up>,
|
||||||
|
is_same<pointer, element_type*>,
|
||||||
|
is_same<typename _Up_up::pointer, _Up_element_type*>,
|
||||||
|
is_convertible<_Up_element_type(*)[], element_type(*)[]>,
|
||||||
|
__or_<__and_<is_reference<deleter_type>, is_same<deleter_type, _Ep>>,
|
||||||
|
__and_<__not_<is_reference<deleter_type>>,
|
||||||
|
is_convertible<_Ep, deleter_type>>>
|
||||||
|
>;
|
||||||
|
|
||||||
|
// helper template for detecting a safe conversion from a raw pointer
|
||||||
|
template<typename _Up>
|
||||||
|
using __safe_conversion_raw = __and_<
|
||||||
|
__or_<__or_<is_same<_Up, pointer>,
|
||||||
|
is_same<_Up, nullptr_t>>,
|
||||||
|
__and_<is_pointer<_Up>,
|
||||||
|
is_same<pointer, element_type*>,
|
||||||
|
is_convertible<
|
||||||
|
typename remove_pointer<_Up>::type(*)[],
|
||||||
|
element_type(*)[]>
|
||||||
|
>
|
||||||
|
>
|
||||||
|
>;
|
||||||
|
|
||||||
// Constructors.
|
// Constructors.
|
||||||
|
|
||||||
/// Default constructor, creates a unique_ptr that owns nothing.
|
/// Default constructor, creates a unique_ptr that owns nothing.
|
||||||
|
|
@ -418,42 +436,48 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
|
|
||||||
/** Takes ownership of a pointer.
|
/** Takes ownership of a pointer.
|
||||||
*
|
*
|
||||||
* @param __p A pointer to an array of @c element_type
|
* @param __p A pointer to an array of a type safely convertible
|
||||||
|
* to an array of @c element_type
|
||||||
*
|
*
|
||||||
* The deleter will be value-initialized.
|
* The deleter will be value-initialized.
|
||||||
*/
|
*/
|
||||||
|
template<typename _Up,
|
||||||
|
typename = typename enable_if<
|
||||||
|
__safe_conversion_raw<_Up>::value, bool>::type>
|
||||||
explicit
|
explicit
|
||||||
unique_ptr(pointer __p) noexcept
|
unique_ptr(_Up __p) noexcept
|
||||||
: _M_t(__p, deleter_type())
|
: _M_t(__p, deleter_type())
|
||||||
{ static_assert(!is_pointer<deleter_type>::value,
|
{ static_assert(!is_pointer<deleter_type>::value,
|
||||||
"constructed with null function pointer deleter"); }
|
"constructed with null function pointer deleter"); }
|
||||||
|
|
||||||
// Disable construction from convertible pointer types.
|
|
||||||
template<typename _Up, typename = _Require<is_pointer<pointer>,
|
|
||||||
is_convertible<_Up*, pointer>, __is_derived_Tp<_Up>>>
|
|
||||||
explicit
|
|
||||||
unique_ptr(_Up* __p) = delete;
|
|
||||||
|
|
||||||
/** Takes ownership of a pointer.
|
/** Takes ownership of a pointer.
|
||||||
*
|
*
|
||||||
* @param __p A pointer to an array of @c element_type
|
* @param __p A pointer to an array of a type safely convertible
|
||||||
|
* to an array of @c element_type
|
||||||
* @param __d A reference to a deleter.
|
* @param __d A reference to a deleter.
|
||||||
*
|
*
|
||||||
* The deleter will be initialized with @p __d
|
* The deleter will be initialized with @p __d
|
||||||
*/
|
*/
|
||||||
unique_ptr(pointer __p,
|
template<typename _Up,
|
||||||
|
typename = typename enable_if<
|
||||||
|
__safe_conversion_raw<_Up>::value, bool>::type>
|
||||||
|
unique_ptr(_Up __p,
|
||||||
typename conditional<is_reference<deleter_type>::value,
|
typename conditional<is_reference<deleter_type>::value,
|
||||||
deleter_type, const deleter_type&>::type __d) noexcept
|
deleter_type, const deleter_type&>::type __d) noexcept
|
||||||
: _M_t(__p, __d) { }
|
: _M_t(__p, __d) { }
|
||||||
|
|
||||||
/** Takes ownership of a pointer.
|
/** Takes ownership of a pointer.
|
||||||
*
|
*
|
||||||
* @param __p A pointer to an array of @c element_type
|
* @param __p A pointer to an array of a type safely convertible
|
||||||
|
* to an array of @c element_type
|
||||||
* @param __d A reference to a deleter.
|
* @param __d A reference to a deleter.
|
||||||
*
|
*
|
||||||
* The deleter will be initialized with @p std::move(__d)
|
* The deleter will be initialized with @p std::move(__d)
|
||||||
*/
|
*/
|
||||||
unique_ptr(pointer __p, typename
|
template<typename _Up,
|
||||||
|
typename = typename enable_if<
|
||||||
|
__safe_conversion_raw<_Up>::value, bool>::type>
|
||||||
|
unique_ptr(_Up __p, typename
|
||||||
remove_reference<deleter_type>::type&& __d) noexcept
|
remove_reference<deleter_type>::type&& __d) noexcept
|
||||||
: _M_t(std::move(__p), std::move(__d))
|
: _M_t(std::move(__p), std::move(__d))
|
||||||
{ static_assert(!is_reference<deleter_type>::value,
|
{ static_assert(!is_reference<deleter_type>::value,
|
||||||
|
|
@ -467,11 +491,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
constexpr unique_ptr(nullptr_t) noexcept : unique_ptr() { }
|
constexpr unique_ptr(nullptr_t) noexcept : unique_ptr() { }
|
||||||
|
|
||||||
template<typename _Up, typename _Ep,
|
template<typename _Up, typename _Ep,
|
||||||
typename = _Require<__safe_conversion<_Up, _Ep>,
|
typename = _Require<__safe_conversion_up<_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
|
unique_ptr(unique_ptr<_Up, _Ep>&& __u) noexcept
|
||||||
: _M_t(__u.release(), std::forward<_Ep>(__u.get_deleter()))
|
: _M_t(__u.release(), std::forward<_Ep>(__u.get_deleter()))
|
||||||
{ }
|
{ }
|
||||||
|
|
@ -510,7 +530,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
*/
|
*/
|
||||||
template<typename _Up, typename _Ep>
|
template<typename _Up, typename _Ep>
|
||||||
typename
|
typename
|
||||||
enable_if<__safe_conversion<_Up, _Ep>::value, unique_ptr&>::type
|
enable_if<__and_<__safe_conversion_up<_Up, _Ep>,
|
||||||
|
is_assignable<deleter_type&, _Ep&&>
|
||||||
|
>::value,
|
||||||
|
unique_ptr&>::type
|
||||||
operator=(unique_ptr<_Up, _Ep>&& __u) noexcept
|
operator=(unique_ptr<_Up, _Ep>&& __u) noexcept
|
||||||
{
|
{
|
||||||
reset(__u.release());
|
reset(__u.release());
|
||||||
|
|
@ -572,8 +595,20 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
*
|
*
|
||||||
* The deleter will be invoked if a pointer is already owned.
|
* The deleter will be invoked if a pointer is already owned.
|
||||||
*/
|
*/
|
||||||
|
template <typename _Up,
|
||||||
|
typename = _Require<
|
||||||
|
__or_<is_same<_Up, pointer>,
|
||||||
|
__and_<is_same<pointer, element_type*>,
|
||||||
|
is_pointer<_Up>,
|
||||||
|
is_convertible<
|
||||||
|
typename remove_pointer<_Up>::type(*)[],
|
||||||
|
element_type(*)[]
|
||||||
|
>
|
||||||
|
>
|
||||||
|
>
|
||||||
|
>>
|
||||||
void
|
void
|
||||||
reset(pointer __p = pointer()) noexcept
|
reset(_Up __p) noexcept
|
||||||
{
|
{
|
||||||
using std::swap;
|
using std::swap;
|
||||||
swap(std::get<0>(_M_t), __p);
|
swap(std::get<0>(_M_t), __p);
|
||||||
|
|
@ -581,10 +616,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
get_deleter()(__p);
|
get_deleter()(__p);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Disable resetting from convertible pointer types.
|
void reset(nullptr_t = nullptr) noexcept
|
||||||
template<typename _Up, typename = _Require<is_pointer<pointer>,
|
{
|
||||||
is_convertible<_Up*, pointer>, __is_derived_Tp<_Up>>>
|
reset(pointer());
|
||||||
void reset(_Up*) = delete;
|
}
|
||||||
|
|
||||||
/// Exchange the pointer and deleter with another object.
|
/// Exchange the pointer and deleter with another object.
|
||||||
void
|
void
|
||||||
|
|
@ -597,19 +632,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
// Disable copy from lvalue.
|
// Disable copy from lvalue.
|
||||||
unique_ptr(const unique_ptr&) = delete;
|
unique_ptr(const unique_ptr&) = delete;
|
||||||
unique_ptr& operator=(const unique_ptr&) = delete;
|
unique_ptr& operator=(const unique_ptr&) = delete;
|
||||||
|
|
||||||
// Disable construction from convertible pointer types.
|
|
||||||
template<typename _Up, typename = _Require<is_pointer<pointer>,
|
|
||||||
is_convertible<_Up*, pointer>, __is_derived_Tp<_Up>>>
|
|
||||||
unique_ptr(_Up*, typename
|
|
||||||
conditional<is_reference<deleter_type>::value,
|
|
||||||
deleter_type, const deleter_type&>::type) = delete;
|
|
||||||
|
|
||||||
// Disable construction from convertible pointer types.
|
|
||||||
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>
|
template<typename _Tp, typename _Dp>
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,5 @@ struct D : B { };
|
||||||
// libstdc++/48631
|
// libstdc++/48631
|
||||||
D d;
|
D d;
|
||||||
std::default_delete<B[]> db;
|
std::default_delete<B[]> db;
|
||||||
typedef decltype(db(&d)) type; // { dg-error "use of deleted function" }
|
typedef decltype(db(&d)) type; // { dg-error "no match" }
|
||||||
// { dg-prune-output "declared" }
|
// { dg-error "no type" "" { target *-*-* } 106 }
|
||||||
// { dg-prune-output "invalid" }
|
|
||||||
|
|
|
||||||
|
|
@ -59,16 +59,8 @@ void test01()
|
||||||
|
|
||||||
DDeleter dd;
|
DDeleter dd;
|
||||||
|
|
||||||
std::unique_ptr<int, DDeleter&> p1t(nullptr, dd);
|
|
||||||
std::unique_ptr<int, Deleter&> p2t(nullptr, d);
|
|
||||||
p2t = std::move(p1t);
|
|
||||||
|
|
||||||
std::unique_ptr<int[], Deleter&> p1a(nullptr, d), p2a(nullptr, d);
|
std::unique_ptr<int[], Deleter&> p1a(nullptr, d), p2a(nullptr, d);
|
||||||
p2a = std::move(p1a);
|
p2a = std::move(p1a);
|
||||||
|
|
||||||
std::unique_ptr<int[], DDeleter&> p1at(nullptr, dd);
|
|
||||||
std::unique_ptr<int[], Deleter&> p2at(nullptr, d);
|
|
||||||
p2at = std::move(p1at);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ struct D;
|
||||||
|
|
||||||
struct B
|
struct B
|
||||||
{
|
{
|
||||||
B& operator=(D&) = delete; // { dg-error "declared here" }
|
B& operator=(D&) = delete;
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
void operator()(T*) const {}
|
void operator()(T*) const {}
|
||||||
|
|
@ -39,12 +39,14 @@ void f()
|
||||||
D d;
|
D d;
|
||||||
|
|
||||||
std::unique_ptr<int, B&> ub(nullptr, b);
|
std::unique_ptr<int, B&> ub(nullptr, b);
|
||||||
|
std::unique_ptr<int, B> ub2(nullptr, b);
|
||||||
std::unique_ptr<int, D&> ud(nullptr, d);
|
std::unique_ptr<int, D&> ud(nullptr, d);
|
||||||
ub = std::move(ud);
|
ub = std::move(ud); // { dg-error "no match" }
|
||||||
// { dg-error "use of deleted function" "" { target *-*-* } 272 }
|
ub2 = ud; // { dg-error "no match" }
|
||||||
|
// { dg-error "no type" "" { target *-*-* } 269 }
|
||||||
|
|
||||||
std::unique_ptr<int[], B&> uba(nullptr, b);
|
std::unique_ptr<int[], B&> uba(nullptr, b);
|
||||||
std::unique_ptr<int[], D&> uda(nullptr, d);
|
std::unique_ptr<int[], D&> uda(nullptr, d);
|
||||||
uba = std::move(uda);
|
uba = std::move(uda); // { dg-error "no match" }
|
||||||
// { dg-error "use of deleted function" "" { target *-*-* } 517 }
|
// { dg-error "no type" "" { target *-*-* } 537 }
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -82,8 +82,10 @@ struct deleter
|
||||||
void
|
void
|
||||||
test04()
|
test04()
|
||||||
{
|
{
|
||||||
// Allow conversions from user-defined pointer-like types
|
// Disallow conversions from incompatible deleter
|
||||||
std::unique_ptr<B[], deleter<A_pointer>> p;
|
std::unique_ptr<B[], deleter<A_pointer>> p;
|
||||||
std::unique_ptr<A[], deleter<A*>> upA;
|
std::unique_ptr<A[], deleter<A*>> upA;
|
||||||
upA = std::move(p);
|
upA = std::move(p); // { dg-error "no match" }
|
||||||
|
// { dg-error "no type" "" { target *-*-* } 537 }
|
||||||
|
// { dg-error "no matching function" "" { target *-*-* } 614 }
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -88,11 +88,25 @@ void
|
||||||
test07()
|
test07()
|
||||||
{
|
{
|
||||||
// Allow conversions from user-defined pointer-like types
|
// Allow conversions from user-defined pointer-like types
|
||||||
|
// for the single-object version
|
||||||
A_pointer p;
|
A_pointer p;
|
||||||
std::unique_ptr<A[]> upA(p);
|
std::unique_ptr<A> upA(p);
|
||||||
std::unique_ptr<const A[]> cA(p);
|
std::unique_ptr<const A> cA(p);
|
||||||
std::unique_ptr<volatile A[]> vA(p);
|
std::unique_ptr<volatile A> vA(p);
|
||||||
std::unique_ptr<const volatile A[]> cvA(p);
|
std::unique_ptr<const volatile A> cvA(p);
|
||||||
|
// Allow conversions from user-defined pointer-like types
|
||||||
|
// for the array version when the type is converted explicitly
|
||||||
|
std::unique_ptr<A[]> upA2((A*)p);
|
||||||
|
std::unique_ptr<const A[]> cA2((A*)p);
|
||||||
|
std::unique_ptr<volatile A[]> vA2((A*)p);
|
||||||
|
std::unique_ptr<const volatile A[]> cvA2((A*)p);
|
||||||
|
// Disallow conversions from user-defined pointer-like types
|
||||||
|
// for the array version
|
||||||
|
std::unique_ptr<A[]> upA3(p); // { dg-error "no matching function" }
|
||||||
|
std::unique_ptr<const A[]> cA3(p); // { dg-error "no matching function" }
|
||||||
|
std::unique_ptr<volatile A[]> vA3(p); // { dg-error "no matching function" }
|
||||||
|
std::unique_ptr<const volatile A[]> cvA3(p); // { dg-error "no matching function" }
|
||||||
|
// { dg-error "no type" "" { target *-*-* } 445 }
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
|
|
@ -108,8 +122,8 @@ struct deleter
|
||||||
void
|
void
|
||||||
test08()
|
test08()
|
||||||
{
|
{
|
||||||
// Allow conversions from user-defined pointer-like types
|
// Disallow conversions from non-assignable deleter
|
||||||
std::unique_ptr<B[], deleter<A_pointer>> p;
|
std::unique_ptr<B[], deleter<A_pointer>> p;
|
||||||
std::unique_ptr<A[], deleter<A*>> upA(std::move(p));
|
std::unique_ptr<A[], deleter<A*>> upA(std::move(p)); // { dg-error "no matching function" }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,38 @@
|
||||||
|
// { dg-options "-std=gnu++11" }
|
||||||
|
// { dg-do compile }
|
||||||
|
|
||||||
|
// Copyright (C) 2015 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/>.
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
|
struct do_nothing
|
||||||
|
{
|
||||||
|
template <class T>
|
||||||
|
void operator()(T*) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
int
|
||||||
|
main()
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
std::unique_ptr<int, do_nothing> p1(&i);
|
||||||
|
std::unique_ptr<int> p2;
|
||||||
|
static_assert(!std::is_assignable<decltype(p2), decltype(p1)>::value, "");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -66,14 +66,36 @@ struct A_pointer { operator A*() const { return nullptr; } };
|
||||||
void
|
void
|
||||||
test07()
|
test07()
|
||||||
{
|
{
|
||||||
// Allow conversions from user-defined pointer-like types
|
|
||||||
A_pointer p;
|
A_pointer p;
|
||||||
std::unique_ptr<A[]> upA;
|
// Allow conversions from user-defined pointer-like types
|
||||||
|
// for the single-object version
|
||||||
|
std::unique_ptr<A> upA;
|
||||||
upA.reset(p);
|
upA.reset(p);
|
||||||
std::unique_ptr<const A[]> cA;
|
std::unique_ptr<const A> cA;
|
||||||
cA.reset(p);
|
cA.reset(p);
|
||||||
std::unique_ptr<volatile A[]> vA;
|
std::unique_ptr<volatile A> vA;
|
||||||
vA.reset(p);
|
vA.reset(p);
|
||||||
std::unique_ptr<const volatile A[]> cvA;
|
std::unique_ptr<const volatile A> cvA;
|
||||||
cvA.reset(p);
|
cvA.reset(p);
|
||||||
|
// Allow conversions from user-defined pointer-like types
|
||||||
|
// for the array version when the type is converted explicitly
|
||||||
|
std::unique_ptr<A[]> upA2;
|
||||||
|
upA2.reset((A*)p);
|
||||||
|
std::unique_ptr<const A[]> cA2;
|
||||||
|
cA2.reset((A*)p);
|
||||||
|
std::unique_ptr<volatile A[]> vA2;
|
||||||
|
vA2.reset((A*)p);
|
||||||
|
std::unique_ptr<const volatile A[]> cvA2;
|
||||||
|
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 }
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue