From b101633fa6b8d7f47943857587c6f83c277482f7 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Fran=C3=A7ois=20Dumont?= Date: Sun, 2 Sep 2018 10:20:57 +0000 Subject: [PATCH] =?utf8?q?2018-09-02=20=20Fran=C3=A7ois=20Dumont=20=20?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit * include/debug/safe_iterator.h (_Safe_iterator<_It, _Seq, _Cat>::_Self): New. (_Safe_iterator<_It, _Seq, std::random_access_iterator_tag>::_Self): New. (_Safe_iterator<_It, _Seq, std::random_access_iterator_tag> ::_OtherSelf): New. (_GLIBCXX_DEBUG_VERIFY_OPERANDS, _GLIBCXX_DEBUG_VERIFY_EQ_OPERANDS) (_GLIBCXX_DEBUG_VERIFY_REL_OPERANDS) (_GLIBCXX_DEBUG_VERIFY_DIST_OPERANDS): Define macros. (_Safe_iterator<_It, _Seq, std::random_access_iterator_tag> ::operator+(difference_type)): Use latters, inline as friend. (_Safe_iterator<_It, _Seq, std::random_access_iterator_tag> ::operator-(difference_type)): Likewise. (operator==(const _Safe_iterator<>&, const _Safe_iterator<>&)): Likewise. (operator!=(const _Safe_iterator<>&, const _Safe_iterator<>&)): Likewise. (operator<(const _Safe_iterator<>&, const _Safe_iterator<>&)): Likewise. (operator<=(const _Safe_iterator<>&, const _Safe_iterator<>&)): Likewise. (operator>(const _Safe_iterator<>&, const _Safe_iterator<>&)): Likewise. (operator>=(const _Safe_iterator<>&, const _Safe_iterator<>&)): Likewise. (operator-(const _Safe_iterator<>&, const _Safe_iterator<>&)): Likewise. (operator+(difference_type, const _Safe_iterator<>&)): Likewise. (operator-(const _Safe_iterator<>&, difference_type)): Likewise. * include/debug/safe_iterator.tcc (_Safe_iterator<>::_M_can_advance(difference_type)): Take parameter by copy. * include/debug/safe_local_iterator.h (_Safe_local_iterator<_It, _Seq>::_Self): New. (_Safe_local_iterator<_It, _Seq>::_OtherSelf): New. (_GLIBCXX_DEBUG_VERIFY_OPERANDS): Define macro. (operator==(const _Safe_local_iterator<>&, const _Safe_local_iterator<>&)): Use latter, inline as friend. (operator!=(const _Safe_local_iterator<>&, const _Safe_local_iterator<>&)): Likewise. * testsuite/util/testsuite_containers.h: Include utility. (struct forward_members_unordered<_Tp, bool>): Remove 2nd template parameter. (forward_members_unordered<>::forward_members_unordered(value_type&)): Add using namespace std::rel_ops. Add iterator_concept_checks on local_iterator and const_local_iterator. Add asserts on comparison between const_local_iterator and local_iterator. (struct forward_members_unordered<_Tp, false>): Remove partial specialization. * testsuite/23_containers/forward_list/types/1.cc: New. * testsuite/23_containers/list/types/1.cc: New. From-SVN: r264039 --- libstdc++-v3/ChangeLog | 52 ++ libstdc++-v3/include/debug/safe_iterator.h | 451 +++++++----------- libstdc++-v3/include/debug/safe_iterator.tcc | 2 +- .../include/debug/safe_local_iterator.h | 121 ++--- .../23_containers/forward_list/types/1.cc | 34 ++ .../testsuite/23_containers/list/types/1.cc | 35 ++ .../testsuite/util/testsuite_containers.h | 118 ++++- 7 files changed, 429 insertions(+), 384 deletions(-) create mode 100644 libstdc++-v3/testsuite/23_containers/forward_list/types/1.cc create mode 100644 libstdc++-v3/testsuite/23_containers/list/types/1.cc diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index d45e4342978..0c6f4084ee3 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,55 @@ +2018-09-02 François Dumont + + * include/debug/safe_iterator.h + (_Safe_iterator<_It, _Seq, _Cat>::_Self): New. + (_Safe_iterator<_It, _Seq, std::random_access_iterator_tag>::_Self): + New. + (_Safe_iterator<_It, _Seq, std::random_access_iterator_tag> + ::_OtherSelf): New. + (_GLIBCXX_DEBUG_VERIFY_OPERANDS, _GLIBCXX_DEBUG_VERIFY_EQ_OPERANDS) + (_GLIBCXX_DEBUG_VERIFY_REL_OPERANDS) + (_GLIBCXX_DEBUG_VERIFY_DIST_OPERANDS): Define macros. + (_Safe_iterator<_It, _Seq, std::random_access_iterator_tag> + ::operator+(difference_type)): Use latters, inline as friend. + (_Safe_iterator<_It, _Seq, std::random_access_iterator_tag> + ::operator-(difference_type)): Likewise. + (operator==(const _Safe_iterator<>&, const _Safe_iterator<>&)): + Likewise. + (operator!=(const _Safe_iterator<>&, const _Safe_iterator<>&)): + Likewise. + (operator<(const _Safe_iterator<>&, const _Safe_iterator<>&)): Likewise. + (operator<=(const _Safe_iterator<>&, const _Safe_iterator<>&)): + Likewise. + (operator>(const _Safe_iterator<>&, const _Safe_iterator<>&)): Likewise. + (operator>=(const _Safe_iterator<>&, const _Safe_iterator<>&)): + Likewise. + (operator-(const _Safe_iterator<>&, const _Safe_iterator<>&)): Likewise. + (operator+(difference_type, const _Safe_iterator<>&)): Likewise. + (operator-(const _Safe_iterator<>&, difference_type)): Likewise. + * include/debug/safe_iterator.tcc + (_Safe_iterator<>::_M_can_advance(difference_type)): Take parameter by + copy. + * include/debug/safe_local_iterator.h + (_Safe_local_iterator<_It, _Seq>::_Self): New. + (_Safe_local_iterator<_It, _Seq>::_OtherSelf): New. + (_GLIBCXX_DEBUG_VERIFY_OPERANDS): Define macro. + (operator==(const _Safe_local_iterator<>&, + const _Safe_local_iterator<>&)): Use latter, inline as friend. + (operator!=(const _Safe_local_iterator<>&, + const _Safe_local_iterator<>&)): Likewise. + * testsuite/util/testsuite_containers.h: Include utility. + (struct forward_members_unordered<_Tp, bool>): Remove 2nd template + parameter. + (forward_members_unordered<>::forward_members_unordered(value_type&)): + Add using namespace std::rel_ops. + Add iterator_concept_checks on local_iterator and const_local_iterator. + Add asserts on comparison between const_local_iterator and + local_iterator. + (struct forward_members_unordered<_Tp, false>): Remove partial + specialization. + * testsuite/23_containers/forward_list/types/1.cc: New. + * testsuite/23_containers/list/types/1.cc: New. + 2018-09-01 Gerald Pfeifer * doc/xml/manual/profile_mode.xml: Update three ieeexplore.ieee.org diff --git a/libstdc++-v3/include/debug/safe_iterator.h b/libstdc++-v3/include/debug/safe_iterator.h index 86211b9ca3d..f0c2c204523 100644 --- a/libstdc++-v3/include/debug/safe_iterator.h +++ b/libstdc++-v3/include/debug/safe_iterator.h @@ -36,6 +36,28 @@ #include #include +#define _GLIBCXX_DEBUG_VERIFY_OPERANDS(_Lhs, _Rhs, _BadMsgId, _DiffMsgId) \ + _GLIBCXX_DEBUG_VERIFY(!_Lhs._M_singular() && !_Rhs._M_singular(), \ + _M_message(_BadMsgId) \ + ._M_iterator(_Lhs, #_Lhs) \ + ._M_iterator(_Rhs, #_Rhs)); \ + _GLIBCXX_DEBUG_VERIFY(_Lhs._M_can_compare(_Rhs), \ + _M_message(_DiffMsgId) \ + ._M_iterator(_Lhs, #_Lhs) \ + ._M_iterator(_Rhs, #_Rhs)) + +#define _GLIBCXX_DEBUG_VERIFY_EQ_OPERANDS(_Lhs, _Rhs) \ + _GLIBCXX_DEBUG_VERIFY_OPERANDS(_Lhs, _Rhs, __msg_iter_compare_bad, \ + __msg_compare_different) + +#define _GLIBCXX_DEBUG_VERIFY_REL_OPERANDS(_Lhs, _Rhs) \ + _GLIBCXX_DEBUG_VERIFY_OPERANDS(_Lhs, _Rhs, __msg_iter_order_bad, \ + __msg_order_different) + +#define _GLIBCXX_DEBUG_VERIFY_DIST_OPERANDS(_Lhs, _Rhs) \ + _GLIBCXX_DEBUG_VERIFY_OPERANDS(_Lhs, _Rhs, __msg_distance_bad, \ + __msg_distance_different) + namespace __gnu_debug { /** Helper struct to deal with sequence offering a before_begin @@ -180,9 +202,9 @@ namespace __gnu_debug template _Safe_iterator( const _Safe_iterator<_MutableIterator, _Sequence, - typename __gnu_cxx::__enable_if<_IsConstant::__value && - std::__are_same<_MutableIterator, _OtherIterator>::__value, - _Category>::__type>& __x) + typename __gnu_cxx::__enable_if<_IsConstant::__value && + std::__are_same<_MutableIterator, _OtherIterator>::__value, + _Category>::__type>& __x) _GLIBCXX_NOEXCEPT : _Iter_base(__x.base()) { @@ -374,7 +396,7 @@ namespace __gnu_debug // Can we advance the iterator @p __n steps (@p __n may be negative) bool - _M_can_advance(const difference_type& __n) const; + _M_can_advance(difference_type __n) const; // Is the iterator range [*this, __rhs) valid? bool @@ -421,6 +443,44 @@ namespace __gnu_debug bool _M_is_beginnest() const { return _BeforeBeginHelper<_Sequence>::_S_Is_Beginnest(*this); } + + // ------ Operators ------ + + typedef _Safe_iterator<_Iterator, _Sequence, iterator_category> _Self; + + friend bool + operator==(const _Self& __lhs, const _Self& __rhs) _GLIBCXX_NOEXCEPT + { + _GLIBCXX_DEBUG_VERIFY_EQ_OPERANDS(__lhs, __rhs); + return __lhs.base() == __rhs.base(); + } + + template + friend bool + operator==(const _Self& __lhs, + const _Safe_iterator<_IteR, _Sequence, iterator_category>& __rhs) + _GLIBCXX_NOEXCEPT + { + _GLIBCXX_DEBUG_VERIFY_EQ_OPERANDS(__lhs, __rhs); + return __lhs.base() == __rhs.base(); + } + + friend bool + operator!=(const _Self& __lhs, const _Self& __rhs) _GLIBCXX_NOEXCEPT + { + _GLIBCXX_DEBUG_VERIFY_EQ_OPERANDS(__lhs, __rhs); + return __lhs.base() != __rhs.base(); + } + + template + friend bool + operator!=(const _Self& __lhs, + const _Safe_iterator<_IteR, _Sequence, iterator_category>& __rhs) + _GLIBCXX_NOEXCEPT + { + _GLIBCXX_DEBUG_VERIFY_EQ_OPERANDS(__lhs, __rhs); + return __lhs.base() != __rhs.base(); + } }; template @@ -474,8 +534,8 @@ namespace __gnu_debug template _Safe_iterator( const _Safe_iterator<_MutableIterator, _Sequence, - typename __gnu_cxx::__enable_if<_Safe_base::_IsConstant::__value && - std::__are_same<_MutableIterator, _OtherIterator>::__value, + typename __gnu_cxx::__enable_if<_Safe_base::_IsConstant::__value && + std::__are_same<_MutableIterator, _OtherIterator>::__value, std::bidirectional_iterator_tag>::__type>& __x) _GLIBCXX_NOEXCEPT : _Safe_base(__x) @@ -574,6 +634,10 @@ namespace __gnu_debug std::bidirectional_iterator_tag> _Safe_base; typedef typename _Safe_base::_OtherIterator _OtherIterator; + typedef typename _Safe_base::_Self _Self; + typedef _Safe_iterator<_OtherIterator, _Sequence, + std::random_access_iterator_tag> _OtherSelf; + typedef typename _Safe_base::_Attach_single _Attach_single; _Safe_iterator(_Iterator __i, _Safe_sequence_base* __seq, _Attach_single) @@ -706,7 +770,7 @@ namespace __gnu_debug // ------ Random access iterator requirements ------ reference - operator[](const difference_type& __n) const _GLIBCXX_NOEXCEPT + operator[](difference_type __n) const _GLIBCXX_NOEXCEPT { _GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(__n) && this->_M_can_advance(__n + 1), @@ -716,7 +780,7 @@ namespace __gnu_debug } _Safe_iterator& - operator+=(const difference_type& __n) _GLIBCXX_NOEXCEPT + operator+=(difference_type __n) _GLIBCXX_NOEXCEPT { _GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(__n), _M_message(__msg_advance_oob) @@ -726,17 +790,8 @@ namespace __gnu_debug return *this; } - _Safe_iterator - operator+(const difference_type& __n) const _GLIBCXX_NOEXCEPT - { - _GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(__n), - _M_message(__msg_advance_oob) - ._M_iterator(*this)._M_integer(__n)); - return _Safe_iterator(this->base() + __n, this->_M_sequence); - } - _Safe_iterator& - operator-=(const difference_type& __n) _GLIBCXX_NOEXCEPT + operator-=(difference_type __n) _GLIBCXX_NOEXCEPT { _GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(-__n), _M_message(__msg_retreat_oob) @@ -746,288 +801,107 @@ namespace __gnu_debug return *this; } - _Safe_iterator - operator-(const difference_type& __n) const _GLIBCXX_NOEXCEPT + friend bool + operator<(const _Self& __lhs, const _Self& __rhs) _GLIBCXX_NOEXCEPT { - _GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(-__n), - _M_message(__msg_retreat_oob) - ._M_iterator(*this)._M_integer(__n)); - return _Safe_iterator(this->base() - __n, this->_M_sequence); + _GLIBCXX_DEBUG_VERIFY_REL_OPERANDS(__lhs, __rhs); + return __lhs.base() < __rhs.base(); } - }; - - template - inline bool - operator==(const _Safe_iterator<_IteratorL, _Sequence>& __lhs, - const _Safe_iterator<_IteratorR, _Sequence>& __rhs) - _GLIBCXX_NOEXCEPT - { - _GLIBCXX_DEBUG_VERIFY(!__lhs._M_singular() && !__rhs._M_singular(), - _M_message(__msg_iter_compare_bad) - ._M_iterator(__lhs, "lhs") - ._M_iterator(__rhs, "rhs")); - _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs), - _M_message(__msg_compare_different) - ._M_iterator(__lhs, "lhs") - ._M_iterator(__rhs, "rhs")); - return __lhs.base() == __rhs.base(); - } - - template - inline bool - operator==(const _Safe_iterator<_Iterator, _Sequence>& __lhs, - const _Safe_iterator<_Iterator, _Sequence>& __rhs) - _GLIBCXX_NOEXCEPT - { - _GLIBCXX_DEBUG_VERIFY(!__lhs._M_singular() && !__rhs._M_singular(), - _M_message(__msg_iter_compare_bad) - ._M_iterator(__lhs, "lhs") - ._M_iterator(__rhs, "rhs")); - _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs), - _M_message(__msg_compare_different) - ._M_iterator(__lhs, "lhs") - ._M_iterator(__rhs, "rhs")); - return __lhs.base() == __rhs.base(); - } - - template - inline bool - operator!=(const _Safe_iterator<_IteratorL, _Sequence>& __lhs, - const _Safe_iterator<_IteratorR, _Sequence>& __rhs) - _GLIBCXX_NOEXCEPT - { - _GLIBCXX_DEBUG_VERIFY(!__lhs._M_singular() && !__rhs._M_singular(), - _M_message(__msg_iter_compare_bad) - ._M_iterator(__lhs, "lhs") - ._M_iterator(__rhs, "rhs")); - _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs), - _M_message(__msg_compare_different) - ._M_iterator(__lhs, "lhs") - ._M_iterator(__rhs, "rhs")); - return __lhs.base() != __rhs.base(); - } - template - inline bool - operator!=(const _Safe_iterator<_Iterator, _Sequence>& __lhs, - const _Safe_iterator<_Iterator, _Sequence>& __rhs) - _GLIBCXX_NOEXCEPT - { - _GLIBCXX_DEBUG_VERIFY(!__lhs._M_singular() && !__rhs._M_singular(), - _M_message(__msg_iter_compare_bad) - ._M_iterator(__lhs, "lhs") - ._M_iterator(__rhs, "rhs")); - _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs), - _M_message(__msg_compare_different) - ._M_iterator(__lhs, "lhs") - ._M_iterator(__rhs, "rhs")); - return __lhs.base() != __rhs.base(); - } + friend bool + operator<(const _Self& __lhs, const _OtherSelf& __rhs) _GLIBCXX_NOEXCEPT + { + _GLIBCXX_DEBUG_VERIFY_REL_OPERANDS(__lhs, __rhs); + return __lhs.base() < __rhs.base(); + } - template - inline bool - operator<(const _Safe_iterator<_IteratorL, _Sequence, - std::random_access_iterator_tag>& __lhs, - const _Safe_iterator<_IteratorR, _Sequence, - std::random_access_iterator_tag>& __rhs) - _GLIBCXX_NOEXCEPT - { - _GLIBCXX_DEBUG_VERIFY(!__lhs._M_singular() && !__rhs._M_singular(), - _M_message(__msg_iter_order_bad) - ._M_iterator(__lhs, "lhs") - ._M_iterator(__rhs, "rhs")); - _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs), - _M_message(__msg_order_different) - ._M_iterator(__lhs, "lhs") - ._M_iterator(__rhs, "rhs")); - return __lhs.base() < __rhs.base(); - } + friend bool + operator<=(const _Self& __lhs, const _Self& __rhs) _GLIBCXX_NOEXCEPT + { + _GLIBCXX_DEBUG_VERIFY_REL_OPERANDS(__lhs, __rhs); + return __lhs.base() <= __rhs.base(); + } - template - inline bool - operator<(const _Safe_iterator<_Iterator, _Sequence, - std::random_access_iterator_tag>& __lhs, - const _Safe_iterator<_Iterator, _Sequence, - std::random_access_iterator_tag>& __rhs) - _GLIBCXX_NOEXCEPT - { - _GLIBCXX_DEBUG_VERIFY(!__lhs._M_singular() && !__rhs._M_singular(), - _M_message(__msg_iter_order_bad) - ._M_iterator(__lhs, "lhs") - ._M_iterator(__rhs, "rhs")); - _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs), - _M_message(__msg_order_different) - ._M_iterator(__lhs, "lhs") - ._M_iterator(__rhs, "rhs")); - return __lhs.base() < __rhs.base(); - } + friend bool + operator<=(const _Self& __lhs, const _OtherSelf& __rhs) _GLIBCXX_NOEXCEPT + { + _GLIBCXX_DEBUG_VERIFY_REL_OPERANDS(__lhs, __rhs); + return __lhs.base() <= __rhs.base(); + } - template - inline bool - operator<=(const _Safe_iterator<_IteratorL, _Sequence, - std::random_access_iterator_tag>& __lhs, - const _Safe_iterator<_IteratorR, _Sequence, - std::random_access_iterator_tag>& __rhs) - _GLIBCXX_NOEXCEPT - { - _GLIBCXX_DEBUG_VERIFY(!__lhs._M_singular() && !__rhs._M_singular(), - _M_message(__msg_iter_order_bad) - ._M_iterator(__lhs, "lhs") - ._M_iterator(__rhs, "rhs")); - _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs), - _M_message(__msg_order_different) - ._M_iterator(__lhs, "lhs") - ._M_iterator(__rhs, "rhs")); - return __lhs.base() <= __rhs.base(); - } + friend bool + operator>(const _Self& __lhs, const _Self& __rhs) _GLIBCXX_NOEXCEPT + { + _GLIBCXX_DEBUG_VERIFY_REL_OPERANDS(__lhs, __rhs); + return __lhs.base() > __rhs.base(); + } - template - inline bool - operator<=(const _Safe_iterator<_Iterator, _Sequence, - std::random_access_iterator_tag>& __lhs, - const _Safe_iterator<_Iterator, _Sequence, - std::random_access_iterator_tag>& __rhs) - _GLIBCXX_NOEXCEPT - { - _GLIBCXX_DEBUG_VERIFY(!__lhs._M_singular() && !__rhs._M_singular(), - _M_message(__msg_iter_order_bad) - ._M_iterator(__lhs, "lhs") - ._M_iterator(__rhs, "rhs")); - _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs), - _M_message(__msg_order_different) - ._M_iterator(__lhs, "lhs") - ._M_iterator(__rhs, "rhs")); - return __lhs.base() <= __rhs.base(); - } + friend bool + operator>(const _Self& __lhs, const _OtherSelf& __rhs) _GLIBCXX_NOEXCEPT + { + _GLIBCXX_DEBUG_VERIFY_REL_OPERANDS(__lhs, __rhs); + return __lhs.base() > __rhs.base(); + } - template - inline bool - operator>(const _Safe_iterator<_IteratorL, _Sequence, - std::random_access_iterator_tag>& __lhs, - const _Safe_iterator<_IteratorR, _Sequence, - std::random_access_iterator_tag>& __rhs) - _GLIBCXX_NOEXCEPT - { - _GLIBCXX_DEBUG_VERIFY(!__lhs._M_singular() && !__rhs._M_singular(), - _M_message(__msg_iter_order_bad) - ._M_iterator(__lhs, "lhs") - ._M_iterator(__rhs, "rhs")); - _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs), - _M_message(__msg_order_different) - ._M_iterator(__lhs, "lhs") - ._M_iterator(__rhs, "rhs")); - return __lhs.base() > __rhs.base(); - } + friend bool + operator>=(const _Self& __lhs, const _Self& __rhs) _GLIBCXX_NOEXCEPT + { + _GLIBCXX_DEBUG_VERIFY_REL_OPERANDS(__lhs, __rhs); + return __lhs.base() >= __rhs.base(); + } - template - inline bool - operator>(const _Safe_iterator<_Iterator, _Sequence, - std::random_access_iterator_tag>& __lhs, - const _Safe_iterator<_Iterator, _Sequence, - std::random_access_iterator_tag>& __rhs) - _GLIBCXX_NOEXCEPT - { - _GLIBCXX_DEBUG_VERIFY(!__lhs._M_singular() && !__rhs._M_singular(), - _M_message(__msg_iter_order_bad) - ._M_iterator(__lhs, "lhs") - ._M_iterator(__rhs, "rhs")); - _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs), - _M_message(__msg_order_different) - ._M_iterator(__lhs, "lhs") - ._M_iterator(__rhs, "rhs")); - return __lhs.base() > __rhs.base(); - } + friend bool + operator>=(const _Self& __lhs, const _OtherSelf& __rhs) _GLIBCXX_NOEXCEPT + { + _GLIBCXX_DEBUG_VERIFY_REL_OPERANDS(__lhs, __rhs); + return __lhs.base() >= __rhs.base(); + } - template - inline bool - operator>=(const _Safe_iterator<_IteratorL, _Sequence, - std::random_access_iterator_tag>& __lhs, - const _Safe_iterator<_IteratorR, _Sequence, - std::random_access_iterator_tag>& __rhs) - _GLIBCXX_NOEXCEPT - { - _GLIBCXX_DEBUG_VERIFY(!__lhs._M_singular() && !__rhs._M_singular(), - _M_message(__msg_iter_order_bad) - ._M_iterator(__lhs, "lhs") - ._M_iterator(__rhs, "rhs")); - _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs), - _M_message(__msg_order_different) - ._M_iterator(__lhs, "lhs") - ._M_iterator(__rhs, "rhs")); - return __lhs.base() >= __rhs.base(); - } + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // According to the resolution of DR179 not only the various comparison + // operators but also operator- must accept mixed iterator/const_iterator + // parameters. + friend difference_type + operator-(const _Self& __lhs, const _OtherSelf& __rhs) _GLIBCXX_NOEXCEPT + { + _GLIBCXX_DEBUG_VERIFY_DIST_OPERANDS(__lhs, __rhs); + return __lhs.base() - __rhs.base(); + } - template - inline bool - operator>=(const _Safe_iterator<_Iterator, _Sequence, - std::random_access_iterator_tag>& __lhs, - const _Safe_iterator<_Iterator, _Sequence, - std::random_access_iterator_tag>& __rhs) - _GLIBCXX_NOEXCEPT - { - _GLIBCXX_DEBUG_VERIFY(!__lhs._M_singular() && !__rhs._M_singular(), - _M_message(__msg_iter_order_bad) - ._M_iterator(__lhs, "lhs") - ._M_iterator(__rhs, "rhs")); - _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs), - _M_message(__msg_order_different) - ._M_iterator(__lhs, "lhs") - ._M_iterator(__rhs, "rhs")); - return __lhs.base() >= __rhs.base(); - } + friend difference_type + operator-(const _Self& __lhs, const _Self& __rhs) _GLIBCXX_NOEXCEPT + { + _GLIBCXX_DEBUG_VERIFY_DIST_OPERANDS(__lhs, __rhs); + return __lhs.base() - __rhs.base(); + } - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // According to the resolution of DR179 not only the various comparison - // operators but also operator- must accept mixed iterator/const_iterator - // parameters. - template - inline typename _Safe_iterator<_IteratorL, _Sequence, - std::random_access_iterator_tag>::difference_type - operator-(const _Safe_iterator<_IteratorL, _Sequence, - std::random_access_iterator_tag>& __lhs, - const _Safe_iterator<_IteratorR, _Sequence, - std::random_access_iterator_tag>& __rhs) - _GLIBCXX_NOEXCEPT - { - _GLIBCXX_DEBUG_VERIFY(!__lhs._M_singular() && !__rhs._M_singular(), - _M_message(__msg_distance_bad) - ._M_iterator(__lhs, "lhs") - ._M_iterator(__rhs, "rhs")); - _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs), - _M_message(__msg_distance_different) - ._M_iterator(__lhs, "lhs") - ._M_iterator(__rhs, "rhs")); - return __lhs.base() - __rhs.base(); - } + friend _Self + operator+(const _Self& __x, difference_type __n) _GLIBCXX_NOEXCEPT + { + _GLIBCXX_DEBUG_VERIFY(__x._M_can_advance(__n), + _M_message(__msg_advance_oob) + ._M_iterator(__x)._M_integer(__n)); + return _Safe_iterator(__x.base() + __n, __x._M_sequence); + } - template - inline typename _Safe_iterator<_Iterator, _Sequence, - std::random_access_iterator_tag>::difference_type - operator-(const _Safe_iterator<_Iterator, _Sequence, - std::random_access_iterator_tag>& __lhs, - const _Safe_iterator<_Iterator, _Sequence, - std::random_access_iterator_tag>& __rhs) - _GLIBCXX_NOEXCEPT - { - _GLIBCXX_DEBUG_VERIFY(!__lhs._M_singular() && !__rhs._M_singular(), - _M_message(__msg_distance_bad) - ._M_iterator(__lhs, "lhs") - ._M_iterator(__rhs, "rhs")); - _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs), - _M_message(__msg_distance_different) - ._M_iterator(__lhs, "lhs") - ._M_iterator(__rhs, "rhs")); - return __lhs.base() - __rhs.base(); - } + friend _Self + operator+(difference_type __n, const _Self& __x) _GLIBCXX_NOEXCEPT + { + _GLIBCXX_DEBUG_VERIFY(__x._M_can_advance(__n), + _M_message(__msg_advance_oob) + ._M_iterator(__x)._M_integer(__n)); + return _Safe_iterator(__n + __x.base(), __x._M_sequence); + } - template - inline _Safe_iterator<_Iterator, _Sequence, std::random_access_iterator_tag> - operator+(typename _Safe_iterator<_Iterator,_Sequence, - std::random_access_iterator_tag>::difference_type __n, - const _Safe_iterator<_Iterator, _Sequence, - std::random_access_iterator_tag>& __i) - _GLIBCXX_NOEXCEPT - { return __i + __n; } + friend _Self + operator-(const _Self& __x, difference_type __n) _GLIBCXX_NOEXCEPT + { + _GLIBCXX_DEBUG_VERIFY(__x._M_can_advance(-__n), + _M_message(__msg_retreat_oob) + ._M_iterator(__x)._M_integer(__n)); + return _Safe_iterator(__x.base() - __n, __x._M_sequence); + } + }; /** Safe iterators know how to check if they form a valid range. */ template @@ -1076,6 +950,11 @@ namespace __gnu_debug } // namespace __gnu_debug +#undef _GLIBCXX_DEBUG_VERIFY_DIST_OPERANDS +#undef _GLIBCXX_DEBUG_VERIFY_REL_OPERANDS +#undef _GLIBCXX_DEBUG_VERIFY_EQ_OPERANDS +#undef _GLIBCXX_DEBUG_VERIFY_OPERANDS + #include #endif diff --git a/libstdc++-v3/include/debug/safe_iterator.tcc b/libstdc++-v3/include/debug/safe_iterator.tcc index 2841583667f..2bfe134a3a4 100644 --- a/libstdc++-v3/include/debug/safe_iterator.tcc +++ b/libstdc++-v3/include/debug/safe_iterator.tcc @@ -82,7 +82,7 @@ namespace __gnu_debug template bool _Safe_iterator<_Iterator, _Sequence, _Category>:: - _M_can_advance(const difference_type& __n) const + _M_can_advance(difference_type __n) const { if (this->_M_singular()) return false; diff --git a/libstdc++-v3/include/debug/safe_local_iterator.h b/libstdc++-v3/include/debug/safe_local_iterator.h index 854518848f9..8e3ae443e9c 100644 --- a/libstdc++-v3/include/debug/safe_local_iterator.h +++ b/libstdc++-v3/include/debug/safe_local_iterator.h @@ -31,6 +31,20 @@ #include +#define _GLIBCXX_DEBUG_VERIFY_OPERANDS(_Lhs, _Rhs) \ + _GLIBCXX_DEBUG_VERIFY(!_Lhs._M_singular() && !_Rhs._M_singular(), \ + _M_message(__msg_iter_compare_bad) \ + ._M_iterator(_Lhs, "lhs") \ + ._M_iterator(_Rhs, "rhs")); \ + _GLIBCXX_DEBUG_VERIFY(_Lhs._M_can_compare(_Rhs), \ + _M_message(__msg_compare_different) \ + ._M_iterator(_Lhs, "lhs") \ + ._M_iterator(_Rhs, "rhs")); \ + _GLIBCXX_DEBUG_VERIFY(_Lhs._M_in_same_bucket(_Rhs), \ + _M_message(__msg_local_iter_compare_bad) \ + ._M_iterator(_Lhs, "lhs") \ + ._M_iterator(_Rhs, "rhs")) + namespace __gnu_debug { /** \brief Safe iterator wrapper. @@ -65,6 +79,9 @@ namespace __gnu_debug typename _Sequence::_Base::const_local_iterator>::__type _OtherIterator; + typedef _Safe_local_iterator _Self; + typedef _Safe_local_iterator<_OtherIterator, _Sequence> _OtherSelf; + struct _Attach_single { }; @@ -354,87 +371,35 @@ namespace __gnu_debug _M_in_same_bucket(const _Safe_local_iterator<_Other, _Sequence>& __other) const { return bucket() == __other.bucket(); } - }; - template - inline bool - operator==(const _Safe_local_iterator<_IteratorL, _Sequence>& __lhs, - const _Safe_local_iterator<_IteratorR, _Sequence>& __rhs) - { - _GLIBCXX_DEBUG_VERIFY(!__lhs._M_singular() && !__rhs._M_singular(), - _M_message(__msg_iter_compare_bad) - ._M_iterator(__lhs, "lhs") - ._M_iterator(__rhs, "rhs")); - _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs), - _M_message(__msg_compare_different) - ._M_iterator(__lhs, "lhs") - ._M_iterator(__rhs, "rhs")); - _GLIBCXX_DEBUG_VERIFY(__lhs._M_in_same_bucket(__rhs), - _M_message(__msg_local_iter_compare_bad) - ._M_iterator(__lhs, "lhs") - ._M_iterator(__rhs, "rhs")); - return __lhs.base() == __rhs.base(); - } + friend inline bool + operator==(const _Self& __lhs, const _OtherSelf& __rhs) noexcept + { + _GLIBCXX_DEBUG_VERIFY_OPERANDS(__lhs, __rhs); + return __lhs.base() == __rhs.base(); + } - template - inline bool - operator==(const _Safe_local_iterator<_Iterator, _Sequence>& __lhs, - const _Safe_local_iterator<_Iterator, _Sequence>& __rhs) - { - _GLIBCXX_DEBUG_VERIFY(!__lhs._M_singular() && !__rhs._M_singular(), - _M_message(__msg_iter_compare_bad) - ._M_iterator(__lhs, "lhs") - ._M_iterator(__rhs, "rhs")); - _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs), - _M_message(__msg_compare_different) - ._M_iterator(__lhs, "lhs") - ._M_iterator(__rhs, "rhs")); - _GLIBCXX_DEBUG_VERIFY(__lhs._M_in_same_bucket(__rhs), - _M_message(__msg_local_iter_compare_bad) - ._M_iterator(__lhs, "lhs") - ._M_iterator(__rhs, "rhs")); - return __lhs.base() == __rhs.base(); - } + friend inline bool + operator==(const _Self& __lhs, const _Self& __rhs) noexcept + { + _GLIBCXX_DEBUG_VERIFY_OPERANDS(__lhs, __rhs); + return __lhs.base() == __rhs.base(); + } - template - inline bool - operator!=(const _Safe_local_iterator<_IteratorL, _Sequence>& __lhs, - const _Safe_local_iterator<_IteratorR, _Sequence>& __rhs) - { - _GLIBCXX_DEBUG_VERIFY(!__lhs._M_singular() && !__rhs._M_singular(), - _M_message(__msg_iter_compare_bad) - ._M_iterator(__lhs, "lhs") - ._M_iterator(__rhs, "rhs")); - _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs), - _M_message(__msg_compare_different) - ._M_iterator(__lhs, "lhs") - ._M_iterator(__rhs, "rhs")); - _GLIBCXX_DEBUG_VERIFY(__lhs._M_in_same_bucket(__rhs), - _M_message(__msg_local_iter_compare_bad) - ._M_iterator(__lhs, "lhs") - ._M_iterator(__rhs, "rhs")); - return __lhs.base() != __rhs.base(); - } + friend inline bool + operator!=(const _Self& __lhs, const _OtherSelf& __rhs) noexcept + { + _GLIBCXX_DEBUG_VERIFY_OPERANDS(__lhs, __rhs); + return __lhs.base() != __rhs.base(); + } - template - inline bool - operator!=(const _Safe_local_iterator<_Iterator, _Sequence>& __lhs, - const _Safe_local_iterator<_Iterator, _Sequence>& __rhs) - { - _GLIBCXX_DEBUG_VERIFY(!__lhs._M_singular() && !__rhs._M_singular(), - _M_message(__msg_iter_compare_bad) - ._M_iterator(__lhs, "lhs") - ._M_iterator(__rhs, "rhs")); - _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs), - _M_message(__msg_compare_different) - ._M_iterator(__lhs, "lhs") - ._M_iterator(__rhs, "rhs")); - _GLIBCXX_DEBUG_VERIFY(__lhs._M_in_same_bucket(__rhs), - _M_message(__msg_local_iter_compare_bad) - ._M_iterator(__lhs, "lhs") - ._M_iterator(__rhs, "rhs")); - return __lhs.base() != __rhs.base(); - } + friend inline bool + operator!=(const _Self& __lhs, const _Self& __rhs) noexcept + { + _GLIBCXX_DEBUG_VERIFY_OPERANDS(__lhs, __rhs); + return __lhs.base() != __rhs.base(); + } + }; /** Safe local iterators know how to check if they form a valid range. */ template @@ -466,6 +431,8 @@ namespace __gnu_debug } // namespace __gnu_debug +#undef _GLIBCXX_DEBUG_VERIFY_OPERANDS + #include #endif diff --git a/libstdc++-v3/testsuite/23_containers/forward_list/types/1.cc b/libstdc++-v3/testsuite/23_containers/forward_list/types/1.cc new file mode 100644 index 00000000000..164b9c4a14b --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/forward_list/types/1.cc @@ -0,0 +1,34 @@ +// Copyright (C) 2018 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 +// . + +// { dg-do compile { target c++11 } } + +#include +#include + +int main() +{ + std::forward_list fl; + const std::forward_list cfl; + + fl.insert_after(fl.before_begin(), greedy_ops::X()); + fl.insert_after(fl.before_begin(), 1, greedy_ops::X()); + fl.insert_after(fl.before_begin(), cfl.begin(), cfl.end()); + fl = cfl; + + return 0; +} diff --git a/libstdc++-v3/testsuite/23_containers/list/types/1.cc b/libstdc++-v3/testsuite/23_containers/list/types/1.cc new file mode 100644 index 00000000000..a7bb217c623 --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/list/types/1.cc @@ -0,0 +1,35 @@ +// Copyright (C) 2018 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 +// . + +// { dg-do compile } + +#include +#include + +int main() +{ + std::list l; + const std::list cl; + + l.size(); + l.insert(l.begin(), greedy_ops::X()); + l.insert(l.begin(), 1, greedy_ops::X()); + l.insert(l.begin(), cl.begin(), cl.end()); + l = cl; + + return 0; +} diff --git a/libstdc++-v3/testsuite/util/testsuite_containers.h b/libstdc++-v3/testsuite/util/testsuite_containers.h index 759f4d6b79f..eadd43768d2 100644 --- a/libstdc++-v3/testsuite/util/testsuite_containers.h +++ b/libstdc++-v3/testsuite/util/testsuite_containers.h @@ -23,6 +23,7 @@ #include #include #include +#include // for rel_ops. // Container requirement testing. namespace __gnu_test @@ -170,33 +171,38 @@ namespace __gnu_test reverse_members(_Tp& container) { } }; + template::iterator_category> + struct iterator_concept_checks; + // DR 691. - template::is_unordered::value> + template struct forward_members_unordered { forward_members_unordered(typename _Tp::value_type& v) { + // Make sure that even if rel_ops is injected there is no ambiguity + // when comparing iterators. + using namespace std::rel_ops; + typedef _Tp test_type; test_type container; container.insert(v); + + iterator_concept_checks cc; + iterator_concept_checks ccc; + assert( container.cbegin(0) == container.begin(0) ); assert( container.cend(0) == container.end(0) ); const typename test_type::size_type bn = container.bucket(1); assert( container.cbegin(bn) != container.cend(bn) ); + assert( container.cbegin(bn) != container.end(bn) ); + assert( container.begin(bn) != container.cend(bn) ); } }; - template - struct forward_members_unordered<_Tp, false> - { - forward_members_unordered(_Tp& container) { } - }; - - template::iterator_category> - struct iterator_concept_checks; - template struct iterator_concept_checks<_Iterator, false, std::forward_iterator_tag> @@ -263,6 +269,82 @@ namespace __gnu_test } }; + template + struct forward_members + { + forward_members(_Tp& container) + { + // Make sure that even if rel_ops is injected there is no ambiguity + // when comparing iterators. + using namespace std::rel_ops; + + typedef traits<_Tp> traits_type; + iterator_concept_checks cc; + iterator_concept_checks ccc; + + assert( container.cbegin() == container.begin() ); + assert( container.end() == container.cend() ); + assert( container.cbegin() != container.cend() ); + assert( container.cbegin() != container.end() ); + assert( container.begin() != container.cend() ); + } + }; + + template::iterator_category> + struct category_members : forward_members<_Tp> + { + category_members(_Tp& container) + : forward_members<_Tp>(container) + { }; + }; + + template + struct category_members<_Tp, std::random_access_iterator_tag> + : forward_members<_Tp> + { + category_members(_Tp& container) + : forward_members<_Tp>(container) + { + // Make sure that even if rel_ops is injected there is no ambiguity + // when comparing iterators. + using namespace std::rel_ops; + + assert( !(container.begin() < container.begin()) ); + assert( !(container.cbegin() < container.cbegin()) ); + assert( !(container.cbegin() < container.begin()) ); + assert( !(container.begin() < container.cbegin()) ); + assert( container.begin() <= container.begin() ); + assert( container.cbegin() <= container.cbegin() ); + assert( container.cbegin() <= container.begin() ); + assert( container.begin() <= container.cbegin() ); + + assert( !(container.begin() > container.begin()) ); + assert( !(container.cbegin() > container.cbegin()) ); + assert( !(container.cbegin() > container.begin()) ); + assert( !(container.begin() > container.cbegin()) ); + assert( container.begin() >= container.begin() ); + assert( container.cbegin() >= container.cbegin() ); + assert( container.cbegin() >= container.begin() ); + assert( container.begin() >= container.cbegin() ); + + assert( container.begin() - container.begin() == 0 ); + assert( container.cbegin() - container.cbegin() == 0 ); + assert( container.cbegin() - container.begin() == 0 ); + assert( container.begin() - container.cbegin() == 0 ); + + assert( container.begin() + 0 == container.begin() ); + assert( container.cbegin() + 0 == container.cbegin() ); + assert( 0 + container.begin() == container.begin() ); + assert( 0 + container.cbegin() == container.cbegin() ); + assert( container.begin() - 0 == container.begin() ); + assert( container.cbegin() - 0 == container.cbegin() ); + } + }; + template struct citerator { @@ -273,21 +355,17 @@ namespace __gnu_test static test_type _S_container; // Unconditional. - struct forward_members + struct members : category_members<_Tp> { - forward_members() - { - assert( _S_container.cbegin() == _S_container.begin() ); - assert( _S_container.cend() == _S_container.end() ); - assert( _S_container.cbegin() != _S_container.cend() ); - } + members() : category_members<_Tp>(_S_container) + { } }; // Run test. citerator() { populate p(_S_container); - forward_members m1; + members m1; reverse_members m2(_S_container); } }; -- 2.30.2