* debug container patch
@ 2014-04-17 20:52 François Dumont
2014-04-18 10:59 ` Jonathan Wakely
2014-04-27 14:43 ` Jonathan Wakely
0 siblings, 2 replies; 10+ messages in thread
From: François Dumont @ 2014-04-17 20:52 UTC (permalink / raw)
To: libstdc++, gcc-patches
[-- Attachment #1: Type: text/plain, Size: 7145 bytes --]
Hi
Here is a patch to globally enhance debug containers implementation.
I have isolated all code of special functions in a base class so
that in C++11 we can use default implementations for the debug
containers. This way implementation is simpler and inherit from the
noexcept qualifications.
_Safe_container is now using the debug base class (_Safe_sequence,
_Safe_node_sequence, _Safe_forward_list...) as a policy describing what
must be done as _M_invalidate_all or _M_swap. Note that I needed to
invert inheritance so that I can use this base type to do checks with
allocators before they get potentially moved by the normal code. This is
the case for the allocator aware move constructor and move assignment
operator. With the allocator aware move constructor it is in fact fixing
a bug, iterators were not correctly swap when they had to.
I had to put a _IsCpp11AllocatorAware template parameter to this
new type for types that are not yet C++11 allocator aware. We will be
able to simplify it later.
I noticed also that in std/c++11/debug.cc we have some methods
qualified with noexcept while in a C++03 user code those methods will
have a throw() qualification. Is that fine ?
Tested under linux x86_64 normal and debug mode.
2014-04-17 François Dumont <fdumont@gcc.gnu.org>
* include/debug/macros.h [__glibcxx_check_equal_allocs]: Add
parameter to pass the 2 instances to check allocator equality.
* include/debug/safe_container.h (__gnu_debug::_Safe_container<>):
New.
* include/Makefile.am: Add previous.
* include/debug/deque (std::__debug::deque<>): Inherit
_Safe_container<>. Use default implementation for all special
functions.
* include/debug/forward_list (std::__debug::forward_list<>):
Likewise.
* include/debug/list (std::__debug::list<>): Likewise.
* include/debug/map.h (std::__debug::map<>): Likewise.
* include/debug/multimap.h (std::__debug::multimap<>): Likewise.
* include/debug/set.h (std::__debug::set<>): Likewise.
* include/debug/multiset.h (std::__debug::multiset<>): Likewise.
* include/debug/string (std::__debug::basic_string<>): Likewise.
* include/debug/unordered_map
(std::__debug::unordered_map<>): Likewise.
(std::__debug::unordered_multimap<>): Likewise.
* include/debug/unordered_set
(std::__debug::unordered_set<>): Likewise.
(std::__debug::unordered_multiset<>): Likewise.
* include/debug/vector (std::__debug::vector<>): Likewise.
* include/debug/safe_base.h (_Safe_sequence_base()): Add
noexcept.
(_Safe_sequence_base(_Safe_sequence_base&&): Remove.
(~_Safe_sequence_base()): Add noexcept.
* include/debug/safe_sequence.h
(std::__debug::_Safe_node_sequence<>): New.
* include/debug/safe_sequence.tcc
* include/debug/safe_unordered_base.h
* include/debug/safe_unordered_container.h
(_Safe_unordered_container_base()): Add noexcept.
(~_Safe_unordered_container_base()): Likewise.
(_M_swap(_Safe_unordered_container_base&)): Likewise.
* include/debug/safe_unordered_container.tcc
* src/c++11/debug.cc: Limit includes.
* testsuite/util/debug/checks.h (check_construct1): Just check the
invalid call.
(check_construct2): Likewise.
(check_construct3): Likewise.
* testsuite/23_containers/forward_list/allocator/move.cc: Add
check on iterators to make sure they are correctly moved in debug
mode.
* testsuite/23_containers/forward_list/allocator/move_assign.cc:
Likewise.
* testsuite/23_containers/map/allocator/move.cc: Likewise.
* testsuite/23_containers/map/allocator/move_assign.cc: Likewise.
* testsuite/23_containers/multimap/allocator/move.cc: Likewise.
* testsuite/23_containers/multimap/allocator/move_assign.cc:
Likewise.
* testsuite/23_containers/multiset/allocator/move.cc: Likewise.
* testsuite/23_containers/multiset/allocator/move_assign.cc:
Likewise.
* testsuite/23_containers/set/allocator/move.cc: Likewise.
* testsuite/23_containers/set/allocator/move_assign.cc: Likewise.
* testsuite/23_containers/unordered_map/allocator/move.cc:
Likewise.
* testsuite/23_containers/unordered_map/allocator/move_assign.cc:
Likewise.
* testsuite/23_containers/unordered_multimap/allocator/move.cc:
Likewise.
* testsuite/23_containers/unordered_multimap/allocator/move_assign.cc:
Likewise.
* testsuite/23_containers/unordered_multiset/allocator/move.cc:
Likewise.
* testsuite/23_containers/unordered_multiset/allocator/move_assign.cc:
Likewise.
* testsuite/23_containers/unordered_set/allocator/move.cc:
Likewise.
* testsuite/23_containers/unordered_set/allocator/move_assign.cc:
Likewise.
* testsuite/23_containers/forward_list/debug/construct1_neg.cc:
New.
* testsuite/23_containers/forward_list/debug/construct2_neg.cc:
New.
* testsuite/23_containers/forward_list/debug/construct3_neg.cc:
New.
* testsuite/23_containers/forward_list/debug/construct4_neg.cc:
New.
* testsuite/23_containers/forward_list/debug/move_assign_neg.cc:
New.
* testsuite/23_containers/forward_list/debug/move_neg.cc: New.
* testsuite/23_containers/map/debug/construct5_neg.cc: New.
* testsuite/23_containers/map/debug/move_assign_neg.cc: New.
* testsuite/23_containers/map/debug/move_neg.cc: New.
* testsuite/23_containers/multimap/debug/construct5_neg.cc: New.
* testsuite/23_containers/multimap/debug/move_assign_neg.cc: New.
* testsuite/23_containers/multimap/debug/move_neg.cc: New.
* testsuite/23_containers/multiset/debug/construct5_neg.cc: New.
* testsuite/23_containers/multiset/debug/move_assign_neg.cc: New.
* testsuite/23_containers/multiset/debug/move_neg.cc: New.
* testsuite/23_containers/set/debug/construct5_neg.cc: New.
* testsuite/23_containers/set/debug/move_assign_neg.cc: New.
* testsuite/23_containers/set/debug/move_neg.cc: New.
* testsuite/23_containers/unordered_map/debug/construct5_neg.cc:
New.
* testsuite/23_containers/unordered_map/debug/move_assign_neg.cc:
New.
* testsuite/23_containers/unordered_map/debug/move_neg.cc: New.
* testsuite/23_containers/unordered_multimap/debug/construct5_neg.cc:
New.
* testsuite/23_containers/unordered_multimap/debug/move_assign_neg.cc:
New.
* testsuite/23_containers/unordered_multimap/debug/move_neg.cc:
New.
* testsuite/23_containers/unordered_multiset/debug/construct5_neg.cc:
New.
* testsuite/23_containers/unordered_multiset/debug/move_assign_neg.cc:
New.
* testsuite/23_containers/unordered_multiset/debug/move_neg.cc:
New.
* testsuite/23_containers/unordered_set/debug/construct5_neg.cc:
New.
* testsuite/23_containers/unordered_set/debug/move_assign_neg.cc:
New.
* testsuite/23_containers/unordered_set/debug/move_neg.cc: New.
* testsuite/23_containers/vector/debug/move_neg.cc: New.
Ok to commit ?
François
[-- Attachment #2: safe_containers.patch --]
[-- Type: text/x-patch, Size: 165772 bytes --]
Index: include/Makefile.am
===================================================================
--- include/Makefile.am (revision 209446)
+++ include/Makefile.am (working copy)
@@ -733,6 +733,7 @@
${debug_srcdir}/multimap.h \
${debug_srcdir}/multiset.h \
${debug_srcdir}/safe_base.h \
+ ${debug_srcdir}/safe_container.h \
${debug_srcdir}/safe_iterator.h \
${debug_srcdir}/safe_iterator.tcc \
${debug_srcdir}/safe_local_iterator.h \
Index: include/debug/deque
===================================================================
--- include/debug/deque (revision 209446)
+++ include/debug/deque (working copy)
@@ -31,6 +31,7 @@
#include <deque>
#include <debug/safe_sequence.h>
+#include <debug/safe_container.h>
#include <debug/safe_iterator.h>
namespace std _GLIBCXX_VISIBILITY(default)
@@ -40,21 +41,26 @@
/// Class std::deque with safety/checking/debug instrumentation.
template<typename _Tp, typename _Allocator = std::allocator<_Tp> >
class deque
- : public _GLIBCXX_STD_C::deque<_Tp, _Allocator>,
- public __gnu_debug::_Safe_sequence<deque<_Tp, _Allocator> >
+ : public __gnu_debug::_Safe_container<
+ deque<_Tp, _Allocator>, _Allocator,
+ __gnu_debug::_Safe_sequence, false>,
+ public _GLIBCXX_STD_C::deque<_Tp, _Allocator>
{
typedef _GLIBCXX_STD_C::deque<_Tp, _Allocator> _Base;
+ typedef __gnu_debug::_Safe_container<
+ deque, _Allocator, __gnu_debug::_Safe_sequence, false> _Safe;
typedef typename _Base::const_iterator _Base_const_iterator;
typedef typename _Base::iterator _Base_iterator;
typedef __gnu_debug::_Equal_to<_Base_const_iterator> _Equal;
+
public:
typedef typename _Base::reference reference;
typedef typename _Base::const_reference const_reference;
- typedef __gnu_debug::_Safe_iterator<_Base_iterator,deque>
+ typedef __gnu_debug::_Safe_iterator<_Base_iterator, deque>
iterator;
- typedef __gnu_debug::_Safe_iterator<_Base_const_iterator,deque>
+ typedef __gnu_debug::_Safe_iterator<_Base_const_iterator, deque>
const_iterator;
typedef typename _Base::size_type size_type;
@@ -69,8 +75,26 @@
// 23.2.1.1 construct/copy/destroy:
- deque() : _Base() { }
+#if __cplusplus < 201103L
+ deque()
+ : _Base() { }
+ deque(const deque& __x)
+ : _Base(__x) { }
+
+ ~deque() _GLIBCXX_NOEXCEPT { }
+#else
+ deque() = default;
+ deque(const deque&) = default;
+ deque(deque&&) = default;
+
+ deque(initializer_list<value_type> __l,
+ const allocator_type& __a = allocator_type())
+ : _Base(__l, __a) { }
+
+ ~deque() = default;
+#endif
+
explicit
deque(const _Allocator& __a)
: _Base(__a) { }
@@ -103,48 +127,28 @@
__gnu_debug::__base(__last), __a)
{ }
- deque(const deque& __x)
- : _Base(__x) { }
-
deque(const _Base& __x)
: _Base(__x) { }
-#if __cplusplus >= 201103L
- deque(deque&& __x)
- : _Base(std::move(__x))
- { this->_M_swap(__x); }
-
- deque(initializer_list<value_type> __l,
- const allocator_type& __a = allocator_type())
- : _Base(__l, __a) { }
-#endif
-
- ~deque() _GLIBCXX_NOEXCEPT { }
-
+#if __cplusplus < 201103L
deque&
operator=(const deque& __x)
{
- *static_cast<_Base*>(this) = __x;
- this->_M_invalidate_all();
+ this->_M_safe() = __x;
+ _M_base() = __x;
return *this;
}
+#else
+ deque&
+ operator=(const deque&) = default;
-#if __cplusplus >= 201103L
deque&
- operator=(deque&& __x) noexcept
- {
- // NB: DR 1204.
- // NB: DR 675.
- __glibcxx_check_self_move_assign(__x);
- clear();
- swap(__x);
- return *this;
- }
+ operator=(deque&&) = default;
deque&
operator=(initializer_list<value_type> __l)
{
- *static_cast<_Base*>(this) = __l;
+ _M_base() = __l;
this->_M_invalidate_all();
return *this;
}
@@ -559,10 +563,13 @@
}
void
- swap(deque& __x) _GLIBCXX_NOEXCEPT
+ swap(deque& __x)
+#if __cplusplus >= 201103L
+ noexcept( noexcept(declval<_Base>().swap(__x)) )
+#endif
{
+ _Safe::_M_swap(__x);
_Base::swap(__x);
- this->_M_swap(__x);
}
void
Index: include/debug/forward_list
===================================================================
--- include/debug/forward_list (revision 209446)
+++ include/debug/forward_list (working copy)
@@ -33,8 +33,113 @@
#include <forward_list>
#include <debug/safe_sequence.h>
+#include <debug/safe_container.h>
#include <debug/safe_iterator.h>
+namespace __gnu_debug
+{
+ /// Special iterators swap and invalidation for forward_list because of the
+ /// before_begin iterator.
+ template<typename _SafeSequence>
+ class _Safe_forward_list
+ : public _Safe_sequence<_SafeSequence>
+ {
+ _SafeSequence&
+ _M_this() noexcept
+ { return *static_cast<_SafeSequence*>(this); }
+
+ static void
+ _M_swap_aux(_Safe_sequence_base& __lhs,
+ _Safe_iterator_base*& __lhs_iterators,
+ _Safe_sequence_base& __rhs,
+ _Safe_iterator_base*& __rhs_iterators);
+
+ protected:
+ void
+ _M_invalidate_all()
+ {
+ using _Base_const_iterator = __decltype(_M_this()._M_base().cend());
+ this->_M_invalidate_if([this](_Base_const_iterator __it)
+ {
+ return __it != _M_this()._M_base().cbefore_begin()
+ && __it != _M_this()._M_base().cend(); });
+ }
+
+ void _M_swap(_Safe_sequence_base&) noexcept;
+ };
+
+ template<typename _SafeSequence>
+ void
+ _Safe_forward_list<_SafeSequence>::
+ _M_swap_aux(_Safe_sequence_base& __lhs,
+ _Safe_iterator_base*& __lhs_iterators,
+ _Safe_sequence_base& __rhs,
+ _Safe_iterator_base*& __rhs_iterators)
+ {
+ using const_iterator = typename _SafeSequence::const_iterator;
+ _Safe_iterator_base* __bbegin_its = 0;
+ _Safe_iterator_base* __last_bbegin = 0;
+ _SafeSequence& __rseq = static_cast<_SafeSequence&>(__rhs);
+
+ for (_Safe_iterator_base* __iter = __lhs_iterators; __iter;)
+ {
+ // Even iterator are casted to const_iterator, not a problem.
+ const_iterator* __victim = static_cast<const_iterator*>(__iter);
+ __iter = __iter->_M_next;
+ if (__victim->base() == __rseq._M_base().cbefore_begin())
+ {
+ __victim->_M_unlink();
+ if (__lhs_iterators == __victim)
+ __lhs_iterators = __victim->_M_next;
+ if (__bbegin_its)
+ {
+ __victim->_M_next = __bbegin_its;
+ __bbegin_its->_M_prior = __victim;
+ }
+ else
+ __last_bbegin = __victim;
+ __bbegin_its = __victim;
+ }
+ else
+ __victim->_M_sequence = &__lhs;
+ }
+
+ if (__bbegin_its)
+ {
+ if (__rhs_iterators)
+ {
+ __rhs_iterators->_M_prior = __last_bbegin;
+ __last_bbegin->_M_next = __rhs_iterators;
+ }
+ __rhs_iterators = __bbegin_its;
+ }
+ }
+
+ /* Special forward_list _M_swap version that do not swap the
+ * before-begin ownership.*/
+ template<typename _SafeSequence>
+ void
+ _Safe_forward_list<_SafeSequence>::
+ _M_swap(_Safe_sequence_base& __other) noexcept
+ {
+ __gnu_cxx::__scoped_lock sentry(_M_this()._M_get_mutex());
+ std::swap(_M_this()._M_iterators, __other._M_iterators);
+ std::swap(_M_this()._M_const_iterators, __other._M_const_iterators);
+ // Useless, always 1 on forward_list
+ //std::swap(_M_this()_M_version, __other._M_version);
+ _Safe_iterator_base* __this_its = _M_this()._M_iterators;
+ _M_swap_aux(__other, __other._M_iterators,
+ _M_this(), _M_this()._M_iterators);
+ _Safe_iterator_base* __this_const_its = _M_this()._M_const_iterators;
+ _M_swap_aux(__other, __other._M_const_iterators,
+ _M_this(), _M_this()._M_const_iterators);
+ _M_swap_aux(_M_this(), __this_its,
+ __other, __other._M_iterators);
+ _M_swap_aux(_M_this(), __this_const_its,
+ __other, __other._M_const_iterators);
+ }
+}
+
namespace std _GLIBCXX_VISIBILITY(default)
{
namespace __debug
@@ -42,119 +147,88 @@
/// Class std::forward_list with safety/checking/debug instrumentation.
template<typename _Tp, typename _Alloc = std::allocator<_Tp> >
class forward_list
- : public _GLIBCXX_STD_C::forward_list<_Tp, _Alloc>,
- public __gnu_debug::_Safe_sequence<forward_list<_Tp, _Alloc> >
+ : public __gnu_debug::_Safe_container<
+ forward_list<_Tp, _Alloc>, _Alloc, __gnu_debug::_Safe_forward_list>,
+ public _GLIBCXX_STD_C::forward_list<_Tp, _Alloc>
{
typedef _GLIBCXX_STD_C::forward_list<_Tp, _Alloc> _Base;
+ typedef __gnu_debug::_Safe_container<
+ forward_list, _Alloc, __gnu_debug::_Safe_forward_list> _Safe;
typedef typename _Base::iterator _Base_iterator;
typedef typename _Base::const_iterator _Base_const_iterator;
- typedef typename __gnu_cxx::__alloc_traits<_Alloc>::template
- rebind<_GLIBCXX_STD_C::_Fwd_list_node<_Tp>>::other _Node_alloc_type;
-
- typedef __gnu_cxx::__alloc_traits<_Node_alloc_type> _Node_alloc_traits;
-
public:
typedef typename _Base::reference reference;
typedef typename _Base::const_reference const_reference;
- typedef __gnu_debug::_Safe_iterator<_Base_iterator,
- forward_list> iterator;
- typedef __gnu_debug::_Safe_iterator<_Base_const_iterator,
- forward_list> const_iterator;
+ typedef __gnu_debug::_Safe_iterator<
+ _Base_iterator, forward_list> iterator;
+ typedef __gnu_debug::_Safe_iterator<
+ _Base_const_iterator, forward_list> const_iterator;
typedef typename _Base::size_type size_type;
typedef typename _Base::difference_type difference_type;
typedef _Tp value_type;
- typedef _Alloc allocator_type;
+ typedef typename _Base::allocator_type allocator_type;
typedef typename _Base::pointer pointer;
typedef typename _Base::const_pointer const_pointer;
// 23.2.3.1 construct/copy/destroy:
explicit
- forward_list(const _Alloc& __al = _Alloc())
+ forward_list(const allocator_type& __al = allocator_type())
: _Base(__al) { }
- forward_list(const forward_list& __list, const _Alloc& __al)
+ forward_list(const forward_list& __list, const allocator_type& __al)
: _Base(__list, __al)
{ }
- forward_list(forward_list&& __list, const _Alloc& __al)
- : _Base(std::move(__list._M_base()), __al)
- {
- if (__list.get_allocator() == __al)
- this->_M_swap(__list);
- else
- __list._M_invalidate_all();
- }
+ forward_list(forward_list&& __list, const allocator_type& __al)
+ : _Safe(std::move(__list), __al),
+ _Base(std::move(__list), __al)
+ { }
explicit
- forward_list(size_type __n, const _Alloc& __al = _Alloc())
+ forward_list(size_type __n, const allocator_type& __al = allocator_type())
: _Base(__n, __al)
{ }
forward_list(size_type __n, const _Tp& __value,
- const _Alloc& __al = _Alloc())
+ const allocator_type& __al = allocator_type())
: _Base(__n, __value, __al)
{ }
template<typename _InputIterator,
typename = std::_RequireInputIter<_InputIterator>>
forward_list(_InputIterator __first, _InputIterator __last,
- const _Alloc& __al = _Alloc())
+ const allocator_type& __al = allocator_type())
: _Base(__gnu_debug::__base(__gnu_debug::__check_valid_range(__first,
__last)),
__gnu_debug::__base(__last), __al)
{ }
- forward_list(const forward_list& __list)
- : _Base(__list)
- { }
+ forward_list(const forward_list&) = default;
- forward_list(forward_list&& __list) noexcept
- : _Base(std::move(__list._M_base()))
- {
- this->_M_swap(__list);
- }
+ forward_list(forward_list&&) = default;
forward_list(std::initializer_list<_Tp> __il,
- const _Alloc& __al = _Alloc())
+ const allocator_type& __al = allocator_type())
: _Base(__il, __al)
{ }
- ~forward_list() noexcept
- { }
+ ~forward_list() = default;
forward_list&
- operator=(const forward_list& __list)
- {
- static_cast<_Base&>(*this) = __list;
- this->_M_invalidate_all();
- return *this;
- }
+ operator=(const forward_list&) = default;
forward_list&
- operator=(forward_list&& __list)
- noexcept(_Node_alloc_traits::_S_nothrow_move())
- {
- __glibcxx_check_self_move_assign(__list);
- bool __xfer_memory = _Node_alloc_traits::_S_propagate_on_move_assign()
- || __list.get_allocator() == this->get_allocator();
- static_cast<_Base&>(*this) = std::move(__list);
- if (__xfer_memory)
- this->_M_swap(__list);
- else
- this->_M_invalidate_all();
- __list._M_invalidate_all();
- return *this;
- }
+ operator=(forward_list&&) = default;
forward_list&
operator=(std::initializer_list<_Tp> __il)
{
- static_cast<_Base&>(*this) = __il;
+ _M_base() = __il;
this->_M_invalidate_all();
return *this;
}
@@ -347,12 +421,10 @@
void
swap(forward_list& __list)
- noexcept(_Node_alloc_traits::_S_nothrow_swap())
+ noexcept( noexcept(declval<_Base>().swap(__list)) )
{
- if (!_Node_alloc_traits::_S_propagate_on_swap())
- __glibcxx_check_equal_allocs(__list);
+ _Safe::_M_swap(__list);
_Base::swap(__list);
- this->_M_swap(__list);
}
void
@@ -644,93 +716,9 @@
const _Base&
_M_base() const noexcept { return *this; }
-
- private:
- void
- _M_invalidate_all()
- {
- this->_M_invalidate_if([this](_Base_const_iterator __it)
- {
- return __it != this->_M_base().cbefore_begin()
- && __it != this->_M_base().cend();
- });
- }
- typedef __gnu_debug::_Safe_iterator_base _Safe_iterator_base;
- static void
- _M_swap_aux(forward_list& __lhs,
- _Safe_iterator_base*& __lhs_iterators,
- forward_list& __rhs,
- _Safe_iterator_base*& __rhs_iterators);
- void _M_swap(forward_list& __list);
};
template<typename _Tp, typename _Alloc>
- void
- forward_list<_Tp, _Alloc>::
- _M_swap_aux(forward_list<_Tp, _Alloc>& __lhs,
- __gnu_debug::_Safe_iterator_base*& __lhs_iterators,
- forward_list<_Tp, _Alloc>& __rhs,
- __gnu_debug::_Safe_iterator_base*& __rhs_iterators)
- {
- using __gnu_debug::_Safe_iterator_base;
- _Safe_iterator_base* __bbegin_its = 0;
- _Safe_iterator_base* __last_bbegin = 0;
- for (_Safe_iterator_base* __iter = __lhs_iterators; __iter;)
- {
- // Even iterator are casted to const_iterator, not a problem.
- const_iterator* __victim = static_cast<const_iterator*>(__iter);
- __iter = __iter->_M_next;
- if (__victim->base() == __rhs._M_base().cbefore_begin())
- {
- __victim->_M_unlink();
- if (__lhs_iterators == __victim)
- __lhs_iterators = __victim->_M_next;
- if (__bbegin_its)
- {
- __victim->_M_next = __bbegin_its;
- __bbegin_its->_M_prior = __victim;
- }
- else
- __last_bbegin = __victim;
- __bbegin_its = __victim;
- }
- else
- __victim->_M_sequence = &__lhs;
- }
-
- if (__bbegin_its)
- {
- if (__rhs_iterators)
- {
- __rhs_iterators->_M_prior = __last_bbegin;
- __last_bbegin->_M_next = __rhs_iterators;
- }
- __rhs_iterators = __bbegin_its;
- }
- }
-
- /* Special forward_list _M_swap version that do not swap the
- * before-begin ownership.*/
- template<typename _Tp, typename _Alloc>
- void
- forward_list<_Tp, _Alloc>::
- _M_swap(forward_list<_Tp, _Alloc>& __list)
- {
- __gnu_cxx::__scoped_lock sentry(this->_M_get_mutex());
- std::swap(this->_M_iterators, __list._M_iterators);
- std::swap(this->_M_const_iterators, __list._M_const_iterators);
- // Useless, always 1 on forward_list
- //std::swap(this->_M_version, __list._M_version);
- _Safe_iterator_base* __this_its = this->_M_iterators;
- _M_swap_aux(__list, __list._M_iterators, *this, this->_M_iterators);
- _Safe_iterator_base* __this_const_its = this->_M_const_iterators;
- _M_swap_aux(__list, __list._M_const_iterators, *this,
- this->_M_const_iterators);
- _M_swap_aux(*this, __this_its, __list, __list._M_iterators);
- _M_swap_aux(*this, __this_const_its, __list, __list._M_const_iterators);
- }
-
- template<typename _Tp, typename _Alloc>
bool
operator==(const forward_list<_Tp, _Alloc>& __lx,
const forward_list<_Tp, _Alloc>& __ly)
Index: include/debug/list
===================================================================
--- include/debug/list (revision 209446)
+++ include/debug/list (working copy)
@@ -31,6 +31,7 @@
#include <list>
#include <debug/safe_sequence.h>
+#include <debug/safe_container.h>
#include <debug/safe_iterator.h>
namespace std _GLIBCXX_VISIBILITY(default)
@@ -40,15 +41,20 @@
/// Class std::list with safety/checking/debug instrumentation.
template<typename _Tp, typename _Allocator = std::allocator<_Tp> >
class list
- : public _GLIBCXX_STD_C::list<_Tp, _Allocator>,
- public __gnu_debug::_Safe_sequence<list<_Tp, _Allocator> >
+ : public __gnu_debug::_Safe_container<
+ list<_Tp, _Allocator>, _Allocator,
+ __gnu_debug::_Safe_node_sequence, false>,
+ public _GLIBCXX_STD_C::list<_Tp, _Allocator>
{
typedef _GLIBCXX_STD_C::list<_Tp, _Allocator> _Base;
+ typedef __gnu_debug::_Safe_container<
+ list, _Allocator, __gnu_debug::_Safe_node_sequence, false> _Safe;
typedef typename _Base::iterator _Base_iterator;
typedef typename _Base::const_iterator _Base_const_iterator;
typedef __gnu_debug::_Equal_to<_Base_const_iterator> _Equal;
typedef __gnu_debug::_Not_equal_to<_Base_const_iterator> _Not_equal;
+
public:
typedef typename _Base::reference reference;
typedef typename _Base::const_reference const_reference;
@@ -70,9 +76,26 @@
// 23.2.2.1 construct/copy/destroy:
+#if __cplusplus < 201103L
list() _GLIBCXX_NOEXCEPT
: _Base() { }
+ list(const list& __x)
+ : _Base(__x) { }
+
+ ~list() _GLIBCXX_NOEXCEPT { }
+#else
+ list() = default;
+ list(const list&) = default;
+ list(list&&) = default;
+
+ list(initializer_list<value_type> __l,
+ const allocator_type& __a = allocator_type())
+ : _Base(__l, __a) { }
+
+ ~list() = default;
+#endif
+
explicit
list(const _Allocator& __a) _GLIBCXX_NOEXCEPT
: _Base(__a) { }
@@ -105,49 +128,29 @@
__gnu_debug::__base(__last), __a)
{ }
- list(const list& __x)
- : _Base(__x) { }
-
list(const _Base& __x)
: _Base(__x) { }
-#if __cplusplus >= 201103L
- list(list&& __x) noexcept
- : _Base(std::move(__x))
- { this->_M_swap(__x); }
-
- list(initializer_list<value_type> __l,
- const allocator_type& __a = allocator_type())
- : _Base(__l, __a) { }
-#endif
-
- ~list() _GLIBCXX_NOEXCEPT { }
-
+#if __cplusplus < 201103L
list&
operator=(const list& __x)
{
- static_cast<_Base&>(*this) = __x;
- this->_M_invalidate_all();
+ this->_M_safe() = __x;
+ _M_base() = __x;
return *this;
}
+#else
+ list&
+ operator=(const list&) = default;
-#if __cplusplus >= 201103L
list&
- operator=(list&& __x)
- {
- // NB: DR 1204.
- // NB: DR 675.
- __glibcxx_check_self_move_assign(__x);
- clear();
- swap(__x);
- return *this;
- }
+ operator=(list&&) = default;
list&
operator=(initializer_list<value_type> __l)
{
- static_cast<_Base&>(*this) = __l;
this->_M_invalidate_all();
+ _M_base() = __l;
return *this;
}
@@ -245,16 +248,14 @@
{
this->_M_detach_singular();
- // if __sz < size(), invalidate all iterators in [begin+__sz, end())
+ // if __sz < size(), invalidate all iterators in [begin + __sz, end())
_Base_iterator __victim = _Base::begin();
_Base_iterator __end = _Base::end();
for (size_type __i = __sz; __victim != __end && __i > 0; --__i)
++__victim;
for (; __victim != __end; ++__victim)
- {
this->_M_invalidate_if(_Equal(__victim));
- }
__try
{
@@ -272,16 +273,14 @@
{
this->_M_detach_singular();
- // if __sz < size(), invalidate all iterators in [begin+__sz, end())
+ // if __sz < size(), invalidate all iterators in [begin + __sz, end())
_Base_iterator __victim = _Base::begin();
_Base_iterator __end = _Base::end();
for (size_type __i = __sz; __victim != __end && __i > 0; --__i)
++__victim;
for (; __victim != __end; ++__victim)
- {
this->_M_invalidate_if(_Equal(__victim));
- }
__try
{
@@ -299,16 +298,14 @@
{
this->_M_detach_singular();
- // if __sz < size(), invalidate all iterators in [begin+__sz, end())
+ // if __sz < size(), invalidate all iterators in [begin + __sz, end())
_Base_iterator __victim = _Base::begin();
_Base_iterator __end = _Base::end();
for (size_type __i = __sz; __victim != __end && __i > 0; --__i)
++__victim;
for (; __victim != __end; ++__victim)
- {
this->_M_invalidate_if(_Equal(__victim));
- }
__try
{
@@ -504,9 +501,12 @@
void
swap(list& __x)
+#if __cplusplus >= 201103L
+ noexcept( noexcept(declval<_Base>().swap(__x)) )
+#endif
{
+ _Safe::_M_swap(__x);
_Base::swap(__x);
- this->_M_swap(__x);
}
void
@@ -742,13 +742,6 @@
const _Base&
_M_base() const _GLIBCXX_NOEXCEPT { return *this; }
-
- private:
- void
- _M_invalidate_all()
- {
- this->_M_invalidate_if(_Not_equal(_Base::end()));
- }
};
template<typename _Tp, typename _Alloc>
Index: include/debug/macros.h
===================================================================
--- include/debug/macros.h (revision 209446)
+++ include/debug/macros.h (working copy)
@@ -347,10 +347,10 @@
_M_message(__gnu_debug::__msg_valid_load_factor) \
._M_sequence(*this, "this"))
-#define __glibcxx_check_equal_allocs(_Other) \
-_GLIBCXX_DEBUG_VERIFY(this->get_allocator() == _Other.get_allocator(), \
+#define __glibcxx_check_equal_allocs(_This, _Other) \
+_GLIBCXX_DEBUG_VERIFY(_This.get_allocator() == _Other.get_allocator(), \
_M_message(__gnu_debug::__msg_equal_allocs) \
- ._M_sequence(*this, "this"))
+ ._M_sequence(_This, "this"))
#ifdef _GLIBCXX_DEBUG_PEDANTIC
# define __glibcxx_check_string(_String) _GLIBCXX_DEBUG_ASSERT(_String != 0)
Index: include/debug/map.h
===================================================================
--- include/debug/map.h (revision 209446)
+++ include/debug/map.h (working copy)
@@ -30,6 +30,7 @@
#define _GLIBCXX_DEBUG_MAP_H 1
#include <debug/safe_sequence.h>
+#include <debug/safe_container.h>
#include <debug/safe_iterator.h>
#include <utility>
@@ -41,19 +42,20 @@
template<typename _Key, typename _Tp, typename _Compare = std::less<_Key>,
typename _Allocator = std::allocator<std::pair<const _Key, _Tp> > >
class map
- : public _GLIBCXX_STD_C::map<_Key, _Tp, _Compare, _Allocator>,
- public __gnu_debug::_Safe_sequence<map<_Key, _Tp, _Compare, _Allocator> >
+ : public __gnu_debug::_Safe_container<
+ map<_Key, _Tp, _Compare, _Allocator>, _Allocator,
+ __gnu_debug::_Safe_node_sequence>,
+ public _GLIBCXX_STD_C::map<_Key, _Tp, _Compare, _Allocator>
{
- typedef _GLIBCXX_STD_C::map<_Key, _Tp, _Compare, _Allocator> _Base;
+ typedef _GLIBCXX_STD_C::map<
+ _Key, _Tp, _Compare, _Allocator> _Base;
+ typedef __gnu_debug::_Safe_container<
+ map, _Allocator, __gnu_debug::_Safe_node_sequence> _Safe;
typedef typename _Base::const_iterator _Base_const_iterator;
typedef typename _Base::iterator _Base_iterator;
typedef __gnu_debug::_Equal_to<_Base_const_iterator> _Equal;
-#if __cplusplus >= 201103L
- typedef __gnu_cxx::__alloc_traits<typename
- _Base::allocator_type> _Alloc_traits;
-#endif
public:
// types:
typedef _Key key_type;
@@ -78,33 +80,18 @@
// 23.3.1.1 construct/copy/destroy:
+#if __cplusplus < 201103L
map() : _Base() { }
- explicit map(const _Compare& __comp,
- const _Allocator& __a = _Allocator())
- : _Base(__comp, __a) { }
-
- template<typename _InputIterator>
- map(_InputIterator __first, _InputIterator __last,
- const _Compare& __comp = _Compare(),
- const _Allocator& __a = _Allocator())
- : _Base(__gnu_debug::__base(__gnu_debug::__check_valid_range(__first,
- __last)),
- __gnu_debug::__base(__last),
- __comp, __a) { }
-
map(const map& __x)
: _Base(__x) { }
- map(const _Base& __x)
- : _Base(__x) { }
+ ~map() _GLIBCXX_NOEXCEPT { }
+#else
+ map() = default;
+ map(const map&) = default;
+ map(map&&) = default;
-#if __cplusplus >= 201103L
- map(map&& __x)
- noexcept(is_nothrow_copy_constructible<_Compare>::value)
- : _Base(std::move(__x))
- { this->_M_swap(__x); }
-
map(initializer_list<value_type> __l,
const _Compare& __c = _Compare(),
const allocator_type& __a = allocator_type())
@@ -118,7 +105,8 @@
: _Base(__m, __a) { }
map(map&& __m, const allocator_type& __a)
- : _Base(std::move(__m._M_base()), __a) { }
+ : _Safe(std::move(__m), __a),
+ _Base(std::move(__m), __a) { }
map(initializer_list<value_type> __l, const allocator_type& __a)
: _Base(__l, __a) { }
@@ -130,34 +118,40 @@
__last)),
__gnu_debug::__base(__last), __a)
{ }
+
+ ~map() = default;
#endif
- ~map() _GLIBCXX_NOEXCEPT { }
+ map(const _Base& __x)
+ : _Base(__x) { }
+ explicit map(const _Compare& __comp,
+ const _Allocator& __a = _Allocator())
+ : _Base(__comp, __a) { }
+
+ template<typename _InputIterator>
+ map(_InputIterator __first, _InputIterator __last,
+ const _Compare& __comp = _Compare(),
+ const _Allocator& __a = _Allocator())
+ : _Base(__gnu_debug::__base(__gnu_debug::__check_valid_range(__first,
+ __last)),
+ __gnu_debug::__base(__last),
+ __comp, __a) { }
+
+#if __cplusplus < 201103L
map&
operator=(const map& __x)
{
+ this->_M_safe() = __x;
_M_base() = __x;
- this->_M_invalidate_all();
return *this;
}
+#else
+ map&
+ operator=(const map&) = default;
-#if __cplusplus >= 201103L
map&
- operator=(map&& __x)
- noexcept(_Alloc_traits::_S_nothrow_move())
- {
- __glibcxx_check_self_move_assign(__x);
- bool __xfer_memory = _Alloc_traits::_S_propagate_on_move_assign()
- || __x.get_allocator() == this->get_allocator();
- _M_base() = std::move(__x._M_base());
- if (__xfer_memory)
- this->_M_swap(__x);
- else
- this->_M_invalidate_all();
- __x._M_invalidate_all();
- return *this;
- }
+ operator=(map&&) = default;
map&
operator=(initializer_list<value_type> __l)
@@ -395,15 +389,11 @@
void
swap(map& __x)
#if __cplusplus >= 201103L
- noexcept(_Alloc_traits::_S_nothrow_swap())
+ noexcept( noexcept(declval<_Base>().swap(__x)) )
#endif
{
-#if __cplusplus >= 201103L
- if (!_Alloc_traits::_S_propagate_on_swap())
- __glibcxx_check_equal_allocs(__x);
-#endif
+ _Safe::_M_swap(__x);
_Base::swap(__x);
- this->_M_swap(__x);
}
void
@@ -467,14 +457,6 @@
const _Base&
_M_base() const _GLIBCXX_NOEXCEPT { return *this; }
-
- private:
- void
- _M_invalidate_all()
- {
- typedef __gnu_debug::_Not_equal_to<_Base_const_iterator> _Not_equal;
- this->_M_invalidate_if(_Not_equal(_M_base().end()));
- }
};
template<typename _Key, typename _Tp,
Index: include/debug/multimap.h
===================================================================
--- include/debug/multimap.h (revision 209446)
+++ include/debug/multimap.h (working copy)
@@ -30,6 +30,7 @@
#define _GLIBCXX_DEBUG_MULTIMAP_H 1
#include <debug/safe_sequence.h>
+#include <debug/safe_container.h>
#include <debug/safe_iterator.h>
#include <utility>
@@ -41,20 +42,20 @@
template<typename _Key, typename _Tp, typename _Compare = std::less<_Key>,
typename _Allocator = std::allocator<std::pair<const _Key, _Tp> > >
class multimap
- : public _GLIBCXX_STD_C::multimap<_Key, _Tp, _Compare, _Allocator>,
- public __gnu_debug::_Safe_sequence<multimap<_Key, _Tp,
- _Compare, _Allocator> >
+ : public __gnu_debug::_Safe_container<
+ multimap<_Key, _Tp, _Compare, _Allocator>, _Allocator,
+ __gnu_debug::_Safe_node_sequence>,
+ public _GLIBCXX_STD_C::multimap<_Key, _Tp, _Compare, _Allocator>
{
- typedef _GLIBCXX_STD_C::multimap<_Key, _Tp, _Compare, _Allocator> _Base;
+ typedef _GLIBCXX_STD_C::multimap<
+ _Key, _Tp, _Compare, _Allocator> _Base;
+ typedef __gnu_debug::_Safe_container<
+ multimap, _Allocator, __gnu_debug::_Safe_node_sequence> _Safe;
typedef typename _Base::const_iterator _Base_const_iterator;
typedef typename _Base::iterator _Base_iterator;
typedef __gnu_debug::_Equal_to<_Base_const_iterator> _Equal;
-#if __cplusplus >= 201103L
- typedef __gnu_cxx::__alloc_traits<typename
- _Base::allocator_type> _Alloc_traits;
-#endif
public:
// types:
typedef _Key key_type;
@@ -79,33 +80,18 @@
// 23.3.1.1 construct/copy/destroy:
+#if __cplusplus < 201103L
multimap() : _Base() { }
- explicit multimap(const _Compare& __comp,
- const _Allocator& __a = _Allocator())
- : _Base(__comp, __a) { }
-
- template<typename _InputIterator>
- multimap(_InputIterator __first, _InputIterator __last,
- const _Compare& __comp = _Compare(),
- const _Allocator& __a = _Allocator())
- : _Base(__gnu_debug::__base(__gnu_debug::__check_valid_range(__first,
- __last)),
- __gnu_debug::__base(__last),
- __comp, __a) { }
-
multimap(const multimap& __x)
: _Base(__x) { }
- multimap(const _Base& __x)
- : _Base(__x) { }
+ ~multimap() _GLIBCXX_NOEXCEPT { }
+#else
+ multimap() = default;
+ multimap(const multimap&) = default;
+ multimap(multimap&&) = default;
-#if __cplusplus >= 201103L
- multimap(multimap&& __x)
- noexcept(is_nothrow_copy_constructible<_Compare>::value)
- : _Base(std::move(__x))
- { this->_M_swap(__x); }
-
multimap(initializer_list<value_type> __l,
const _Compare& __c = _Compare(),
const allocator_type& __a = allocator_type())
@@ -119,47 +105,52 @@
: _Base(__m, __a) { }
multimap(multimap&& __m, const allocator_type& __a)
- : _Base(std::move(__m._M_base()), __a) { }
+ : _Safe(std::move(__m), __a),
+ _Base(std::move(__m), __a) { }
multimap(initializer_list<value_type> __l, const allocator_type& __a)
- : _Base(__l, __a)
- { }
+ : _Base(__l, __a) { }
template<typename _InputIterator>
multimap(_InputIterator __first, _InputIterator __last,
const allocator_type& __a)
: _Base(__gnu_debug::__base(__gnu_debug::__check_valid_range(__first,
__last)),
- __gnu_debug::__base(__last), __a)
- { }
+ __gnu_debug::__base(__last), __a) { }
+
+ ~multimap() = default;
#endif
- ~multimap() _GLIBCXX_NOEXCEPT { }
+ explicit multimap(const _Compare& __comp,
+ const _Allocator& __a = _Allocator())
+ : _Base(__comp, __a) { }
+ template<typename _InputIterator>
+ multimap(_InputIterator __first, _InputIterator __last,
+ const _Compare& __comp = _Compare(),
+ const _Allocator& __a = _Allocator())
+ : _Base(__gnu_debug::__base(__gnu_debug::__check_valid_range(__first,
+ __last)),
+ __gnu_debug::__base(__last),
+ __comp, __a) { }
+
+ multimap(const _Base& __x)
+ : _Base(__x) { }
+
+#if __cplusplus < 201103L
multimap&
operator=(const multimap& __x)
{
+ this->_M_safe() = __x;
_M_base() = __x;
- this->_M_invalidate_all();
return *this;
}
+#else
+ multimap&
+ operator=(const multimap&) = default;
-#if __cplusplus >= 201103L
multimap&
- operator=(multimap&& __x)
- noexcept(_Alloc_traits::_S_nothrow_move())
- {
- __glibcxx_check_self_move_assign(__x);
- bool __xfer_memory = _Alloc_traits::_S_propagate_on_move_assign()
- || __x.get_allocator() == this->get_allocator();
- _M_base() = std::move(__x._M_base());
- if (__xfer_memory)
- this->_M_swap(__x);
- else
- this->_M_invalidate_all();
- __x._M_invalidate_all();
- return *this;
- }
+ operator=(multimap&&) = default;
multimap&
operator=(initializer_list<value_type> __l)
@@ -379,15 +370,11 @@
void
swap(multimap& __x)
#if __cplusplus >= 201103L
- noexcept(_Alloc_traits::_S_nothrow_swap())
+ noexcept( noexcept(declval<_Base>().swap(__x)) )
#endif
{
-#if __cplusplus >= 201103L
- if (!_Alloc_traits::_S_propagate_on_swap())
- __glibcxx_check_equal_allocs(__x);
-#endif
+ _Safe::_M_swap(__x);
_Base::swap(__x);
- this->_M_swap(__x);
}
void
@@ -451,14 +438,6 @@
const _Base&
_M_base() const _GLIBCXX_NOEXCEPT { return *this; }
-
- private:
- void
- _M_invalidate_all()
- {
- typedef __gnu_debug::_Not_equal_to<_Base_const_iterator> _Not_equal;
- this->_M_invalidate_if(_Not_equal(_Base::end()));
- }
};
template<typename _Key, typename _Tp,
Index: include/debug/multiset.h
===================================================================
--- include/debug/multiset.h (revision 209446)
+++ include/debug/multiset.h (working copy)
@@ -30,6 +30,7 @@
#define _GLIBCXX_DEBUG_MULTISET_H 1
#include <debug/safe_sequence.h>
+#include <debug/safe_container.h>
#include <debug/safe_iterator.h>
#include <utility>
@@ -41,19 +42,19 @@
template<typename _Key, typename _Compare = std::less<_Key>,
typename _Allocator = std::allocator<_Key> >
class multiset
- : public _GLIBCXX_STD_C::multiset<_Key, _Compare, _Allocator>,
- public __gnu_debug::_Safe_sequence<multiset<_Key, _Compare, _Allocator> >
+ : public __gnu_debug::_Safe_container<
+ multiset<_Key, _Compare, _Allocator>, _Allocator,
+ __gnu_debug::_Safe_node_sequence>,
+ public _GLIBCXX_STD_C::multiset<_Key, _Compare, _Allocator>
{
typedef _GLIBCXX_STD_C::multiset<_Key, _Compare, _Allocator> _Base;
+ typedef __gnu_debug::_Safe_container<
+ multiset, _Allocator, __gnu_debug::_Safe_node_sequence> _Safe;
typedef typename _Base::const_iterator _Base_const_iterator;
typedef typename _Base::iterator _Base_iterator;
typedef __gnu_debug::_Equal_to<_Base_const_iterator> _Equal;
-#if __cplusplus >= 201103L
- typedef __gnu_cxx::__alloc_traits<typename
- _Base::allocator_type> _Alloc_traits;
-#endif
public:
// types:
typedef _Key key_type;
@@ -78,33 +79,18 @@
// 23.3.3.1 construct/copy/destroy:
+#if __cplusplus < 201103L
multiset() : _Base() { }
- explicit multiset(const _Compare& __comp,
- const _Allocator& __a = _Allocator())
- : _Base(__comp, __a) { }
-
- template<typename _InputIterator>
- multiset(_InputIterator __first, _InputIterator __last,
- const _Compare& __comp = _Compare(),
- const _Allocator& __a = _Allocator())
- : _Base(__gnu_debug::__base(__gnu_debug::__check_valid_range(__first,
- __last)),
- __gnu_debug::__base(__last),
- __comp, __a) { }
-
multiset(const multiset& __x)
: _Base(__x) { }
- multiset(const _Base& __x)
- : _Base(__x) { }
+ ~multiset() _GLIBCXX_NOEXCEPT { }
+#else
+ multiset() = default;
+ multiset(const multiset&) = default;
+ multiset(multiset&&) = default;
-#if __cplusplus >= 201103L
- multiset(multiset&& __x)
- noexcept(is_nothrow_copy_constructible<_Compare>::value)
- : _Base(std::move(__x))
- { this->_M_swap(__x); }
-
multiset(initializer_list<value_type> __l,
const _Compare& __comp = _Compare(),
const allocator_type& __a = allocator_type())
@@ -118,7 +104,8 @@
: _Base(__m, __a) { }
multiset(multiset&& __m, const allocator_type& __a)
- : _Base(std::move(__m._M_base()), __a) { }
+ : _Safe(std::move(__m), __a),
+ _Base(std::move(__m), __a) { }
multiset(initializer_list<value_type> __l, const allocator_type& __a)
: _Base(__l, __a)
@@ -129,36 +116,41 @@
const allocator_type& __a)
: _Base(__gnu_debug::__base(__gnu_debug::__check_valid_range(__first,
__last)),
- __gnu_debug::__base(__last), __a)
- { }
+ __gnu_debug::__base(__last), __a) { }
+
+ ~multiset() = default;
#endif
- ~multiset() _GLIBCXX_NOEXCEPT { }
+ explicit multiset(const _Compare& __comp,
+ const _Allocator& __a = _Allocator())
+ : _Base(__comp, __a) { }
+ template<typename _InputIterator>
+ multiset(_InputIterator __first, _InputIterator __last,
+ const _Compare& __comp = _Compare(),
+ const _Allocator& __a = _Allocator())
+ : _Base(__gnu_debug::__base(__gnu_debug::__check_valid_range(__first,
+ __last)),
+ __gnu_debug::__base(__last),
+ __comp, __a) { }
+
+ multiset(const _Base& __x)
+ : _Base(__x) { }
+
+#if __cplusplus < 201103L
multiset&
operator=(const multiset& __x)
{
+ this->_M_safe() = __x;
_M_base() = __x;
- this->_M_invalidate_all();
return *this;
}
+#else
+ multiset&
+ operator=(const multiset&) = default;
-#if __cplusplus >= 201103L
multiset&
- operator=(multiset&& __x)
- noexcept(_Alloc_traits::_S_nothrow_move())
- {
- __glibcxx_check_self_move_assign(__x);
- bool __xfer_memory = _Alloc_traits::_S_propagate_on_move_assign()
- || __x.get_allocator() == this->get_allocator();
- _M_base() = std::move(__x._M_base());
- if (__xfer_memory)
- this->_M_swap(__x);
- else
- this->_M_invalidate_all();
- __x._M_invalidate_all();
- return *this;
- }
+ operator=(multiset&&) = default;
multiset&
operator=(initializer_list<value_type> __l)
@@ -233,7 +225,8 @@
iterator
emplace(_Args&&... __args)
{
- return iterator(_Base::emplace(std::forward<_Args>(__args)...), this);
+ return iterator(_Base::emplace(std::forward<_Args>(__args)...),
+ this);
}
template<typename... _Args>
@@ -364,15 +357,11 @@
void
swap(multiset& __x)
#if __cplusplus >= 201103L
- noexcept(_Alloc_traits::_S_nothrow_swap())
+ noexcept( noexcept(declval<_Base>().swap(__x)) )
#endif
{
-#if __cplusplus >= 201103L
- if (!_Alloc_traits::_S_propagate_on_swap())
- __glibcxx_check_equal_allocs(__x);
-#endif
+ _Safe::_M_swap(__x);
_Base::swap(__x);
- this->_M_swap(__x);
}
void
@@ -444,14 +433,6 @@
const _Base&
_M_base() const _GLIBCXX_NOEXCEPT { return *this; }
-
- private:
- void
- _M_invalidate_all()
- {
- typedef __gnu_debug::_Not_equal_to<_Base_const_iterator> _Not_equal;
- this->_M_invalidate_if(_Not_equal(_Base::end()));
- }
};
template<typename _Key, typename _Compare, typename _Allocator>
Index: include/debug/safe_base.h
===================================================================
--- include/debug/safe_base.h (revision 209446)
+++ include/debug/safe_base.h (working copy)
@@ -188,22 +188,18 @@
protected:
// Initialize with a version number of 1 and no iterators
- _Safe_sequence_base()
+ _Safe_sequence_base() _GLIBCXX_NOEXCEPT
: _M_iterators(0), _M_const_iterators(0), _M_version(1)
{ }
#if __cplusplus >= 201103L
_Safe_sequence_base(const _Safe_sequence_base&) noexcept
: _Safe_sequence_base() { }
-
- _Safe_sequence_base(_Safe_sequence_base&& __x) noexcept
- : _Safe_sequence_base()
- { _M_swap(__x); }
#endif
/** Notify all iterators that reference this sequence that the
sequence is being destroyed. */
- ~_Safe_sequence_base()
+ ~_Safe_sequence_base() _GLIBCXX_NOEXCEPT
{ this->_M_detach_all(); }
/** Detach all iterators, leaving them singular. */
@@ -231,7 +227,7 @@
* one container now reference the other container.
*/
void
- _M_swap(_Safe_sequence_base& __x);
+ _M_swap(_Safe_sequence_base& __x) _GLIBCXX_NOEXCEPT;
/** For use in _Safe_sequence. */
__gnu_cxx::__mutex& _M_get_mutex() throw ();
Index: include/debug/safe_container.h
===================================================================
--- include/debug/safe_container.h (revision 0)
+++ include/debug/safe_container.h (working copy)
@@ -0,0 +1,125 @@
+// Safe container implementation -*- C++ -*-
+
+// Copyright (C) 2014 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.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+// <http://www.gnu.org/licenses/>.
+
+/** @file debug/safe_container.h
+ * This file is a GNU debug extension to the Standard C++ Library.
+ */
+
+#ifndef _GLIBCXX_DEBUG_SAFE_CONTAINER_H
+#define _GLIBCXX_DEBUG_SAFE_CONTAINER_H 1
+
+#include <ext/alloc_traits.h>
+
+namespace __gnu_debug
+{
+ /// Safe class dealing with some allocator dependent operations.
+ template<typename _SafeContainer,
+ typename _Alloc,
+ template<typename> class _SafeBase,
+ bool _IsCpp11AllocatorAware = true>
+ class _Safe_container
+ : public _SafeBase<_SafeContainer>
+ {
+ typedef _SafeBase<_SafeContainer> _Base;
+
+ _SafeContainer&
+ _M_cont() _GLIBCXX_NOEXCEPT
+ { return *static_cast<_SafeContainer*>(this); }
+
+ protected:
+ _Safe_container&
+ _M_safe() _GLIBCXX_NOEXCEPT
+ { return *this; }
+
+#if __cplusplus >= 201103L
+ _Safe_container() = default;
+ _Safe_container(const _Safe_container&) = default;
+ _Safe_container(_Safe_container&& __x) noexcept
+ : _Safe_container()
+ { _Base::_M_swap(__x); }
+
+ _Safe_container(_Safe_container&& __x,
+ const _Alloc& __a)
+ : _Safe_container()
+ {
+ if (__x._M_cont().get_allocator() == __a)
+ _Base::_M_swap(__x);
+ else
+ __x._M_invalidate_all();
+ }
+#endif
+
+ public:
+ // Copy assignment invalidate all iterators.
+ _Safe_container&
+ operator=(const _Safe_container&) _GLIBCXX_NOEXCEPT
+ {
+ this->_M_invalidate_all();
+ return *this;
+ }
+
+#if __cplusplus >= 201103L
+ _Safe_container&
+ operator=(_Safe_container&& __x) noexcept
+ {
+ __glibcxx_check_self_move_assign(__x);
+
+ if (_IsCpp11AllocatorAware)
+ {
+ typedef __gnu_cxx::__alloc_traits<_Alloc> _Alloc_traits;
+
+ bool __xfer_memory = _Alloc_traits::_S_propagate_on_move_assign()
+ || _M_cont().get_allocator() == __x._M_cont().get_allocator();
+ if (__xfer_memory)
+ _Base::_M_swap(__x);
+ else
+ this->_M_invalidate_all();
+ }
+ else
+ _Base::_M_swap(__x);
+
+ __x._M_invalidate_all();
+ return *this;
+ }
+
+ void
+ _M_swap(_Safe_container& __x) noexcept
+ {
+ if (_IsCpp11AllocatorAware)
+ {
+ typedef __gnu_cxx::__alloc_traits<_Alloc> _Alloc_traits;
+
+ if (!_Alloc_traits::_S_propagate_on_swap())
+ __glibcxx_check_equal_allocs(this->_M_cont()._M_base(),
+ __x._M_cont()._M_base());
+ }
+
+ _Base::_M_swap(__x);
+ }
+#endif
+ };
+
+} // namespace __gnu_debug
+
+#endif
Index: include/debug/safe_sequence.h
===================================================================
--- include/debug/safe_sequence.h (revision 209446)
+++ include/debug/safe_sequence.h (working copy)
@@ -127,6 +127,25 @@
void
_M_transfer_from_if(_Safe_sequence& __from, _Predicate __pred);
};
+
+ /// Like _Safe_sequence but with a special _M_invalidate_all implementation
+ /// not invalidating past-the-end iterators. Used by node based sequence.
+ template<typename _Sequence>
+ class _Safe_node_sequence
+ : public _Safe_sequence<_Sequence>
+ {
+ protected:
+ void
+ _M_invalidate_all()
+ {
+ typedef typename _Sequence::const_iterator _Const_iterator;
+ typedef typename _Const_iterator::iterator_type _Base_const_iterator;
+ typedef __gnu_debug::_Not_equal_to<_Base_const_iterator> _Not_equal;
+ const _Sequence& __seq = *static_cast<_Sequence*>(this);
+ this->_M_invalidate_if(_Not_equal(__seq._M_base().end()));
+ }
+ };
+
} // namespace __gnu_debug
#include <debug/safe_sequence.tcc>
Index: include/debug/safe_unordered_base.h
===================================================================
--- include/debug/safe_unordered_base.h (revision 209446)
+++ include/debug/safe_unordered_base.h (working copy)
@@ -132,15 +132,16 @@
protected:
// Initialize with a version number of 1 and no iterators
- _Safe_unordered_container_base()
+ _Safe_unordered_container_base() noexcept
: _M_local_iterators(nullptr), _M_const_local_iterators(nullptr)
{ }
- // Initialize with a version number of 1 and no iterators
+ // Copy constructor do not copy iterators.
_Safe_unordered_container_base(const _Safe_unordered_container_base&)
noexcept
: _Safe_unordered_container_base() { }
+ // When moved unordered containers iterators are swapped.
_Safe_unordered_container_base(_Safe_unordered_container_base&& __x)
noexcept
: _Safe_unordered_container_base()
@@ -148,7 +149,7 @@
/** Notify all iterators that reference this container that the
container is being destroyed. */
- ~_Safe_unordered_container_base()
+ ~_Safe_unordered_container_base() noexcept
{ this->_M_detach_all(); }
/** Detach all iterators, leaving them singular. */
@@ -161,7 +162,7 @@
* one container now reference the other container.
*/
void
- _M_swap(_Safe_unordered_container_base& __x);
+ _M_swap(_Safe_unordered_container_base& __x) noexcept;
public:
/** Attach an iterator to this container. */
Index: include/debug/safe_unordered_container.h
===================================================================
--- include/debug/safe_unordered_container.h (revision 209446)
+++ include/debug/safe_unordered_container.h (working copy)
@@ -54,10 +54,33 @@
* template _Safe_local_iterator for this container. Iterators will
* then be tracked automatically.
*/
- template<typename _Container>
+ template<typename _SafeContainer>
class _Safe_unordered_container : public _Safe_unordered_container_base
{
- public:
+ _SafeContainer&
+ _M_cont() noexcept
+ { return *static_cast<_SafeContainer*>(this); }
+
+ protected:
+ void
+ _M_invalidate_locals()
+ {
+ auto __local_end = _M_cont()._M_base().end(0);
+ this->_M_invalidate_local_if(
+ [__local_end](__decltype(_M_cont()._M_base().cend(0)) __it)
+ { return __it != __local_end; });
+ }
+
+ void
+ _M_invalidate_all()
+ {
+ auto __end = _M_cont()._M_base().end();
+ this->_M_invalidate_if(
+ [__end](__decltype(_M_cont()._M_base().cend()) __it)
+ { return __it != __end; });
+ _M_invalidate_locals();
+ }
+
/** Invalidates all iterators @c x that reference this container,
are not singular, and for which @c __pred(x) returns @c
true. @c __pred will be invoked with the normal iterators nested
Index: include/debug/safe_unordered_container.tcc
===================================================================
--- include/debug/safe_unordered_container.tcc (revision 209446)
+++ include/debug/safe_unordered_container.tcc (working copy)
@@ -31,14 +31,14 @@
namespace __gnu_debug
{
- template<typename _Container>
+ template<typename _SafeContainer>
template<typename _Predicate>
void
- _Safe_unordered_container<_Container>::
+ _Safe_unordered_container<_SafeContainer>::
_M_invalidate_if(_Predicate __pred)
{
- typedef typename _Container::iterator iterator;
- typedef typename _Container::const_iterator const_iterator;
+ typedef typename _SafeContainer::iterator iterator;
+ typedef typename _SafeContainer::const_iterator const_iterator;
__gnu_cxx::__scoped_lock sentry(this->_M_get_mutex());
for (_Safe_iterator_base* __iter = _M_iterators; __iter;)
@@ -63,14 +63,14 @@
}
- template<typename _Container>
+ template<typename _SafeContainer>
template<typename _Predicate>
void
- _Safe_unordered_container<_Container>::
+ _Safe_unordered_container<_SafeContainer>::
_M_invalidate_local_if(_Predicate __pred)
{
- typedef typename _Container::local_iterator local_iterator;
- typedef typename _Container::const_local_iterator const_local_iterator;
+ typedef typename _SafeContainer::local_iterator local_iterator;
+ typedef typename _SafeContainer::const_local_iterator const_local_iterator;
__gnu_cxx::__scoped_lock sentry(this->_M_get_mutex());
for (_Safe_iterator_base* __iter = _M_local_iterators; __iter;)
Index: include/debug/set.h
===================================================================
--- include/debug/set.h (revision 209446)
+++ include/debug/set.h (working copy)
@@ -30,6 +30,7 @@
#define _GLIBCXX_DEBUG_SET_H 1
#include <debug/safe_sequence.h>
+#include <debug/safe_container.h>
#include <debug/safe_iterator.h>
#include <utility>
@@ -41,18 +42,19 @@
template<typename _Key, typename _Compare = std::less<_Key>,
typename _Allocator = std::allocator<_Key> >
class set
- : public _GLIBCXX_STD_C::set<_Key,_Compare,_Allocator>,
- public __gnu_debug::_Safe_sequence<set<_Key, _Compare, _Allocator> >
+ : public __gnu_debug::_Safe_container<
+ set<_Key, _Compare, _Allocator>, _Allocator,
+ __gnu_debug::_Safe_node_sequence>,
+ public _GLIBCXX_STD_C::set<_Key,_Compare,_Allocator>
{
typedef _GLIBCXX_STD_C::set<_Key, _Compare, _Allocator> _Base;
+ typedef __gnu_debug::_Safe_container<
+ set, _Allocator, __gnu_debug::_Safe_node_sequence> _Safe;
typedef typename _Base::const_iterator _Base_const_iterator;
typedef typename _Base::iterator _Base_iterator;
typedef __gnu_debug::_Equal_to<_Base_const_iterator> _Equal;
-#if __cplusplus >= 201103L
- typedef __gnu_cxx::__alloc_traits<typename
- _Base::allocator_type> _Alloc_traits;
-#endif
+
public:
// types:
typedef _Key key_type;
@@ -77,33 +79,18 @@
// 23.3.3.1 construct/copy/destroy:
+#if __cplusplus < 201103L
set() : _Base() { }
- explicit set(const _Compare& __comp,
- const _Allocator& __a = _Allocator())
- : _Base(__comp, __a) { }
-
- template<typename _InputIterator>
- set(_InputIterator __first, _InputIterator __last,
- const _Compare& __comp = _Compare(),
- const _Allocator& __a = _Allocator())
- : _Base(__gnu_debug::__base(__gnu_debug::__check_valid_range(__first,
- __last)),
- __gnu_debug::__base(__last),
- __comp, __a) { }
-
set(const set& __x)
: _Base(__x) { }
- set(const _Base& __x)
- : _Base(__x) { }
+ ~set() _GLIBCXX_NOEXCEPT { }
+#else
+ set() = default;
+ set(const set&) = default;
+ set(set&&) = default;
-#if __cplusplus >= 201103L
- set(set&& __x)
- noexcept(is_nothrow_copy_constructible<_Compare>::value)
- : _Base(std::move(__x))
- { this->_M_swap(__x); }
-
set(initializer_list<value_type> __l,
const _Compare& __comp = _Compare(),
const allocator_type& __a = allocator_type())
@@ -117,47 +104,52 @@
: _Base(__x, __a) { }
set(set&& __x, const allocator_type& __a)
- : _Base(std::move(__x._M_base()), __a) { }
+ : _Safe(std::move(__x), __a),
+ _Base(std::move(__x), __a) { }
set(initializer_list<value_type> __l, const allocator_type& __a)
- : _Base(__l, __a)
- { }
+ : _Base(__l, __a) { }
template<typename _InputIterator>
set(_InputIterator __first, _InputIterator __last,
const allocator_type& __a)
: _Base(__gnu_debug::__base(__gnu_debug::__check_valid_range(__first,
__last)),
- __gnu_debug::__base(__last), __a)
- { }
+ __gnu_debug::__base(__last), __a) { }
+
+ ~set() = default;
#endif
- ~set() _GLIBCXX_NOEXCEPT { }
+ explicit set(const _Compare& __comp,
+ const _Allocator& __a = _Allocator())
+ : _Base(__comp, __a) { }
+ template<typename _InputIterator>
+ set(_InputIterator __first, _InputIterator __last,
+ const _Compare& __comp = _Compare(),
+ const _Allocator& __a = _Allocator())
+ : _Base(__gnu_debug::__base(__gnu_debug::__check_valid_range(__first,
+ __last)),
+ __gnu_debug::__base(__last),
+ __comp, __a) { }
+
+ set(const _Base& __x)
+ : _Base(__x) { }
+
+#if __cplusplus < 201103L
set&
operator=(const set& __x)
{
+ this->_M_safe() = __x;
_M_base() = __x;
- this->_M_invalidate_all();
return *this;
}
+#else
+ set&
+ operator=(const set&) = default;
-#if __cplusplus >= 201103L
set&
- operator=(set&& __x)
- noexcept(_Alloc_traits::_S_nothrow_move())
- {
- __glibcxx_check_self_move_assign(__x);
- bool __xfer_memory = _Alloc_traits::_S_propagate_on_move_assign()
- || __x.get_allocator() == this->get_allocator();
- _M_base() = std::move(__x._M_base());
- if (__xfer_memory)
- this->_M_swap(__x);
- else
- this->_M_invalidate_all();
- __x._M_invalidate_all();
- return *this;
- }
+ operator=(set&&) = default;
set&
operator=(initializer_list<value_type> __l)
@@ -372,15 +364,11 @@
void
swap(set& __x)
#if __cplusplus >= 201103L
- noexcept(_Alloc_traits::_S_nothrow_swap())
+ noexcept( noexcept(declval<_Base>().swap(__x)) )
#endif
{
-#if __cplusplus >= 201103L
- if (!_Alloc_traits::_S_propagate_on_swap())
- __glibcxx_check_equal_allocs(__x);
-#endif
+ _Safe::_M_swap(__x);
_Base::swap(__x);
- this->_M_swap(__x);
}
void
@@ -452,14 +440,6 @@
const _Base&
_M_base() const _GLIBCXX_NOEXCEPT { return *this; }
-
- private:
- void
- _M_invalidate_all()
- {
- typedef __gnu_debug::_Not_equal_to<_Base_const_iterator> _Not_equal;
- this->_M_invalidate_if(_Not_equal(_M_base().end()));
- }
};
template<typename _Key, typename _Compare, typename _Allocator>
Index: include/debug/string
===================================================================
--- include/debug/string (revision 209446)
+++ include/debug/string (working copy)
@@ -31,6 +31,7 @@
#include <string>
#include <debug/safe_sequence.h>
+#include <debug/safe_container.h>
#include <debug/safe_iterator.h>
namespace __gnu_debug
@@ -39,12 +40,14 @@
template<typename _CharT, typename _Traits = std::char_traits<_CharT>,
typename _Allocator = std::allocator<_CharT> >
class basic_string
+ : public __gnu_debug::_Safe_container<
+ basic_string<_CharT, _Traits, _Allocator>, _Allocator,
+ _Safe_sequence, false>
: public std::basic_string<_CharT, _Traits, _Allocator>,
- public __gnu_debug::_Safe_sequence<basic_string<_CharT, _Traits,
- _Allocator> >
{
typedef std::basic_string<_CharT, _Traits, _Allocator> _Base;
- typedef __gnu_debug::_Safe_sequence<basic_string> _Safe_base;
+ typedef __gnu_debug::_Safe_container<
+ basic_string, _Allocator, _Safe_sequence, false> _Safe;
public:
// types:
@@ -58,10 +61,10 @@
typedef typename _Base::pointer pointer;
typedef typename _Base::const_pointer const_pointer;
- typedef __gnu_debug::_Safe_iterator<typename _Base::iterator, basic_string>
- iterator;
- typedef __gnu_debug::_Safe_iterator<typename _Base::const_iterator,
- basic_string> const_iterator;
+ typedef __gnu_debug::_Safe_iterator<
+ typename _Base::iterator, basic_string> iterator;
+ typedef __gnu_debug::_Safe_iterator<
+ typename _Base::const_iterator, basic_string> const_iterator;
typedef std::reverse_iterator<iterator> reverse_iterator;
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
@@ -71,18 +74,29 @@
// 21.3.1 construct/copy/destroy:
explicit basic_string(const _Allocator& __a = _Allocator())
// _GLIBCXX_NOEXCEPT
- : _Base(__a)
- { }
+ : _Base(__a) { }
- // Provides conversion from a release-mode string to a debug-mode string
- basic_string(const _Base& __base) : _Base(__base) { }
+#if __cplusplus < 201103L
+ basic_string(const basic_string& __str)
+ : _Base(__str) { }
- // _GLIBCXX_RESOLVE_LIB_DEFECTS
- // 42. string ctors specify wrong default allocator
- basic_string(const basic_string& __str)
- : _Base(__str, 0, _Base::npos, __str.get_allocator())
+ ~basic_string() _GLIBCXX_NOEXCEPT { }
+#else
+ basic_string(const basic_string&) = default;
+ basic_string(basic_string&&) = default;
+
+ basic_string(std::initializer_list<_CharT> __l,
+ const _Allocator& __a = _Allocator())
+ : _Base(__l, __a)
{ }
+ ~basic_string() = default;
+#endif // C++11
+
+ // Provides conversion from a normal-mode string to a debug-mode string
+ basic_string(const _Base& __base)
+ : _Base(__base) { }
+
// _GLIBCXX_RESOLVE_LIB_DEFECTS
// 42. string ctors specify wrong default allocator
basic_string(const basic_string& __str, size_type __pos,
@@ -113,32 +127,27 @@
__gnu_debug::__base(__end), __a)
{ }
-#if __cplusplus >= 201103L
- basic_string(basic_string&& __str) // noexcept
- : _Base(std::move(__str))
- { }
-
- basic_string(std::initializer_list<_CharT> __l,
- const _Allocator& __a = _Allocator())
- : _Base(__l, __a)
- { }
-#endif // C++11
-
- ~basic_string() _GLIBCXX_NOEXCEPT { }
-
+#if __cplusplus < 201103L
basic_string&
operator=(const basic_string& __str)
{
- *static_cast<_Base*>(this) = __str;
- this->_M_invalidate_all();
+ this->_M_safe() = __str;
+ _M_base() = __str;
return *this;
}
+#else
+ basic_string&
+ operator=(const basic_string&) = default;
basic_string&
+ operator=(basic_string&&) = default;
+#endif
+
+ basic_string&
operator=(const _CharT* __s)
{
__glibcxx_check_string(__s);
- *static_cast<_Base*>(this) = __s;
+ _M_base() = __s;
this->_M_invalidate_all();
return *this;
}
@@ -146,25 +155,16 @@
basic_string&
operator=(_CharT __c)
{
- *static_cast<_Base*>(this) = __c;
+ _M_base() = __c;
this->_M_invalidate_all();
return *this;
}
#if __cplusplus >= 201103L
basic_string&
- operator=(basic_string&& __str)
- {
- __glibcxx_check_self_move_assign(__str);
- *static_cast<_Base*>(this) = std::move(__str);
- this->_M_invalidate_all();
- return *this;
- }
-
- basic_string&
operator=(std::initializer_list<_CharT> __l)
{
- *static_cast<_Base*>(this) = __l;
+ _M_base() = __l;
this->_M_invalidate_all();
return *this;
}
@@ -704,12 +704,13 @@
}
void
- swap(basic_string<_CharT,_Traits,_Allocator>& __x)
+ swap(basic_string& __x)
+#if __cplusplus >= 201103L
+ noexcept( noexcept(declval<_Base>().swap(__x)) )
+#endif
{
+ _Safe::_M_swap(__x);
_Base::swap(__x);
- this->_M_swap(__x);
- this->_M_invalidate_all();
- __x._M_invalidate_all();
}
// 21.3.6 string operations:
@@ -922,7 +923,7 @@
const _Base&
_M_base() const _GLIBCXX_NOEXCEPT { return *this; }
- using _Safe_base::_M_invalidate_all;
+ using _Safe::_M_invalidate_all;
};
template<typename _CharT, typename _Traits, typename _Allocator>
Index: include/debug/unordered_map
===================================================================
--- include/debug/unordered_map (revision 209446)
+++ include/debug/unordered_map (working copy)
@@ -35,6 +35,7 @@
# include <unordered_map>
#include <debug/safe_unordered_container.h>
+#include <debug/safe_container.h>
#include <debug/safe_iterator.h>
#include <debug/safe_local_iterator.h>
@@ -48,21 +49,21 @@
typename _Pred = std::equal_to<_Key>,
typename _Alloc = std::allocator<std::pair<const _Key, _Tp> > >
class unordered_map
- : public _GLIBCXX_STD_C::unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>,
- public __gnu_debug::_Safe_unordered_container<unordered_map<_Key, _Tp,
- _Hash, _Pred, _Alloc> >
+ : public __gnu_debug::_Safe_container<
+ unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>, _Alloc,
+ __gnu_debug::_Safe_unordered_container>,
+ public _GLIBCXX_STD_C::unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>
{
typedef _GLIBCXX_STD_C::unordered_map<_Key, _Tp, _Hash,
_Pred, _Alloc> _Base;
- typedef __gnu_debug::_Safe_unordered_container<unordered_map> _Safe_base;
+ typedef __gnu_debug::_Safe_container<unordered_map,
+ _Alloc, __gnu_debug::_Safe_unordered_container> _Safe;
typedef typename _Base::const_iterator _Base_const_iterator;
typedef typename _Base::iterator _Base_iterator;
- typedef typename _Base::const_local_iterator _Base_const_local_iterator;
+ typedef typename _Base::const_local_iterator
+ _Base_const_local_iterator;
typedef typename _Base::local_iterator _Base_local_iterator;
- typedef __gnu_cxx::__alloc_traits<typename
- _Base::allocator_type> _Alloc_traits;
-
public:
typedef typename _Base::size_type size_type;
typedef typename _Base::hasher hasher;
@@ -72,14 +73,14 @@
typedef typename _Base::key_type key_type;
typedef typename _Base::value_type value_type;
- typedef __gnu_debug::_Safe_iterator<_Base_iterator,
- unordered_map> iterator;
- typedef __gnu_debug::_Safe_iterator<_Base_const_iterator,
- unordered_map> const_iterator;
- typedef __gnu_debug::_Safe_local_iterator<_Base_local_iterator,
- unordered_map> local_iterator;
- typedef __gnu_debug::_Safe_local_iterator<_Base_const_local_iterator,
- unordered_map> const_local_iterator;
+ typedef __gnu_debug::_Safe_iterator<
+ _Base_iterator, unordered_map> iterator;
+ typedef __gnu_debug::_Safe_iterator<
+ _Base_const_iterator, unordered_map> const_iterator;
+ typedef __gnu_debug::_Safe_local_iterator<
+ _Base_local_iterator, unordered_map> local_iterator;
+ typedef __gnu_debug::_Safe_local_iterator<
+ _Base_const_local_iterator, unordered_map> const_local_iterator;
explicit
unordered_map(size_type __n = 10,
@@ -108,18 +109,16 @@
explicit
unordered_map(const allocator_type& __a)
- : _Base(__a)
- { }
+ : _Base(__a) { }
unordered_map(const unordered_map& __umap,
const allocator_type& __a)
- : _Base(__umap._M_base(), __a)
- { }
+ : _Base(__umap, __a) { }
unordered_map(unordered_map&& __umap,
const allocator_type& __a)
- : _Base(std::move(__umap._M_base()), __a)
- { }
+ : _Safe(std::move(__umap), __a),
+ _Base(std::move(__umap), __a) { }
unordered_map(initializer_list<value_type> __l,
size_type __n = 0,
@@ -128,31 +127,13 @@
const allocator_type& __a = allocator_type())
: _Base(__l, __n, __hf, __eql, __a) { }
- ~unordered_map() noexcept { }
+ ~unordered_map() = default;
unordered_map&
- operator=(const unordered_map& __x)
- {
- _M_base() = __x._M_base();
- this->_M_invalidate_all();
- return *this;
- }
+ operator=(const unordered_map&) = default;
unordered_map&
- operator=(unordered_map&& __x)
- noexcept(_Alloc_traits::_S_nothrow_move())
- {
- __glibcxx_check_self_move_assign(__x);
- bool __xfer_memory = _Alloc_traits::_S_propagate_on_move_assign()
- || __x.get_allocator() == this->get_allocator();
- _M_base() = std::move(__x._M_base());
- if (__xfer_memory)
- this->_M_swap(__x);
- else
- this->_M_invalidate_all();
- __x._M_invalidate_all();
- return *this;
- }
+ operator=(unordered_map&&) = default;
unordered_map&
operator=(initializer_list<value_type> __l)
@@ -164,12 +145,10 @@
void
swap(unordered_map& __x)
- noexcept(_Alloc_traits::_S_nothrow_swap())
+ noexcept( noexcept(declval<_Base>().swap(__x)) )
{
- if (!_Alloc_traits::_S_propagate_on_swap())
- __glibcxx_check_equal_allocs(__x);
+ _Safe::_M_swap(__x);
_Base::swap(__x);
- _Safe_base::_M_swap(__x);
}
void
@@ -449,28 +428,10 @@
private:
void
- _M_invalidate_locals()
- {
- _Base_local_iterator __local_end = _Base::end(0);
- this->_M_invalidate_local_if(
- [__local_end](_Base_const_local_iterator __it)
- { return __it != __local_end; });
- }
-
- void
- _M_invalidate_all()
- {
- _Base_iterator __end = _Base::end();
- this->_M_invalidate_if([__end](_Base_const_iterator __it)
- { return __it != __end; });
- _M_invalidate_locals();
- }
-
- void
_M_check_rehashed(size_type __prev_count)
{
if (__prev_count != this->bucket_count())
- _M_invalidate_locals();
+ this->_M_invalidate_locals();
}
};
@@ -502,23 +463,20 @@
typename _Pred = std::equal_to<_Key>,
typename _Alloc = std::allocator<std::pair<const _Key, _Tp> > >
class unordered_multimap
- : public _GLIBCXX_STD_C::unordered_multimap<_Key, _Tp, _Hash,
- _Pred, _Alloc>,
- public __gnu_debug::_Safe_unordered_container<unordered_multimap<_Key,
- _Tp, _Hash, _Pred, _Alloc> >
+ : public __gnu_debug::_Safe_container<
+ unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>, _Alloc,
+ __gnu_debug::_Safe_unordered_container>,
+ public _GLIBCXX_STD_C::unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>
{
typedef _GLIBCXX_STD_C::unordered_multimap<_Key, _Tp, _Hash,
_Pred, _Alloc> _Base;
- typedef __gnu_debug::_Safe_unordered_container<unordered_multimap>
- _Safe_base;
+ typedef __gnu_debug::_Safe_container<unordered_multimap,
+ _Alloc, __gnu_debug::_Safe_unordered_container> _Safe;
typedef typename _Base::const_iterator _Base_const_iterator;
typedef typename _Base::iterator _Base_iterator;
typedef typename _Base::const_local_iterator _Base_const_local_iterator;
typedef typename _Base::local_iterator _Base_local_iterator;
- typedef __gnu_cxx::__alloc_traits<typename
- _Base::allocator_type> _Alloc_traits;
-
public:
typedef typename _Base::size_type size_type;
typedef typename _Base::hasher hasher;
@@ -528,10 +486,10 @@
typedef typename _Base::key_type key_type;
typedef typename _Base::value_type value_type;
- typedef __gnu_debug::_Safe_iterator<_Base_iterator,
- unordered_multimap> iterator;
- typedef __gnu_debug::_Safe_iterator<_Base_const_iterator,
- unordered_multimap> const_iterator;
+ typedef __gnu_debug::_Safe_iterator<
+ _Base_iterator, unordered_multimap> iterator;
+ typedef __gnu_debug::_Safe_iterator<
+ _Base_const_iterator, unordered_multimap> const_iterator;
typedef __gnu_debug::_Safe_local_iterator<
_Base_local_iterator, unordered_multimap> local_iterator;
typedef __gnu_debug::_Safe_local_iterator<
@@ -564,18 +522,16 @@
explicit
unordered_multimap(const allocator_type& __a)
- : _Base(__a)
- { }
+ : _Base(__a) { }
unordered_multimap(const unordered_multimap& __umap,
const allocator_type& __a)
- : _Base(__umap._M_base(), __a)
- { }
+ : _Base(__umap, __a) { }
unordered_multimap(unordered_multimap&& __umap,
const allocator_type& __a)
- : _Base(std::move(__umap._M_base()), __a)
- { }
+ : _Safe(std::move(__umap), __a),
+ _Base(std::move(__umap), __a) { }
unordered_multimap(initializer_list<value_type> __l,
size_type __n = 0,
@@ -584,48 +540,28 @@
const allocator_type& __a = allocator_type())
: _Base(__l, __n, __hf, __eql, __a) { }
- ~unordered_multimap() noexcept { }
+ ~unordered_multimap() = default;
unordered_multimap&
- operator=(const unordered_multimap& __x)
- {
- _M_base() = __x._M_base();
- this->_M_invalidate_all();
- return *this;
- }
+ operator=(const unordered_multimap&) = default;
unordered_multimap&
- operator=(unordered_multimap&& __x)
- noexcept(_Alloc_traits::_S_nothrow_move())
- {
- __glibcxx_check_self_move_assign(__x);
- bool __xfer_memory = _Alloc_traits::_S_propagate_on_move_assign()
- || __x.get_allocator() == this->get_allocator();
- _M_base() = std::move(__x._M_base());
- if (__xfer_memory)
- this->_M_swap(__x);
- else
- this->_M_invalidate_all();
- __x._M_invalidate_all();
- return *this;
- }
+ operator=(unordered_multimap&&) = default;
unordered_multimap&
operator=(initializer_list<value_type> __l)
{
- _M_base() = __l;
+ this->_M_base() = __l;
this->_M_invalidate_all();
return *this;
}
void
swap(unordered_multimap& __x)
- noexcept(_Alloc_traits::_S_nothrow_swap())
+ noexcept( noexcept(declval<_Base>().swap(__x)) )
{
- if (!_Alloc_traits::_S_propagate_on_swap())
- __glibcxx_check_equal_allocs(__x);
+ _Safe::_M_swap(__x);
_Base::swap(__x);
- _Safe_base::_M_swap(__x);
}
void
@@ -901,28 +837,10 @@
private:
void
- _M_invalidate_locals()
- {
- _Base_local_iterator __local_end = _Base::end(0);
- this->_M_invalidate_local_if(
- [__local_end](_Base_const_local_iterator __it)
- { return __it != __local_end; });
- }
-
- void
- _M_invalidate_all()
- {
- _Base_iterator __end = _Base::end();
- this->_M_invalidate_if([__end](_Base_const_iterator __it)
- { return __it != __end; });
- _M_invalidate_locals();
- }
-
- void
_M_check_rehashed(size_type __prev_count)
{
if (__prev_count != this->bucket_count())
- _M_invalidate_locals();
+ this->_M_invalidate_locals();
}
};
Index: include/debug/unordered_set
===================================================================
--- include/debug/unordered_set (revision 209446)
+++ include/debug/unordered_set (working copy)
@@ -35,6 +35,7 @@
# include <unordered_set>
#include <debug/safe_unordered_container.h>
+#include <debug/safe_container.h>
#include <debug/safe_iterator.h>
#include <debug/safe_local_iterator.h>
@@ -48,20 +49,21 @@
typename _Pred = std::equal_to<_Value>,
typename _Alloc = std::allocator<_Value> >
class unordered_set
- : public _GLIBCXX_STD_C::unordered_set<_Value, _Hash, _Pred, _Alloc>,
- public __gnu_debug::_Safe_unordered_container<unordered_set<_Value, _Hash,
- _Pred, _Alloc> >
+ : public __gnu_debug::_Safe_container<
+ unordered_set<_Value, _Hash, _Pred, _Alloc>, _Alloc,
+ __gnu_debug::_Safe_unordered_container>,
+ public _GLIBCXX_STD_C::unordered_set<_Value, _Hash, _Pred, _Alloc>
{
- typedef _GLIBCXX_STD_C::unordered_set<_Value, _Hash,
- _Pred, _Alloc> _Base;
- typedef __gnu_debug::_Safe_unordered_container<unordered_set> _Safe_base;
+ typedef _GLIBCXX_STD_C::unordered_set<
+ _Value, _Hash, _Pred, _Alloc> _Base;
+ typedef __gnu_debug::_Safe_container<
+ unordered_set, _Alloc, __gnu_debug::_Safe_unordered_container> _Safe;
+
typedef typename _Base::const_iterator _Base_const_iterator;
typedef typename _Base::iterator _Base_iterator;
typedef typename _Base::const_local_iterator _Base_const_local_iterator;
typedef typename _Base::local_iterator _Base_local_iterator;
- typedef __gnu_cxx::__alloc_traits<typename
- _Base::allocator_type> _Alloc_traits;
public:
typedef typename _Base::size_type size_type;
typedef typename _Base::hasher hasher;
@@ -71,14 +73,14 @@
typedef typename _Base::key_type key_type;
typedef typename _Base::value_type value_type;
- typedef __gnu_debug::_Safe_iterator<_Base_iterator,
- unordered_set> iterator;
- typedef __gnu_debug::_Safe_iterator<_Base_const_iterator,
- unordered_set> const_iterator;
- typedef __gnu_debug::_Safe_local_iterator<_Base_local_iterator,
- unordered_set> local_iterator;
- typedef __gnu_debug::_Safe_local_iterator<_Base_const_local_iterator,
- unordered_set> const_local_iterator;
+ typedef __gnu_debug::_Safe_iterator<
+ _Base_iterator, unordered_set> iterator;
+ typedef __gnu_debug::_Safe_iterator<
+ _Base_const_iterator, unordered_set> const_iterator;
+ typedef __gnu_debug::_Safe_local_iterator<
+ _Base_local_iterator, unordered_set> local_iterator;
+ typedef __gnu_debug::_Safe_local_iterator<
+ _Base_const_local_iterator, unordered_set> const_local_iterator;
explicit
unordered_set(size_type __n = 10,
@@ -107,18 +109,16 @@
explicit
unordered_set(const allocator_type& __a)
- : _Base(__a)
- { }
+ : _Base(__a) { }
unordered_set(const unordered_set& __uset,
const allocator_type& __a)
- : _Base(__uset._M_base(), __a)
- { }
+ : _Base(__uset, __a) { }
unordered_set(unordered_set&& __uset,
const allocator_type& __a)
- : _Base(std::move(__uset._M_base()), __a)
- { }
+ : _Safe(std::move(__uset), __a),
+ _Base(std::move(__uset), __a) { }
unordered_set(initializer_list<value_type> __l,
size_type __n = 0,
@@ -127,31 +127,13 @@
const allocator_type& __a = allocator_type())
: _Base(__l, __n, __hf, __eql, __a) { }
- ~unordered_set() noexcept { }
+ ~unordered_set() = default;
unordered_set&
- operator=(const unordered_set& __x)
- {
- _M_base() = __x._M_base();
- this->_M_invalidate_all();
- return *this;
- }
+ operator=(const unordered_set&) = default;
unordered_set&
- operator=(unordered_set&& __x)
- noexcept(_Alloc_traits::_S_nothrow_move())
- {
- __glibcxx_check_self_move_assign(__x);
- bool __xfer_memory = _Alloc_traits::_S_propagate_on_move_assign()
- || __x.get_allocator() == this->get_allocator();
- _M_base() = std::move(__x._M_base());
- if (__xfer_memory)
- this->_M_swap(__x);
- else
- this->_M_invalidate_all();
- __x._M_invalidate_all();
- return *this;
- }
+ operator=(unordered_set&&) = default;
unordered_set&
operator=(initializer_list<value_type> __l)
@@ -163,12 +145,10 @@
void
swap(unordered_set& __x)
- noexcept(_Alloc_traits::_S_nothrow_swap())
+ noexcept( noexcept(declval<_Base>().swap(__x)) )
{
- if (!_Alloc_traits::_S_propagate_on_swap())
- __glibcxx_check_equal_allocs(__x);
+ _Safe::_M_swap(__x);
_Base::swap(__x);
- _Safe_base::_M_swap(__x);
}
void
@@ -290,8 +270,8 @@
insert(const value_type& __obj)
{
size_type __bucket_count = this->bucket_count();
- typedef std::pair<_Base_iterator, bool> __pair_type;
- __pair_type __res = _Base::insert(__obj);
+ std::pair<_Base_iterator, bool> __res
+ = _Base::insert(__obj);
_M_check_rehashed(__bucket_count);
return std::make_pair(iterator(__res.first, this), __res.second);
}
@@ -310,8 +290,8 @@
insert(value_type&& __obj)
{
size_type __bucket_count = this->bucket_count();
- typedef std::pair<typename _Base::iterator, bool> __pair_type;
- __pair_type __res = _Base::insert(std::move(__obj));
+ std::pair<_Base_iterator, bool> __res
+ = _Base::insert(std::move(__obj));
_M_check_rehashed(__bucket_count);
return std::make_pair(iterator(__res.first, this), __res.second);
}
@@ -356,8 +336,8 @@
std::pair<iterator, iterator>
equal_range(const key_type& __key)
{
- typedef std::pair<_Base_iterator, _Base_iterator> __pair_type;
- __pair_type __res = _Base::equal_range(__key);
+ std::pair<_Base_iterator, _Base_iterator> __res
+ = _Base::equal_range(__key);
return std::make_pair(iterator(__res.first, this),
iterator(__res.second, this));
}
@@ -446,29 +426,10 @@
private:
void
- _M_invalidate_locals()
- {
- _Base_local_iterator __local_end = _Base::end(0);
- this->_M_invalidate_local_if(
- [__local_end](_Base_const_local_iterator __it)
- { return __it != __local_end; });
- }
-
- void
- _M_invalidate_all()
- {
- _Base_iterator __end = _Base::end();
- this->_M_invalidate_if(
- [__end](_Base_const_iterator __it)
- { return __it != __end; });
- _M_invalidate_locals();
- }
-
- void
_M_check_rehashed(size_type __prev_count)
{
if (__prev_count != this->bucket_count())
- _M_invalidate_locals();
+ this->_M_invalidate_locals();
}
};
@@ -497,22 +458,21 @@
typename _Pred = std::equal_to<_Value>,
typename _Alloc = std::allocator<_Value> >
class unordered_multiset
- : public _GLIBCXX_STD_C::unordered_multiset<_Value, _Hash, _Pred, _Alloc>,
- public __gnu_debug::_Safe_unordered_container<
- unordered_multiset<_Value, _Hash, _Pred, _Alloc> >
+ : public __gnu_debug::_Safe_container<
+ unordered_multiset<_Value, _Hash, _Pred, _Alloc>, _Alloc,
+ __gnu_debug::_Safe_unordered_container>,
+ public _GLIBCXX_STD_C::unordered_multiset<_Value, _Hash, _Pred, _Alloc>
{
- typedef _GLIBCXX_STD_C::unordered_multiset<_Value, _Hash,
- _Pred, _Alloc> _Base;
- typedef __gnu_debug::_Safe_unordered_container<unordered_multiset>
- _Safe_base;
+ typedef _GLIBCXX_STD_C::unordered_multiset<
+ _Value, _Hash, _Pred, _Alloc> _Base;
+ typedef __gnu_debug::_Safe_container<unordered_multiset,
+ _Alloc, __gnu_debug::_Safe_unordered_container> _Safe;
typedef typename _Base::const_iterator _Base_const_iterator;
typedef typename _Base::iterator _Base_iterator;
- typedef typename _Base::const_local_iterator _Base_const_local_iterator;
+ typedef typename _Base::const_local_iterator
+ _Base_const_local_iterator;
typedef typename _Base::local_iterator _Base_local_iterator;
- typedef __gnu_cxx::__alloc_traits<typename
- _Base::allocator_type> _Alloc_traits;
-
public:
typedef typename _Base::size_type size_type;
typedef typename _Base::hasher hasher;
@@ -522,10 +482,10 @@
typedef typename _Base::key_type key_type;
typedef typename _Base::value_type value_type;
- typedef __gnu_debug::_Safe_iterator<_Base_iterator,
- unordered_multiset> iterator;
- typedef __gnu_debug::_Safe_iterator<_Base_const_iterator,
- unordered_multiset> const_iterator;
+ typedef __gnu_debug::_Safe_iterator<
+ _Base_iterator, unordered_multiset> iterator;
+ typedef __gnu_debug::_Safe_iterator<
+ _Base_const_iterator, unordered_multiset> const_iterator;
typedef __gnu_debug::_Safe_local_iterator<
_Base_local_iterator, unordered_multiset> local_iterator;
typedef __gnu_debug::_Safe_local_iterator<
@@ -558,18 +518,16 @@
explicit
unordered_multiset(const allocator_type& __a)
- : _Base(__a)
- { }
+ : _Base(__a) { }
unordered_multiset(const unordered_multiset& __uset,
const allocator_type& __a)
- : _Base(__uset._M_base(), __a)
- { }
+ : _Base(__uset, __a) { }
unordered_multiset(unordered_multiset&& __uset,
const allocator_type& __a)
- : _Base(std::move(__uset._M_base()), __a)
- { }
+ : _Safe(std::move(__uset), __a),
+ _Base(std::move(__uset), __a) { }
unordered_multiset(initializer_list<value_type> __l,
size_type __n = 0,
@@ -578,48 +536,28 @@
const allocator_type& __a = allocator_type())
: _Base(__l, __n, __hf, __eql, __a) { }
- ~unordered_multiset() noexcept { }
+ ~unordered_multiset() = default;
unordered_multiset&
- operator=(const unordered_multiset& __x)
- {
- _M_base() = __x._M_base();
- this->_M_invalidate_all();
- return *this;
- }
+ operator=(const unordered_multiset&) = default;
unordered_multiset&
- operator=(unordered_multiset&& __x)
- noexcept(_Alloc_traits::_S_nothrow_move())
- {
- __glibcxx_check_self_move_assign(__x);
- bool __xfer_memory = _Alloc_traits::_S_propagate_on_move_assign()
- || __x.get_allocator() == this->get_allocator();
- _M_base() = std::move(__x._M_base());
- if (__xfer_memory)
- this->_M_swap(__x);
- else
- this->_M_invalidate_all();
- __x._M_invalidate_all();
- return *this;
- }
+ operator=(unordered_multiset&&) = default;
unordered_multiset&
operator=(initializer_list<value_type> __l)
{
- _M_base() = __l;
+ this->_M_base() = __l;
this->_M_invalidate_all();
return *this;
}
void
swap(unordered_multiset& __x)
- noexcept(_Alloc_traits::_S_nothrow_swap())
+ noexcept( noexcept(declval<_Base>().swap(__x)) )
{
- if (!_Alloc_traits::_S_propagate_on_swap())
- __glibcxx_check_equal_allocs(__x);
+ _Safe::_M_swap(__x);
_Base::swap(__x);
- _Safe_base::_M_swap(__x);
}
void
@@ -805,8 +743,8 @@
std::pair<iterator, iterator>
equal_range(const key_type& __key)
{
- typedef std::pair<_Base_iterator, _Base_iterator> __pair_type;
- __pair_type __res = _Base::equal_range(__key);
+ std::pair<_Base_iterator, _Base_iterator> __res
+ = _Base::equal_range(__key);
return std::make_pair(iterator(__res.first, this),
iterator(__res.second, this));
}
@@ -885,28 +823,10 @@
private:
void
- _M_invalidate_locals()
- {
- _Base_local_iterator __local_end = _Base::end(0);
- this->_M_invalidate_local_if(
- [__local_end](_Base_const_local_iterator __it)
- { return __it != __local_end; });
- }
-
- void
- _M_invalidate_all()
- {
- _Base_iterator __end = _Base::end();
- this->_M_invalidate_if([__end](_Base_const_iterator __it)
- { return __it != __end; });
- _M_invalidate_locals();
- }
-
- void
_M_check_rehashed(size_type __prev_count)
{
if (__prev_count != this->bucket_count())
- _M_invalidate_locals();
+ this->_M_invalidate_locals();
}
};
Index: include/debug/vector
===================================================================
--- include/debug/vector (revision 209446)
+++ include/debug/vector (working copy)
@@ -32,8 +32,68 @@
#include <vector>
#include <utility>
#include <debug/safe_sequence.h>
+#include <debug/safe_container.h>
#include <debug/safe_iterator.h>
+namespace __gnu_debug
+{
+ /// Special vector safe base class to add a guaranteed capacity information
+ /// useful to detect code relying on the libstdc++ reallocation management
+ /// implementation detail.
+ template<typename _SafeSequence,
+ typename _BaseSequence>
+ class _Safe_vector
+ {
+ typedef typename _BaseSequence::size_type size_type;
+
+ const _SafeSequence&
+ _M_seq() const { return *static_cast<const _SafeSequence*>(this); }
+
+ protected:
+ _Safe_vector() _GLIBCXX_NOEXCEPT
+ : _M_guaranteed_capacity(0)
+ { _M_update_guaranteed_capacity(); }
+
+ _Safe_vector(const _Safe_vector&) _GLIBCXX_NOEXCEPT
+ : _M_guaranteed_capacity(0)
+ { _M_update_guaranteed_capacity(); }
+
+ _Safe_vector(size_type __n) _GLIBCXX_NOEXCEPT
+ : _M_guaranteed_capacity(__n)
+ { }
+
+#if __cplusplus >= 201103L
+ _Safe_vector(_Safe_vector&& __x) noexcept
+ : _Safe_vector()
+ { __x._M_guaranteed_capacity = 0; }
+
+ _Safe_vector&
+ operator=(const _Safe_vector&) noexcept
+ { _M_update_guaranteed_capacity(); }
+
+ _Safe_vector&
+ operator=(_Safe_vector&& __x) noexcept
+ {
+ _M_update_guaranteed_capacity();
+ __x._M_guaranteed_capacity = 0;
+ }
+#endif
+
+ size_type _M_guaranteed_capacity;
+
+ bool
+ _M_requires_reallocation(size_type __elements) const _GLIBCXX_NOEXCEPT
+ { return __elements > _M_seq().capacity(); }
+
+ void
+ _M_update_guaranteed_capacity() _GLIBCXX_NOEXCEPT
+ {
+ if (_M_seq().size() > _M_guaranteed_capacity)
+ _M_guaranteed_capacity = _M_seq().size();
+ }
+ };
+}
+
namespace std _GLIBCXX_VISIBILITY(default)
{
namespace __debug
@@ -42,28 +102,30 @@
template<typename _Tp,
typename _Allocator = std::allocator<_Tp> >
class vector
- : public _GLIBCXX_STD_C::vector<_Tp, _Allocator>,
- public __gnu_debug::_Safe_sequence<vector<_Tp, _Allocator> >
+ : public __gnu_debug::_Safe_container<
+ vector<_Tp, _Allocator>, _Allocator, __gnu_debug::_Safe_sequence>,
+ public _GLIBCXX_STD_C::vector<_Tp, _Allocator>,
+ public __gnu_debug::_Safe_vector<
+ vector<_Tp, _Allocator>,
+ _GLIBCXX_STD_C::vector<_Tp, _Allocator> >
{
typedef _GLIBCXX_STD_C::vector<_Tp, _Allocator> _Base;
+ typedef __gnu_debug::_Safe_container<
+ vector, _Allocator, __gnu_debug::_Safe_sequence> _Safe;
+ typedef __gnu_debug::_Safe_vector<vector, _Base> _Safe_vector;
typedef typename _Base::iterator _Base_iterator;
typedef typename _Base::const_iterator _Base_const_iterator;
typedef __gnu_debug::_Equal_to<_Base_const_iterator> _Equal;
-#if __cplusplus >= 201103L
- typedef __gnu_debug::_Safe_sequence<vector<_Tp, _Allocator> > _Safe_base;
- typedef __gnu_cxx::__alloc_traits<_Allocator> _Alloc_traits;
-#endif
-
public:
typedef typename _Base::reference reference;
typedef typename _Base::const_reference const_reference;
- typedef __gnu_debug::_Safe_iterator<_Base_iterator,vector>
- iterator;
- typedef __gnu_debug::_Safe_iterator<_Base_const_iterator,vector>
- const_iterator;
+ typedef __gnu_debug::_Safe_iterator<
+ _Base_iterator, vector> iterator;
+ typedef __gnu_debug::_Safe_iterator<
+ _Base_const_iterator, vector> const_iterator;
typedef typename _Base::size_type size_type;
typedef typename _Base::difference_type difference_type;
@@ -77,26 +139,30 @@
// 23.2.4.1 construct/copy/destroy:
+#if __cplusplus < 201103L
vector() _GLIBCXX_NOEXCEPT
- : _Base(), _M_guaranteed_capacity(0) { }
+ : _Base() { }
+#else
+ vector() = default;
+#endif
explicit
vector(const _Allocator& __a) _GLIBCXX_NOEXCEPT
- : _Base(__a), _M_guaranteed_capacity(0) { }
+ : _Base(__a) { }
#if __cplusplus >= 201103L
explicit
vector(size_type __n, const _Allocator& __a = _Allocator())
- : _Base(__n, __a), _M_guaranteed_capacity(__n) { }
+ : _Base(__n, __a), _Safe_vector(__n) { }
vector(size_type __n, const _Tp& __value,
const _Allocator& __a = _Allocator())
- : _Base(__n, __value, __a), _M_guaranteed_capacity(__n) { }
+ : _Base(__n, __value, __a) { }
#else
explicit
vector(size_type __n, const _Tp& __value = _Tp(),
const _Allocator& __a = _Allocator())
- : _Base(__n, __value, __a), _M_guaranteed_capacity(__n) { }
+ : _Base(__n, __value, __a) { }
#endif
#if __cplusplus >= 201103L
@@ -109,79 +175,58 @@
const _Allocator& __a = _Allocator())
: _Base(__gnu_debug::__base(__gnu_debug::__check_valid_range(__first,
__last)),
- __gnu_debug::__base(__last), __a),
- _M_guaranteed_capacity(0)
- { _M_update_guaranteed_capacity(); }
+ __gnu_debug::__base(__last), __a) { }
+#if __cplusplus < 201103L
vector(const vector& __x)
- : _Base(__x), _M_guaranteed_capacity(__x.size()) { }
+ : _Base(__x) { }
- /// Construction from a normal-mode vector
- vector(const _Base& __x)
- : _Base(__x), _M_guaranteed_capacity(__x.size()) { }
+ ~vector() _GLIBCXX_NOEXCEPT { }
+#else
+ vector(const vector&) = default;
+ vector(vector&&) = default;
-#if __cplusplus >= 201103L
- vector(vector&& __x) noexcept
- : _Base(std::move(__x)),
- _Safe_base(std::move(__x)),
- _M_guaranteed_capacity(this->size())
- { __x._M_guaranteed_capacity = 0; }
-
vector(const vector& __x, const allocator_type& __a)
- : _Base(__x, __a), _M_guaranteed_capacity(__x.size()) { }
+ : _Base(__x, __a) { }
vector(vector&& __x, const allocator_type& __a)
- : _Base(std::move(__x), __a),
- _M_guaranteed_capacity(this->size())
- {
- if (__x.get_allocator() == __a)
- this->_M_swap(__x);
- else
- __x._M_invalidate_all();
- __x._M_guaranteed_capacity = 0;
- }
+ : _Safe(std::move(__x), __a),
+ _Base(std::move(__x), __a),
+ _Safe_vector(std::move(__x)) { }
vector(initializer_list<value_type> __l,
const allocator_type& __a = allocator_type())
- : _Base(__l, __a),
- _M_guaranteed_capacity(__l.size()) { }
+ : _Base(__l, __a) { }
+
+ ~vector() = default;
#endif
- ~vector() _GLIBCXX_NOEXCEPT { }
+ /// Construction from a normal-mode vector
+ vector(const _Base& __x)
+ : _Base(__x) { }
+#if __cplusplus < 201103L
vector&
operator=(const vector& __x)
{
+ this->_M_safe() = __x;
_M_base() = __x;
- this->_M_invalidate_all();
- _M_update_guaranteed_capacity();
+ this->_M_update_guaranteed_capacity();
return *this;
}
+#else
+ vector&
+ operator=(const vector&) = default;
-#if __cplusplus >= 201103L
vector&
- operator=(vector&& __x) noexcept(_Alloc_traits::_S_nothrow_move())
- {
- __glibcxx_check_self_move_assign(__x);
- bool __xfer_memory = _Alloc_traits::_S_propagate_on_move_assign()
- || __x.get_allocator() == this->get_allocator();
- _M_base() = std::move(__x._M_base());
- if (__xfer_memory)
- this->_M_swap(__x);
- else
- this->_M_invalidate_all();
- _M_update_guaranteed_capacity();
- __x._M_invalidate_all();
- __x._M_guaranteed_capacity = 0;
- return *this;
- }
+ operator=(vector&&) = default;
vector&
operator=(initializer_list<value_type> __l)
{
_M_base() = __l;
this->_M_invalidate_all();
- _M_update_guaranteed_capacity();
+ this->_M_update_guaranteed_capacity();
return *this;
}
#endif
@@ -199,7 +244,7 @@
_Base::assign(__gnu_debug::__base(__first),
__gnu_debug::__base(__last));
this->_M_invalidate_all();
- _M_update_guaranteed_capacity();
+ this->_M_update_guaranteed_capacity();
}
void
@@ -207,7 +252,7 @@
{
_Base::assign(__n, __u);
this->_M_invalidate_all();
- _M_update_guaranteed_capacity();
+ this->_M_update_guaranteed_capacity();
}
#if __cplusplus >= 201103L
@@ -216,7 +261,7 @@
{
_Base::assign(__l);
this->_M_invalidate_all();
- _M_update_guaranteed_capacity();
+ this->_M_update_guaranteed_capacity();
}
#endif
@@ -281,37 +326,37 @@
void
resize(size_type __sz)
{
- bool __realloc = _M_requires_reallocation(__sz);
+ bool __realloc = this->_M_requires_reallocation(__sz);
if (__sz < this->size())
this->_M_invalidate_after_nth(__sz);
_Base::resize(__sz);
if (__realloc)
this->_M_invalidate_all();
- _M_update_guaranteed_capacity();
+ this->_M_update_guaranteed_capacity();
}
void
resize(size_type __sz, const _Tp& __c)
{
- bool __realloc = _M_requires_reallocation(__sz);
+ bool __realloc = this->_M_requires_reallocation(__sz);
if (__sz < this->size())
this->_M_invalidate_after_nth(__sz);
_Base::resize(__sz, __c);
if (__realloc)
this->_M_invalidate_all();
- _M_update_guaranteed_capacity();
+ this->_M_update_guaranteed_capacity();
}
#else
void
resize(size_type __sz, _Tp __c = _Tp())
{
- bool __realloc = _M_requires_reallocation(__sz);
+ bool __realloc = this->_M_requires_reallocation(__sz);
if (__sz < this->size())
this->_M_invalidate_after_nth(__sz);
_Base::resize(__sz, __c);
if (__realloc)
this->_M_invalidate_all();
- _M_update_guaranteed_capacity();
+ this->_M_update_guaranteed_capacity();
}
#endif
@@ -321,7 +366,7 @@
{
if (_Base::_M_shrink_to_fit())
{
- _M_guaranteed_capacity = _Base::capacity();
+ this->_M_guaranteed_capacity = _Base::capacity();
this->_M_invalidate_all();
}
}
@@ -331,7 +376,7 @@
capacity() const _GLIBCXX_NOEXCEPT
{
#ifdef _GLIBCXX_DEBUG_PEDANTIC
- return _M_guaranteed_capacity;
+ return this->_M_guaranteed_capacity;
#else
return _Base::capacity();
#endif
@@ -342,10 +387,10 @@
void
reserve(size_type __n)
{
- bool __realloc = _M_requires_reallocation(__n);
+ bool __realloc = this->_M_requires_reallocation(__n);
_Base::reserve(__n);
- if (__n > _M_guaranteed_capacity)
- _M_guaranteed_capacity = __n;
+ if (__n > this->_M_guaranteed_capacity)
+ this->_M_guaranteed_capacity = __n;
if (__realloc)
this->_M_invalidate_all();
}
@@ -403,11 +448,11 @@
void
push_back(const _Tp& __x)
{
- bool __realloc = _M_requires_reallocation(this->size() + 1);
+ bool __realloc = this->_M_requires_reallocation(this->size() + 1);
_Base::push_back(__x);
if (__realloc)
this->_M_invalidate_all();
- _M_update_guaranteed_capacity();
+ this->_M_update_guaranteed_capacity();
}
#if __cplusplus >= 201103L
@@ -421,11 +466,11 @@
void
emplace_back(_Args&&... __args)
{
- bool __realloc = _M_requires_reallocation(this->size() + 1);
+ bool __realloc = this->_M_requires_reallocation(this->size() + 1);
_Base::emplace_back(std::forward<_Args>(__args)...);
if (__realloc)
this->_M_invalidate_all();
- _M_update_guaranteed_capacity();
+ this->_M_update_guaranteed_capacity();
}
#endif
@@ -443,7 +488,7 @@
emplace(const_iterator __position, _Args&&... __args)
{
__glibcxx_check_insert(__position);
- bool __realloc = _M_requires_reallocation(this->size() + 1);
+ bool __realloc = this->_M_requires_reallocation(this->size() + 1);
difference_type __offset = __position.base() - _Base::begin();
_Base_iterator __res = _Base::emplace(__position.base(),
std::forward<_Args>(__args)...);
@@ -451,7 +496,7 @@
this->_M_invalidate_all();
else
this->_M_invalidate_after_nth(__offset);
- _M_update_guaranteed_capacity();
+ this->_M_update_guaranteed_capacity();
return iterator(__res, this);
}
#endif
@@ -464,14 +509,14 @@
#endif
{
__glibcxx_check_insert(__position);
- bool __realloc = _M_requires_reallocation(this->size() + 1);
+ bool __realloc = this->_M_requires_reallocation(this->size() + 1);
difference_type __offset = __position.base() - _Base::begin();
_Base_iterator __res = _Base::insert(__position.base(), __x);
if (__realloc)
this->_M_invalidate_all();
else
this->_M_invalidate_after_nth(__offset);
- _M_update_guaranteed_capacity();
+ this->_M_update_guaranteed_capacity();
return iterator(__res, this);
}
@@ -492,14 +537,14 @@
insert(const_iterator __position, size_type __n, const _Tp& __x)
{
__glibcxx_check_insert(__position);
- bool __realloc = _M_requires_reallocation(this->size() + __n);
+ bool __realloc = this->_M_requires_reallocation(this->size() + __n);
difference_type __offset = __position.base() - _Base::cbegin();
_Base_iterator __res = _Base::insert(__position.base(), __n, __x);
if (__realloc)
this->_M_invalidate_all();
else
this->_M_invalidate_after_nth(__offset);
- _M_update_guaranteed_capacity();
+ this->_M_update_guaranteed_capacity();
return iterator(__res, this);
}
#else
@@ -507,14 +552,14 @@
insert(iterator __position, size_type __n, const _Tp& __x)
{
__glibcxx_check_insert(__position);
- bool __realloc = _M_requires_reallocation(this->size() + __n);
+ bool __realloc = this->_M_requires_reallocation(this->size() + __n);
difference_type __offset = __position.base() - _Base::begin();
_Base::insert(__position.base(), __n, __x);
if (__realloc)
this->_M_invalidate_all();
else
this->_M_invalidate_after_nth(__offset);
- _M_update_guaranteed_capacity();
+ this->_M_update_guaranteed_capacity();
}
#endif
@@ -540,7 +585,7 @@
this->_M_invalidate_all();
else
this->_M_invalidate_after_nth(__offset);
- _M_update_guaranteed_capacity();
+ this->_M_update_guaranteed_capacity();
return iterator(__res, this);
}
#else
@@ -563,7 +608,7 @@
this->_M_invalidate_all();
else
this->_M_invalidate_after_nth(__offset);
- _M_update_guaranteed_capacity();
+ this->_M_update_guaranteed_capacity();
}
#endif
@@ -611,16 +656,12 @@
void
swap(vector& __x)
#if __cplusplus >= 201103L
- noexcept(_Alloc_traits::_S_nothrow_swap())
+ noexcept( noexcept(declval<_Base>().swap(__x)) )
#endif
{
-#if __cplusplus >= 201103L
- if (!_Alloc_traits::_S_propagate_on_swap())
- __glibcxx_check_equal_allocs(__x);
-#endif
+ _Safe::_M_swap(__x);
_Base::swap(__x);
- this->_M_swap(__x);
- std::swap(_M_guaranteed_capacity, __x._M_guaranteed_capacity);
+ std::swap(this->_M_guaranteed_capacity, __x._M_guaranteed_capacity);
}
void
@@ -628,7 +669,7 @@
{
_Base::clear();
this->_M_invalidate_all();
- _M_guaranteed_capacity = 0;
+ this->_M_guaranteed_capacity = 0;
}
_Base&
@@ -638,20 +679,7 @@
_M_base() const _GLIBCXX_NOEXCEPT { return *this; }
private:
- size_type _M_guaranteed_capacity;
-
- bool
- _M_requires_reallocation(size_type __elements) _GLIBCXX_NOEXCEPT
- { return __elements > this->capacity(); }
-
void
- _M_update_guaranteed_capacity() _GLIBCXX_NOEXCEPT
- {
- if (this->size() > _M_guaranteed_capacity)
- _M_guaranteed_capacity = this->size();
- }
-
- void
_M_invalidate_after_nth(difference_type __n) _GLIBCXX_NOEXCEPT
{
typedef __gnu_debug::_After_nth_from<_Base_const_iterator> _After_nth;
Index: src/c++11/debug.cc
===================================================================
--- src/c++11/debug.cc (revision 209446)
+++ src/c++11/debug.cc (working copy)
@@ -23,8 +23,8 @@
// <http://www.gnu.org/licenses/>.
#include <debug/debug.h>
-#include <debug/safe_sequence.h>
-#include <debug/safe_unordered_container.h>
+#include <debug/safe_base.h>
+#include <debug/safe_unordered_base.h>
#include <debug/safe_iterator.h>
#include <debug/safe_local_iterator.h>
#include <algorithm>
@@ -235,7 +235,7 @@
void
_Safe_sequence_base::
- _M_swap(_Safe_sequence_base& __x)
+ _M_swap(_Safe_sequence_base& __x) noexcept
{
// We need to lock both sequences to swap
using namespace __gnu_cxx;
@@ -382,7 +382,7 @@
_Safe_unordered_container_base*
_Safe_local_iterator_base::
- _M_get_container() const _GLIBCXX_NOEXCEPT
+ _M_get_container() const noexcept
{ return static_cast<_Safe_unordered_container_base*>(_M_sequence); }
void
@@ -455,7 +455,7 @@
void
_Safe_unordered_container_base::
- _M_swap(_Safe_unordered_container_base& __x)
+ _M_swap(_Safe_unordered_container_base& __x) noexcept
{
// We need to lock both containers to swap
using namespace __gnu_cxx;
Index: testsuite/23_containers/forward_list/allocator/move.cc
===================================================================
--- testsuite/23_containers/forward_list/allocator/move.cc (revision 209446)
+++ testsuite/23_containers/forward_list/allocator/move.cc (working copy)
@@ -32,9 +32,11 @@
typedef std::forward_list<T, alloc_type> test_type;
test_type v1(alloc_type(1));
v1 = { T() };
+ auto it = v1.begin();
test_type v2(std::move(v1));
VERIFY(1 == v1.get_allocator().get_personality());
VERIFY(1 == v2.get_allocator().get_personality());
+ VERIFY( it == v2.begin() );
}
void test02()
Index: testsuite/23_containers/forward_list/allocator/move_assign.cc
===================================================================
--- testsuite/23_containers/forward_list/allocator/move_assign.cc (revision 209446)
+++ testsuite/23_containers/forward_list/allocator/move_assign.cc (working copy)
@@ -46,11 +46,13 @@
typedef std::forward_list<T, alloc_type> test_type;
test_type v1(alloc_type(1));
v1.push_front(T());
+ auto it = v1.begin();
test_type v2(alloc_type(2));
v2.push_front(T());
v2 = std::move(v1);
VERIFY(0 == v1.get_allocator().get_personality());
VERIFY(1 == v2.get_allocator().get_personality());
+ VERIFY( it == v2.begin() );
}
int main()
Index: testsuite/23_containers/forward_list/debug/construct1_neg.cc
===================================================================
--- testsuite/23_containers/forward_list/debug/construct1_neg.cc (revision 0)
+++ testsuite/23_containers/forward_list/debug/construct1_neg.cc (working copy)
@@ -0,0 +1,34 @@
+// Copyright (C) 2014 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/>.
+//
+// { dg-require-debug-mode "" }
+// { dg-options "-std=gnu++11" }
+// { dg-do run { xfail *-*-* } }
+
+#include <forward_list>
+#include <debug/checks.h>
+
+void test01()
+{
+ __gnu_test::check_construct1<std::forward_list<int> >();
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
Index: testsuite/23_containers/forward_list/debug/construct2_neg.cc
===================================================================
--- testsuite/23_containers/forward_list/debug/construct2_neg.cc (revision 0)
+++ testsuite/23_containers/forward_list/debug/construct2_neg.cc (working copy)
@@ -0,0 +1,34 @@
+// Copyright (C) 2014 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/>.
+//
+// { dg-require-debug-mode "" }
+// { dg-options "-std=gnu++11" }
+// { dg-do run { xfail *-*-* } }
+
+#include <forward_list>
+#include <debug/checks.h>
+
+void test01()
+{
+ __gnu_test::check_construct2<std::forward_list<int> >();
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
Index: testsuite/23_containers/forward_list/debug/construct3_neg.cc
===================================================================
--- testsuite/23_containers/forward_list/debug/construct3_neg.cc (revision 0)
+++ testsuite/23_containers/forward_list/debug/construct3_neg.cc (working copy)
@@ -0,0 +1,34 @@
+// Copyright (C) 2010-2014 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/>.
+//
+// { dg-require-debug-mode "" }
+// { dg-options "-std=gnu++11" }
+// { dg-do run { xfail *-*-* } }
+
+#include <forward_list>
+#include <debug/checks.h>
+
+void test01()
+{
+ __gnu_test::check_construct3<std::forward_list<int> >();
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
Index: testsuite/23_containers/forward_list/debug/construct4_neg.cc
===================================================================
--- testsuite/23_containers/forward_list/debug/construct4_neg.cc (revision 0)
+++ testsuite/23_containers/forward_list/debug/construct4_neg.cc (working copy)
@@ -0,0 +1,44 @@
+// Copyright (C) 2014 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/>.
+//
+// { dg-options "-std=gnu++11" }
+// { dg-do run { xfail *-*-* } }
+
+#include <debug/forward_list>
+
+#include <testsuite_allocator.h>
+
+void test01()
+{
+ bool test __attribute__((unused)) = true;
+
+ typedef __gnu_test::uneq_allocator<int> alloc_type;
+ typedef __gnu_debug::forward_list<int, alloc_type> test_type;
+ test_type v1(alloc_type(1));
+ v1.push_front(0);
+ auto it = v1.begin();
+
+ test_type v2(std::move(v1), alloc_type(2));
+
+ VERIFY( it == v2.begin() ); // Error, it is singular
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
Index: testsuite/23_containers/forward_list/debug/move_assign_neg.cc
===================================================================
--- testsuite/23_containers/forward_list/debug/move_assign_neg.cc (revision 0)
+++ testsuite/23_containers/forward_list/debug/move_assign_neg.cc (working copy)
@@ -0,0 +1,47 @@
+// Copyright (C) 2014 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/>.
+//
+// { dg-options "-std=gnu++11" }
+// { dg-do run { xfail *-*-* } }
+
+#include <debug/forward_list>
+#include <testsuite_allocator.h>
+
+void test01()
+{
+ bool test __attribute__((unused)) = true;
+
+ typedef __gnu_test::uneq_allocator<int> alloc_type;
+ typedef __gnu_debug::forward_list<int, alloc_type> test_type;
+
+ test_type v1(alloc_type(1));
+ v1.push_front(0);
+ auto it = v1.begin();
+
+ test_type v2(alloc_type(2));
+ v2.push_front(1);
+
+ v2 = std::move(v1);
+
+ VERIFY( *it == 0 ); // Error, it is singular.
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
Index: testsuite/23_containers/forward_list/debug/move_neg.cc
===================================================================
--- testsuite/23_containers/forward_list/debug/move_neg.cc (revision 0)
+++ testsuite/23_containers/forward_list/debug/move_neg.cc (working copy)
@@ -0,0 +1,48 @@
+// Copyright (C) 2014 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/>.
+
+// { dg-options "-std=gnu++11" }
+// { dg-do run { xfail *-*-* } }
+
+#include <debug/forward_list>
+
+#include <testsuite_hooks.h>
+#include <testsuite_allocator.h>
+
+using __gnu_test::uneq_allocator;
+
+void test01()
+{
+ bool test __attribute__((unused)) = true;
+
+ typedef uneq_allocator<int> alloc_type;
+ typedef __gnu_debug::forward_list<int, alloc_type> test_type;
+
+ test_type v1(alloc_type(1));
+ v1 = { 0 };
+ auto it = v1.begin();
+
+ test_type v2(std::move(v1), alloc_type(2));
+
+ VERIFY( *it == 0 );
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
Index: testsuite/23_containers/map/allocator/move.cc
===================================================================
--- testsuite/23_containers/map/allocator/move.cc (revision 209446)
+++ testsuite/23_containers/map/allocator/move.cc (working copy)
@@ -38,9 +38,13 @@
typedef std::map<T, U, Cmp, alloc_type> test_type;
test_type v1(alloc_type(1));
v1 = { test_type::value_type{} };
+ auto it = v1.begin();
+
test_type v2(std::move(v1));
+
VERIFY(1 == v1.get_allocator().get_personality());
VERIFY(1 == v2.get_allocator().get_personality());
+ VERIFY( it == v2.begin() );
}
void test02()
Index: testsuite/23_containers/map/allocator/move_assign.cc
===================================================================
--- testsuite/23_containers/map/allocator/move_assign.cc (revision 209446)
+++ testsuite/23_containers/map/allocator/move_assign.cc (working copy)
@@ -38,9 +38,11 @@
typedef std::map<T, U, Cmp, alloc_type> test_type;
test_type v1(alloc_type(1));
v1 = { test_type::value_type{} };
+
test_type v2(alloc_type(2));
v2 = { test_type::value_type{} };
v2 = std::move(v1);
+
VERIFY(1 == v1.get_allocator().get_personality());
VERIFY(2 == v2.get_allocator().get_personality());
}
@@ -52,11 +54,15 @@
typedef std::map<T, U, Cmp, alloc_type> test_type;
test_type v1(alloc_type(1));
v1 = { test_type::value_type{} };
+ auto it = v1.begin();
+
test_type v2(alloc_type(2));
v2 = { test_type::value_type{} };
v2 = std::move(v1);
+
VERIFY(0 == v1.get_allocator().get_personality());
VERIFY(1 == v2.get_allocator().get_personality());
+ VERIFY( it == v2.begin() );
}
int main()
Index: testsuite/23_containers/map/debug/construct5_neg.cc
===================================================================
--- testsuite/23_containers/map/debug/construct5_neg.cc (revision 0)
+++ testsuite/23_containers/map/debug/construct5_neg.cc (working copy)
@@ -0,0 +1,45 @@
+// Copyright (C) 2014 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/>.
+//
+// { dg-options "-std=gnu++11" }
+// { dg-do run { xfail *-*-* } }
+
+#include <debug/map>
+
+#include <testsuite_allocator.h>
+
+void test01()
+{
+ bool test __attribute__((unused)) = true;
+
+ typedef __gnu_test::uneq_allocator<std::pair<const int, int> > alloc_type;
+ typedef __gnu_debug::map<int, int, std::less<int>, alloc_type> test_type;
+
+ test_type v1(alloc_type(1));
+ v1.insert(std::make_pair(0, 0));
+ auto it = v1.begin();
+
+ test_type v2(std::move(v1), alloc_type(2));
+
+ VERIFY( it->first == 0 ); // Error, it is singular
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
Index: testsuite/23_containers/map/debug/move_assign_neg.cc
===================================================================
--- testsuite/23_containers/map/debug/move_assign_neg.cc (revision 0)
+++ testsuite/23_containers/map/debug/move_assign_neg.cc (working copy)
@@ -0,0 +1,47 @@
+// Copyright (C) 2014 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/>.
+//
+// { dg-options "-std=gnu++11" }
+// { dg-do run { xfail *-*-* } }
+
+#include <debug/map>
+#include <testsuite_allocator.h>
+
+void test01()
+{
+ bool test __attribute__((unused)) = true;
+
+ typedef __gnu_test::uneq_allocator<std::pair<const int, int> > alloc_type;
+ typedef __gnu_debug::map<int, int, std::less<int>, alloc_type> test_type;
+
+ test_type v1(alloc_type(1));
+ v1.insert(std::make_pair(0, 0));
+ auto it = v1.begin();
+
+ test_type v2(alloc_type(2));
+ v2.insert(std::make_pair(1, 1));
+
+ v2 = std::move(v1);
+
+ VERIFY( it == v2.begin() ); // Error, it is singular.
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
Index: testsuite/23_containers/map/debug/move_neg.cc
===================================================================
--- testsuite/23_containers/map/debug/move_neg.cc (revision 0)
+++ testsuite/23_containers/map/debug/move_neg.cc (working copy)
@@ -0,0 +1,48 @@
+// Copyright (C) 2014 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/>.
+
+// { dg-options "-std=gnu++11" }
+// { dg-do run { xfail *-*-* } }
+
+#include <debug/map>
+
+#include <testsuite_hooks.h>
+#include <testsuite_allocator.h>
+
+using __gnu_test::uneq_allocator;
+
+void test01()
+{
+ bool test __attribute__((unused)) = true;
+
+ typedef uneq_allocator<std::pair<const int, int> > alloc_type;
+ typedef __gnu_debug::map<int, int, std::less<int>, alloc_type> test_type;
+
+ test_type v1(alloc_type(1));
+ v1 = { { 0, 0 } };
+ auto it = v1.begin();
+
+ test_type v2(std::move(v1), alloc_type(2));
+
+ VERIFY( it->first == 0 );
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
Index: testsuite/23_containers/multimap/allocator/move.cc
===================================================================
--- testsuite/23_containers/multimap/allocator/move.cc (revision 209446)
+++ testsuite/23_containers/multimap/allocator/move.cc (working copy)
@@ -38,9 +38,13 @@
typedef std::multimap<T, U, Cmp, alloc_type> test_type;
test_type v1(alloc_type(1));
v1 = { test_type::value_type{} };
+ auto it = v1.begin();
+
test_type v2(std::move(v1));
+
VERIFY(1 == v1.get_allocator().get_personality());
VERIFY(1 == v2.get_allocator().get_personality());
+ VERIFY( it == v2.begin() );
}
void test02()
Index: testsuite/23_containers/multimap/allocator/move_assign.cc
===================================================================
--- testsuite/23_containers/multimap/allocator/move_assign.cc (revision 209446)
+++ testsuite/23_containers/multimap/allocator/move_assign.cc (working copy)
@@ -52,11 +52,13 @@
typedef std::multimap<T, U, Cmp, alloc_type> test_type;
test_type v1(alloc_type(1));
v1 = { test_type::value_type{} };
+ auto it = v1.begin();
test_type v2(alloc_type(2));
v2 = { test_type::value_type{} };
v2 = std::move(v1);
VERIFY(0 == v1.get_allocator().get_personality());
VERIFY(1 == v2.get_allocator().get_personality());
+ VERIFY( it == v2.begin() );
}
int main()
Index: testsuite/23_containers/multimap/debug/construct5_neg.cc
===================================================================
--- testsuite/23_containers/multimap/debug/construct5_neg.cc (revision 0)
+++ testsuite/23_containers/multimap/debug/construct5_neg.cc (working copy)
@@ -0,0 +1,45 @@
+// Copyright (C) 2014 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/>.
+//
+// { dg-options "-std=gnu++11" }
+// { dg-do run { xfail *-*-* } }
+
+#include <debug/map>
+
+#include <testsuite_allocator.h>
+
+void test01()
+{
+ bool test __attribute__((unused)) = true;
+
+ typedef __gnu_test::uneq_allocator<std::pair<const int, int> > alloc_type;
+ typedef __gnu_debug::multimap<int, int, std::less<int>, alloc_type> test_type;
+
+ test_type v1(alloc_type(1));
+ v1.insert(std::make_pair(0, 0));
+ auto it = v1.begin();
+
+ test_type v2(std::move(v1), alloc_type(2));
+
+ VERIFY( it->first == 0 ); // Error, it is singular
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
Index: testsuite/23_containers/multimap/debug/move_assign_neg.cc
===================================================================
--- testsuite/23_containers/multimap/debug/move_assign_neg.cc (revision 0)
+++ testsuite/23_containers/multimap/debug/move_assign_neg.cc (working copy)
@@ -0,0 +1,47 @@
+// Copyright (C) 2014 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/>.
+//
+// { dg-options "-std=gnu++11" }
+// { dg-do run { xfail *-*-* } }
+
+#include <debug/map>
+#include <testsuite_allocator.h>
+
+void test01()
+{
+ bool test __attribute__((unused)) = true;
+
+ typedef __gnu_test::uneq_allocator<std::pair<const int, int> > alloc_type;
+ typedef __gnu_debug::multimap<int, int, std::less<int>, alloc_type> test_type;
+
+ test_type v1(alloc_type(1));
+ v1.insert(std::make_pair(0, 0));
+ auto it = v1.begin();
+
+ test_type v2(alloc_type(2));
+ v2.insert(std::make_pair(1, 1));
+
+ v2 = std::move(v1);
+
+ VERIFY( it == v2.begin() ); // Error, it is singular.
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
Index: testsuite/23_containers/multimap/debug/move_neg.cc
===================================================================
--- testsuite/23_containers/multimap/debug/move_neg.cc (revision 0)
+++ testsuite/23_containers/multimap/debug/move_neg.cc (working copy)
@@ -0,0 +1,48 @@
+// Copyright (C) 2014 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/>.
+
+// { dg-options "-std=gnu++11" }
+// { dg-do run { xfail *-*-* } }
+
+#include <debug/map>
+
+#include <testsuite_hooks.h>
+#include <testsuite_allocator.h>
+
+using __gnu_test::uneq_allocator;
+
+void test01()
+{
+ bool test __attribute__((unused)) = true;
+
+ typedef uneq_allocator<std::pair<const int, int> > alloc_type;
+ typedef __gnu_debug::multimap<int, int, std::less<int>, alloc_type> test_type;
+
+ test_type v1(alloc_type(1));
+ v1 = { { 0, 0 } };
+ auto it = v1.begin();
+
+ test_type v2(std::move(v1), alloc_type(2));
+
+ VERIFY( it->first == 0 );
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
Index: testsuite/23_containers/multiset/allocator/move.cc
===================================================================
--- testsuite/23_containers/multiset/allocator/move.cc (revision 209446)
+++ testsuite/23_containers/multiset/allocator/move.cc (working copy)
@@ -36,9 +36,13 @@
typedef std::multiset<T, Cmp, alloc_type> test_type;
test_type v1(alloc_type(1));
v1 = { test_type::value_type{} };
+ auto it = v1.begin();
+
test_type v2(std::move(v1));
+
VERIFY(1 == v1.get_allocator().get_personality());
VERIFY(1 == v2.get_allocator().get_personality());
+ VERIFY( it == v2.begin() );
}
void test02()
Index: testsuite/23_containers/multiset/allocator/move_assign.cc
===================================================================
--- testsuite/23_containers/multiset/allocator/move_assign.cc (revision 209446)
+++ testsuite/23_containers/multiset/allocator/move_assign.cc (working copy)
@@ -50,11 +50,13 @@
typedef std::multiset<T, Cmp, alloc_type> test_type;
test_type v1(alloc_type(1));
v1 = { test_type::value_type{} };
+ auto it = v1.begin();
test_type v2(alloc_type(2));
v2 = { test_type::value_type{} };
v2 = std::move(v1);
VERIFY(0 == v1.get_allocator().get_personality());
VERIFY(1 == v2.get_allocator().get_personality());
+ VERIFY( it == v2.begin() );
}
int main()
Index: testsuite/23_containers/multiset/debug/construct5_neg.cc
===================================================================
--- testsuite/23_containers/multiset/debug/construct5_neg.cc (revision 0)
+++ testsuite/23_containers/multiset/debug/construct5_neg.cc (working copy)
@@ -0,0 +1,45 @@
+// Copyright (C) 2014 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/>.
+//
+// { dg-options "-std=gnu++11" }
+// { dg-do run { xfail *-*-* } }
+
+#include <debug/set>
+
+#include <testsuite_allocator.h>
+
+void test01()
+{
+ bool test __attribute__((unused)) = true;
+
+ typedef __gnu_test::uneq_allocator<int> alloc_type;
+ typedef __gnu_debug::multiset<int, std::less<int>, alloc_type> test_type;
+
+ test_type v1(alloc_type(1));
+ v1.insert(0);
+ auto it = v1.begin();
+
+ test_type v2(std::move(v1), alloc_type(2));
+
+ VERIFY( *it == 0 ); // Error, it is singular
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
Index: testsuite/23_containers/multiset/debug/move_assign_neg.cc
===================================================================
--- testsuite/23_containers/multiset/debug/move_assign_neg.cc (revision 0)
+++ testsuite/23_containers/multiset/debug/move_assign_neg.cc (working copy)
@@ -0,0 +1,47 @@
+// Copyright (C) 2014 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/>.
+//
+// { dg-options "-std=gnu++11" }
+// { dg-do run { xfail *-*-* } }
+
+#include <debug/set>
+#include <testsuite_allocator.h>
+
+void test01()
+{
+ bool test __attribute__((unused)) = true;
+
+ typedef __gnu_test::uneq_allocator<int> alloc_type;
+ typedef __gnu_debug::multiset<int, std::less<int>, alloc_type> test_type;
+
+ test_type v1(alloc_type(1));
+ v1.insert(0);
+ auto it = v1.begin();
+
+ test_type v2(alloc_type(2));
+ v2.insert(1);
+
+ v2 = std::move(v1);
+
+ VERIFY( it == v2.begin() ); // Error, it is singular.
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
Index: testsuite/23_containers/multiset/debug/move_neg.cc
===================================================================
--- testsuite/23_containers/multiset/debug/move_neg.cc (revision 0)
+++ testsuite/23_containers/multiset/debug/move_neg.cc (working copy)
@@ -0,0 +1,48 @@
+// Copyright (C) 2014 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/>.
+
+// { dg-options "-std=gnu++11" }
+// { dg-do run { xfail *-*-* } }
+
+#include <debug/set>
+
+#include <testsuite_hooks.h>
+#include <testsuite_allocator.h>
+
+using __gnu_test::uneq_allocator;
+
+void test01()
+{
+ bool test __attribute__((unused)) = true;
+
+ typedef uneq_allocator<int> alloc_type;
+ typedef __gnu_debug::multiset<int, std::less<int>, alloc_type> test_type;
+
+ test_type v1(alloc_type(1));
+ v1 = { 0 };
+ auto it = v1.begin();
+
+ test_type v2(std::move(v1), alloc_type(2));
+
+ VERIFY( *it == 0 );
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
Index: testsuite/23_containers/set/allocator/move.cc
===================================================================
--- testsuite/23_containers/set/allocator/move.cc (revision 209446)
+++ testsuite/23_containers/set/allocator/move.cc (working copy)
@@ -38,9 +38,13 @@
typedef std::set<T, Cmp, alloc_type> test_type;
test_type v1(alloc_type(1));
v1 = { test_type::value_type{} };
+ auto it = v1.begin();
+
test_type v2(std::move(v1));
+
VERIFY(1 == v1.get_allocator().get_personality());
VERIFY(1 == v2.get_allocator().get_personality());
+ VERIFY( it == v2.begin() );
}
void test02()
Index: testsuite/23_containers/set/allocator/move_assign.cc
===================================================================
--- testsuite/23_containers/set/allocator/move_assign.cc (revision 209446)
+++ testsuite/23_containers/set/allocator/move_assign.cc (working copy)
@@ -50,11 +50,13 @@
typedef std::set<T, Cmp, alloc_type> test_type;
test_type v1(alloc_type(1));
v1 = { test_type::value_type{} };
+ auto it = v1.begin();
test_type v2(alloc_type(2));
v2 = { test_type::value_type{} };
v2 = std::move(v1);
VERIFY(0 == v1.get_allocator().get_personality());
VERIFY(1 == v2.get_allocator().get_personality());
+ VERIFY( it == v2.begin() );
}
int main()
Index: testsuite/23_containers/set/debug/construct5_neg.cc
===================================================================
--- testsuite/23_containers/set/debug/construct5_neg.cc (revision 0)
+++ testsuite/23_containers/set/debug/construct5_neg.cc (working copy)
@@ -0,0 +1,45 @@
+// Copyright (C) 2014 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/>.
+//
+// { dg-options "-std=gnu++11" }
+// { dg-do run { xfail *-*-* } }
+
+#include <debug/set>
+
+#include <testsuite_allocator.h>
+
+void test01()
+{
+ bool test __attribute__((unused)) = true;
+
+ typedef __gnu_test::uneq_allocator<int> alloc_type;
+ typedef __gnu_debug::set<int, std::less<int>, alloc_type> test_type;
+
+ test_type v1(alloc_type(1));
+ v1.insert(0);
+ auto it = v1.begin();
+
+ test_type v2(std::move(v1), alloc_type(2));
+
+ VERIFY( *it == 0 ); // Error, it is singular
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
Index: testsuite/23_containers/set/debug/move_assign_neg.cc
===================================================================
--- testsuite/23_containers/set/debug/move_assign_neg.cc (revision 0)
+++ testsuite/23_containers/set/debug/move_assign_neg.cc (working copy)
@@ -0,0 +1,47 @@
+// Copyright (C) 2014 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/>.
+//
+// { dg-options "-std=gnu++11" }
+// { dg-do run { xfail *-*-* } }
+
+#include <debug/set>
+#include <testsuite_allocator.h>
+
+void test01()
+{
+ bool test __attribute__((unused)) = true;
+
+ typedef __gnu_test::uneq_allocator<int> alloc_type;
+ typedef __gnu_debug::set<int, std::less<int>, alloc_type> test_type;
+
+ test_type v1(alloc_type(1));
+ v1.insert(0);
+ auto it = v1.begin();
+
+ test_type v2(alloc_type(2));
+ v2.insert(1);
+
+ v2 = std::move(v1);
+
+ VERIFY( it == v2.begin() ); // Error, it is singular.
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
Index: testsuite/23_containers/set/debug/move_neg.cc
===================================================================
--- testsuite/23_containers/set/debug/move_neg.cc (revision 0)
+++ testsuite/23_containers/set/debug/move_neg.cc (working copy)
@@ -0,0 +1,48 @@
+// Copyright (C) 2014 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/>.
+
+// { dg-options "-std=gnu++11" }
+// { dg-do run { xfail *-*-* } }
+
+#include <debug/set>
+
+#include <testsuite_hooks.h>
+#include <testsuite_allocator.h>
+
+using __gnu_test::uneq_allocator;
+
+void test01()
+{
+ bool test __attribute__((unused)) = true;
+
+ typedef uneq_allocator<int> alloc_type;
+ typedef __gnu_debug::set<int, std::less<int>, alloc_type> test_type;
+
+ test_type v1(alloc_type(1));
+ v1 = { 0 };
+ auto it = v1.begin();
+
+ test_type v2(std::move(v1), alloc_type(2));
+
+ VERIFY( *it == 0 );
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
Index: testsuite/23_containers/unordered_map/allocator/move.cc
===================================================================
--- testsuite/23_containers/unordered_map/allocator/move.cc (revision 209446)
+++ testsuite/23_containers/unordered_map/allocator/move.cc (working copy)
@@ -45,9 +45,11 @@
test_type v1(alloc_type(1));
v1.emplace(std::piecewise_construct,
std::make_tuple(T()), std::make_tuple(T()));
+ auto it = v1.begin();
test_type v2(std::move(v1));
VERIFY(1 == v1.get_allocator().get_personality());
VERIFY(1 == v2.get_allocator().get_personality());
+ VERIFY( it == v2.begin() );
}
void test02()
Index: testsuite/23_containers/unordered_map/allocator/move_assign.cc
===================================================================
--- testsuite/23_containers/unordered_map/allocator/move_assign.cc (revision 209446)
+++ testsuite/23_containers/unordered_map/allocator/move_assign.cc (working copy)
@@ -66,6 +66,8 @@
v1.emplace(std::piecewise_construct,
std::make_tuple(1), std::make_tuple(1));
+ auto it = v1.begin();
+
test_type v2(alloc_type(2));
v2.emplace(std::piecewise_construct,
std::make_tuple(2), std::make_tuple(2));
@@ -79,6 +81,8 @@
VERIFY( counter_type::move_assign_count == 0 );
VERIFY( counter_type::destructor_count == 2 );
+
+ VERIFY( it == v2.begin() );
}
int main()
Index: testsuite/23_containers/unordered_map/debug/construct5_neg.cc
===================================================================
--- testsuite/23_containers/unordered_map/debug/construct5_neg.cc (revision 0)
+++ testsuite/23_containers/unordered_map/debug/construct5_neg.cc (working copy)
@@ -0,0 +1,47 @@
+// Copyright (C) 2014 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/>.
+//
+// { dg-options "-std=gnu++11" }
+// { dg-do run { xfail *-*-* } }
+
+#include <debug/unordered_map>
+
+#include <testsuite_allocator.h>
+
+void test01()
+{
+ bool test __attribute__((unused)) = true;
+
+ typedef __gnu_test::uneq_allocator<std::pair<const int, int>> alloc_type;
+ typedef __gnu_debug::unordered_map<int, int, std::hash<int>,
+ std::equal_to<int>,
+ alloc_type> test_type;
+
+ test_type v1(alloc_type(1));
+ v1.insert(std::make_pair(0, 0));
+ auto it = v1.begin();
+
+ test_type v2(std::move(v1), alloc_type(2));
+
+ VERIFY( it == v2.begin() ); // Error, it is singular.
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
Index: testsuite/23_containers/unordered_map/debug/move_assign_neg.cc
===================================================================
--- testsuite/23_containers/unordered_map/debug/move_assign_neg.cc (revision 0)
+++ testsuite/23_containers/unordered_map/debug/move_assign_neg.cc (working copy)
@@ -0,0 +1,48 @@
+// Copyright (C) 2014 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/>.
+//
+// { dg-options "-std=gnu++11" }
+// { dg-do run { xfail *-*-* } }
+
+#include <debug/unordered_map>
+#include <testsuite_allocator.h>
+
+void test01()
+{
+ bool test __attribute__((unused)) = true;
+
+ typedef __gnu_test::uneq_allocator<std::pair<const int, int> > alloc_type;
+ typedef __gnu_debug::unordered_map<int, int,
+ std::hash<int>, std::equal_to<int>,
+ alloc_type> test_type;
+
+ test_type v1(alloc_type(1));
+ v1.insert(std::make_pair(0, 0));
+ auto it = v1.begin();
+
+ test_type v2(alloc_type(2));
+
+ v2 = std::move(v1);
+
+ VERIFY( it == v2.begin() ); // Error, it is singular.
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
Index: testsuite/23_containers/unordered_map/debug/move_neg.cc
===================================================================
--- testsuite/23_containers/unordered_map/debug/move_neg.cc (revision 0)
+++ testsuite/23_containers/unordered_map/debug/move_neg.cc (working copy)
@@ -0,0 +1,49 @@
+// Copyright (C) 2014 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/>.
+
+// { dg-options "-std=gnu++11" }
+// { dg-do run { xfail *-*-* } }
+
+#include <debug/unordered_map>
+
+#include <testsuite_hooks.h>
+#include <testsuite_allocator.h>
+
+using __gnu_test::uneq_allocator;
+
+void test01()
+{
+ bool test __attribute__((unused)) = true;
+
+ typedef uneq_allocator<std::pair<const int, int> > alloc_type;
+ typedef __gnu_debug::unordered_map<
+ int, int, std::hash<int>, std::equal_to<int>, alloc_type> test_type;
+
+ test_type v1(alloc_type(1));
+ v1 = { { 0, 0 } };
+ auto it = v1.begin();
+
+ test_type v2(std::move(v1), alloc_type(2));
+
+ VERIFY( it->first == 0 );
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
Index: testsuite/23_containers/unordered_multimap/allocator/move.cc
===================================================================
--- testsuite/23_containers/unordered_multimap/allocator/move.cc (revision 209446)
+++ testsuite/23_containers/unordered_multimap/allocator/move.cc (working copy)
@@ -45,9 +45,11 @@
test_type v1(alloc_type(1));
v1.emplace(std::piecewise_construct,
std::make_tuple(T()), std::make_tuple(T()));
+ auto it = v1.begin();
test_type v2(std::move(v1));
VERIFY(1 == v1.get_allocator().get_personality());
VERIFY(1 == v2.get_allocator().get_personality());
+ VERIFY( it == v2.begin() );
}
void test02()
Index: testsuite/23_containers/unordered_multimap/allocator/move_assign.cc
===================================================================
--- testsuite/23_containers/unordered_multimap/allocator/move_assign.cc (revision 209446)
+++ testsuite/23_containers/unordered_multimap/allocator/move_assign.cc (working copy)
@@ -66,6 +66,8 @@
v1.emplace(std::piecewise_construct,
std::make_tuple(1), std::make_tuple(1));
+ auto it = v1.begin();
+
test_type v2(alloc_type(2));
v2.emplace(std::piecewise_construct,
std::make_tuple(2), std::make_tuple(2));
@@ -79,6 +81,8 @@
VERIFY( counter_type::move_assign_count == 0 );
VERIFY( counter_type::destructor_count == 2 );
+
+ VERIFY( it == v2.begin() );
}
int main()
Index: testsuite/23_containers/unordered_multimap/debug/construct5_neg.cc
===================================================================
--- testsuite/23_containers/unordered_multimap/debug/construct5_neg.cc (revision 0)
+++ testsuite/23_containers/unordered_multimap/debug/construct5_neg.cc (working copy)
@@ -0,0 +1,47 @@
+// Copyright (C) 2014 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/>.
+//
+// { dg-options "-std=gnu++11" }
+// { dg-do run { xfail *-*-* } }
+
+#include <debug/unordered_map>
+
+#include <testsuite_allocator.h>
+
+void test01()
+{
+ bool test __attribute__((unused)) = true;
+
+ typedef __gnu_test::uneq_allocator<std::pair<const int, int>> alloc_type;
+ typedef __gnu_debug::unordered_multimap<int, int,
+ std::hash<int>, std::equal_to<int>,
+ alloc_type> test_type;
+
+ test_type v1(alloc_type(1));
+ v1.insert(std::make_pair(0, 0));
+ auto it = v1.begin();
+
+ test_type v2(std::move(v1), alloc_type(2));
+
+ VERIFY( it == v2.begin() ); // Error, it is singular.
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
Index: testsuite/23_containers/unordered_multimap/debug/move_assign_neg.cc
===================================================================
--- testsuite/23_containers/unordered_multimap/debug/move_assign_neg.cc (revision 0)
+++ testsuite/23_containers/unordered_multimap/debug/move_assign_neg.cc (working copy)
@@ -0,0 +1,48 @@
+// Copyright (C) 2014 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/>.
+//
+// { dg-options "-std=gnu++11" }
+// { dg-do run { xfail *-*-* } }
+
+#include <debug/unordered_map>
+#include <testsuite_allocator.h>
+
+void test01()
+{
+ bool test __attribute__((unused)) = true;
+
+ typedef __gnu_test::uneq_allocator<std::pair<const int, int>> alloc_type;
+ typedef __gnu_debug::unordered_multimap<int, int, std::hash<int>,
+ std::equal_to<int>,
+ alloc_type> test_type;
+
+ test_type v1(alloc_type(1));
+ v1.insert(std::make_pair(0, 0));
+ auto it = v1.begin();
+
+ test_type v2(alloc_type(2));
+
+ v2 = std::move(v1);
+
+ VERIFY( it == v2.begin() ); // Error, it is singular.
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
Index: testsuite/23_containers/unordered_multimap/debug/move_neg.cc
===================================================================
--- testsuite/23_containers/unordered_multimap/debug/move_neg.cc (revision 0)
+++ testsuite/23_containers/unordered_multimap/debug/move_neg.cc (working copy)
@@ -0,0 +1,49 @@
+// Copyright (C) 2014 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/>.
+
+// { dg-options "-std=gnu++11" }
+// { dg-do run { xfail *-*-* } }
+
+#include <debug/unordered_map>
+
+#include <testsuite_hooks.h>
+#include <testsuite_allocator.h>
+
+using __gnu_test::uneq_allocator;
+
+void test01()
+{
+ bool test __attribute__((unused)) = true;
+
+ typedef uneq_allocator<std::pair<const int, int> > alloc_type;
+ typedef __gnu_debug::unordered_multimap<
+ int, int, std::hash<int>, std::equal_to<int>, alloc_type> test_type;
+
+ test_type v1(alloc_type(1));
+ v1 = { { 0, 0 } };
+ auto it = v1.begin();
+
+ test_type v2(std::move(v1), alloc_type(2));
+
+ VERIFY( it->first == 0 );
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
Index: testsuite/23_containers/unordered_multiset/allocator/move.cc
===================================================================
--- testsuite/23_containers/unordered_multiset/allocator/move.cc (revision 209446)
+++ testsuite/23_containers/unordered_multiset/allocator/move.cc (working copy)
@@ -44,9 +44,11 @@
typedef std::unordered_multiset<T, hash, equal_to, alloc_type> test_type;
test_type v1(alloc_type(1));
v1.insert(T());
+ auto it = v1.begin();
test_type v2(std::move(v1));
VERIFY(1 == v1.get_allocator().get_personality());
VERIFY(1 == v2.get_allocator().get_personality());
+ VERIFY( it == v2.begin() );
}
void test02()
Index: testsuite/23_containers/unordered_multiset/allocator/move_assign.cc
===================================================================
--- testsuite/23_containers/unordered_multiset/allocator/move_assign.cc (revision 209446)
+++ testsuite/23_containers/unordered_multiset/allocator/move_assign.cc (working copy)
@@ -63,6 +63,8 @@
test_type v1(alloc_type(1));
v1.emplace(0);
+ auto it = v1.begin();
+
test_type v2(alloc_type(2));
v2.emplace(0);
@@ -76,6 +78,8 @@
VERIFY( counter_type::move_count == 0 );
VERIFY( counter_type::copy_count == 0 );
VERIFY( counter_type::destructor_count == 1 );
+
+ VERIFY( it == v2.begin() );
}
int main()
Index: testsuite/23_containers/unordered_multiset/debug/construct5_neg.cc
===================================================================
--- testsuite/23_containers/unordered_multiset/debug/construct5_neg.cc (revision 0)
+++ testsuite/23_containers/unordered_multiset/debug/construct5_neg.cc (working copy)
@@ -0,0 +1,47 @@
+// Copyright (C) 2014 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/>.
+//
+// { dg-options "-std=gnu++11" }
+// { dg-do run { xfail *-*-* } }
+
+#include <debug/unordered_set>
+
+#include <testsuite_allocator.h>
+
+void test01()
+{
+ bool test __attribute__((unused)) = true;
+
+ typedef __gnu_test::uneq_allocator<int> alloc_type;
+ typedef __gnu_debug::unordered_multiset<int, std::hash<int>,
+ std::equal_to<int>,
+ alloc_type> test_type;
+
+ test_type v1(alloc_type(1));
+ v1.insert(0);
+ auto it = v1.begin();
+
+ test_type v2(std::move(v1), alloc_type(2));
+
+ VERIFY( it == v2.begin() ); // Error, it is singular
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
Index: testsuite/23_containers/unordered_multiset/debug/move_assign_neg.cc
===================================================================
--- testsuite/23_containers/unordered_multiset/debug/move_assign_neg.cc (revision 0)
+++ testsuite/23_containers/unordered_multiset/debug/move_assign_neg.cc (working copy)
@@ -0,0 +1,49 @@
+// Copyright (C) 2014 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/>.
+//
+// { dg-options "-std=gnu++11" }
+// { dg-do run { xfail *-*-* } }
+
+#include <debug/unordered_set>
+#include <testsuite_allocator.h>
+
+void test01()
+{
+ bool test __attribute__((unused)) = true;
+
+ typedef __gnu_test::uneq_allocator<int> alloc_type;
+ typedef __gnu_debug::unordered_multiset<int, std::hash<int>,
+ std::equal_to<int>,
+ alloc_type> test_type;
+
+ test_type v1(alloc_type(1));
+ v1.emplace(0);
+ auto it = v1.begin();
+
+ test_type v2(alloc_type(2));
+ v2.emplace(1);
+
+ v2 = std::move(v1);
+
+ VERIFY( it == v2.begin() ); // Error, it is singular.
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
Index: testsuite/23_containers/unordered_multiset/debug/move_neg.cc
===================================================================
--- testsuite/23_containers/unordered_multiset/debug/move_neg.cc (revision 0)
+++ testsuite/23_containers/unordered_multiset/debug/move_neg.cc (working copy)
@@ -0,0 +1,49 @@
+// Copyright (C) 2014 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/>.
+
+// { dg-options "-std=gnu++11" }
+// { dg-do run { xfail *-*-* } }
+
+#include <debug/unordered_set>
+
+#include <testsuite_hooks.h>
+#include <testsuite_allocator.h>
+
+using __gnu_test::uneq_allocator;
+
+void test01()
+{
+ bool test __attribute__((unused)) = true;
+
+ typedef uneq_allocator<int> alloc_type;
+ typedef __gnu_debug::unordered_multiset<
+ int, std::hash<int>, std::equal_to<int>, alloc_type> test_type;
+
+ test_type v1(alloc_type(1));
+ v1 = { 0 };
+ auto it = v1.begin();
+
+ test_type v2(std::move(v1), alloc_type(2));
+
+ VERIFY( *it == 0 );
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
Index: testsuite/23_containers/unordered_set/allocator/move.cc
===================================================================
--- testsuite/23_containers/unordered_set/allocator/move.cc (revision 209446)
+++ testsuite/23_containers/unordered_set/allocator/move.cc (working copy)
@@ -44,9 +44,11 @@
typedef std::unordered_set<T, hash, equal_to, alloc_type> test_type;
test_type v1(alloc_type(1));
v1.insert(T());
+ auto it = v1.begin();
test_type v2(std::move(v1));
VERIFY(1 == v1.get_allocator().get_personality());
VERIFY(1 == v2.get_allocator().get_personality());
+ VERIFY( it == v2.begin() );
}
void test02()
Index: testsuite/23_containers/unordered_set/allocator/move_assign.cc
===================================================================
--- testsuite/23_containers/unordered_set/allocator/move_assign.cc (revision 209446)
+++ testsuite/23_containers/unordered_set/allocator/move_assign.cc (working copy)
@@ -63,6 +63,8 @@
test_type v1(alloc_type(1));
v1.emplace(0);
+ auto it = v1.begin();
+
test_type v2(alloc_type(2));
v2.emplace(0);
@@ -76,6 +78,8 @@
VERIFY( counter_type::move_count == 0 );
VERIFY( counter_type::copy_count == 0 );
VERIFY( counter_type::destructor_count == 1 );
+
+ VERIFY( it == v2.begin() );
}
int main()
Index: testsuite/23_containers/unordered_set/debug/construct5_neg.cc
===================================================================
--- testsuite/23_containers/unordered_set/debug/construct5_neg.cc (revision 0)
+++ testsuite/23_containers/unordered_set/debug/construct5_neg.cc (working copy)
@@ -0,0 +1,45 @@
+// Copyright (C) 2014 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/>.
+//
+// { dg-options "-std=gnu++11" }
+// { dg-do run { xfail *-*-* } }
+
+#include <debug/unordered_set>
+
+#include <testsuite_allocator.h>
+
+void test01()
+{
+ bool test __attribute__((unused)) = true;
+
+ typedef __gnu_test::uneq_allocator<int> alloc_type;
+ typedef __gnu_debug::unordered_set<int, std::hash<int>,
+ std::equal_to<int>, alloc_type> test_type;
+ test_type v1(alloc_type(1));
+ v1.insert(0);
+ auto it = v1.begin();
+
+ test_type v2(std::move(v1), alloc_type(2));
+
+ VERIFY( it == v2.begin() ); // Error, it is singular
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
Index: testsuite/23_containers/unordered_set/debug/move_assign_neg.cc
===================================================================
--- testsuite/23_containers/unordered_set/debug/move_assign_neg.cc (revision 0)
+++ testsuite/23_containers/unordered_set/debug/move_assign_neg.cc (working copy)
@@ -0,0 +1,49 @@
+// Copyright (C) 2014 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/>.
+//
+// { dg-options "-std=gnu++11" }
+// { dg-do run { xfail *-*-* } }
+
+#include <debug/unordered_set>
+#include <testsuite_allocator.h>
+
+void test01()
+{
+ bool test __attribute__((unused)) = true;
+
+ typedef __gnu_test::uneq_allocator<int> alloc_type;
+ typedef __gnu_debug::unordered_set<int, std::hash<int>,
+ std::equal_to<int>,
+ alloc_type> test_type;
+
+ test_type v1(alloc_type(1));
+ v1.emplace(0);
+ auto it = v1.begin();
+
+ test_type v2(alloc_type(2));
+ v2.emplace(1);
+
+ v2 = std::move(v1);
+
+ VERIFY( it == v2.begin() ); // Error, it is singular.
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
Index: testsuite/23_containers/unordered_set/debug/move_neg.cc
===================================================================
--- testsuite/23_containers/unordered_set/debug/move_neg.cc (revision 0)
+++ testsuite/23_containers/unordered_set/debug/move_neg.cc (working copy)
@@ -0,0 +1,49 @@
+// Copyright (C) 2014 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/>.
+
+// { dg-options "-std=gnu++11" }
+// { dg-do run { xfail *-*-* } }
+
+#include <debug/unordered_set>
+
+#include <testsuite_hooks.h>
+#include <testsuite_allocator.h>
+
+using __gnu_test::uneq_allocator;
+
+void test01()
+{
+ bool test __attribute__((unused)) = true;
+
+ typedef uneq_allocator<int> alloc_type;
+ typedef __gnu_debug::unordered_set<
+ int, std::hash<int>, std::equal_to<int>, alloc_type> test_type;
+
+ test_type v1(alloc_type(1));
+ v1 = { 0 };
+ auto it = v1.begin();
+
+ test_type v2(std::move(v1), alloc_type(2));
+
+ VERIFY( *it == 0 );
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
Index: testsuite/23_containers/vector/debug/move_neg.cc
===================================================================
--- testsuite/23_containers/vector/debug/move_neg.cc (revision 0)
+++ testsuite/23_containers/vector/debug/move_neg.cc (working copy)
@@ -0,0 +1,48 @@
+// Copyright (C) 2014 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/>.
+
+// { dg-options "-std=gnu++11" }
+// { dg-do run { xfail *-*-* } }
+
+#include <debug/vector>
+
+#include <testsuite_hooks.h>
+#include <testsuite_allocator.h>
+
+using __gnu_test::uneq_allocator;
+
+void test01()
+{
+ bool test __attribute__((unused)) = true;
+
+ typedef uneq_allocator<int> alloc_type;
+ typedef __gnu_debug::vector<int, alloc_type> test_type;
+
+ test_type v1(alloc_type(1));
+ v1 = { 0 };
+ auto it = v1.begin();
+
+ test_type v2(std::move(v1), alloc_type(2));
+
+ VERIFY( *it == 0 );
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
Index: testsuite/util/debug/checks.h
===================================================================
--- testsuite/util/debug/checks.h (revision 209446)
+++ testsuite/util/debug/checks.h (working copy)
@@ -179,10 +179,8 @@
val_type *first = &v.front() + 1;
val_type *last = first + 2;
- cont_type c1(first, last);
- VERIFY(c1.size() == 2);
- cont_type c2(last, first); // Expected failure
+ cont_type c(last, first); // Expected failure
}
// Check that invalid range of debug random iterators is detected
@@ -206,10 +204,8 @@
typename vector_type::iterator first = v.begin() + 1;
typename vector_type::iterator last = first + 2;
- cont_type c1(first, last);
- VERIFY(c1.size() == 2);
- cont_type c2(last, first); // Expected failure
+ cont_type c(last, first); // Expected failure
}
// Check that invalid range of debug not random iterators is detected
@@ -233,10 +229,8 @@
typename list_type::iterator first = l.begin(); ++first;
typename list_type::iterator last = first; ++last; ++last;
- cont_type c1(first, last);
- VERIFY(c1.size() == 2);
- cont_type c2(last, first); // Expected failure
+ cont_type c(last, first); // Expected failure
}
template <typename _Cont>
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: debug container patch
2014-04-17 20:52 debug container patch François Dumont
@ 2014-04-18 10:59 ` Jonathan Wakely
2014-04-27 14:43 ` Jonathan Wakely
1 sibling, 0 replies; 10+ messages in thread
From: Jonathan Wakely @ 2014-04-18 10:59 UTC (permalink / raw)
To: François Dumont; +Cc: libstdc++, gcc-patches
On 17 April 2014 21:43, François Dumont wrote:
> Hi
>
> Here is a patch to globally enhance debug containers implementation.
>
> I have isolated all code of special functions in a base class so that in
> C++11 we can use default implementations for the debug containers. This way
> implementation is simpler and inherit from the noexcept qualifications.
Excellent.
> I had to put a _IsCpp11AllocatorAware template parameter to this new
> type for types that are not yet C++11 allocator aware. We will be able to
> simplify it later.
Minor: we switch from using "cpp" to "cxx", meaning "cpp" can
unambiguously refer to the preprocessor, so I would use _IsCxx11...
for that.
> I noticed also that in std/c++11/debug.cc we have some methods qualified
> with noexcept while in a C++03 user code those methods will have a throw()
> qualification. Is that fine ?
Yes, an empty throw() is compatible with noexcept(true).
I'll review the rest of the patch over the weekend, thanks!
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: debug container patch
2014-04-17 20:52 debug container patch François Dumont
2014-04-18 10:59 ` Jonathan Wakely
@ 2014-04-27 14:43 ` Jonathan Wakely
2014-04-28 21:14 ` François Dumont
1 sibling, 1 reply; 10+ messages in thread
From: Jonathan Wakely @ 2014-04-27 14:43 UTC (permalink / raw)
To: François Dumont; +Cc: libstdc++, gcc-patches
On 17/04/14 22:43 +0200, François Dumont wrote:
>Hi
>
> Here is a patch to globally enhance debug containers implementation.
François, sorry for the delay, this is a large patch and I wanted to
give it the time it deserves to review properly.
> I have isolated all code of special functions in a base class so
>that in C++11 we can use default implementations for the debug
>containers. This way implementation is simpler and inherit from the
>noexcept qualifications.
I like this approach, the result is simpler and less repetitive, but
I'm slightly concerned by inverting the inheritance ...
> _Safe_container is now using the debug base class
>(_Safe_sequence, _Safe_node_sequence, _Safe_forward_list...) as a
>policy describing what must be done as _M_invalidate_all or _M_swap.
>Note that I needed to invert inheritance so that I can use this base
>type to do checks with allocators before they get potentially moved
>by the normal code.
I understand why this is needed, but it changes the layout of the
classes in very significant ways, meaning the debug containers will
not be compatible across GCC releases. I'm OK with that now, but from
the next major GCC release I'd like to avoid that in future.
> This is the case for the allocator aware move
>constructor and move assignment operator. With the allocator aware
>move constructor it is in fact fixing a bug, iterators were not
>correctly swap when they had to.
Great, I had been meaning to fully review the iterator handling in
those kind of cases, thanks for finding and fixing this.
> I had to put a _IsCpp11AllocatorAware template parameter to this
>new type for types that are not yet C++11 allocator aware. We will be
>able to simplify it later.
Yes, that should become unnecessary by the end of stage 1, but for now
it serves a purpose. As I said in my other email, please rename it to
_IsCxx11AllocatorAware, for consistency with the rest of the library.
> I noticed also that in std/c++11/debug.cc we have some methods
>qualified with noexcept while in a C++03 user code those methods will
>have a throw() qualification. Is that fine ?
As I said in my last mail, yes, those specifications are compatible.
But I don't think your changes are doing what you think they are doing
in all cases. Using _GLIBCXX_NOEXCEPT does not expand to throw() in
C++03 mode, it expands to nothing.
If you want a macro that expands to either throw() or noexcept, then
you should be using _GLIBCXX_USE_NOEXCEPT.
> * include/debug/safe_sequence.tcc
> * include/debug/safe_unordered_base.h
> * include/debug/safe_unordered_container.h
> (_Safe_unordered_container_base()): Add noexcept.
> (~_Safe_unordered_container_base()): Likewise.
> (_M_swap(_Safe_unordered_container_base&)): Likewise.
> * include/debug/safe_unordered_container.tcc
N.B. This file has no changes listed in the changelog entry.
>@@ -69,8 +75,26 @@
>
> // 23.2.1.1 construct/copy/destroy:
>
>- deque() : _Base() { }
>+#if __cplusplus < 201103L
>+ deque()
>+ : _Base() { }
>
>+ deque(const deque& __x)
>+ : _Base(__x) { }
>+
>+ ~deque() _GLIBCXX_NOEXCEPT { }
In C++03 mode the _GLIBCXX_NOEXCEPT macro expands to an empty string,
so it is useless in this chunk of code, which is only compiled for
C++03 mode. It should probably just be removed here (and in all the
other debug containers which use it in C++03-only code).
>Index: include/debug/forward_list
>===================================================================
>--- include/debug/forward_list (revision 209446)
>+++ include/debug/forward_list (working copy)
>@@ -33,8 +33,113 @@
>
> #include <forward_list>
> #include <debug/safe_sequence.h>
>+#include <debug/safe_container.h>
> #include <debug/safe_iterator.h>
>
>+namespace __gnu_debug
>+{
>+ /// Special iterators swap and invalidation for forward_list because of the
>+ /// before_begin iterator.
>+ template<typename _SafeSequence>
>+ class _Safe_forward_list
>+ : public _Safe_sequence<_SafeSequence>
>+ {
>+ _SafeSequence&
>+ _M_this() noexcept
>+ { return *static_cast<_SafeSequence*>(this); }
>+
>+ static void
>+ _M_swap_aux(_Safe_sequence_base& __lhs,
>+ _Safe_iterator_base*& __lhs_iterators,
>+ _Safe_sequence_base& __rhs,
>+ _Safe_iterator_base*& __rhs_iterators);
>+
>+ protected:
>+ void
>+ _M_invalidate_all()
>+ {
>+ using _Base_const_iterator = __decltype(_M_this()._M_base().cend());
>+ this->_M_invalidate_if([this](_Base_const_iterator __it)
>+ {
>+ return __it != _M_this()._M_base().cbefore_begin()
>+ && __it != _M_this()._M_base().cend(); });
>+ }
>+
>+ void _M_swap(_Safe_sequence_base&) noexcept;
>+ };
>+
>+ template<typename _SafeSequence>
>+ void
>+ _Safe_forward_list<_SafeSequence>::
>+ _M_swap_aux(_Safe_sequence_base& __lhs,
>+ _Safe_iterator_base*& __lhs_iterators,
>+ _Safe_sequence_base& __rhs,
>+ _Safe_iterator_base*& __rhs_iterators)
>+ {
>+ using const_iterator = typename _SafeSequence::const_iterator;
>+ _Safe_iterator_base* __bbegin_its = 0;
>+ _Safe_iterator_base* __last_bbegin = 0;
>+ _SafeSequence& __rseq = static_cast<_SafeSequence&>(__rhs);
>+
>+ for (_Safe_iterator_base* __iter = __lhs_iterators; __iter;)
>+ {
>+ // Even iterator are casted to const_iterator, not a problem.
"is cast" not "are casted" please
>+ const_iterator* __victim = static_cast<const_iterator*>(__iter);
>+ __iter = __iter->_M_next;
>+ if (__victim->base() == __rseq._M_base().cbefore_begin())
>+ {
>+ __victim->_M_unlink();
>+ if (__lhs_iterators == __victim)
>+ __lhs_iterators = __victim->_M_next;
>+ if (__bbegin_its)
>+ {
>+ __victim->_M_next = __bbegin_its;
>+ __bbegin_its->_M_prior = __victim;
>+ }
>+ else
>+ __last_bbegin = __victim;
>+ __bbegin_its = __victim;
>+ }
>+ else
>+ __victim->_M_sequence = &__lhs;
>+ }
>+
>+ if (__bbegin_its)
>+ {
>+ if (__rhs_iterators)
>+ {
>+ __rhs_iterators->_M_prior = __last_bbegin;
>+ __last_bbegin->_M_next = __rhs_iterators;
>+ }
>+ __rhs_iterators = __bbegin_its;
>+ }
>+ }
>+
>+ /* Special forward_list _M_swap version that do not swap the
"does not" instead of "do not" please
>+ * before-begin ownership.*/
>+ template<typename _SafeSequence>
>+ void
>+ _Safe_forward_list<_SafeSequence>::
>+ _M_swap(_Safe_sequence_base& __other) noexcept
>+ {
>+ __gnu_cxx::__scoped_lock sentry(_M_this()._M_get_mutex());
Shouldn't we be locking both containers' mutexes here?
As we do in src/c++11/debug.cc
>+ forward_list(forward_list&& __list, const allocator_type& __al)
>+ : _Safe(std::move(__list), __al),
>+ _Base(std::move(__list), __al)
>+ { }
This makes me feel uneasy, seeing a moved-from object being used
again, but I don't think changing it to use static_casts to the two
base classes would look better, so let's leave it like that.
>Index: include/debug/safe_base.h
>===================================================================
>--- include/debug/safe_base.h (revision 209446)
>+++ include/debug/safe_base.h (working copy)
>@@ -188,22 +188,18 @@
>
> protected:
> // Initialize with a version number of 1 and no iterators
>- _Safe_sequence_base()
>+ _Safe_sequence_base() _GLIBCXX_NOEXCEPT
This use of _GLIBCXX_NOEXCEPT are correct, if the intention is to be
noexcept in C++11 and have no exception specification in C++98/C++03.
> : _M_iterators(0), _M_const_iterators(0), _M_version(1)
> { }
>
> #if __cplusplus >= 201103L
> _Safe_sequence_base(const _Safe_sequence_base&) noexcept
> : _Safe_sequence_base() { }
>-
>- _Safe_sequence_base(_Safe_sequence_base&& __x) noexcept
>- : _Safe_sequence_base()
>- { _M_swap(__x); }
> #endif
>
> /** Notify all iterators that reference this sequence that the
> sequence is being destroyed. */
>- ~_Safe_sequence_base()
>+ ~_Safe_sequence_base() _GLIBCXX_NOEXCEPT
This is redundant. In C++03 the macro expands to nothing, and in C++11
destructors are noexcept by default anyway, so the macro adds nothing.
> { this->_M_detach_all(); }
>
> /** Detach all iterators, leaving them singular. */
>@@ -231,7 +227,7 @@
> * one container now reference the other container.
> */
> void
>- _M_swap(_Safe_sequence_base& __x);
>+ _M_swap(_Safe_sequence_base& __x) _GLIBCXX_NOEXCEPT;
This is OK, if the intention is to only have an exc eption spec in
C++11.
>+#if __cplusplus >= 201103L
>+ _Safe_container&
>+ operator=(_Safe_container&& __x) noexcept
>+ {
>+ __glibcxx_check_self_move_assign(__x);
N.B. I'm writing a paper for the next committee meeting to make it
clear that self-move-assignment is not undefined behaviour, so this
check will have to be removed in the future. At least your change
means there are fewer places to remove it from :-)
See http://gcc.gnu.org/PR59603 for some background.
> #include <debug/safe_sequence.tcc>
>Index: include/debug/safe_unordered_base.h
>===================================================================
>--- include/debug/safe_unordered_base.h (revision 209446)
>+++ include/debug/safe_unordered_base.h (working copy)
>@@ -132,15 +132,16 @@
>
> protected:
> // Initialize with a version number of 1 and no iterators
>- _Safe_unordered_container_base()
>+ _Safe_unordered_container_base() noexcept
> : _M_local_iterators(nullptr), _M_const_local_iterators(nullptr)
> { }
>
>- // Initialize with a version number of 1 and no iterators
>+ // Copy constructor do not copy iterators.
"does not" instead of "do not"
> _Safe_unordered_container_base(const _Safe_unordered_container_base&)
> noexcept
> : _Safe_unordered_container_base() { }
>
>+ // When moved unordered containers iterators are swapped.
> _Safe_unordered_container_base(_Safe_unordered_container_base&& __x)
> noexcept
> : _Safe_unordered_container_base()
>@@ -148,7 +149,7 @@
>
> /** Notify all iterators that reference this container that the
> container is being destroyed. */
>- ~_Safe_unordered_container_base()
>+ ~_Safe_unordered_container_base() noexcept
This noexcept is redundant.
I only looked over the testsuite changes quickly, but they look good.
The changes above are only minor, overall I like the proposal very
much. Thanks for working on this, one day our debug mode containers
will be perfect! :-)
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: debug container patch
2014-04-27 14:43 ` Jonathan Wakely
@ 2014-04-28 21:14 ` François Dumont
2014-05-02 20:33 ` François Dumont
2014-05-06 14:05 ` Jonathan Wakely
0 siblings, 2 replies; 10+ messages in thread
From: François Dumont @ 2014-04-28 21:14 UTC (permalink / raw)
To: Jonathan Wakely; +Cc: libstdc++, gcc-patches
[-- Attachment #1: Type: text/plain, Size: 12739 bytes --]
On 27/04/2014 15:39, Jonathan Wakely wrote:
> On 17/04/14 22:43 +0200, François Dumont wrote:
>> Hi
>>
>> Here is a patch to globally enhance debug containers implementation.
>
> François, sorry for the delay, this is a large patch and I wanted to
> give it the time it deserves to review properly.
No problem, I see that there are a lot of proposals lately.
>
> I understand why this is needed, but it changes the layout of the
> classes in very significant ways, meaning the debug containers will
> not be compatible across GCC releases. I'm OK with that now, but from
> the next major GCC release I'd like to avoid that in future.
I remember Paolo saying that there is no abi guaranty for debug mode
this is why I didn't hesitate in making this proposal. Will there be one
in the future ? I plan also breaking changes for profile mode to fix its
very bad performance.
>
>> I noticed also that in std/c++11/debug.cc we have some methods
>> qualified with noexcept while in a C++03 user code those methods will
>> have a throw() qualification. Is that fine ?
>
> As I said in my last mail, yes, those specifications are compatible.
> But I don't think your changes are doing what you think they are doing
> in all cases. Using _GLIBCXX_NOEXCEPT does not expand to throw() in
> C++03 mode, it expands to nothing.
Yes, I discover this difference in one of your recent mail.
>
>> * include/debug/safe_unordered_container.tcc
>
> N.B. This file has no changes listed in the changelog entry.
I reviewed the ChangeLog and limit modifications like in this file. Note
however that patch have been generated with '-x -b' option to hide white
space modifications. I clean usage of white chars in impacted files,
replaced some white spaces with tabs and remove useless white spaces.
>
>> @@ -69,8 +75,26 @@
>>
>> // 23.2.1.1 construct/copy/destroy:
>>
>> - deque() : _Base() { }
>> +#if __cplusplus < 201103L
>> + deque()
>> + : _Base() { }
>>
>> + deque(const deque& __x)
>> + : _Base(__x) { }
>> +
>> + ~deque() _GLIBCXX_NOEXCEPT { }
>
> In C++03 mode the _GLIBCXX_NOEXCEPT macro expands to an empty string,
> so it is useless in this chunk of code, which is only compiled for
> C++03 mode. It should probably just be removed here (and in all the
> other debug containers which use it in C++03-only code).
Ok, I cleaned those. Did you mean removing the whole explicit destructor
? Is it a coding Standard to always explicitly implement the destructor
or just a way to have Doxygen generate ?
> + * before-begin ownership.*/
>> + template<typename _SafeSequence>
>> + void
>> + _Safe_forward_list<_SafeSequence>::
>> + _M_swap(_Safe_sequence_base& __other) noexcept
>> + {
>> + __gnu_cxx::__scoped_lock sentry(_M_this()._M_get_mutex());
>
> Shouldn't we be locking both containers' mutexes here?
> As we do in src/c++11/debug.cc
Good point, not a regression but nice to fix in this patch.
>
>> + forward_list(forward_list&& __list, const allocator_type& __al)
>> + : _Safe(std::move(__list), __al),
>> + _Base(std::move(__list), __al)
>> + { }
>
> This makes me feel uneasy, seeing a moved-from object being used
> again, but I don't think changing it to use static_casts to the two
> base classes would look better, so let's leave it like that.
That indeed looks scary, we replaced with:
forward_list(forward_list&& __list, const allocator_type& __al)
: _Safe(std::move(__list._M_safe()), __al),
_Base(std::move(__list._M_base()), __al)
{ }
it makes clearer the fact that we move each part.
>
>> Index: include/debug/safe_base.h
>> ===================================================================
>> --- include/debug/safe_base.h (revision 209446)
>> +++ include/debug/safe_base.h (working copy)
>> @@ -188,22 +188,18 @@
>>
>> protected:
>> // Initialize with a version number of 1 and no iterators
>> - _Safe_sequence_base()
>> + _Safe_sequence_base() _GLIBCXX_NOEXCEPT
>
> This use of _GLIBCXX_NOEXCEPT are correct, if the intention is to be
> noexcept in C++11 and have no exception specification in C++98/C++03.
Yes, I preferred to use default implementation for special function in
C++11 so I qualified as many things as possible noexcept so that
resulting noexcept qualification depends only on the normal mode
noexcept qualification.
>
>> : _M_iterators(0), _M_const_iterators(0), _M_version(1)
>> { }
>>
>> #if __cplusplus >= 201103L
>> _Safe_sequence_base(const _Safe_sequence_base&) noexcept
>> : _Safe_sequence_base() { }
>> -
>> - _Safe_sequence_base(_Safe_sequence_base&& __x) noexcept
>> - : _Safe_sequence_base()
>> - { _M_swap(__x); }
>> #endif
>>
>> /** Notify all iterators that reference this sequence that the
>> sequence is being destroyed. */
>> - ~_Safe_sequence_base()
>> + ~_Safe_sequence_base() _GLIBCXX_NOEXCEPT
>
> This is redundant. In C++03 the macro expands to nothing, and in C++11
> destructors are noexcept by default anyway, so the macro adds nothing.
Ok, I didn't knew, I cleaned those then.
>
>> { this->_M_detach_all(); }
>>
>> /** Detach all iterators, leaving them singular. */
>> @@ -231,7 +227,7 @@
>> * one container now reference the other container.
>> */
>> void
>> - _M_swap(_Safe_sequence_base& __x);
>> + _M_swap(_Safe_sequence_base& __x) _GLIBCXX_NOEXCEPT;
>
> This is OK, if the intention is to only have an exc eption spec in
> C++11.
This is used in noexcept constructors so I prefer to make it
noexcept too.
I replaced this one with _GLIBCXX_USE_NOEXCEPT cause in
src/c++11/debug.cc we always build it as noexcept, just in case it
impacts the mangled name. I saw _GLIBCXX_NOTHROW in c++config but
doesn't seem to be used.
>
>
>> +#if __cplusplus >= 201103L
>> + _Safe_container&
>> + operator=(_Safe_container&& __x) noexcept
>> + {
>> + __glibcxx_check_self_move_assign(__x);
>
> N.B. I'm writing a paper for the next committee meeting to make it
> clear that self-move-assignment is not undefined behaviour, so this
> check will have to be removed in the future. At least your change
> means there are fewer places to remove it from :-)
> See http://gcc.gnu.org/PR59603 for some background.
>
> I only looked over the testsuite changes quickly, but they look good.
>
> The changes above are only minor, overall I like the proposal very
> much. Thanks for working on this, one day our debug mode containers
> will be perfect! :-)
>
Not yet, I will start submitting patches for the debug algos soon :-)
Here is the patch again with all your remarks. Ok to commit with the
following ChangeLog ?
2014-04-29 François Dumont <fdumont@gcc.gnu.org>
* include/debug/macros.h [__glibcxx_check_equal_allocs]: Add
parameter to pass the 2 instances to check allocator equality.
* include/debug/safe_container.h: New, define _Safe_container<>.
* include/Makefile.am: Add previous.
* include/debug/deque (std::__debug::deque<>): Inherit
_Safe_container<>. Use default implementation for all special
functions.
* include/debug/forward_list (std::__debug::forward_list<>):
Likewise.
* include/debug/list (std::__debug::list<>): Likewise.
* include/debug/map.h (std::__debug::map<>): Likewise.
* include/debug/multimap.h (std::__debug::multimap<>): Likewise.
* include/debug/set.h (std::__debug::set<>): Likewise.
* include/debug/multiset.h (std::__debug::multiset<>): Likewise.
* include/debug/string (std::__debug::basic_string<>): Likewise.
* include/debug/unordered_map
(std::__debug::unordered_map<>): Likewise.
(std::__debug::unordered_multimap<>): Likewise.
* include/debug/unordered_set
(std::__debug::unordered_set<>): Likewise.
(std::__debug::unordered_multiset<>): Likewise.
* include/debug/vector (std::__debug::vector<>): Likewise.
* include/debug/safe_base.h (_Safe_sequence_base()): Add
noexcept.
(_Safe_sequence_base(_Safe_sequence_base&&): Remove.
(~_Safe_sequence_base()): Add noexcept.
* include/debug/safe_sequence.h
(std::__debug::_Safe_node_sequence<>): New.
* include/debug/safe_unordered_base.h
(_Safe_unordered_container_base()): Add noexcept.
(~_Safe_unordered_container_base()): Likewise.
(_M_swap(_Safe_unordered_container_base&)): Likewise.
* include/debug/safe_unordered_container.h:
(_Safe_unordered_container<>::_M_invalidate_locals()): New.
(_Safe_unordered_container<>::_M_invalidate_all()): New.
* src/c++11/debug.cc: Limit includes, adapt methods noexcept
qualifications.
* testsuite/util/debug/checks.h (check_construct1): Just implement
an invalid constructor invocation and no other operations
potentially not supported by some types of container.
(check_construct2): Likewise.
(check_construct3): Likewise.
* testsuite/23_containers/forward_list/allocator/move.cc: Add
check on iterators to make sure they are correctly moved in debug
mode.
* testsuite/23_containers/forward_list/allocator/move_assign.cc:
Likewise.
* testsuite/23_containers/map/allocator/move.cc: Likewise.
* testsuite/23_containers/map/allocator/move_assign.cc: Likewise.
* testsuite/23_containers/multimap/allocator/move.cc: Likewise.
* testsuite/23_containers/multimap/allocator/move_assign.cc:
Likewise.
* testsuite/23_containers/multiset/allocator/move.cc: Likewise.
* testsuite/23_containers/multiset/allocator/move_assign.cc:
Likewise.
* testsuite/23_containers/set/allocator/move.cc: Likewise.
* testsuite/23_containers/set/allocator/move_assign.cc: Likewise.
* testsuite/23_containers/unordered_map/allocator/move.cc:
Likewise.
* testsuite/23_containers/unordered_map/allocator/move_assign.cc:
Likewise.
* testsuite/23_containers/unordered_multimap/allocator/move.cc:
Likewise.
* testsuite/23_containers/unordered_multimap/allocator/move_assign.cc:
Likewise.
* testsuite/23_containers/unordered_multiset/allocator/move.cc:
Likewise.
* testsuite/23_containers/unordered_multiset/allocator/move_assign.cc:
Likewise.
* testsuite/23_containers/unordered_set/allocator/move.cc:
Likewise.
* testsuite/23_containers/unordered_set/allocator/move_assign.cc:
Likewise.
* testsuite/23_containers/forward_list/debug/construct1_neg.cc:
New.
* testsuite/23_containers/forward_list/debug/construct2_neg.cc:
New.
* testsuite/23_containers/forward_list/debug/construct3_neg.cc:
New.
* testsuite/23_containers/forward_list/debug/construct4_neg.cc:
New.
* testsuite/23_containers/forward_list/debug/move_assign_neg.cc:
New.
* testsuite/23_containers/forward_list/debug/move_neg.cc: New.
* testsuite/23_containers/map/debug/construct5_neg.cc: New.
* testsuite/23_containers/map/debug/move_assign_neg.cc: New.
* testsuite/23_containers/map/debug/move_neg.cc: New.
* testsuite/23_containers/multimap/debug/construct5_neg.cc: New.
* testsuite/23_containers/multimap/debug/move_assign_neg.cc: New.
* testsuite/23_containers/multimap/debug/move_neg.cc: New.
* testsuite/23_containers/multiset/debug/construct5_neg.cc: New.
* testsuite/23_containers/multiset/debug/move_assign_neg.cc: New.
* testsuite/23_containers/multiset/debug/move_neg.cc: New.
* testsuite/23_containers/set/debug/construct5_neg.cc: New.
* testsuite/23_containers/set/debug/move_assign_neg.cc: New.
* testsuite/23_containers/set/debug/move_neg.cc: New.
* testsuite/23_containers/unordered_map/debug/construct5_neg.cc:
New.
* testsuite/23_containers/unordered_map/debug/move_assign_neg.cc:
New.
* testsuite/23_containers/unordered_map/debug/move_neg.cc: New.
* testsuite/23_containers/unordered_multimap/debug/construct5_neg.cc:
New.
* testsuite/23_containers/unordered_multimap/debug/move_assign_neg.cc:
New.
* testsuite/23_containers/unordered_multimap/debug/move_neg.cc:
New.
* testsuite/23_containers/unordered_multiset/debug/construct5_neg.cc:
New.
* testsuite/23_containers/unordered_multiset/debug/move_assign_neg.cc:
New.
* testsuite/23_containers/unordered_multiset/debug/move_neg.cc:
New.
* testsuite/23_containers/unordered_set/debug/construct5_neg.cc:
New.
* testsuite/23_containers/unordered_set/debug/move_assign_neg.cc:
New.
* testsuite/23_containers/unordered_set/debug/move_neg.cc: New.
* testsuite/23_containers/vector/debug/move_neg.cc: New.
François
[-- Attachment #2: safe_containers.patch --]
[-- Type: text/x-patch, Size: 173332 bytes --]
Index: include/Makefile.am
===================================================================
--- include/Makefile.am (revision 209879)
+++ include/Makefile.am (working copy)
@@ -733,6 +733,7 @@
${debug_srcdir}/multimap.h \
${debug_srcdir}/multiset.h \
${debug_srcdir}/safe_base.h \
+ ${debug_srcdir}/safe_container.h \
${debug_srcdir}/safe_iterator.h \
${debug_srcdir}/safe_iterator.tcc \
${debug_srcdir}/safe_local_iterator.h \
Index: include/debug/deque
===================================================================
--- include/debug/deque (revision 209879)
+++ include/debug/deque (working copy)
@@ -31,6 +31,7 @@
#include <deque>
#include <debug/safe_sequence.h>
+#include <debug/safe_container.h>
#include <debug/safe_iterator.h>
namespace std _GLIBCXX_VISIBILITY(default)
@@ -40,21 +41,26 @@
/// Class std::deque with safety/checking/debug instrumentation.
template<typename _Tp, typename _Allocator = std::allocator<_Tp> >
class deque
- : public _GLIBCXX_STD_C::deque<_Tp, _Allocator>,
- public __gnu_debug::_Safe_sequence<deque<_Tp, _Allocator> >
+ : public __gnu_debug::_Safe_container<
+ deque<_Tp, _Allocator>, _Allocator,
+ __gnu_debug::_Safe_sequence, false>,
+ public _GLIBCXX_STD_C::deque<_Tp, _Allocator>
{
typedef _GLIBCXX_STD_C::deque<_Tp, _Allocator> _Base;
+ typedef __gnu_debug::_Safe_container<
+ deque, _Allocator, __gnu_debug::_Safe_sequence, false> _Safe;
typedef typename _Base::const_iterator _Base_const_iterator;
typedef typename _Base::iterator _Base_iterator;
typedef __gnu_debug::_Equal_to<_Base_const_iterator> _Equal;
+
public:
typedef typename _Base::reference reference;
typedef typename _Base::const_reference const_reference;
- typedef __gnu_debug::_Safe_iterator<_Base_iterator,deque>
+ typedef __gnu_debug::_Safe_iterator<_Base_iterator, deque>
iterator;
- typedef __gnu_debug::_Safe_iterator<_Base_const_iterator,deque>
+ typedef __gnu_debug::_Safe_iterator<_Base_const_iterator, deque>
const_iterator;
typedef typename _Base::size_type size_type;
@@ -69,8 +75,26 @@
// 23.2.1.1 construct/copy/destroy:
- deque() : _Base() { }
+#if __cplusplus < 201103L
+ deque()
+ : _Base() { }
+ deque(const deque& __x)
+ : _Base(__x) { }
+
+ ~deque() { }
+#else
+ deque() = default;
+ deque(const deque&) = default;
+ deque(deque&&) = default;
+
+ deque(initializer_list<value_type> __l,
+ const allocator_type& __a = allocator_type())
+ : _Base(__l, __a) { }
+
+ ~deque() = default;
+#endif
+
explicit
deque(const _Allocator& __a)
: _Base(__a) { }
@@ -103,48 +127,28 @@
__gnu_debug::__base(__last), __a)
{ }
- deque(const deque& __x)
- : _Base(__x) { }
-
deque(const _Base& __x)
: _Base(__x) { }
-#if __cplusplus >= 201103L
- deque(deque&& __x)
- : _Base(std::move(__x))
- { this->_M_swap(__x); }
-
- deque(initializer_list<value_type> __l,
- const allocator_type& __a = allocator_type())
- : _Base(__l, __a) { }
-#endif
-
- ~deque() _GLIBCXX_NOEXCEPT { }
-
+#if __cplusplus < 201103L
deque&
operator=(const deque& __x)
{
- *static_cast<_Base*>(this) = __x;
- this->_M_invalidate_all();
+ this->_M_safe() = __x;
+ _M_base() = __x;
return *this;
}
+#else
+ deque&
+ operator=(const deque&) = default;
-#if __cplusplus >= 201103L
deque&
- operator=(deque&& __x) noexcept
- {
- // NB: DR 1204.
- // NB: DR 675.
- __glibcxx_check_self_move_assign(__x);
- clear();
- swap(__x);
- return *this;
- }
+ operator=(deque&&) = default;
deque&
operator=(initializer_list<value_type> __l)
{
- *static_cast<_Base*>(this) = __l;
+ _M_base() = __l;
this->_M_invalidate_all();
return *this;
}
@@ -241,7 +245,7 @@
typedef __gnu_debug::_After_nth_from<_Base_const_iterator> _After_nth;
this->_M_invalidate_if(_After_nth(__n, _Base::begin()));
}
-
+
public:
// 23.2.1.2 capacity:
using _Base::size;
@@ -559,10 +563,13 @@
}
void
- swap(deque& __x) _GLIBCXX_NOEXCEPT
+ swap(deque& __x)
+#if __cplusplus >= 201103L
+ noexcept( noexcept(declval<_Base>().swap(__x)) )
+#endif
{
+ _Safe::_M_swap(__x);
_Base::swap(__x);
- this->_M_swap(__x);
}
void
Index: include/debug/forward_list
===================================================================
--- include/debug/forward_list (revision 209879)
+++ include/debug/forward_list (working copy)
@@ -33,8 +33,138 @@
#include <forward_list>
#include <debug/safe_sequence.h>
+#include <debug/safe_container.h>
#include <debug/safe_iterator.h>
+namespace __gnu_debug
+{
+ /// Special iterators swap and invalidation for forward_list because of the
+ /// before_begin iterator.
+ template<typename _SafeSequence>
+ class _Safe_forward_list
+ : public _Safe_sequence<_SafeSequence>
+ {
+ _SafeSequence&
+ _M_this() noexcept
+ { return *static_cast<_SafeSequence*>(this); }
+
+ static void
+ _M_swap_aux(_Safe_sequence_base& __lhs,
+ _Safe_iterator_base*& __lhs_iterators,
+ _Safe_sequence_base& __rhs,
+ _Safe_iterator_base*& __rhs_iterators);
+
+ void _M_swap_single(_Safe_sequence_base&) noexcept;
+
+ protected:
+ void
+ _M_invalidate_all()
+ {
+ using _Base_const_iterator = __decltype(_M_this()._M_base().cend());
+ this->_M_invalidate_if([this](_Base_const_iterator __it)
+ {
+ return __it != _M_this()._M_base().cbefore_begin()
+ && __it != _M_this()._M_base().cend(); });
+ }
+
+ void _M_swap(_Safe_sequence_base&) noexcept;
+ };
+
+ template<typename _SafeSequence>
+ void
+ _Safe_forward_list<_SafeSequence>::
+ _M_swap_aux(_Safe_sequence_base& __lhs,
+ _Safe_iterator_base*& __lhs_iterators,
+ _Safe_sequence_base& __rhs,
+ _Safe_iterator_base*& __rhs_iterators)
+ {
+ using const_iterator = typename _SafeSequence::const_iterator;
+ _Safe_iterator_base* __bbegin_its = 0;
+ _Safe_iterator_base* __last_bbegin = 0;
+ _SafeSequence& __rseq = static_cast<_SafeSequence&>(__rhs);
+
+ for (_Safe_iterator_base* __iter = __lhs_iterators; __iter;)
+ {
+ // Even iterator is cast to const_iterator, not a problem.
+ const_iterator* __victim = static_cast<const_iterator*>(__iter);
+ __iter = __iter->_M_next;
+ if (__victim->base() == __rseq._M_base().cbefore_begin())
+ {
+ __victim->_M_unlink();
+ if (__lhs_iterators == __victim)
+ __lhs_iterators = __victim->_M_next;
+ if (__bbegin_its)
+ {
+ __victim->_M_next = __bbegin_its;
+ __bbegin_its->_M_prior = __victim;
+ }
+ else
+ __last_bbegin = __victim;
+ __bbegin_its = __victim;
+ }
+ else
+ __victim->_M_sequence = &__lhs;
+ }
+
+ if (__bbegin_its)
+ {
+ if (__rhs_iterators)
+ {
+ __rhs_iterators->_M_prior = __last_bbegin;
+ __last_bbegin->_M_next = __rhs_iterators;
+ }
+ __rhs_iterators = __bbegin_its;
+ }
+ }
+
+ template<typename _SafeSequence>
+ void
+ _Safe_forward_list<_SafeSequence>::
+ _M_swap_single(_Safe_sequence_base& __other) noexcept
+ {
+ std::swap(_M_this()._M_iterators, __other._M_iterators);
+ std::swap(_M_this()._M_const_iterators, __other._M_const_iterators);
+ // Useless, always 1 on forward_list
+ //std::swap(_M_this()_M_version, __other._M_version);
+ _Safe_iterator_base* __this_its = _M_this()._M_iterators;
+ _M_swap_aux(__other, __other._M_iterators,
+ _M_this(), _M_this()._M_iterators);
+ _Safe_iterator_base* __this_const_its = _M_this()._M_const_iterators;
+ _M_swap_aux(__other, __other._M_const_iterators,
+ _M_this(), _M_this()._M_const_iterators);
+ _M_swap_aux(_M_this(), __this_its,
+ __other, __other._M_iterators);
+ _M_swap_aux(_M_this(), __this_const_its,
+ __other, __other._M_const_iterators);
+ }
+
+ /* Special forward_list _M_swap version that does not swap the
+ * before-begin ownership.*/
+ template<typename _SafeSequence>
+ void
+ _Safe_forward_list<_SafeSequence>::
+ _M_swap(_Safe_sequence_base& __other) noexcept
+ {
+ // We need to lock both sequences to swap
+ using namespace __gnu_cxx;
+ __mutex *__this_mutex = &_M_this()._M_get_mutex();
+ __mutex *__other_mutex = &__other._M_get_mutex();
+ if (__this_mutex == __other_mutex)
+ {
+ __scoped_lock __lock(*__this_mutex);
+ _M_swap_single(__other);
+ }
+ else
+ {
+ __scoped_lock __l1(__this_mutex < __other_mutex
+ ? *__this_mutex : *__other_mutex);
+ __scoped_lock __l2(__this_mutex < __other_mutex
+ ? *__other_mutex : *__this_mutex);
+ _M_swap_single(__other);
+ }
+ }
+}
+
namespace std _GLIBCXX_VISIBILITY(default)
{
namespace __debug
@@ -42,119 +172,88 @@
/// Class std::forward_list with safety/checking/debug instrumentation.
template<typename _Tp, typename _Alloc = std::allocator<_Tp> >
class forward_list
- : public _GLIBCXX_STD_C::forward_list<_Tp, _Alloc>,
- public __gnu_debug::_Safe_sequence<forward_list<_Tp, _Alloc> >
+ : public __gnu_debug::_Safe_container<
+ forward_list<_Tp, _Alloc>, _Alloc, __gnu_debug::_Safe_forward_list>,
+ public _GLIBCXX_STD_C::forward_list<_Tp, _Alloc>
{
typedef _GLIBCXX_STD_C::forward_list<_Tp, _Alloc> _Base;
+ typedef __gnu_debug::_Safe_container<
+ forward_list, _Alloc, __gnu_debug::_Safe_forward_list> _Safe;
typedef typename _Base::iterator _Base_iterator;
typedef typename _Base::const_iterator _Base_const_iterator;
- typedef typename __gnu_cxx::__alloc_traits<_Alloc>::template
- rebind<_GLIBCXX_STD_C::_Fwd_list_node<_Tp>>::other _Node_alloc_type;
-
- typedef __gnu_cxx::__alloc_traits<_Node_alloc_type> _Node_alloc_traits;
-
public:
typedef typename _Base::reference reference;
typedef typename _Base::const_reference const_reference;
- typedef __gnu_debug::_Safe_iterator<_Base_iterator,
- forward_list> iterator;
- typedef __gnu_debug::_Safe_iterator<_Base_const_iterator,
- forward_list> const_iterator;
+ typedef __gnu_debug::_Safe_iterator<
+ _Base_iterator, forward_list> iterator;
+ typedef __gnu_debug::_Safe_iterator<
+ _Base_const_iterator, forward_list> const_iterator;
typedef typename _Base::size_type size_type;
typedef typename _Base::difference_type difference_type;
typedef _Tp value_type;
- typedef _Alloc allocator_type;
+ typedef typename _Base::allocator_type allocator_type;
typedef typename _Base::pointer pointer;
typedef typename _Base::const_pointer const_pointer;
// 23.2.3.1 construct/copy/destroy:
explicit
- forward_list(const _Alloc& __al = _Alloc())
+ forward_list(const allocator_type& __al = allocator_type())
: _Base(__al) { }
- forward_list(const forward_list& __list, const _Alloc& __al)
+ forward_list(const forward_list& __list, const allocator_type& __al)
: _Base(__list, __al)
{ }
- forward_list(forward_list&& __list, const _Alloc& __al)
- : _Base(std::move(__list._M_base()), __al)
- {
- if (__list.get_allocator() == __al)
- this->_M_swap(__list);
- else
- __list._M_invalidate_all();
- }
+ forward_list(forward_list&& __list, const allocator_type& __al)
+ : _Safe(std::move(__list._M_safe()), __al),
+ _Base(std::move(__list._M_base()), __al)
+ { }
explicit
- forward_list(size_type __n, const _Alloc& __al = _Alloc())
+ forward_list(size_type __n, const allocator_type& __al = allocator_type())
: _Base(__n, __al)
{ }
forward_list(size_type __n, const _Tp& __value,
- const _Alloc& __al = _Alloc())
+ const allocator_type& __al = allocator_type())
: _Base(__n, __value, __al)
{ }
template<typename _InputIterator,
typename = std::_RequireInputIter<_InputIterator>>
forward_list(_InputIterator __first, _InputIterator __last,
- const _Alloc& __al = _Alloc())
+ const allocator_type& __al = allocator_type())
: _Base(__gnu_debug::__base(__gnu_debug::__check_valid_range(__first,
__last)),
__gnu_debug::__base(__last), __al)
{ }
- forward_list(const forward_list& __list)
- : _Base(__list)
- { }
+ forward_list(const forward_list&) = default;
- forward_list(forward_list&& __list) noexcept
- : _Base(std::move(__list._M_base()))
- {
- this->_M_swap(__list);
- }
+ forward_list(forward_list&&) = default;
forward_list(std::initializer_list<_Tp> __il,
- const _Alloc& __al = _Alloc())
+ const allocator_type& __al = allocator_type())
: _Base(__il, __al)
{ }
- ~forward_list() noexcept
- { }
+ ~forward_list() = default;
forward_list&
- operator=(const forward_list& __list)
- {
- static_cast<_Base&>(*this) = __list;
- this->_M_invalidate_all();
- return *this;
- }
+ operator=(const forward_list&) = default;
forward_list&
- operator=(forward_list&& __list)
- noexcept(_Node_alloc_traits::_S_nothrow_move())
- {
- __glibcxx_check_self_move_assign(__list);
- bool __xfer_memory = _Node_alloc_traits::_S_propagate_on_move_assign()
- || __list.get_allocator() == this->get_allocator();
- static_cast<_Base&>(*this) = std::move(__list);
- if (__xfer_memory)
- this->_M_swap(__list);
- else
- this->_M_invalidate_all();
- __list._M_invalidate_all();
- return *this;
- }
+ operator=(forward_list&&) = default;
forward_list&
operator=(std::initializer_list<_Tp> __il)
{
- static_cast<_Base&>(*this) = __il;
+ _M_base() = __il;
this->_M_invalidate_all();
return *this;
}
@@ -347,12 +446,10 @@
void
swap(forward_list& __list)
- noexcept(_Node_alloc_traits::_S_nothrow_swap())
+ noexcept( noexcept(declval<_Base>().swap(__list)) )
{
- if (!_Node_alloc_traits::_S_propagate_on_swap())
- __glibcxx_check_equal_allocs(__list);
+ _Safe::_M_swap(__list);
_Base::swap(__list);
- this->_M_swap(__list);
}
void
@@ -644,93 +741,9 @@
const _Base&
_M_base() const noexcept { return *this; }
-
- private:
- void
- _M_invalidate_all()
- {
- this->_M_invalidate_if([this](_Base_const_iterator __it)
- {
- return __it != this->_M_base().cbefore_begin()
- && __it != this->_M_base().cend();
- });
- }
- typedef __gnu_debug::_Safe_iterator_base _Safe_iterator_base;
- static void
- _M_swap_aux(forward_list& __lhs,
- _Safe_iterator_base*& __lhs_iterators,
- forward_list& __rhs,
- _Safe_iterator_base*& __rhs_iterators);
- void _M_swap(forward_list& __list);
};
template<typename _Tp, typename _Alloc>
- void
- forward_list<_Tp, _Alloc>::
- _M_swap_aux(forward_list<_Tp, _Alloc>& __lhs,
- __gnu_debug::_Safe_iterator_base*& __lhs_iterators,
- forward_list<_Tp, _Alloc>& __rhs,
- __gnu_debug::_Safe_iterator_base*& __rhs_iterators)
- {
- using __gnu_debug::_Safe_iterator_base;
- _Safe_iterator_base* __bbegin_its = 0;
- _Safe_iterator_base* __last_bbegin = 0;
- for (_Safe_iterator_base* __iter = __lhs_iterators; __iter;)
- {
- // Even iterator are casted to const_iterator, not a problem.
- const_iterator* __victim = static_cast<const_iterator*>(__iter);
- __iter = __iter->_M_next;
- if (__victim->base() == __rhs._M_base().cbefore_begin())
- {
- __victim->_M_unlink();
- if (__lhs_iterators == __victim)
- __lhs_iterators = __victim->_M_next;
- if (__bbegin_its)
- {
- __victim->_M_next = __bbegin_its;
- __bbegin_its->_M_prior = __victim;
- }
- else
- __last_bbegin = __victim;
- __bbegin_its = __victim;
- }
- else
- __victim->_M_sequence = &__lhs;
- }
-
- if (__bbegin_its)
- {
- if (__rhs_iterators)
- {
- __rhs_iterators->_M_prior = __last_bbegin;
- __last_bbegin->_M_next = __rhs_iterators;
- }
- __rhs_iterators = __bbegin_its;
- }
- }
-
- /* Special forward_list _M_swap version that do not swap the
- * before-begin ownership.*/
- template<typename _Tp, typename _Alloc>
- void
- forward_list<_Tp, _Alloc>::
- _M_swap(forward_list<_Tp, _Alloc>& __list)
- {
- __gnu_cxx::__scoped_lock sentry(this->_M_get_mutex());
- std::swap(this->_M_iterators, __list._M_iterators);
- std::swap(this->_M_const_iterators, __list._M_const_iterators);
- // Useless, always 1 on forward_list
- //std::swap(this->_M_version, __list._M_version);
- _Safe_iterator_base* __this_its = this->_M_iterators;
- _M_swap_aux(__list, __list._M_iterators, *this, this->_M_iterators);
- _Safe_iterator_base* __this_const_its = this->_M_const_iterators;
- _M_swap_aux(__list, __list._M_const_iterators, *this,
- this->_M_const_iterators);
- _M_swap_aux(*this, __this_its, __list, __list._M_iterators);
- _M_swap_aux(*this, __this_const_its, __list, __list._M_const_iterators);
- }
-
- template<typename _Tp, typename _Alloc>
bool
operator==(const forward_list<_Tp, _Alloc>& __lx,
const forward_list<_Tp, _Alloc>& __ly)
Index: include/debug/list
===================================================================
--- include/debug/list (revision 209879)
+++ include/debug/list (working copy)
@@ -31,6 +31,7 @@
#include <list>
#include <debug/safe_sequence.h>
+#include <debug/safe_container.h>
#include <debug/safe_iterator.h>
namespace std _GLIBCXX_VISIBILITY(default)
@@ -40,15 +41,20 @@
/// Class std::list with safety/checking/debug instrumentation.
template<typename _Tp, typename _Allocator = std::allocator<_Tp> >
class list
- : public _GLIBCXX_STD_C::list<_Tp, _Allocator>,
- public __gnu_debug::_Safe_sequence<list<_Tp, _Allocator> >
+ : public __gnu_debug::_Safe_container<
+ list<_Tp, _Allocator>, _Allocator,
+ __gnu_debug::_Safe_node_sequence, false>,
+ public _GLIBCXX_STD_C::list<_Tp, _Allocator>
{
typedef _GLIBCXX_STD_C::list<_Tp, _Allocator> _Base;
+ typedef __gnu_debug::_Safe_container<
+ list, _Allocator, __gnu_debug::_Safe_node_sequence, false> _Safe;
typedef typename _Base::iterator _Base_iterator;
typedef typename _Base::const_iterator _Base_const_iterator;
typedef __gnu_debug::_Equal_to<_Base_const_iterator> _Equal;
typedef __gnu_debug::_Not_equal_to<_Base_const_iterator> _Not_equal;
+
public:
typedef typename _Base::reference reference;
typedef typename _Base::const_reference const_reference;
@@ -70,9 +76,26 @@
// 23.2.2.1 construct/copy/destroy:
- list() _GLIBCXX_NOEXCEPT
+#if __cplusplus < 201103L
+ list()
: _Base() { }
+ list(const list& __x)
+ : _Base(__x) { }
+
+ ~list() { }
+#else
+ list() = default;
+ list(const list&) = default;
+ list(list&&) = default;
+
+ list(initializer_list<value_type> __l,
+ const allocator_type& __a = allocator_type())
+ : _Base(__l, __a) { }
+
+ ~list() = default;
+#endif
+
explicit
list(const _Allocator& __a) _GLIBCXX_NOEXCEPT
: _Base(__a) { }
@@ -105,49 +128,29 @@
__gnu_debug::__base(__last), __a)
{ }
- list(const list& __x)
- : _Base(__x) { }
-
list(const _Base& __x)
: _Base(__x) { }
-#if __cplusplus >= 201103L
- list(list&& __x) noexcept
- : _Base(std::move(__x))
- { this->_M_swap(__x); }
-
- list(initializer_list<value_type> __l,
- const allocator_type& __a = allocator_type())
- : _Base(__l, __a) { }
-#endif
-
- ~list() _GLIBCXX_NOEXCEPT { }
-
+#if __cplusplus < 201103L
list&
operator=(const list& __x)
{
- static_cast<_Base&>(*this) = __x;
- this->_M_invalidate_all();
+ this->_M_safe() = __x;
+ _M_base() = __x;
return *this;
}
+#else
+ list&
+ operator=(const list&) = default;
-#if __cplusplus >= 201103L
list&
- operator=(list&& __x)
- {
- // NB: DR 1204.
- // NB: DR 675.
- __glibcxx_check_self_move_assign(__x);
- clear();
- swap(__x);
- return *this;
- }
+ operator=(list&&) = default;
list&
operator=(initializer_list<value_type> __l)
{
- static_cast<_Base&>(*this) = __l;
this->_M_invalidate_all();
+ _M_base() = __l;
return *this;
}
@@ -245,16 +248,14 @@
{
this->_M_detach_singular();
- // if __sz < size(), invalidate all iterators in [begin+__sz, end())
+ // if __sz < size(), invalidate all iterators in [begin + __sz, end())
_Base_iterator __victim = _Base::begin();
_Base_iterator __end = _Base::end();
for (size_type __i = __sz; __victim != __end && __i > 0; --__i)
++__victim;
for (; __victim != __end; ++__victim)
- {
this->_M_invalidate_if(_Equal(__victim));
- }
__try
{
@@ -272,16 +273,14 @@
{
this->_M_detach_singular();
- // if __sz < size(), invalidate all iterators in [begin+__sz, end())
+ // if __sz < size(), invalidate all iterators in [begin + __sz, end())
_Base_iterator __victim = _Base::begin();
_Base_iterator __end = _Base::end();
for (size_type __i = __sz; __victim != __end && __i > 0; --__i)
++__victim;
for (; __victim != __end; ++__victim)
- {
this->_M_invalidate_if(_Equal(__victim));
- }
__try
{
@@ -299,16 +298,14 @@
{
this->_M_detach_singular();
- // if __sz < size(), invalidate all iterators in [begin+__sz, end())
+ // if __sz < size(), invalidate all iterators in [begin + __sz, end())
_Base_iterator __victim = _Base::begin();
_Base_iterator __end = _Base::end();
for (size_type __i = __sz; __victim != __end && __i > 0; --__i)
++__victim;
for (; __victim != __end; ++__victim)
- {
this->_M_invalidate_if(_Equal(__victim));
- }
__try
{
@@ -504,9 +501,12 @@
void
swap(list& __x)
+#if __cplusplus >= 201103L
+ noexcept( noexcept(declval<_Base>().swap(__x)) )
+#endif
{
+ _Safe::_M_swap(__x);
_Base::swap(__x);
- this->_M_swap(__x);
}
void
@@ -742,13 +742,6 @@
const _Base&
_M_base() const _GLIBCXX_NOEXCEPT { return *this; }
-
- private:
- void
- _M_invalidate_all()
- {
- this->_M_invalidate_if(_Not_equal(_Base::end()));
- }
};
template<typename _Tp, typename _Alloc>
Index: include/debug/macros.h
===================================================================
--- include/debug/macros.h (revision 209879)
+++ include/debug/macros.h (working copy)
@@ -347,10 +347,10 @@
_M_message(__gnu_debug::__msg_valid_load_factor) \
._M_sequence(*this, "this"))
-#define __glibcxx_check_equal_allocs(_Other) \
-_GLIBCXX_DEBUG_VERIFY(this->get_allocator() == _Other.get_allocator(), \
+#define __glibcxx_check_equal_allocs(_This, _Other) \
+_GLIBCXX_DEBUG_VERIFY(_This.get_allocator() == _Other.get_allocator(), \
_M_message(__gnu_debug::__msg_equal_allocs) \
- ._M_sequence(*this, "this"))
+ ._M_sequence(_This, "this"))
#ifdef _GLIBCXX_DEBUG_PEDANTIC
# define __glibcxx_check_string(_String) _GLIBCXX_DEBUG_ASSERT(_String != 0)
Index: include/debug/map.h
===================================================================
--- include/debug/map.h (revision 209879)
+++ include/debug/map.h (working copy)
@@ -30,6 +30,7 @@
#define _GLIBCXX_DEBUG_MAP_H 1
#include <debug/safe_sequence.h>
+#include <debug/safe_container.h>
#include <debug/safe_iterator.h>
#include <utility>
@@ -41,19 +42,20 @@
template<typename _Key, typename _Tp, typename _Compare = std::less<_Key>,
typename _Allocator = std::allocator<std::pair<const _Key, _Tp> > >
class map
- : public _GLIBCXX_STD_C::map<_Key, _Tp, _Compare, _Allocator>,
- public __gnu_debug::_Safe_sequence<map<_Key, _Tp, _Compare, _Allocator> >
+ : public __gnu_debug::_Safe_container<
+ map<_Key, _Tp, _Compare, _Allocator>, _Allocator,
+ __gnu_debug::_Safe_node_sequence>,
+ public _GLIBCXX_STD_C::map<_Key, _Tp, _Compare, _Allocator>
{
- typedef _GLIBCXX_STD_C::map<_Key, _Tp, _Compare, _Allocator> _Base;
+ typedef _GLIBCXX_STD_C::map<
+ _Key, _Tp, _Compare, _Allocator> _Base;
+ typedef __gnu_debug::_Safe_container<
+ map, _Allocator, __gnu_debug::_Safe_node_sequence> _Safe;
typedef typename _Base::const_iterator _Base_const_iterator;
typedef typename _Base::iterator _Base_iterator;
typedef __gnu_debug::_Equal_to<_Base_const_iterator> _Equal;
-#if __cplusplus >= 201103L
- typedef __gnu_cxx::__alloc_traits<typename
- _Base::allocator_type> _Alloc_traits;
-#endif
public:
// types:
typedef _Key key_type;
@@ -78,33 +80,18 @@
// 23.3.1.1 construct/copy/destroy:
+#if __cplusplus < 201103L
map() : _Base() { }
- explicit map(const _Compare& __comp,
- const _Allocator& __a = _Allocator())
- : _Base(__comp, __a) { }
-
- template<typename _InputIterator>
- map(_InputIterator __first, _InputIterator __last,
- const _Compare& __comp = _Compare(),
- const _Allocator& __a = _Allocator())
- : _Base(__gnu_debug::__base(__gnu_debug::__check_valid_range(__first,
- __last)),
- __gnu_debug::__base(__last),
- __comp, __a) { }
-
map(const map& __x)
: _Base(__x) { }
- map(const _Base& __x)
- : _Base(__x) { }
+ ~map() { }
+#else
+ map() = default;
+ map(const map&) = default;
+ map(map&&) = default;
-#if __cplusplus >= 201103L
- map(map&& __x)
- noexcept(is_nothrow_copy_constructible<_Compare>::value)
- : _Base(std::move(__x))
- { this->_M_swap(__x); }
-
map(initializer_list<value_type> __l,
const _Compare& __c = _Compare(),
const allocator_type& __a = allocator_type())
@@ -118,7 +105,8 @@
: _Base(__m, __a) { }
map(map&& __m, const allocator_type& __a)
- : _Base(std::move(__m._M_base()), __a) { }
+ : _Safe(std::move(__m._M_safe()), __a),
+ _Base(std::move(__m._M_base()), __a) { }
map(initializer_list<value_type> __l, const allocator_type& __a)
: _Base(__l, __a) { }
@@ -130,34 +118,40 @@
__last)),
__gnu_debug::__base(__last), __a)
{ }
+
+ ~map() = default;
#endif
- ~map() _GLIBCXX_NOEXCEPT { }
+ map(const _Base& __x)
+ : _Base(__x) { }
+ explicit map(const _Compare& __comp,
+ const _Allocator& __a = _Allocator())
+ : _Base(__comp, __a) { }
+
+ template<typename _InputIterator>
+ map(_InputIterator __first, _InputIterator __last,
+ const _Compare& __comp = _Compare(),
+ const _Allocator& __a = _Allocator())
+ : _Base(__gnu_debug::__base(__gnu_debug::__check_valid_range(__first,
+ __last)),
+ __gnu_debug::__base(__last),
+ __comp, __a) { }
+
+#if __cplusplus < 201103L
map&
operator=(const map& __x)
{
+ this->_M_safe() = __x;
_M_base() = __x;
- this->_M_invalidate_all();
return *this;
}
+#else
+ map&
+ operator=(const map&) = default;
-#if __cplusplus >= 201103L
map&
- operator=(map&& __x)
- noexcept(_Alloc_traits::_S_nothrow_move())
- {
- __glibcxx_check_self_move_assign(__x);
- bool __xfer_memory = _Alloc_traits::_S_propagate_on_move_assign()
- || __x.get_allocator() == this->get_allocator();
- _M_base() = std::move(__x._M_base());
- if (__xfer_memory)
- this->_M_swap(__x);
- else
- this->_M_invalidate_all();
- __x._M_invalidate_all();
- return *this;
- }
+ operator=(map&&) = default;
map&
operator=(initializer_list<value_type> __l)
@@ -173,7 +167,7 @@
using _Base::get_allocator;
// iterators:
- iterator
+ iterator
begin() _GLIBCXX_NOEXCEPT
{ return iterator(_Base::begin(), this); }
@@ -395,15 +389,11 @@
void
swap(map& __x)
#if __cplusplus >= 201103L
- noexcept(_Alloc_traits::_S_nothrow_swap())
+ noexcept( noexcept(declval<_Base>().swap(__x)) )
#endif
{
-#if __cplusplus >= 201103L
- if (!_Alloc_traits::_S_propagate_on_swap())
- __glibcxx_check_equal_allocs(__x);
-#endif
+ _Safe::_M_swap(__x);
_Base::swap(__x);
- this->_M_swap(__x);
}
void
@@ -467,14 +457,6 @@
const _Base&
_M_base() const _GLIBCXX_NOEXCEPT { return *this; }
-
- private:
- void
- _M_invalidate_all()
- {
- typedef __gnu_debug::_Not_equal_to<_Base_const_iterator> _Not_equal;
- this->_M_invalidate_if(_Not_equal(_M_base().end()));
- }
};
template<typename _Key, typename _Tp,
Index: include/debug/multimap.h
===================================================================
--- include/debug/multimap.h (revision 209879)
+++ include/debug/multimap.h (working copy)
@@ -30,6 +30,7 @@
#define _GLIBCXX_DEBUG_MULTIMAP_H 1
#include <debug/safe_sequence.h>
+#include <debug/safe_container.h>
#include <debug/safe_iterator.h>
#include <utility>
@@ -41,20 +42,20 @@
template<typename _Key, typename _Tp, typename _Compare = std::less<_Key>,
typename _Allocator = std::allocator<std::pair<const _Key, _Tp> > >
class multimap
- : public _GLIBCXX_STD_C::multimap<_Key, _Tp, _Compare, _Allocator>,
- public __gnu_debug::_Safe_sequence<multimap<_Key, _Tp,
- _Compare, _Allocator> >
+ : public __gnu_debug::_Safe_container<
+ multimap<_Key, _Tp, _Compare, _Allocator>, _Allocator,
+ __gnu_debug::_Safe_node_sequence>,
+ public _GLIBCXX_STD_C::multimap<_Key, _Tp, _Compare, _Allocator>
{
- typedef _GLIBCXX_STD_C::multimap<_Key, _Tp, _Compare, _Allocator> _Base;
+ typedef _GLIBCXX_STD_C::multimap<
+ _Key, _Tp, _Compare, _Allocator> _Base;
+ typedef __gnu_debug::_Safe_container<
+ multimap, _Allocator, __gnu_debug::_Safe_node_sequence> _Safe;
typedef typename _Base::const_iterator _Base_const_iterator;
typedef typename _Base::iterator _Base_iterator;
typedef __gnu_debug::_Equal_to<_Base_const_iterator> _Equal;
-#if __cplusplus >= 201103L
- typedef __gnu_cxx::__alloc_traits<typename
- _Base::allocator_type> _Alloc_traits;
-#endif
public:
// types:
typedef _Key key_type;
@@ -79,33 +80,18 @@
// 23.3.1.1 construct/copy/destroy:
+#if __cplusplus < 201103L
multimap() : _Base() { }
- explicit multimap(const _Compare& __comp,
- const _Allocator& __a = _Allocator())
- : _Base(__comp, __a) { }
-
- template<typename _InputIterator>
- multimap(_InputIterator __first, _InputIterator __last,
- const _Compare& __comp = _Compare(),
- const _Allocator& __a = _Allocator())
- : _Base(__gnu_debug::__base(__gnu_debug::__check_valid_range(__first,
- __last)),
- __gnu_debug::__base(__last),
- __comp, __a) { }
-
multimap(const multimap& __x)
: _Base(__x) { }
- multimap(const _Base& __x)
- : _Base(__x) { }
+ ~multimap() { }
+#else
+ multimap() = default;
+ multimap(const multimap&) = default;
+ multimap(multimap&&) = default;
-#if __cplusplus >= 201103L
- multimap(multimap&& __x)
- noexcept(is_nothrow_copy_constructible<_Compare>::value)
- : _Base(std::move(__x))
- { this->_M_swap(__x); }
-
multimap(initializer_list<value_type> __l,
const _Compare& __c = _Compare(),
const allocator_type& __a = allocator_type())
@@ -119,47 +105,52 @@
: _Base(__m, __a) { }
multimap(multimap&& __m, const allocator_type& __a)
- : _Base(std::move(__m._M_base()), __a) { }
+ : _Safe(std::move(__m._M_safe()), __a),
+ _Base(std::move(__m._M_base()), __a) { }
multimap(initializer_list<value_type> __l, const allocator_type& __a)
- : _Base(__l, __a)
- { }
+ : _Base(__l, __a) { }
template<typename _InputIterator>
multimap(_InputIterator __first, _InputIterator __last,
const allocator_type& __a)
: _Base(__gnu_debug::__base(__gnu_debug::__check_valid_range(__first,
__last)),
- __gnu_debug::__base(__last), __a)
- { }
+ __gnu_debug::__base(__last), __a) { }
+
+ ~multimap() = default;
#endif
- ~multimap() _GLIBCXX_NOEXCEPT { }
+ explicit multimap(const _Compare& __comp,
+ const _Allocator& __a = _Allocator())
+ : _Base(__comp, __a) { }
+ template<typename _InputIterator>
+ multimap(_InputIterator __first, _InputIterator __last,
+ const _Compare& __comp = _Compare(),
+ const _Allocator& __a = _Allocator())
+ : _Base(__gnu_debug::__base(__gnu_debug::__check_valid_range(__first,
+ __last)),
+ __gnu_debug::__base(__last),
+ __comp, __a) { }
+
+ multimap(const _Base& __x)
+ : _Base(__x) { }
+
+#if __cplusplus < 201103L
multimap&
operator=(const multimap& __x)
{
+ this->_M_safe() = __x;
_M_base() = __x;
- this->_M_invalidate_all();
return *this;
}
+#else
+ multimap&
+ operator=(const multimap&) = default;
-#if __cplusplus >= 201103L
multimap&
- operator=(multimap&& __x)
- noexcept(_Alloc_traits::_S_nothrow_move())
- {
- __glibcxx_check_self_move_assign(__x);
- bool __xfer_memory = _Alloc_traits::_S_propagate_on_move_assign()
- || __x.get_allocator() == this->get_allocator();
- _M_base() = std::move(__x._M_base());
- if (__xfer_memory)
- this->_M_swap(__x);
- else
- this->_M_invalidate_all();
- __x._M_invalidate_all();
- return *this;
- }
+ operator=(multimap&&) = default;
multimap&
operator=(initializer_list<value_type> __l)
@@ -247,7 +238,7 @@
this);
}
#endif
-
+
iterator
insert(const value_type& __x)
{ return iterator(_Base::insert(__x), this); }
@@ -379,15 +370,11 @@
void
swap(multimap& __x)
#if __cplusplus >= 201103L
- noexcept(_Alloc_traits::_S_nothrow_swap())
+ noexcept( noexcept(declval<_Base>().swap(__x)) )
#endif
{
-#if __cplusplus >= 201103L
- if (!_Alloc_traits::_S_propagate_on_swap())
- __glibcxx_check_equal_allocs(__x);
-#endif
+ _Safe::_M_swap(__x);
_Base::swap(__x);
- this->_M_swap(__x);
}
void
@@ -451,14 +438,6 @@
const _Base&
_M_base() const _GLIBCXX_NOEXCEPT { return *this; }
-
- private:
- void
- _M_invalidate_all()
- {
- typedef __gnu_debug::_Not_equal_to<_Base_const_iterator> _Not_equal;
- this->_M_invalidate_if(_Not_equal(_Base::end()));
- }
};
template<typename _Key, typename _Tp,
Index: include/debug/multiset.h
===================================================================
--- include/debug/multiset.h (revision 209879)
+++ include/debug/multiset.h (working copy)
@@ -30,6 +30,7 @@
#define _GLIBCXX_DEBUG_MULTISET_H 1
#include <debug/safe_sequence.h>
+#include <debug/safe_container.h>
#include <debug/safe_iterator.h>
#include <utility>
@@ -41,19 +42,19 @@
template<typename _Key, typename _Compare = std::less<_Key>,
typename _Allocator = std::allocator<_Key> >
class multiset
- : public _GLIBCXX_STD_C::multiset<_Key, _Compare, _Allocator>,
- public __gnu_debug::_Safe_sequence<multiset<_Key, _Compare, _Allocator> >
+ : public __gnu_debug::_Safe_container<
+ multiset<_Key, _Compare, _Allocator>, _Allocator,
+ __gnu_debug::_Safe_node_sequence>,
+ public _GLIBCXX_STD_C::multiset<_Key, _Compare, _Allocator>
{
typedef _GLIBCXX_STD_C::multiset<_Key, _Compare, _Allocator> _Base;
+ typedef __gnu_debug::_Safe_container<
+ multiset, _Allocator, __gnu_debug::_Safe_node_sequence> _Safe;
typedef typename _Base::const_iterator _Base_const_iterator;
typedef typename _Base::iterator _Base_iterator;
typedef __gnu_debug::_Equal_to<_Base_const_iterator> _Equal;
-#if __cplusplus >= 201103L
- typedef __gnu_cxx::__alloc_traits<typename
- _Base::allocator_type> _Alloc_traits;
-#endif
public:
// types:
typedef _Key key_type;
@@ -78,33 +79,18 @@
// 23.3.3.1 construct/copy/destroy:
+#if __cplusplus < 201103L
multiset() : _Base() { }
- explicit multiset(const _Compare& __comp,
- const _Allocator& __a = _Allocator())
- : _Base(__comp, __a) { }
-
- template<typename _InputIterator>
- multiset(_InputIterator __first, _InputIterator __last,
- const _Compare& __comp = _Compare(),
- const _Allocator& __a = _Allocator())
- : _Base(__gnu_debug::__base(__gnu_debug::__check_valid_range(__first,
- __last)),
- __gnu_debug::__base(__last),
- __comp, __a) { }
-
multiset(const multiset& __x)
: _Base(__x) { }
- multiset(const _Base& __x)
- : _Base(__x) { }
+ ~multiset() { }
+#else
+ multiset() = default;
+ multiset(const multiset&) = default;
+ multiset(multiset&&) = default;
-#if __cplusplus >= 201103L
- multiset(multiset&& __x)
- noexcept(is_nothrow_copy_constructible<_Compare>::value)
- : _Base(std::move(__x))
- { this->_M_swap(__x); }
-
multiset(initializer_list<value_type> __l,
const _Compare& __comp = _Compare(),
const allocator_type& __a = allocator_type())
@@ -118,7 +104,8 @@
: _Base(__m, __a) { }
multiset(multiset&& __m, const allocator_type& __a)
- : _Base(std::move(__m._M_base()), __a) { }
+ : _Safe(std::move(__m._M_safe()), __a),
+ _Base(std::move(__m._M_base()), __a) { }
multiset(initializer_list<value_type> __l, const allocator_type& __a)
: _Base(__l, __a)
@@ -129,36 +116,41 @@
const allocator_type& __a)
: _Base(__gnu_debug::__base(__gnu_debug::__check_valid_range(__first,
__last)),
- __gnu_debug::__base(__last), __a)
- { }
+ __gnu_debug::__base(__last), __a) { }
+
+ ~multiset() = default;
#endif
- ~multiset() _GLIBCXX_NOEXCEPT { }
+ explicit multiset(const _Compare& __comp,
+ const _Allocator& __a = _Allocator())
+ : _Base(__comp, __a) { }
+ template<typename _InputIterator>
+ multiset(_InputIterator __first, _InputIterator __last,
+ const _Compare& __comp = _Compare(),
+ const _Allocator& __a = _Allocator())
+ : _Base(__gnu_debug::__base(__gnu_debug::__check_valid_range(__first,
+ __last)),
+ __gnu_debug::__base(__last),
+ __comp, __a) { }
+
+ multiset(const _Base& __x)
+ : _Base(__x) { }
+
+#if __cplusplus < 201103L
multiset&
operator=(const multiset& __x)
{
+ this->_M_safe() = __x;
_M_base() = __x;
- this->_M_invalidate_all();
return *this;
}
+#else
+ multiset&
+ operator=(const multiset&) = default;
-#if __cplusplus >= 201103L
multiset&
- operator=(multiset&& __x)
- noexcept(_Alloc_traits::_S_nothrow_move())
- {
- __glibcxx_check_self_move_assign(__x);
- bool __xfer_memory = _Alloc_traits::_S_propagate_on_move_assign()
- || __x.get_allocator() == this->get_allocator();
- _M_base() = std::move(__x._M_base());
- if (__xfer_memory)
- this->_M_swap(__x);
- else
- this->_M_invalidate_all();
- __x._M_invalidate_all();
- return *this;
- }
+ operator=(multiset&&) = default;
multiset&
operator=(initializer_list<value_type> __l)
@@ -233,7 +225,8 @@
iterator
emplace(_Args&&... __args)
{
- return iterator(_Base::emplace(std::forward<_Args>(__args)...), this);
+ return iterator(_Base::emplace(std::forward<_Args>(__args)...),
+ this);
}
template<typename... _Args>
@@ -364,15 +357,11 @@
void
swap(multiset& __x)
#if __cplusplus >= 201103L
- noexcept(_Alloc_traits::_S_nothrow_swap())
+ noexcept( noexcept(declval<_Base>().swap(__x)) )
#endif
{
-#if __cplusplus >= 201103L
- if (!_Alloc_traits::_S_propagate_on_swap())
- __glibcxx_check_equal_allocs(__x);
-#endif
+ _Safe::_M_swap(__x);
_Base::swap(__x);
- this->_M_swap(__x);
}
void
@@ -444,14 +433,6 @@
const _Base&
_M_base() const _GLIBCXX_NOEXCEPT { return *this; }
-
- private:
- void
- _M_invalidate_all()
- {
- typedef __gnu_debug::_Not_equal_to<_Base_const_iterator> _Not_equal;
- this->_M_invalidate_if(_Not_equal(_Base::end()));
- }
};
template<typename _Key, typename _Compare, typename _Allocator>
Index: include/debug/safe_base.h
===================================================================
--- include/debug/safe_base.h (revision 209879)
+++ include/debug/safe_base.h (working copy)
@@ -104,7 +104,8 @@
~_Safe_iterator_base() { this->_M_detach(); }
/** For use in _Safe_iterator. */
- __gnu_cxx::__mutex& _M_get_mutex() throw ();
+ __gnu_cxx::__mutex&
+ _M_get_mutex() throw ();
public:
/** Attaches this iterator to the given sequence, detaching it
@@ -112,30 +113,37 @@
* new sequence is the NULL pointer, the iterator is left
* unattached.
*/
- void _M_attach(_Safe_sequence_base* __seq, bool __constant);
+ void
+ _M_attach(_Safe_sequence_base* __seq, bool __constant);
/** Likewise, but not thread-safe. */
- void _M_attach_single(_Safe_sequence_base* __seq, bool __constant) throw ();
+ void
+ _M_attach_single(_Safe_sequence_base* __seq, bool __constant) throw ();
/** Detach the iterator for whatever sequence it is attached to,
* if any.
*/
- void _M_detach();
+ void
+ _M_detach();
/** Likewise, but not thread-safe. */
- void _M_detach_single() throw ();
+ void
+ _M_detach_single() throw ();
/** Determines if we are attached to the given sequence. */
- bool _M_attached_to(const _Safe_sequence_base* __seq) const
+ bool
+ _M_attached_to(const _Safe_sequence_base* __seq) const
{ return _M_sequence == __seq; }
/** Is this iterator singular? */
- _GLIBCXX_PURE bool _M_singular() const throw ();
+ _GLIBCXX_PURE bool
+ _M_singular() const throw ();
/** Can we compare this iterator to the given iterator @p __x?
Returns true if both iterators are nonsingular and reference
the same sequence. */
- _GLIBCXX_PURE bool _M_can_compare(const _Safe_iterator_base& __x) const throw ();
+ _GLIBCXX_PURE bool
+ _M_can_compare(const _Safe_iterator_base& __x) const throw ();
/** Invalidate the iterator, making it singular. */
void
@@ -188,17 +196,13 @@
protected:
// Initialize with a version number of 1 and no iterators
- _Safe_sequence_base()
+ _Safe_sequence_base() _GLIBCXX_NOEXCEPT
: _M_iterators(0), _M_const_iterators(0), _M_version(1)
{ }
#if __cplusplus >= 201103L
_Safe_sequence_base(const _Safe_sequence_base&) noexcept
: _Safe_sequence_base() { }
-
- _Safe_sequence_base(_Safe_sequence_base&& __x) noexcept
- : _Safe_sequence_base()
- { _M_swap(__x); }
#endif
/** Notify all iterators that reference this sequence that the
@@ -231,10 +235,11 @@
* one container now reference the other container.
*/
void
- _M_swap(_Safe_sequence_base& __x);
+ _M_swap(_Safe_sequence_base& __x) _GLIBCXX_USE_NOEXCEPT;
/** For use in _Safe_sequence. */
- __gnu_cxx::__mutex& _M_get_mutex() throw ();
+ __gnu_cxx::__mutex&
+ _M_get_mutex() throw ();
public:
/** Invalidates all iterators. */
Index: include/debug/safe_container.h
===================================================================
--- include/debug/safe_container.h (revision 0)
+++ include/debug/safe_container.h (working copy)
@@ -0,0 +1,125 @@
+// Safe container implementation -*- C++ -*-
+
+// Copyright (C) 2014 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.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+// <http://www.gnu.org/licenses/>.
+
+/** @file debug/safe_container.h
+ * This file is a GNU debug extension to the Standard C++ Library.
+ */
+
+#ifndef _GLIBCXX_DEBUG_SAFE_CONTAINER_H
+#define _GLIBCXX_DEBUG_SAFE_CONTAINER_H 1
+
+#include <ext/alloc_traits.h>
+
+namespace __gnu_debug
+{
+ /// Safe class dealing with some allocator dependent operations.
+ template<typename _SafeContainer,
+ typename _Alloc,
+ template<typename> class _SafeBase,
+ bool _IsCxx11AllocatorAware = true>
+ class _Safe_container
+ : public _SafeBase<_SafeContainer>
+ {
+ typedef _SafeBase<_SafeContainer> _Base;
+
+ _SafeContainer&
+ _M_cont() _GLIBCXX_NOEXCEPT
+ { return *static_cast<_SafeContainer*>(this); }
+
+ protected:
+ _Safe_container&
+ _M_safe() _GLIBCXX_NOEXCEPT
+ { return *this; }
+
+#if __cplusplus >= 201103L
+ _Safe_container() = default;
+ _Safe_container(const _Safe_container&) = default;
+ _Safe_container(_Safe_container&& __x) noexcept
+ : _Safe_container()
+ { _Base::_M_swap(__x); }
+
+ _Safe_container(_Safe_container&& __x,
+ const _Alloc& __a)
+ : _Safe_container()
+ {
+ if (__x._M_cont().get_allocator() == __a)
+ _Base::_M_swap(__x);
+ else
+ __x._M_invalidate_all();
+ }
+#endif
+
+ public:
+ // Copy assignment invalidate all iterators.
+ _Safe_container&
+ operator=(const _Safe_container&) _GLIBCXX_NOEXCEPT
+ {
+ this->_M_invalidate_all();
+ return *this;
+ }
+
+#if __cplusplus >= 201103L
+ _Safe_container&
+ operator=(_Safe_container&& __x) noexcept
+ {
+ __glibcxx_check_self_move_assign(__x);
+
+ if (_IsCxx11AllocatorAware)
+ {
+ typedef __gnu_cxx::__alloc_traits<_Alloc> _Alloc_traits;
+
+ bool __xfer_memory = _Alloc_traits::_S_propagate_on_move_assign()
+ || _M_cont().get_allocator() == __x._M_cont().get_allocator();
+ if (__xfer_memory)
+ _Base::_M_swap(__x);
+ else
+ this->_M_invalidate_all();
+ }
+ else
+ _Base::_M_swap(__x);
+
+ __x._M_invalidate_all();
+ return *this;
+ }
+
+ void
+ _M_swap(_Safe_container& __x) noexcept
+ {
+ if (_IsCxx11AllocatorAware)
+ {
+ typedef __gnu_cxx::__alloc_traits<_Alloc> _Alloc_traits;
+
+ if (!_Alloc_traits::_S_propagate_on_swap())
+ __glibcxx_check_equal_allocs(this->_M_cont()._M_base(),
+ __x._M_cont()._M_base());
+ }
+
+ _Base::_M_swap(__x);
+ }
+#endif
+ };
+
+} // namespace __gnu_debug
+
+#endif
Index: include/debug/safe_iterator.h
===================================================================
--- include/debug/safe_iterator.h (revision 209879)
+++ include/debug/safe_iterator.h (working copy)
@@ -58,7 +58,7 @@
/** Iterators that derive from _Safe_iterator_base can be determined singular
* or non-singular.
**/
- inline bool
+ inline bool
__check_singular_aux(const _Safe_iterator_base* __x)
{ return __x->_M_singular(); }
Index: include/debug/safe_sequence.h
===================================================================
--- include/debug/safe_sequence.h (revision 209879)
+++ include/debug/safe_sequence.h (working copy)
@@ -127,6 +127,25 @@
void
_M_transfer_from_if(_Safe_sequence& __from, _Predicate __pred);
};
+
+ /// Like _Safe_sequence but with a special _M_invalidate_all implementation
+ /// not invalidating past-the-end iterators. Used by node based sequence.
+ template<typename _Sequence>
+ class _Safe_node_sequence
+ : public _Safe_sequence<_Sequence>
+ {
+ protected:
+ void
+ _M_invalidate_all()
+ {
+ typedef typename _Sequence::const_iterator _Const_iterator;
+ typedef typename _Const_iterator::iterator_type _Base_const_iterator;
+ typedef __gnu_debug::_Not_equal_to<_Base_const_iterator> _Not_equal;
+ const _Sequence& __seq = *static_cast<_Sequence*>(this);
+ this->_M_invalidate_if(_Not_equal(__seq._M_base().end()));
+ }
+ };
+
} // namespace __gnu_debug
#include <debug/safe_sequence.tcc>
Index: include/debug/safe_unordered_base.h
===================================================================
--- include/debug/safe_unordered_base.h (revision 209879)
+++ include/debug/safe_unordered_base.h (working copy)
@@ -80,7 +80,7 @@
~_Safe_local_iterator_base() { this->_M_detach(); }
_Safe_unordered_container_base*
- _M_get_container() const _GLIBCXX_NOEXCEPT;
+ _M_get_container() const noexcept;
public:
/** Attaches this iterator to the given container, detaching it
@@ -132,15 +132,16 @@
protected:
// Initialize with a version number of 1 and no iterators
- _Safe_unordered_container_base()
+ _Safe_unordered_container_base() noexcept
: _M_local_iterators(nullptr), _M_const_local_iterators(nullptr)
{ }
- // Initialize with a version number of 1 and no iterators
+ // Copy constructor does not copy iterators.
_Safe_unordered_container_base(const _Safe_unordered_container_base&)
noexcept
: _Safe_unordered_container_base() { }
+ // When moved unordered containers iterators are swapped.
_Safe_unordered_container_base(_Safe_unordered_container_base&& __x)
noexcept
: _Safe_unordered_container_base()
@@ -148,7 +149,7 @@
/** Notify all iterators that reference this container that the
container is being destroyed. */
- ~_Safe_unordered_container_base()
+ ~_Safe_unordered_container_base() noexcept
{ this->_M_detach_all(); }
/** Detach all iterators, leaving them singular. */
@@ -161,7 +162,7 @@
* one container now reference the other container.
*/
void
- _M_swap(_Safe_unordered_container_base& __x);
+ _M_swap(_Safe_unordered_container_base& __x) noexcept;
public:
/** Attach an iterator to this container. */
Index: include/debug/safe_unordered_container.h
===================================================================
--- include/debug/safe_unordered_container.h (revision 209879)
+++ include/debug/safe_unordered_container.h (working copy)
@@ -57,7 +57,31 @@
template<typename _Container>
class _Safe_unordered_container : public _Safe_unordered_container_base
{
- public:
+ private:
+ _Container&
+ _M_cont() noexcept
+ { return *static_cast<_Container*>(this); }
+
+ protected:
+ void
+ _M_invalidate_locals()
+ {
+ auto __local_end = _M_cont()._M_base().end(0);
+ this->_M_invalidate_local_if(
+ [__local_end](__decltype(_M_cont()._M_base().cend(0)) __it)
+ { return __it != __local_end; });
+ }
+
+ void
+ _M_invalidate_all()
+ {
+ auto __end = _M_cont()._M_base().end();
+ this->_M_invalidate_if(
+ [__end](__decltype(_M_cont()._M_base().cend()) __it)
+ { return __it != __end; });
+ _M_invalidate_locals();
+ }
+
/** Invalidates all iterators @c x that reference this container,
are not singular, and for which @c __pred(x) returns @c
true. @c __pred will be invoked with the normal iterators nested
Index: include/debug/set.h
===================================================================
--- include/debug/set.h (revision 209879)
+++ include/debug/set.h (working copy)
@@ -30,10 +30,11 @@
#define _GLIBCXX_DEBUG_SET_H 1
#include <debug/safe_sequence.h>
+#include <debug/safe_container.h>
#include <debug/safe_iterator.h>
#include <utility>
-namespace std _GLIBCXX_VISIBILITY(default)
+namespace std _GLIBCXX_VISIBILITY(default)
{
namespace __debug
{
@@ -41,18 +42,19 @@
template<typename _Key, typename _Compare = std::less<_Key>,
typename _Allocator = std::allocator<_Key> >
class set
- : public _GLIBCXX_STD_C::set<_Key,_Compare,_Allocator>,
- public __gnu_debug::_Safe_sequence<set<_Key, _Compare, _Allocator> >
+ : public __gnu_debug::_Safe_container<
+ set<_Key, _Compare, _Allocator>, _Allocator,
+ __gnu_debug::_Safe_node_sequence>,
+ public _GLIBCXX_STD_C::set<_Key,_Compare,_Allocator>
{
typedef _GLIBCXX_STD_C::set<_Key, _Compare, _Allocator> _Base;
+ typedef __gnu_debug::_Safe_container<
+ set, _Allocator, __gnu_debug::_Safe_node_sequence> _Safe;
typedef typename _Base::const_iterator _Base_const_iterator;
typedef typename _Base::iterator _Base_iterator;
typedef __gnu_debug::_Equal_to<_Base_const_iterator> _Equal;
-#if __cplusplus >= 201103L
- typedef __gnu_cxx::__alloc_traits<typename
- _Base::allocator_type> _Alloc_traits;
-#endif
+
public:
// types:
typedef _Key key_type;
@@ -77,33 +79,18 @@
// 23.3.3.1 construct/copy/destroy:
+#if __cplusplus < 201103L
set() : _Base() { }
- explicit set(const _Compare& __comp,
- const _Allocator& __a = _Allocator())
- : _Base(__comp, __a) { }
-
- template<typename _InputIterator>
- set(_InputIterator __first, _InputIterator __last,
- const _Compare& __comp = _Compare(),
- const _Allocator& __a = _Allocator())
- : _Base(__gnu_debug::__base(__gnu_debug::__check_valid_range(__first,
- __last)),
- __gnu_debug::__base(__last),
- __comp, __a) { }
-
set(const set& __x)
: _Base(__x) { }
- set(const _Base& __x)
- : _Base(__x) { }
+ ~set() { }
+#else
+ set() = default;
+ set(const set&) = default;
+ set(set&&) = default;
-#if __cplusplus >= 201103L
- set(set&& __x)
- noexcept(is_nothrow_copy_constructible<_Compare>::value)
- : _Base(std::move(__x))
- { this->_M_swap(__x); }
-
set(initializer_list<value_type> __l,
const _Compare& __comp = _Compare(),
const allocator_type& __a = allocator_type())
@@ -117,47 +104,52 @@
: _Base(__x, __a) { }
set(set&& __x, const allocator_type& __a)
- : _Base(std::move(__x._M_base()), __a) { }
+ : _Safe(std::move(__x._M_safe()), __a),
+ _Base(std::move(__x._M_base()), __a) { }
set(initializer_list<value_type> __l, const allocator_type& __a)
- : _Base(__l, __a)
- { }
+ : _Base(__l, __a) { }
template<typename _InputIterator>
set(_InputIterator __first, _InputIterator __last,
const allocator_type& __a)
: _Base(__gnu_debug::__base(__gnu_debug::__check_valid_range(__first,
__last)),
- __gnu_debug::__base(__last), __a)
- { }
+ __gnu_debug::__base(__last), __a) { }
+
+ ~set() = default;
#endif
- ~set() _GLIBCXX_NOEXCEPT { }
+ explicit set(const _Compare& __comp,
+ const _Allocator& __a = _Allocator())
+ : _Base(__comp, __a) { }
+ template<typename _InputIterator>
+ set(_InputIterator __first, _InputIterator __last,
+ const _Compare& __comp = _Compare(),
+ const _Allocator& __a = _Allocator())
+ : _Base(__gnu_debug::__base(__gnu_debug::__check_valid_range(__first,
+ __last)),
+ __gnu_debug::__base(__last),
+ __comp, __a) { }
+
+ set(const _Base& __x)
+ : _Base(__x) { }
+
+#if __cplusplus < 201103L
set&
operator=(const set& __x)
{
+ this->_M_safe() = __x;
_M_base() = __x;
- this->_M_invalidate_all();
return *this;
}
+#else
+ set&
+ operator=(const set&) = default;
-#if __cplusplus >= 201103L
set&
- operator=(set&& __x)
- noexcept(_Alloc_traits::_S_nothrow_move())
- {
- __glibcxx_check_self_move_assign(__x);
- bool __xfer_memory = _Alloc_traits::_S_propagate_on_move_assign()
- || __x.get_allocator() == this->get_allocator();
- _M_base() = std::move(__x._M_base());
- if (__xfer_memory)
- this->_M_swap(__x);
- else
- this->_M_invalidate_all();
- __x._M_invalidate_all();
- return *this;
- }
+ operator=(set&&) = default;
set&
operator=(initializer_list<value_type> __l)
@@ -372,15 +364,11 @@
void
swap(set& __x)
#if __cplusplus >= 201103L
- noexcept(_Alloc_traits::_S_nothrow_swap())
+ noexcept( noexcept(declval<_Base>().swap(__x)) )
#endif
{
-#if __cplusplus >= 201103L
- if (!_Alloc_traits::_S_propagate_on_swap())
- __glibcxx_check_equal_allocs(__x);
-#endif
+ _Safe::_M_swap(__x);
_Base::swap(__x);
- this->_M_swap(__x);
}
void
@@ -452,14 +440,6 @@
const _Base&
_M_base() const _GLIBCXX_NOEXCEPT { return *this; }
-
- private:
- void
- _M_invalidate_all()
- {
- typedef __gnu_debug::_Not_equal_to<_Base_const_iterator> _Not_equal;
- this->_M_invalidate_if(_Not_equal(_M_base().end()));
- }
};
template<typename _Key, typename _Compare, typename _Allocator>
Index: include/debug/string
===================================================================
--- include/debug/string (revision 209879)
+++ include/debug/string (working copy)
@@ -31,6 +31,7 @@
#include <string>
#include <debug/safe_sequence.h>
+#include <debug/safe_container.h>
#include <debug/safe_iterator.h>
namespace __gnu_debug
@@ -39,12 +40,14 @@
template<typename _CharT, typename _Traits = std::char_traits<_CharT>,
typename _Allocator = std::allocator<_CharT> >
class basic_string
+ : public __gnu_debug::_Safe_container<
+ basic_string<_CharT, _Traits, _Allocator>, _Allocator,
+ _Safe_sequence, false>
: public std::basic_string<_CharT, _Traits, _Allocator>,
- public __gnu_debug::_Safe_sequence<basic_string<_CharT, _Traits,
- _Allocator> >
{
typedef std::basic_string<_CharT, _Traits, _Allocator> _Base;
- typedef __gnu_debug::_Safe_sequence<basic_string> _Safe_base;
+ typedef __gnu_debug::_Safe_container<
+ basic_string, _Allocator, _Safe_sequence, false> _Safe;
public:
// types:
@@ -58,10 +61,10 @@
typedef typename _Base::pointer pointer;
typedef typename _Base::const_pointer const_pointer;
- typedef __gnu_debug::_Safe_iterator<typename _Base::iterator, basic_string>
- iterator;
- typedef __gnu_debug::_Safe_iterator<typename _Base::const_iterator,
- basic_string> const_iterator;
+ typedef __gnu_debug::_Safe_iterator<
+ typename _Base::iterator, basic_string> iterator;
+ typedef __gnu_debug::_Safe_iterator<
+ typename _Base::const_iterator, basic_string> const_iterator;
typedef std::reverse_iterator<iterator> reverse_iterator;
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
@@ -71,18 +74,29 @@
// 21.3.1 construct/copy/destroy:
explicit basic_string(const _Allocator& __a = _Allocator())
// _GLIBCXX_NOEXCEPT
- : _Base(__a)
- { }
+ : _Base(__a) { }
- // Provides conversion from a release-mode string to a debug-mode string
- basic_string(const _Base& __base) : _Base(__base) { }
+#if __cplusplus < 201103L
+ basic_string(const basic_string& __str)
+ : _Base(__str) { }
- // _GLIBCXX_RESOLVE_LIB_DEFECTS
- // 42. string ctors specify wrong default allocator
- basic_string(const basic_string& __str)
- : _Base(__str, 0, _Base::npos, __str.get_allocator())
+ ~basic_string() { }
+#else
+ basic_string(const basic_string&) = default;
+ basic_string(basic_string&&) = default;
+
+ basic_string(std::initializer_list<_CharT> __l,
+ const _Allocator& __a = _Allocator())
+ : _Base(__l, __a)
{ }
+ ~basic_string() = default;
+#endif // C++11
+
+ // Provides conversion from a normal-mode string to a debug-mode string
+ basic_string(const _Base& __base)
+ : _Base(__base) { }
+
// _GLIBCXX_RESOLVE_LIB_DEFECTS
// 42. string ctors specify wrong default allocator
basic_string(const basic_string& __str, size_type __pos,
@@ -113,32 +127,27 @@
__gnu_debug::__base(__end), __a)
{ }
-#if __cplusplus >= 201103L
- basic_string(basic_string&& __str) // noexcept
- : _Base(std::move(__str))
- { }
-
- basic_string(std::initializer_list<_CharT> __l,
- const _Allocator& __a = _Allocator())
- : _Base(__l, __a)
- { }
-#endif // C++11
-
- ~basic_string() _GLIBCXX_NOEXCEPT { }
-
+#if __cplusplus < 201103L
basic_string&
operator=(const basic_string& __str)
{
- *static_cast<_Base*>(this) = __str;
- this->_M_invalidate_all();
+ this->_M_safe() = __str;
+ _M_base() = __str;
return *this;
}
+#else
+ basic_string&
+ operator=(const basic_string&) = default;
basic_string&
+ operator=(basic_string&&) = default;
+#endif
+
+ basic_string&
operator=(const _CharT* __s)
{
__glibcxx_check_string(__s);
- *static_cast<_Base*>(this) = __s;
+ _M_base() = __s;
this->_M_invalidate_all();
return *this;
}
@@ -146,25 +155,16 @@
basic_string&
operator=(_CharT __c)
{
- *static_cast<_Base*>(this) = __c;
+ _M_base() = __c;
this->_M_invalidate_all();
return *this;
}
#if __cplusplus >= 201103L
basic_string&
- operator=(basic_string&& __str)
- {
- __glibcxx_check_self_move_assign(__str);
- *static_cast<_Base*>(this) = std::move(__str);
- this->_M_invalidate_all();
- return *this;
- }
-
- basic_string&
operator=(std::initializer_list<_CharT> __l)
{
- *static_cast<_Base*>(this) = __l;
+ _M_base() = __l;
this->_M_invalidate_all();
return *this;
}
@@ -704,12 +704,13 @@
}
void
- swap(basic_string<_CharT,_Traits,_Allocator>& __x)
+ swap(basic_string& __x)
+#if __cplusplus >= 201103L
+ noexcept( noexcept(declval<_Base>().swap(__x)) )
+#endif
{
+ _Safe::_M_swap(__x);
_Base::swap(__x);
- this->_M_swap(__x);
- this->_M_invalidate_all();
- __x._M_invalidate_all();
}
// 21.3.6 string operations:
@@ -801,7 +802,7 @@
{ return _Base::find_first_of(__c, __pos); }
size_type
- find_last_of(const basic_string& __str,
+ find_last_of(const basic_string& __str,
size_type __pos = _Base::npos) const _GLIBCXX_NOEXCEPT
{ return _Base::find_last_of(__str, __pos); }
@@ -922,7 +923,7 @@
const _Base&
_M_base() const _GLIBCXX_NOEXCEPT { return *this; }
- using _Safe_base::_M_invalidate_all;
+ using _Safe::_M_invalidate_all;
};
template<typename _CharT, typename _Traits, typename _Allocator>
Index: include/debug/unordered_map
===================================================================
--- include/debug/unordered_map (revision 209879)
+++ include/debug/unordered_map (working copy)
@@ -35,6 +35,7 @@
# include <unordered_map>
#include <debug/safe_unordered_container.h>
+#include <debug/safe_container.h>
#include <debug/safe_iterator.h>
#include <debug/safe_local_iterator.h>
@@ -48,21 +49,21 @@
typename _Pred = std::equal_to<_Key>,
typename _Alloc = std::allocator<std::pair<const _Key, _Tp> > >
class unordered_map
- : public _GLIBCXX_STD_C::unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>,
- public __gnu_debug::_Safe_unordered_container<unordered_map<_Key, _Tp,
- _Hash, _Pred, _Alloc> >
+ : public __gnu_debug::_Safe_container<
+ unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>, _Alloc,
+ __gnu_debug::_Safe_unordered_container>,
+ public _GLIBCXX_STD_C::unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>
{
typedef _GLIBCXX_STD_C::unordered_map<_Key, _Tp, _Hash,
_Pred, _Alloc> _Base;
- typedef __gnu_debug::_Safe_unordered_container<unordered_map> _Safe_base;
+ typedef __gnu_debug::_Safe_container<unordered_map,
+ _Alloc, __gnu_debug::_Safe_unordered_container> _Safe;
typedef typename _Base::const_iterator _Base_const_iterator;
typedef typename _Base::iterator _Base_iterator;
- typedef typename _Base::const_local_iterator _Base_const_local_iterator;
+ typedef typename _Base::const_local_iterator
+ _Base_const_local_iterator;
typedef typename _Base::local_iterator _Base_local_iterator;
- typedef __gnu_cxx::__alloc_traits<typename
- _Base::allocator_type> _Alloc_traits;
-
public:
typedef typename _Base::size_type size_type;
typedef typename _Base::hasher hasher;
@@ -72,14 +73,14 @@
typedef typename _Base::key_type key_type;
typedef typename _Base::value_type value_type;
- typedef __gnu_debug::_Safe_iterator<_Base_iterator,
- unordered_map> iterator;
- typedef __gnu_debug::_Safe_iterator<_Base_const_iterator,
- unordered_map> const_iterator;
- typedef __gnu_debug::_Safe_local_iterator<_Base_local_iterator,
- unordered_map> local_iterator;
- typedef __gnu_debug::_Safe_local_iterator<_Base_const_local_iterator,
- unordered_map> const_local_iterator;
+ typedef __gnu_debug::_Safe_iterator<
+ _Base_iterator, unordered_map> iterator;
+ typedef __gnu_debug::_Safe_iterator<
+ _Base_const_iterator, unordered_map> const_iterator;
+ typedef __gnu_debug::_Safe_local_iterator<
+ _Base_local_iterator, unordered_map> local_iterator;
+ typedef __gnu_debug::_Safe_local_iterator<
+ _Base_const_local_iterator, unordered_map> const_local_iterator;
explicit
unordered_map(size_type __n = 10,
@@ -89,10 +90,10 @@
: _Base(__n, __hf, __eql, __a) { }
template<typename _InputIterator>
- unordered_map(_InputIterator __first, _InputIterator __last,
+ unordered_map(_InputIterator __first, _InputIterator __last,
size_type __n = 0,
- const hasher& __hf = hasher(),
- const key_equal& __eql = key_equal(),
+ const hasher& __hf = hasher(),
+ const key_equal& __eql = key_equal(),
const allocator_type& __a = allocator_type())
: _Base(__gnu_debug::__base(__gnu_debug::__check_valid_range(__first,
__last)),
@@ -108,18 +109,16 @@
explicit
unordered_map(const allocator_type& __a)
- : _Base(__a)
- { }
+ : _Base(__a) { }
unordered_map(const unordered_map& __umap,
const allocator_type& __a)
- : _Base(__umap._M_base(), __a)
- { }
+ : _Base(__umap, __a) { }
unordered_map(unordered_map&& __umap,
const allocator_type& __a)
- : _Base(std::move(__umap._M_base()), __a)
- { }
+ : _Safe(std::move(__umap._M_safe()), __a),
+ _Base(std::move(__umap._M_base()), __a) { }
unordered_map(initializer_list<value_type> __l,
size_type __n = 0,
@@ -128,31 +127,13 @@
const allocator_type& __a = allocator_type())
: _Base(__l, __n, __hf, __eql, __a) { }
- ~unordered_map() noexcept { }
+ ~unordered_map() = default;
unordered_map&
- operator=(const unordered_map& __x)
- {
- _M_base() = __x._M_base();
- this->_M_invalidate_all();
- return *this;
- }
+ operator=(const unordered_map&) = default;
unordered_map&
- operator=(unordered_map&& __x)
- noexcept(_Alloc_traits::_S_nothrow_move())
- {
- __glibcxx_check_self_move_assign(__x);
- bool __xfer_memory = _Alloc_traits::_S_propagate_on_move_assign()
- || __x.get_allocator() == this->get_allocator();
- _M_base() = std::move(__x._M_base());
- if (__xfer_memory)
- this->_M_swap(__x);
- else
- this->_M_invalidate_all();
- __x._M_invalidate_all();
- return *this;
- }
+ operator=(unordered_map&&) = default;
unordered_map&
operator=(initializer_list<value_type> __l)
@@ -164,12 +145,10 @@
void
swap(unordered_map& __x)
- noexcept(_Alloc_traits::_S_nothrow_swap())
+ noexcept( noexcept(declval<_Base>().swap(__x)) )
{
- if (!_Alloc_traits::_S_propagate_on_swap())
- __glibcxx_check_equal_allocs(__x);
+ _Safe::_M_swap(__x);
_Base::swap(__x);
- _Safe_base::_M_swap(__x);
}
void
@@ -179,7 +158,7 @@
this->_M_invalidate_all();
}
- iterator
+ iterator
begin() noexcept
{ return iterator(_Base::begin(), this); }
@@ -301,7 +280,7 @@
{
__glibcxx_check_insert(__hint);
size_type __bucket_count = this->bucket_count();
- _Base_iterator __it = _Base::insert(__hint.base(), __obj);
+ _Base_iterator __it = _Base::insert(__hint.base(), __obj);
_M_check_rehashed(__bucket_count);
return iterator(__it, this);
}
@@ -409,7 +388,7 @@
[__victim](_Base_const_local_iterator __it)
{ return __it._M_curr() == __victim._M_cur; });
size_type __bucket_count = this->bucket_count();
- _Base_iterator __next = _Base::erase(__it.base());
+ _Base_iterator __next = _Base::erase(__it.base());
_M_check_rehashed(__bucket_count);
return iterator(__next, this);
}
@@ -449,28 +428,10 @@
private:
void
- _M_invalidate_locals()
- {
- _Base_local_iterator __local_end = _Base::end(0);
- this->_M_invalidate_local_if(
- [__local_end](_Base_const_local_iterator __it)
- { return __it != __local_end; });
- }
-
- void
- _M_invalidate_all()
- {
- _Base_iterator __end = _Base::end();
- this->_M_invalidate_if([__end](_Base_const_iterator __it)
- { return __it != __end; });
- _M_invalidate_locals();
- }
-
- void
_M_check_rehashed(size_type __prev_count)
{
if (__prev_count != this->bucket_count())
- _M_invalidate_locals();
+ this->_M_invalidate_locals();
}
};
@@ -502,23 +463,20 @@
typename _Pred = std::equal_to<_Key>,
typename _Alloc = std::allocator<std::pair<const _Key, _Tp> > >
class unordered_multimap
- : public _GLIBCXX_STD_C::unordered_multimap<_Key, _Tp, _Hash,
- _Pred, _Alloc>,
- public __gnu_debug::_Safe_unordered_container<unordered_multimap<_Key,
- _Tp, _Hash, _Pred, _Alloc> >
+ : public __gnu_debug::_Safe_container<
+ unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>, _Alloc,
+ __gnu_debug::_Safe_unordered_container>,
+ public _GLIBCXX_STD_C::unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>
{
typedef _GLIBCXX_STD_C::unordered_multimap<_Key, _Tp, _Hash,
_Pred, _Alloc> _Base;
- typedef __gnu_debug::_Safe_unordered_container<unordered_multimap>
- _Safe_base;
+ typedef __gnu_debug::_Safe_container<unordered_multimap,
+ _Alloc, __gnu_debug::_Safe_unordered_container> _Safe;
typedef typename _Base::const_iterator _Base_const_iterator;
typedef typename _Base::iterator _Base_iterator;
typedef typename _Base::const_local_iterator _Base_const_local_iterator;
typedef typename _Base::local_iterator _Base_local_iterator;
- typedef __gnu_cxx::__alloc_traits<typename
- _Base::allocator_type> _Alloc_traits;
-
public:
typedef typename _Base::size_type size_type;
typedef typename _Base::hasher hasher;
@@ -528,10 +486,10 @@
typedef typename _Base::key_type key_type;
typedef typename _Base::value_type value_type;
- typedef __gnu_debug::_Safe_iterator<_Base_iterator,
- unordered_multimap> iterator;
- typedef __gnu_debug::_Safe_iterator<_Base_const_iterator,
- unordered_multimap> const_iterator;
+ typedef __gnu_debug::_Safe_iterator<
+ _Base_iterator, unordered_multimap> iterator;
+ typedef __gnu_debug::_Safe_iterator<
+ _Base_const_iterator, unordered_multimap> const_iterator;
typedef __gnu_debug::_Safe_local_iterator<
_Base_local_iterator, unordered_multimap> local_iterator;
typedef __gnu_debug::_Safe_local_iterator<
@@ -545,10 +503,10 @@
: _Base(__n, __hf, __eql, __a) { }
template<typename _InputIterator>
- unordered_multimap(_InputIterator __first, _InputIterator __last,
+ unordered_multimap(_InputIterator __first, _InputIterator __last,
size_type __n = 0,
- const hasher& __hf = hasher(),
- const key_equal& __eql = key_equal(),
+ const hasher& __hf = hasher(),
+ const key_equal& __eql = key_equal(),
const allocator_type& __a = allocator_type())
: _Base(__gnu_debug::__base(__gnu_debug::__check_valid_range(__first,
__last)),
@@ -557,25 +515,23 @@
unordered_multimap(const unordered_multimap&) = default;
- unordered_multimap(const _Base& __x)
+ unordered_multimap(const _Base& __x)
: _Base(__x) { }
unordered_multimap(unordered_multimap&&) = default;
explicit
unordered_multimap(const allocator_type& __a)
- : _Base(__a)
- { }
+ : _Base(__a) { }
unordered_multimap(const unordered_multimap& __umap,
const allocator_type& __a)
- : _Base(__umap._M_base(), __a)
- { }
+ : _Base(__umap, __a) { }
unordered_multimap(unordered_multimap&& __umap,
const allocator_type& __a)
- : _Base(std::move(__umap._M_base()), __a)
- { }
+ : _Safe(std::move(__umap._M_safe()), __a),
+ _Base(std::move(__umap._M_base()), __a) { }
unordered_multimap(initializer_list<value_type> __l,
size_type __n = 0,
@@ -584,48 +540,28 @@
const allocator_type& __a = allocator_type())
: _Base(__l, __n, __hf, __eql, __a) { }
- ~unordered_multimap() noexcept { }
+ ~unordered_multimap() = default;
unordered_multimap&
- operator=(const unordered_multimap& __x)
- {
- _M_base() = __x._M_base();
- this->_M_invalidate_all();
- return *this;
- }
+ operator=(const unordered_multimap&) = default;
unordered_multimap&
- operator=(unordered_multimap&& __x)
- noexcept(_Alloc_traits::_S_nothrow_move())
- {
- __glibcxx_check_self_move_assign(__x);
- bool __xfer_memory = _Alloc_traits::_S_propagate_on_move_assign()
- || __x.get_allocator() == this->get_allocator();
- _M_base() = std::move(__x._M_base());
- if (__xfer_memory)
- this->_M_swap(__x);
- else
- this->_M_invalidate_all();
- __x._M_invalidate_all();
- return *this;
- }
+ operator=(unordered_multimap&&) = default;
unordered_multimap&
operator=(initializer_list<value_type> __l)
{
- _M_base() = __l;
+ this->_M_base() = __l;
this->_M_invalidate_all();
return *this;
}
void
swap(unordered_multimap& __x)
- noexcept(_Alloc_traits::_S_nothrow_swap())
+ noexcept( noexcept(declval<_Base>().swap(__x)) )
{
- if (!_Alloc_traits::_S_propagate_on_swap())
- __glibcxx_check_equal_allocs(__x);
+ _Safe::_M_swap(__x);
_Base::swap(__x);
- _Safe_base::_M_swap(__x);
}
void
@@ -635,7 +571,7 @@
this->_M_invalidate_all();
}
- iterator
+ iterator
begin() noexcept
{ return iterator(_Base::begin(), this); }
@@ -901,28 +837,10 @@
private:
void
- _M_invalidate_locals()
- {
- _Base_local_iterator __local_end = _Base::end(0);
- this->_M_invalidate_local_if(
- [__local_end](_Base_const_local_iterator __it)
- { return __it != __local_end; });
- }
-
- void
- _M_invalidate_all()
- {
- _Base_iterator __end = _Base::end();
- this->_M_invalidate_if([__end](_Base_const_iterator __it)
- { return __it != __end; });
- _M_invalidate_locals();
- }
-
- void
_M_check_rehashed(size_type __prev_count)
{
if (__prev_count != this->bucket_count())
- _M_invalidate_locals();
+ this->_M_invalidate_locals();
}
};
Index: include/debug/unordered_set
===================================================================
--- include/debug/unordered_set (revision 209879)
+++ include/debug/unordered_set (working copy)
@@ -35,6 +35,7 @@
# include <unordered_set>
#include <debug/safe_unordered_container.h>
+#include <debug/safe_container.h>
#include <debug/safe_iterator.h>
#include <debug/safe_local_iterator.h>
@@ -48,20 +49,21 @@
typename _Pred = std::equal_to<_Value>,
typename _Alloc = std::allocator<_Value> >
class unordered_set
- : public _GLIBCXX_STD_C::unordered_set<_Value, _Hash, _Pred, _Alloc>,
- public __gnu_debug::_Safe_unordered_container<unordered_set<_Value, _Hash,
- _Pred, _Alloc> >
+ : public __gnu_debug::_Safe_container<
+ unordered_set<_Value, _Hash, _Pred, _Alloc>, _Alloc,
+ __gnu_debug::_Safe_unordered_container>,
+ public _GLIBCXX_STD_C::unordered_set<_Value, _Hash, _Pred, _Alloc>
{
- typedef _GLIBCXX_STD_C::unordered_set<_Value, _Hash,
- _Pred, _Alloc> _Base;
- typedef __gnu_debug::_Safe_unordered_container<unordered_set> _Safe_base;
+ typedef _GLIBCXX_STD_C::unordered_set<
+ _Value, _Hash, _Pred, _Alloc> _Base;
+ typedef __gnu_debug::_Safe_container<
+ unordered_set, _Alloc, __gnu_debug::_Safe_unordered_container> _Safe;
+
typedef typename _Base::const_iterator _Base_const_iterator;
typedef typename _Base::iterator _Base_iterator;
typedef typename _Base::const_local_iterator _Base_const_local_iterator;
typedef typename _Base::local_iterator _Base_local_iterator;
- typedef __gnu_cxx::__alloc_traits<typename
- _Base::allocator_type> _Alloc_traits;
public:
typedef typename _Base::size_type size_type;
typedef typename _Base::hasher hasher;
@@ -71,14 +73,14 @@
typedef typename _Base::key_type key_type;
typedef typename _Base::value_type value_type;
- typedef __gnu_debug::_Safe_iterator<_Base_iterator,
- unordered_set> iterator;
- typedef __gnu_debug::_Safe_iterator<_Base_const_iterator,
- unordered_set> const_iterator;
- typedef __gnu_debug::_Safe_local_iterator<_Base_local_iterator,
- unordered_set> local_iterator;
- typedef __gnu_debug::_Safe_local_iterator<_Base_const_local_iterator,
- unordered_set> const_local_iterator;
+ typedef __gnu_debug::_Safe_iterator<
+ _Base_iterator, unordered_set> iterator;
+ typedef __gnu_debug::_Safe_iterator<
+ _Base_const_iterator, unordered_set> const_iterator;
+ typedef __gnu_debug::_Safe_local_iterator<
+ _Base_local_iterator, unordered_set> local_iterator;
+ typedef __gnu_debug::_Safe_local_iterator<
+ _Base_const_local_iterator, unordered_set> const_local_iterator;
explicit
unordered_set(size_type __n = 10,
@@ -88,10 +90,10 @@
: _Base(__n, __hf, __eql, __a) { }
template<typename _InputIterator>
- unordered_set(_InputIterator __first, _InputIterator __last,
+ unordered_set(_InputIterator __first, _InputIterator __last,
size_type __n = 0,
- const hasher& __hf = hasher(),
- const key_equal& __eql = key_equal(),
+ const hasher& __hf = hasher(),
+ const key_equal& __eql = key_equal(),
const allocator_type& __a = allocator_type())
: _Base(__gnu_debug::__base(__gnu_debug::__check_valid_range(__first,
__last)),
@@ -107,18 +109,16 @@
explicit
unordered_set(const allocator_type& __a)
- : _Base(__a)
- { }
+ : _Base(__a) { }
unordered_set(const unordered_set& __uset,
const allocator_type& __a)
- : _Base(__uset._M_base(), __a)
- { }
+ : _Base(__uset, __a) { }
unordered_set(unordered_set&& __uset,
const allocator_type& __a)
- : _Base(std::move(__uset._M_base()), __a)
- { }
+ : _Safe(std::move(__uset._M_safe()), __a),
+ _Base(std::move(__uset._M_base()), __a) { }
unordered_set(initializer_list<value_type> __l,
size_type __n = 0,
@@ -127,31 +127,13 @@
const allocator_type& __a = allocator_type())
: _Base(__l, __n, __hf, __eql, __a) { }
- ~unordered_set() noexcept { }
+ ~unordered_set() = default;
unordered_set&
- operator=(const unordered_set& __x)
- {
- _M_base() = __x._M_base();
- this->_M_invalidate_all();
- return *this;
- }
+ operator=(const unordered_set&) = default;
unordered_set&
- operator=(unordered_set&& __x)
- noexcept(_Alloc_traits::_S_nothrow_move())
- {
- __glibcxx_check_self_move_assign(__x);
- bool __xfer_memory = _Alloc_traits::_S_propagate_on_move_assign()
- || __x.get_allocator() == this->get_allocator();
- _M_base() = std::move(__x._M_base());
- if (__xfer_memory)
- this->_M_swap(__x);
- else
- this->_M_invalidate_all();
- __x._M_invalidate_all();
- return *this;
- }
+ operator=(unordered_set&&) = default;
unordered_set&
operator=(initializer_list<value_type> __l)
@@ -163,12 +145,10 @@
void
swap(unordered_set& __x)
- noexcept(_Alloc_traits::_S_nothrow_swap())
+ noexcept( noexcept(declval<_Base>().swap(__x)) )
{
- if (!_Alloc_traits::_S_propagate_on_swap())
- __glibcxx_check_equal_allocs(__x);
+ _Safe::_M_swap(__x);
_Base::swap(__x);
- _Safe_base::_M_swap(__x);
}
void
@@ -178,7 +158,7 @@
this->_M_invalidate_all();
}
- iterator
+ iterator
begin() noexcept
{ return iterator(_Base::begin(), this); }
@@ -290,8 +270,8 @@
insert(const value_type& __obj)
{
size_type __bucket_count = this->bucket_count();
- typedef std::pair<_Base_iterator, bool> __pair_type;
- __pair_type __res = _Base::insert(__obj);
+ std::pair<_Base_iterator, bool> __res
+ = _Base::insert(__obj);
_M_check_rehashed(__bucket_count);
return std::make_pair(iterator(__res.first, this), __res.second);
}
@@ -310,8 +290,8 @@
insert(value_type&& __obj)
{
size_type __bucket_count = this->bucket_count();
- typedef std::pair<typename _Base::iterator, bool> __pair_type;
- __pair_type __res = _Base::insert(std::move(__obj));
+ std::pair<_Base_iterator, bool> __res
+ = _Base::insert(std::move(__obj));
_M_check_rehashed(__bucket_count);
return std::make_pair(iterator(__res.first, this), __res.second);
}
@@ -356,8 +336,8 @@
std::pair<iterator, iterator>
equal_range(const key_type& __key)
{
- typedef std::pair<_Base_iterator, _Base_iterator> __pair_type;
- __pair_type __res = _Base::equal_range(__key);
+ std::pair<_Base_iterator, _Base_iterator> __res
+ = _Base::equal_range(__key);
return std::make_pair(iterator(__res.first, this),
iterator(__res.second, this));
}
@@ -446,29 +426,10 @@
private:
void
- _M_invalidate_locals()
- {
- _Base_local_iterator __local_end = _Base::end(0);
- this->_M_invalidate_local_if(
- [__local_end](_Base_const_local_iterator __it)
- { return __it != __local_end; });
- }
-
- void
- _M_invalidate_all()
- {
- _Base_iterator __end = _Base::end();
- this->_M_invalidate_if(
- [__end](_Base_const_iterator __it)
- { return __it != __end; });
- _M_invalidate_locals();
- }
-
- void
_M_check_rehashed(size_type __prev_count)
{
if (__prev_count != this->bucket_count())
- _M_invalidate_locals();
+ this->_M_invalidate_locals();
}
};
@@ -497,22 +458,21 @@
typename _Pred = std::equal_to<_Value>,
typename _Alloc = std::allocator<_Value> >
class unordered_multiset
- : public _GLIBCXX_STD_C::unordered_multiset<_Value, _Hash, _Pred, _Alloc>,
- public __gnu_debug::_Safe_unordered_container<
- unordered_multiset<_Value, _Hash, _Pred, _Alloc> >
+ : public __gnu_debug::_Safe_container<
+ unordered_multiset<_Value, _Hash, _Pred, _Alloc>, _Alloc,
+ __gnu_debug::_Safe_unordered_container>,
+ public _GLIBCXX_STD_C::unordered_multiset<_Value, _Hash, _Pred, _Alloc>
{
- typedef _GLIBCXX_STD_C::unordered_multiset<_Value, _Hash,
- _Pred, _Alloc> _Base;
- typedef __gnu_debug::_Safe_unordered_container<unordered_multiset>
- _Safe_base;
+ typedef _GLIBCXX_STD_C::unordered_multiset<
+ _Value, _Hash, _Pred, _Alloc> _Base;
+ typedef __gnu_debug::_Safe_container<unordered_multiset,
+ _Alloc, __gnu_debug::_Safe_unordered_container> _Safe;
typedef typename _Base::const_iterator _Base_const_iterator;
typedef typename _Base::iterator _Base_iterator;
- typedef typename _Base::const_local_iterator _Base_const_local_iterator;
+ typedef typename _Base::const_local_iterator
+ _Base_const_local_iterator;
typedef typename _Base::local_iterator _Base_local_iterator;
- typedef __gnu_cxx::__alloc_traits<typename
- _Base::allocator_type> _Alloc_traits;
-
public:
typedef typename _Base::size_type size_type;
typedef typename _Base::hasher hasher;
@@ -522,10 +482,10 @@
typedef typename _Base::key_type key_type;
typedef typename _Base::value_type value_type;
- typedef __gnu_debug::_Safe_iterator<_Base_iterator,
- unordered_multiset> iterator;
- typedef __gnu_debug::_Safe_iterator<_Base_const_iterator,
- unordered_multiset> const_iterator;
+ typedef __gnu_debug::_Safe_iterator<
+ _Base_iterator, unordered_multiset> iterator;
+ typedef __gnu_debug::_Safe_iterator<
+ _Base_const_iterator, unordered_multiset> const_iterator;
typedef __gnu_debug::_Safe_local_iterator<
_Base_local_iterator, unordered_multiset> local_iterator;
typedef __gnu_debug::_Safe_local_iterator<
@@ -539,10 +499,10 @@
: _Base(__n, __hf, __eql, __a) { }
template<typename _InputIterator>
- unordered_multiset(_InputIterator __first, _InputIterator __last,
+ unordered_multiset(_InputIterator __first, _InputIterator __last,
size_type __n = 0,
- const hasher& __hf = hasher(),
- const key_equal& __eql = key_equal(),
+ const hasher& __hf = hasher(),
+ const key_equal& __eql = key_equal(),
const allocator_type& __a = allocator_type())
: _Base(__gnu_debug::__base(__gnu_debug::__check_valid_range(__first,
__last)),
@@ -551,25 +511,23 @@
unordered_multiset(const unordered_multiset&) = default;
- unordered_multiset(const _Base& __x)
+ unordered_multiset(const _Base& __x)
: _Base(__x) { }
unordered_multiset(unordered_multiset&&) = default;
explicit
unordered_multiset(const allocator_type& __a)
- : _Base(__a)
- { }
+ : _Base(__a) { }
unordered_multiset(const unordered_multiset& __uset,
const allocator_type& __a)
- : _Base(__uset._M_base(), __a)
- { }
-
+ : _Base(__uset, __a) { }
+
unordered_multiset(unordered_multiset&& __uset,
const allocator_type& __a)
- : _Base(std::move(__uset._M_base()), __a)
- { }
+ : _Safe(std::move(__uset._M_safe()), __a),
+ _Base(std::move(__uset._M_base()), __a) { }
unordered_multiset(initializer_list<value_type> __l,
size_type __n = 0,
@@ -578,48 +536,28 @@
const allocator_type& __a = allocator_type())
: _Base(__l, __n, __hf, __eql, __a) { }
- ~unordered_multiset() noexcept { }
+ ~unordered_multiset() = default;
unordered_multiset&
- operator=(const unordered_multiset& __x)
- {
- _M_base() = __x._M_base();
- this->_M_invalidate_all();
- return *this;
- }
+ operator=(const unordered_multiset&) = default;
unordered_multiset&
- operator=(unordered_multiset&& __x)
- noexcept(_Alloc_traits::_S_nothrow_move())
- {
- __glibcxx_check_self_move_assign(__x);
- bool __xfer_memory = _Alloc_traits::_S_propagate_on_move_assign()
- || __x.get_allocator() == this->get_allocator();
- _M_base() = std::move(__x._M_base());
- if (__xfer_memory)
- this->_M_swap(__x);
- else
- this->_M_invalidate_all();
- __x._M_invalidate_all();
- return *this;
- }
+ operator=(unordered_multiset&&) = default;
unordered_multiset&
operator=(initializer_list<value_type> __l)
{
- _M_base() = __l;
+ this->_M_base() = __l;
this->_M_invalidate_all();
return *this;
}
void
swap(unordered_multiset& __x)
- noexcept(_Alloc_traits::_S_nothrow_swap())
+ noexcept( noexcept(declval<_Base>().swap(__x)) )
{
- if (!_Alloc_traits::_S_propagate_on_swap())
- __glibcxx_check_equal_allocs(__x);
+ _Safe::_M_swap(__x);
_Base::swap(__x);
- _Safe_base::_M_swap(__x);
}
void
@@ -751,7 +689,7 @@
{
__glibcxx_check_insert(__hint);
size_type __bucket_count = this->bucket_count();
- _Base_iterator __it = _Base::insert(__hint.base(), __obj);
+ _Base_iterator __it = _Base::insert(__hint.base(), __obj);
_M_check_rehashed(__bucket_count);
return iterator(__it, this);
}
@@ -760,7 +698,7 @@
insert(value_type&& __obj)
{
size_type __bucket_count = this->bucket_count();
- _Base_iterator __it = _Base::insert(std::move(__obj));
+ _Base_iterator __it = _Base::insert(std::move(__obj));
_M_check_rehashed(__bucket_count);
return iterator(__it, this);
}
@@ -770,7 +708,7 @@
{
__glibcxx_check_insert(__hint);
size_type __bucket_count = this->bucket_count();
- _Base_iterator __it = _Base::insert(__hint.base(), std::move(__obj));
+ _Base_iterator __it = _Base::insert(__hint.base(), std::move(__obj));
_M_check_rehashed(__bucket_count);
return iterator(__it, this);
}
@@ -805,8 +743,8 @@
std::pair<iterator, iterator>
equal_range(const key_type& __key)
{
- typedef std::pair<_Base_iterator, _Base_iterator> __pair_type;
- __pair_type __res = _Base::equal_range(__key);
+ std::pair<_Base_iterator, _Base_iterator> __res
+ = _Base::equal_range(__key);
return std::make_pair(iterator(__res.first, this),
iterator(__res.second, this));
}
@@ -885,28 +823,10 @@
private:
void
- _M_invalidate_locals()
- {
- _Base_local_iterator __local_end = _Base::end(0);
- this->_M_invalidate_local_if(
- [__local_end](_Base_const_local_iterator __it)
- { return __it != __local_end; });
- }
-
- void
- _M_invalidate_all()
- {
- _Base_iterator __end = _Base::end();
- this->_M_invalidate_if([__end](_Base_const_iterator __it)
- { return __it != __end; });
- _M_invalidate_locals();
- }
-
- void
_M_check_rehashed(size_type __prev_count)
{
if (__prev_count != this->bucket_count())
- _M_invalidate_locals();
+ this->_M_invalidate_locals();
}
};
Index: include/debug/vector
===================================================================
--- include/debug/vector (revision 209879)
+++ include/debug/vector (working copy)
@@ -32,8 +32,68 @@
#include <vector>
#include <utility>
#include <debug/safe_sequence.h>
+#include <debug/safe_container.h>
#include <debug/safe_iterator.h>
+namespace __gnu_debug
+{
+ /// Special vector safe base class to add a guaranteed capacity information
+ /// useful to detect code relying on the libstdc++ reallocation management
+ /// implementation detail.
+ template<typename _SafeSequence,
+ typename _BaseSequence>
+ class _Safe_vector
+ {
+ typedef typename _BaseSequence::size_type size_type;
+
+ const _SafeSequence&
+ _M_seq() const { return *static_cast<const _SafeSequence*>(this); }
+
+ protected:
+ _Safe_vector() _GLIBCXX_NOEXCEPT
+ : _M_guaranteed_capacity(0)
+ { _M_update_guaranteed_capacity(); }
+
+ _Safe_vector(const _Safe_vector&) _GLIBCXX_NOEXCEPT
+ : _M_guaranteed_capacity(0)
+ { _M_update_guaranteed_capacity(); }
+
+ _Safe_vector(size_type __n) _GLIBCXX_NOEXCEPT
+ : _M_guaranteed_capacity(__n)
+ { }
+
+#if __cplusplus >= 201103L
+ _Safe_vector(_Safe_vector&& __x) noexcept
+ : _Safe_vector()
+ { __x._M_guaranteed_capacity = 0; }
+
+ _Safe_vector&
+ operator=(const _Safe_vector&) noexcept
+ { _M_update_guaranteed_capacity(); }
+
+ _Safe_vector&
+ operator=(_Safe_vector&& __x) noexcept
+ {
+ _M_update_guaranteed_capacity();
+ __x._M_guaranteed_capacity = 0;
+ }
+#endif
+
+ size_type _M_guaranteed_capacity;
+
+ bool
+ _M_requires_reallocation(size_type __elements) const _GLIBCXX_NOEXCEPT
+ { return __elements > _M_seq().capacity(); }
+
+ void
+ _M_update_guaranteed_capacity() _GLIBCXX_NOEXCEPT
+ {
+ if (_M_seq().size() > _M_guaranteed_capacity)
+ _M_guaranteed_capacity = _M_seq().size();
+ }
+ };
+}
+
namespace std _GLIBCXX_VISIBILITY(default)
{
namespace __debug
@@ -42,28 +102,30 @@
template<typename _Tp,
typename _Allocator = std::allocator<_Tp> >
class vector
- : public _GLIBCXX_STD_C::vector<_Tp, _Allocator>,
- public __gnu_debug::_Safe_sequence<vector<_Tp, _Allocator> >
+ : public __gnu_debug::_Safe_container<
+ vector<_Tp, _Allocator>, _Allocator, __gnu_debug::_Safe_sequence>,
+ public _GLIBCXX_STD_C::vector<_Tp, _Allocator>,
+ public __gnu_debug::_Safe_vector<
+ vector<_Tp, _Allocator>,
+ _GLIBCXX_STD_C::vector<_Tp, _Allocator> >
{
typedef _GLIBCXX_STD_C::vector<_Tp, _Allocator> _Base;
+ typedef __gnu_debug::_Safe_container<
+ vector, _Allocator, __gnu_debug::_Safe_sequence> _Safe;
+ typedef __gnu_debug::_Safe_vector<vector, _Base> _Safe_vector;
typedef typename _Base::iterator _Base_iterator;
typedef typename _Base::const_iterator _Base_const_iterator;
typedef __gnu_debug::_Equal_to<_Base_const_iterator> _Equal;
-#if __cplusplus >= 201103L
- typedef __gnu_debug::_Safe_sequence<vector<_Tp, _Allocator> > _Safe_base;
- typedef __gnu_cxx::__alloc_traits<_Allocator> _Alloc_traits;
-#endif
-
public:
typedef typename _Base::reference reference;
typedef typename _Base::const_reference const_reference;
- typedef __gnu_debug::_Safe_iterator<_Base_iterator,vector>
- iterator;
- typedef __gnu_debug::_Safe_iterator<_Base_const_iterator,vector>
- const_iterator;
+ typedef __gnu_debug::_Safe_iterator<
+ _Base_iterator, vector> iterator;
+ typedef __gnu_debug::_Safe_iterator<
+ _Base_const_iterator, vector> const_iterator;
typedef typename _Base::size_type size_type;
typedef typename _Base::difference_type difference_type;
@@ -77,26 +139,30 @@
// 23.2.4.1 construct/copy/destroy:
+#if __cplusplus < 201103L
vector() _GLIBCXX_NOEXCEPT
- : _Base(), _M_guaranteed_capacity(0) { }
+ : _Base() { }
+#else
+ vector() = default;
+#endif
explicit
vector(const _Allocator& __a) _GLIBCXX_NOEXCEPT
- : _Base(__a), _M_guaranteed_capacity(0) { }
+ : _Base(__a) { }
#if __cplusplus >= 201103L
explicit
vector(size_type __n, const _Allocator& __a = _Allocator())
- : _Base(__n, __a), _M_guaranteed_capacity(__n) { }
+ : _Base(__n, __a), _Safe_vector(__n) { }
vector(size_type __n, const _Tp& __value,
const _Allocator& __a = _Allocator())
- : _Base(__n, __value, __a), _M_guaranteed_capacity(__n) { }
+ : _Base(__n, __value, __a) { }
#else
explicit
vector(size_type __n, const _Tp& __value = _Tp(),
const _Allocator& __a = _Allocator())
- : _Base(__n, __value, __a), _M_guaranteed_capacity(__n) { }
+ : _Base(__n, __value, __a) { }
#endif
#if __cplusplus >= 201103L
@@ -109,79 +175,58 @@
const _Allocator& __a = _Allocator())
: _Base(__gnu_debug::__base(__gnu_debug::__check_valid_range(__first,
__last)),
- __gnu_debug::__base(__last), __a),
- _M_guaranteed_capacity(0)
- { _M_update_guaranteed_capacity(); }
+ __gnu_debug::__base(__last), __a) { }
+#if __cplusplus < 201103L
vector(const vector& __x)
- : _Base(__x), _M_guaranteed_capacity(__x.size()) { }
+ : _Base(__x) { }
- /// Construction from a normal-mode vector
- vector(const _Base& __x)
- : _Base(__x), _M_guaranteed_capacity(__x.size()) { }
+ ~vector() _GLIBCXX_NOEXCEPT { }
+#else
+ vector(const vector&) = default;
+ vector(vector&&) = default;
-#if __cplusplus >= 201103L
- vector(vector&& __x) noexcept
- : _Base(std::move(__x)),
- _Safe_base(std::move(__x)),
- _M_guaranteed_capacity(this->size())
- { __x._M_guaranteed_capacity = 0; }
-
vector(const vector& __x, const allocator_type& __a)
- : _Base(__x, __a), _M_guaranteed_capacity(__x.size()) { }
+ : _Base(__x, __a) { }
vector(vector&& __x, const allocator_type& __a)
- : _Base(std::move(__x), __a),
- _M_guaranteed_capacity(this->size())
- {
- if (__x.get_allocator() == __a)
- this->_M_swap(__x);
- else
- __x._M_invalidate_all();
- __x._M_guaranteed_capacity = 0;
- }
+ : _Safe(std::move(__x._M_safe()), __a),
+ _Base(std::move(__x._M_base()), __a),
+ _Safe_vector(std::move(__x)) { }
vector(initializer_list<value_type> __l,
const allocator_type& __a = allocator_type())
- : _Base(__l, __a),
- _M_guaranteed_capacity(__l.size()) { }
+ : _Base(__l, __a) { }
+
+ ~vector() = default;
#endif
- ~vector() _GLIBCXX_NOEXCEPT { }
+ /// Construction from a normal-mode vector
+ vector(const _Base& __x)
+ : _Base(__x) { }
+#if __cplusplus < 201103L
vector&
operator=(const vector& __x)
{
+ this->_M_safe() = __x;
_M_base() = __x;
- this->_M_invalidate_all();
- _M_update_guaranteed_capacity();
+ this->_M_update_guaranteed_capacity();
return *this;
}
+#else
+ vector&
+ operator=(const vector&) = default;
-#if __cplusplus >= 201103L
vector&
- operator=(vector&& __x) noexcept(_Alloc_traits::_S_nothrow_move())
- {
- __glibcxx_check_self_move_assign(__x);
- bool __xfer_memory = _Alloc_traits::_S_propagate_on_move_assign()
- || __x.get_allocator() == this->get_allocator();
- _M_base() = std::move(__x._M_base());
- if (__xfer_memory)
- this->_M_swap(__x);
- else
- this->_M_invalidate_all();
- _M_update_guaranteed_capacity();
- __x._M_invalidate_all();
- __x._M_guaranteed_capacity = 0;
- return *this;
- }
+ operator=(vector&&) = default;
vector&
operator=(initializer_list<value_type> __l)
{
_M_base() = __l;
this->_M_invalidate_all();
- _M_update_guaranteed_capacity();
+ this->_M_update_guaranteed_capacity();
return *this;
}
#endif
@@ -199,7 +244,7 @@
_Base::assign(__gnu_debug::__base(__first),
__gnu_debug::__base(__last));
this->_M_invalidate_all();
- _M_update_guaranteed_capacity();
+ this->_M_update_guaranteed_capacity();
}
void
@@ -207,7 +252,7 @@
{
_Base::assign(__n, __u);
this->_M_invalidate_all();
- _M_update_guaranteed_capacity();
+ this->_M_update_guaranteed_capacity();
}
#if __cplusplus >= 201103L
@@ -216,7 +261,7 @@
{
_Base::assign(__l);
this->_M_invalidate_all();
- _M_update_guaranteed_capacity();
+ this->_M_update_guaranteed_capacity();
}
#endif
@@ -281,37 +326,37 @@
void
resize(size_type __sz)
{
- bool __realloc = _M_requires_reallocation(__sz);
+ bool __realloc = this->_M_requires_reallocation(__sz);
if (__sz < this->size())
this->_M_invalidate_after_nth(__sz);
_Base::resize(__sz);
if (__realloc)
this->_M_invalidate_all();
- _M_update_guaranteed_capacity();
+ this->_M_update_guaranteed_capacity();
}
void
resize(size_type __sz, const _Tp& __c)
{
- bool __realloc = _M_requires_reallocation(__sz);
+ bool __realloc = this->_M_requires_reallocation(__sz);
if (__sz < this->size())
this->_M_invalidate_after_nth(__sz);
_Base::resize(__sz, __c);
if (__realloc)
this->_M_invalidate_all();
- _M_update_guaranteed_capacity();
+ this->_M_update_guaranteed_capacity();
}
#else
void
resize(size_type __sz, _Tp __c = _Tp())
{
- bool __realloc = _M_requires_reallocation(__sz);
+ bool __realloc = this->_M_requires_reallocation(__sz);
if (__sz < this->size())
this->_M_invalidate_after_nth(__sz);
_Base::resize(__sz, __c);
if (__realloc)
this->_M_invalidate_all();
- _M_update_guaranteed_capacity();
+ this->_M_update_guaranteed_capacity();
}
#endif
@@ -321,7 +366,7 @@
{
if (_Base::_M_shrink_to_fit())
{
- _M_guaranteed_capacity = _Base::capacity();
+ this->_M_guaranteed_capacity = _Base::capacity();
this->_M_invalidate_all();
}
}
@@ -331,7 +376,7 @@
capacity() const _GLIBCXX_NOEXCEPT
{
#ifdef _GLIBCXX_DEBUG_PEDANTIC
- return _M_guaranteed_capacity;
+ return this->_M_guaranteed_capacity;
#else
return _Base::capacity();
#endif
@@ -342,10 +387,10 @@
void
reserve(size_type __n)
{
- bool __realloc = _M_requires_reallocation(__n);
+ bool __realloc = this->_M_requires_reallocation(__n);
_Base::reserve(__n);
- if (__n > _M_guaranteed_capacity)
- _M_guaranteed_capacity = __n;
+ if (__n > this->_M_guaranteed_capacity)
+ this->_M_guaranteed_capacity = __n;
if (__realloc)
this->_M_invalidate_all();
}
@@ -403,11 +448,11 @@
void
push_back(const _Tp& __x)
{
- bool __realloc = _M_requires_reallocation(this->size() + 1);
+ bool __realloc = this->_M_requires_reallocation(this->size() + 1);
_Base::push_back(__x);
if (__realloc)
this->_M_invalidate_all();
- _M_update_guaranteed_capacity();
+ this->_M_update_guaranteed_capacity();
}
#if __cplusplus >= 201103L
@@ -421,11 +466,11 @@
void
emplace_back(_Args&&... __args)
{
- bool __realloc = _M_requires_reallocation(this->size() + 1);
+ bool __realloc = this->_M_requires_reallocation(this->size() + 1);
_Base::emplace_back(std::forward<_Args>(__args)...);
if (__realloc)
this->_M_invalidate_all();
- _M_update_guaranteed_capacity();
+ this->_M_update_guaranteed_capacity();
}
#endif
@@ -443,7 +488,7 @@
emplace(const_iterator __position, _Args&&... __args)
{
__glibcxx_check_insert(__position);
- bool __realloc = _M_requires_reallocation(this->size() + 1);
+ bool __realloc = this->_M_requires_reallocation(this->size() + 1);
difference_type __offset = __position.base() - _Base::begin();
_Base_iterator __res = _Base::emplace(__position.base(),
std::forward<_Args>(__args)...);
@@ -451,7 +496,7 @@
this->_M_invalidate_all();
else
this->_M_invalidate_after_nth(__offset);
- _M_update_guaranteed_capacity();
+ this->_M_update_guaranteed_capacity();
return iterator(__res, this);
}
#endif
@@ -464,14 +509,14 @@
#endif
{
__glibcxx_check_insert(__position);
- bool __realloc = _M_requires_reallocation(this->size() + 1);
+ bool __realloc = this->_M_requires_reallocation(this->size() + 1);
difference_type __offset = __position.base() - _Base::begin();
_Base_iterator __res = _Base::insert(__position.base(), __x);
if (__realloc)
this->_M_invalidate_all();
else
this->_M_invalidate_after_nth(__offset);
- _M_update_guaranteed_capacity();
+ this->_M_update_guaranteed_capacity();
return iterator(__res, this);
}
@@ -492,14 +537,14 @@
insert(const_iterator __position, size_type __n, const _Tp& __x)
{
__glibcxx_check_insert(__position);
- bool __realloc = _M_requires_reallocation(this->size() + __n);
+ bool __realloc = this->_M_requires_reallocation(this->size() + __n);
difference_type __offset = __position.base() - _Base::cbegin();
_Base_iterator __res = _Base::insert(__position.base(), __n, __x);
if (__realloc)
this->_M_invalidate_all();
else
this->_M_invalidate_after_nth(__offset);
- _M_update_guaranteed_capacity();
+ this->_M_update_guaranteed_capacity();
return iterator(__res, this);
}
#else
@@ -507,14 +552,14 @@
insert(iterator __position, size_type __n, const _Tp& __x)
{
__glibcxx_check_insert(__position);
- bool __realloc = _M_requires_reallocation(this->size() + __n);
+ bool __realloc = this->_M_requires_reallocation(this->size() + __n);
difference_type __offset = __position.base() - _Base::begin();
_Base::insert(__position.base(), __n, __x);
if (__realloc)
this->_M_invalidate_all();
else
this->_M_invalidate_after_nth(__offset);
- _M_update_guaranteed_capacity();
+ this->_M_update_guaranteed_capacity();
}
#endif
@@ -540,7 +585,7 @@
this->_M_invalidate_all();
else
this->_M_invalidate_after_nth(__offset);
- _M_update_guaranteed_capacity();
+ this->_M_update_guaranteed_capacity();
return iterator(__res, this);
}
#else
@@ -563,7 +608,7 @@
this->_M_invalidate_all();
else
this->_M_invalidate_after_nth(__offset);
- _M_update_guaranteed_capacity();
+ this->_M_update_guaranteed_capacity();
}
#endif
@@ -611,16 +656,12 @@
void
swap(vector& __x)
#if __cplusplus >= 201103L
- noexcept(_Alloc_traits::_S_nothrow_swap())
+ noexcept( noexcept(declval<_Base>().swap(__x)) )
#endif
{
-#if __cplusplus >= 201103L
- if (!_Alloc_traits::_S_propagate_on_swap())
- __glibcxx_check_equal_allocs(__x);
-#endif
+ _Safe::_M_swap(__x);
_Base::swap(__x);
- this->_M_swap(__x);
- std::swap(_M_guaranteed_capacity, __x._M_guaranteed_capacity);
+ std::swap(this->_M_guaranteed_capacity, __x._M_guaranteed_capacity);
}
void
@@ -628,7 +669,7 @@
{
_Base::clear();
this->_M_invalidate_all();
- _M_guaranteed_capacity = 0;
+ this->_M_guaranteed_capacity = 0;
}
_Base&
@@ -638,20 +679,7 @@
_M_base() const _GLIBCXX_NOEXCEPT { return *this; }
private:
- size_type _M_guaranteed_capacity;
-
- bool
- _M_requires_reallocation(size_type __elements) _GLIBCXX_NOEXCEPT
- { return __elements > this->capacity(); }
-
void
- _M_update_guaranteed_capacity() _GLIBCXX_NOEXCEPT
- {
- if (this->size() > _M_guaranteed_capacity)
- _M_guaranteed_capacity = this->size();
- }
-
- void
_M_invalidate_after_nth(difference_type __n) _GLIBCXX_NOEXCEPT
{
typedef __gnu_debug::_After_nth_from<_Base_const_iterator> _After_nth;
Index: src/c++11/debug.cc
===================================================================
--- src/c++11/debug.cc (revision 209879)
+++ src/c++11/debug.cc (working copy)
@@ -23,8 +23,8 @@
// <http://www.gnu.org/licenses/>.
#include <debug/debug.h>
-#include <debug/safe_sequence.h>
-#include <debug/safe_unordered_container.h>
+#include <debug/safe_base.h>
+#include <debug/safe_unordered_base.h>
#include <debug/safe_iterator.h>
#include <debug/safe_local_iterator.h>
#include <algorithm>
@@ -235,7 +235,7 @@
void
_Safe_sequence_base::
- _M_swap(_Safe_sequence_base& __x)
+ _M_swap(_Safe_sequence_base& __x) noexcept
{
// We need to lock both sequences to swap
using namespace __gnu_cxx;
@@ -382,7 +382,7 @@
_Safe_unordered_container_base*
_Safe_local_iterator_base::
- _M_get_container() const _GLIBCXX_NOEXCEPT
+ _M_get_container() const noexcept
{ return static_cast<_Safe_unordered_container_base*>(_M_sequence); }
void
@@ -455,7 +455,7 @@
void
_Safe_unordered_container_base::
- _M_swap(_Safe_unordered_container_base& __x)
+ _M_swap(_Safe_unordered_container_base& __x) noexcept
{
// We need to lock both containers to swap
using namespace __gnu_cxx;
Index: testsuite/23_containers/forward_list/allocator/move.cc
===================================================================
--- testsuite/23_containers/forward_list/allocator/move.cc (revision 209879)
+++ testsuite/23_containers/forward_list/allocator/move.cc (working copy)
@@ -32,9 +32,11 @@
typedef std::forward_list<T, alloc_type> test_type;
test_type v1(alloc_type(1));
v1 = { T() };
+ auto it = v1.begin();
test_type v2(std::move(v1));
VERIFY(1 == v1.get_allocator().get_personality());
VERIFY(1 == v2.get_allocator().get_personality());
+ VERIFY( it == v2.begin() );
}
void test02()
Index: testsuite/23_containers/forward_list/allocator/move_assign.cc
===================================================================
--- testsuite/23_containers/forward_list/allocator/move_assign.cc (revision 209879)
+++ testsuite/23_containers/forward_list/allocator/move_assign.cc (working copy)
@@ -46,11 +46,13 @@
typedef std::forward_list<T, alloc_type> test_type;
test_type v1(alloc_type(1));
v1.push_front(T());
+ auto it = v1.begin();
test_type v2(alloc_type(2));
v2.push_front(T());
v2 = std::move(v1);
VERIFY(0 == v1.get_allocator().get_personality());
VERIFY(1 == v2.get_allocator().get_personality());
+ VERIFY( it == v2.begin() );
}
int main()
Index: testsuite/23_containers/forward_list/debug/construct1_neg.cc
===================================================================
--- testsuite/23_containers/forward_list/debug/construct1_neg.cc (revision 0)
+++ testsuite/23_containers/forward_list/debug/construct1_neg.cc (working copy)
@@ -0,0 +1,34 @@
+// Copyright (C) 2014 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/>.
+//
+// { dg-require-debug-mode "" }
+// { dg-options "-std=gnu++11" }
+// { dg-do run { xfail *-*-* } }
+
+#include <forward_list>
+#include <debug/checks.h>
+
+void test01()
+{
+ __gnu_test::check_construct1<std::forward_list<int> >();
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
Index: testsuite/23_containers/forward_list/debug/construct2_neg.cc
===================================================================
--- testsuite/23_containers/forward_list/debug/construct2_neg.cc (revision 0)
+++ testsuite/23_containers/forward_list/debug/construct2_neg.cc (working copy)
@@ -0,0 +1,34 @@
+// Copyright (C) 2014 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/>.
+//
+// { dg-require-debug-mode "" }
+// { dg-options "-std=gnu++11" }
+// { dg-do run { xfail *-*-* } }
+
+#include <forward_list>
+#include <debug/checks.h>
+
+void test01()
+{
+ __gnu_test::check_construct2<std::forward_list<int> >();
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
Index: testsuite/23_containers/forward_list/debug/construct3_neg.cc
===================================================================
--- testsuite/23_containers/forward_list/debug/construct3_neg.cc (revision 0)
+++ testsuite/23_containers/forward_list/debug/construct3_neg.cc (working copy)
@@ -0,0 +1,34 @@
+// Copyright (C) 2010-2014 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/>.
+//
+// { dg-require-debug-mode "" }
+// { dg-options "-std=gnu++11" }
+// { dg-do run { xfail *-*-* } }
+
+#include <forward_list>
+#include <debug/checks.h>
+
+void test01()
+{
+ __gnu_test::check_construct3<std::forward_list<int> >();
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
Index: testsuite/23_containers/forward_list/debug/construct4_neg.cc
===================================================================
--- testsuite/23_containers/forward_list/debug/construct4_neg.cc (revision 0)
+++ testsuite/23_containers/forward_list/debug/construct4_neg.cc (working copy)
@@ -0,0 +1,44 @@
+// Copyright (C) 2014 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/>.
+//
+// { dg-options "-std=gnu++11" }
+// { dg-do run { xfail *-*-* } }
+
+#include <debug/forward_list>
+
+#include <testsuite_allocator.h>
+
+void test01()
+{
+ bool test __attribute__((unused)) = true;
+
+ typedef __gnu_test::uneq_allocator<int> alloc_type;
+ typedef __gnu_debug::forward_list<int, alloc_type> test_type;
+ test_type v1(alloc_type(1));
+ v1.push_front(0);
+ auto it = v1.begin();
+
+ test_type v2(std::move(v1), alloc_type(2));
+
+ VERIFY( it == v2.begin() ); // Error, it is singular
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
Index: testsuite/23_containers/forward_list/debug/move_assign_neg.cc
===================================================================
--- testsuite/23_containers/forward_list/debug/move_assign_neg.cc (revision 0)
+++ testsuite/23_containers/forward_list/debug/move_assign_neg.cc (working copy)
@@ -0,0 +1,47 @@
+// Copyright (C) 2014 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/>.
+//
+// { dg-options "-std=gnu++11" }
+// { dg-do run { xfail *-*-* } }
+
+#include <debug/forward_list>
+#include <testsuite_allocator.h>
+
+void test01()
+{
+ bool test __attribute__((unused)) = true;
+
+ typedef __gnu_test::uneq_allocator<int> alloc_type;
+ typedef __gnu_debug::forward_list<int, alloc_type> test_type;
+
+ test_type v1(alloc_type(1));
+ v1.push_front(0);
+ auto it = v1.begin();
+
+ test_type v2(alloc_type(2));
+ v2.push_front(1);
+
+ v2 = std::move(v1);
+
+ VERIFY( *it == 0 ); // Error, it is singular.
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
Index: testsuite/23_containers/forward_list/debug/move_neg.cc
===================================================================
--- testsuite/23_containers/forward_list/debug/move_neg.cc (revision 0)
+++ testsuite/23_containers/forward_list/debug/move_neg.cc (working copy)
@@ -0,0 +1,48 @@
+// Copyright (C) 2014 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/>.
+
+// { dg-options "-std=gnu++11" }
+// { dg-do run { xfail *-*-* } }
+
+#include <debug/forward_list>
+
+#include <testsuite_hooks.h>
+#include <testsuite_allocator.h>
+
+using __gnu_test::uneq_allocator;
+
+void test01()
+{
+ bool test __attribute__((unused)) = true;
+
+ typedef uneq_allocator<int> alloc_type;
+ typedef __gnu_debug::forward_list<int, alloc_type> test_type;
+
+ test_type v1(alloc_type(1));
+ v1 = { 0 };
+ auto it = v1.begin();
+
+ test_type v2(std::move(v1), alloc_type(2));
+
+ VERIFY( *it == 0 );
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
Index: testsuite/23_containers/map/allocator/move.cc
===================================================================
--- testsuite/23_containers/map/allocator/move.cc (revision 209879)
+++ testsuite/23_containers/map/allocator/move.cc (working copy)
@@ -38,9 +38,13 @@
typedef std::map<T, U, Cmp, alloc_type> test_type;
test_type v1(alloc_type(1));
v1 = { test_type::value_type{} };
+ auto it = v1.begin();
+
test_type v2(std::move(v1));
+
VERIFY(1 == v1.get_allocator().get_personality());
VERIFY(1 == v2.get_allocator().get_personality());
+ VERIFY( it == v2.begin() );
}
void test02()
Index: testsuite/23_containers/map/allocator/move_assign.cc
===================================================================
--- testsuite/23_containers/map/allocator/move_assign.cc (revision 209879)
+++ testsuite/23_containers/map/allocator/move_assign.cc (working copy)
@@ -38,9 +38,11 @@
typedef std::map<T, U, Cmp, alloc_type> test_type;
test_type v1(alloc_type(1));
v1 = { test_type::value_type{} };
+
test_type v2(alloc_type(2));
v2 = { test_type::value_type{} };
v2 = std::move(v1);
+
VERIFY(1 == v1.get_allocator().get_personality());
VERIFY(2 == v2.get_allocator().get_personality());
}
@@ -52,11 +54,15 @@
typedef std::map<T, U, Cmp, alloc_type> test_type;
test_type v1(alloc_type(1));
v1 = { test_type::value_type{} };
+ auto it = v1.begin();
+
test_type v2(alloc_type(2));
v2 = { test_type::value_type{} };
v2 = std::move(v1);
+
VERIFY(0 == v1.get_allocator().get_personality());
VERIFY(1 == v2.get_allocator().get_personality());
+ VERIFY( it == v2.begin() );
}
int main()
Index: testsuite/23_containers/map/debug/construct5_neg.cc
===================================================================
--- testsuite/23_containers/map/debug/construct5_neg.cc (revision 0)
+++ testsuite/23_containers/map/debug/construct5_neg.cc (working copy)
@@ -0,0 +1,45 @@
+// Copyright (C) 2014 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/>.
+//
+// { dg-options "-std=gnu++11" }
+// { dg-do run { xfail *-*-* } }
+
+#include <debug/map>
+
+#include <testsuite_allocator.h>
+
+void test01()
+{
+ bool test __attribute__((unused)) = true;
+
+ typedef __gnu_test::uneq_allocator<std::pair<const int, int> > alloc_type;
+ typedef __gnu_debug::map<int, int, std::less<int>, alloc_type> test_type;
+
+ test_type v1(alloc_type(1));
+ v1.insert(std::make_pair(0, 0));
+ auto it = v1.begin();
+
+ test_type v2(std::move(v1), alloc_type(2));
+
+ VERIFY( it->first == 0 ); // Error, it is singular
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
Index: testsuite/23_containers/map/debug/move_assign_neg.cc
===================================================================
--- testsuite/23_containers/map/debug/move_assign_neg.cc (revision 0)
+++ testsuite/23_containers/map/debug/move_assign_neg.cc (working copy)
@@ -0,0 +1,47 @@
+// Copyright (C) 2014 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/>.
+//
+// { dg-options "-std=gnu++11" }
+// { dg-do run { xfail *-*-* } }
+
+#include <debug/map>
+#include <testsuite_allocator.h>
+
+void test01()
+{
+ bool test __attribute__((unused)) = true;
+
+ typedef __gnu_test::uneq_allocator<std::pair<const int, int> > alloc_type;
+ typedef __gnu_debug::map<int, int, std::less<int>, alloc_type> test_type;
+
+ test_type v1(alloc_type(1));
+ v1.insert(std::make_pair(0, 0));
+ auto it = v1.begin();
+
+ test_type v2(alloc_type(2));
+ v2.insert(std::make_pair(1, 1));
+
+ v2 = std::move(v1);
+
+ VERIFY( it == v2.begin() ); // Error, it is singular.
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
Index: testsuite/23_containers/map/debug/move_neg.cc
===================================================================
--- testsuite/23_containers/map/debug/move_neg.cc (revision 0)
+++ testsuite/23_containers/map/debug/move_neg.cc (working copy)
@@ -0,0 +1,48 @@
+// Copyright (C) 2014 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/>.
+
+// { dg-options "-std=gnu++11" }
+// { dg-do run { xfail *-*-* } }
+
+#include <debug/map>
+
+#include <testsuite_hooks.h>
+#include <testsuite_allocator.h>
+
+using __gnu_test::uneq_allocator;
+
+void test01()
+{
+ bool test __attribute__((unused)) = true;
+
+ typedef uneq_allocator<std::pair<const int, int> > alloc_type;
+ typedef __gnu_debug::map<int, int, std::less<int>, alloc_type> test_type;
+
+ test_type v1(alloc_type(1));
+ v1 = { { 0, 0 } };
+ auto it = v1.begin();
+
+ test_type v2(std::move(v1), alloc_type(2));
+
+ VERIFY( it->first == 0 );
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
Index: testsuite/23_containers/multimap/allocator/move.cc
===================================================================
--- testsuite/23_containers/multimap/allocator/move.cc (revision 209879)
+++ testsuite/23_containers/multimap/allocator/move.cc (working copy)
@@ -38,9 +38,13 @@
typedef std::multimap<T, U, Cmp, alloc_type> test_type;
test_type v1(alloc_type(1));
v1 = { test_type::value_type{} };
+ auto it = v1.begin();
+
test_type v2(std::move(v1));
+
VERIFY(1 == v1.get_allocator().get_personality());
VERIFY(1 == v2.get_allocator().get_personality());
+ VERIFY( it == v2.begin() );
}
void test02()
Index: testsuite/23_containers/multimap/allocator/move_assign.cc
===================================================================
--- testsuite/23_containers/multimap/allocator/move_assign.cc (revision 209879)
+++ testsuite/23_containers/multimap/allocator/move_assign.cc (working copy)
@@ -52,11 +52,13 @@
typedef std::multimap<T, U, Cmp, alloc_type> test_type;
test_type v1(alloc_type(1));
v1 = { test_type::value_type{} };
+ auto it = v1.begin();
test_type v2(alloc_type(2));
v2 = { test_type::value_type{} };
v2 = std::move(v1);
VERIFY(0 == v1.get_allocator().get_personality());
VERIFY(1 == v2.get_allocator().get_personality());
+ VERIFY( it == v2.begin() );
}
int main()
Index: testsuite/23_containers/multimap/debug/construct5_neg.cc
===================================================================
--- testsuite/23_containers/multimap/debug/construct5_neg.cc (revision 0)
+++ testsuite/23_containers/multimap/debug/construct5_neg.cc (working copy)
@@ -0,0 +1,45 @@
+// Copyright (C) 2014 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/>.
+//
+// { dg-options "-std=gnu++11" }
+// { dg-do run { xfail *-*-* } }
+
+#include <debug/map>
+
+#include <testsuite_allocator.h>
+
+void test01()
+{
+ bool test __attribute__((unused)) = true;
+
+ typedef __gnu_test::uneq_allocator<std::pair<const int, int> > alloc_type;
+ typedef __gnu_debug::multimap<int, int, std::less<int>, alloc_type> test_type;
+
+ test_type v1(alloc_type(1));
+ v1.insert(std::make_pair(0, 0));
+ auto it = v1.begin();
+
+ test_type v2(std::move(v1), alloc_type(2));
+
+ VERIFY( it->first == 0 ); // Error, it is singular
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
Index: testsuite/23_containers/multimap/debug/move_assign_neg.cc
===================================================================
--- testsuite/23_containers/multimap/debug/move_assign_neg.cc (revision 0)
+++ testsuite/23_containers/multimap/debug/move_assign_neg.cc (working copy)
@@ -0,0 +1,47 @@
+// Copyright (C) 2014 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/>.
+//
+// { dg-options "-std=gnu++11" }
+// { dg-do run { xfail *-*-* } }
+
+#include <debug/map>
+#include <testsuite_allocator.h>
+
+void test01()
+{
+ bool test __attribute__((unused)) = true;
+
+ typedef __gnu_test::uneq_allocator<std::pair<const int, int> > alloc_type;
+ typedef __gnu_debug::multimap<int, int, std::less<int>, alloc_type> test_type;
+
+ test_type v1(alloc_type(1));
+ v1.insert(std::make_pair(0, 0));
+ auto it = v1.begin();
+
+ test_type v2(alloc_type(2));
+ v2.insert(std::make_pair(1, 1));
+
+ v2 = std::move(v1);
+
+ VERIFY( it == v2.begin() ); // Error, it is singular.
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
Index: testsuite/23_containers/multimap/debug/move_neg.cc
===================================================================
--- testsuite/23_containers/multimap/debug/move_neg.cc (revision 0)
+++ testsuite/23_containers/multimap/debug/move_neg.cc (working copy)
@@ -0,0 +1,48 @@
+// Copyright (C) 2014 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/>.
+
+// { dg-options "-std=gnu++11" }
+// { dg-do run { xfail *-*-* } }
+
+#include <debug/map>
+
+#include <testsuite_hooks.h>
+#include <testsuite_allocator.h>
+
+using __gnu_test::uneq_allocator;
+
+void test01()
+{
+ bool test __attribute__((unused)) = true;
+
+ typedef uneq_allocator<std::pair<const int, int> > alloc_type;
+ typedef __gnu_debug::multimap<int, int, std::less<int>, alloc_type> test_type;
+
+ test_type v1(alloc_type(1));
+ v1 = { { 0, 0 } };
+ auto it = v1.begin();
+
+ test_type v2(std::move(v1), alloc_type(2));
+
+ VERIFY( it->first == 0 );
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
Index: testsuite/23_containers/multiset/allocator/move.cc
===================================================================
--- testsuite/23_containers/multiset/allocator/move.cc (revision 209879)
+++ testsuite/23_containers/multiset/allocator/move.cc (working copy)
@@ -36,9 +36,13 @@
typedef std::multiset<T, Cmp, alloc_type> test_type;
test_type v1(alloc_type(1));
v1 = { test_type::value_type{} };
+ auto it = v1.begin();
+
test_type v2(std::move(v1));
+
VERIFY(1 == v1.get_allocator().get_personality());
VERIFY(1 == v2.get_allocator().get_personality());
+ VERIFY( it == v2.begin() );
}
void test02()
Index: testsuite/23_containers/multiset/allocator/move_assign.cc
===================================================================
--- testsuite/23_containers/multiset/allocator/move_assign.cc (revision 209879)
+++ testsuite/23_containers/multiset/allocator/move_assign.cc (working copy)
@@ -50,11 +50,13 @@
typedef std::multiset<T, Cmp, alloc_type> test_type;
test_type v1(alloc_type(1));
v1 = { test_type::value_type{} };
+ auto it = v1.begin();
test_type v2(alloc_type(2));
v2 = { test_type::value_type{} };
v2 = std::move(v1);
VERIFY(0 == v1.get_allocator().get_personality());
VERIFY(1 == v2.get_allocator().get_personality());
+ VERIFY( it == v2.begin() );
}
int main()
Index: testsuite/23_containers/multiset/debug/construct5_neg.cc
===================================================================
--- testsuite/23_containers/multiset/debug/construct5_neg.cc (revision 0)
+++ testsuite/23_containers/multiset/debug/construct5_neg.cc (working copy)
@@ -0,0 +1,45 @@
+// Copyright (C) 2014 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/>.
+//
+// { dg-options "-std=gnu++11" }
+// { dg-do run { xfail *-*-* } }
+
+#include <debug/set>
+
+#include <testsuite_allocator.h>
+
+void test01()
+{
+ bool test __attribute__((unused)) = true;
+
+ typedef __gnu_test::uneq_allocator<int> alloc_type;
+ typedef __gnu_debug::multiset<int, std::less<int>, alloc_type> test_type;
+
+ test_type v1(alloc_type(1));
+ v1.insert(0);
+ auto it = v1.begin();
+
+ test_type v2(std::move(v1), alloc_type(2));
+
+ VERIFY( *it == 0 ); // Error, it is singular
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
Index: testsuite/23_containers/multiset/debug/move_assign_neg.cc
===================================================================
--- testsuite/23_containers/multiset/debug/move_assign_neg.cc (revision 0)
+++ testsuite/23_containers/multiset/debug/move_assign_neg.cc (working copy)
@@ -0,0 +1,47 @@
+// Copyright (C) 2014 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/>.
+//
+// { dg-options "-std=gnu++11" }
+// { dg-do run { xfail *-*-* } }
+
+#include <debug/set>
+#include <testsuite_allocator.h>
+
+void test01()
+{
+ bool test __attribute__((unused)) = true;
+
+ typedef __gnu_test::uneq_allocator<int> alloc_type;
+ typedef __gnu_debug::multiset<int, std::less<int>, alloc_type> test_type;
+
+ test_type v1(alloc_type(1));
+ v1.insert(0);
+ auto it = v1.begin();
+
+ test_type v2(alloc_type(2));
+ v2.insert(1);
+
+ v2 = std::move(v1);
+
+ VERIFY( it == v2.begin() ); // Error, it is singular.
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
Index: testsuite/23_containers/multiset/debug/move_neg.cc
===================================================================
--- testsuite/23_containers/multiset/debug/move_neg.cc (revision 0)
+++ testsuite/23_containers/multiset/debug/move_neg.cc (working copy)
@@ -0,0 +1,48 @@
+// Copyright (C) 2014 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/>.
+
+// { dg-options "-std=gnu++11" }
+// { dg-do run { xfail *-*-* } }
+
+#include <debug/set>
+
+#include <testsuite_hooks.h>
+#include <testsuite_allocator.h>
+
+using __gnu_test::uneq_allocator;
+
+void test01()
+{
+ bool test __attribute__((unused)) = true;
+
+ typedef uneq_allocator<int> alloc_type;
+ typedef __gnu_debug::multiset<int, std::less<int>, alloc_type> test_type;
+
+ test_type v1(alloc_type(1));
+ v1 = { 0 };
+ auto it = v1.begin();
+
+ test_type v2(std::move(v1), alloc_type(2));
+
+ VERIFY( *it == 0 );
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
Index: testsuite/23_containers/set/allocator/move.cc
===================================================================
--- testsuite/23_containers/set/allocator/move.cc (revision 209879)
+++ testsuite/23_containers/set/allocator/move.cc (working copy)
@@ -38,9 +38,13 @@
typedef std::set<T, Cmp, alloc_type> test_type;
test_type v1(alloc_type(1));
v1 = { test_type::value_type{} };
+ auto it = v1.begin();
+
test_type v2(std::move(v1));
+
VERIFY(1 == v1.get_allocator().get_personality());
VERIFY(1 == v2.get_allocator().get_personality());
+ VERIFY( it == v2.begin() );
}
void test02()
Index: testsuite/23_containers/set/allocator/move_assign.cc
===================================================================
--- testsuite/23_containers/set/allocator/move_assign.cc (revision 209879)
+++ testsuite/23_containers/set/allocator/move_assign.cc (working copy)
@@ -50,11 +50,13 @@
typedef std::set<T, Cmp, alloc_type> test_type;
test_type v1(alloc_type(1));
v1 = { test_type::value_type{} };
+ auto it = v1.begin();
test_type v2(alloc_type(2));
v2 = { test_type::value_type{} };
v2 = std::move(v1);
VERIFY(0 == v1.get_allocator().get_personality());
VERIFY(1 == v2.get_allocator().get_personality());
+ VERIFY( it == v2.begin() );
}
int main()
Index: testsuite/23_containers/set/debug/construct5_neg.cc
===================================================================
--- testsuite/23_containers/set/debug/construct5_neg.cc (revision 0)
+++ testsuite/23_containers/set/debug/construct5_neg.cc (working copy)
@@ -0,0 +1,45 @@
+// Copyright (C) 2014 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/>.
+//
+// { dg-options "-std=gnu++11" }
+// { dg-do run { xfail *-*-* } }
+
+#include <debug/set>
+
+#include <testsuite_allocator.h>
+
+void test01()
+{
+ bool test __attribute__((unused)) = true;
+
+ typedef __gnu_test::uneq_allocator<int> alloc_type;
+ typedef __gnu_debug::set<int, std::less<int>, alloc_type> test_type;
+
+ test_type v1(alloc_type(1));
+ v1.insert(0);
+ auto it = v1.begin();
+
+ test_type v2(std::move(v1), alloc_type(2));
+
+ VERIFY( *it == 0 ); // Error, it is singular
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
Index: testsuite/23_containers/set/debug/move_assign_neg.cc
===================================================================
--- testsuite/23_containers/set/debug/move_assign_neg.cc (revision 0)
+++ testsuite/23_containers/set/debug/move_assign_neg.cc (working copy)
@@ -0,0 +1,47 @@
+// Copyright (C) 2014 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/>.
+//
+// { dg-options "-std=gnu++11" }
+// { dg-do run { xfail *-*-* } }
+
+#include <debug/set>
+#include <testsuite_allocator.h>
+
+void test01()
+{
+ bool test __attribute__((unused)) = true;
+
+ typedef __gnu_test::uneq_allocator<int> alloc_type;
+ typedef __gnu_debug::set<int, std::less<int>, alloc_type> test_type;
+
+ test_type v1(alloc_type(1));
+ v1.insert(0);
+ auto it = v1.begin();
+
+ test_type v2(alloc_type(2));
+ v2.insert(1);
+
+ v2 = std::move(v1);
+
+ VERIFY( it == v2.begin() ); // Error, it is singular.
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
Index: testsuite/23_containers/set/debug/move_neg.cc
===================================================================
--- testsuite/23_containers/set/debug/move_neg.cc (revision 0)
+++ testsuite/23_containers/set/debug/move_neg.cc (working copy)
@@ -0,0 +1,48 @@
+// Copyright (C) 2014 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/>.
+
+// { dg-options "-std=gnu++11" }
+// { dg-do run { xfail *-*-* } }
+
+#include <debug/set>
+
+#include <testsuite_hooks.h>
+#include <testsuite_allocator.h>
+
+using __gnu_test::uneq_allocator;
+
+void test01()
+{
+ bool test __attribute__((unused)) = true;
+
+ typedef uneq_allocator<int> alloc_type;
+ typedef __gnu_debug::set<int, std::less<int>, alloc_type> test_type;
+
+ test_type v1(alloc_type(1));
+ v1 = { 0 };
+ auto it = v1.begin();
+
+ test_type v2(std::move(v1), alloc_type(2));
+
+ VERIFY( *it == 0 );
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
Index: testsuite/23_containers/unordered_map/allocator/move.cc
===================================================================
--- testsuite/23_containers/unordered_map/allocator/move.cc (revision 209879)
+++ testsuite/23_containers/unordered_map/allocator/move.cc (working copy)
@@ -45,9 +45,11 @@
test_type v1(alloc_type(1));
v1.emplace(std::piecewise_construct,
std::make_tuple(T()), std::make_tuple(T()));
+ auto it = v1.begin();
test_type v2(std::move(v1));
VERIFY(1 == v1.get_allocator().get_personality());
VERIFY(1 == v2.get_allocator().get_personality());
+ VERIFY( it == v2.begin() );
}
void test02()
Index: testsuite/23_containers/unordered_map/allocator/move_assign.cc
===================================================================
--- testsuite/23_containers/unordered_map/allocator/move_assign.cc (revision 209879)
+++ testsuite/23_containers/unordered_map/allocator/move_assign.cc (working copy)
@@ -66,6 +66,8 @@
v1.emplace(std::piecewise_construct,
std::make_tuple(1), std::make_tuple(1));
+ auto it = v1.begin();
+
test_type v2(alloc_type(2));
v2.emplace(std::piecewise_construct,
std::make_tuple(2), std::make_tuple(2));
@@ -79,6 +81,8 @@
VERIFY( counter_type::move_assign_count == 0 );
VERIFY( counter_type::destructor_count == 2 );
+
+ VERIFY( it == v2.begin() );
}
int main()
Index: testsuite/23_containers/unordered_map/debug/construct5_neg.cc
===================================================================
--- testsuite/23_containers/unordered_map/debug/construct5_neg.cc (revision 0)
+++ testsuite/23_containers/unordered_map/debug/construct5_neg.cc (working copy)
@@ -0,0 +1,47 @@
+// Copyright (C) 2014 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/>.
+//
+// { dg-options "-std=gnu++11" }
+// { dg-do run { xfail *-*-* } }
+
+#include <debug/unordered_map>
+
+#include <testsuite_allocator.h>
+
+void test01()
+{
+ bool test __attribute__((unused)) = true;
+
+ typedef __gnu_test::uneq_allocator<std::pair<const int, int>> alloc_type;
+ typedef __gnu_debug::unordered_map<int, int, std::hash<int>,
+ std::equal_to<int>,
+ alloc_type> test_type;
+
+ test_type v1(alloc_type(1));
+ v1.insert(std::make_pair(0, 0));
+ auto it = v1.begin();
+
+ test_type v2(std::move(v1), alloc_type(2));
+
+ VERIFY( it == v2.begin() ); // Error, it is singular.
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
Index: testsuite/23_containers/unordered_map/debug/move_assign_neg.cc
===================================================================
--- testsuite/23_containers/unordered_map/debug/move_assign_neg.cc (revision 0)
+++ testsuite/23_containers/unordered_map/debug/move_assign_neg.cc (working copy)
@@ -0,0 +1,48 @@
+// Copyright (C) 2014 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/>.
+//
+// { dg-options "-std=gnu++11" }
+// { dg-do run { xfail *-*-* } }
+
+#include <debug/unordered_map>
+#include <testsuite_allocator.h>
+
+void test01()
+{
+ bool test __attribute__((unused)) = true;
+
+ typedef __gnu_test::uneq_allocator<std::pair<const int, int> > alloc_type;
+ typedef __gnu_debug::unordered_map<int, int,
+ std::hash<int>, std::equal_to<int>,
+ alloc_type> test_type;
+
+ test_type v1(alloc_type(1));
+ v1.insert(std::make_pair(0, 0));
+ auto it = v1.begin();
+
+ test_type v2(alloc_type(2));
+
+ v2 = std::move(v1);
+
+ VERIFY( it == v2.begin() ); // Error, it is singular.
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
Index: testsuite/23_containers/unordered_map/debug/move_neg.cc
===================================================================
--- testsuite/23_containers/unordered_map/debug/move_neg.cc (revision 0)
+++ testsuite/23_containers/unordered_map/debug/move_neg.cc (working copy)
@@ -0,0 +1,49 @@
+// Copyright (C) 2014 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/>.
+
+// { dg-options "-std=gnu++11" }
+// { dg-do run { xfail *-*-* } }
+
+#include <debug/unordered_map>
+
+#include <testsuite_hooks.h>
+#include <testsuite_allocator.h>
+
+using __gnu_test::uneq_allocator;
+
+void test01()
+{
+ bool test __attribute__((unused)) = true;
+
+ typedef uneq_allocator<std::pair<const int, int> > alloc_type;
+ typedef __gnu_debug::unordered_map<
+ int, int, std::hash<int>, std::equal_to<int>, alloc_type> test_type;
+
+ test_type v1(alloc_type(1));
+ v1 = { { 0, 0 } };
+ auto it = v1.begin();
+
+ test_type v2(std::move(v1), alloc_type(2));
+
+ VERIFY( it->first == 0 );
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
Index: testsuite/23_containers/unordered_multimap/allocator/move.cc
===================================================================
--- testsuite/23_containers/unordered_multimap/allocator/move.cc (revision 209879)
+++ testsuite/23_containers/unordered_multimap/allocator/move.cc (working copy)
@@ -45,9 +45,11 @@
test_type v1(alloc_type(1));
v1.emplace(std::piecewise_construct,
std::make_tuple(T()), std::make_tuple(T()));
+ auto it = v1.begin();
test_type v2(std::move(v1));
VERIFY(1 == v1.get_allocator().get_personality());
VERIFY(1 == v2.get_allocator().get_personality());
+ VERIFY( it == v2.begin() );
}
void test02()
Index: testsuite/23_containers/unordered_multimap/allocator/move_assign.cc
===================================================================
--- testsuite/23_containers/unordered_multimap/allocator/move_assign.cc (revision 209879)
+++ testsuite/23_containers/unordered_multimap/allocator/move_assign.cc (working copy)
@@ -66,6 +66,8 @@
v1.emplace(std::piecewise_construct,
std::make_tuple(1), std::make_tuple(1));
+ auto it = v1.begin();
+
test_type v2(alloc_type(2));
v2.emplace(std::piecewise_construct,
std::make_tuple(2), std::make_tuple(2));
@@ -79,6 +81,8 @@
VERIFY( counter_type::move_assign_count == 0 );
VERIFY( counter_type::destructor_count == 2 );
+
+ VERIFY( it == v2.begin() );
}
int main()
Index: testsuite/23_containers/unordered_multimap/debug/construct5_neg.cc
===================================================================
--- testsuite/23_containers/unordered_multimap/debug/construct5_neg.cc (revision 0)
+++ testsuite/23_containers/unordered_multimap/debug/construct5_neg.cc (working copy)
@@ -0,0 +1,47 @@
+// Copyright (C) 2014 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/>.
+//
+// { dg-options "-std=gnu++11" }
+// { dg-do run { xfail *-*-* } }
+
+#include <debug/unordered_map>
+
+#include <testsuite_allocator.h>
+
+void test01()
+{
+ bool test __attribute__((unused)) = true;
+
+ typedef __gnu_test::uneq_allocator<std::pair<const int, int>> alloc_type;
+ typedef __gnu_debug::unordered_multimap<int, int,
+ std::hash<int>, std::equal_to<int>,
+ alloc_type> test_type;
+
+ test_type v1(alloc_type(1));
+ v1.insert(std::make_pair(0, 0));
+ auto it = v1.begin();
+
+ test_type v2(std::move(v1), alloc_type(2));
+
+ VERIFY( it == v2.begin() ); // Error, it is singular.
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
Index: testsuite/23_containers/unordered_multimap/debug/move_assign_neg.cc
===================================================================
--- testsuite/23_containers/unordered_multimap/debug/move_assign_neg.cc (revision 0)
+++ testsuite/23_containers/unordered_multimap/debug/move_assign_neg.cc (working copy)
@@ -0,0 +1,48 @@
+// Copyright (C) 2014 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/>.
+//
+// { dg-options "-std=gnu++11" }
+// { dg-do run { xfail *-*-* } }
+
+#include <debug/unordered_map>
+#include <testsuite_allocator.h>
+
+void test01()
+{
+ bool test __attribute__((unused)) = true;
+
+ typedef __gnu_test::uneq_allocator<std::pair<const int, int>> alloc_type;
+ typedef __gnu_debug::unordered_multimap<int, int, std::hash<int>,
+ std::equal_to<int>,
+ alloc_type> test_type;
+
+ test_type v1(alloc_type(1));
+ v1.insert(std::make_pair(0, 0));
+ auto it = v1.begin();
+
+ test_type v2(alloc_type(2));
+
+ v2 = std::move(v1);
+
+ VERIFY( it == v2.begin() ); // Error, it is singular.
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
Index: testsuite/23_containers/unordered_multimap/debug/move_neg.cc
===================================================================
--- testsuite/23_containers/unordered_multimap/debug/move_neg.cc (revision 0)
+++ testsuite/23_containers/unordered_multimap/debug/move_neg.cc (working copy)
@@ -0,0 +1,49 @@
+// Copyright (C) 2014 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/>.
+
+// { dg-options "-std=gnu++11" }
+// { dg-do run { xfail *-*-* } }
+
+#include <debug/unordered_map>
+
+#include <testsuite_hooks.h>
+#include <testsuite_allocator.h>
+
+using __gnu_test::uneq_allocator;
+
+void test01()
+{
+ bool test __attribute__((unused)) = true;
+
+ typedef uneq_allocator<std::pair<const int, int> > alloc_type;
+ typedef __gnu_debug::unordered_multimap<
+ int, int, std::hash<int>, std::equal_to<int>, alloc_type> test_type;
+
+ test_type v1(alloc_type(1));
+ v1 = { { 0, 0 } };
+ auto it = v1.begin();
+
+ test_type v2(std::move(v1), alloc_type(2));
+
+ VERIFY( it->first == 0 );
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
Index: testsuite/23_containers/unordered_multiset/allocator/move.cc
===================================================================
--- testsuite/23_containers/unordered_multiset/allocator/move.cc (revision 209879)
+++ testsuite/23_containers/unordered_multiset/allocator/move.cc (working copy)
@@ -44,9 +44,11 @@
typedef std::unordered_multiset<T, hash, equal_to, alloc_type> test_type;
test_type v1(alloc_type(1));
v1.insert(T());
+ auto it = v1.begin();
test_type v2(std::move(v1));
VERIFY(1 == v1.get_allocator().get_personality());
VERIFY(1 == v2.get_allocator().get_personality());
+ VERIFY( it == v2.begin() );
}
void test02()
Index: testsuite/23_containers/unordered_multiset/allocator/move_assign.cc
===================================================================
--- testsuite/23_containers/unordered_multiset/allocator/move_assign.cc (revision 209879)
+++ testsuite/23_containers/unordered_multiset/allocator/move_assign.cc (working copy)
@@ -63,6 +63,8 @@
test_type v1(alloc_type(1));
v1.emplace(0);
+ auto it = v1.begin();
+
test_type v2(alloc_type(2));
v2.emplace(0);
@@ -76,6 +78,8 @@
VERIFY( counter_type::move_count == 0 );
VERIFY( counter_type::copy_count == 0 );
VERIFY( counter_type::destructor_count == 1 );
+
+ VERIFY( it == v2.begin() );
}
int main()
Index: testsuite/23_containers/unordered_multiset/debug/construct5_neg.cc
===================================================================
--- testsuite/23_containers/unordered_multiset/debug/construct5_neg.cc (revision 0)
+++ testsuite/23_containers/unordered_multiset/debug/construct5_neg.cc (working copy)
@@ -0,0 +1,47 @@
+// Copyright (C) 2014 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/>.
+//
+// { dg-options "-std=gnu++11" }
+// { dg-do run { xfail *-*-* } }
+
+#include <debug/unordered_set>
+
+#include <testsuite_allocator.h>
+
+void test01()
+{
+ bool test __attribute__((unused)) = true;
+
+ typedef __gnu_test::uneq_allocator<int> alloc_type;
+ typedef __gnu_debug::unordered_multiset<int, std::hash<int>,
+ std::equal_to<int>,
+ alloc_type> test_type;
+
+ test_type v1(alloc_type(1));
+ v1.insert(0);
+ auto it = v1.begin();
+
+ test_type v2(std::move(v1), alloc_type(2));
+
+ VERIFY( it == v2.begin() ); // Error, it is singular
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
Index: testsuite/23_containers/unordered_multiset/debug/move_assign_neg.cc
===================================================================
--- testsuite/23_containers/unordered_multiset/debug/move_assign_neg.cc (revision 0)
+++ testsuite/23_containers/unordered_multiset/debug/move_assign_neg.cc (working copy)
@@ -0,0 +1,49 @@
+// Copyright (C) 2014 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/>.
+//
+// { dg-options "-std=gnu++11" }
+// { dg-do run { xfail *-*-* } }
+
+#include <debug/unordered_set>
+#include <testsuite_allocator.h>
+
+void test01()
+{
+ bool test __attribute__((unused)) = true;
+
+ typedef __gnu_test::uneq_allocator<int> alloc_type;
+ typedef __gnu_debug::unordered_multiset<int, std::hash<int>,
+ std::equal_to<int>,
+ alloc_type> test_type;
+
+ test_type v1(alloc_type(1));
+ v1.emplace(0);
+ auto it = v1.begin();
+
+ test_type v2(alloc_type(2));
+ v2.emplace(1);
+
+ v2 = std::move(v1);
+
+ VERIFY( it == v2.begin() ); // Error, it is singular.
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
Index: testsuite/23_containers/unordered_multiset/debug/move_neg.cc
===================================================================
--- testsuite/23_containers/unordered_multiset/debug/move_neg.cc (revision 0)
+++ testsuite/23_containers/unordered_multiset/debug/move_neg.cc (working copy)
@@ -0,0 +1,49 @@
+// Copyright (C) 2014 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/>.
+
+// { dg-options "-std=gnu++11" }
+// { dg-do run { xfail *-*-* } }
+
+#include <debug/unordered_set>
+
+#include <testsuite_hooks.h>
+#include <testsuite_allocator.h>
+
+using __gnu_test::uneq_allocator;
+
+void test01()
+{
+ bool test __attribute__((unused)) = true;
+
+ typedef uneq_allocator<int> alloc_type;
+ typedef __gnu_debug::unordered_multiset<
+ int, std::hash<int>, std::equal_to<int>, alloc_type> test_type;
+
+ test_type v1(alloc_type(1));
+ v1 = { 0 };
+ auto it = v1.begin();
+
+ test_type v2(std::move(v1), alloc_type(2));
+
+ VERIFY( *it == 0 );
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
Index: testsuite/23_containers/unordered_set/allocator/move.cc
===================================================================
--- testsuite/23_containers/unordered_set/allocator/move.cc (revision 209879)
+++ testsuite/23_containers/unordered_set/allocator/move.cc (working copy)
@@ -44,9 +44,11 @@
typedef std::unordered_set<T, hash, equal_to, alloc_type> test_type;
test_type v1(alloc_type(1));
v1.insert(T());
+ auto it = v1.begin();
test_type v2(std::move(v1));
VERIFY(1 == v1.get_allocator().get_personality());
VERIFY(1 == v2.get_allocator().get_personality());
+ VERIFY( it == v2.begin() );
}
void test02()
Index: testsuite/23_containers/unordered_set/allocator/move_assign.cc
===================================================================
--- testsuite/23_containers/unordered_set/allocator/move_assign.cc (revision 209879)
+++ testsuite/23_containers/unordered_set/allocator/move_assign.cc (working copy)
@@ -63,6 +63,8 @@
test_type v1(alloc_type(1));
v1.emplace(0);
+ auto it = v1.begin();
+
test_type v2(alloc_type(2));
v2.emplace(0);
@@ -76,6 +78,8 @@
VERIFY( counter_type::move_count == 0 );
VERIFY( counter_type::copy_count == 0 );
VERIFY( counter_type::destructor_count == 1 );
+
+ VERIFY( it == v2.begin() );
}
int main()
Index: testsuite/23_containers/unordered_set/debug/construct5_neg.cc
===================================================================
--- testsuite/23_containers/unordered_set/debug/construct5_neg.cc (revision 0)
+++ testsuite/23_containers/unordered_set/debug/construct5_neg.cc (working copy)
@@ -0,0 +1,45 @@
+// Copyright (C) 2014 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/>.
+//
+// { dg-options "-std=gnu++11" }
+// { dg-do run { xfail *-*-* } }
+
+#include <debug/unordered_set>
+
+#include <testsuite_allocator.h>
+
+void test01()
+{
+ bool test __attribute__((unused)) = true;
+
+ typedef __gnu_test::uneq_allocator<int> alloc_type;
+ typedef __gnu_debug::unordered_set<int, std::hash<int>,
+ std::equal_to<int>, alloc_type> test_type;
+ test_type v1(alloc_type(1));
+ v1.insert(0);
+ auto it = v1.begin();
+
+ test_type v2(std::move(v1), alloc_type(2));
+
+ VERIFY( it == v2.begin() ); // Error, it is singular
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
Index: testsuite/23_containers/unordered_set/debug/move_assign_neg.cc
===================================================================
--- testsuite/23_containers/unordered_set/debug/move_assign_neg.cc (revision 0)
+++ testsuite/23_containers/unordered_set/debug/move_assign_neg.cc (working copy)
@@ -0,0 +1,49 @@
+// Copyright (C) 2014 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/>.
+//
+// { dg-options "-std=gnu++11" }
+// { dg-do run { xfail *-*-* } }
+
+#include <debug/unordered_set>
+#include <testsuite_allocator.h>
+
+void test01()
+{
+ bool test __attribute__((unused)) = true;
+
+ typedef __gnu_test::uneq_allocator<int> alloc_type;
+ typedef __gnu_debug::unordered_set<int, std::hash<int>,
+ std::equal_to<int>,
+ alloc_type> test_type;
+
+ test_type v1(alloc_type(1));
+ v1.emplace(0);
+ auto it = v1.begin();
+
+ test_type v2(alloc_type(2));
+ v2.emplace(1);
+
+ v2 = std::move(v1);
+
+ VERIFY( it == v2.begin() ); // Error, it is singular.
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
Index: testsuite/23_containers/unordered_set/debug/move_neg.cc
===================================================================
--- testsuite/23_containers/unordered_set/debug/move_neg.cc (revision 0)
+++ testsuite/23_containers/unordered_set/debug/move_neg.cc (working copy)
@@ -0,0 +1,49 @@
+// Copyright (C) 2014 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/>.
+
+// { dg-options "-std=gnu++11" }
+// { dg-do run { xfail *-*-* } }
+
+#include <debug/unordered_set>
+
+#include <testsuite_hooks.h>
+#include <testsuite_allocator.h>
+
+using __gnu_test::uneq_allocator;
+
+void test01()
+{
+ bool test __attribute__((unused)) = true;
+
+ typedef uneq_allocator<int> alloc_type;
+ typedef __gnu_debug::unordered_set<
+ int, std::hash<int>, std::equal_to<int>, alloc_type> test_type;
+
+ test_type v1(alloc_type(1));
+ v1 = { 0 };
+ auto it = v1.begin();
+
+ test_type v2(std::move(v1), alloc_type(2));
+
+ VERIFY( *it == 0 );
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
Index: testsuite/23_containers/vector/debug/move_neg.cc
===================================================================
--- testsuite/23_containers/vector/debug/move_neg.cc (revision 0)
+++ testsuite/23_containers/vector/debug/move_neg.cc (working copy)
@@ -0,0 +1,48 @@
+// Copyright (C) 2014 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/>.
+
+// { dg-options "-std=gnu++11" }
+// { dg-do run { xfail *-*-* } }
+
+#include <debug/vector>
+
+#include <testsuite_hooks.h>
+#include <testsuite_allocator.h>
+
+using __gnu_test::uneq_allocator;
+
+void test01()
+{
+ bool test __attribute__((unused)) = true;
+
+ typedef uneq_allocator<int> alloc_type;
+ typedef __gnu_debug::vector<int, alloc_type> test_type;
+
+ test_type v1(alloc_type(1));
+ v1 = { 0 };
+ auto it = v1.begin();
+
+ test_type v2(std::move(v1), alloc_type(2));
+
+ VERIFY( *it == 0 );
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
Index: testsuite/util/debug/checks.h
===================================================================
--- testsuite/util/debug/checks.h (revision 209879)
+++ testsuite/util/debug/checks.h (working copy)
@@ -179,10 +179,8 @@
val_type *first = &v.front() + 1;
val_type *last = first + 2;
- cont_type c1(first, last);
- VERIFY(c1.size() == 2);
- cont_type c2(last, first); // Expected failure
+ cont_type c(last, first); // Expected failure
}
// Check that invalid range of debug random iterators is detected
@@ -206,10 +204,8 @@
typename vector_type::iterator first = v.begin() + 1;
typename vector_type::iterator last = first + 2;
- cont_type c1(first, last);
- VERIFY(c1.size() == 2);
- cont_type c2(last, first); // Expected failure
+ cont_type c(last, first); // Expected failure
}
// Check that invalid range of debug not random iterators is detected
@@ -233,10 +229,8 @@
typename list_type::iterator first = l.begin(); ++first;
typename list_type::iterator last = first; ++last; ++last;
- cont_type c1(first, last);
- VERIFY(c1.size() == 2);
- cont_type c2(last, first); // Expected failure
+ cont_type c(last, first); // Expected failure
}
template <typename _Cont>
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: debug container patch
2014-04-28 21:14 ` François Dumont
@ 2014-05-02 20:33 ` François Dumont
2014-05-06 14:05 ` Jonathan Wakely
1 sibling, 0 replies; 10+ messages in thread
From: François Dumont @ 2014-05-02 20:33 UTC (permalink / raw)
To: Jonathan Wakely; +Cc: libstdc++, gcc-patches
Hi Jonathan
I just wanted to make sure that you are aware that I preferred to
wait for another validation of the small modification I have done.
François
On 28/04/2014 23:07, François Dumont wrote:
> On 27/04/2014 15:39, Jonathan Wakely wrote:
>> On 17/04/14 22:43 +0200, François Dumont wrote:
>>> Hi
>>>
>>> Here is a patch to globally enhance debug containers implementation.
>>
>> François, sorry for the delay, this is a large patch and I wanted to
>> give it the time it deserves to review properly.
>
> No problem, I see that there are a lot of proposals lately.
>
>>
>> I understand why this is needed, but it changes the layout of the
>> classes in very significant ways, meaning the debug containers will
>> not be compatible across GCC releases. I'm OK with that now, but from
>> the next major GCC release I'd like to avoid that in future.
>
> I remember Paolo saying that there is no abi guaranty for debug mode
> this is why I didn't hesitate in making this proposal. Will there be
> one in the future ? I plan also breaking changes for profile mode to
> fix its very bad performance.
>
>>
>>> I noticed also that in std/c++11/debug.cc we have some methods
>>> qualified with noexcept while in a C++03 user code those methods
>>> will have a throw() qualification. Is that fine ?
>>
>> As I said in my last mail, yes, those specifications are compatible.
>> But I don't think your changes are doing what you think they are doing
>> in all cases. Using _GLIBCXX_NOEXCEPT does not expand to throw() in
>> C++03 mode, it expands to nothing.
>
> Yes, I discover this difference in one of your recent mail.
>
>>
>>> * include/debug/safe_unordered_container.tcc
>>
>> N.B. This file has no changes listed in the changelog entry.
>
> I reviewed the ChangeLog and limit modifications like in this file.
> Note however that patch have been generated with '-x -b' option to
> hide white space modifications. I clean usage of white chars in
> impacted files, replaced some white spaces with tabs and remove
> useless white spaces.
>
>>
>>> @@ -69,8 +75,26 @@
>>>
>>> // 23.2.1.1 construct/copy/destroy:
>>>
>>> - deque() : _Base() { }
>>> +#if __cplusplus < 201103L
>>> + deque()
>>> + : _Base() { }
>>>
>>> + deque(const deque& __x)
>>> + : _Base(__x) { }
>>> +
>>> + ~deque() _GLIBCXX_NOEXCEPT { }
>>
>> In C++03 mode the _GLIBCXX_NOEXCEPT macro expands to an empty string,
>> so it is useless in this chunk of code, which is only compiled for
>> C++03 mode. It should probably just be removed here (and in all the
>> other debug containers which use it in C++03-only code).
>
> Ok, I cleaned those. Did you mean removing the whole explicit
> destructor ? Is it a coding Standard to always explicitly implement
> the destructor or just a way to have Doxygen generate ?
>
>> + * before-begin ownership.*/
>>> + template<typename _SafeSequence>
>>> + void
>>> + _Safe_forward_list<_SafeSequence>::
>>> + _M_swap(_Safe_sequence_base& __other) noexcept
>>> + {
>>> + __gnu_cxx::__scoped_lock sentry(_M_this()._M_get_mutex());
>>
>> Shouldn't we be locking both containers' mutexes here?
>> As we do in src/c++11/debug.cc
>
> Good point, not a regression but nice to fix in this patch.
>
>>
>>> + forward_list(forward_list&& __list, const allocator_type& __al)
>>> + : _Safe(std::move(__list), __al),
>>> + _Base(std::move(__list), __al)
>>> + { }
>>
>> This makes me feel uneasy, seeing a moved-from object being used
>> again, but I don't think changing it to use static_casts to the two
>> base classes would look better, so let's leave it like that.
>
> That indeed looks scary, we replaced with:
>
> forward_list(forward_list&& __list, const allocator_type& __al)
> : _Safe(std::move(__list._M_safe()), __al),
> _Base(std::move(__list._M_base()), __al)
> { }
>
> it makes clearer the fact that we move each part.
>
>>
>>> Index: include/debug/safe_base.h
>>> ===================================================================
>>> --- include/debug/safe_base.h (revision 209446)
>>> +++ include/debug/safe_base.h (working copy)
>>> @@ -188,22 +188,18 @@
>>>
>>> protected:
>>> // Initialize with a version number of 1 and no iterators
>>> - _Safe_sequence_base()
>>> + _Safe_sequence_base() _GLIBCXX_NOEXCEPT
>>
>> This use of _GLIBCXX_NOEXCEPT are correct, if the intention is to be
>> noexcept in C++11 and have no exception specification in C++98/C++03.
>
> Yes, I preferred to use default implementation for special function in
> C++11 so I qualified as many things as possible noexcept so that
> resulting noexcept qualification depends only on the normal mode
> noexcept qualification.
>
>>
>>> : _M_iterators(0), _M_const_iterators(0), _M_version(1)
>>> { }
>>>
>>> #if __cplusplus >= 201103L
>>> _Safe_sequence_base(const _Safe_sequence_base&) noexcept
>>> : _Safe_sequence_base() { }
>>> -
>>> - _Safe_sequence_base(_Safe_sequence_base&& __x) noexcept
>>> - : _Safe_sequence_base()
>>> - { _M_swap(__x); }
>>> #endif
>>>
>>> /** Notify all iterators that reference this sequence that the
>>> sequence is being destroyed. */
>>> - ~_Safe_sequence_base()
>>> + ~_Safe_sequence_base() _GLIBCXX_NOEXCEPT
>>
>> This is redundant. In C++03 the macro expands to nothing, and in C++11
>> destructors are noexcept by default anyway, so the macro adds nothing.
>
> Ok, I didn't knew, I cleaned those then.
>
>>
>>> { this->_M_detach_all(); }
>>>
>>> /** Detach all iterators, leaving them singular. */
>>> @@ -231,7 +227,7 @@
>>> * one container now reference the other container.
>>> */
>>> void
>>> - _M_swap(_Safe_sequence_base& __x);
>>> + _M_swap(_Safe_sequence_base& __x) _GLIBCXX_NOEXCEPT;
>>
>> This is OK, if the intention is to only have an exc eption spec in
>> C++11.
>
> This is used in noexcept constructors so I prefer to make it
> noexcept too.
>
> I replaced this one with _GLIBCXX_USE_NOEXCEPT cause in
> src/c++11/debug.cc we always build it as noexcept, just in case it
> impacts the mangled name. I saw _GLIBCXX_NOTHROW in c++config but
> doesn't seem to be used.
>
>>
>>
>>> +#if __cplusplus >= 201103L
>>> + _Safe_container&
>>> + operator=(_Safe_container&& __x) noexcept
>>> + {
>>> + __glibcxx_check_self_move_assign(__x);
>>
>> N.B. I'm writing a paper for the next committee meeting to make it
>> clear that self-move-assignment is not undefined behaviour, so this
>> check will have to be removed in the future. At least your change
>> means there are fewer places to remove it from :-)
>> See http://gcc.gnu.org/PR59603 for some background.
>>
>> I only looked over the testsuite changes quickly, but they look good.
>>
>> The changes above are only minor, overall I like the proposal very
>> much. Thanks for working on this, one day our debug mode containers
>> will be perfect! :-)
>>
>
> Not yet, I will start submitting patches for the debug algos soon :-)
>
> Here is the patch again with all your remarks. Ok to commit with the
> following ChangeLog ?
>
> 2014-04-29 François Dumont <fdumont@gcc.gnu.org>
>
> * include/debug/macros.h [__glibcxx_check_equal_allocs]: Add
> parameter to pass the 2 instances to check allocator equality.
> * include/debug/safe_container.h: New, define _Safe_container<>.
> * include/Makefile.am: Add previous.
> * include/debug/deque (std::__debug::deque<>): Inherit
> _Safe_container<>. Use default implementation for all special
> functions.
> * include/debug/forward_list (std::__debug::forward_list<>):
> Likewise.
> * include/debug/list (std::__debug::list<>): Likewise.
> * include/debug/map.h (std::__debug::map<>): Likewise.
> * include/debug/multimap.h (std::__debug::multimap<>): Likewise.
> * include/debug/set.h (std::__debug::set<>): Likewise.
> * include/debug/multiset.h (std::__debug::multiset<>): Likewise.
> * include/debug/string (std::__debug::basic_string<>): Likewise.
> * include/debug/unordered_map
> (std::__debug::unordered_map<>): Likewise.
> (std::__debug::unordered_multimap<>): Likewise.
> * include/debug/unordered_set
> (std::__debug::unordered_set<>): Likewise.
> (std::__debug::unordered_multiset<>): Likewise.
> * include/debug/vector (std::__debug::vector<>): Likewise.
> * include/debug/safe_base.h (_Safe_sequence_base()): Add
> noexcept.
> (_Safe_sequence_base(_Safe_sequence_base&&): Remove.
> (~_Safe_sequence_base()): Add noexcept.
> * include/debug/safe_sequence.h
> (std::__debug::_Safe_node_sequence<>): New.
> * include/debug/safe_unordered_base.h
> (_Safe_unordered_container_base()): Add noexcept.
> (~_Safe_unordered_container_base()): Likewise.
> (_M_swap(_Safe_unordered_container_base&)): Likewise.
> * include/debug/safe_unordered_container.h:
> (_Safe_unordered_container<>::_M_invalidate_locals()): New.
> (_Safe_unordered_container<>::_M_invalidate_all()): New.
> * src/c++11/debug.cc: Limit includes, adapt methods noexcept
> qualifications.
> * testsuite/util/debug/checks.h (check_construct1): Just implement
> an invalid constructor invocation and no other operations
> potentially not supported by some types of container.
> (check_construct2): Likewise.
> (check_construct3): Likewise.
> * testsuite/23_containers/forward_list/allocator/move.cc: Add
> check on iterators to make sure they are correctly moved in debug
> mode.
> * testsuite/23_containers/forward_list/allocator/move_assign.cc:
> Likewise.
> * testsuite/23_containers/map/allocator/move.cc: Likewise.
> * testsuite/23_containers/map/allocator/move_assign.cc: Likewise.
> * testsuite/23_containers/multimap/allocator/move.cc: Likewise.
> * testsuite/23_containers/multimap/allocator/move_assign.cc:
> Likewise.
> * testsuite/23_containers/multiset/allocator/move.cc: Likewise.
> * testsuite/23_containers/multiset/allocator/move_assign.cc:
> Likewise.
> * testsuite/23_containers/set/allocator/move.cc: Likewise.
> * testsuite/23_containers/set/allocator/move_assign.cc: Likewise.
> * testsuite/23_containers/unordered_map/allocator/move.cc:
> Likewise.
> * testsuite/23_containers/unordered_map/allocator/move_assign.cc:
> Likewise.
> * testsuite/23_containers/unordered_multimap/allocator/move.cc:
> Likewise.
> *
> testsuite/23_containers/unordered_multimap/allocator/move_assign.cc:
> Likewise.
> * testsuite/23_containers/unordered_multiset/allocator/move.cc:
> Likewise.
> *
> testsuite/23_containers/unordered_multiset/allocator/move_assign.cc:
> Likewise.
> * testsuite/23_containers/unordered_set/allocator/move.cc:
> Likewise.
> * testsuite/23_containers/unordered_set/allocator/move_assign.cc:
> Likewise.
> * testsuite/23_containers/forward_list/debug/construct1_neg.cc:
> New.
> * testsuite/23_containers/forward_list/debug/construct2_neg.cc:
> New.
> * testsuite/23_containers/forward_list/debug/construct3_neg.cc:
> New.
> * testsuite/23_containers/forward_list/debug/construct4_neg.cc:
> New.
> * testsuite/23_containers/forward_list/debug/move_assign_neg.cc:
> New.
> * testsuite/23_containers/forward_list/debug/move_neg.cc: New.
> * testsuite/23_containers/map/debug/construct5_neg.cc: New.
> * testsuite/23_containers/map/debug/move_assign_neg.cc: New.
> * testsuite/23_containers/map/debug/move_neg.cc: New.
> * testsuite/23_containers/multimap/debug/construct5_neg.cc: New.
> * testsuite/23_containers/multimap/debug/move_assign_neg.cc: New.
> * testsuite/23_containers/multimap/debug/move_neg.cc: New.
> * testsuite/23_containers/multiset/debug/construct5_neg.cc: New.
> * testsuite/23_containers/multiset/debug/move_assign_neg.cc: New.
> * testsuite/23_containers/multiset/debug/move_neg.cc: New.
> * testsuite/23_containers/set/debug/construct5_neg.cc: New.
> * testsuite/23_containers/set/debug/move_assign_neg.cc: New.
> * testsuite/23_containers/set/debug/move_neg.cc: New.
> * testsuite/23_containers/unordered_map/debug/construct5_neg.cc:
> New.
> * testsuite/23_containers/unordered_map/debug/move_assign_neg.cc:
> New.
> * testsuite/23_containers/unordered_map/debug/move_neg.cc: New.
> * testsuite/23_containers/unordered_multimap/debug/construct5_neg.cc:
> New.
> *
> testsuite/23_containers/unordered_multimap/debug/move_assign_neg.cc:
> New.
> * testsuite/23_containers/unordered_multimap/debug/move_neg.cc:
> New.
> * testsuite/23_containers/unordered_multiset/debug/construct5_neg.cc:
> New.
> *
> testsuite/23_containers/unordered_multiset/debug/move_assign_neg.cc:
> New.
> * testsuite/23_containers/unordered_multiset/debug/move_neg.cc:
> New.
> * testsuite/23_containers/unordered_set/debug/construct5_neg.cc:
> New.
> * testsuite/23_containers/unordered_set/debug/move_assign_neg.cc:
> New.
> * testsuite/23_containers/unordered_set/debug/move_neg.cc: New.
> * testsuite/23_containers/vector/debug/move_neg.cc: New.
>
>
> François
>
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: debug container patch
2014-04-28 21:14 ` François Dumont
2014-05-02 20:33 ` François Dumont
@ 2014-05-06 14:05 ` Jonathan Wakely
2014-05-07 1:15 ` Paolo Carlini
1 sibling, 1 reply; 10+ messages in thread
From: Jonathan Wakely @ 2014-05-06 14:05 UTC (permalink / raw)
To: François Dumont; +Cc: libstdc++, gcc-patches
On 28/04/14 23:07 +0200, François Dumont wrote:
>On 27/04/2014 15:39, Jonathan Wakely wrote:
>>On 17/04/14 22:43 +0200, François Dumont wrote:
>>>Hi
>>>
>>> Here is a patch to globally enhance debug containers implementation.
>>
>>François, sorry for the delay, this is a large patch and I wanted to
>>give it the time it deserves to review properly.
>
>No problem, I see that there are a lot of proposals lately.
Yes, I need to review patches faster!
>>I understand why this is needed, but it changes the layout of the
>>classes in very significant ways, meaning the debug containers will
>>not be compatible across GCC releases. I'm OK with that now, but from
>>the next major GCC release I'd like to avoid that in future.
>
>I remember Paolo saying that there is no abi guaranty for debug mode
>this is why I didn't hesitate in making this proposal. Will there be
>one in the future ?
Probably not. Originally the performance impact of debug mode was so
large that noone would use the containers except for special builds to
find specific problems. With some of your performance improvements
(unwrapping safe iterators once we know they are valid etc.) I wonder
if some people would choose to use e.g. __gnu_debug::vector directly
in "release builds". If anyone is doing that they would probably want
a stable ABI, but we don't guarantee that now, and probably shouldn't
guarantee it in future.
If people want extra safety without _GLIBCXX_DEBUG we should probably
consider the lightweight checks that have been implemented on the
Google branch.
> I plan also breaking changes for profile mode to
>fix its very bad performance.
I don't care about Profile mode at all! :-)
>I reviewed the ChangeLog and limit modifications like in this file.
>Note however that patch have been generated with '-x -b' option to
>hide white space modifications. I clean usage of white chars in
>impacted files, replaced some white spaces with tabs and remove
>useless white spaces.
Great, thank you.
>>In C++03 mode the _GLIBCXX_NOEXCEPT macro expands to an empty string,
>>so it is useless in this chunk of code, which is only compiled for
>>C++03 mode. It should probably just be removed here (and in all the
>>other debug containers which use it in C++03-only code).
>
>Ok, I cleaned those. Did you mean removing the whole explicit
>destructor ? Is it a coding Standard to always explicitly implement
>the destructor or just a way to have Doxygen generate ?
What you've done in your patch is fine.
We don't have any such coding standard for destructors though (AFAIK!)
To avoid losing the Doxygen comments we could put them on the
defaulted C++11 destructor. If we don't do so already we should
consider generating Doxygen docs with -std=gnu++11 (it's not the
default used by G++, but it would show more complete, and more modern,
API information).
>>+ * before-begin ownership.*/
>>>+ template<typename _SafeSequence>
>>>+ void
>>>+ _Safe_forward_list<_SafeSequence>::
>>>+ _M_swap(_Safe_sequence_base& __other) noexcept
>>>+ {
>>>+ __gnu_cxx::__scoped_lock sentry(_M_this()._M_get_mutex());
>>
>>Shouldn't we be locking both containers' mutexes here?
>>As we do in src/c++11/debug.cc
>
>Good point, not a regression but nice to fix in this patch.
Looks good now, thanks.
>That indeed looks scary, we replaced with:
>
> forward_list(forward_list&& __list, const allocator_type& __al)
> : _Safe(std::move(__list._M_safe()), __al),
> _Base(std::move(__list._M_base()), __al)
> { }
>
>it makes clearer the fact that we move each part.
Yes, this is much less scary :-)
Thanks, the revised patch is OK for trunk.
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: debug container patch
2014-05-06 14:05 ` Jonathan Wakely
@ 2014-05-07 1:15 ` Paolo Carlini
2014-05-07 13:17 ` Ramana Radhakrishnan
0 siblings, 1 reply; 10+ messages in thread
From: Paolo Carlini @ 2014-05-07 1:15 UTC (permalink / raw)
To: Jonathan Wakely, François Dumont; +Cc: libstdc++, gcc-patches
-- Francois,
remember to regenerate and commit the Makefile.in changes.
Thanks,
Paolo.
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: debug container patch
2014-05-07 1:15 ` Paolo Carlini
@ 2014-05-07 13:17 ` Ramana Radhakrishnan
2014-05-07 13:22 ` Jonathan Wakely
0 siblings, 1 reply; 10+ messages in thread
From: Ramana Radhakrishnan @ 2014-05-07 13:17 UTC (permalink / raw)
To: Paolo Carlini
Cc: Jonathan Wakely, François Dumont, libstdc++, gcc-patches
On Wed, May 7, 2014 at 2:13 AM, Paolo Carlini <paolo.carlini@oracle.com> wrote:
> -- Francois,
>
> remember to regenerate and commit the Makefile.in changes.
Can someone regenerate and commit the Makefile.in changes soon ? I'm
seeing testsuite failures thanks to missing debug/safe_container.h on
arm-none-linux-gnueabihf
I don't have access to a machine right now with the right versions of
autoconf and automake that can do this easily.
Ramana
>
> Thanks,
> Paolo.
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: debug container patch
2014-05-07 13:17 ` Ramana Radhakrishnan
@ 2014-05-07 13:22 ` Jonathan Wakely
2014-05-07 13:24 ` Ramana Radhakrishnan
0 siblings, 1 reply; 10+ messages in thread
From: Jonathan Wakely @ 2014-05-07 13:22 UTC (permalink / raw)
To: ramrad01; +Cc: Paolo Carlini, François Dumont, libstdc++, gcc-patches
On 07/05/14 14:17 +0100, Ramana Radhakrishnan wrote:
>Can someone regenerate and commit the Makefile.in changes soon ? I'm
>seeing testsuite failures thanks to missing debug/safe_container.h on
>arm-none-linux-gnueabihf
It was done hours ago by
http://gcc.gnu.org/ml/gcc-cvs/2014-05/msg00170.html
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: debug container patch
2014-05-07 13:22 ` Jonathan Wakely
@ 2014-05-07 13:24 ` Ramana Radhakrishnan
0 siblings, 0 replies; 10+ messages in thread
From: Ramana Radhakrishnan @ 2014-05-07 13:24 UTC (permalink / raw)
To: Jonathan Wakely
Cc: Paolo Carlini, François Dumont, libstdc++, gcc-patches
On Wed, May 7, 2014 at 2:22 PM, Jonathan Wakely <jwakely@redhat.com> wrote:
> On 07/05/14 14:17 +0100, Ramana Radhakrishnan wrote:
>>
>> Can someone regenerate and commit the Makefile.in changes soon ? I'm
>> seeing testsuite failures thanks to missing debug/safe_container.h on
>> arm-none-linux-gnueabihf
>
>
> It was done hours ago by
> http://gcc.gnu.org/ml/gcc-cvs/2014-05/msg00170.html
Sorry about the noise. I realized that just after I had hit send. not
enough coffee today.
Ramana
^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2014-05-07 13:24 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-04-17 20:52 debug container patch François Dumont
2014-04-18 10:59 ` Jonathan Wakely
2014-04-27 14:43 ` Jonathan Wakely
2014-04-28 21:14 ` François Dumont
2014-05-02 20:33 ` François Dumont
2014-05-06 14:05 ` Jonathan Wakely
2014-05-07 1:15 ` Paolo Carlini
2014-05-07 13:17 ` Ramana Radhakrishnan
2014-05-07 13:22 ` Jonathan Wakely
2014-05-07 13:24 ` Ramana Radhakrishnan
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).