re PR libstdc++/50529 ([C++0x] std::vector::erase invokes undefined behavior with empty range)

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
This commit is contained in:
Paolo Carlini 2011-09-27 02:39:34 +00:00 committed by Paolo Carlini
parent b92edfe52d
commit a7cee01d32
9 changed files with 119 additions and 13 deletions

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

View 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();

View 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;
}

View 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;
}

View 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();

View 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

View 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 );
}

View File

@ -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;
}

View File

@ -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;
}