diff mbox

[v3] More noexcept -- 3rd

Message ID alpine.DEB.2.02.1309181725480.10748@stedding.saclay.inria.fr
State New
Headers show

Commit Message

Marc Glisse Sept. 18, 2013, 3:51 p.m. UTC
Hello,

some more containers...

In debug array, we already have throw in noexcept functions, but if I
understand correctly it is only because of syntax limitations for constexpr
functions and aborts before throwing, although the use of
_GLIBCXX_THROW_OR_ABORT is suspicious. In any case, I am not changing this
with my patch.

I replaced throw with abort in list, as discussed, and thus removed the
corresponding testcase.

bootstrap+testsuite ok.

2013-09-19  Marc Glisse  <marc.glisse@inria.fr>

 	PR libstdc++/58338
 	* include/bits/stl_iterator.h (__normal_iterator) [__normal_iterator,
 	_M_const_cast, operator*, operator->, operator++, operator--,
 	operator[], operator+=, operator+, operator-=, operator-, base]:
 	Mark as noexcept.
 	(operator==(const __normal_iterator&, const __normal_iterator&),
 	operator!=(const __normal_iterator&, const __normal_iterator&),
 	operator<(const __normal_iterator&, const __normal_iterator&),
 	operator>(const __normal_iterator&, const __normal_iterator&),
 	operator<=(const __normal_iterator&, const __normal_iterator&),
 	operator>=(const __normal_iterator&, const __normal_iterator&),
 	operator-(const __normal_iterator&, const __normal_iterator&),
 	operator+(difference_type, const __normal_iterator&)): Likewise.
 	* include/bits/stl_list.h (list) [splice, _M_check_equal_allocators]:
 	Likewise.
 	(list::_M_check_equal_allocators): Abort instead of throwing.
 	* include/debug/array (array) [operator[], front, back]: Mark as
 	noexcept.
 	* include/profile/array (array) [operator[], front, back]: Likewise.
 	* include/std/array (array) [operator[], front, back]: Likewise.
 	* include/debug/list (list::splice): Likewise.
 	* include/profile/list (list::splice): Likewise.
 	* testsuite/23_containers/list/operations/5.cc: Remove file.
 	* testsuite/23_containers/list/operations/5.h: Likewise.

Comments

Paolo Carlini Sept. 18, 2013, 4 p.m. UTC | #1
Hi,

On 09/18/2013 05:51 PM, Marc Glisse wrote:
> Hello,
>
> some more containers...
>
> In debug array, we already have throw in noexcept functions, but if I
> understand correctly it is only because of syntax limitations for 
> constexpr
> functions and aborts before throwing, although the use of
> _GLIBCXX_THROW_OR_ABORT is suspicious. In any case, I am not changing 
> this
> with my patch.
If I remember correctly, somebody invented that mild hack and suggested 
it to indeed have a check as part of a constexpr function, not a trivial 
task. Jon participated to that discussion. After a while I resurrected 
that old discussion, tested the code and it appeared to work well. In 
practice, are you experiencing specific problems with it?

Thanks,
Paolo.
Jonathan Wakely Sept. 18, 2013, 4:09 p.m. UTC | #2
On 18 September 2013 17:00, Paolo Carlini wrote:
> Hi,
>
>
> On 09/18/2013 05:51 PM, Marc Glisse wrote:
>>
>> Hello,
>>
>> some more containers...

Great, thanks for working your way through all these!

>> In debug array, we already have throw in noexcept functions, but if I
>> understand correctly it is only because of syntax limitations for
>> constexpr
>> functions and aborts before throwing, although the use of
>> _GLIBCXX_THROW_OR_ABORT is suspicious. In any case, I am not changing this
>> with my patch.
>
> If I remember correctly, somebody invented that mild hack and suggested it
> to indeed have a check as part of a constexpr function, not a trivial task.
> Jon participated to that discussion.

I think that old discussion was in the "Should _GLIBCXX_DEBUG affect
tr1/array?" thread in January 2012.

> After a while I resurrected that old
> discussion, tested the code and it appeared to work well. In practice, are
> you experiencing specific problems with it?
Jonathan Wakely Sept. 18, 2013, 4:14 p.m. UTC | #3
On 18 September 2013 16:51, Marc Glisse wrote:
> Hello,
>
> some more containers...
>
> In debug array, we already have throw in noexcept functions, but if I
> understand correctly it is only because of syntax limitations for constexpr
> functions and aborts before throwing, although the use of
> _GLIBCXX_THROW_OR_ABORT is suspicious. In any case, I am not changing this
> with my patch.
>
> I replaced throw with abort in list, as discussed, and thus removed the
> corresponding testcase.
>
> bootstrap+testsuite ok.
>
> 2013-09-19  Marc Glisse  <marc.glisse@inria.fr>
>
>         PR libstdc++/58338
>         * include/bits/stl_iterator.h (__normal_iterator)
> [__normal_iterator,
>         _M_const_cast, operator*, operator->, operator++, operator--,
>         operator[], operator+=, operator+, operator-=, operator-, base]:
>         Mark as noexcept.
>         (operator==(const __normal_iterator&, const __normal_iterator&),
>         operator!=(const __normal_iterator&, const __normal_iterator&),
>         operator<(const __normal_iterator&, const __normal_iterator&),
>         operator>(const __normal_iterator&, const __normal_iterator&),
>         operator<=(const __normal_iterator&, const __normal_iterator&),
>         operator>=(const __normal_iterator&, const __normal_iterator&),
>         operator-(const __normal_iterator&, const __normal_iterator&),
>         operator+(difference_type, const __normal_iterator&)): Likewise.
>         * include/bits/stl_list.h (list) [splice,
> _M_check_equal_allocators]:
>         Likewise.
>         (list::_M_check_equal_allocators): Abort instead of throwing.
>         * include/debug/array (array) [operator[], front, back]: Mark as
>         noexcept.
>         * include/profile/array (array) [operator[], front, back]: Likewise.
>         * include/std/array (array) [operator[], front, back]: Likewise.
>         * include/debug/list (list::splice): Likewise.
>         * include/profile/list (list::splice): Likewise.
>         * testsuite/23_containers/list/operations/5.cc: Remove file.
>         * testsuite/23_containers/list/operations/5.h: Likewise.


This patch looks good to me, thanks again.
Marc Glisse Sept. 18, 2013, 4:27 p.m. UTC | #4
On Wed, 18 Sep 2013, Paolo Carlini wrote:
> On 09/18/2013 05:51 PM, Marc Glisse wrote:
>> In debug array, we already have throw in noexcept functions, but if I
>> understand correctly it is only because of syntax limitations for constexpr
>> functions and aborts before throwing, although the use of
>> _GLIBCXX_THROW_OR_ABORT is suspicious. In any case, I am not changing this
>> with my patch.
> If I remember correctly, somebody invented that mild hack and suggested it to 
> indeed have a check as part of a constexpr function, not a trivial task. Jon 
> participated to that discussion. After a while I resurrected that old 
> discussion, tested the code and it appeared to work well. In practice, are 
> you experiencing specific problems with it?

No, no problem. For some reason I thought there would be issues when the 
macro expands to __builtin_abort(), but there aren't, great.

Any other comments on the patch? (Jon's "great" doesn't really sound like 
an "ok")
Jonathan Wakely Sept. 18, 2013, 4:29 p.m. UTC | #5
On 18 September 2013 17:27, Marc Glisse <marc.glisse@inria.fr> wrote:
> On Wed, 18 Sep 2013, Paolo Carlini wrote:
>>
>> On 09/18/2013 05:51 PM, Marc Glisse wrote:
>>>
>>> In debug array, we already have throw in noexcept functions, but if I
>>> understand correctly it is only because of syntax limitations for
>>> constexpr
>>> functions and aborts before throwing, although the use of
>>> _GLIBCXX_THROW_OR_ABORT is suspicious. In any case, I am not changing
>>> this
>>> with my patch.
>>
>> If I remember correctly, somebody invented that mild hack and suggested it
>> to indeed have a check as part of a constexpr function, not a trivial task.
>> Jon participated to that discussion. After a while I resurrected that old
>> discussion, tested the code and it appeared to work well. In practice, are
>> you experiencing specific problems with it?
>
>
> No, no problem. For some reason I thought there would be issues when the
> macro expands to __builtin_abort(), but there aren't, great.
>
> Any other comments on the patch? (Jon's "great" doesn't really sound like an
> "ok")

It wasn't, as I hadn't reviewed the patch at that time, but I sent
another mail with an "ok" after reading it :)
diff mbox

Patch

Index: include/bits/stl_iterator.h
===================================================================
--- include/bits/stl_iterator.h	(revision 202699)
+++ include/bits/stl_iterator.h	(working copy)
@@ -714,216 +714,232 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
       typedef iterator_traits<_Iterator>		__traits_type;
 
     public:
       typedef _Iterator					iterator_type;
       typedef typename __traits_type::iterator_category iterator_category;
       typedef typename __traits_type::value_type  	value_type;
       typedef typename __traits_type::difference_type 	difference_type;
       typedef typename __traits_type::reference 	reference;
       typedef typename __traits_type::pointer   	pointer;
 
-      _GLIBCXX_CONSTEXPR __normal_iterator() : _M_current(_Iterator()) { }
+      _GLIBCXX_CONSTEXPR __normal_iterator() _GLIBCXX_NOEXCEPT
+      : _M_current(_Iterator()) { }
 
       explicit
-      __normal_iterator(const _Iterator& __i) : _M_current(__i) { }
+      __normal_iterator(const _Iterator& __i) _GLIBCXX_NOEXCEPT
+      : _M_current(__i) { }
 
       // Allow iterator to const_iterator conversion
       template<typename _Iter>
         __normal_iterator(const __normal_iterator<_Iter,
 			  typename __enable_if<
       	       (std::__are_same<_Iter, typename _Container::pointer>::__value),
-		      _Container>::__type>& __i)
+		      _Container>::__type>& __i) _GLIBCXX_NOEXCEPT
         : _M_current(__i.base()) { }
 
 #if __cplusplus >= 201103L
       __normal_iterator<typename _Container::pointer, _Container>
-      _M_const_cast() const
+      _M_const_cast() const noexcept
       {
 	using _PTraits = std::pointer_traits<typename _Container::pointer>;
 	return __normal_iterator<typename _Container::pointer, _Container>
 	  (_PTraits::pointer_to(const_cast<typename _PTraits::element_type&>
 				(*_M_current)));
       }
 #else
       __normal_iterator
       _M_const_cast() const
       { return *this; }
 #endif
 
       // Forward iterator requirements
       reference
-      operator*() const
+      operator*() const _GLIBCXX_NOEXCEPT
       { return *_M_current; }
 
       pointer
-      operator->() const
+      operator->() const _GLIBCXX_NOEXCEPT
       { return _M_current; }
 
       __normal_iterator&
-      operator++()
+      operator++() _GLIBCXX_NOEXCEPT
       {
 	++_M_current;
 	return *this;
       }
 
       __normal_iterator
-      operator++(int)
+      operator++(int) _GLIBCXX_NOEXCEPT
       { return __normal_iterator(_M_current++); }
 
       // Bidirectional iterator requirements
       __normal_iterator&
-      operator--()
+      operator--() _GLIBCXX_NOEXCEPT
       {
 	--_M_current;
 	return *this;
       }
 
       __normal_iterator
-      operator--(int)
+      operator--(int) _GLIBCXX_NOEXCEPT
       { return __normal_iterator(_M_current--); }
 
       // Random access iterator requirements
       reference
-      operator[](difference_type __n) const
+      operator[](difference_type __n) const _GLIBCXX_NOEXCEPT
       { return _M_current[__n]; }
 
       __normal_iterator&
-      operator+=(difference_type __n)
+      operator+=(difference_type __n) _GLIBCXX_NOEXCEPT
       { _M_current += __n; return *this; }
 
       __normal_iterator
-      operator+(difference_type __n) const
+      operator+(difference_type __n) const _GLIBCXX_NOEXCEPT
       { return __normal_iterator(_M_current + __n); }
 
       __normal_iterator&
-      operator-=(difference_type __n)
+      operator-=(difference_type __n) _GLIBCXX_NOEXCEPT
       { _M_current -= __n; return *this; }
 
       __normal_iterator
-      operator-(difference_type __n) const
+      operator-(difference_type __n) const _GLIBCXX_NOEXCEPT
       { return __normal_iterator(_M_current - __n); }
 
       const _Iterator&
-      base() const
+      base() const _GLIBCXX_NOEXCEPT
       { return _M_current; }
     };
 
   // Note: In what follows, the left- and right-hand-side iterators are
   // allowed to vary in types (conceptually in cv-qualification) so that
   // comparison between cv-qualified and non-cv-qualified iterators be
   // valid.  However, the greedy and unfriendly operators in std::rel_ops
   // will make overload resolution ambiguous (when in scope) if we don't
   // provide overloads whose operands are of the same type.  Can someone
   // remind me what generic programming is about? -- Gaby
 
   // Forward iterator requirements
   template<typename _IteratorL, typename _IteratorR, typename _Container>
     inline bool
     operator==(const __normal_iterator<_IteratorL, _Container>& __lhs,
 	       const __normal_iterator<_IteratorR, _Container>& __rhs)
+    _GLIBCXX_NOEXCEPT
     { return __lhs.base() == __rhs.base(); }
 
   template<typename _Iterator, typename _Container>
     inline bool
     operator==(const __normal_iterator<_Iterator, _Container>& __lhs,
 	       const __normal_iterator<_Iterator, _Container>& __rhs)
+    _GLIBCXX_NOEXCEPT
     { return __lhs.base() == __rhs.base(); }
 
   template<typename _IteratorL, typename _IteratorR, typename _Container>
     inline bool
     operator!=(const __normal_iterator<_IteratorL, _Container>& __lhs,
 	       const __normal_iterator<_IteratorR, _Container>& __rhs)
+    _GLIBCXX_NOEXCEPT
     { return __lhs.base() != __rhs.base(); }
 
   template<typename _Iterator, typename _Container>
     inline bool
     operator!=(const __normal_iterator<_Iterator, _Container>& __lhs,
 	       const __normal_iterator<_Iterator, _Container>& __rhs)
+    _GLIBCXX_NOEXCEPT
     { return __lhs.base() != __rhs.base(); }
 
   // Random access iterator requirements
   template<typename _IteratorL, typename _IteratorR, typename _Container>
     inline bool
     operator<(const __normal_iterator<_IteratorL, _Container>& __lhs,
 	      const __normal_iterator<_IteratorR, _Container>& __rhs)
+    _GLIBCXX_NOEXCEPT
     { return __lhs.base() < __rhs.base(); }
 
   template<typename _Iterator, typename _Container>
     inline bool
     operator<(const __normal_iterator<_Iterator, _Container>& __lhs,
 	      const __normal_iterator<_Iterator, _Container>& __rhs)
+    _GLIBCXX_NOEXCEPT
     { return __lhs.base() < __rhs.base(); }
 
   template<typename _IteratorL, typename _IteratorR, typename _Container>
     inline bool
     operator>(const __normal_iterator<_IteratorL, _Container>& __lhs,
 	      const __normal_iterator<_IteratorR, _Container>& __rhs)
+    _GLIBCXX_NOEXCEPT
     { return __lhs.base() > __rhs.base(); }
 
   template<typename _Iterator, typename _Container>
     inline bool
     operator>(const __normal_iterator<_Iterator, _Container>& __lhs,
 	      const __normal_iterator<_Iterator, _Container>& __rhs)
+    _GLIBCXX_NOEXCEPT
     { return __lhs.base() > __rhs.base(); }
 
   template<typename _IteratorL, typename _IteratorR, typename _Container>
     inline bool
     operator<=(const __normal_iterator<_IteratorL, _Container>& __lhs,
 	       const __normal_iterator<_IteratorR, _Container>& __rhs)
+    _GLIBCXX_NOEXCEPT
     { return __lhs.base() <= __rhs.base(); }
 
   template<typename _Iterator, typename _Container>
     inline bool
     operator<=(const __normal_iterator<_Iterator, _Container>& __lhs,
 	       const __normal_iterator<_Iterator, _Container>& __rhs)
+    _GLIBCXX_NOEXCEPT
     { return __lhs.base() <= __rhs.base(); }
 
   template<typename _IteratorL, typename _IteratorR, typename _Container>
     inline bool
     operator>=(const __normal_iterator<_IteratorL, _Container>& __lhs,
 	       const __normal_iterator<_IteratorR, _Container>& __rhs)
+    _GLIBCXX_NOEXCEPT
     { return __lhs.base() >= __rhs.base(); }
 
   template<typename _Iterator, typename _Container>
     inline bool
     operator>=(const __normal_iterator<_Iterator, _Container>& __lhs,
 	       const __normal_iterator<_Iterator, _Container>& __rhs)
+    _GLIBCXX_NOEXCEPT
     { return __lhs.base() >= __rhs.base(); }
 
   // _GLIBCXX_RESOLVE_LIB_DEFECTS
   // According to the resolution of DR179 not only the various comparison
   // operators but also operator- must accept mixed iterator/const_iterator
   // parameters.
   template<typename _IteratorL, typename _IteratorR, typename _Container>
 #if __cplusplus >= 201103L
     // DR 685.
     inline auto
     operator-(const __normal_iterator<_IteratorL, _Container>& __lhs,
-	      const __normal_iterator<_IteratorR, _Container>& __rhs)
+	      const __normal_iterator<_IteratorR, _Container>& __rhs) noexcept
     -> decltype(__lhs.base() - __rhs.base())
 #else
     inline typename __normal_iterator<_IteratorL, _Container>::difference_type
     operator-(const __normal_iterator<_IteratorL, _Container>& __lhs,
 	      const __normal_iterator<_IteratorR, _Container>& __rhs)
 #endif
     { return __lhs.base() - __rhs.base(); }
 
   template<typename _Iterator, typename _Container>
     inline typename __normal_iterator<_Iterator, _Container>::difference_type
     operator-(const __normal_iterator<_Iterator, _Container>& __lhs,
 	      const __normal_iterator<_Iterator, _Container>& __rhs)
+    _GLIBCXX_NOEXCEPT
     { return __lhs.base() - __rhs.base(); }
 
   template<typename _Iterator, typename _Container>
     inline __normal_iterator<_Iterator, _Container>
     operator+(typename __normal_iterator<_Iterator, _Container>::difference_type
 	      __n, const __normal_iterator<_Iterator, _Container>& __i)
+    _GLIBCXX_NOEXCEPT
     { return __normal_iterator<_Iterator, _Container>(__i.base() + __n); }
 
 _GLIBCXX_END_NAMESPACE_VERSION
 } // namespace
 
 #if __cplusplus >= 201103L
 
 namespace std _GLIBCXX_VISIBILITY(default)
 {
 _GLIBCXX_BEGIN_NAMESPACE_VERSION
Index: include/bits/stl_list.h
===================================================================
--- include/bits/stl_list.h	(revision 202699)
+++ include/bits/stl_list.h	(working copy)
@@ -1302,53 +1302,53 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
        *  @param  __x  Source list.
        *
        *  The elements of @a __x are inserted in constant time in front of
        *  the element referenced by @a __position.  @a __x becomes an empty
        *  list.
        *
        *  Requires this != @a __x.
        */
       void
 #if __cplusplus >= 201103L
-      splice(const_iterator __position, list&& __x)
+      splice(const_iterator __position, list&& __x) noexcept
 #else
       splice(iterator __position, list& __x)
 #endif
       {
 	if (!__x.empty())
 	  {
 	    _M_check_equal_allocators(__x);
 
 	    this->_M_transfer(__position._M_const_cast(),
 			      __x.begin(), __x.end());
 	  }
       }
 
 #if __cplusplus >= 201103L
       void
-      splice(const_iterator __position, list& __x)
+      splice(const_iterator __position, list& __x) noexcept
       { splice(__position, std::move(__x)); }
 #endif
 
 #if __cplusplus >= 201103L
       /**
        *  @brief  Insert element from another %list.
        *  @param  __position  Const_iterator referencing the element to
        *                      insert before.
        *  @param  __x  Source list.
        *  @param  __i  Const_iterator referencing the element to move.
        *
        *  Removes the element in list @a __x referenced by @a __i and
        *  inserts it into the current list before @a __position.
        */
       void
-      splice(const_iterator __position, list&& __x, const_iterator __i)
+      splice(const_iterator __position, list&& __x, const_iterator __i) noexcept
 #else
       /**
        *  @brief  Insert element from another %list.
        *  @param  __position  Iterator referencing the element to insert before.
        *  @param  __x  Source list.
        *  @param  __i  Iterator referencing the element to move.
        *
        *  Removes the element in list @a __x referenced by @a __i and
        *  inserts it into the current list before @a __position.
        */
@@ -1373,41 +1373,41 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
        *  @brief  Insert element from another %list.
        *  @param  __position  Const_iterator referencing the element to
        *                      insert before.
        *  @param  __x  Source list.
        *  @param  __i  Const_iterator referencing the element to move.
        *
        *  Removes the element in list @a __x referenced by @a __i and
        *  inserts it into the current list before @a __position.
        */
       void
-      splice(const_iterator __position, list& __x, const_iterator __i)
+      splice(const_iterator __position, list& __x, const_iterator __i) noexcept
       { splice(__position, std::move(__x), __i); }
 #endif
 
 #if __cplusplus >= 201103L
       /**
        *  @brief  Insert range from another %list.
        *  @param  __position  Const_iterator referencing the element to
        *                      insert before.
        *  @param  __x  Source list.
        *  @param  __first  Const_iterator referencing the start of range in x.
        *  @param  __last  Const_iterator referencing the end of range in x.
        *
        *  Removes elements in the range [__first,__last) and inserts them
        *  before @a __position in constant time.
        *
        *  Undefined if @a __position is in [__first,__last).
        */
       void
       splice(const_iterator __position, list&& __x, const_iterator __first,
-	     const_iterator __last)
+	     const_iterator __last) noexcept
 #else
       /**
        *  @brief  Insert range from another %list.
        *  @param  __position  Iterator referencing the element to insert before.
        *  @param  __x  Source list.
        *  @param  __first  Iterator referencing the start of range in x.
        *  @param  __last  Iterator referencing the end of range in x.
        *
        *  Removes elements in the range [__first,__last) and inserts them
        *  before @a __position in constant time.
@@ -1439,21 +1439,21 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
        *  @param  __first  Const_iterator referencing the start of range in x.
        *  @param  __last  Const_iterator referencing the end of range in x.
        *
        *  Removes elements in the range [__first,__last) and inserts them
        *  before @a __position in constant time.
        *
        *  Undefined if @a __position is in [__first,__last).
        */
       void
       splice(const_iterator __position, list& __x, const_iterator __first,
-	     const_iterator __last)
+	     const_iterator __last) noexcept
       { splice(__position, std::move(__x), __first, __last); }
 #endif
 
       /**
        *  @brief  Remove all elements equal to value.
        *  @param  __value  The value to remove.
        *
        *  Removes every element in the list equal to @a value.
        *  Remaining elements stay in list order.  Note that this
        *  function only erases the elements, and that if the elements
@@ -1689,25 +1689,25 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 #if __cplusplus >= 201103L
         _M_get_Node_allocator().destroy(__n);
 #else
 	_M_get_Tp_allocator().destroy(std::__addressof(__n->_M_data));
 #endif
         _M_put_node(__n);
       }
 
       // To implement the splice (and merge) bits of N1599.
       void
-      _M_check_equal_allocators(list& __x)
+      _M_check_equal_allocators(list& __x) _GLIBCXX_NOEXCEPT
       {
 	if (std::__alloc_neq<typename _Base::_Node_alloc_type>::
 	    _S_do_it(_M_get_Node_allocator(), __x._M_get_Node_allocator()))
-	  __throw_runtime_error(__N("list::_M_check_equal_allocators"));
+	  __builtin_abort();
       }
     };
 
   /**
    *  @brief  List equality comparison.
    *  @param  __x  A %list.
    *  @param  __y  A %list of the same type as @a __x.
    *  @return  True iff the size and elements of the lists are equal.
    *
    *  This is an equivalence relation.  It is linear in the size of
Index: include/debug/array
===================================================================
--- include/debug/array	(revision 202699)
+++ include/debug/array	(working copy)
@@ -140,21 +140,21 @@  namespace __debug
       size() const noexcept { return _Nm; }
 
       constexpr size_type 
       max_size() const noexcept { return _Nm; }
 
       constexpr bool 
       empty() const noexcept { return size() == 0; }
 
       // Element access.
       reference
-      operator[](size_type __n)
+      operator[](size_type __n) noexcept
       {
 	__glibcxx_check_subscript(__n);
 	return _AT_Type::_S_ref(_M_elems, __n);
       }
 
       constexpr const_reference
       operator[](size_type __n) const noexcept
       {
 	return __n < _Nm ? _AT_Type::_S_ref(_M_elems, __n)
 	 : (_GLIBCXX_THROW_OR_ABORT(_Array_check_subscript<_Nm>(__n)),
@@ -173,43 +173,43 @@  namespace __debug
       at(size_type __n) const
       {
 	// Result of conditional expression must be an lvalue so use
 	// boolean ? lvalue : (throw-expr, lvalue)
 	return __n < _Nm ? _AT_Type::_S_ref(_M_elems, __n)
 	  : (std::__throw_out_of_range(__N("array::at")),
 	     _AT_Type::_S_ref(_M_elems, 0));
       }
 
       reference 
-      front()
+      front() noexcept
       {
 	__glibcxx_check_nonempty();
 	return *begin();
       }
 
       constexpr const_reference 
-      front() const
+      front() const noexcept
       {
 	return _Nm ? _AT_Type::_S_ref(_M_elems, 0)
 	  : (_GLIBCXX_THROW_OR_ABORT(_Array_check_nonempty<_Nm>()),
 	     _AT_Type::_S_ref(_M_elems, 0));
       }
 
       reference 
-      back()
+      back() noexcept
       {
 	__glibcxx_check_nonempty();
 	return _Nm ? *(end() - 1) : *end();
       }
 
       constexpr const_reference 
-      back() const
+      back() const noexcept
       {
 	return _Nm ? _AT_Type::_S_ref(_M_elems, _Nm - 1)
 	  : (_GLIBCXX_THROW_OR_ABORT(_Array_check_nonempty<_Nm>()),
 	     _AT_Type::_S_ref(_M_elems, 0));
       }
 
       pointer
       data() noexcept
       { return std::__addressof(_AT_Type::_S_ref(_M_elems, 0)); }
 
Index: include/debug/list
===================================================================
--- include/debug/list	(revision 202699)
+++ include/debug/list	(working copy)
@@ -508,41 +508,41 @@  namespace __debug
       void
       clear() _GLIBCXX_NOEXCEPT
       {
 	_Base::clear();
 	this->_M_invalidate_all();
       }
 
       // 23.2.2.4 list operations:
       void
 #if __cplusplus >= 201103L
-      splice(const_iterator __position, list&& __x)
+      splice(const_iterator __position, list&& __x) noexcept
 #else
       splice(iterator __position, list& __x)
 #endif
       {
 	_GLIBCXX_DEBUG_VERIFY(&__x != this,
 			      _M_message(__gnu_debug::__msg_self_splice)
 			      ._M_sequence(*this, "this"));
 	this->_M_transfer_from_if(__x, _Not_equal(__x._M_base().end()));
 	_Base::splice(__position.base(), _GLIBCXX_MOVE(__x._M_base()));
       }
 
 #if __cplusplus >= 201103L
       void
-      splice(const_iterator __position, list& __x)
+      splice(const_iterator __position, list& __x) noexcept
       { splice(__position, std::move(__x)); }
 #endif
 
       void
 #if __cplusplus >= 201103L
-      splice(const_iterator __position, list&& __x, const_iterator __i)
+      splice(const_iterator __position, list&& __x, const_iterator __i) noexcept
 #else
       splice(iterator __position, list& __x, iterator __i)
 #endif
       {
 	__glibcxx_check_insert(__position);
 
 	// We used to perform the splice_alloc check:  not anymore, redundant
 	// after implementing the relevant bits of N1599.
 
 	_GLIBCXX_DEBUG_VERIFY(__i._M_dereferenceable(),
@@ -554,28 +554,28 @@  namespace __debug
 
 	// _GLIBCXX_RESOLVE_LIB_DEFECTS
 	// 250. splicing invalidates iterators
 	this->_M_transfer_from_if(__x, _Equal(__i.base()));
 	_Base::splice(__position.base(), _GLIBCXX_MOVE(__x._M_base()),
 		      __i.base());
       }
 
 #if __cplusplus >= 201103L
       void
-      splice(const_iterator __position, list& __x, const_iterator __i)
+      splice(const_iterator __position, list& __x, const_iterator __i) noexcept
       { splice(__position, std::move(__x), __i); }
 #endif
 
       void
 #if __cplusplus >= 201103L
       splice(const_iterator __position, list&& __x, const_iterator __first,
-	     const_iterator __last)
+	     const_iterator __last) noexcept
 #else
       splice(iterator __position, list& __x, iterator __first,
 	     iterator __last)
 #endif
       {
 	__glibcxx_check_insert(__position);
 	__glibcxx_check_valid_range(__first, __last);
 	_GLIBCXX_DEBUG_VERIFY(__first._M_attached_to(&__x),
 			      _M_message(__gnu_debug::__msg_splice_other)
 			      ._M_sequence(__x, "x")
@@ -601,21 +601,21 @@  namespace __debug
 	    this->_M_transfer_from_if(__x, _Equal(__tmp));
 	  }
 
 	_Base::splice(__position.base(), _GLIBCXX_MOVE(__x._M_base()),
 		      __first.base(), __last.base());
       }
 
 #if __cplusplus >= 201103L
       void
       splice(const_iterator __position, list& __x,
-	     const_iterator __first, const_iterator __last)
+	     const_iterator __first, const_iterator __last) noexcept
       { splice(__position, std::move(__x), __first, __last); }
 #endif
 
       void
       remove(const _Tp& __value)
       {
 	for (_Base_iterator __x = _Base::begin(); __x != _Base::end(); )
 	  {
 	    if (*__x == __value)
 	      __x = _M_erase(__x);
Index: include/profile/array
===================================================================
--- include/profile/array	(revision 202699)
+++ include/profile/array	(working copy)
@@ -120,21 +120,21 @@  namespace __profile
       size() const noexcept { return _Nm; }
 
       constexpr size_type 
       max_size() const noexcept { return _Nm; }
 
       constexpr bool 
       empty() const noexcept { return size() == 0; }
 
       // Element access.
       reference
-      operator[](size_type __n)
+      operator[](size_type __n) noexcept
       {	return _AT_Type::_S_ref(_M_elems, __n); }
 
       constexpr const_reference
       operator[](size_type __n) const noexcept
       { return _AT_Type::_S_ref(_M_elems, __n); }
 
       reference
       at(size_type __n)
       {
 	if (__n >= _Nm)
@@ -146,33 +146,33 @@  namespace __profile
       at(size_type __n) const
       {
 	// Result of conditional expression must be an lvalue so use
 	// boolean ? lvalue : (throw-expr, lvalue)
 	return __n < _Nm ? _AT_Type::_S_ref(_M_elems, __n)
 	  : (std::__throw_out_of_range(__N("array::at")),
 	     _AT_Type::_S_ref(_M_elems, 0));
       }
 
       reference 
-      front()
+      front() noexcept
       { return *begin(); }
 
       constexpr const_reference 
-      front() const
+      front() const noexcept
       { return _AT_Type::_S_ref(_M_elems, 0); }
 
       reference 
-      back()
+      back() noexcept
       { return _Nm ? *(end() - 1) : *end(); }
 
       constexpr const_reference 
-      back() const
+      back() const noexcept
       {
 	return _Nm ? _AT_Type::_S_ref(_M_elems, _Nm - 1)
  	           : _AT_Type::_S_ref(_M_elems, 0);	  
       }
 
       pointer
       data() noexcept
       { return std::__addressof(_AT_Type::_S_ref(_M_elems, 0)); }
 
       const_pointer
Index: include/profile/list
===================================================================
--- include/profile/list	(revision 202699)
+++ include/profile/list	(working copy)
@@ -433,71 +433,71 @@  template<typename _Tp, typename _Allocat
       swap(list& __x)
       {	_Base::swap(__x); }
 
       void
       clear() _GLIBCXX_NOEXCEPT
       {	_Base::clear(); }
 
       // 23.2.2.4 list operations:
       void
 #if __cplusplus >= 201103L
-      splice(const_iterator __position, list&& __x)
+      splice(const_iterator __position, list&& __x) noexcept
 #else
       splice(iterator __position, list& __x)
 #endif
       { this->splice(__position, _GLIBCXX_MOVE(__x), __x.begin(), __x.end()); }
 
 #if __cplusplus >= 201103L
       void
-      splice(const_iterator __position, list& __x)
+      splice(const_iterator __position, list& __x) noexcept
       { this->splice(__position, std::move(__x)); }
 
       void
       splice(const_iterator __position, list& __x, const_iterator __i)
       { this->splice(__position, std::move(__x), __i); }
 #endif
 
       void
 #if __cplusplus >= 201103L
-      splice(const_iterator __position, list&& __x, const_iterator __i)
+      splice(const_iterator __position, list&& __x, const_iterator __i) noexcept
 #else
       splice(iterator __position, list& __x, iterator __i)
 #endif
       {
 	// We used to perform the splice_alloc check:  not anymore, redundant
 	// after implementing the relevant bits of N1599.
 
 	// _GLIBCXX_RESOLVE_LIB_DEFECTS
 	_Base::splice(__position.base(), _GLIBCXX_MOVE(__x._M_base()),
 		      __i.base());
       }
 
       void
 #if __cplusplus >= 201103L
       splice(const_iterator __position, list&& __x, const_iterator __first,
-	     const_iterator __last)
+	     const_iterator __last) noexcept
 #else
       splice(iterator __position, list& __x, iterator __first,
 	     iterator __last)
 #endif
       {
 	// We used to perform the splice_alloc check:  not anymore, redundant
 	// after implementing the relevant bits of N1599.
 
 	_Base::splice(__position.base(), _GLIBCXX_MOVE(__x._M_base()),
 		      __first.base(), __last.base());
       }
 
 #if __cplusplus >= 201103L
       void
       splice(const_iterator __position, list& __x,
-	     const_iterator __first, const_iterator __last)
+	     const_iterator __first, const_iterator __last) noexcept
       { this->splice(__position, std::move(__x), __first, __last); }
 #endif
 
       void
       remove(const _Tp& __value)
       {
 	for (iterator __x = begin(); __x != end(); )
 	  {
 	    if (*__x == __value)
 	      __x = erase(__x);
Index: include/std/array
===================================================================
--- include/std/array	(revision 202699)
+++ include/std/array	(working copy)
@@ -162,21 +162,21 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
       size() const noexcept { return _Nm; }
 
       constexpr size_type 
       max_size() const noexcept { return _Nm; }
 
       constexpr bool 
       empty() const noexcept { return size() == 0; }
 
       // Element access.
       reference
-      operator[](size_type __n)
+      operator[](size_type __n) noexcept
       { return _AT_Type::_S_ref(_M_elems, __n); }
 
       constexpr const_reference
       operator[](size_type __n) const noexcept
       { return _AT_Type::_S_ref(_M_elems, __n); }
 
       reference
       at(size_type __n)
       {
 	if (__n >= _Nm)
@@ -188,33 +188,33 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
       at(size_type __n) const
       {
 	// Result of conditional expression must be an lvalue so use
 	// boolean ? lvalue : (throw-expr, lvalue)
 	return __n < _Nm ? _AT_Type::_S_ref(_M_elems, __n)
 	  : (std::__throw_out_of_range(__N("array::at")),
 	     _AT_Type::_S_ref(_M_elems, 0));
       }
 
       reference 
-      front()
+      front() noexcept
       { return *begin(); }
 
       constexpr const_reference 
-      front() const
+      front() const noexcept
       { return _AT_Type::_S_ref(_M_elems, 0); }
 
       reference 
-      back()
+      back() noexcept
       { return _Nm ? *(end() - 1) : *end(); }
 
       constexpr const_reference 
-      back() const
+      back() const noexcept
       { 
 	return _Nm ? _AT_Type::_S_ref(_M_elems, _Nm - 1) 
  	           : _AT_Type::_S_ref(_M_elems, 0);
       }
 
       pointer
       data() noexcept
       { return std::__addressof(_AT_Type::_S_ref(_M_elems, 0)); }
 
       const_pointer
Index: testsuite/23_containers/list/operations/5.cc
===================================================================
--- testsuite/23_containers/list/operations/5.cc	(revision 202699)
+++ testsuite/23_containers/list/operations/5.cc	(working copy)
@@ -1,31 +0,0 @@ 
-// 2006-01-19  Paolo Carlini  <pcarlini@suse.de>
-
-// Copyright (C) 2006-2013 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 "5.h"
-#include <list>
-
-int main()
-{
-  typedef int value_type;
-  typedef __gnu_test::uneq_allocator<value_type> allocator_type;
-  typedef std::list<value_type, allocator_type> list_type;
-
-  operations05<list_type>();
-  return 0;
-}
Index: testsuite/23_containers/list/operations/5.h
===================================================================
--- testsuite/23_containers/list/operations/5.h	(revision 202699)
+++ testsuite/23_containers/list/operations/5.h	(working copy)
@@ -1,134 +0,0 @@ 
-// 2006-01-19  Paolo Carlini  <pcarlini@suse.de>
-
-// Copyright (C) 2006-2013 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/>.
-
-// 23.2.2.4 list operations [lib.list.ops]
-
-#include <stdexcept>
-#include <testsuite_hooks.h>
-#include <testsuite_allocator.h>
-
-// Check the splice (and merge) bits of N1599.
-template<typename _Tp>
-void
-operations05()
-{
-  bool test __attribute__((unused)) = true;
-  
-  typedef _Tp list_type;
-  typedef typename list_type::allocator_type allocator_type;
-
-  const int data1[] = {1, 2, 3, 4, 5};
-  const int data2[] = {6, 7, 8, 9, 10};
-  const size_t N1 = sizeof(data1) / sizeof(int);
-  const size_t N2 = sizeof(data2) / sizeof(int);
-  
-  allocator_type alloc01(1), alloc02(2);
-
-  list_type l01(data1, data1 + N1, alloc01);
-  const list_type l01_ref = l01;
-
-  list_type l02(data2, data2 + N2, alloc02);
-  const list_type l02_ref = l02;
-
-  bool catched = false;
-
-  try
-    {
-      l01.splice(l01.begin(), l02);
-    }
-  catch(std::runtime_error&)
-    {
-      catched = true;
-    }
-  catch(...)
-    {
-      VERIFY( false );
-    }
-  VERIFY( catched );
-  VERIFY( l01 == l01_ref );
-  VERIFY( l02 == l02_ref );
-  
-  catched = false;
-  try
-    {
-      l01.splice(l01.begin(), l02, l02.begin());
-    }
-  catch(std::runtime_error&)
-    {
-      catched = true;
-    }
-  catch(...)
-    {
-      VERIFY( false );
-    }
-  VERIFY( catched );
-  VERIFY( l01 == l01_ref );
-  VERIFY( l02 == l02_ref );
-
-  catched = false;
-  try
-    {
-      l01.splice(l01.begin(), l02, l02.begin(), l02.end());
-    }
-  catch(std::runtime_error&)
-    {
-      catched = true;
-    }
-  catch(...)
-    {
-      VERIFY( false );
-    }
-  VERIFY( catched );
-  VERIFY( l01 == l01_ref );
-  VERIFY( l02 == l02_ref );
-
-  catched = false;
-  try
-    {
-      l01.merge(l02);
-    }
-  catch(std::runtime_error&)
-    {
-      catched = true;
-    }
-  catch(...)
-    {
-      VERIFY( false );
-    }
-  VERIFY( catched );
-  VERIFY( l01 == l01_ref );
-  VERIFY( l02 == l02_ref );
-
-  catched = false;
-  try
-    {
-      l01.merge(l02, std::less<int>());
-    }
-  catch(std::runtime_error&)
-    {
-      catched = true;
-    }
-  catch(...)
-    {
-      VERIFY( false );
-    }
-  VERIFY( catched );
-  VERIFY( l01 == l01_ref );
-  VERIFY( l02 == l02_ref );
-}