[v3] Fix libstdc++/54577

Submitted by Paolo Carlini on May 10, 2013, 2:17 p.m.

Details

Message ID 518D0177.8090709@oracle.com
State New
Headers show

Commit Message

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.

Comments

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 hide | download patch | download mbox

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>>