tuple (tuple<>::operator=(tuple&&)): Specify as noexcept.

2011-05-19  Paolo Carlini  <paolo.carlini@oracle.com>

	* include/std/tuple (tuple<>::operator=(tuple&&)): Specify as
        noexcept.
	(__get_helper): Likewise.
	(_Head_base<>::_M_head, _Tuple_impl<>::_M_head, _M_tail): Likewise.
	* include/bits/move.h (swap): Likewise.
	* include/bits/algorithmfwd.h (swap): Adjust.
	* include/bits/stl_pair.h (pair<>::operator=(pair&&)): Spec noexcept.
	* testsuite/util/testsuite_allocator.h (uneq_allocator): In C++0x
	mode, prefer delete to access control to make the type not copy
	assignable.
	* testsuite/util/testsuite_tr1.h: Add test classes.
	* testsuite/20_util/tuple/noexcept_swap.cc: New.
	* testsuite/20_util/tuple/noexcept_move_assign.cc: Likewise.
	* testsuite/25_algorithms/reverse/moveable.cc: Likewise, prefer
	delete to access control.
	* testsuite/25_algorithms/swap_ranges/moveable.cc: Likewise.
	* testsuite/20_util/weak_ptr/comparison/cmp_neg.cc: Adjust dg-warning
	line numbers.

From-SVN: r173917
This commit is contained in:
Paolo Carlini 2011-05-19 17:20:22 +00:00 committed by Paolo Carlini
parent 12d844c830
commit 173f26ae56
12 changed files with 282 additions and 28 deletions

View File

@ -1,3 +1,24 @@
2011-05-19 Paolo Carlini <paolo.carlini@oracle.com>
* include/std/tuple (tuple<>::operator=(tuple&&)): Specify as
noexcept.
(__get_helper): Likewise.
(_Head_base<>::_M_head, _Tuple_impl<>::_M_head, _M_tail): Likewise.
* include/bits/move.h (swap): Likewise.
* include/bits/algorithmfwd.h (swap): Adjust.
* include/bits/stl_pair.h (pair<>::operator=(pair&&)): Spec noexcept.
* testsuite/util/testsuite_allocator.h (uneq_allocator): In C++0x
mode, prefer delete to access control to make the type not copy
assignable.
* testsuite/util/testsuite_tr1.h: Add test classes.
* testsuite/20_util/tuple/noexcept_swap.cc: New.
* testsuite/20_util/tuple/noexcept_move_assign.cc: Likewise.
* testsuite/25_algorithms/reverse/moveable.cc: Likewise, prefer
delete to access control.
* testsuite/25_algorithms/swap_ranges/moveable.cc: Likewise.
* testsuite/20_util/weak_ptr/comparison/cmp_neg.cc: Adjust dg-warning
line numbers.
2011-05-19 Daniel Krugler <daniel.kruegler@googlemail.com>
* testsuite/util/testsuite_tr1.h: Add test classes.

View File

@ -549,7 +549,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _Tp>
void
swap(_Tp&, _Tp&);
swap(_Tp&, _Tp&)
#ifdef __GXX_EXPERIMENTAL_CXX0X__
noexcept(is_nothrow_move_constructible<_Tp>::value
&& is_nothrow_move_assignable<_Tp>::value)
#endif
;
template<typename _Tp, size_t _Nm>
void

View File

@ -135,7 +135,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _Tp>
inline void
swap(_Tp& __a, _Tp& __b)
// noexcept has to wait is_nothrow_move_assignable
#ifdef __GXX_EXPERIMENTAL_CXX0X__
noexcept(is_nothrow_move_constructible<_Tp>::value
&& is_nothrow_move_assignable<_Tp>::value)
#endif
{
// concept requirements
__glibcxx_function_requires(_SGIAssignableConcept<_Tp>)

View File

@ -153,7 +153,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
pair&
operator=(pair&& __p)
// noexcept has to wait is_nothrow_move_assignable
noexcept(is_nothrow_move_assignable<_T1>::value
&& is_nothrow_move_assignable<_T2>::value)
{
first = std::move(__p.first);
second = std::move(__p.second);

View File

@ -85,8 +85,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_Head_base(_UHead&& __h)
: _Head(std::forward<_UHead>(__h)) { }
_Head& _M_head() { return *this; }
const _Head& _M_head() const { return *this; }
_Head& _M_head() noexcept { return *this; }
const _Head& _M_head() const noexcept { return *this; }
};
template<std::size_t _Idx, typename _Head>
@ -102,8 +102,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_Head_base(_UHead&& __h)
: _M_head_impl(std::forward<_UHead>(__h)) { }
_Head& _M_head() { return _M_head_impl; }
const _Head& _M_head() const { return _M_head_impl; }
_Head& _M_head() noexcept { return _M_head_impl; }
const _Head& _M_head() const noexcept { return _M_head_impl; }
_Head _M_head_impl;
};
@ -147,11 +147,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
typedef _Tuple_impl<_Idx + 1, _Tail...> _Inherited;
typedef _Head_base<_Idx, _Head, std::is_empty<_Head>::value> _Base;
_Head& _M_head() { return _Base::_M_head(); }
const _Head& _M_head() const { return _Base::_M_head(); }
_Head& _M_head() noexcept { return _Base::_M_head(); }
const _Head& _M_head() const noexcept { return _Base::_M_head(); }
_Inherited& _M_tail() { return *this; }
const _Inherited& _M_tail() const { return *this; }
_Inherited& _M_tail() noexcept { return *this; }
const _Inherited& _M_tail() const noexcept { return *this; }
constexpr _Tuple_impl()
: _Inherited(), _Base() { }
@ -191,6 +191,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_Tuple_impl&
operator=(_Tuple_impl&& __in)
noexcept(is_nothrow_move_assignable<_Head>::value
&& is_nothrow_move_assignable<_Inherited>::value)
{
_M_head() = std::forward<_Head>(__in._M_head());
_M_tail() = std::move(__in._M_tail());
@ -276,6 +278,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
tuple&
operator=(tuple&& __in)
noexcept(is_nothrow_move_assignable<_Inherited>::value)
{
static_cast<_Inherited&>(*this) = std::move(__in);
return *this;
@ -364,7 +367,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
tuple&
operator=(tuple&& __in)
// noexcept has to wait is_nothrow_move_assignable
noexcept(is_nothrow_move_assignable<_Inherited>::value)
{
static_cast<_Inherited&>(*this) = std::move(__in);
return *this;
@ -397,7 +400,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _U1, typename _U2>
tuple&
operator=(pair<_U1, _U2>&& __in) noexcept
operator=(pair<_U1, _U2>&& __in)
{
this->_M_head() = std::forward<_U1>(__in.first);
this->_M_tail()._M_head() = std::forward<_U2>(__in.second);
@ -452,6 +455,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
tuple&
operator=(tuple&& __in)
noexcept(is_nothrow_move_assignable<_Inherited>::value)
{
static_cast<_Inherited&>(*this) = std::move(__in);
return *this;
@ -517,12 +521,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<std::size_t __i, typename _Head, typename... _Tail>
inline typename __add_ref<_Head>::type
__get_helper(_Tuple_impl<__i, _Head, _Tail...>& __t)
__get_helper(_Tuple_impl<__i, _Head, _Tail...>& __t) noexcept
{ return __t._M_head(); }
template<std::size_t __i, typename _Head, typename... _Tail>
inline typename __add_c_ref<_Head>::type
__get_helper(const _Tuple_impl<__i, _Head, _Tail...>& __t)
__get_helper(const _Tuple_impl<__i, _Head, _Tail...>& __t) noexcept
{ return __t._M_head(); }
// Return a reference (const reference, rvalue reference) to the ith element

View File

@ -0,0 +1,59 @@
// { dg-do compile }
// { dg-options "-std=gnu++0x" }
// 2011-05-19 Paolo Carlini <paolo.carlini@oracle.com>
//
// Copyright (C) 2011 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 <tuple>
#include <testsuite_tr1.h>
using namespace __gnu_test;
typedef std::tuple<int> tt1;
typedef std::tuple<int, double> tt2;
typedef std::tuple<short, double, int> tt3;
typedef std::tuple<short, NoexceptMoveAssignClass, double> tt4;
typedef std::tuple<NoexceptMoveAssignClass,
NoexceptMoveAssignClass, double> tt5;
typedef std::tuple<NoexceptMoveAssignClass,
NoexceptMoveAssignClass,
NoexceptMoveAssignClass> tt6;
typedef std::tuple<ExceptMoveAssignClass> tt7;
typedef std::tuple<ExceptMoveAssignClass, double> tt8;
typedef std::tuple<short, double, ExceptMoveAssignClass> tt9;
typedef std::tuple<ExceptMoveAssignClass, double,
ExceptMoveAssignClass> tt10;
typedef std::tuple<NoexceptMoveAssignClass,
ExceptMoveAssignClass> tt11;
typedef std::tuple<int,
NoexceptMoveAssignClass,
ExceptMoveAssignClass> tt12;
static_assert(std::is_nothrow_move_assignable<tt1>::value, "Error");
static_assert(std::is_nothrow_move_assignable<tt2>::value, "Error");
static_assert(std::is_nothrow_move_assignable<tt3>::value, "Error");
static_assert(std::is_nothrow_move_assignable<tt4>::value, "Error");
static_assert(std::is_nothrow_move_assignable<tt5>::value, "Error");
static_assert(std::is_nothrow_move_assignable<tt6>::value, "Error");
static_assert(!std::is_nothrow_move_assignable<tt7>::value, "Error");
static_assert(!std::is_nothrow_move_assignable<tt8>::value, "Error");
static_assert(!std::is_nothrow_move_assignable<tt9>::value, "Error");
static_assert(!std::is_nothrow_move_assignable<tt10>::value, "Error");
static_assert(!std::is_nothrow_move_assignable<tt11>::value, "Error");
static_assert(!std::is_nothrow_move_assignable<tt12>::value, "Error");

View File

@ -0,0 +1,116 @@
// { dg-do compile }
// { dg-options "-std=gnu++0x" }
// 2011-05-19 Paolo Carlini <paolo.carlini@oracle.com>
//
// Copyright (C) 2011 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 <tuple>
#include <testsuite_tr1.h>
using namespace __gnu_test;
typedef std::tuple<int> tt1;
typedef std::tuple<int, double> tt2;
typedef std::tuple<short, double, int> tt3;
typedef std::tuple<short, NoexceptMoveAssignClass, double> tt4;
typedef std::tuple<ExceptMoveAssignClass> tt5;
typedef std::tuple<ExceptMoveAssignClass, double> tt6;
typedef std::tuple<short, double, ExceptMoveAssignClass> tt7;
typedef std::tuple<ExceptMoveConsClass> tt8;
typedef std::tuple<int, ExceptMoveConsClass> tt9;
typedef std::tuple<ExceptMoveConsClass, short, double> tt10;
typedef std::tuple<short, NoexceptMoveConsClass, double> tt11;
typedef std::tuple<NoexceptMoveConsClass> tt12;
typedef std::tuple<NoexceptMoveConsNoexceptMoveAssignClass> tt13;
typedef std::tuple<ExceptMoveConsNoexceptMoveAssignClass> tt14;
typedef std::tuple<NoexceptMoveConsExceptMoveAssignClass> tt15;
typedef std::tuple<ExceptMoveConsExceptMoveAssignClass> tt16;
typedef std::tuple<NoexceptMoveConsNoexceptMoveAssignClass,
double> tt17;
typedef std::tuple<double,
NoexceptMoveConsNoexceptMoveAssignClass,
short> tt18;
typedef std::tuple<NoexceptMoveConsNoexceptMoveAssignClass,
NoexceptMoveConsNoexceptMoveAssignClass,
char> tt19;
typedef std::tuple<NoexceptMoveConsNoexceptMoveAssignClass,
NoexceptMoveConsNoexceptMoveAssignClass,
NoexceptMoveConsNoexceptMoveAssignClass> tt20;
typedef std::tuple<NoexceptMoveConsNoexceptMoveAssignClass,
ExceptMoveConsNoexceptMoveAssignClass,
NoexceptMoveConsNoexceptMoveAssignClass> tt21;
typedef std::tuple<NoexceptMoveConsNoexceptMoveAssignClass,
ExceptMoveConsNoexceptMoveAssignClass,
NoexceptMoveConsExceptMoveAssignClass> tt22;
typedef std::tuple<NoexceptMoveConsNoexceptMoveAssignClass,
NoexceptMoveConsNoexceptMoveAssignClass,
ExceptMoveConsExceptMoveAssignClass> tt23;
typedef std::tuple<NoexceptMoveConsNoexceptMoveAssignClass,
short, ExceptMoveConsExceptMoveAssignClass> tt24;
typedef std::tuple<NoexceptMoveConsNoexceptMoveAssignClass,
short, ExceptMoveConsExceptMoveAssignClass> tt25;
static_assert(noexcept(std::declval<tt1&>().swap(std::declval<tt1&>())),
"Error");
static_assert(noexcept(std::declval<tt2&>().swap(std::declval<tt2&>())),
"Error");
static_assert(noexcept(std::declval<tt3&>().swap(std::declval<tt3&>())),
"Error");
static_assert(noexcept(std::declval<tt4&>().swap(std::declval<tt4&>())),
"Error");
static_assert(!noexcept(std::declval<tt5&>().swap(std::declval<tt5&>())),
"Error");
static_assert(!noexcept(std::declval<tt6&>().swap(std::declval<tt6&>())),
"Error");
static_assert(!noexcept(std::declval<tt7&>().swap(std::declval<tt7&>())),
"Error");
static_assert(!noexcept(std::declval<tt8&>().swap(std::declval<tt8&>())),
"Error");
static_assert(!noexcept(std::declval<tt9&>().swap(std::declval<tt9&>())),
"Error");
static_assert(!noexcept(std::declval<tt10&>().swap(std::declval<tt10&>())),
"Error");
static_assert(noexcept(std::declval<tt11&>().swap(std::declval<tt11&>())),
"Error");
static_assert(noexcept(std::declval<tt12&>().swap(std::declval<tt12&>())),
"Error");
static_assert(noexcept(std::declval<tt13&>().swap(std::declval<tt13&>())),
"Error");
static_assert(!noexcept(std::declval<tt14&>().swap(std::declval<tt14&>())),
"Error");
static_assert(!noexcept(std::declval<tt15&>().swap(std::declval<tt15&>())),
"Error");
static_assert(!noexcept(std::declval<tt16&>().swap(std::declval<tt16&>())),
"Error");
static_assert(noexcept(std::declval<tt17&>().swap(std::declval<tt17&>())),
"Error");
static_assert(noexcept(std::declval<tt18&>().swap(std::declval<tt18&>())),
"Error");
static_assert(noexcept(std::declval<tt19&>().swap(std::declval<tt19&>())),
"Error");
static_assert(noexcept(std::declval<tt20&>().swap(std::declval<tt20&>())),
"Error");
static_assert(!noexcept(std::declval<tt21&>().swap(std::declval<tt21&>())),
"Error");
static_assert(!noexcept(std::declval<tt22&>().swap(std::declval<tt22&>())),
"Error");
static_assert(!noexcept(std::declval<tt23&>().swap(std::declval<tt23&>())),
"Error");
static_assert(!noexcept(std::declval<tt24&>().swap(std::declval<tt24&>())),
"Error");

View File

@ -51,9 +51,9 @@ main()
// { dg-warning "note" "" { target *-*-* } 485 }
// { dg-warning "note" "" { target *-*-* } 479 }
// { dg-warning "note" "" { target *-*-* } 469 }
// { dg-warning "note" "" { target *-*-* } 599 }
// { dg-warning "note" "" { target *-*-* } 603 }
// { dg-warning "note" "" { target *-*-* } 1056 }
// { dg-warning "note" "" { target *-*-* } 1050 }
// { dg-warning "note" "" { target *-*-* } 342 }
// { dg-warning "note" "" { target *-*-* } 292 }
// { dg-warning "note" "" { target *-*-* } 211 }
// { dg-warning "note" "" { target *-*-* } 212 }

View File

@ -1,7 +1,7 @@
// { dg-do compile }
// { dg-options "-std=gnu++0x" }
// Copyright (C) 2005, 2007, 2009 Free Software Foundation, Inc.
// Copyright (C) 2005, 2007, 2009, 2011 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
@ -27,11 +27,11 @@
using __gnu_test::bidirectional_iterator_wrapper;
class X
{
X();
X(const X&);
void operator=(const X&);
struct X
{
X() = delete;
X(const X&) = delete;
void operator=(const X&) = delete;
};
void

View File

@ -1,7 +1,7 @@
// { dg-do compile }
// { dg-options "-std=gnu++0x" }
// Copyright (C) 2005, 2007, 2009 Free Software Foundation, Inc.
// Copyright (C) 2005, 2007, 2009, 2011 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
@ -27,11 +27,11 @@
using __gnu_test::forward_iterator_wrapper;
class X
struct X
{
X();
X(const X&);
void operator=(const X&);
X() = delete;
X(const X&) = delete;
void operator=(const X&) = delete;
};
void

View File

@ -327,10 +327,19 @@ namespace __gnu_test
void
destroy(pointer p) { p->~Tp(); }
#ifdef __GXX_EXPERIMENTAL_CXX0X__
// Not copy assignable...
uneq_allocator&
operator=(const uneq_allocator&) = delete;
#endif
private:
#ifndef __GXX_EXPERIMENTAL_CXX0X__
// Not assignable...
uneq_allocator&
operator=(const uneq_allocator&);
#endif
// ... yet swappable!
friend inline void

View File

@ -240,6 +240,42 @@ namespace __gnu_test
DeletedMoveAssignClass&
operator=(DeletedMoveAssignClass&&) = delete;
};
struct NoexceptMoveConsNoexceptMoveAssignClass
{
NoexceptMoveConsNoexceptMoveAssignClass
(NoexceptMoveConsNoexceptMoveAssignClass&&) noexcept(true);
NoexceptMoveConsNoexceptMoveAssignClass&
operator=(NoexceptMoveConsNoexceptMoveAssignClass&&) noexcept(true);
};
struct ExceptMoveConsNoexceptMoveAssignClass
{
ExceptMoveConsNoexceptMoveAssignClass
(ExceptMoveConsNoexceptMoveAssignClass&&) noexcept(false);
ExceptMoveConsNoexceptMoveAssignClass&
operator=(ExceptMoveConsNoexceptMoveAssignClass&&) noexcept(true);
};
struct NoexceptMoveConsExceptMoveAssignClass
{
NoexceptMoveConsExceptMoveAssignClass
(NoexceptMoveConsExceptMoveAssignClass&&) noexcept(true);
NoexceptMoveConsExceptMoveAssignClass&
operator=(NoexceptMoveConsExceptMoveAssignClass&&) noexcept(false);
};
struct ExceptMoveConsExceptMoveAssignClass
{
ExceptMoveConsExceptMoveAssignClass
(ExceptMoveConsExceptMoveAssignClass&&) noexcept(false);
ExceptMoveConsExceptMoveAssignClass&
operator=(ExceptMoveConsExceptMoveAssignClass&&) noexcept(false);
};
#endif
struct NType // neither trivial nor standard-layout