Patchwork [v3] Fix libstdc++/54577

login
register
mail settings
Submitter Paolo Carlini
Date May 10, 2013, 2:17 p.m.
Message ID <518D0177.8090709@oracle.com>
Download mbox | patch
Permalink /patch/242993/
State New
Headers show

Comments

Paolo Carlini - May 10, 2013, 2:17 p.m.
Hi,

this is the issue about the signatures of the erase member functions of 
the sequence containers. Mostly rather straightfoward stuff within the 
limits of the current infrastructure: the various _M_const_case are 
normally simple enough, I only mention the rather ugly std::vector one, 
required otherwise an ext_pointer testcase fails: I suppose that 
handling these issues in a proper way will happen together with changing 
the vector::pointer typedef to the conforming:

     typedef typename _Alloc_traits::pointer  pointer;

and I suppose Jonathan has the issue "under control". Something similar 
is true for the other containers.

Tested x86_64-linux.

Thanks,
Paolo.

////////////////////////////
2013-05-10  Paolo Carlini  <paolo.carlini@oracle.com>

	PR libstdc++/54577
	* include/bits/stl_deque.h (erase): Fix signatures in C++11 mode.
	(_Deque_iterator<>::_M_const_cast): Add.
	(deque<>::_M_erase): Declare.
	* include/bits/deque.tcc: ... and define.
	* include/bits/stl_list.h (erase): Fix signatures in C++11 mode.
	(_List_const_iterator<>::_M_const_cast): Add.
	* include/bits/list.tcc (erase (iterator)): Fix.
	* include/bits/stl_iterator.h (__normal_iterator<>::_M_const_cast):
	Add; include <ext/cast.h>.
	* include/bits/stl_vector.h (erase): Fix signatures in C++11 mode.
	(vector<>::_M_erase): Declare.
	* include/bits/stl_bvector.h: Likewise.
	* include/bits/vector.tcc (vector<>::_M_erase): Define.
	* include/ext/vstring.h (erase): Fix signatures in C++11 mode.
	* include/debug/deque: Adjust.
	* include/debug/list: Likewise.
	* include/debug/vector: Likewise.
	* include/profile/deque: Likewise.
	* include/profile/list: Likewise.
	* include/profile/vector: Likewise.
	* testsuite/util/exception/safety.h (erase_base<deque>,
	erase_base<deque>, erase_base<vector>): Remove.
	(erase_base<__versa_string>): Update.
	* testsuite/ext/vstring/modifiers/char/54577.cc: New.
	* testsuite/ext/vstring/modifiers/wchar_t/54577.cc: Likewise.
	* testsuite/23_containers/deque/modifiers/erase/54577.cc: Likewise.
	* testsuite/23_containers/list/modifiers/erase/54577.cc: Likewise.
	* testsuite/23_containers/vector/bool/modifiers/erase/54577.cc:
	Likewise.
	* testsuite/23_containers/vector/modifiers/erase/54577.cc: Likewise.
	* testsuite/23_containers/deque/requirements/dr438/assign_neg.cc:
	Adjust dg-error line numbers.
	* testsuite/23_containers/deque/requirements/dr438/
	constructor_1_neg.cc: Likewise.
	* testsuite/23_containers/deque/requirements/dr438/
	constructor_2_neg.cc: Likewise.
	* testsuite/23_containers/deque/requirements/dr438/insert_neg.cc:
	Likewise.
	* testsuite/23_containers/list/requirements/dr438/assign_neg.cc:
	Likewise.
	* testsuite/23_containers/list/requirements/dr438/
	constructor_1_neg.cc: Likewise.
	* testsuite/23_containers/list/requirements/dr438/
	constructor_2_neg.cc: Likewise.
	* testsuite/23_containers/list/requirements/dr438/
	insert_neg.cc: Likewise.
	* testsuite/23_containers/vector/requirements/dr438/assign_neg.cc:
	Likewise.
	* testsuite/23_containers/vector/requirements/dr438/
	constructor_1_neg.cc: Likewise.
	* testsuite/23_containers/vector/requirements/dr438/
	constructor_2_neg.cc: Likewise.
	* testsuite/23_containers/vector/requirements/dr438/insert_neg.cc:
	Likewise.
Paolo Carlini - May 14, 2013, 12:40 p.m.
On 05/10/2013 04:17 PM, Paolo Carlini wrote:
> this is the issue about the signatures of the erase member functions 
> of the sequence containers. Mostly rather straightfoward stuff within 
> the limits of the current infrastructure: the various _M_const_case 
> are normally simple enough, I only mention the rather ugly std::vector 
> one, required otherwise an ext_pointer testcase fails: I suppose that 
> handling these issues in a proper way will happen together with 
> changing the vector::pointer typedef to the conforming:
>
>     typedef typename _Alloc_traits::pointer  pointer;
Oops, the PR that Jonathan just filed made me notice that in fact 
std::vector must be correct, because _Base::pointer actually means using 
_Alloc_traits.

Then I suppose that the correct way to move forward to C++11 the 
ext/pointer.h stuff would be adding a pointer_traits specialization for 
those pointer-like types, which would also wrap the cast operations in 
pointer_to. Then, in __normal_iterator::_M_const_cast use pointer_traits.

Paolo.
Paolo Carlini - May 14, 2013, 12:51 p.m.
On 05/14/2013 02:40 PM, Paolo Carlini wrote:
> Then I suppose that the correct way to move forward to C++11 the 
> ext/pointer.h stuff would be adding a pointer_traits specialization 
> for those pointer-like types, which would also wrap the cast 
> operations in pointer_to. Then, in __normal_iterator::_M_const_cast 
> use pointer_traits.
... and even more interestingly, looks like Jonathan already did most of 
this, at the end of ext/pointer.h. Oh my ;)

Paolo.
Jonathan Wakely - May 14, 2013, 1:41 p.m.
On 14 May 2013 13:51, Paolo Carlini wrote:
> On 05/14/2013 02:40 PM, Paolo Carlini wrote:
>>
>> Then I suppose that the correct way to move forward to C++11 the
>> ext/pointer.h stuff would be adding a pointer_traits specialization for
>> those pointer-like types, which would also wrap the cast operations in
>> pointer_to. Then, in __normal_iterator::_M_const_cast use pointer_traits.
>
> ... and even more interestingly, looks like Jonathan already did most of
> this, at the end of ext/pointer.h. Oh my ;)

I forgot that I had marked your first mail in this thread, meaning to
come back to it when I had time to understand the vector::pointer
issue that I supposedly had under control :-)

I'd forgotten about the existence of __const_pointer_cast etc. in
<ext/cast.h> ... I agree that in C++11 mode
__normal_iterator::_M_const_cast should not rely on the existence of a
get() member on the custom pointer, because that's not required to
exist, and you can do it like this instead:

using PT = pointer_traits<ToType>;
auto to = PT::pointer_to(const_cast<PT::element_type&>(*from));
Paolo Carlini - May 14, 2013, 1:50 p.m.
Hi,

On 05/14/2013 03:41 PM, Jonathan Wakely wrote:
> I'd forgotten about the existence of __const_pointer_cast etc. in 
> <ext/cast.h> ...
Me too ;) I resorted to it as a sort of temporary kludge.
> I agree that in C++11 mode __normal_iterator::_M_const_cast should not 
> rely on the existence of a get() member on the custom pointer, because 
> that's not required to exist, and you can do it like this instead: 
> using PT = pointer_traits<ToType>; auto to = 
> PT::pointer_to(const_cast<PT::element_type&>(*from)); 
Indeed, I have something like this in my tree too.

Thanks!
Paolo.
Jonathan Wakely - May 19, 2013, 12:09 a.m.
On 10 May 2013 15:17, Paolo Carlini wrote:
> Hi,
>
> this is the issue about the signatures of the erase member functions of the
> sequence containers.

This only does the erase() functions, is there any reason not to do
the same for the insert() functions too, which was also changed by
N2350?
Paolo Carlini - May 19, 2013, 12:25 a.m.
On 05/19/2013 02:09 AM, Jonathan Wakely wrote:
> On 10 May 2013 15:17, Paolo Carlini wrote:
>> Hi,
>>
>> this is the issue about the signatures of the erase member functions of the
>> sequence containers.
> This only does the erase() functions, is there any reason not to do
> the same for the insert() functions too, which was also changed by
> N2350?
I can't imagine any reason, no. Apparently people wanted erase first and 
we also had a Bugzilla, thus I found the time to do those. Surely sooner 
or later we have to fix all the signatures.

Paolo.
Jonathan Wakely - May 19, 2013, 10:45 a.m.
On 19 May 2013 01:25, Paolo Carlini wrote:
> On 05/19/2013 02:09 AM, Jonathan Wakely wrote:
>>
>> On 10 May 2013 15:17, Paolo Carlini wrote:
>>>
>>> Hi,
>>>
>>> this is the issue about the signatures of the erase member functions of
>>> the
>>> sequence containers.
>>
>> This only does the erase() functions, is there any reason not to do
>> the same for the insert() functions too, which was also changed by
>> N2350?
>
> I can't imagine any reason, no. Apparently people wanted erase first and we
> also had a Bugzilla, thus I found the time to do those. Surely sooner or
> later we have to fix all the signatures.

OK, cool, I might do it soon.  I wanted to add
std::vector<bool>::emplace() (for LWG 2187) and wanted
insert(const_iterator, bool).

Patch

Index: include/bits/deque.tcc
===================================================================
--- include/bits/deque.tcc	(revision 198770)
+++ include/bits/deque.tcc	(working copy)
@@ -191,7 +191,7 @@ 
   template <typename _Tp, typename _Alloc>
     typename deque<_Tp, _Alloc>::iterator
     deque<_Tp, _Alloc>::
-    erase(iterator __position)
+    _M_erase(iterator __position)
     {
       iterator __next = __position;
       ++__next;
@@ -214,7 +214,7 @@ 
   template <typename _Tp, typename _Alloc>
     typename deque<_Tp, _Alloc>::iterator
     deque<_Tp, _Alloc>::
-    erase(iterator __first, iterator __last)
+    _M_erase(iterator __first, iterator __last)
     {
       if (__first == __last)
 	return __first;
Index: include/bits/list.tcc
===================================================================
--- include/bits/list.tcc	(revision 198770)
+++ include/bits/list.tcc	(working copy)
@@ -106,10 +106,18 @@ 
   template<typename _Tp, typename _Alloc>
     typename list<_Tp, _Alloc>::iterator
     list<_Tp, _Alloc>::
+#if __cplusplus >= 201103L
+    erase(const_iterator __position)
+#else
     erase(iterator __position)
+#endif
     {
       iterator __ret = iterator(__position._M_node->_M_next);
+#if __cplusplus >= 201103L
+      _M_erase(__position._M_const_cast());
+#else
       _M_erase(__position);
+#endif
       return __ret;
     }
 
Index: include/bits/stl_bvector.h
===================================================================
--- include/bits/stl_bvector.h	(revision 198770)
+++ include/bits/stl_bvector.h	(working copy)
@@ -308,6 +308,10 @@ 
     _Bit_const_iterator(const _Bit_iterator& __x)
     : _Bit_iterator_base(__x._M_p, __x._M_offset) { }
 
+    _Bit_iterator
+    _M_const_cast() const
+    { return _Bit_iterator(_M_p, _M_offset); }
+
     const_reference
     operator*() const
     { return _Bit_reference(_M_p, 1UL << _M_offset); }
@@ -898,21 +902,22 @@ 
     { --this->_M_impl._M_finish; }
 
     iterator
+#if __cplusplus >= 201103L
+    erase(const_iterator __position)
+    { return _M_erase(__position._M_const_cast()); }
+#else
     erase(iterator __position)
-    {
-      if (__position + 1 != end())
-        std::copy(__position + 1, end(), __position);
-      --this->_M_impl._M_finish;
-      return __position;
-    }
+    { return _M_erase(__position); }
+#endif
 
     iterator
+#if __cplusplus >= 201103L
+    erase(const_iterator __first, const_iterator __last)
+    { return _M_erase(__first._M_const_cast(), __last._M_const_cast()); }
+#else
     erase(iterator __first, iterator __last)
-    {
-      if (__first != __last)
-	_M_erase_at_end(std::copy(__last, end(), __first));
-      return __first;
-    }
+    { return _M_erase(__first, __last); }
+#endif
 
     void
     resize(size_type __new_size, bool __x = bool())
@@ -1124,6 +1129,12 @@ 
     void
     _M_erase_at_end(iterator __pos)
     { this->_M_impl._M_finish = __pos; }
+
+    iterator
+    _M_erase(iterator __pos);
+
+    iterator
+    _M_erase(iterator __first, iterator __last);
   };
 
 _GLIBCXX_END_NAMESPACE_CONTAINER
Index: include/bits/stl_deque.h
===================================================================
--- include/bits/stl_deque.h	(revision 198770)
+++ include/bits/stl_deque.h	(working copy)
@@ -136,6 +136,10 @@ 
       : _M_cur(__x._M_cur), _M_first(__x._M_first),
         _M_last(__x._M_last), _M_node(__x._M_node) { }
 
+      iterator
+      _M_const_cast() const
+      { return iterator(_M_cur, _M_node); }
+
       reference
       operator*() const
       { return *_M_cur; }
@@ -1562,7 +1566,13 @@ 
        *  Managing the pointer is the user's responsibility.
        */
       iterator
-      erase(iterator __position);
+#if __cplusplus >= 201103L
+      erase(const_iterator __position)
+      { return _M_erase(__position._M_const_cast()); }
+#else
+      erase(iterator __position)
+      { return _M_erase(__position); }
+#endif
 
       /**
        *  @brief  Remove a range of elements.
@@ -1581,7 +1591,13 @@ 
        *  way.  Managing the pointer is the user's responsibility.
        */
       iterator
-      erase(iterator __first, iterator __last);
+#if __cplusplus >= 201103L
+      erase(const_iterator __first, const_iterator __last)
+      { return _M_erase(__first._M_const_cast(), __last._M_const_cast()); }
+#else
+      erase(iterator __first, iterator __last)
+      { return _M_erase(__first, __last); }
+#endif
 
       /**
        *  @brief  Swaps data with another %deque.
@@ -1873,6 +1889,12 @@ 
 	this->_M_impl._M_finish = __pos;
       }
 
+      iterator
+      _M_erase(iterator __pos);
+
+      iterator
+      _M_erase(iterator __first, iterator __last);
+
 #if __cplusplus >= 201103L
       // Called by resize(sz).
       void
Index: include/bits/stl_iterator.h
===================================================================
--- include/bits/stl_iterator.h	(revision 198770)
+++ include/bits/stl_iterator.h	(working copy)
@@ -63,6 +63,7 @@ 
 #include <bits/cpp_type_traits.h>
 #include <ext/type_traits.h>
 #include <bits/move.h>
+#include <ext/cast.h>
 
 namespace std _GLIBCXX_VISIBILITY(default)
 {
@@ -733,6 +734,12 @@ 
 		      _Container>::__type>& __i)
         : _M_current(__i.base()) { }
 
+      __normal_iterator<typename _Container::pointer, _Container>
+      _M_const_cast() const
+      { return __normal_iterator<typename _Container::pointer, _Container>
+	  (__gnu_cxx::__const_pointer_cast<typename _Container::pointer>
+	   (_M_current)); }
+
       // Forward iterator requirements
       reference
       operator*() const
Index: include/bits/stl_list.h
===================================================================
--- include/bits/stl_list.h	(revision 198770)
+++ include/bits/stl_list.h	(working copy)
@@ -219,6 +219,10 @@ 
       _List_const_iterator(const iterator& __x)
       : _M_node(__x._M_node) { }
 
+      iterator
+      _M_const_cast() const
+      { return iterator(const_cast<__detail::_List_node_base*>(_M_node)); }
+
       // Must downcast from List_node_base to _List_node to get to
       // _M_data.
       reference
@@ -1169,7 +1173,11 @@ 
        *  any way.  Managing the pointer is the user's responsibility.
        */
       iterator
+#if __cplusplus >= 201103L
+      erase(const_iterator __position);
+#else
       erase(iterator __position);
+#endif
 
       /**
        *  @brief  Remove a range of elements.
@@ -1190,11 +1198,19 @@ 
        *  is the user's responsibility.
        */
       iterator
+#if __cplusplus >= 201103L
+      erase(const_iterator __first, const_iterator __last)
+#else
       erase(iterator __first, iterator __last)
+#endif
       {
 	while (__first != __last)
 	  __first = erase(__first);
+#if __cplusplus >= 201103L
+	return __last._M_const_cast();
+#else
 	return __last;
+#endif
       }
 
       /**
Index: include/bits/stl_vector.h
===================================================================
--- include/bits/stl_vector.h	(revision 198770)
+++ include/bits/stl_vector.h	(working copy)
@@ -1072,7 +1072,13 @@ 
        *  the pointer is the user's responsibility.
        */
       iterator
-      erase(iterator __position);
+#if __cplusplus >= 201103L
+      erase(const_iterator __position)
+      { return _M_erase(__position._M_const_cast()); }
+#else
+      erase(iterator __position)
+      { return _M_erase(__position); }
+#endif
 
       /**
        *  @brief  Remove a range of elements.
@@ -1093,7 +1099,13 @@ 
        *  Managing the pointer is the user's responsibility.
        */
       iterator
-      erase(iterator __first, iterator __last);
+#if __cplusplus >= 201103L
+      erase(const_iterator __first, const_iterator __last)
+      { return _M_erase(__first._M_const_cast(), __last._M_const_cast()); }
+#else
+      erase(iterator __first, iterator __last)
+      { return _M_erase(__first, __last); }
+#endif
 
       /**
        *  @brief  Swaps data with another %vector.
@@ -1353,6 +1365,12 @@ 
 	this->_M_impl._M_finish = __pos;
       }
 
+      iterator
+      _M_erase(iterator __position);
+
+      iterator
+      _M_erase(iterator __first, iterator __last);
+
 #if __cplusplus >= 201103L
     private:
       // Constant-time move assignment when source object's memory can be
Index: include/bits/vector.tcc
===================================================================
--- include/bits/vector.tcc	(revision 198770)
+++ include/bits/vector.tcc	(working copy)
@@ -132,7 +132,7 @@ 
   template<typename _Tp, typename _Alloc>
     typename vector<_Tp, _Alloc>::iterator
     vector<_Tp, _Alloc>::
-    erase(iterator __position)
+    _M_erase(iterator __position)
     {
       if (__position + 1 != end())
 	_GLIBCXX_MOVE3(__position + 1, end(), __position);
@@ -144,7 +144,7 @@ 
   template<typename _Tp, typename _Alloc>
     typename vector<_Tp, _Alloc>::iterator
     vector<_Tp, _Alloc>::
-    erase(iterator __first, iterator __last)
+    _M_erase(iterator __first, iterator __last)
     {
       if (__first != __last)
 	{
@@ -790,6 +790,27 @@ 
 	}
     }
 
+  template<typename _Alloc>
+    typename vector<bool, _Alloc>::iterator
+    vector<bool, _Alloc>::
+    _M_erase(iterator __position)
+    {
+      if (__position + 1 != end())
+        std::copy(__position + 1, end(), __position);
+      --this->_M_impl._M_finish;
+      return __position;
+    }
+
+  template<typename _Alloc>
+    typename vector<bool, _Alloc>::iterator
+    vector<bool, _Alloc>::
+    _M_erase(iterator __first, iterator __last)
+    {
+      if (__first != __last)
+	_M_erase_at_end(std::copy(__last, end(), __first));
+      return __first;
+    }
+
 #if __cplusplus >= 201103L
   template<typename _Alloc>
     bool
Index: include/debug/deque
===================================================================
--- include/debug/deque	(revision 198770)
+++ include/debug/deque	(working copy)
@@ -456,11 +456,19 @@ 
       }
 
       iterator
-      erase(iterator __position)
+#if __cplusplus >= 201103L
+      erase(const_iterator __position)
+#else
+      erase(iterator __position)	
+#endif
       {
 	__glibcxx_check_erase(__position);
+#if __cplusplus >= 201103L
+	_Base_const_iterator __victim = __position.base();
+#else
 	_Base_iterator __victim = __position.base();
-	if (__victim == _Base::begin() || __victim == _Base::end()-1)
+#endif
+	if (__victim == _Base::begin() || __victim == _Base::end() - 1)
 	  {
 	    this->_M_invalidate_if(_Equal(__victim));
 	    return iterator(_Base::erase(__victim), this);
@@ -474,19 +482,27 @@ 
       }
 
       iterator
+#if __cplusplus >= 201103L
+      erase(const_iterator __first, const_iterator __last)
+#else
       erase(iterator __first, iterator __last)
+#endif
       {
 	// _GLIBCXX_RESOLVE_LIB_DEFECTS
 	// 151. can't currently clear() empty container
 	__glibcxx_check_erase_range(__first, __last);
 
 	if (__first.base() == __last.base())
+#if __cplusplus >= 201103L
+	  return iterator(__first.base()._M_const_cast(), this);
+#else
 	  return __first;
+#endif
         else if (__first.base() == _Base::begin()
 		 || __last.base() == _Base::end())
 	  {
 	    this->_M_detach_singular();
-	    for (_Base_iterator __position = __first.base();
+	    for (_Base_const_iterator __position = __first.base();
 		 __position != __last.base(); ++__position)
 	      {
 		this->_M_invalidate_if(_Equal(__position));
Index: include/debug/list
===================================================================
--- include/debug/list	(revision 198770)
+++ include/debug/list	(working copy)
@@ -431,35 +431,48 @@ 
 
     private:
       _Base_iterator
+#if __cplusplus >= 201103L
+      _M_erase(_Base_const_iterator __position)
+#else
       _M_erase(_Base_iterator __position)
+#endif
       {
 	this->_M_invalidate_if(_Equal(__position));
 	return _Base::erase(__position);
       }
+
     public:
       iterator
+#if __cplusplus >= 201103L
+      erase(const_iterator __position)
+#else
       erase(iterator __position)
+#endif
       {
 	__glibcxx_check_erase(__position);
 	return iterator(_M_erase(__position.base()), this);
       }
 
       iterator
-      erase(iterator __position, iterator __last)
+#if __cplusplus >= 201103L
+      erase(const_iterator __first, const_iterator __last)
+#else
+      erase(iterator __first, iterator __last)
+#endif
       {
 	// _GLIBCXX_RESOLVE_LIB_DEFECTS
 	// 151. can't currently clear() empty container
-	__glibcxx_check_erase_range(__position, __last);
-	for (_Base_iterator __victim = __position.base();
+	__glibcxx_check_erase_range(__first, __last);
+	for (_Base_const_iterator __victim = __first.base();
 	     __victim != __last.base(); ++__victim)
 	  {
 	    _GLIBCXX_DEBUG_VERIFY(__victim != _Base::end(),
 			          _M_message(__gnu_debug::__msg_valid_range)
-				  ._M_iterator(__position, "position")
+				  ._M_iterator(__first, "position")
 				  ._M_iterator(__last, "last"));
 	    this->_M_invalidate_if(_Equal(__victim));
 	  }
-	return iterator(_Base::erase(__position.base(), __last.base()), this);
+	return iterator(_Base::erase(__first.base(), __last.base()), this);
       }
 
       void
Index: include/debug/vector
===================================================================
--- include/debug/vector	(revision 198770)
+++ include/debug/vector	(working copy)
@@ -514,7 +514,11 @@ 
 	}
 
       iterator
+#if __cplusplus >= 201103L
+      erase(const_iterator __position)
+#else
       erase(iterator __position)
+#endif
       {
 	__glibcxx_check_erase(__position);
 	difference_type __offset = __position.base() - _Base::begin();
@@ -524,7 +528,11 @@ 
       }
 
       iterator
+#if __cplusplus >= 201103L
+      erase(const_iterator __first, const_iterator __last)
+#else
       erase(iterator __first, iterator __last)
+#endif
       {
 	// _GLIBCXX_RESOLVE_LIB_DEFECTS
 	// 151. can't currently clear() empty container
@@ -539,7 +547,11 @@ 
 	    return iterator(__res, this);
 	  }
 	else
+#if __cplusplus >= 201103L
+	  return iterator(__first.base()._M_const_cast(), this);
+#else
 	  return __first;
+#endif
       }
 
       void
Index: include/ext/vstring.h
===================================================================
--- include/ext/vstring.h	(revision 198770)
+++ include/ext/vstring.h	(working copy)
@@ -1128,7 +1128,11 @@ 
        *  value of the string doesn't change if an error is thrown.
       */
       iterator
-      erase(iterator __position)
+#if __cplusplus >= 201103L
+      erase(const_iterator __position)
+#else
+      erase(iterator __position)	
+#endif
       {
 	_GLIBCXX_DEBUG_PEDASSERT(__position >= _M_ibegin()
 				 && __position < _M_iend());
@@ -1149,7 +1153,11 @@ 
        *  is thrown.
       */
       iterator
+#if __cplusplus >= 201103L
+      erase(const_iterator __first, const_iterator __last)
+#else
       erase(iterator __first, iterator __last)
+#endif
       {
 	_GLIBCXX_DEBUG_PEDASSERT(__first >= _M_ibegin() && __first <= __last
 				 && __last <= _M_iend());
Index: include/profile/deque
===================================================================
--- include/profile/deque	(revision 198770)
+++ include/profile/deque	(working copy)
@@ -379,25 +379,25 @@ 
       }
 
       iterator
-      erase(iterator __position)
+#if __cplusplus >= 201103L
+      erase(const_iterator __position)
+#else
+      erase(iterator __position)	
+#endif
       {
-	if (__position == begin() || __position == end()-1)
-	  {
-	    return iterator(_Base::erase(__position));
-	  }
-	else
-	  {
-	    typename _Base::iterator __res = _Base::erase(__position);
-	    return iterator(__res);
-	  }
+	return _Base::erase(__position);
       }
 
       iterator
+#if __cplusplus >= 201103L
+      erase(const_iterator __first, const_iterator __last)
+#else
       erase(iterator __first, iterator __last)
+#endif
       {
 	// _GLIBCXX_RESOLVE_LIB_DEFECTS
 	// 151. can't currently clear() empty container
-        return iterator(_Base::erase(__first, __last));
+        return _Base::erase(__first, __last);
       }
 
       void
Index: include/profile/list
===================================================================
--- include/profile/list	(revision 198770)
+++ include/profile/list	(working copy)
@@ -389,11 +389,19 @@ 
 	}
 
       iterator
+#if __cplusplus >= 201103L
+      erase(const_iterator __position)
+#else
       erase(iterator __position)
+#endif
       {	return iterator(_Base::erase(__position.base()), this); }
 
       iterator
+#if __cplusplus >= 201103L
+      erase(const_iterator __position, const_iterator __last)
+#else
       erase(iterator __position, iterator __last)
+#endif
       {
 	// _GLIBCXX_RESOLVE_LIB_DEFECTS
 	// 151. can't currently clear() empty container
Index: include/profile/vector
===================================================================
--- include/profile/vector	(revision 198770)
+++ include/profile/vector	(working copy)
@@ -425,14 +425,22 @@ 
 
 
       iterator
-      erase(iterator __position)
+#if __cplusplus >= 201103L
+      erase(const_iterator __position)
+#else
+      erase(iterator __position)	
+#endif
       {
 	typename _Base::iterator __res = _Base::erase(__position.base());
 	return iterator(__res, this);
       }
 
       iterator
+#if __cplusplus >= 201103L
+      erase(const_iterator __first, const_iterator __last)
+#else
       erase(iterator __first, iterator __last)
+#endif
       {
 	// _GLIBCXX_RESOLVE_LIB_DEFECTS
 	// 151. can't currently clear() empty container
Index: testsuite/23_containers/deque/modifiers/erase/54577.cc
===================================================================
--- testsuite/23_containers/deque/modifiers/erase/54577.cc	(revision 0)
+++ testsuite/23_containers/deque/modifiers/erase/54577.cc	(working copy)
@@ -0,0 +1,33 @@ 
+// { dg-options "-std=gnu++11" }
+// { dg-do compile }
+
+// Copyright (C) 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 <deque>
+
+void test01() 
+{
+  std::deque<int> d1;
+  d1.push_back(1);
+  d1.erase(d1.cbegin());
+
+  std::deque<int> d2;
+  d2.push_back(2);
+  d2.push_back(3);
+  d2.erase(d2.cbegin(), d2.cend());
+}
Index: testsuite/23_containers/deque/requirements/dr438/assign_neg.cc
===================================================================
--- testsuite/23_containers/deque/requirements/dr438/assign_neg.cc	(revision 198770)
+++ testsuite/23_containers/deque/requirements/dr438/assign_neg.cc	(working copy)
@@ -18,7 +18,7 @@ 
 // <http://www.gnu.org/licenses/>.
 
 // { dg-do compile }
-// { dg-error "no matching" "" { target *-*-* } 1698 }
+// { dg-error "no matching" "" { target *-*-* } 1714 }
 
 #include <deque>
 
Index: testsuite/23_containers/deque/requirements/dr438/constructor_1_neg.cc
===================================================================
--- testsuite/23_containers/deque/requirements/dr438/constructor_1_neg.cc	(revision 198770)
+++ testsuite/23_containers/deque/requirements/dr438/constructor_1_neg.cc	(working copy)
@@ -18,7 +18,7 @@ 
 // <http://www.gnu.org/licenses/>.
 
 // { dg-do compile }
-// { dg-error "no matching" "" { target *-*-* } 1631 }
+// { dg-error "no matching" "" { target *-*-* } 1647 }
 
 #include <deque>
 
Index: testsuite/23_containers/deque/requirements/dr438/constructor_2_neg.cc
===================================================================
--- testsuite/23_containers/deque/requirements/dr438/constructor_2_neg.cc	(revision 198770)
+++ testsuite/23_containers/deque/requirements/dr438/constructor_2_neg.cc	(working copy)
@@ -18,7 +18,7 @@ 
 // <http://www.gnu.org/licenses/>.
 
 // { dg-do compile }
-// { dg-error "no matching" "" { target *-*-* } 1631 }
+// { dg-error "no matching" "" { target *-*-* } 1647 }
 
 #include <deque>
 #include <utility>
Index: testsuite/23_containers/deque/requirements/dr438/insert_neg.cc
===================================================================
--- testsuite/23_containers/deque/requirements/dr438/insert_neg.cc	(revision 198770)
+++ testsuite/23_containers/deque/requirements/dr438/insert_neg.cc	(working copy)
@@ -18,7 +18,7 @@ 
 // <http://www.gnu.org/licenses/>.
 
 // { dg-do compile }
-// { dg-error "no matching" "" { target *-*-* } 1782 }
+// { dg-error "no matching" "" { target *-*-* } 1798 }
 
 #include <deque>
 
Index: testsuite/23_containers/list/modifiers/erase/54577.cc
===================================================================
--- testsuite/23_containers/list/modifiers/erase/54577.cc	(revision 0)
+++ testsuite/23_containers/list/modifiers/erase/54577.cc	(working copy)
@@ -0,0 +1,33 @@ 
+// { dg-options "-std=gnu++11" }
+// { dg-do compile }
+
+// Copyright (C) 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 <list>
+
+void test01() 
+{
+  std::list<int> l1;
+  l1.push_back(1);
+  l1.erase(l1.cbegin());
+
+  std::list<int> l2;
+  l2.push_back(2);
+  l2.push_back(3);
+  l2.erase(l2.cbegin(), l2.cend());
+}
Index: testsuite/23_containers/list/requirements/dr438/assign_neg.cc
===================================================================
--- testsuite/23_containers/list/requirements/dr438/assign_neg.cc	(revision 198770)
+++ testsuite/23_containers/list/requirements/dr438/assign_neg.cc	(working copy)
@@ -18,7 +18,7 @@ 
 // <http://www.gnu.org/licenses/>.
 
 // { dg-do compile }
-// { dg-error "no matching" "" { target *-*-* } 1529 }
+// { dg-error "no matching" "" { target *-*-* } 1545 }
 
 #include <list>
 
Index: testsuite/23_containers/list/requirements/dr438/constructor_1_neg.cc
===================================================================
--- testsuite/23_containers/list/requirements/dr438/constructor_1_neg.cc	(revision 198770)
+++ testsuite/23_containers/list/requirements/dr438/constructor_1_neg.cc	(working copy)
@@ -18,7 +18,7 @@ 
 // <http://www.gnu.org/licenses/>.
 
 // { dg-do compile }
-// { dg-error "no matching" "" { target *-*-* } 1481 }
+// { dg-error "no matching" "" { target *-*-* } 1497 }
 
 #include <list>
 
Index: testsuite/23_containers/list/requirements/dr438/constructor_2_neg.cc
===================================================================
--- testsuite/23_containers/list/requirements/dr438/constructor_2_neg.cc	(revision 198770)
+++ testsuite/23_containers/list/requirements/dr438/constructor_2_neg.cc	(working copy)
@@ -18,7 +18,7 @@ 
 // <http://www.gnu.org/licenses/>.
 
 // { dg-do compile }
-// { dg-error "no matching" "" { target *-*-* } 1481 }
+// { dg-error "no matching" "" { target *-*-* } 1497 }
 
 #include <list>
 #include <utility>
Index: testsuite/23_containers/list/requirements/dr438/insert_neg.cc
===================================================================
--- testsuite/23_containers/list/requirements/dr438/insert_neg.cc	(revision 198770)
+++ testsuite/23_containers/list/requirements/dr438/insert_neg.cc	(working copy)
@@ -18,7 +18,7 @@ 
 // <http://www.gnu.org/licenses/>.
 
 // { dg-do compile }
-// { dg-error "no matching" "" { target *-*-* } 1481 }
+// { dg-error "no matching" "" { target *-*-* } 1497 }
 
 #include <list>
 
Index: testsuite/23_containers/vector/bool/modifiers/erase/54577.cc
===================================================================
--- testsuite/23_containers/vector/bool/modifiers/erase/54577.cc	(revision 0)
+++ testsuite/23_containers/vector/bool/modifiers/erase/54577.cc	(working copy)
@@ -0,0 +1,33 @@ 
+// { dg-options "-std=gnu++11" }
+// { dg-do compile }
+
+// Copyright (C) 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 <vector>
+
+void test01() 
+{
+  std::vector<bool> vb1;
+  vb1.push_back(true);
+  vb1.erase(vb1.cbegin());
+
+  std::vector<bool> vb2;
+  vb2.push_back(false);
+  vb2.push_back(true);
+  vb2.erase(vb2.cbegin(), vb2.cend());
+}
Index: testsuite/23_containers/vector/modifiers/erase/54577.cc
===================================================================
--- testsuite/23_containers/vector/modifiers/erase/54577.cc	(revision 0)
+++ testsuite/23_containers/vector/modifiers/erase/54577.cc	(working copy)
@@ -0,0 +1,33 @@ 
+// { dg-options "-std=gnu++11" }
+// { dg-do compile }
+
+// Copyright (C) 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 <vector>
+
+void test01() 
+{
+  std::vector<int> v1;
+  v1.push_back(1);
+  v1.erase(v1.cbegin());
+
+  std::vector<int> v2;
+  v2.push_back(2);
+  v2.push_back(3);
+  v2.erase(v2.cbegin(), v2.cend());
+}
Index: testsuite/23_containers/vector/requirements/dr438/assign_neg.cc
===================================================================
--- testsuite/23_containers/vector/requirements/dr438/assign_neg.cc	(revision 198770)
+++ testsuite/23_containers/vector/requirements/dr438/assign_neg.cc	(working copy)
@@ -18,7 +18,7 @@ 
 // <http://www.gnu.org/licenses/>.
 
 // { dg-do compile }
-// { dg-error "no matching" "" { target *-*-* } 1240 }
+// { dg-error "no matching" "" { target *-*-* } 1252 }
 
 #include <vector>
 
Index: testsuite/23_containers/vector/requirements/dr438/constructor_1_neg.cc
===================================================================
--- testsuite/23_containers/vector/requirements/dr438/constructor_1_neg.cc	(revision 198770)
+++ testsuite/23_containers/vector/requirements/dr438/constructor_1_neg.cc	(working copy)
@@ -18,7 +18,7 @@ 
 // <http://www.gnu.org/licenses/>.
 
 // { dg-do compile }
-// { dg-error "no matching" "" { target *-*-* } 1166 }
+// { dg-error "no matching" "" { target *-*-* } 1178 }
 
 #include <vector>
 
Index: testsuite/23_containers/vector/requirements/dr438/constructor_2_neg.cc
===================================================================
--- testsuite/23_containers/vector/requirements/dr438/constructor_2_neg.cc	(revision 198770)
+++ testsuite/23_containers/vector/requirements/dr438/constructor_2_neg.cc	(working copy)
@@ -18,7 +18,7 @@ 
 // <http://www.gnu.org/licenses/>.
 
 // { dg-do compile }
-// { dg-error "no matching" "" { target *-*-* } 1166 }
+// { dg-error "no matching" "" { target *-*-* } 1178 }
 
 #include <vector>
 #include <utility>
Index: testsuite/23_containers/vector/requirements/dr438/insert_neg.cc
===================================================================
--- testsuite/23_containers/vector/requirements/dr438/insert_neg.cc	(revision 198770)
+++ testsuite/23_containers/vector/requirements/dr438/insert_neg.cc	(working copy)
@@ -18,7 +18,7 @@ 
 // <http://www.gnu.org/licenses/>.
 
 // { dg-do compile }
-// { dg-error "no matching" "" { target *-*-* } 1281 }
+// { dg-error "no matching" "" { target *-*-* } 1293 }
 
 #include <vector>
 
Index: testsuite/ext/vstring/modifiers/char/54577.cc
===================================================================
--- testsuite/ext/vstring/modifiers/char/54577.cc	(revision 0)
+++ testsuite/ext/vstring/modifiers/char/54577.cc	(working copy)
@@ -0,0 +1,33 @@ 
+// { dg-options "-std=gnu++11" }
+// { dg-do compile }
+
+// Copyright (C) 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 <ext/vstring.h>
+
+void test01() 
+{
+  __gnu_cxx::__vstring vs1;
+  vs1.push_back('1');
+  vs1.erase(vs1.cbegin());
+
+  __gnu_cxx::__vstring vs2;
+  vs2.push_back('2');
+  vs2.push_back('3');
+  vs2.erase(vs2.cbegin(), vs2.cend());
+}
Index: testsuite/ext/vstring/modifiers/wchar_t/54577.cc
===================================================================
--- testsuite/ext/vstring/modifiers/wchar_t/54577.cc	(revision 0)
+++ testsuite/ext/vstring/modifiers/wchar_t/54577.cc	(working copy)
@@ -0,0 +1,33 @@ 
+// { dg-options "-std=gnu++11" }
+// { dg-do compile }
+
+// Copyright (C) 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 <ext/vstring.h>
+
+void test01() 
+{
+  __gnu_cxx::__wvstring wvs1;
+  wvs1.push_back(L'1');
+  wvs1.erase(wvs1.cbegin());
+
+  __gnu_cxx::__wvstring wvs2;
+  wvs2.push_back(L'2');
+  wvs2.push_back(L'3');
+  wvs2.erase(wvs2.cbegin(), wvs2.cend());
+}
Index: testsuite/util/exception/safety.h
===================================================================
--- testsuite/util/exception/safety.h	(revision 198770)
+++ testsuite/util/exception/safety.h	(working copy)
@@ -287,57 +287,17 @@ 
 	typedef __gnu_cxx::__versa_string<_Tp1, _Tp2, _Tp3, _Tp4>
 	                                                container_type;
 	typedef typename container_type::iterator 	iterator;
+	typedef typename container_type::const_iterator const_iterator;
 
-	iterator (container_type::* _F_erase_point)(iterator);
-	iterator (container_type::* _F_erase_range)(iterator, iterator);
+	iterator (container_type::* _F_erase_point)(const_iterator);
+	iterator (container_type::* _F_erase_range)(const_iterator,
+						    const_iterator);
 
 	erase_base()
 	: _F_erase_point(&container_type::erase),
 	  _F_erase_range(&container_type::erase) { }
       };
 
-    template<typename _Tp1, typename _Tp2>
-      struct erase_base<std::deque<_Tp1, _Tp2>>
-      {
-	typedef std::deque<_Tp1, _Tp2> 		        container_type;
-	typedef typename container_type::iterator 	iterator;
-
-	iterator (container_type::* _F_erase_point)(iterator);
-	iterator (container_type::* _F_erase_range)(iterator, iterator);
-
-	erase_base()
-	: _F_erase_point(&container_type::erase),
-	  _F_erase_range(&container_type::erase) { }
-      };
-
-    template<typename _Tp1, typename _Tp2>
-      struct erase_base<std::list<_Tp1, _Tp2>>
-      {
-	typedef std::list<_Tp1, _Tp2> 		        container_type;
-	typedef typename container_type::iterator 	iterator;
-
-	iterator (container_type::* _F_erase_point)(iterator);
-	iterator (container_type::* _F_erase_range)(iterator, iterator);
-
-	erase_base()
-	: _F_erase_point(&container_type::erase),
-	  _F_erase_range(&container_type::erase) { }
-      };
-
-    template<typename _Tp1, typename _Tp2>
-      struct erase_base<std::vector<_Tp1, _Tp2>>
-      {
-	typedef std::vector<_Tp1, _Tp2>		        container_type;
-	typedef typename container_type::iterator 	iterator;
-
-	iterator (container_type::* _F_erase_point)(iterator);
-	iterator (container_type::* _F_erase_range)(iterator, iterator);
-
-	erase_base()
-	: _F_erase_point(&container_type::erase),
-	  _F_erase_range(&container_type::erase) { }
-      };
-
     // Specialization, as forward_list has erase_after.
     template<typename _Tp1, typename _Tp2>
       struct erase_base<std::forward_list<_Tp1, _Tp2>>