This patch adds a _Guard_nodes scope guard nested to the _Deque_base,
that deallocates the range of nodes, and replaces __try/__catch block
with appropriately constructed guard object.
libstdc++-v3/ChangeLog:
* include/bits/deque.tcc (_Deque_base::_Guard_nodes): Define.
(_Deque_base::_M_create_nodes): Moved defintion from stl_deque.h
and replace __try/__catch with _Guard_nodes scope object.
(deque::_M_fill_insert, deque::_M_default_append)
(deque::_M_push_back_aux, deque::_M_push_front_aux)
(deque::_M_range_prepend, deque::_M_range_append, deque::_M_insert_aux):
Replace __try/__catch with _Guard_nodes scope object.
(deque::_M_new_elements_at_back, deque::_M_new_elements_at_back): Use
_M_create_nodes.
* include/bits/stl_deque.h (_Deque_base::_Guard_nodes): Declare.
(_Deque_base<_Tp, _Alloc)::_M_create_nodes): Move defintion to
deque.tcc.
(deque::_Guard_nodes): Add typedef, so name is found by lookup.
* testsuite/23_containers/deque/modifiers/push_back/throw.cc: New test.
---
Fixed the off-by-one error in _M_push_back_aux and added test that reliably
detecst it.
Updated description and removed new line before struct.
Tested on x86_64 linux. Separately tested push_back/throw.cc with all standards.
OK for trunk?
libstdc++-v3/include/bits/deque.tcc | 423 ++++++++----------
libstdc++-v3/include/bits/stl_deque.h | 20 +-
.../deque/modifiers/push_back/throw.cc | 56 +++
3 files changed, 251 insertions(+), 248 deletions(-)
create mode 100644
libstdc++-v3/testsuite/23_containers/deque/modifiers/push_back/throw.cc
diff --git a/libstdc++-v3/include/bits/deque.tcc
b/libstdc++-v3/include/bits/deque.tcc
index dabb6ec5365..71c4f13170a 100644
--- a/libstdc++-v3/include/bits/deque.tcc
+++ b/libstdc++-v3/include/bits/deque.tcc
@@ -63,6 +63,39 @@ namespace std _GLIBCXX_VISIBILITY(default)
_GLIBCXX_BEGIN_NAMESPACE_VERSION
_GLIBCXX_BEGIN_NAMESPACE_CONTAINER
+ template<typename _Tp, typename _Alloc>
+ struct _Deque_base<_Tp, _Alloc>::_Guard_nodes
+ {
+ _Guard_nodes(_Deque_base& __self,
+ _Map_pointer __first, _Map_pointer __last)
+ : _M_self(__self), _M_first(__first), _M_last(__last)
+ { }
+
+ ~_Guard_nodes()
+ { _M_self._M_destroy_nodes(_M_first, _M_last); }
+
+ void _M_disarm()
+ { _M_first = _M_last; }
+
+ _Deque_base& _M_self;
+ _Map_pointer _M_first;
+ _Map_pointer _M_last;
+
+ private:
+ _Guard_nodes(_Guard_nodes const&);
+ };
+
+ template<typename _Tp, typename _Alloc>
+ void
+ _Deque_base<_Tp, _Alloc>::
+ _M_create_nodes(_Map_pointer __nstart, _Map_pointer __nfinish)
+ {
+ _Guard_nodes __guard(*this, __nstart, __nstart);
+ for (_Map_pointer& __cur = __guard._M_last; __cur < __nfinish; ++__cur)
+ *__cur = this->_M_allocate_node();
+ __guard._M_disarm();
+ }
+
#if __cplusplus >= 201103L
template <typename _Tp, typename _Alloc>
void
@@ -310,35 +343,25 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
if (__pos._M_cur == this->_M_impl._M_start._M_cur)
{
iterator __new_start = _M_reserve_elements_at_front(__n);
- __try
- {
- std::__uninitialized_fill_a(__new_start, this->_M_impl._M_start,
- __x, _M_get_Tp_allocator());
- this->_M_impl._M_start = __new_start;
- }
- __catch(...)
- {
- _M_destroy_nodes(__new_start._M_node,
- this->_M_impl._M_start._M_node);
- __throw_exception_again;
- }
+ _Guard_nodes __guard(*this, __new_start._M_node,
+ this->_M_impl._M_start._M_node);
+
+ std::__uninitialized_fill_a(__new_start, this->_M_impl._M_start,
+ __x, _M_get_Tp_allocator());
+ __guard._M_disarm();
+ this->_M_impl._M_start = __new_start;
}
else if (__pos._M_cur == this->_M_impl._M_finish._M_cur)
{
iterator __new_finish = _M_reserve_elements_at_back(__n);
- __try
- {
- std::__uninitialized_fill_a(this->_M_impl._M_finish,
- __new_finish, __x,
- _M_get_Tp_allocator());
- this->_M_impl._M_finish = __new_finish;
- }
- __catch(...)
- {
- _M_destroy_nodes(this->_M_impl._M_finish._M_node + 1,
- __new_finish._M_node + 1);
- __throw_exception_again;
- }
+ _Guard_nodes __guard(*this, this->_M_impl._M_finish._M_node + 1,
+ __new_finish._M_node + 1);
+
+ std::__uninitialized_fill_a(this->_M_impl._M_finish,
+ __new_finish, __x,
+ _M_get_Tp_allocator());
+ __guard._M_disarm();
+ this->_M_impl._M_finish = __new_finish;
}
else
_M_insert_aux(__pos, __n, __x);
@@ -350,23 +373,18 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
deque<_Tp, _Alloc>::
_M_default_append(size_type __n)
{
- if (__n)
- {
- iterator __new_finish = _M_reserve_elements_at_back(__n);
- __try
- {
- std::__uninitialized_default_a(this->_M_impl._M_finish,
- __new_finish,
- _M_get_Tp_allocator());
- this->_M_impl._M_finish = __new_finish;
- }
- __catch(...)
- {
- _M_destroy_nodes(this->_M_impl._M_finish._M_node + 1,
- __new_finish._M_node + 1);
- __throw_exception_again;
- }
- }
+ if (!__n)
+ return;
+
+ iterator __new_finish = _M_reserve_elements_at_back(__n);
+ _Guard_nodes __guard(*this, this->_M_impl._M_finish._M_node + 1,
+ __new_finish._M_node + 1);
+
+ std::__uninitialized_default_a(this->_M_impl._M_finish,
+ __new_finish,
+ _M_get_Tp_allocator());
+ __guard._M_disarm();
+ this->_M_impl._M_finish = __new_finish;
}
template <typename _Tp, typename _Alloc>
@@ -495,24 +513,18 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
_M_reserve_map_at_back();
*(this->_M_impl._M_finish._M_node + 1) = this->_M_allocate_node();
- __try
- {
+ _Guard_nodes __guard(*this, this->_M_impl._M_finish._M_node + 1,
+ this->_M_impl._M_finish._M_node + 2);
#if __cplusplus >= 201103L
- _Alloc_traits::construct(this->_M_impl,
- this->_M_impl._M_finish._M_cur,
- std::forward<_Args>(__args)...);
+ _Alloc_traits::construct(this->_M_impl,
+ this->_M_impl._M_finish._M_cur,
+ std::forward<_Args>(__args)...);
#else
- this->_M_impl.construct(this->_M_impl._M_finish._M_cur, __t);
+ this->_M_impl.construct(this->_M_impl._M_finish._M_cur, __t);
#endif
- this->_M_impl._M_finish._M_set_node(this->_M_impl._M_finish._M_node
- + 1);
- this->_M_impl._M_finish._M_cur = this->_M_impl._M_finish._M_first;
- }
- __catch(...)
- {
- _M_deallocate_node(*(this->_M_impl._M_finish._M_node + 1));
- __throw_exception_again;
- }
+ __guard._M_disarm();
+ this->_M_impl._M_finish._M_set_node(this->_M_impl._M_finish._M_node +
1);
+ this->_M_impl._M_finish._M_cur = this->_M_impl._M_finish._M_first;
}
// Called only if _M_impl._M_start._M_cur == _M_impl._M_start._M_first.
@@ -534,25 +546,21 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
_M_reserve_map_at_front();
*(this->_M_impl._M_start._M_node - 1) = this->_M_allocate_node();
- __try
- {
- this->_M_impl._M_start._M_set_node(this->_M_impl._M_start._M_node
- - 1);
- this->_M_impl._M_start._M_cur = this->_M_impl._M_start._M_last - 1;
+ _Guard_nodes __guard(*this, this->_M_impl._M_start._M_node - 1,
+ this->_M_impl._M_start._M_node);
+
+ iterator __new_start;
+ __new_start._M_set_node(this->_M_impl._M_start._M_node - 1);
+ __new_start._M_cur = __new_start._M_last - 1;
#if __cplusplus >= 201103L
- _Alloc_traits::construct(this->_M_impl,
- this->_M_impl._M_start._M_cur,
- std::forward<_Args>(__args)...);
+ _Alloc_traits::construct(this->_M_impl,
+ __new_start._M_cur,
+ std::forward<_Args>(__args)...);
#else
- this->_M_impl.construct(this->_M_impl._M_start._M_cur, __t);
+ this->_M_impl.construct(__new_start._M_cur, __t);
#endif
- }
- __catch(...)
- {
- ++this->_M_impl._M_start;
- _M_deallocate_node(*(this->_M_impl._M_start._M_node - 1));
- __throw_exception_again;
- }
+ __guard._M_disarm();
+ this->_M_impl._M_start = __new_start;
}
// Called only if _M_impl._M_finish._M_cur == _M_impl._M_finish._M_first.
@@ -591,18 +599,13 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
size_type __n)
{
iterator __new_start = _M_reserve_elements_at_front(__n);
- __try
- {
- std::__uninitialized_copy_a(_GLIBCXX_MOVE(__first), __last,
- __new_start, _M_get_Tp_allocator());
- this->_M_impl._M_start = __new_start;
- }
- __catch(...)
- {
- _M_destroy_nodes(__new_start._M_node,
- this->_M_impl._M_start._M_node);
- __throw_exception_again;
- }
+ _Guard_nodes __guard(*this, __new_start._M_node,
+ this->_M_impl._M_start._M_node);
+
+ std::__uninitialized_copy_a(_GLIBCXX_MOVE(__first), __last,
+ __new_start, _M_get_Tp_allocator());
+ __guard._M_disarm();
+ this->_M_impl._M_start = __new_start;
}
template <typename _Tp, typename _Alloc>
@@ -613,19 +616,14 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
size_type __n)
{
iterator __new_finish = _M_reserve_elements_at_back(__n);
- __try
- {
- std::__uninitialized_copy_a(_GLIBCXX_MOVE(__first), __last,
- this->_M_impl._M_finish,
- _M_get_Tp_allocator());
- this->_M_impl._M_finish = __new_finish;
- }
- __catch(...)
- {
- _M_destroy_nodes(this->_M_impl._M_finish._M_node + 1,
- __new_finish._M_node + 1);
- __throw_exception_again;
- }
+ _Guard_nodes __guard(*this, this->_M_impl._M_finish._M_node + 1,
+ __new_finish._M_node + 1);
+
+ std::__uninitialized_copy_a(_GLIBCXX_MOVE(__first), __last,
+ this->_M_impl._M_finish,
+ _M_get_Tp_allocator());
+ __guard._M_disarm();
+ this->_M_impl._M_finish = __new_finish;
}
template <typename _Tp, typename _Alloc>
@@ -712,35 +710,31 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
iterator __new_start = _M_reserve_elements_at_front(__n);
iterator __old_start = this->_M_impl._M_start;
__pos = this->_M_impl._M_start + __elems_before;
- __try
+
+ _Guard_nodes __guard(*this, __new_start._M_node,
+ this->_M_impl._M_start._M_node);
+ if (__elems_before >= difference_type(__n))
{
- if (__elems_before >= difference_type(__n))
- {
- iterator __start_n = (this->_M_impl._M_start
- + difference_type(__n));
- std::__uninitialized_move_a(this->_M_impl._M_start,
- __start_n, __new_start,
- _M_get_Tp_allocator());
- this->_M_impl._M_start = __new_start;
- _GLIBCXX_MOVE3(__start_n, __pos, __old_start);
- std::fill(__pos - difference_type(__n), __pos, __x_copy);
- }
- else
- {
- std::__uninitialized_move_fill(this->_M_impl._M_start,
- __pos, __new_start,
- this->_M_impl._M_start,
- __x_copy,
- _M_get_Tp_allocator());
- this->_M_impl._M_start = __new_start;
- std::fill(__old_start, __pos, __x_copy);
- }
+ iterator __start_n = (this->_M_impl._M_start
+ + difference_type(__n));
+ std::__uninitialized_move_a(this->_M_impl._M_start,
+ __start_n, __new_start,
+ _M_get_Tp_allocator());
+ __guard._M_disarm();
+ this->_M_impl._M_start = __new_start;
+ _GLIBCXX_MOVE3(__start_n, __pos, __old_start);
+ std::fill(__pos - difference_type(__n), __pos, __x_copy);
}
- __catch(...)
+ else
{
- _M_destroy_nodes(__new_start._M_node,
- this->_M_impl._M_start._M_node);
- __throw_exception_again;
+ std::__uninitialized_move_fill(this->_M_impl._M_start,
+ __pos, __new_start,
+ this->_M_impl._M_start,
+ __x_copy,
+ _M_get_Tp_allocator());
+ __guard._M_disarm();
+ this->_M_impl._M_start = __new_start;
+ std::fill(__old_start, __pos, __x_copy);
}
}
else
@@ -750,36 +744,32 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
const difference_type __elems_after =
difference_type(__length) - __elems_before;
__pos = this->_M_impl._M_finish - __elems_after;
- __try
+
+ _Guard_nodes __guard(*this, this->_M_impl._M_finish._M_node + 1,
+ __new_finish._M_node + 1);
+ if (__elems_after > difference_type(__n))
{
- if (__elems_after > difference_type(__n))
- {
- iterator __finish_n = (this->_M_impl._M_finish
- - difference_type(__n));
- std::__uninitialized_move_a(__finish_n,
- this->_M_impl._M_finish,
- this->_M_impl._M_finish,
- _M_get_Tp_allocator());
- this->_M_impl._M_finish = __new_finish;
- _GLIBCXX_MOVE_BACKWARD3(__pos, __finish_n, __old_finish);
- std::fill(__pos, __pos + difference_type(__n), __x_copy);
- }
- else
- {
- std::__uninitialized_fill_move(this->_M_impl._M_finish,
- __pos + difference_type(__n),
- __x_copy, __pos,
- this->_M_impl._M_finish,
- _M_get_Tp_allocator());
- this->_M_impl._M_finish = __new_finish;
- std::fill(__pos, __old_finish, __x_copy);
- }
+ iterator __finish_n = (this->_M_impl._M_finish
+ - difference_type(__n));
+ std::__uninitialized_move_a(__finish_n,
+ this->_M_impl._M_finish,
+ this->_M_impl._M_finish,
+ _M_get_Tp_allocator());
+ __guard._M_disarm();
+ this->_M_impl._M_finish = __new_finish;
+ _GLIBCXX_MOVE_BACKWARD3(__pos, __finish_n, __old_finish);
+ std::fill(__pos, __pos + difference_type(__n), __x_copy);
}
- __catch(...)
+ else
{
- _M_destroy_nodes(this->_M_impl._M_finish._M_node + 1,
- __new_finish._M_node + 1);
- __throw_exception_again;
+ std::__uninitialized_fill_move(this->_M_impl._M_finish,
+ __pos + difference_type(__n),
+ __x_copy, __pos,
+ this->_M_impl._M_finish,
+ _M_get_Tp_allocator());
+ __guard._M_disarm();
+ this->_M_impl._M_finish = __new_finish;
+ std::fill(__pos, __old_finish, __x_copy);
}
}
}
@@ -799,36 +789,33 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
iterator __new_start = _M_reserve_elements_at_front(__n);
iterator __old_start = this->_M_impl._M_start;
__pos = this->_M_impl._M_start + __elemsbefore;
- __try
+
+ _Guard_nodes __guard(*this, __new_start._M_node,
+ this->_M_impl._M_start._M_node);
+
+ if (__elemsbefore >= difference_type(__n))
{
- if (__elemsbefore >= difference_type(__n))
- {
- iterator __start_n = (this->_M_impl._M_start
- + difference_type(__n));
- std::__uninitialized_move_a(this->_M_impl._M_start,
- __start_n, __new_start,
- _M_get_Tp_allocator());
- this->_M_impl._M_start = __new_start;
- _GLIBCXX_MOVE3(__start_n, __pos, __old_start);
- std::copy(__first, __last, __pos - difference_type(__n));
- }
- else
- {
- _ForwardIterator __mid = __first;
- std::advance(__mid, difference_type(__n) - __elemsbefore);
- std::__uninitialized_move_copy(this->_M_impl._M_start,
- __pos, __first, __mid,
- __new_start,
- _M_get_Tp_allocator());
- this->_M_impl._M_start = __new_start;
- std::copy(__mid, __last, __old_start);
- }
+ iterator __start_n = (this->_M_impl._M_start
+ + difference_type(__n));
+ std::__uninitialized_move_a(this->_M_impl._M_start,
+ __start_n, __new_start,
+ _M_get_Tp_allocator());
+ __guard._M_disarm();
+ this->_M_impl._M_start = __new_start;
+ _GLIBCXX_MOVE3(__start_n, __pos, __old_start);
+ std::copy(__first, __last, __pos - difference_type(__n));
}
- __catch(...)
+ else
{
- _M_destroy_nodes(__new_start._M_node,
- this->_M_impl._M_start._M_node);
- __throw_exception_again;
+ _ForwardIterator __mid = __first;
+ std::advance(__mid, difference_type(__n) - __elemsbefore);
+ std::__uninitialized_move_copy(this->_M_impl._M_start,
+ __pos, __first, __mid,
+ __new_start,
+ _M_get_Tp_allocator());
+ __guard._M_disarm();
+ this->_M_impl._M_start = __new_start;
+ std::copy(__mid, __last, __old_start);
}
}
else
@@ -838,37 +825,33 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
const difference_type __elemsafter =
difference_type(__length) - __elemsbefore;
__pos = this->_M_impl._M_finish - __elemsafter;
- __try
+
+ _Guard_nodes __guard(*this, this->_M_impl._M_finish._M_node + 1,
+ __new_finish._M_node + 1);
+ if (__elemsafter > difference_type(__n))
{
- if (__elemsafter > difference_type(__n))
- {
- iterator __finish_n = (this->_M_impl._M_finish
- - difference_type(__n));
- std::__uninitialized_move_a(__finish_n,
- this->_M_impl._M_finish,
- this->_M_impl._M_finish,
- _M_get_Tp_allocator());
- this->_M_impl._M_finish = __new_finish;
- _GLIBCXX_MOVE_BACKWARD3(__pos, __finish_n, __old_finish);
- std::copy(__first, __last, __pos);
- }
- else
- {
- _ForwardIterator __mid = __first;
- std::advance(__mid, __elemsafter);
- std::__uninitialized_copy_move(__mid, __last, __pos,
- this->_M_impl._M_finish,
- this->_M_impl._M_finish,
- _M_get_Tp_allocator());
- this->_M_impl._M_finish = __new_finish;
- std::copy(__first, __mid, __pos);
- }
+ iterator __finish_n = (this->_M_impl._M_finish
+ - difference_type(__n));
+ std::__uninitialized_move_a(__finish_n,
+ this->_M_impl._M_finish,
+ this->_M_impl._M_finish,
+ _M_get_Tp_allocator());
+ __guard._M_disarm();
+ this->_M_impl._M_finish = __new_finish;
+ _GLIBCXX_MOVE_BACKWARD3(__pos, __finish_n, __old_finish);
+ std::copy(__first, __last, __pos);
}
- __catch(...)
+ else
{
- _M_destroy_nodes(this->_M_impl._M_finish._M_node + 1,
- __new_finish._M_node + 1);
- __throw_exception_again;
+ _ForwardIterator __mid = __first;
+ std::advance(__mid, __elemsafter);
+ std::__uninitialized_copy_move(__mid, __last, __pos,
+ this->_M_impl._M_finish,
+ this->_M_impl._M_finish,
+ _M_get_Tp_allocator());
+ __guard._M_disarm();
+ this->_M_impl._M_finish = __new_finish;
+ std::copy(__first, __mid, __pos);
}
}
}
@@ -1057,18 +1040,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
const size_type __new_nodes = ((__new_elems + _S_buffer_size() - 1)
/ _S_buffer_size());
_M_reserve_map_at_front(__new_nodes);
- size_type __i;
- __try
- {
- for (__i = 1; __i <= __new_nodes; ++__i)
- *(this->_M_impl._M_start._M_node - __i) = this->_M_allocate_node();
- }
- __catch(...)
- {
- for (size_type __j = 1; __j < __i; ++__j)
- _M_deallocate_node(*(this->_M_impl._M_start._M_node - __j));
- __throw_exception_again;
- }
+ _M_create_nodes(this->_M_impl._M_start._M_node - __new_nodes,
+ this->_M_impl._M_start._M_node);
}
template <typename _Tp, typename _Alloc>
@@ -1082,18 +1055,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
const size_type __new_nodes = ((__new_elems + _S_buffer_size() - 1)
/ _S_buffer_size());
_M_reserve_map_at_back(__new_nodes);
- size_type __i;
- __try
- {
- for (__i = 1; __i <= __new_nodes; ++__i)
- *(this->_M_impl._M_finish._M_node + __i) = this->_M_allocate_node();
- }
- __catch(...)
- {
- for (size_type __j = 1; __j < __i; ++__j)
- _M_deallocate_node(*(this->_M_impl._M_finish._M_node + __j));
- __throw_exception_again;
- }
+ _M_create_nodes(_M_impl._M_finish._M_node + 1,
+ _M_impl._M_finish._M_node + __new_nodes + 1);
}
template <typename _Tp, typename _Alloc>
diff --git a/libstdc++-v3/include/bits/stl_deque.h
b/libstdc++-v3/include/bits/stl_deque.h
index 8d8ee575a26..73e48299938 100644
--- a/libstdc++-v3/include/bits/stl_deque.h
+++ b/libstdc++-v3/include/bits/stl_deque.h
@@ -612,6 +612,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
void _M_destroy_nodes(_Map_pointer __nstart,
_Map_pointer __nfinish) _GLIBCXX_NOEXCEPT;
enum { _S_initial_map_size = 8 };
+ struct _Guard_nodes;
_Deque_impl _M_impl;
};
@@ -675,24 +676,6 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
% __deque_buf_size(sizeof(_Tp)));
}
- template<typename _Tp, typename _Alloc>
- void
- _Deque_base<_Tp, _Alloc>::
- _M_create_nodes(_Map_pointer __nstart, _Map_pointer __nfinish)
- {
- _Map_pointer __cur;
- __try
- {
- for (__cur = __nstart; __cur < __nfinish; ++__cur)
- *__cur = this->_M_allocate_node();
- }
- __catch(...)
- {
- _M_destroy_nodes(__nstart, __cur);
- __throw_exception_again;
- }
- }
-
template<typename _Tp, typename _Alloc>
void
_Deque_base<_Tp, _Alloc>::
@@ -812,6 +795,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
typedef typename _Base::_Tp_alloc_type _Tp_alloc_type;
typedef typename _Base::_Alloc_traits _Alloc_traits;
typedef typename _Base::_Map_pointer _Map_pointer;
+ typedef typename _Base::_Guard_nodes _Guard_nodes;
public:
typedef _Tp value_type;
diff --git
a/libstdc++-v3/testsuite/23_containers/deque/modifiers/push_back/throw.cc
b/libstdc++-v3/testsuite/23_containers/deque/modifiers/push_back/throw.cc
new file mode 100644
index 00000000000..7d4bf6954f2
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/deque/modifiers/push_back/throw.cc
@@ -0,0 +1,56 @@
+// { dg-do run }
+
+#include <deque>
+#include <testsuite_hooks.h>
+#include <testsuite_allocator.h>
+
+struct Thrower
+{
+ Thrower(int p) : v(p) {}
+ Thrower(Thrower const& p) : v(p.v)
+ {
+ if (v < 0)
+ throw v;
+ }
+
+ int v;
+};
+
+void test01()
+{
+ using namespace std;
+ typedef __gnu_test::uneq_allocator<Thrower> Allocator;
+ typedef __gnu_test::uneq_allocator_base AllocatorBase;
+
+ const std::size_t buf_elems =
_GLIBCXX_STD_C::__deque_buf_size(sizeof(Thrower));
+ std::deque<Thrower, Allocator> d;
+ for (std::size_t i = 1; i < buf_elems; i++)
+ d.push_back(Thrower(i));
+ const AllocatorBase::map_type allocated = AllocatorBase::get_map();
+
+ try
+ {
+ d.push_back(Thrower(-1));
+ VERIFY( false );
+ }
+ catch (int p)
+ {
+ VERIFY( p == -1 );
+ }
+
+ VERIFY( d.size() == buf_elems - 1 );
+ for (std::size_t i = 1; i < buf_elems; i++)
+ VERIFY( d[i-1].v == i );
+
+ const AllocatorBase::map_type& current = AllocatorBase::get_map();
+ VERIFY( current.size() == allocated.size() );
+ for (AllocatorBase::map_type::const_iterator it = current.begin();
+ it != current.end(); ++it)
+ VERIFY( allocated.find(it->first) != allocated.end() );
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
--
2.49.0