re PR libstdc++/68222 (_Safe_iterator provides operators the wrapped iterator can't actually support)

2018-08-22  François Dumont  <fdumont@gcc.gnu.org>

	PR libstdc++/68222
	* include/debug/safe_iterator.h
	(_Safe_iterator<_It, _Sq, _Cat>): Add category template parameter.
	(_Safe_iterator<>::_Const_iterator): Remove.
	(_Safe_iterator<>::_IsConstant): New.
	(_Safe_iterator<>::_OtherIterator): New.
	(_Safe_iterator<_It, _Sq, _Cat>::_Safe_iterator<_MutIte>(
	const _Safe_iterator<_MutIte, _Sq, _Cat>&)): Add _IsConstant::__value in
	__gnu_cxx::__enable_if condition.
	(_Safe_iterator<_It, _Sq, _Cat>::_M_get_distance_to): New.
	(_Safe_iterator<_It, _Sq, _Cat>::_M_get_distance_from_begin): New.
	(_Safe_iterator<_It, _Sq, _Cat>::_M_get_distance_to_end): New.
	(_Safe_iterator<_It, _Sq, std::bidirectional_iterator_tag>): New.
	(_Safe_iterator<_It, _Sq, _Cat>::operator--()): Move...
	(_Safe_iterator<_It, _Sq, std::bidirectional_iterator_tag>
	::operator--()): ...here.
	(_Safe_iterator<_It, _Sq, _Cat>::operator--(int)): Move...
	(_Safe_iterator<_It, _Sq, std::bidirectional_iterator_tag>
	::operator--(int)): ...here.
	(_Safe_iterator<_It, _Sq, _Cat>::_M_decrementable()): Move...
	(_Safe_iterator<_It, _Sq, std::bidirectional_iterator_tag>
	::_M_decrementable()): ...here.
	(_Safe_iterator<_It, _Sq, std::random_access_iterator_tag>): New.
	(_Safe_iterator<_It, _Sq, _Cat>::operator[](const difference_type&)):
	Move...
	(_Safe_iterator<_It, _Sq, std::random_access_iterator_tag>
	::operator[](const difference_type&)): ...here.
	(_Safe_iterator<_It, _Sq, _Cat>::operator+=(const difference_type&)):
	Move...
	(_Safe_iterator<_It, _Sq, std::random_access_iterator_tag>
	::operator+=(const difference_type&)): ...here.
	(_Safe_iterator<_It, _Sq, _Cat>::operator+(const difference_type&)):
	Move...
	(_Safe_iterator<_It, _Sq, std::random_access_iterator_tag>
	::operator+(const difference_type&)): ...here.
	(_Safe_iterator<_It, _Sq, _Cat>::operator-=(const difference_type&)):
	Move...
	(_Safe_iterator<_It, _Sq, std::random_access_iterator_tag>
	::operator-=(const difference_type&)): ...here.
	(_Safe_iterator<_It, _Sq, _Cat>::operator-(const difference_type&)):
	Move...
	(_Safe_iterator<_It, _Sq, std::random_access_iterator_tag>
	::operator-(const difference_type&)): ...here.
	(operator<(const _Safe_iterator<>&, const _Safe_iterator<>&)):
	Constraint to random access iterators.
	(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 difference_type&, const _Safe_iterator<>&)): Likewise.
	(__check_dereferenceable(const _Safe_iterator<>&)): Remove.
	(__get_distance): Remove.
	(__get_distance_from_begin): Remove.
	(__get_distance_to_end): Remove.
	(struct __is_safe_random_iterator<_Safe_iterator<>>): Remove partial
	specialization.
	(__base(const _Safe_iterator<>&, std::input_iterator_tag)): Remove.
	(__base(const _Safe_iterator<>&, std::random_access_iterator_tag)): Remove.
	(__base(const _Safe_iterator<>&)): Constraint to random access iterator.
	* include/debug/safe_iterator.tcc
	(_Safe_iterator<>::_M_get_distance_from_begin()): New.
	(_Safe_iterator<>::_M_get_distance_to_end()): New.
	(_Safe_iterator<>::_M_get_distance_to(const _Safe_iterator<>&)): New.
	(_Safe_iterator<_It, _Seq, std::random_access_iterator_tag>
	::_M_valid_range): New.
	* include/debug/safe_local_iterator.h
	(_Safe_local_iterator<>::_Const_local_iterator): Remove.
	(_Safe_local_iterator<>::_IsConstant): New.
	(_Safe_local_iterator<>::_OtherIterator): New.
	(_Safe_local_iterator<_It, _Cont>::_Safe_local_iterator<_MutIte, _Cont>(
	const _Safe_local_iterator<_MutIte, _Seq>&)): Add _IsConstant::__value
	in __gnu_cxx::__enable_if condition. If singular compare base iterator
	with _MutIte rather than _It.
	(_Safe_local_iterator<>::_S_constant): Make constexpr.
	(_Safe_local_iterator<>::_M_get_distance_to): New.
	(__check_dereferenceable(const _Safe_local_iterator<>&)): Remove.
	(__get_distance(const _Safe_local_iterator<>&,
	const _Safe_local_iterator<>&, std::input_iterator_tag)): Remove.
	(__valid_range(const _Safe_local_iterator<>&,
	const _Safe_local_iterator<>&)): New.
	* include/debug/safe_local_iterator.tcc
	(_Safe_local_iterator<>::_M_get_distance_to): New.
	* include/debug/deque (std::__debug::deque<>): Add
	::__gnu_debug::_Safe_iterator<> friend declaration.
	* 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
	and add ::__gnu_debug::_Safe_local_iterator<> friend declaration.
	(std::__debug::unordered_multimap<>): Likewise.
	* include/debug/unordered_set (std::__debug::unordered_set<>): Likewise.
	(std::__debug::unordered_multiset<>): Likewise.
	* include/debug/formatter.h: Adapt.
	* include/debug/helper_functions.h
	(__gnu_debug::_Safe_local_iterator<>): Add declaration.
	(__get_distance<_Ite>(_Ite, _Ite, std::random_access_iterator_tag):
	Pass parameter by copy.
	(__get_distance<_Ite>(_Ite, _Ite, std::input_iterator_tag): Likewise.
	(__get_distance<_Ite>(_Ite, _Ite): Likewise.
	(__valid_range_aux<_Integral>): Pass _Integral by copy.
	(__valid_range<_InputIterator>): Pass _InputIterator by copy.
	(__valid_range<>(const _Safe_iterator<>&,
	const _Safe_iterator<>&, typename _Distance_traits<>::__type&)):
	Declare.
	(__valid_range(const _Safe_local_iterator<>&,
	const _Safe_local_iterator<>&, typename _Distance_traits<>::__type&)):
	Declare.
	(__valid_range<>(const _Safe_iterator<>&, const _Safe_iterator<>&)):
	Declare.
	(__valid_range(const _Safe_local_iterator<>&, const _Safe_local_iterator<>&)):
	Declare.
	(__can_advance): Adapt.
	(struct __is_safe_random_iterator<>): Remove.
	(struct _SIter_base<>): Remove.
	* include/debug/functions.h: Include <bits/stl_iterator.h>.
	(__check_dereferenceable): Remove.
	(__foreign_iterator_aux4, __foreign_iterator_aux3): Adapt.
	(__foreign_iterator_aux2, __foreign_iterator_aux): Adapt.
	(__foreign_iterator): Adapt.
	* include/debug/stl_iterator.h
	(__is_safe_random_iterator<std::reverse_iterator<>>): Remove.
	(__base(const std::reverse_iterator<_Safe_iterator<_It, _Sq>)):
	Constraint for random access iterators.
	(__niter_base): Adapt.
	* testsuite/util/testsuite_containers.h:
	Include <bits/boost_concept_check.h>.
	(iterator_concept_checks<_It, _Mutable, _Category>): New.
	(citerator<_Cont>::forward_members::forward_members()): Instantiate
	latter for container iterator and const_iterator.
	* testsuite/23_containers/list/68222_neg.cc: New.
	* testsuite/23_containers/vector/cons/destructible_debug_neg.cc: Adapt
	line number.
	* testsuite/23_containers/unordered_set/debug/debug_functions.cc:
	(test01): Remove.
	* testsuite/23_containers/vector/debug/debug_functions.cc (test01):
	Remove.

From-SVN: r263786
This commit is contained in:
François Dumont 2018-08-22 18:51:25 +00:00
parent 66f32b0e21
commit e9afbed0d6
25 changed files with 1095 additions and 539 deletions

View File

@ -1,3 +1,148 @@
2018-08-22 François Dumont <fdumont@gcc.gnu.org>
PR libstdc++/68222
* include/debug/safe_iterator.h
(_Safe_iterator<_It, _Sq, _Cat>): Add category template parameter.
(_Safe_iterator<>::_Const_iterator): Remove.
(_Safe_iterator<>::_IsConstant): New.
(_Safe_iterator<>::_OtherIterator): New.
(_Safe_iterator<_It, _Sq, _Cat>::_Safe_iterator<_MutIte>(
const _Safe_iterator<_MutIte, _Sq, _Cat>&)): Add _IsConstant::__value in
__gnu_cxx::__enable_if condition.
(_Safe_iterator<_It, _Sq, _Cat>::_M_get_distance_to): New.
(_Safe_iterator<_It, _Sq, _Cat>::_M_get_distance_from_begin): New.
(_Safe_iterator<_It, _Sq, _Cat>::_M_get_distance_to_end): New.
(_Safe_iterator<_It, _Sq, std::bidirectional_iterator_tag>): New.
(_Safe_iterator<_It, _Sq, _Cat>::operator--()): Move...
(_Safe_iterator<_It, _Sq, std::bidirectional_iterator_tag>
::operator--()): ...here.
(_Safe_iterator<_It, _Sq, _Cat>::operator--(int)): Move...
(_Safe_iterator<_It, _Sq, std::bidirectional_iterator_tag>
::operator--(int)): ...here.
(_Safe_iterator<_It, _Sq, _Cat>::_M_decrementable()): Move...
(_Safe_iterator<_It, _Sq, std::bidirectional_iterator_tag>
::_M_decrementable()): ...here.
(_Safe_iterator<_It, _Sq, std::random_access_iterator_tag>): New.
(_Safe_iterator<_It, _Sq, _Cat>::operator[](const difference_type&)):
Move...
(_Safe_iterator<_It, _Sq, std::random_access_iterator_tag>
::operator[](const difference_type&)): ...here.
(_Safe_iterator<_It, _Sq, _Cat>::operator+=(const difference_type&)):
Move...
(_Safe_iterator<_It, _Sq, std::random_access_iterator_tag>
::operator+=(const difference_type&)): ...here.
(_Safe_iterator<_It, _Sq, _Cat>::operator+(const difference_type&)):
Move...
(_Safe_iterator<_It, _Sq, std::random_access_iterator_tag>
::operator+(const difference_type&)): ...here.
(_Safe_iterator<_It, _Sq, _Cat>::operator-=(const difference_type&)):
Move...
(_Safe_iterator<_It, _Sq, std::random_access_iterator_tag>
::operator-=(const difference_type&)): ...here.
(_Safe_iterator<_It, _Sq, _Cat>::operator-(const difference_type&)):
Move...
(_Safe_iterator<_It, _Sq, std::random_access_iterator_tag>
::operator-(const difference_type&)): ...here.
(operator<(const _Safe_iterator<>&, const _Safe_iterator<>&)):
Constraint to random access iterators.
(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 difference_type&, const _Safe_iterator<>&)): Likewise.
(__check_dereferenceable(const _Safe_iterator<>&)): Remove.
(__get_distance): Remove.
(__get_distance_from_begin): Remove.
(__get_distance_to_end): Remove.
(struct __is_safe_random_iterator<_Safe_iterator<>>): Remove partial
specialization.
(__base(const _Safe_iterator<>&, std::input_iterator_tag)): Remove.
(__base(const _Safe_iterator<>&, std::random_access_iterator_tag)): Remove.
(__base(const _Safe_iterator<>&)): Constraint to random access iterator.
* include/debug/safe_iterator.tcc
(_Safe_iterator<>::_M_get_distance_from_begin()): New.
(_Safe_iterator<>::_M_get_distance_to_end()): New.
(_Safe_iterator<>::_M_get_distance_to(const _Safe_iterator<>&)): New.
(_Safe_iterator<_It, _Seq, std::random_access_iterator_tag>
::_M_valid_range): New.
* include/debug/safe_local_iterator.h
(_Safe_local_iterator<>::_Const_local_iterator): Remove.
(_Safe_local_iterator<>::_IsConstant): New.
(_Safe_local_iterator<>::_OtherIterator): New.
(_Safe_local_iterator<_It, _Cont>::_Safe_local_iterator<_MutIte, _Cont>(
const _Safe_local_iterator<_MutIte, _Seq>&)): Add _IsConstant::__value
in __gnu_cxx::__enable_if condition. If singular compare base iterator
with _MutIte rather than _It.
(_Safe_local_iterator<>::_S_constant): Make constexpr.
(_Safe_local_iterator<>::_M_get_distance_to): New.
(__check_dereferenceable(const _Safe_local_iterator<>&)): Remove.
(__get_distance(const _Safe_local_iterator<>&,
const _Safe_local_iterator<>&, std::input_iterator_tag)): Remove.
(__valid_range(const _Safe_local_iterator<>&,
const _Safe_local_iterator<>&)): New.
* include/debug/safe_local_iterator.tcc
(_Safe_local_iterator<>::_M_get_distance_to): New.
* include/debug/deque (std::__debug::deque<>): Add
::__gnu_debug::_Safe_iterator<> friend declaration.
* 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
and add ::__gnu_debug::_Safe_local_iterator<> friend declaration.
(std::__debug::unordered_multimap<>): Likewise.
* include/debug/unordered_set (std::__debug::unordered_set<>): Likewise.
(std::__debug::unordered_multiset<>): Likewise.
* include/debug/formatter.h: Adapt.
* include/debug/helper_functions.h
(__gnu_debug::_Safe_local_iterator<>): Add declaration.
(__get_distance<_Ite>(_Ite, _Ite, std::random_access_iterator_tag):
Pass parameter by copy.
(__get_distance<_Ite>(_Ite, _Ite, std::input_iterator_tag): Likewise.
(__get_distance<_Ite>(_Ite, _Ite): Likewise.
(__valid_range_aux<_Integral>): Pass _Integral by copy.
(__valid_range<_InputIterator>): Pass _InputIterator by copy.
(__valid_range<>(const _Safe_iterator<>&,
const _Safe_iterator<>&, typename _Distance_traits<>::__type&)):
Declare.
(__valid_range(const _Safe_local_iterator<>&,
const _Safe_local_iterator<>&, typename _Distance_traits<>::__type&)):
Declare.
(__valid_range<>(const _Safe_iterator<>&, const _Safe_iterator<>&)):
Declare.
(__valid_range(const _Safe_local_iterator<>&, const _Safe_local_iterator<>&)):
Declare.
(__can_advance): Adapt.
(struct __is_safe_random_iterator<>): Remove.
(struct _SIter_base<>): Remove.
* include/debug/functions.h: Include <bits/stl_iterator.h>.
(__check_dereferenceable): Remove.
(__foreign_iterator_aux4, __foreign_iterator_aux3): Adapt.
(__foreign_iterator_aux2, __foreign_iterator_aux): Adapt.
(__foreign_iterator): Adapt.
* include/debug/stl_iterator.h
(__is_safe_random_iterator<std::reverse_iterator<>>): Remove.
(__base(const std::reverse_iterator<_Safe_iterator<_It, _Sq>)):
Constraint for random access iterators.
(__niter_base): Adapt.
* testsuite/util/testsuite_containers.h:
Include <bits/boost_concept_check.h>.
(iterator_concept_checks<_It, _Mutable, _Category>): New.
(citerator<_Cont>::forward_members::forward_members()): Instantiate
latter for container iterator and const_iterator.
* testsuite/23_containers/list/68222_neg.cc: New.
* testsuite/23_containers/vector/cons/destructible_debug_neg.cc: Adapt
line number.
* testsuite/23_containers/unordered_set/debug/debug_functions.cc:
(test01): Remove.
* testsuite/23_containers/vector/debug/debug_functions.cc (test01):
Remove.
2018-08-22 Jonathan Wakely <jwakely@redhat.com>
PR libstdc++/77854

View File

@ -56,6 +56,9 @@ namespace __debug
typedef typename _Base::iterator _Base_iterator;
typedef __gnu_debug::_Equal_to<_Base_const_iterator> _Equal;
template<typename _ItT, typename _SeqT, typename _CatT>
friend class ::__gnu_debug::_Safe_iterator;
public:
typedef typename _Base::reference reference;
typedef typename _Base::const_reference const_reference;

View File

@ -76,7 +76,7 @@ namespace __gnu_debug
class _Safe_sequence_base;
template<typename _Iterator, typename _Sequence>
template<typename _Iterator, typename _Sequence, typename _Category>
class _Safe_iterator;
template<typename _Iterator, typename _Sequence>
@ -263,8 +263,8 @@ namespace __gnu_debug
_M_variant._M_string._M_value = __value;
}
template<typename _Iterator, typename _Sequence>
_Parameter(_Safe_iterator<_Iterator, _Sequence> const& __it,
template<typename _Iterator, typename _Sequence, typename _Category>
_Parameter(_Safe_iterator<_Iterator, _Sequence, _Category> const& __it,
const char* __name, _Is_iterator)
: _M_kind(__iterator), _M_variant()
{
@ -378,10 +378,10 @@ namespace __gnu_debug
= _S_reverse_state(_M_variant._M_iterator._M_state);
}
template<typename _Iterator, typename _Sequence>
_Parameter(std::reverse_iterator<_Safe_iterator<_Iterator,
_Sequence>> const& __it,
const char* __name, _Is_iterator)
template<typename _Iterator, typename _Sequence, typename _Category>
_Parameter(std::reverse_iterator<_Safe_iterator<_Iterator, _Sequence,
_Category>> const& __it,
const char* __name, _Is_iterator)
: _Parameter(__it.base(), __name, _Is_iterator{})
{
_M_variant._M_iterator._M_type
@ -396,10 +396,10 @@ namespace __gnu_debug
: _Parameter(__it.base(), __name, _Is_iterator{})
{ _M_variant._M_iterator._M_type = _GLIBCXX_TYPEID(__it); }
template<typename _Iterator, typename _Sequence>
_Parameter(std::move_iterator<_Safe_iterator<_Iterator,
_Sequence>> const& __it,
const char* __name, _Is_iterator)
template<typename _Iterator, typename _Sequence, typename _Category>
_Parameter(std::move_iterator<_Safe_iterator<_Iterator, _Sequence,
_Category>> const& __it,
const char* __name, _Is_iterator)
: _Parameter(__it.base(), __name, _Is_iterator{})
{
_M_variant._M_iterator._M_type

View File

@ -193,6 +193,9 @@ namespace __debug
typedef typename _Base::iterator _Base_iterator;
typedef typename _Base::const_iterator _Base_const_iterator;
template<typename _ItT, typename _SeqT, typename _CatT>
friend class ::__gnu_debug::_Safe_iterator;
public:
typedef typename _Base::reference reference;
typedef typename _Base::const_reference const_reference;

View File

@ -31,7 +31,9 @@
#include <bits/move.h> // for __addressof
#include <bits/stl_function.h> // for less
#if __cplusplus >= 201103L
# include <bits/stl_iterator.h> // for __miter_base
# include <type_traits> // for is_lvalue_reference and conditional.
#endif
@ -64,19 +66,6 @@ namespace __gnu_debug
__check_singular(const _Tp* __ptr)
{ return __ptr == 0; }
/** Assume that some arbitrary iterator is dereferenceable, because we
can't prove that it isn't. */
template<typename _Iterator>
inline bool
__check_dereferenceable(const _Iterator&)
{ return true; }
/** Non-NULL pointers are dereferenceable. */
template<typename _Tp>
inline bool
__check_dereferenceable(const _Tp* __ptr)
{ return __ptr; }
/* Checks that [first, last) is a valid range, and then returns
* __first. This routine is useful when we can't use a separate
* assertion statement because, e.g., we are in a constructor.
@ -95,10 +84,11 @@ namespace __gnu_debug
}
/* Handle the case where __other is a pointer to _Sequence::value_type. */
template<typename _Iterator, typename _Sequence>
template<typename _Iterator, typename _Sequence, typename _Category>
inline bool
__foreign_iterator_aux4(const _Safe_iterator<_Iterator, _Sequence>& __it,
const typename _Sequence::value_type* __other)
__foreign_iterator_aux4(
const _Safe_iterator<_Iterator, _Sequence, _Category>& __it,
const typename _Sequence::value_type* __other)
{
typedef const typename _Sequence::value_type* _PointerType;
typedef std::less<_PointerType> _Less;
@ -116,18 +106,20 @@ namespace __gnu_debug
}
/* Fallback overload for when we can't tell, assume it is valid. */
template<typename _Iterator, typename _Sequence>
template<typename _Iterator, typename _Sequence, typename _Category>
inline bool
__foreign_iterator_aux4(const _Safe_iterator<_Iterator, _Sequence>&, ...)
__foreign_iterator_aux4(
const _Safe_iterator<_Iterator, _Sequence, _Category>&, ...)
{ return true; }
/* Handle sequences with contiguous storage */
template<typename _Iterator, typename _Sequence, typename _InputIterator>
template<typename _Iterator, typename _Sequence, typename _Category,
typename _InputIterator>
inline bool
__foreign_iterator_aux3(const _Safe_iterator<_Iterator, _Sequence>& __it,
const _InputIterator& __other,
const _InputIterator& __other_end,
std::__true_type)
__foreign_iterator_aux3(
const _Safe_iterator<_Iterator, _Sequence, _Category>& __it,
const _InputIterator& __other, const _InputIterator& __other_end,
std::__true_type)
{
if (__other == __other_end)
return true; // inserting nothing is safe even if not foreign iters
@ -137,36 +129,46 @@ namespace __gnu_debug
}
/* Handle non-contiguous containers, assume it is valid. */
template<typename _Iterator, typename _Sequence, typename _InputIterator>
template<typename _Iterator, typename _Sequence, typename _Category,
typename _InputIterator>
inline bool
__foreign_iterator_aux3(const _Safe_iterator<_Iterator, _Sequence>&,
const _InputIterator&, const _InputIterator&,
std::__false_type)
__foreign_iterator_aux3(
const _Safe_iterator<_Iterator, _Sequence, _Category>&,
const _InputIterator&, const _InputIterator&,
std::__false_type)
{ return true; }
/** Handle debug iterators from the same type of container. */
template<typename _Iterator, typename _Sequence, typename _OtherIterator>
template<typename _Iterator, typename _Sequence, typename _Category,
typename _OtherIterator>
inline bool
__foreign_iterator_aux2(const _Safe_iterator<_Iterator, _Sequence>& __it,
const _Safe_iterator<_OtherIterator, _Sequence>& __other,
const _Safe_iterator<_OtherIterator, _Sequence>&)
__foreign_iterator_aux2(
const _Safe_iterator<_Iterator, _Sequence, _Category>& __it,
const _Safe_iterator<_OtherIterator, _Sequence, _Category>& __other,
const _Safe_iterator<_OtherIterator, _Sequence, _Category>&)
{ return __it._M_get_sequence() != __other._M_get_sequence(); }
/** Handle debug iterators from different types of container. */
template<typename _Iterator, typename _Sequence, typename _OtherIterator,
typename _OtherSequence>
template<typename _Iterator, typename _Sequence, typename _Category,
typename _OtherIterator, typename _OtherSequence,
typename _OtherCategory>
inline bool
__foreign_iterator_aux2(const _Safe_iterator<_Iterator, _Sequence>& __it,
const _Safe_iterator<_OtherIterator, _OtherSequence>&,
const _Safe_iterator<_OtherIterator, _OtherSequence>&)
__foreign_iterator_aux2(
const _Safe_iterator<_Iterator, _Sequence, _Category>&,
const _Safe_iterator<_OtherIterator, _OtherSequence,
_OtherCategory>&,
const _Safe_iterator<_OtherIterator, _OtherSequence,
_OtherCategory>&)
{ return true; }
/* Handle non-debug iterators. */
template<typename _Iterator, typename _Sequence, typename _InputIterator>
template<typename _Iterator, typename _Sequence, typename _Category,
typename _InputIterator>
inline bool
__foreign_iterator_aux2(const _Safe_iterator<_Iterator, _Sequence>& __it,
const _InputIterator& __other,
const _InputIterator& __other_end)
__foreign_iterator_aux2(
const _Safe_iterator<_Iterator, _Sequence, _Category>& __it,
const _InputIterator& __other,
const _InputIterator& __other_end)
{
#if __cplusplus < 201103L
typedef _Is_contiguous_sequence<_Sequence> __tag;
@ -181,31 +183,34 @@ namespace __gnu_debug
}
/* Handle the case where we aren't really inserting a range after all */
template<typename _Iterator, typename _Sequence, typename _Integral>
template<typename _Iterator, typename _Sequence, typename _Category,
typename _Integral>
inline bool
__foreign_iterator_aux(const _Safe_iterator<_Iterator, _Sequence>&,
_Integral, _Integral,
std::__true_type)
__foreign_iterator_aux(
const _Safe_iterator<_Iterator, _Sequence, _Category>&,
_Integral, _Integral, std::__true_type)
{ return true; }
/* Handle all iterators. */
template<typename _Iterator, typename _Sequence,
template<typename _Iterator, typename _Sequence, typename _Category,
typename _InputIterator>
inline bool
__foreign_iterator_aux(const _Safe_iterator<_Iterator, _Sequence>& __it,
_InputIterator __other, _InputIterator __other_end,
std::__false_type)
__foreign_iterator_aux(
const _Safe_iterator<_Iterator, _Sequence, _Category>& __it,
_InputIterator __other, _InputIterator __other_end,
std::__false_type)
{
return _Insert_range_from_self_is_safe<_Sequence>::__value
|| __foreign_iterator_aux2(__it, std::__miter_base(__other),
std::__miter_base(__other_end));
}
template<typename _Iterator, typename _Sequence,
template<typename _Iterator, typename _Sequence, typename _Category,
typename _InputIterator>
inline bool
__foreign_iterator(const _Safe_iterator<_Iterator, _Sequence>& __it,
_InputIterator __other, _InputIterator __other_end)
__foreign_iterator(
const _Safe_iterator<_Iterator, _Sequence, _Category>& __it,
_InputIterator __other, _InputIterator __other_end)
{
typedef typename std::__is_integer<_InputIterator>::__type _Integral;
return __foreign_iterator_aux(__it, __other, __other_end, _Integral());

View File

@ -37,9 +37,14 @@
namespace __gnu_debug
{
template<typename _Iterator, typename _Sequence>
template<typename _Iterator, typename _Sequence, typename _Category>
class _Safe_iterator;
#if __cplusplus >= 201103L
template<typename _Iterator, typename _Sequence>
class _Safe_local_iterator;
#endif
/** The precision to which we can calculate the distance between
* two iterators.
*/
@ -83,13 +88,13 @@ namespace __gnu_debug
*/
template<typename _Iterator>
inline typename _Distance_traits<_Iterator>::__type
__get_distance(const _Iterator& __lhs, const _Iterator& __rhs,
__get_distance(_Iterator __lhs, _Iterator __rhs,
std::random_access_iterator_tag)
{ return std::make_pair(__rhs - __lhs, __dp_exact); }
template<typename _Iterator>
inline typename _Distance_traits<_Iterator>::__type
__get_distance(const _Iterator& __lhs, const _Iterator& __rhs,
__get_distance(_Iterator __lhs, _Iterator __rhs,
std::input_iterator_tag)
{
if (__lhs == __rhs)
@ -100,7 +105,7 @@ namespace __gnu_debug
template<typename _Iterator>
inline typename _Distance_traits<_Iterator>::__type
__get_distance(const _Iterator& __lhs, const _Iterator& __rhs)
__get_distance(_Iterator __lhs, _Iterator __rhs)
{ return __get_distance(__lhs, __rhs, std::__iterator_category(__lhs)); }
/** We say that integral types for a valid range, and defer to other
@ -109,7 +114,7 @@ namespace __gnu_debug
*/
template<typename _Integral>
inline bool
__valid_range_aux(const _Integral&, const _Integral&,
__valid_range_aux(_Integral, _Integral,
typename _Distance_traits<_Integral>::__type& __dist,
std::__true_type)
{
@ -117,13 +122,12 @@ namespace __gnu_debug
return true;
}
/** We have iterators, so figure out what kind of iterators that are
/** We have iterators, so figure out what kind of iterators they are
* to see if we can check the range ahead of time.
*/
template<typename _InputIterator>
inline bool
__valid_range_aux(const _InputIterator& __first,
const _InputIterator& __last,
__valid_range_aux(_InputIterator __first, _InputIterator __last,
typename _Distance_traits<_InputIterator>::__type& __dist,
std::__false_type)
{
@ -152,61 +156,69 @@ namespace __gnu_debug
*/
template<typename _InputIterator>
inline bool
__valid_range(const _InputIterator& __first, const _InputIterator& __last,
__valid_range(_InputIterator __first, _InputIterator __last,
typename _Distance_traits<_InputIterator>::__type& __dist)
{
typedef typename std::__is_integer<_InputIterator>::__type _Integral;
return __valid_range_aux(__first, __last, __dist, _Integral());
}
template<typename _Iterator, typename _Sequence, typename _Category>
bool
__valid_range(const _Safe_iterator<_Iterator, _Sequence, _Category>&,
const _Safe_iterator<_Iterator, _Sequence, _Category>&,
typename _Distance_traits<_Iterator>::__type&);
#if __cplusplus >= 201103L
template<typename _Iterator,typename _Sequence>
bool
__valid_range(const _Safe_local_iterator<_Iterator, _Sequence>&,
const _Safe_local_iterator<_Iterator, _Sequence>&,
typename _Distance_traits<_Iterator>::__type&);
#endif
template<typename _InputIterator>
inline bool
__valid_range(const _InputIterator& __first, const _InputIterator& __last)
__valid_range(_InputIterator __first, _InputIterator __last)
{
typename _Distance_traits<_InputIterator>::__type __dist;
return __valid_range(__first, __last, __dist);
}
template<typename _Iterator, typename _Sequence, typename _Category>
bool
__valid_range(const _Safe_iterator<_Iterator, _Sequence, _Category>&,
const _Safe_iterator<_Iterator, _Sequence, _Category>&);
#if __cplusplus >= 201103L
template<typename _Iterator, typename _Sequence>
bool
__valid_range(const _Safe_local_iterator<_Iterator, _Sequence>&,
const _Safe_local_iterator<_Iterator, _Sequence>&);
#endif
// Fallback method, always ok.
template<typename _InputIterator, typename _Size>
inline bool
__can_advance(_InputIterator, _Size)
{ return true; }
template<typename _Iterator, typename _Sequence, typename _Size>
template<typename _Iterator, typename _Sequence, typename _Category,
typename _Size>
bool
__can_advance(const _Safe_iterator<_Iterator, _Sequence>&, _Size);
#if __cplusplus < 201103L
// Helper struct to detect random access safe iterators.
template<typename _Iterator>
struct __is_safe_random_iterator
{
enum { __value = 0 };
typedef std::__false_type __type;
};
template<typename _Iterator>
struct _Siter_base
: std::_Iter_base<_Iterator, __is_safe_random_iterator<_Iterator>::__value>
{ };
__can_advance(const _Safe_iterator<_Iterator, _Sequence, _Category>&,
_Size);
/** Helper function to extract base iterator of random access safe iterator
in order to reduce performance impact of debug mode. Limited to random
access iterator because it is the only category for which it is possible
to check for correct iterators order in the __valid_range function
thanks to the < operator.
*/
template<typename _Iterator>
inline typename _Siter_base<_Iterator>::iterator_type
__base(_Iterator __it)
{ return _Siter_base<_Iterator>::_S_base(__it); }
#else
* in order to reduce performance impact of debug mode. Limited to random
* access iterator because it is the only category for which it is possible
* to check for correct iterators order in the __valid_range function
* thanks to the < operator.
*/
template<typename _Iterator>
inline _Iterator
__base(_Iterator __it)
{ return __it; }
#endif
#if __cplusplus < 201103L
template<typename _Iterator>

View File

@ -57,6 +57,9 @@ namespace __debug
typedef __gnu_debug::_Equal_to<_Base_const_iterator> _Equal;
typedef __gnu_debug::_Not_equal_to<_Base_const_iterator> _Not_equal;
template<typename _ItT, typename _SeqT, typename _CatT>
friend class ::__gnu_debug::_Safe_iterator;
public:
typedef typename _Base::reference reference;
typedef typename _Base::const_reference const_reference;

View File

@ -56,6 +56,9 @@ namespace __debug
typedef typename _Base::iterator _Base_iterator;
typedef __gnu_debug::_Equal_to<_Base_const_iterator> _Equal;
template<typename _ItT, typename _SeqT, typename _CatT>
friend class ::__gnu_debug::_Safe_iterator;
public:
// types:
typedef _Key key_type;

View File

@ -56,6 +56,9 @@ namespace __debug
typedef typename _Base::iterator _Base_iterator;
typedef __gnu_debug::_Equal_to<_Base_const_iterator> _Equal;
template<typename _ItT, typename _SeqT, typename _CatT>
friend class ::__gnu_debug::_Safe_iterator;
public:
// types:
typedef _Key key_type;

View File

@ -55,6 +55,9 @@ namespace __debug
typedef typename _Base::iterator _Base_iterator;
typedef __gnu_debug::_Equal_to<_Base_const_iterator> _Equal;
template<typename _ItT, typename _SeqT, typename _CatT>
friend class ::__gnu_debug::_Safe_iterator;
public:
// types:
typedef _Key key_type;

View File

@ -44,14 +44,14 @@ namespace __gnu_debug
template<typename _Sequence>
struct _BeforeBeginHelper
{
template<typename _Iterator>
template<typename _Iterator, typename _Category>
static bool
_S_Is(const _Safe_iterator<_Iterator, _Sequence>&)
_S_Is(const _Safe_iterator<_Iterator, _Sequence, _Category>&)
{ return false; }
template<typename _Iterator>
template<typename _Iterator, typename _Category>
static bool
_S_Is_Beginnest(const _Safe_iterator<_Iterator, _Sequence>& __it)
_S_Is_Beginnest(const _Safe_iterator<_Iterator, _Sequence, _Category>& __it)
{ return __it.base() == __it._M_get_sequence()->_M_base().begin(); }
};
@ -82,22 +82,30 @@ namespace __gnu_debug
* of iterators and it is being detached before _Iterator get
* destroyed. Otherwise it would result in a data race.
*/
template<typename _Iterator, typename _Sequence>
template<typename _Iterator, typename _Sequence, typename _Category
= typename std::iterator_traits<_Iterator>::iterator_category>
class _Safe_iterator
: private _Iterator,
public _Safe_iterator_base
{
typedef _Iterator _Iter_base;
typedef _Safe_iterator_base _Safe_base;
typedef typename _Sequence::const_iterator _Const_iterator;
typedef std::iterator_traits<_Iterator> _Traits;
protected:
typedef std::__are_same<typename _Sequence::_Base::const_iterator,
_Iterator> _IsConstant;
typedef typename __gnu_cxx::__conditional_type<
_IsConstant::__value,
typename _Sequence::_Base::iterator,
typename _Sequence::_Base::const_iterator>::__type _OtherIterator;
struct _Attach_single
{ };
_Safe_iterator(const _Iterator& __i, _Safe_sequence_base* __seq,
_Attach_single)
_Safe_iterator(_Iterator __i, _Safe_sequence_base* __seq, _Attach_single)
_GLIBCXX_NOEXCEPT
: _Iter_base(__i)
{ _M_attach_single(__seq); }
@ -120,7 +128,7 @@ namespace __gnu_debug
* @pre @p seq is not NULL
* @post this is not singular
*/
_Safe_iterator(const _Iterator& __i, const _Safe_sequence_base* __seq)
_Safe_iterator(_Iterator __i, const _Safe_sequence_base* __seq)
_GLIBCXX_NOEXCEPT
: _Iter_base(__i), _Safe_base(__seq, _S_constant())
{
@ -171,10 +179,11 @@ namespace __gnu_debug
*/
template<typename _MutableIterator>
_Safe_iterator(
const _Safe_iterator<_MutableIterator,
typename __gnu_cxx::__enable_if<(std::__are_same<_MutableIterator,
typename _Sequence::iterator::iterator_type>::__value),
_Sequence>::__type>& __x) _GLIBCXX_NOEXCEPT
const _Safe_iterator<_MutableIterator, _Sequence,
typename __gnu_cxx::__enable_if<_IsConstant::__value &&
std::__are_same<_MutableIterator, _OtherIterator>::__value,
_Category>::__type>& __x)
_GLIBCXX_NOEXCEPT
: _Iter_base(__x.base())
{
// _GLIBCXX_RESOLVE_LIB_DEFECTS
@ -309,93 +318,12 @@ namespace __gnu_debug
return _Safe_iterator(base()++, this->_M_sequence, _Attach_single());
}
// ------ Bidirectional iterator requirements ------
/**
* @brief Iterator predecrement
* @pre iterator is decrementable
*/
_Safe_iterator&
operator--() _GLIBCXX_NOEXCEPT
{
_GLIBCXX_DEBUG_VERIFY(this->_M_decrementable(),
_M_message(__msg_bad_dec)
._M_iterator(*this, "this"));
__gnu_cxx::__scoped_lock __l(this->_M_get_mutex());
--base();
return *this;
}
/**
* @brief Iterator postdecrement
* @pre iterator is decrementable
*/
_Safe_iterator
operator--(int) _GLIBCXX_NOEXCEPT
{
_GLIBCXX_DEBUG_VERIFY(this->_M_decrementable(),
_M_message(__msg_bad_dec)
._M_iterator(*this, "this"));
__gnu_cxx::__scoped_lock __l(this->_M_get_mutex());
return _Safe_iterator(base()--, this->_M_sequence, _Attach_single());
}
// ------ Random access iterator requirements ------
reference
operator[](const difference_type& __n) const _GLIBCXX_NOEXCEPT
{
_GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(__n)
&& this->_M_can_advance(__n+1),
_M_message(__msg_iter_subscript_oob)
._M_iterator(*this)._M_integer(__n));
return base()[__n];
}
_Safe_iterator&
operator+=(const difference_type& __n) _GLIBCXX_NOEXCEPT
{
_GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(__n),
_M_message(__msg_advance_oob)
._M_iterator(*this)._M_integer(__n));
__gnu_cxx::__scoped_lock __l(this->_M_get_mutex());
base() += __n;
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(base() + __n, this->_M_sequence);
}
_Safe_iterator&
operator-=(const difference_type& __n) _GLIBCXX_NOEXCEPT
{
_GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(-__n),
_M_message(__msg_retreat_oob)
._M_iterator(*this)._M_integer(__n));
__gnu_cxx::__scoped_lock __l(this->_M_get_mutex());
base() -= __n;
return *this;
}
_Safe_iterator
operator-(const difference_type& __n) const _GLIBCXX_NOEXCEPT
{
_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 ------
/// Determine if this is a constant iterator.
static bool
static _GLIBCXX_CONSTEXPR bool
_S_constant()
{ return std::__are_same<_Const_iterator, _Safe_iterator>::__value; }
{ return _IsConstant::__value; }
/**
* @brief Return the underlying iterator
@ -444,10 +372,6 @@ namespace __gnu_debug
_M_incrementable() const
{ return !this->_M_singular() && !_M_is_end(); }
// Is the iterator decrementable?
bool
_M_decrementable() const { return !_M_singular() && !_M_is_begin(); }
// Can we advance the iterator @p __n steps (@p __n may be negative)
bool
_M_can_advance(const difference_type& __n) const;
@ -459,14 +383,23 @@ namespace __gnu_debug
bool __check_dereferenceable = true) const;
// The sequence this iterator references.
typename
__gnu_cxx::__conditional_type<std::__are_same<_Const_iterator,
_Safe_iterator>::__value,
const _Sequence*,
_Sequence*>::__type
typename __gnu_cxx::__conditional_type<
_IsConstant::__value, const _Sequence*, _Sequence*>::__type
_M_get_sequence() const
{ return static_cast<_Sequence*>(_M_sequence); }
// Get distance to __rhs.
typename _Distance_traits<_Iterator>::__type
_M_get_distance_to(const _Safe_iterator& __rhs) const;
// Get distance from sequence begin up to *this.
typename _Distance_traits<_Iterator>::__type
_M_get_distance_from_begin() const;
// Get distance from *this to sequence end.
typename _Distance_traits<_Iterator>::__type
_M_get_distance_to_end() const;
/// Is this iterator equal to the sequence's begin() iterator?
bool
_M_is_begin() const
@ -490,13 +423,346 @@ namespace __gnu_debug
{ return _BeforeBeginHelper<_Sequence>::_S_Is_Beginnest(*this); }
};
template<typename _Iterator, typename _Sequence>
class _Safe_iterator<_Iterator, _Sequence, std::bidirectional_iterator_tag>
: public _Safe_iterator<_Iterator, _Sequence, std::forward_iterator_tag>
{
typedef _Safe_iterator<_Iterator, _Sequence,
std::forward_iterator_tag> _Safe_base;
protected:
typedef typename _Safe_base::_OtherIterator _OtherIterator;
typedef typename _Safe_base::_Attach_single _Attach_single;
_Safe_iterator(_Iterator __i, _Safe_sequence_base* __seq, _Attach_single)
_GLIBCXX_NOEXCEPT
: _Safe_base(__i, __seq, _Attach_single())
{ }
public:
/// @post the iterator is singular and unattached
_Safe_iterator() _GLIBCXX_NOEXCEPT { }
/**
* @brief Safe iterator construction from an unsafe iterator and
* its sequence.
*
* @pre @p seq is not NULL
* @post this is not singular
*/
_Safe_iterator(_Iterator __i, const _Safe_sequence_base* __seq)
_GLIBCXX_NOEXCEPT
: _Safe_base(__i, __seq)
{ }
/**
* @brief Copy construction.
*/
_Safe_iterator(const _Safe_iterator& __x) _GLIBCXX_NOEXCEPT
: _Safe_base(__x)
{ }
#if __cplusplus >= 201103L
/** @brief Move construction. */
_Safe_iterator(_Safe_iterator&&) = default;
#endif
/**
* @brief Converting constructor from a mutable iterator to a
* constant iterator.
*/
template<typename _MutableIterator>
_Safe_iterator(
const _Safe_iterator<_MutableIterator, _Sequence,
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)
{ }
#if __cplusplus >= 201103L
/** @brief Copy assignment. */
_Safe_iterator&
operator=(const _Safe_iterator&) = default;
/** @brief Move assignment. */
_Safe_iterator&
operator=(_Safe_iterator&&) = default;
#else
/** @brief Copy assignment. */
_Safe_iterator&
operator=(const _Safe_iterator& __x)
{
_Safe_base::operator=(__x);
return *this;
}
#endif
// ------ Input iterator requirements ------
/**
* @brief Iterator preincrement
* @pre iterator is incrementable
*/
_Safe_iterator&
operator++() _GLIBCXX_NOEXCEPT
{
_Safe_base::operator++();
return *this;
}
/**
* @brief Iterator postincrement
* @pre iterator is incrementable
*/
_Safe_iterator
operator++(int) _GLIBCXX_NOEXCEPT
{
_GLIBCXX_DEBUG_VERIFY(this->_M_incrementable(),
_M_message(__msg_bad_inc)
._M_iterator(*this, "this"));
__gnu_cxx::__scoped_lock __l(this->_M_get_mutex());
return _Safe_iterator(this->base()++, this->_M_sequence,
_Attach_single());
}
// ------ Bidirectional iterator requirements ------
/**
* @brief Iterator predecrement
* @pre iterator is decrementable
*/
_Safe_iterator&
operator--() _GLIBCXX_NOEXCEPT
{
_GLIBCXX_DEBUG_VERIFY(this->_M_decrementable(),
_M_message(__msg_bad_dec)
._M_iterator(*this, "this"));
__gnu_cxx::__scoped_lock __l(this->_M_get_mutex());
--this->base();
return *this;
}
/**
* @brief Iterator postdecrement
* @pre iterator is decrementable
*/
_Safe_iterator
operator--(int) _GLIBCXX_NOEXCEPT
{
_GLIBCXX_DEBUG_VERIFY(this->_M_decrementable(),
_M_message(__msg_bad_dec)
._M_iterator(*this, "this"));
__gnu_cxx::__scoped_lock __l(this->_M_get_mutex());
return _Safe_iterator(this->base()--, this->_M_sequence,
_Attach_single());
}
// ------ Utilities ------
// Is the iterator decrementable?
bool
_M_decrementable() const
{ return !this->_M_singular() && !this->_M_is_begin(); }
};
template<typename _Iterator, typename _Sequence>
class _Safe_iterator<_Iterator, _Sequence, std::random_access_iterator_tag>
: public _Safe_iterator<_Iterator, _Sequence,
std::bidirectional_iterator_tag>
{
typedef _Safe_iterator<_Iterator, _Sequence,
std::bidirectional_iterator_tag> _Safe_base;
typedef typename _Safe_base::_OtherIterator _OtherIterator;
typedef typename _Safe_base::_Attach_single _Attach_single;
_Safe_iterator(_Iterator __i, _Safe_sequence_base* __seq, _Attach_single)
_GLIBCXX_NOEXCEPT
: _Safe_base(__i, __seq, _Attach_single())
{ }
public:
typedef typename _Safe_base::difference_type difference_type;
typedef typename _Safe_base::reference reference;
/// @post the iterator is singular and unattached
_Safe_iterator() _GLIBCXX_NOEXCEPT { }
/**
* @brief Safe iterator construction from an unsafe iterator and
* its sequence.
*
* @pre @p seq is not NULL
* @post this is not singular
*/
_Safe_iterator(_Iterator __i, const _Safe_sequence_base* __seq)
_GLIBCXX_NOEXCEPT
: _Safe_base(__i, __seq)
{ }
/**
* @brief Copy construction.
*/
_Safe_iterator(const _Safe_iterator& __x) _GLIBCXX_NOEXCEPT
: _Safe_base(__x)
{ }
#if __cplusplus >= 201103L
/** @brief Move construction. */
_Safe_iterator(_Safe_iterator&&) = default;
#endif
/**
* @brief Converting constructor from a mutable iterator to a
* constant iterator.
*/
template<typename _MutableIterator>
_Safe_iterator(
const _Safe_iterator<_MutableIterator, _Sequence,
typename __gnu_cxx::__enable_if<_Safe_base::_IsConstant::__value &&
std::__are_same<_MutableIterator, _OtherIterator>::__value,
std::random_access_iterator_tag>::__type>& __x)
_GLIBCXX_NOEXCEPT
: _Safe_base(__x)
{ }
#if __cplusplus >= 201103L
/** @brief Copy assignment. */
_Safe_iterator&
operator=(const _Safe_iterator&) = default;
/** @brief Move assignment. */
_Safe_iterator&
operator=(_Safe_iterator&&) = default;
#else
/** @brief Copy assignment. */
_Safe_iterator&
operator=(const _Safe_iterator& __x)
{
_Safe_base::operator=(__x);
return *this;
}
#endif
// Is the iterator range [*this, __rhs) valid?
bool
_M_valid_range(const _Safe_iterator& __rhs,
std::pair<difference_type,
_Distance_precision>& __dist) const;
// ------ Input iterator requirements ------
/**
* @brief Iterator preincrement
* @pre iterator is incrementable
*/
_Safe_iterator&
operator++() _GLIBCXX_NOEXCEPT
{
_Safe_base::operator++();
return *this;
}
/**
* @brief Iterator postincrement
* @pre iterator is incrementable
*/
_Safe_iterator
operator++(int) _GLIBCXX_NOEXCEPT
{
_GLIBCXX_DEBUG_VERIFY(this->_M_incrementable(),
_M_message(__msg_bad_inc)
._M_iterator(*this, "this"));
__gnu_cxx::__scoped_lock __l(this->_M_get_mutex());
return _Safe_iterator(this->base()++, this->_M_sequence,
_Attach_single());
}
// ------ Bidirectional iterator requirements ------
/**
* @brief Iterator predecrement
* @pre iterator is decrementable
*/
_Safe_iterator&
operator--() _GLIBCXX_NOEXCEPT
{
_Safe_base::operator--();
return *this;
}
/**
* @brief Iterator postdecrement
* @pre iterator is decrementable
*/
_Safe_iterator
operator--(int) _GLIBCXX_NOEXCEPT
{
_GLIBCXX_DEBUG_VERIFY(this->_M_decrementable(),
_M_message(__msg_bad_dec)
._M_iterator(*this, "this"));
__gnu_cxx::__scoped_lock __l(this->_M_get_mutex());
return _Safe_iterator(this->base()--, this->_M_sequence,
_Attach_single());
}
// ------ Random access iterator requirements ------
reference
operator[](const difference_type& __n) const _GLIBCXX_NOEXCEPT
{
_GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(__n)
&& this->_M_can_advance(__n + 1),
_M_message(__msg_iter_subscript_oob)
._M_iterator(*this)._M_integer(__n));
return this->base()[__n];
}
_Safe_iterator&
operator+=(const difference_type& __n) _GLIBCXX_NOEXCEPT
{
_GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(__n),
_M_message(__msg_advance_oob)
._M_iterator(*this)._M_integer(__n));
__gnu_cxx::__scoped_lock __l(this->_M_get_mutex());
this->base() += __n;
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
{
_GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(-__n),
_M_message(__msg_retreat_oob)
._M_iterator(*this)._M_integer(__n));
__gnu_cxx::__scoped_lock __l(this->_M_get_mutex());
this->base() -= __n;
return *this;
}
_Safe_iterator
operator-(const difference_type& __n) const _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);
}
};
template<typename _IteratorL, typename _IteratorR, typename _Sequence>
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(),
_GLIBCXX_DEBUG_VERIFY(!__lhs._M_singular() && !__rhs._M_singular(),
_M_message(__msg_iter_compare_bad)
._M_iterator(__lhs, "lhs")
._M_iterator(__rhs, "rhs"));
@ -513,7 +779,7 @@ namespace __gnu_debug
const _Safe_iterator<_Iterator, _Sequence>& __rhs)
_GLIBCXX_NOEXCEPT
{
_GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
_GLIBCXX_DEBUG_VERIFY(!__lhs._M_singular() && !__rhs._M_singular(),
_M_message(__msg_iter_compare_bad)
._M_iterator(__lhs, "lhs")
._M_iterator(__rhs, "rhs"));
@ -530,7 +796,7 @@ namespace __gnu_debug
const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
_GLIBCXX_NOEXCEPT
{
_GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
_GLIBCXX_DEBUG_VERIFY(!__lhs._M_singular() && !__rhs._M_singular(),
_M_message(__msg_iter_compare_bad)
._M_iterator(__lhs, "lhs")
._M_iterator(__rhs, "rhs"));
@ -547,7 +813,7 @@ namespace __gnu_debug
const _Safe_iterator<_Iterator, _Sequence>& __rhs)
_GLIBCXX_NOEXCEPT
{
_GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
_GLIBCXX_DEBUG_VERIFY(!__lhs._M_singular() && !__rhs._M_singular(),
_M_message(__msg_iter_compare_bad)
._M_iterator(__lhs, "lhs")
._M_iterator(__rhs, "rhs"));
@ -560,11 +826,13 @@ namespace __gnu_debug
template<typename _IteratorL, typename _IteratorR, typename _Sequence>
inline bool
operator<(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
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(),
_GLIBCXX_DEBUG_VERIFY(!__lhs._M_singular() && !__rhs._M_singular(),
_M_message(__msg_iter_order_bad)
._M_iterator(__lhs, "lhs")
._M_iterator(__rhs, "rhs"));
@ -577,11 +845,13 @@ namespace __gnu_debug
template<typename _Iterator, typename _Sequence>
inline bool
operator<(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
const _Safe_iterator<_Iterator, _Sequence>& __rhs)
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(),
_GLIBCXX_DEBUG_VERIFY(!__lhs._M_singular() && !__rhs._M_singular(),
_M_message(__msg_iter_order_bad)
._M_iterator(__lhs, "lhs")
._M_iterator(__rhs, "rhs"));
@ -594,11 +864,13 @@ namespace __gnu_debug
template<typename _IteratorL, typename _IteratorR, typename _Sequence>
inline bool
operator<=(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
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(),
_GLIBCXX_DEBUG_VERIFY(!__lhs._M_singular() && !__rhs._M_singular(),
_M_message(__msg_iter_order_bad)
._M_iterator(__lhs, "lhs")
._M_iterator(__rhs, "rhs"));
@ -611,11 +883,13 @@ namespace __gnu_debug
template<typename _Iterator, typename _Sequence>
inline bool
operator<=(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
const _Safe_iterator<_Iterator, _Sequence>& __rhs)
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(),
_GLIBCXX_DEBUG_VERIFY(!__lhs._M_singular() && !__rhs._M_singular(),
_M_message(__msg_iter_order_bad)
._M_iterator(__lhs, "lhs")
._M_iterator(__rhs, "rhs"));
@ -628,11 +902,13 @@ namespace __gnu_debug
template<typename _IteratorL, typename _IteratorR, typename _Sequence>
inline bool
operator>(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
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(),
_GLIBCXX_DEBUG_VERIFY(!__lhs._M_singular() && !__rhs._M_singular(),
_M_message(__msg_iter_order_bad)
._M_iterator(__lhs, "lhs")
._M_iterator(__rhs, "rhs"));
@ -645,11 +921,13 @@ namespace __gnu_debug
template<typename _Iterator, typename _Sequence>
inline bool
operator>(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
const _Safe_iterator<_Iterator, _Sequence>& __rhs)
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(),
_GLIBCXX_DEBUG_VERIFY(!__lhs._M_singular() && !__rhs._M_singular(),
_M_message(__msg_iter_order_bad)
._M_iterator(__lhs, "lhs")
._M_iterator(__rhs, "rhs"));
@ -662,11 +940,13 @@ namespace __gnu_debug
template<typename _IteratorL, typename _IteratorR, typename _Sequence>
inline bool
operator>=(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
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(),
_GLIBCXX_DEBUG_VERIFY(!__lhs._M_singular() && !__rhs._M_singular(),
_M_message(__msg_iter_order_bad)
._M_iterator(__lhs, "lhs")
._M_iterator(__rhs, "rhs"));
@ -679,11 +959,13 @@ namespace __gnu_debug
template<typename _Iterator, typename _Sequence>
inline bool
operator>=(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
const _Safe_iterator<_Iterator, _Sequence>& __rhs)
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(),
_GLIBCXX_DEBUG_VERIFY(!__lhs._M_singular() && !__rhs._M_singular(),
_M_message(__msg_iter_order_bad)
._M_iterator(__lhs, "lhs")
._M_iterator(__rhs, "rhs"));
@ -699,12 +981,15 @@ namespace __gnu_debug
// operators but also operator- must accept mixed iterator/const_iterator
// parameters.
template<typename _IteratorL, typename _IteratorR, typename _Sequence>
inline typename _Safe_iterator<_IteratorL, _Sequence>::difference_type
operator-(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
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(),
_GLIBCXX_DEBUG_VERIFY(!__lhs._M_singular() && !__rhs._M_singular(),
_M_message(__msg_distance_bad)
._M_iterator(__lhs, "lhs")
._M_iterator(__rhs, "rhs"));
@ -715,185 +1000,69 @@ namespace __gnu_debug
return __lhs.base() - __rhs.base();
}
template<typename _Iterator, typename _Sequence>
inline typename _Safe_iterator<_Iterator, _Sequence>::difference_type
operator-(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
const _Safe_iterator<_Iterator, _Sequence>& __rhs)
template<typename _Iterator, typename _Sequence>
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();
}
{
_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();
}
template<typename _Iterator, typename _Sequence>
inline _Safe_iterator<_Iterator, _Sequence>
operator+(typename _Safe_iterator<_Iterator,_Sequence>::difference_type __n,
const _Safe_iterator<_Iterator, _Sequence>& __i) _GLIBCXX_NOEXCEPT
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; }
/** Safe iterators know if they are dereferenceable. */
template<typename _Iterator, typename _Sequence>
inline bool
__check_dereferenceable(const _Safe_iterator<_Iterator, _Sequence>& __x)
{ return __x._M_dereferenceable(); }
/** Safe iterators know how to check if they form a valid range. */
template<typename _Iterator, typename _Sequence>
template<typename _Iterator, typename _Sequence, typename _Category>
inline bool
__valid_range(const _Safe_iterator<_Iterator, _Sequence>& __first,
const _Safe_iterator<_Iterator, _Sequence>& __last,
__valid_range(const _Safe_iterator<_Iterator, _Sequence,
_Category>& __first,
const _Safe_iterator<_Iterator, _Sequence,
_Category>& __last,
typename _Distance_traits<_Iterator>::__type& __dist)
{ return __first._M_valid_range(__last, __dist); }
/** Safe iterators can help to get better distance knowledge. */
template<typename _Iterator, typename _Sequence>
inline typename _Distance_traits<_Iterator>::__type
__get_distance(const _Safe_iterator<_Iterator, _Sequence>& __first,
const _Safe_iterator<_Iterator, _Sequence>& __last,
std::random_access_iterator_tag)
{ return std::make_pair(__last.base() - __first.base(), __dp_exact); }
template<typename _Iterator, typename _Sequence>
inline typename _Distance_traits<_Iterator>::__type
__get_distance(const _Safe_iterator<_Iterator, _Sequence>& __first,
const _Safe_iterator<_Iterator, _Sequence>& __last,
std::input_iterator_tag)
{
typedef typename _Distance_traits<_Iterator>::__type _Diff;
typedef _Sequence_traits<_Sequence> _SeqTraits;
if (__first.base() == __last.base())
return std::make_pair(0, __dp_exact);
if (__first._M_is_before_begin())
{
if (__last._M_is_begin())
return std::make_pair(1, __dp_exact);
return std::make_pair(1, __dp_sign);
}
if (__first._M_is_begin())
{
if (__last._M_is_before_begin())
return std::make_pair(-1, __dp_exact);
if (__last._M_is_end())
return _SeqTraits::_S_size(*__first._M_get_sequence());
return std::make_pair(1, __dp_sign);
}
if (__first._M_is_end())
{
if (__last._M_is_before_begin())
return std::make_pair(-1, __dp_exact);
if (__last._M_is_begin())
{
_Diff __diff = _SeqTraits::_S_size(*__first._M_get_sequence());
return std::make_pair(-__diff.first, __diff.second);
}
return std::make_pair(-1, __dp_sign);
}
if (__last._M_is_before_begin() || __last._M_is_begin())
return std::make_pair(-1, __dp_sign);
if (__last._M_is_end())
return std::make_pair(1, __dp_sign);
return std::make_pair(1, __dp_equality);
}
// Get distance from sequence begin to specified iterator.
template<typename _Iterator, typename _Sequence>
inline typename _Distance_traits<_Iterator>::__type
__get_distance_from_begin(const _Safe_iterator<_Iterator, _Sequence>& __it)
{
typedef _Sequence_traits<_Sequence> _SeqTraits;
// No need to consider before_begin as this function is only used in
// _M_can_advance which won't be used for forward_list iterators.
if (__it._M_is_begin())
return std::make_pair(0, __dp_exact);
if (__it._M_is_end())
return _SeqTraits::_S_size(*__it._M_get_sequence());
typename _Distance_traits<_Iterator>::__type __res
= __get_distance(__it._M_get_sequence()->_M_base().begin(), __it.base());
if (__res.second == __dp_equality)
return std::make_pair(1, __dp_sign);
return __res;
}
// Get distance from specified iterator to sequence end.
template<typename _Iterator, typename _Sequence>
inline typename _Distance_traits<_Iterator>::__type
__get_distance_to_end(const _Safe_iterator<_Iterator, _Sequence>& __it)
{
typedef _Sequence_traits<_Sequence> _SeqTraits;
// No need to consider before_begin as this function is only used in
// _M_can_advance which won't be used for forward_list iterators.
if (__it._M_is_begin())
return _SeqTraits::_S_size(*__it._M_get_sequence());
if (__it._M_is_end())
return std::make_pair(0, __dp_exact);
typename _Distance_traits<_Iterator>::__type __res
= __get_distance(__it.base(), __it._M_get_sequence()->_M_base().end());
if (__res.second == __dp_equality)
return std::make_pair(1, __dp_sign);
return __res;
}
template<typename _Iterator, typename _Sequence, typename _Size>
template<typename _Iterator, typename _Sequence, typename _Category>
inline bool
__can_advance(const _Safe_iterator<_Iterator, _Sequence>& __it, _Size __n)
__valid_range(const _Safe_iterator<_Iterator, _Sequence,
_Category>& __first,
const _Safe_iterator<_Iterator, _Sequence,
_Category>& __last)
{
typename _Distance_traits<_Iterator>::__type __dist;
return __first._M_valid_range(__last, __dist);
}
template<typename _Iterator, typename _Sequence, typename _Category,
typename _Size>
inline bool
__can_advance(const _Safe_iterator<_Iterator, _Sequence, _Category>& __it,
_Size __n)
{ return __it._M_can_advance(__n); }
#if __cplusplus < 201103L
template<typename _Iterator, typename _Sequence>
struct __is_safe_random_iterator<_Safe_iterator<_Iterator, _Sequence> >
: std::__are_same<std::random_access_iterator_tag,
typename std::iterator_traits<_Iterator>::
iterator_category>
{ };
#else
template<typename _Iterator, typename _Sequence>
_Iterator
__base(const _Safe_iterator<_Iterator, _Sequence>& __it,
std::random_access_iterator_tag)
__base(const _Safe_iterator<_Iterator, _Sequence,
std::random_access_iterator_tag>& __it)
{ return __it.base(); }
template<typename _Iterator, typename _Sequence>
const _Safe_iterator<_Iterator, _Sequence>&
__base(const _Safe_iterator<_Iterator, _Sequence>& __it,
std::input_iterator_tag)
{ return __it; }
template<typename _Iterator, typename _Sequence>
auto
__base(const _Safe_iterator<_Iterator, _Sequence>& __it)
-> decltype(__base(__it, std::__iterator_category(__it)))
{ return __base(__it, std::__iterator_category(__it)); }
#endif
#if __cplusplus < 201103L
template<typename _Iterator, typename _Sequence>
struct _Unsafe_type<_Safe_iterator<_Iterator, _Sequence> >

View File

@ -31,9 +31,57 @@
namespace __gnu_debug
{
template<typename _Iterator, typename _Sequence>
template<typename _Iterator, typename _Sequence, typename _Category>
typename _Distance_traits<_Iterator>::__type
_Safe_iterator<_Iterator, _Sequence, _Category>::
_M_get_distance_from_begin() const
{
typedef _Sequence_traits<_Sequence> _SeqTraits;
// No need to consider before_begin as this function is only used in
// _M_can_advance which won't be used for forward_list iterators.
if (_M_is_begin())
return std::make_pair(0, __dp_exact);
if (_M_is_end())
return _SeqTraits::_S_size(*_M_get_sequence());
typename _Distance_traits<_Iterator>::__type __res
= __get_distance(_M_get_sequence()->_M_base().begin(), base());
if (__res.second == __dp_equality)
return std::make_pair(1, __dp_sign);
return __res;
}
template<typename _Iterator, typename _Sequence, typename _Category>
typename _Distance_traits<_Iterator>::__type
_Safe_iterator<_Iterator, _Sequence, _Category>::
_M_get_distance_to_end() const
{
typedef _Sequence_traits<_Sequence> _SeqTraits;
// No need to consider before_begin as this function is only used in
// _M_can_advance which won't be used for forward_list iterators.
if (_M_is_begin())
return _SeqTraits::_S_size(*_M_get_sequence());
if (_M_is_end())
return std::make_pair(0, __dp_exact);
typename _Distance_traits<_Iterator>::__type __res
= __get_distance(base(), _M_get_sequence()->_M_base().end());
if (__res.second == __dp_equality)
return std::make_pair(1, __dp_sign);
return __res;
}
template<typename _Iterator, typename _Sequence, typename _Category>
bool
_Safe_iterator<_Iterator, _Sequence>::
_Safe_iterator<_Iterator, _Sequence, _Category>::
_M_can_advance(const difference_type& __n) const
{
if (this->_M_singular())
@ -45,7 +93,7 @@ namespace __gnu_debug
if (__n < 0)
{
std::pair<difference_type, _Distance_precision> __dist =
__get_distance_from_begin(*this);
_M_get_distance_from_begin();
bool __ok = ((__dist.second == __dp_exact && __dist.first >= -__n)
|| (__dist.second != __dp_exact && __dist.first > 0));
return __ok;
@ -53,16 +101,69 @@ namespace __gnu_debug
else
{
std::pair<difference_type, _Distance_precision> __dist =
__get_distance_to_end(*this);
_M_get_distance_to_end();
bool __ok = ((__dist.second == __dp_exact && __dist.first >= __n)
|| (__dist.second != __dp_exact && __dist.first > 0));
return __ok;
}
}
template<typename _Iterator, typename _Sequence>
template<typename _Iterator, typename _Sequence, typename _Category>
typename _Distance_traits<_Iterator>::__type
_Safe_iterator<_Iterator, _Sequence, _Category>::
_M_get_distance_to(const _Safe_iterator& __rhs) const
{
typedef typename _Distance_traits<_Iterator>::__type _Diff;
typedef _Sequence_traits<_Sequence> _SeqTraits;
if (this->base() == __rhs.base())
return std::make_pair(0, __dp_exact);
if (this->_M_is_before_begin())
{
if (__rhs._M_is_begin())
return std::make_pair(1, __dp_exact);
return std::make_pair(1, __dp_sign);
}
if (this->_M_is_begin())
{
if (__rhs._M_is_before_begin())
return std::make_pair(-1, __dp_exact);
if (__rhs._M_is_end())
return _SeqTraits::_S_size(*this->_M_get_sequence());
return std::make_pair(1, __dp_sign);
}
if (this->_M_is_end())
{
if (__rhs._M_is_before_begin())
return std::make_pair(-1, __dp_exact);
if (__rhs._M_is_begin())
{
_Diff __diff = _SeqTraits::_S_size(*this->_M_get_sequence());
return std::make_pair(-__diff.first, __diff.second);
}
return std::make_pair(-1, __dp_sign);
}
if (__rhs._M_is_before_begin() || __rhs._M_is_begin())
return std::make_pair(-1, __dp_sign);
if (__rhs._M_is_end())
return std::make_pair(1, __dp_sign);
return std::make_pair(1, __dp_equality);
}
template<typename _Iterator, typename _Sequence, typename _Category>
bool
_Safe_iterator<_Iterator, _Sequence>::
_Safe_iterator<_Iterator, _Sequence, _Category>::
_M_valid_range(const _Safe_iterator& __rhs,
std::pair<difference_type, _Distance_precision>& __dist,
bool __check_dereferenceable) const
@ -71,7 +172,7 @@ namespace __gnu_debug
return false;
/* Determine iterators order */
__dist = __get_distance(*this, __rhs);
__dist = _M_get_distance_to(__rhs);
switch (__dist.second)
{
case __dp_equality:
@ -90,6 +191,25 @@ namespace __gnu_debug
// Assume that this is a valid range; we can't check anything else.
return true;
}
template<typename _Iterator, typename _Sequence>
bool
_Safe_iterator<_Iterator, _Sequence, std::random_access_iterator_tag>::
_M_valid_range(const _Safe_iterator& __rhs,
std::pair<difference_type,
_Distance_precision>& __dist) const
{
if (!this->_M_can_compare(__rhs))
return false;
/* Determine iterators order */
__dist = std::make_pair(__rhs.base() - this->base(), __dp_exact);
// If range is not empty first iterator must be dereferenceable.
if (__dist.first > 0)
return this->_M_dereferenceable();
return __dist.first == 0;
}
} // namespace __gnu_debug
#endif

View File

@ -51,15 +51,24 @@ namespace __gnu_debug
{
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;
typedef std::iterator_traits<_Iterator> _Traits;
typedef std::__are_same<
typename _Sequence::_Base::const_local_iterator,
_Iterator> _IsConstant;
typedef typename __gnu_cxx::__conditional_type<_IsConstant::__value,
typename _Sequence::_Base::local_iterator,
typename _Sequence::_Base::const_local_iterator>::__type
_OtherIterator;
struct _Attach_single
{ };
_Safe_local_iterator(const _Iterator& __i, _Safe_sequence_base* __cont,
_Safe_local_iterator(_Iterator __i, _Safe_sequence_base* __cont,
_Attach_single) noexcept
: _Iter_base(__i)
{ _M_attach_single(__cont); }
@ -82,8 +91,7 @@ namespace __gnu_debug
* @pre @p seq is not NULL
* @post this is not singular
*/
_Safe_local_iterator(const _Iterator& __i,
const _Safe_sequence_base* __cont)
_Safe_local_iterator(_Iterator __i, const _Safe_sequence_base* __cont)
: _Iter_base(__i), _Safe_base(__cont, _S_constant())
{
_GLIBCXX_DEBUG_VERIFY(!this->_M_singular(),
@ -132,16 +140,15 @@ namespace __gnu_debug
template<typename _MutableIterator>
_Safe_local_iterator(
const _Safe_local_iterator<_MutableIterator,
typename __gnu_cxx::__enable_if<std::__are_same<
_MutableIterator,
typename _Sequence::local_iterator::iterator_type>::__value,
_Sequence>::__type>& __x)
typename __gnu_cxx::__enable_if<_IsConstant::__value &&
std::__are_same<_MutableIterator, _OtherIterator>::__value,
_Sequence>::__type>& __x) noexcept
: _Iter_base(__x.base())
{
// _GLIBCXX_RESOLVE_LIB_DEFECTS
// DR 408. Is vector<reverse_iterator<char*> > forbidden?
_GLIBCXX_DEBUG_VERIFY(!__x._M_singular()
|| __x.base() == _Iterator(),
|| __x.base() == _MutableIterator(),
_M_message(__msg_init_const_singular)
._M_iterator(*this, "this")
._M_iterator(__x, "other"));
@ -272,12 +279,9 @@ namespace __gnu_debug
// ------ Utilities ------
/// Determine if this is a constant iterator.
static bool
static constexpr bool
_S_constant()
{
return std::__are_same<_Const_local_iterator,
_Safe_local_iterator>::__value;
}
{ return _IsConstant::__value; }
/**
* @brief Return the underlying iterator
@ -326,12 +330,13 @@ namespace __gnu_debug
std::pair<difference_type,
_Distance_precision>& __dist_info) const;
// Get distance to __rhs.
typename _Distance_traits<_Iterator>::__type
_M_get_distance_to(const _Safe_local_iterator& __rhs) const;
// The sequence this iterator references.
typename
__gnu_cxx::__conditional_type<std::__are_same<_Const_local_iterator,
_Safe_local_iterator>::__value,
const _Sequence*,
_Sequence*>::__type
typename __gnu_cxx::__conditional_type<
_IsConstant::__value, const _Sequence*, _Sequence*>::__type
_M_get_sequence() const
{ return static_cast<_Sequence*>(_M_sequence); }
@ -396,7 +401,7 @@ namespace __gnu_debug
operator!=(const _Safe_local_iterator<_IteratorL, _Sequence>& __lhs,
const _Safe_local_iterator<_IteratorR, _Sequence>& __rhs)
{
_GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
_GLIBCXX_DEBUG_VERIFY(!__lhs._M_singular() && !__rhs._M_singular(),
_M_message(__msg_iter_compare_bad)
._M_iterator(__lhs, "lhs")
._M_iterator(__rhs, "rhs"));
@ -431,13 +436,6 @@ namespace __gnu_debug
return __lhs.base() != __rhs.base();
}
/** Safe local iterators know if they are dereferenceable. */
template<typename _Iterator, typename _Sequence>
inline bool
__check_dereferenceable(const _Safe_local_iterator<_Iterator,
_Sequence>& __x)
{ return __x._M_dereferenceable(); }
/** Safe local iterators know how to check if they form a valid range. */
template<typename _Iterator, typename _Sequence>
inline bool
@ -446,49 +444,13 @@ namespace __gnu_debug
typename _Distance_traits<_Iterator>::__type& __dist_info)
{ return __first._M_valid_range(__last, __dist_info); }
/** Safe local iterators need a special method to get distance between each
other. */
template<typename _Iterator, typename _Sequence>
inline std::pair<typename std::iterator_traits<_Iterator>::difference_type,
_Distance_precision>
__get_distance(const _Safe_local_iterator<_Iterator, _Sequence>& __first,
const _Safe_local_iterator<_Iterator, _Sequence>& __last,
std::input_iterator_tag)
inline bool
__valid_range(const _Safe_local_iterator<_Iterator, _Sequence>& __first,
const _Safe_local_iterator<_Iterator, _Sequence>& __last)
{
if (__first.base() == __last.base())
return { 0, __dp_exact };
if (__first._M_is_begin())
{
if (__last._M_is_end())
return
{
__first._M_get_sequence()->bucket_size(__first.bucket()),
__dp_exact
};
return { 1, __dp_sign };
}
if (__first._M_is_end())
{
if (__last._M_is_begin())
return
{
-__first._M_get_sequence()->bucket_size(__first.bucket()),
__dp_exact
};
return { -1, __dp_sign };
}
if (__last._M_is_begin())
return { -1, __dp_sign };
if (__last._M_is_end())
return { 1, __dp_sign };
return { 1, __dp_equality };
typename _Distance_traits<_Iterator>::__type __dist_info;
return __first._M_valid_range(__last, __dist_info);
}
#if __cplusplus < 201103L

View File

@ -31,6 +31,47 @@
namespace __gnu_debug
{
template<typename _Iterator, typename _Sequence>
typename _Distance_traits<_Iterator>::__type
_Safe_local_iterator<_Iterator, _Sequence>::
_M_get_distance_to(const _Safe_local_iterator& __rhs) const
{
if (base() == __rhs.base())
return { 0, __dp_exact };
if (_M_is_begin())
{
if (__rhs._M_is_end())
return
{
_M_get_sequence()->bucket_size(bucket()),
__dp_exact
};
return { 1, __dp_sign };
}
if (_M_is_end())
{
if (__rhs._M_is_begin())
return
{
-_M_get_sequence()->bucket_size(bucket()),
__dp_exact
};
return { -1, __dp_sign };
}
if (__rhs._M_is_begin())
return { -1, __dp_sign };
if (__rhs._M_is_end())
return { 1, __dp_sign };
return { 1, __dp_equality };
}
template<typename _Iterator, typename _Sequence>
bool
_Safe_local_iterator<_Iterator, _Sequence>::
@ -45,7 +86,7 @@ namespace __gnu_debug
/* Determine if we can order the iterators without the help of
the container */
__dist = __get_distance(*this, __rhs);
__dist = _M_get_distance_to(__rhs);
switch (__dist.second)
{
case __dp_equality:

View File

@ -55,6 +55,9 @@ namespace __debug
typedef typename _Base::iterator _Base_iterator;
typedef __gnu_debug::_Equal_to<_Base_const_iterator> _Equal;
template<typename _ItT, typename _SeqT, typename _CatT>
friend class ::__gnu_debug::_Safe_iterator;
public:
// types:
typedef _Key key_type;

View File

@ -52,12 +52,13 @@ namespace __gnu_debug
__can_advance(const std::reverse_iterator<_Iterator>& __it, _Size __n)
{ return __can_advance(__it.base(), -__n); }
#if __cplusplus < 201103L
template<typename _Iterator>
struct __is_safe_random_iterator<std::reverse_iterator<_Iterator> >
: __is_safe_random_iterator<_Iterator>
{ };
template<typename _Iterator, typename _Sequence>
inline std::reverse_iterator<_Iterator>
__base(const std::reverse_iterator<_Safe_iterator<
_Iterator, _Sequence, std::random_access_iterator_tag> >& __it)
{ return std::reverse_iterator<_Iterator>(__it.base().base()); }
#if __cplusplus < 201103L
template<typename _Iterator>
struct _Unsafe_type<std::reverse_iterator<_Iterator> >
{
@ -73,12 +74,6 @@ namespace __gnu_debug
return std::reverse_iterator<_UnsafeType>(__unsafe(__it.base()));
}
#else
template<typename _Iterator>
inline auto
__base(const std::reverse_iterator<_Iterator>& __it)
-> decltype(std::__make_reverse_iterator(__base(__it.base())))
{ return std::__make_reverse_iterator(__base(__it.base())); }
template<typename _Iterator>
inline auto
__unsafe(const std::reverse_iterator<_Iterator>& __it)
@ -128,7 +123,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_Iterator
__niter_base(const __gnu_debug::_Safe_iterator<
__gnu_cxx::__normal_iterator<_Iterator, _Container>,
_Sequence>&);
_Sequence, std::random_access_iterator_tag>&);
_GLIBCXX_END_NAMESPACE_VERSION
}

View File

@ -94,6 +94,9 @@ namespace __gnu_debug
basic_string, _Allocator, _Safe_sequence, bool(_GLIBCXX_USE_CXX11_ABI)>
_Safe;
template<typename _ItT, typename _SeqT, typename _CatT>
friend class ::__gnu_debug::_Safe_iterator;
public:
// types:
typedef _Traits traits_type;

View File

@ -66,6 +66,11 @@ namespace __debug
_Base_const_local_iterator;
typedef typename _Base::local_iterator _Base_local_iterator;
template<typename _ItT, typename _SeqT, typename _CatT>
friend class ::__gnu_debug::_Safe_iterator;
template<typename _ItT, typename _SeqT>
friend class ::__gnu_debug::_Safe_local_iterator;
public:
typedef typename _Base::size_type size_type;
typedef typename _Base::hasher hasher;
@ -752,6 +757,11 @@ namespace __debug
typedef typename _Base::const_local_iterator _Base_const_local_iterator;
typedef typename _Base::local_iterator _Base_local_iterator;
template<typename _ItT, typename _SeqT, typename _CatT>
friend class ::__gnu_debug::_Safe_iterator;
template<typename _ItT, typename _SeqT>
friend class ::__gnu_debug::_Safe_local_iterator;
public:
typedef typename _Base::size_type size_type;
typedef typename _Base::hasher hasher;
@ -768,7 +778,7 @@ namespace __debug
typedef __gnu_debug::_Safe_local_iterator<
_Base_local_iterator, unordered_multimap> local_iterator;
typedef __gnu_debug::_Safe_local_iterator<
_Base_const_local_iterator, unordered_multimap> const_local_iterator;
_Base_const_local_iterator, unordered_multimap> const_local_iterator;
unordered_multimap() = default;

View File

@ -66,6 +66,11 @@ namespace __debug
typedef typename _Base::const_local_iterator _Base_const_local_iterator;
typedef typename _Base::local_iterator _Base_local_iterator;
template<typename _ItT, typename _SeqT, typename _CatT>
friend class ::__gnu_debug::_Safe_iterator;
template<typename _ItT, typename _SeqT>
friend class ::__gnu_debug::_Safe_local_iterator;
public:
typedef typename _Base::size_type size_type;
typedef typename _Base::hasher hasher;
@ -629,6 +634,11 @@ namespace __debug
_Base_const_local_iterator;
typedef typename _Base::local_iterator _Base_local_iterator;
template<typename _ItT, typename _SeqT, typename _CatT>
friend class ::__gnu_debug::_Safe_iterator;
template<typename _ItT, typename _SeqT>
friend class ::__gnu_debug::_Safe_local_iterator;
public:
typedef typename _Base::size_type size_type;
typedef typename _Base::hasher hasher;
@ -645,7 +655,7 @@ namespace __debug
typedef __gnu_debug::_Safe_local_iterator<
_Base_local_iterator, unordered_multiset> local_iterator;
typedef __gnu_debug::_Safe_local_iterator<
_Base_const_local_iterator, unordered_multiset> const_local_iterator;
_Base_const_local_iterator, unordered_multiset> const_local_iterator;
unordered_multiset() = default;

View File

@ -127,6 +127,9 @@ namespace __debug
typedef typename _Base::const_iterator _Base_const_iterator;
typedef __gnu_debug::_Equal_to<_Base_const_iterator> _Equal;
template<typename _ItT, typename _SeqT, typename _CatT>
friend class ::__gnu_debug::_Safe_iterator;
public:
typedef typename _Base::reference reference;
typedef typename _Base::const_reference const_reference;
@ -789,7 +792,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_Iterator
__niter_base(const __gnu_debug::_Safe_iterator<
__gnu_cxx::__normal_iterator<_Iterator, _Container>,
_Sequence>& __it)
_Sequence, std::random_access_iterator_tag>& __it)
{ return std::__niter_base(__it.base()); }
_GLIBCXX_END_NAMESPACE_VERSION

View File

@ -0,0 +1,37 @@
// 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
// <http://www.gnu.org/licenses/>.
// { dg-do compile { target c++11 } }
#include <list>
void
test01()
{
// A list of int.
const std::list<int> nums = { 1, 2, 3, 4 };
// Grab the iterator type.
using list_itr_type = decltype( std::cbegin( nums ) );
// Confirm cend returns the same type.
static_assert( std::is_same< decltype( std::cend( nums ) ), list_itr_type >::value, "" );
// The list's iterator type provides a well-formed non-member operator-() with valid return type (long int)
using substraction_type
= decltype( std::declval<list_itr_type>() - std::declval<list_itr_type>() ); // { dg-error "no match for 'operator-'" }
}

View File

@ -21,31 +21,6 @@
#include <unordered_set>
#include <testsuite_hooks.h>
void test01()
{
using namespace __gnu_debug;
std::unordered_set<int> u = { 0, 1, 2 };
VERIFY( __check_dereferenceable(u.begin()) );
auto it = u.begin();
VERIFY( __check_dereferenceable(it) );
VERIFY( __check_dereferenceable(u.cbegin()) );
auto cit = u.begin();
VERIFY( __check_dereferenceable(cit) );
VERIFY( !__check_dereferenceable(u.end()) );
it = u.end();
VERIFY( !__check_dereferenceable(it) );
auto bucket = u.bucket(0);
VERIFY( __check_dereferenceable(u.begin(bucket)) );
auto lit = u.begin(bucket);
VERIFY( __check_dereferenceable(lit) );
VERIFY( !__check_dereferenceable(u.end(bucket)) );
}
void test02()
{
using namespace __gnu_debug;
@ -84,7 +59,6 @@ void test02()
int main()
{
test01();
test02();
return 0;
}

View File

@ -45,4 +45,4 @@ test02()
// { dg-error "value type is destructible" "" { target *-*-* } 0 }
// In Debug Mode the "required from here" errors come from <debug/vector>
// { dg-error "required from here" "" { target *-*-* } 155 }
// { dg-error "required from here" "" { target *-*-* } 158 }

View File

@ -20,28 +20,6 @@
#include <vector>
#include <testsuite_hooks.h>
void test01()
{
using namespace __gnu_debug;
std::vector<int> v1(3, 1);
VERIFY( __check_dereferenceable(v1.begin()) );
std::vector<int>::iterator it = v1.begin();
VERIFY( __check_dereferenceable(it) );
VERIFY( !__check_dereferenceable(v1.end()) );
it = v1.end();
VERIFY( !__check_dereferenceable(it) );
const volatile int* pi = 0;
VERIFY( !__check_dereferenceable(pi) );
int i;
pi = &i;
VERIFY( __check_dereferenceable(pi) );
}
void test02()
{
using namespace __gnu_debug;
@ -67,7 +45,6 @@ void test02()
int main()
{
test01();
test02();
return 0;
}

View File

@ -20,6 +20,7 @@
#ifndef _GLIBCXX_TESTSUITE_CONTAINERS_H
#define _GLIBCXX_TESTSUITE_CONTAINERS_H
#include <bits/boost_concept_check.h>
#include <cassert>
#include <testsuite_container_traits.h>
@ -191,6 +192,77 @@ namespace __gnu_test
forward_members_unordered(_Tp& container) { }
};
template<typename _Iterator,
bool _Mutable,
typename = typename std::iterator_traits<_Iterator>::iterator_category>
struct iterator_concept_checks;
template<typename _Iterator>
struct iterator_concept_checks<_Iterator, false,
std::forward_iterator_tag>
{
iterator_concept_checks()
{
using namespace __gnu_cxx;
__function_requires<_ForwardIteratorConcept<_Iterator>>();
}
};
template<typename _Iterator>
struct iterator_concept_checks<_Iterator, true,
std::forward_iterator_tag>
{
iterator_concept_checks()
{
using namespace __gnu_cxx;
__function_requires<_Mutable_ForwardIteratorConcept<_Iterator>>();
}
};
template<typename _Iterator>
struct iterator_concept_checks<_Iterator, false,
std::bidirectional_iterator_tag>
{
iterator_concept_checks()
{
using namespace __gnu_cxx;
__function_requires<_BidirectionalIteratorConcept<_Iterator>>();
}
};
template<typename _Iterator>
struct iterator_concept_checks<_Iterator, true,
std::bidirectional_iterator_tag>
{
iterator_concept_checks()
{
using namespace __gnu_cxx;
__function_requires<_Mutable_BidirectionalIteratorConcept<_Iterator>>();
}
};
template<typename _Iterator>
struct iterator_concept_checks<_Iterator, false,
std::random_access_iterator_tag>
{
iterator_concept_checks()
{
using namespace __gnu_cxx;
__function_requires<_RandomAccessIteratorConcept<_Iterator>>();
}
};
template<typename _Iterator>
struct iterator_concept_checks<_Iterator, true,
std::random_access_iterator_tag>
{
iterator_concept_checks()
{
using namespace __gnu_cxx;
__function_requires<_Mutable_RandomAccessIteratorConcept<_Iterator>>();
}
};
template<typename _Tp>
struct citerator
{