Fix PR#23767. Add tests for iterator invalidation for deque::erase/pop_front/pop_back

llvm-svn: 239196
This commit is contained in:
Marshall Clow 2015-06-05 22:34:19 +00:00
parent 55c1c3495d
commit b41e76bb0b
5 changed files with 248 additions and 2 deletions

View File

@ -2699,7 +2699,7 @@ deque<_Tp, _Allocator>::erase(const_iterator __f)
difference_type __pos = __f - __b;
iterator __p = __b + __pos;
allocator_type& __a = __base::__alloc();
if (__pos < (__base::size() - 1) / 2)
if (__pos <= (__base::size() - 1) / 2)
{ // erase from front
_VSTD::move_backward(__b, __p, _VSTD::next(__p));
__alloc_traits::destroy(__a, _VSTD::addressof(*__b));
@ -2737,7 +2737,7 @@ deque<_Tp, _Allocator>::erase(const_iterator __f, const_iterator __l)
if (__n > 0)
{
allocator_type& __a = __base::__alloc();
if (__pos < (__base::size() - __n) / 2)
if (__pos <= (__base::size() - __n) / 2)
{ // erase from front
iterator __i = _VSTD::move_backward(__b, __p, __p + __n);
for (; __b != __i; ++__b)

View File

@ -0,0 +1,70 @@
//===----------------------------------------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
// <deque>
// iterator erase(const_iterator f)
// Erasing items from the beginning or the end of a deque shall not invalidate iterators
// to items that were not erased.
#include <deque>
#include <cassert>
template <typename C>
void del_at_start(C c)
{
typename C::iterator first = c.begin();
typename C::iterator it1 = first + 1;
typename C::iterator it2 = c.end() - 1;
c.erase (first);
typename C::iterator it3 = c.begin();
typename C::iterator it4 = c.end() - 1;
assert( it1 == it3);
assert( *it1 == *it3);
assert(&*it1 == &*it3);
assert( it2 == it4);
assert( *it2 == *it4);
assert(&*it2 == &*it4);
}
template <typename C>
void del_at_end(C c)
{
typename C::iterator first = c.end() - 1;
typename C::iterator it1 = c.begin();
typename C::iterator it2 = first - 1;
c.erase (first);
typename C::iterator it3 = c.begin();
typename C::iterator it4 = c.end() - 1;
assert( it1 == it3);
assert( *it1 == *it3);
assert(&*it1 == &*it3);
assert( it2 == it4);
assert( *it2 == *it4);
assert(&*it2 == &*it4);
}
int main()
{
std::deque<int> queue;
for (int i = 0; i < 20; ++i)
queue.push_back(i);
while (queue.size() > 1)
{
del_at_start(queue);
del_at_end(queue);
queue.pop_back();
}
}

View File

@ -0,0 +1,78 @@
//===----------------------------------------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
// <deque>
// iterator erase(const_iterator f, const_iterator l)
// Erasing items from the beginning or the end of a deque shall not invalidate iterators
// to items that were not erased.
#include <deque>
#include <cstdint>
#include <cassert>
template <typename C>
void del_at_start(C c, size_t num)
{
typename C::iterator first = c.begin();
typename C::iterator last = first + num;
typename C::iterator it1 = last;
typename C::iterator it2 = c.end() - 1;
c.erase (first, last);
typename C::iterator it3 = c.begin();
typename C::iterator it4 = c.end() - 1;
assert( it1 == it3);
assert( *it1 == *it3);
assert(&*it1 == &*it3);
assert( it2 == it4);
assert( *it2 == *it4);
assert(&*it2 == &*it4);
}
template <typename C>
void del_at_end(C c, size_t num)
{
typename C::iterator last = c.end();
typename C::iterator first = last - num;
typename C::iterator it1 = c.begin();
typename C::iterator it2 = first - 1;
c.erase (first, last);
typename C::iterator it3 = c.begin();
typename C::iterator it4 = c.end() - 1;
assert( it1 == it3);
assert( *it1 == *it3);
assert(&*it1 == &*it3);
assert( it2 == it4);
assert( *it2 == *it4);
assert(&*it2 == &*it4);
}
int main()
{
std::deque<int> queue;
for (int i = 0; i < 20; ++i)
queue.push_back(i);
while (queue.size() > 1)
{
for (size_t i = 1; i < queue.size(); ++i)
{
del_at_start(queue, i);
del_at_end (queue, i);
}
queue.pop_back();
}
}

View File

@ -0,0 +1,49 @@
//===----------------------------------------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
// <deque>
// void pop_back()
// Erasing items from the beginning or the end of a deque shall not invalidate iterators
// to items that were not erased.
#include <deque>
#include <cassert>
template <typename C>
void test(C c)
{
typename C::iterator it1 = c.begin();
typename C::iterator it2 = c.end() - 2;
c.pop_back();
typename C::iterator it3 = c.begin();
typename C::iterator it4 = c.end() - 1;
assert( it1 == it3);
assert( *it1 == *it3);
assert(&*it1 == &*it3);
assert( it2 == it4);
assert( *it2 == *it4);
assert(&*it2 == &*it4);
}
int main()
{
std::deque<int> queue;
for (int i = 0; i < 20; ++i)
queue.push_back(i);
while (queue.size() > 1)
{
test(queue);
queue.pop_back();
}
}

View File

@ -0,0 +1,49 @@
//===----------------------------------------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
// <deque>
// void pop_front()
// Erasing items from the beginning or the end of a deque shall not invalidate iterators
// to items that were not erased.
#include <deque>
#include <cassert>
template <typename C>
void test(C c)
{
typename C::iterator it1 = c.begin() + 1;
typename C::iterator it2 = c.end() - 1;
c.pop_front();
typename C::iterator it3 = c.begin();
typename C::iterator it4 = c.end() - 1;
assert( it1 == it3);
assert( *it1 == *it3);
assert(&*it1 == &*it3);
assert( it2 == it4);
assert( *it2 == *it4);
assert(&*it2 == &*it4);
}
int main()
{
std::deque<int> queue;
for (int i = 0; i < 20; ++i)
queue.push_back(i);
while (queue.size() > 1)
{
test(queue);
queue.pop_back();
}
}