re PR libstdc++/50529 ([C++0x] std::vector::erase invokes undefined behavior with...
authorPaolo Carlini <paolo.carlini@oracle.com>
Tue, 27 Sep 2011 02:39:34 +0000 (02:39 +0000)
committerPaolo Carlini <paolo@gcc.gnu.org>
Tue, 27 Sep 2011 02:39:34 +0000 (02:39 +0000)
2011-09-26  Paolo Carlini  <paolo.carlini@oracle.com>

PR libstdc++/50529
* include/bits/vector.tcc (vector<>::erase(iterator, iterator)):
Fix to do nothing if the range is empty.
* include/bits/stl_bvector.h: Likewise.
* include/bits/deque.tcc: Likewise.
* include/debug/vector: Adjust.
* include/debug/deque: Likewise.
* testsuite/23_containers/vector/modifiers/erase/50529.cc: New.
* testsuite/23_containers/deque/modifiers/erase/50529.cc: Likewise.
* testsuite/23_containers/deque/modifiers/erase/3.cc: Adjust.

From-SVN: r179234

libstdc++-v3/ChangeLog
libstdc++-v3/include/bits/deque.tcc
libstdc++-v3/include/bits/stl_bvector.h
libstdc++-v3/include/bits/vector.tcc
libstdc++-v3/include/debug/deque
libstdc++-v3/include/debug/vector
libstdc++-v3/testsuite/23_containers/deque/modifiers/erase/3.cc
libstdc++-v3/testsuite/23_containers/deque/modifiers/erase/50529.cc [new file with mode: 0644]
libstdc++-v3/testsuite/23_containers/vector/modifiers/erase/50529.cc [new file with mode: 0644]

index 05f7ef262ca064b6271ad8acb7c71e6a24b7fba4..140bdb1a5b652ee4bf2f4eecc30538b172e57488 100644 (file)
@@ -1,3 +1,16 @@
+2011-09-26  Paolo Carlini  <paolo.carlini@oracle.com>
+
+       PR libstdc++/50529
+       * include/bits/vector.tcc (vector<>::erase(iterator, iterator)):
+       Fix to do nothing if the range is empty.
+       * include/bits/stl_bvector.h: Likewise.
+       * include/bits/deque.tcc: Likewise.
+       * include/debug/vector: Adjust.
+       * include/debug/deque: Likewise.
+       * testsuite/23_containers/vector/modifiers/erase/50529.cc: New.
+       * testsuite/23_containers/deque/modifiers/erase/50529.cc: Likewise.
+       * testsuite/23_containers/deque/modifiers/erase/3.cc: Adjust.
+
 2011-09-25  Benjamin Kosnik  <bkoz@redhat.com
             Jonathan Wakely  <jwakely.gcc@gmail.com>
 
index fab79157cdb04bb9147ae68fa1ca5d74de8527d5..5b56875b4936a2b44f14f189a7415c3a6965d0f5 100644 (file)
@@ -218,7 +218,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
     deque<_Tp, _Alloc>::
     erase(iterator __first, iterator __last)
     {
-      if (__first == begin() && __last == end())
+      if (__first == __last)
+       return __first;
+      else if (__first == begin() && __last == end())
        {
          clear();
          return end();
index 22443f4a4c1ce7a0b70064cbce6e37d3a223d36f..bddecb0d4c51eb217b7ad6724976ffddf52a52c7 100644 (file)
@@ -838,7 +838,8 @@ template<typename _Alloc>
     iterator
     erase(iterator __first, iterator __last)
     {
-      _M_erase_at_end(std::copy(__last, end(), __first));
+      if (__first != __last)
+       _M_erase_at_end(std::copy(__last, end(), __first));
       return __first;
     }
 
index ba98c7cb07ebd1aa7c319e441b3fa0f218507b4b..b74684228c1a9c5842a33863811491ee99065cae 100644 (file)
@@ -147,9 +147,12 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
     vector<_Tp, _Alloc>::
     erase(iterator __first, iterator __last)
     {
-      if (__last != end())
-       _GLIBCXX_MOVE3(__last, end(), __first);
-      _M_erase_at_end(__first.base() + (end() - __last));
+      if (__first != __last)
+       {
+         if (__last != end())
+           _GLIBCXX_MOVE3(__last, end(), __first);
+         _M_erase_at_end(__first.base() + (end() - __last));
+       }
       return __first;
     }
 
index 08c1cdfd0b4e43fba88f353cf8f2df12d06cbaa7..2bce99281d6961518a50674b66c5719ba0e6afdd 100644 (file)
@@ -464,7 +464,11 @@ namespace __debug
        // _GLIBCXX_RESOLVE_LIB_DEFECTS
        // 151. can't currently clear() empty container
        __glibcxx_check_erase_range(__first, __last);
-        if (__first.base() == _Base::begin() || __last.base() == _Base::end())
+
+       if (__first == __last)
+         return __first;
+        else if (__first.base() == _Base::begin()
+                || __last.base() == _Base::end())
          {
            this->_M_detach_singular();
            for (_Base_iterator __position = __first.base();
index 9d68d007c121ca1c461198301a5ab52f0706fd60..865c27564549e630177718f4ed24fe9d960a7849 100644 (file)
@@ -499,11 +499,16 @@ namespace __debug
        // 151. can't currently clear() empty container
        __glibcxx_check_erase_range(__first, __last);
 
-       difference_type __offset = __first.base() - _Base::begin();
-       _Base_iterator __res = _Base::erase(__first.base(),
-                                                     __last.base());
-       this->_M_invalidate_after_nth(__offset);
-       return iterator(__res, this);
+       if (__first != __last)
+         {
+           difference_type __offset = __first.base() - _Base::begin();
+           _Base_iterator __res = _Base::erase(__first.base(),
+                                               __last.base());
+           this->_M_invalidate_after_nth(__offset);
+           return iterator(__res, this);
+         }
+       else
+         return __first;
       }
 
       void
index 34d0f74f12a1a5e4eeb7fdb596c16edf1c75f452..79a046ed75eed18f1148e1173f684c80a66a32ca 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2007, 2009 Free Software Foundation, Inc.
+// Copyright (C) 2007, 2009, 2010, 2011 Free Software Foundation, Inc.
 //
 // This file is part of the GNU ISO C++ Library.  This library is free
 // software; you can redistribute it and/or modify it under the
@@ -31,7 +31,9 @@ void erase(size_t num_elm, size_t elm_strt, size_t elm_end)
   
   x.erase(x.begin() + elm_strt, x.begin() + elm_end);
   
-  const size_t min_num_cpy = std::min(elm_strt, num_elm - elm_end);
+  const size_t min_num_cpy
+    = elm_strt == elm_end ? 0 : std::min(elm_strt, num_elm - elm_end);
+
   VERIFY( assignment_operator::count() == min_num_cpy );
 }
 
diff --git a/libstdc++-v3/testsuite/23_containers/deque/modifiers/erase/50529.cc b/libstdc++-v3/testsuite/23_containers/deque/modifiers/erase/50529.cc
new file mode 100644 (file)
index 0000000..f534758
--- /dev/null
@@ -0,0 +1,38 @@
+// { dg-options "-std=gnu++0x" }
+
+// 2011-09-26  Paolo Carlini  <paolo.carlini@oracle.com>
+
+// Copyright (C) 2011 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <deque>
+#include <testsuite_rvalref.h>
+
+// libstdc++/50529
+void test01()
+{
+  std::deque<__gnu_test::rvalstruct> d(10);
+
+  for (auto it = d.begin(); it != d.end(); ++it)
+    d.erase(it, it);
+}
+
+int main()
+{
+  test01();
+  return 0;
+}
diff --git a/libstdc++-v3/testsuite/23_containers/vector/modifiers/erase/50529.cc b/libstdc++-v3/testsuite/23_containers/vector/modifiers/erase/50529.cc
new file mode 100644 (file)
index 0000000..d76bed5
--- /dev/null
@@ -0,0 +1,38 @@
+// { dg-options "-std=gnu++0x" }
+
+// 2011-09-26  Paolo Carlini  <paolo.carlini@oracle.com>
+
+// Copyright (C) 2011 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <vector>
+#include <testsuite_rvalref.h>
+
+// libstdc++/50529
+void test01()
+{
+  std::vector<__gnu_test::rvalstruct> v(10);
+
+  for (auto it = v.begin(); it != v.end(); ++it)
+    v.erase(it, it);
+}
+
+int main()
+{
+  test01();
+  return 0;
+}