From 173f26ae56c9d4ac260db7a3d7b3ee44b7d07bf2 Mon Sep 17 00:00:00 2001 From: Paolo Carlini Date: Thu, 19 May 2011 17:20:22 +0000 Subject: [PATCH] tuple (tuple<>::operator=(tuple&&)): Specify as noexcept. 2011-05-19 Paolo Carlini * 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 --- libstdc++-v3/ChangeLog | 21 ++++ libstdc++-v3/include/bits/algorithmfwd.h | 7 +- libstdc++-v3/include/bits/move.h | 5 +- libstdc++-v3/include/bits/stl_pair.h | 3 +- libstdc++-v3/include/std/tuple | 28 +++-- .../20_util/tuple/noexcept_move_assign.cc | 59 +++++++++ .../testsuite/20_util/tuple/noexcept_swap.cc | 116 ++++++++++++++++++ .../20_util/weak_ptr/comparison/cmp_neg.cc | 4 +- .../25_algorithms/reverse/moveable.cc | 12 +- .../25_algorithms/swap_ranges/moveable.cc | 10 +- .../testsuite/util/testsuite_allocator.h | 9 ++ libstdc++-v3/testsuite/util/testsuite_tr1.h | 36 ++++++ 12 files changed, 282 insertions(+), 28 deletions(-) create mode 100644 libstdc++-v3/testsuite/20_util/tuple/noexcept_move_assign.cc create mode 100644 libstdc++-v3/testsuite/20_util/tuple/noexcept_swap.cc diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 344d1853d87..6275373d9f5 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,24 @@ +2011-05-19 Paolo Carlini + + * 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 * testsuite/util/testsuite_tr1.h: Add test classes. diff --git a/libstdc++-v3/include/bits/algorithmfwd.h b/libstdc++-v3/include/bits/algorithmfwd.h index 8632bf5dd63..fe3b68f6a25 100644 --- a/libstdc++-v3/include/bits/algorithmfwd.h +++ b/libstdc++-v3/include/bits/algorithmfwd.h @@ -549,7 +549,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template 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 void diff --git a/libstdc++-v3/include/bits/move.h b/libstdc++-v3/include/bits/move.h index 4b50bbb9efc..963dd4c655d 100644 --- a/libstdc++-v3/include/bits/move.h +++ b/libstdc++-v3/include/bits/move.h @@ -135,7 +135,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template 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>) diff --git a/libstdc++-v3/include/bits/stl_pair.h b/libstdc++-v3/include/bits/stl_pair.h index 7902f2653d7..e2fc16deae5 100644 --- a/libstdc++-v3/include/bits/stl_pair.h +++ b/libstdc++-v3/include/bits/stl_pair.h @@ -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); diff --git a/libstdc++-v3/include/std/tuple b/libstdc++-v3/include/std/tuple index 066b3d0855c..682e3c92a47 100644 --- a/libstdc++-v3/include/std/tuple +++ b/libstdc++-v3/include/std/tuple @@ -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 @@ -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 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 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 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 diff --git a/libstdc++-v3/testsuite/20_util/tuple/noexcept_move_assign.cc b/libstdc++-v3/testsuite/20_util/tuple/noexcept_move_assign.cc new file mode 100644 index 00000000000..7acf0b95358 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/tuple/noexcept_move_assign.cc @@ -0,0 +1,59 @@ +// { dg-do compile } +// { dg-options "-std=gnu++0x" } + +// 2011-05-19 Paolo Carlini +// +// 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 +// . + +#include +#include + +using namespace __gnu_test; + +typedef std::tuple tt1; +typedef std::tuple tt2; +typedef std::tuple tt3; +typedef std::tuple tt4; +typedef std::tuple tt5; +typedef std::tuple tt6; +typedef std::tuple tt7; +typedef std::tuple tt8; +typedef std::tuple tt9; +typedef std::tuple tt10; +typedef std::tuple tt11; +typedef std::tuple tt12; + +static_assert(std::is_nothrow_move_assignable::value, "Error"); +static_assert(std::is_nothrow_move_assignable::value, "Error"); +static_assert(std::is_nothrow_move_assignable::value, "Error"); +static_assert(std::is_nothrow_move_assignable::value, "Error"); +static_assert(std::is_nothrow_move_assignable::value, "Error"); +static_assert(std::is_nothrow_move_assignable::value, "Error"); +static_assert(!std::is_nothrow_move_assignable::value, "Error"); +static_assert(!std::is_nothrow_move_assignable::value, "Error"); +static_assert(!std::is_nothrow_move_assignable::value, "Error"); +static_assert(!std::is_nothrow_move_assignable::value, "Error"); +static_assert(!std::is_nothrow_move_assignable::value, "Error"); +static_assert(!std::is_nothrow_move_assignable::value, "Error"); diff --git a/libstdc++-v3/testsuite/20_util/tuple/noexcept_swap.cc b/libstdc++-v3/testsuite/20_util/tuple/noexcept_swap.cc new file mode 100644 index 00000000000..4ad327036fa --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/tuple/noexcept_swap.cc @@ -0,0 +1,116 @@ +// { dg-do compile } +// { dg-options "-std=gnu++0x" } + +// 2011-05-19 Paolo Carlini +// +// 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 +// . + +#include +#include + +using namespace __gnu_test; + +typedef std::tuple tt1; +typedef std::tuple tt2; +typedef std::tuple tt3; +typedef std::tuple tt4; +typedef std::tuple tt5; +typedef std::tuple tt6; +typedef std::tuple tt7; +typedef std::tuple tt8; +typedef std::tuple tt9; +typedef std::tuple tt10; +typedef std::tuple tt11; +typedef std::tuple tt12; +typedef std::tuple tt13; +typedef std::tuple tt14; +typedef std::tuple tt15; +typedef std::tuple tt16; +typedef std::tuple tt17; +typedef std::tuple tt18; +typedef std::tuple tt19; +typedef std::tuple tt20; +typedef std::tuple tt21; +typedef std::tuple tt22; +typedef std::tuple tt23; +typedef std::tuple tt24; +typedef std::tuple tt25; + +static_assert(noexcept(std::declval().swap(std::declval())), + "Error"); +static_assert(noexcept(std::declval().swap(std::declval())), + "Error"); +static_assert(noexcept(std::declval().swap(std::declval())), + "Error"); +static_assert(noexcept(std::declval().swap(std::declval())), + "Error"); +static_assert(!noexcept(std::declval().swap(std::declval())), + "Error"); +static_assert(!noexcept(std::declval().swap(std::declval())), + "Error"); +static_assert(!noexcept(std::declval().swap(std::declval())), + "Error"); +static_assert(!noexcept(std::declval().swap(std::declval())), + "Error"); +static_assert(!noexcept(std::declval().swap(std::declval())), + "Error"); +static_assert(!noexcept(std::declval().swap(std::declval())), + "Error"); +static_assert(noexcept(std::declval().swap(std::declval())), + "Error"); +static_assert(noexcept(std::declval().swap(std::declval())), + "Error"); +static_assert(noexcept(std::declval().swap(std::declval())), + "Error"); +static_assert(!noexcept(std::declval().swap(std::declval())), + "Error"); +static_assert(!noexcept(std::declval().swap(std::declval())), + "Error"); +static_assert(!noexcept(std::declval().swap(std::declval())), + "Error"); +static_assert(noexcept(std::declval().swap(std::declval())), + "Error"); +static_assert(noexcept(std::declval().swap(std::declval())), + "Error"); +static_assert(noexcept(std::declval().swap(std::declval())), + "Error"); +static_assert(noexcept(std::declval().swap(std::declval())), + "Error"); +static_assert(!noexcept(std::declval().swap(std::declval())), + "Error"); +static_assert(!noexcept(std::declval().swap(std::declval())), + "Error"); +static_assert(!noexcept(std::declval().swap(std::declval())), + "Error"); +static_assert(!noexcept(std::declval().swap(std::declval())), + "Error"); diff --git a/libstdc++-v3/testsuite/20_util/weak_ptr/comparison/cmp_neg.cc b/libstdc++-v3/testsuite/20_util/weak_ptr/comparison/cmp_neg.cc index 8316d483cdb..24168ceda2c 100644 --- a/libstdc++-v3/testsuite/20_util/weak_ptr/comparison/cmp_neg.cc +++ b/libstdc++-v3/testsuite/20_util/weak_ptr/comparison/cmp_neg.cc @@ -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 } diff --git a/libstdc++-v3/testsuite/25_algorithms/reverse/moveable.cc b/libstdc++-v3/testsuite/25_algorithms/reverse/moveable.cc index 9a871db5f48..ec6d241ac5d 100644 --- a/libstdc++-v3/testsuite/25_algorithms/reverse/moveable.cc +++ b/libstdc++-v3/testsuite/25_algorithms/reverse/moveable.cc @@ -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 diff --git a/libstdc++-v3/testsuite/25_algorithms/swap_ranges/moveable.cc b/libstdc++-v3/testsuite/25_algorithms/swap_ranges/moveable.cc index 5377ea838f1..78750f29b40 100644 --- a/libstdc++-v3/testsuite/25_algorithms/swap_ranges/moveable.cc +++ b/libstdc++-v3/testsuite/25_algorithms/swap_ranges/moveable.cc @@ -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 diff --git a/libstdc++-v3/testsuite/util/testsuite_allocator.h b/libstdc++-v3/testsuite/util/testsuite_allocator.h index a534d85845d..73622f1a7a1 100644 --- a/libstdc++-v3/testsuite/util/testsuite_allocator.h +++ b/libstdc++-v3/testsuite/util/testsuite_allocator.h @@ -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 diff --git a/libstdc++-v3/testsuite/util/testsuite_tr1.h b/libstdc++-v3/testsuite/util/testsuite_tr1.h index 03cc431c1cf..842d4453897 100644 --- a/libstdc++-v3/testsuite/util/testsuite_tr1.h +++ b/libstdc++-v3/testsuite/util/testsuite_tr1.h @@ -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