From a7cee01d32cdbe912b32ad113b569b39a0e95445 Mon Sep 17 00:00:00 2001 From: Paolo Carlini Date: Tue, 27 Sep 2011 02:39:34 +0000 Subject: [PATCH] re PR libstdc++/50529 ([C++0x] std::vector::erase invokes undefined behavior with empty range) 2011-09-26 Paolo Carlini 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 | 13 +++++++ libstdc++-v3/include/bits/deque.tcc | 4 +- libstdc++-v3/include/bits/stl_bvector.h | 3 +- libstdc++-v3/include/bits/vector.tcc | 9 +++-- libstdc++-v3/include/debug/deque | 6 ++- libstdc++-v3/include/debug/vector | 15 +++++--- .../23_containers/deque/modifiers/erase/3.cc | 6 ++- .../deque/modifiers/erase/50529.cc | 38 +++++++++++++++++++ .../vector/modifiers/erase/50529.cc | 38 +++++++++++++++++++ 9 files changed, 119 insertions(+), 13 deletions(-) create mode 100644 libstdc++-v3/testsuite/23_containers/deque/modifiers/erase/50529.cc create mode 100644 libstdc++-v3/testsuite/23_containers/vector/modifiers/erase/50529.cc diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 05f7ef262ca0..140bdb1a5b65 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,16 @@ +2011-09-26 Paolo Carlini + + 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 diff --git a/libstdc++-v3/include/bits/deque.tcc b/libstdc++-v3/include/bits/deque.tcc index fab79157cdb0..5b56875b4936 100644 --- a/libstdc++-v3/include/bits/deque.tcc +++ b/libstdc++-v3/include/bits/deque.tcc @@ -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(); diff --git a/libstdc++-v3/include/bits/stl_bvector.h b/libstdc++-v3/include/bits/stl_bvector.h index 22443f4a4c1c..bddecb0d4c51 100644 --- a/libstdc++-v3/include/bits/stl_bvector.h +++ b/libstdc++-v3/include/bits/stl_bvector.h @@ -838,7 +838,8 @@ template 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; } diff --git a/libstdc++-v3/include/bits/vector.tcc b/libstdc++-v3/include/bits/vector.tcc index ba98c7cb07eb..b74684228c1a 100644 --- a/libstdc++-v3/include/bits/vector.tcc +++ b/libstdc++-v3/include/bits/vector.tcc @@ -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; } diff --git a/libstdc++-v3/include/debug/deque b/libstdc++-v3/include/debug/deque index 08c1cdfd0b4e..2bce99281d69 100644 --- a/libstdc++-v3/include/debug/deque +++ b/libstdc++-v3/include/debug/deque @@ -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(); diff --git a/libstdc++-v3/include/debug/vector b/libstdc++-v3/include/debug/vector index 9d68d007c121..865c27564549 100644 --- a/libstdc++-v3/include/debug/vector +++ b/libstdc++-v3/include/debug/vector @@ -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 diff --git a/libstdc++-v3/testsuite/23_containers/deque/modifiers/erase/3.cc b/libstdc++-v3/testsuite/23_containers/deque/modifiers/erase/3.cc index 34d0f74f12a1..79a046ed75ee 100644 --- a/libstdc++-v3/testsuite/23_containers/deque/modifiers/erase/3.cc +++ b/libstdc++-v3/testsuite/23_containers/deque/modifiers/erase/3.cc @@ -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 index 000000000000..f534758a9d17 --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/deque/modifiers/erase/50529.cc @@ -0,0 +1,38 @@ +// { dg-options "-std=gnu++0x" } + +// 2011-09-26 Paolo Carlini + +// Copyright (C) 2011 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +#include +#include + +// 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 index 000000000000..d76bed53cef7 --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/vector/modifiers/erase/50529.cc @@ -0,0 +1,38 @@ +// { dg-options "-std=gnu++0x" } + +// 2011-09-26 Paolo Carlini + +// Copyright (C) 2011 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +#include +#include + +// 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; +}