From ebd4c354b39912dfa95b1288d28a658d671b2285 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Fran=C3=A7ois=20Dumont?= Date: Mon, 29 Sep 2014 21:22:17 +0000 Subject: [PATCH] re PR libstdc++/62313 (Data race in debug iterators) MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit 2014-09-29 François Dumont PR libstdc++/62313 * include/debug/safe_base.h (_Safe_iterator_base(const _Safe_iterator_base&)): Delete declaration. (_Safe_iterator_base& operator=(const _Safe_iterator_base&)): Likewise. * include/debug/safe_iterator.h (_Safe_iterator<>): Move normal iterator before _Safe_iterator_base in memory. Lock before modifying the iterator in numerous places. * include/debug/safe_local_iterator.h (_Safe_local_iterator_base(const _Safe_local_iterator_base&)): Delete declaration. (_Safe_local_iterator_base& operator=(const _Safe_local_iterator_base&)): Likewise. * include/debug/safe_unordered_base.h (_Safe_local_iterator<>): Move normal iterator before _Safe_iterator_base in memory. Lock before modifying the iterator in numerous places. * include/debug/forward_list (_Safe_forward_list<>::_M_swap_aux): Adapt. * include/debug/safe_sequence.tcc (_Safe_sequence<>::_M_transfer_from_if): Adapt. From-SVN: r215693 --- libstdc++-v3/ChangeLog | 21 +++ libstdc++-v3/include/debug/forward_list | 18 ++- libstdc++-v3/include/debug/safe_base.h | 6 - libstdc++-v3/include/debug/safe_iterator.h | 148 ++++++++++++------ .../include/debug/safe_local_iterator.h | 131 ++++++++++++---- libstdc++-v3/include/debug/safe_sequence.tcc | 29 ++-- .../include/debug/safe_unordered_base.h | 6 - 7 files changed, 247 insertions(+), 112 deletions(-) diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index f4478235623..6560372986f 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,24 @@ +2014-09-29 François Dumont + + PR libstdc++/62313 + * include/debug/safe_base.h + (_Safe_iterator_base(const _Safe_iterator_base&)): Delete declaration. + (_Safe_iterator_base& operator=(const _Safe_iterator_base&)): Likewise. + * include/debug/safe_iterator.h (_Safe_iterator<>): Move normal iterator + before _Safe_iterator_base in memory. Lock before modifying the iterator + in numerous places. + * include/debug/safe_local_iterator.h + (_Safe_local_iterator_base(const _Safe_local_iterator_base&)): Delete + declaration. + (_Safe_local_iterator_base& operator=(const _Safe_local_iterator_base&)): + Likewise. + * include/debug/safe_unordered_base.h (_Safe_local_iterator<>): Move + normal iterator before _Safe_iterator_base in memory. Lock before + modifying the iterator in numerous places. + * include/debug/forward_list (_Safe_forward_list<>::_M_swap_aux): Adapt. + * include/debug/safe_sequence.tcc + (_Safe_sequence<>::_M_transfer_from_if): Adapt. + 2014-09-25 Jonathan Wakely DR 1339 diff --git a/libstdc++-v3/include/debug/forward_list b/libstdc++-v3/include/debug/forward_list index c67fb464860..a46f6d44760 100644 --- a/libstdc++-v3/include/debug/forward_list +++ b/libstdc++-v3/include/debug/forward_list @@ -86,24 +86,26 @@ namespace __gnu_debug for (_Safe_iterator_base* __iter = __lhs_iterators; __iter;) { // Even iterator is cast to const_iterator, not a problem. - const_iterator* __victim = static_cast(__iter); + _Safe_iterator_base* __victim_base = __iter; + const_iterator* __victim = + static_cast(__victim_base); __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 (__lhs_iterators == __victim_base) + __lhs_iterators = __victim_base->_M_next; if (__bbegin_its) { - __victim->_M_next = __bbegin_its; - __bbegin_its->_M_prior = __victim; + __victim_base->_M_next = __bbegin_its; + __bbegin_its->_M_prior = __victim_base; } else - __last_bbegin = __victim; - __bbegin_its = __victim; + __last_bbegin = __victim_base; + __bbegin_its = __victim_base; } else - __victim->_M_sequence = &__lhs; + __victim_base->_M_sequence = &__lhs; } if (__bbegin_its) diff --git a/libstdc++-v3/include/debug/safe_base.h b/libstdc++-v3/include/debug/safe_base.h index fc589159a37..35e399dc535 100644 --- a/libstdc++-v3/include/debug/safe_base.h +++ b/libstdc++-v3/include/debug/safe_base.h @@ -95,12 +95,6 @@ namespace __gnu_debug : _M_sequence(0), _M_version(0), _M_prior(0), _M_next(0) { this->_M_attach(__x._M_sequence, __constant); } - _Safe_iterator_base& - operator=(const _Safe_iterator_base&); - - explicit - _Safe_iterator_base(const _Safe_iterator_base&); - ~_Safe_iterator_base() { this->_M_detach(); } /** For use in _Safe_iterator. */ diff --git a/libstdc++-v3/include/debug/safe_iterator.h b/libstdc++-v3/include/debug/safe_iterator.h index b6f136322f4..8083ed31719 100644 --- a/libstdc++-v3/include/debug/safe_iterator.h +++ b/libstdc++-v3/include/debug/safe_iterator.h @@ -109,16 +109,21 @@ namespace __gnu_debug * %_Safe_iterator has member functions for iterator invalidation, * attaching/detaching the iterator from sequences, and querying * the iterator's state. + * + * Note that _Iterator must be the first base class so that it gets + * initialized before the iterator is being attached to the container's list + * of iterators and it is being detached before _Iterator get + * destroyed. Otherwise it would result in a data race. */ template - class _Safe_iterator : public _Safe_iterator_base + class _Safe_iterator + : private _Iterator, + public _Safe_iterator_base { - typedef _Safe_iterator _Self; + typedef _Iterator _Iter_base; + typedef _Safe_iterator_base _Safe_base; typedef typename _Sequence::const_iterator _Const_iterator; - /// The underlying iterator - _Iterator _M_current; - /// Determine if this is a constant iterator. bool _M_constant() const @@ -126,6 +131,15 @@ namespace __gnu_debug typedef std::iterator_traits<_Iterator> _Traits; + struct _Attach_single + { }; + + _Safe_iterator(const _Iterator& __i, _Safe_sequence_base* __seq, + _Attach_single) + _GLIBCXX_NOEXCEPT + : _Iter_base(__i) + { _M_attach_single(__seq); } + public: typedef _Iterator iterator_type; typedef typename _Traits::iterator_category iterator_category; @@ -135,7 +149,7 @@ namespace __gnu_debug typedef typename _Traits::pointer pointer; /// @post the iterator is singular and unattached - _Safe_iterator() _GLIBCXX_NOEXCEPT : _M_current() { } + _Safe_iterator() _GLIBCXX_NOEXCEPT : _Iter_base() { } /** * @brief Safe iterator construction from an unsafe iterator and @@ -144,11 +158,11 @@ namespace __gnu_debug * @pre @p seq is not NULL * @post this is not singular */ - _Safe_iterator(const _Iterator& __i, const _Sequence* __seq) + _Safe_iterator(const _Iterator& __i, const _Safe_sequence_base* __seq) _GLIBCXX_NOEXCEPT - : _Safe_iterator_base(__seq, _M_constant()), _M_current(__i) + : _Iter_base(__i), _Safe_base(__seq, _M_constant()) { - _GLIBCXX_DEBUG_VERIFY(! this->_M_singular(), + _GLIBCXX_DEBUG_VERIFY(!this->_M_singular(), _M_message(__msg_init_singular) ._M_iterator(*this, "this")); } @@ -157,15 +171,16 @@ namespace __gnu_debug * @brief Copy construction. */ _Safe_iterator(const _Safe_iterator& __x) _GLIBCXX_NOEXCEPT - : _Safe_iterator_base(__x, _M_constant()), _M_current(__x._M_current) + : _Iter_base(__x.base()) { // _GLIBCXX_RESOLVE_LIB_DEFECTS // DR 408. Is vector > forbidden? _GLIBCXX_DEBUG_VERIFY(!__x._M_singular() - || __x._M_current == _Iterator(), + || __x.base() == _Iterator(), _M_message(__msg_init_copy_singular) ._M_iterator(*this, "this") ._M_iterator(__x, "other")); + _M_attach(__x._M_sequence); } #if __cplusplus >= 201103L @@ -173,16 +188,18 @@ namespace __gnu_debug * @brief Move construction. * @post __x is singular and unattached */ - _Safe_iterator(_Safe_iterator&& __x) noexcept : _M_current() + _Safe_iterator(_Safe_iterator&& __x) noexcept + : _Iter_base() { _GLIBCXX_DEBUG_VERIFY(!__x._M_singular() - || __x._M_current == _Iterator(), + || __x.base() == _Iterator(), _M_message(__msg_init_copy_singular) ._M_iterator(*this, "this") ._M_iterator(__x, "other")); - std::swap(_M_current, __x._M_current); - this->_M_attach(__x._M_sequence); + _Safe_sequence_base* __seq = __x._M_sequence; __x._M_detach(); + std::swap(base(), __x.base()); + _M_attach(__seq); } #endif @@ -196,7 +213,7 @@ namespace __gnu_debug typename __gnu_cxx::__enable_if<(std::__are_same<_MutableIterator, typename _Sequence::iterator::iterator_type>::__value), _Sequence>::__type>& __x) _GLIBCXX_NOEXCEPT - : _Safe_iterator_base(__x, _M_constant()), _M_current(__x.base()) + : _Iter_base(__x.base()) { // _GLIBCXX_RESOLVE_LIB_DEFECTS // DR 408. Is vector > forbidden? @@ -205,6 +222,7 @@ namespace __gnu_debug _M_message(__msg_init_const_singular) ._M_iterator(*this, "this") ._M_iterator(__x, "other")); + _M_attach(__x._M_sequence); } /** @@ -216,12 +234,24 @@ namespace __gnu_debug // _GLIBCXX_RESOLVE_LIB_DEFECTS // DR 408. Is vector > forbidden? _GLIBCXX_DEBUG_VERIFY(!__x._M_singular() - || __x._M_current == _Iterator(), + || __x.base() == _Iterator(), _M_message(__msg_copy_singular) ._M_iterator(*this, "this") ._M_iterator(__x, "other")); - _M_current = __x._M_current; - this->_M_attach(__x._M_sequence); + + if (this->_M_sequence && this->_M_sequence == __x._M_sequence) + { + __gnu_cxx::__scoped_lock __l(this->_M_get_mutex()); + base() = __x.base(); + _M_version = __x._M_sequence->_M_version; + } + else + { + _M_detach(); + base() = __x.base(); + _M_attach(__x._M_sequence); + } + return *this; } @@ -237,14 +267,26 @@ namespace __gnu_debug _M_message(__msg_self_move_assign) ._M_iterator(*this, "this")); _GLIBCXX_DEBUG_VERIFY(!__x._M_singular() - || __x._M_current == _Iterator(), + || __x.base() == _Iterator(), _M_message(__msg_copy_singular) ._M_iterator(*this, "this") ._M_iterator(__x, "other")); - _M_current = __x._M_current; - _M_attach(__x._M_sequence); + + if (this->_M_sequence && this->_M_sequence == __x._M_sequence) + { + __gnu_cxx::__scoped_lock __l(this->_M_get_mutex()); + base() = __x.base(); + _M_version = __x._M_sequence->_M_version; + } + else + { + _M_detach(); + base() = __x.base(); + _M_attach(__x._M_sequence); + } + __x._M_detach(); - __x._M_current = _Iterator(); + __x.base() = _Iterator(); return *this; } #endif @@ -259,7 +301,7 @@ namespace __gnu_debug _GLIBCXX_DEBUG_VERIFY(this->_M_dereferenceable(), _M_message(__msg_bad_deref) ._M_iterator(*this, "this")); - return *_M_current; + return *base(); } /** @@ -273,7 +315,7 @@ namespace __gnu_debug _GLIBCXX_DEBUG_VERIFY(this->_M_dereferenceable(), _M_message(__msg_bad_deref) ._M_iterator(*this, "this")); - return std::__addressof(*_M_current); + return std::__addressof(*base()); } // ------ Input iterator requirements ------ @@ -287,7 +329,8 @@ namespace __gnu_debug _GLIBCXX_DEBUG_VERIFY(this->_M_incrementable(), _M_message(__msg_bad_inc) ._M_iterator(*this, "this")); - ++_M_current; + __gnu_cxx::__scoped_lock(this->_M_get_mutex()); + ++base(); return *this; } @@ -301,9 +344,8 @@ namespace __gnu_debug _GLIBCXX_DEBUG_VERIFY(this->_M_incrementable(), _M_message(__msg_bad_inc) ._M_iterator(*this, "this")); - _Safe_iterator __tmp(*this); - ++_M_current; - return __tmp; + __gnu_cxx::__scoped_lock __l(this->_M_get_mutex()); + return _Safe_iterator(base()++, this->_M_sequence, _Attach_single()); } // ------ Bidirectional iterator requirements ------ @@ -317,7 +359,8 @@ namespace __gnu_debug _GLIBCXX_DEBUG_VERIFY(this->_M_decrementable(), _M_message(__msg_bad_dec) ._M_iterator(*this, "this")); - --_M_current; + __gnu_cxx::__scoped_lock __l(this->_M_get_mutex()); + --base(); return *this; } @@ -331,9 +374,8 @@ namespace __gnu_debug _GLIBCXX_DEBUG_VERIFY(this->_M_decrementable(), _M_message(__msg_bad_dec) ._M_iterator(*this, "this")); - _Safe_iterator __tmp(*this); - --_M_current; - return __tmp; + __gnu_cxx::__scoped_lock __l(this->_M_get_mutex()); + return _Safe_iterator(base()--, this->_M_sequence, _Attach_single()); } // ------ Random access iterator requirements ------ @@ -344,8 +386,7 @@ namespace __gnu_debug && this->_M_can_advance(__n+1), _M_message(__msg_iter_subscript_oob) ._M_iterator(*this)._M_integer(__n)); - - return _M_current[__n]; + return base()[__n]; } _Safe_iterator& @@ -354,16 +395,18 @@ namespace __gnu_debug _GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(__n), _M_message(__msg_advance_oob) ._M_iterator(*this)._M_integer(__n)); - _M_current += __n; + __gnu_cxx::__scoped_lock __l(this->_M_get_mutex()); + base() += __n; return *this; } _Safe_iterator operator+(const difference_type& __n) const _GLIBCXX_NOEXCEPT { - _Safe_iterator __tmp(*this); - __tmp += __n; - return __tmp; + _GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(__n), + _M_message(__msg_advance_oob) + ._M_iterator(*this)._M_integer(__n)); + return _Safe_iterator(base() + __n, this->_M_sequence); } _Safe_iterator& @@ -372,44 +415,45 @@ namespace __gnu_debug _GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(-__n), _M_message(__msg_retreat_oob) ._M_iterator(*this)._M_integer(__n)); - _M_current += -__n; + __gnu_cxx::__scoped_lock __l(this->_M_get_mutex()); + base() -= __n; return *this; } _Safe_iterator operator-(const difference_type& __n) const _GLIBCXX_NOEXCEPT { - _Safe_iterator __tmp(*this); - __tmp -= __n; - return __tmp; + _GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(-__n), + _M_message(__msg_retreat_oob) + ._M_iterator(*this)._M_integer(__n)); + return _Safe_iterator(base() - __n, this->_M_sequence); } // ------ Utilities ------ /** * @brief Return the underlying iterator */ - _Iterator - base() const _GLIBCXX_NOEXCEPT { return _M_current; } + _Iterator& + base() _GLIBCXX_NOEXCEPT { return *this; } + + const _Iterator& + base() const _GLIBCXX_NOEXCEPT { return *this; } /** * @brief Conversion to underlying non-debug iterator to allow * better interaction with non-debug containers. */ - operator _Iterator() const _GLIBCXX_NOEXCEPT { return _M_current; } + operator _Iterator() const _GLIBCXX_NOEXCEPT { return *this; } /** Attach iterator to the given sequence. */ void _M_attach(_Safe_sequence_base* __seq) - { - _Safe_iterator_base::_M_attach(__seq, _M_constant()); - } + { _Safe_base::_M_attach(__seq, _M_constant()); } /** Likewise, but not thread-safe. */ void _M_attach_single(_Safe_sequence_base* __seq) - { - _Safe_iterator_base::_M_attach_single(__seq, _M_constant()); - } + { _Safe_base::_M_attach_single(__seq, _M_constant()); } /// Is the iterator dereferenceable? bool diff --git a/libstdc++-v3/include/debug/safe_local_iterator.h b/libstdc++-v3/include/debug/safe_local_iterator.h index 50da161ebce..8fe16919c02 100644 --- a/libstdc++-v3/include/debug/safe_local_iterator.h +++ b/libstdc++-v3/include/debug/safe_local_iterator.h @@ -49,15 +49,15 @@ namespace __gnu_debug * the iterator's state. */ template - class _Safe_local_iterator : public _Safe_local_iterator_base + class _Safe_local_iterator + : private _Iterator + , public _Safe_local_iterator_base { - typedef _Safe_local_iterator _Self; + typedef _Iterator _Iter_base; + typedef _Safe_local_iterator_base _Safe_base; typedef typename _Sequence::const_local_iterator _Const_local_iterator; typedef typename _Sequence::size_type size_type; - /// The underlying iterator - _Iterator _M_current; - /// Determine if this is a constant iterator. bool _M_constant() const @@ -68,6 +68,14 @@ namespace __gnu_debug typedef std::iterator_traits<_Iterator> _Traits; + struct _Attach_single + { }; + + _Safe_local_iterator(const _Iterator& __i, _Safe_sequence_base* __cont, + _Attach_single) noexcept + : _Iter_base(__i) + { _M_attach_single(__cont); } + public: typedef _Iterator iterator_type; typedef typename _Traits::iterator_category iterator_category; @@ -77,7 +85,7 @@ namespace __gnu_debug typedef typename _Traits::pointer pointer; /// @post the iterator is singular and unattached - _Safe_local_iterator() : _M_current() { } + _Safe_local_iterator() noexcept : _Iter_base() { } /** * @brief Safe iterator construction from an unsafe iterator and @@ -86,8 +94,9 @@ namespace __gnu_debug * @pre @p seq is not NULL * @post this is not singular */ - _Safe_local_iterator(const _Iterator& __i, const _Sequence* __seq) - : _Safe_local_iterator_base(__seq, _M_constant()), _M_current(__i) + _Safe_local_iterator(const _Iterator& __i, + const _Safe_sequence_base* __cont) + : _Iter_base(__i), _Safe_base(__cont, _M_constant()) { _GLIBCXX_DEBUG_VERIFY(!this->_M_singular(), _M_message(__msg_init_singular) @@ -97,9 +106,8 @@ namespace __gnu_debug /** * @brief Copy construction. */ - _Safe_local_iterator(const _Safe_local_iterator& __x) - : _Safe_local_iterator_base(__x, _M_constant()), - _M_current(__x._M_current) + _Safe_local_iterator(const _Safe_local_iterator& __x) noexcept + : _Iter_base(__x.base()) { // _GLIBCXX_RESOLVE_LIB_DEFECTS // DR 408. Is vector > forbidden? @@ -108,6 +116,25 @@ namespace __gnu_debug _M_message(__msg_init_copy_singular) ._M_iterator(*this, "this") ._M_iterator(__x, "other")); + _M_attach(__x._M_sequence); + } + + /** + * @brief Move construction. + * @post __x is singular and unattached + */ + _Safe_local_iterator(_Safe_local_iterator&& __x) noexcept + : _Iter_base() + { + _GLIBCXX_DEBUG_VERIFY(!__x._M_singular() + || __x.base() == _Iterator(), + _M_message(__msg_init_copy_singular) + ._M_iterator(*this, "this") + ._M_iterator(__x, "other")); + auto __cont = __x._M_sequence; + __x._M_detach(); + std::swap(base(), __x.base()); + _M_attach(__cont); } /** @@ -121,8 +148,7 @@ namespace __gnu_debug _MutableIterator, typename _Sequence::local_iterator::iterator_type>::__value, _Sequence>::__type>& __x) - : _Safe_local_iterator_base(__x, _M_constant()), - _M_current(__x.base()) + : _Iter_base(__x.base()) { // _GLIBCXX_RESOLVE_LIB_DEFECTS // DR 408. Is vector > forbidden? @@ -131,6 +157,7 @@ namespace __gnu_debug _M_message(__msg_init_const_singular) ._M_iterator(*this, "this") ._M_iterator(__x, "other")); + _M_attach(__x._M_sequence); } /** @@ -146,8 +173,54 @@ namespace __gnu_debug _M_message(__msg_copy_singular) ._M_iterator(*this, "this") ._M_iterator(__x, "other")); - _M_current = __x._M_current; - this->_M_attach(__x._M_sequence); + + if (this->_M_sequence && this->_M_sequence == __x._M_sequence) + { + __gnu_cxx::__scoped_lock __l(this->_M_get_mutex()); + base() = __x.base(); + _M_version = __x._M_sequence->_M_version; + } + else + { + _M_detach(); + base() = __x.base(); + _M_attach(__x._M_sequence); + } + + return *this; + } + + /** + * @brief Move assignment. + * @post __x is singular and unattached + */ + _Safe_local_iterator& + operator=(_Safe_local_iterator&& __x) noexcept + { + _GLIBCXX_DEBUG_VERIFY(this != &__x, + _M_message(__msg_self_move_assign) + ._M_iterator(*this, "this")); + _GLIBCXX_DEBUG_VERIFY(!__x._M_singular() + || __x.base() == _Iterator(), + _M_message(__msg_copy_singular) + ._M_iterator(*this, "this") + ._M_iterator(__x, "other")); + + if (this->_M_sequence && this->_M_sequence == __x._M_sequence) + { + __gnu_cxx::__scoped_lock __l(this->_M_get_mutex()); + base() = __x.base(); + _M_version = __x._M_sequence->_M_version; + } + else + { + _M_detach(); + base() = __x.base(); + _M_attach(__x._M_sequence); + } + + __x._M_detach(); + __x.base() = _Iterator(); return *this; } @@ -161,7 +234,7 @@ namespace __gnu_debug _GLIBCXX_DEBUG_VERIFY(this->_M_dereferenceable(), _M_message(__msg_bad_deref) ._M_iterator(*this, "this")); - return *_M_current; + return *base(); } /** @@ -175,7 +248,7 @@ namespace __gnu_debug _GLIBCXX_DEBUG_VERIFY(this->_M_dereferenceable(), _M_message(__msg_bad_deref) ._M_iterator(*this, "this")); - return std::__addressof(*_M_current); + return std::__addressof(*base()); } // ------ Input iterator requirements ------ @@ -189,7 +262,8 @@ namespace __gnu_debug _GLIBCXX_DEBUG_VERIFY(this->_M_incrementable(), _M_message(__msg_bad_inc) ._M_iterator(*this, "this")); - ++_M_current; + __gnu_cxx::__scoped_lock __l(this->_M_get_mutex()); + ++base(); return *this; } @@ -203,39 +277,42 @@ namespace __gnu_debug _GLIBCXX_DEBUG_VERIFY(this->_M_incrementable(), _M_message(__msg_bad_inc) ._M_iterator(*this, "this")); - _Safe_local_iterator __tmp(*this); - ++_M_current; - return __tmp; + __gnu_cxx::__scoped_lock __l(this->_M_get_mutex()); + return _Safe_local_iterator(base()++, this->_M_sequence, + _Attach_single()); } // ------ Utilities ------ /** * @brief Return the underlying iterator */ - _Iterator - base() const { return _M_current; } + _Iterator& + base() noexcept { return *this; } + + const _Iterator& + base() const noexcept { return *this; } /** * @brief Return the bucket */ size_type - bucket() const { return _M_current._M_get_bucket(); } + bucket() const { return base()._M_get_bucket(); } /** * @brief Conversion to underlying non-debug iterator to allow * better interaction with non-debug containers. */ - operator _Iterator() const { return _M_current; } + operator _Iterator() const { return *this; } /** Attach iterator to the given sequence. */ void _M_attach(_Safe_sequence_base* __seq) - { _Safe_iterator_base::_M_attach(__seq, _M_constant()); } + { _Safe_base::_M_attach(__seq, _M_constant()); } /** Likewise, but not thread-safe. */ void _M_attach_single(_Safe_sequence_base* __seq) - { _Safe_iterator_base::_M_attach_single(__seq, _M_constant()); } + { _Safe_base::_M_attach_single(__seq, _M_constant()); } /// Is the iterator dereferenceable? bool diff --git a/libstdc++-v3/include/debug/safe_sequence.tcc b/libstdc++-v3/include/debug/safe_sequence.tcc index 5fef446359e..da9482a9443 100644 --- a/libstdc++-v3/include/debug/safe_sequence.tcc +++ b/libstdc++-v3/include/debug/safe_sequence.tcc @@ -81,42 +81,45 @@ namespace __gnu_debug for (_Safe_iterator_base* __iter = __from._M_iterators; __iter;) { - iterator* __victim = static_cast(__iter); + _Safe_iterator_base* __victim_base = __iter; + iterator* __victim = static_cast(__victim_base); __iter = __iter->_M_next; if (!__victim->_M_singular() && __pred(__victim->base())) { __victim->_M_detach_single(); if (__transfered_iterators) { - __victim->_M_next = __transfered_iterators; - __transfered_iterators->_M_prior = __victim; + __victim_base->_M_next = __transfered_iterators; + __transfered_iterators->_M_prior = __victim_base; } else - __last_iterator = __victim; - __victim->_M_sequence = this; - __victim->_M_version = this->_M_version; - __transfered_iterators = __victim; + __last_iterator = __victim_base; + __victim_base->_M_sequence = this; + __victim_base->_M_version = this->_M_version; + __transfered_iterators = __victim_base; } } for (_Safe_iterator_base* __iter2 = __from._M_const_iterators; __iter2;) { - const_iterator* __victim = static_cast(__iter2); + _Safe_iterator_base* __victim_base = __iter2; + const_iterator* __victim = + static_cast(__victim_base); __iter2 = __iter2->_M_next; if (!__victim->_M_singular() && __pred(__victim->base())) { __victim->_M_detach_single(); if (__transfered_const_iterators) { - __victim->_M_next = __transfered_const_iterators; - __transfered_const_iterators->_M_prior = __victim; + __victim_base->_M_next = __transfered_const_iterators; + __transfered_const_iterators->_M_prior = __victim_base; } else __last_const_iterator = __victim; - __victim->_M_sequence = this; - __victim->_M_version = this->_M_version; - __transfered_const_iterators = __victim; + __victim_base->_M_sequence = this; + __victim_base->_M_version = this->_M_version; + __transfered_const_iterators = __victim_base; } } } diff --git a/libstdc++-v3/include/debug/safe_unordered_base.h b/libstdc++-v3/include/debug/safe_unordered_base.h index 31c5c894cc1..380d7fe8602 100644 --- a/libstdc++-v3/include/debug/safe_unordered_base.h +++ b/libstdc++-v3/include/debug/safe_unordered_base.h @@ -71,12 +71,6 @@ namespace __gnu_debug bool __constant) { this->_M_attach(__x._M_sequence, __constant); } - _Safe_local_iterator_base& - operator=(const _Safe_local_iterator_base&); - - explicit - _Safe_local_iterator_base(const _Safe_local_iterator_base&); - ~_Safe_local_iterator_base() { this->_M_detach(); } _Safe_unordered_container_base* -- 2.30.2