stl_iterator_base_types.h (_Iter_base): Limit definition to pre-C++11 mode.

2015-06-29  François Dumont  <fdumont@gcc.gnu.org>

	* include/bits/stl_iterator_base_types.h (_Iter_base): Limit definition
	to pre-C++11 mode.
	* include/debug/functions.h
	(__gnu_debug::__valid_range, __gnu_debug::__base): Move...
	* include/debug/safe_iterator.h
	(__gnu_debug::_Sequence_traits): New.
	(__gnu_debug::__get_distance_from_begin): New.
	(__gnu_debug::__get_distance_to_end): New.
	(__gnu_debug::_Safe_iterator<>::_M_valid_range): Expose iterator range
	distance information. Add optional check_dereferenceable parameter,
	default true.
	(__gnu_debug::_Distance_precision, __gnu_debug::__get_distance): Move
	default definition...
	(__gnu_debug::__get_distance): New overload for _Safe_iterator.
	(__gnu_debug::__unsafe): Likewise.
	* include/debug/helper_functions.h: ...here. New.
	(__gnu_debug::__unsafe): New helper function to remove safe iterator
	layer.
	* include/debug/stl_iterator.h: New. Include latter.
	* include/bits/stl_iterator.h: Include latter in debug mode.
	* include/debug/stl_iterator.tcc: Adapt.
	* include/debug/safe_local_iterator.h (__gnu_debug::__get_distance): Add
	overload for _Safe_local_iterator.
	(__gnu_debug::__unsafe): Likewise.
	* include/debug/safe_local_iterator.tcc: Adapt.
	* include/debug/macros.h (__glibcxx_check_valid_range2): New.
	(__glibcxx_check_insert_range): Add _Dist parameter.
	(__glibcxx_check_insert_range_after): Likewise.
	(__glibcxx_check_string, __glibcxx_check_string_len): Implement using
	_GLIBCXX_DEBUG_PEDASSERT.
	* include/debug/deque (deque<>::assign): Remove iterator debug layer
	when possible.
	(deque<>::insert): Likewise.
	* include/debug/forward_list (__glibcxx_check_valid_fl_range): New.
	(forward_list<>::splice_after): Use latter.
	(forward_list<>::assign): Remove iterator debug layer when possible.
	(forward_list<>::insert_after): Likewise.
	(__gnu_debug::_Sequence_traits<>): Partial specialization.
	* include/debug/list (list<>::assign): Remove iterator debug layer when
	possible.
	(list<>::insert): Likewise.
	[__gnu_debug::_Sequence_traits<>]: Partial specialization pre C++11 ABI.
	* include/debug/map.h (map<>::insert): Remove iterator debug layer when
	possible.
	* include/debug/multimap.h (multimap<>::insert): Likewise.
	* include/debug/set.h (set<>::insert): Likewise.
	* include/debug/multiset.h (multiset<>::insert): Likewise.
	* include/debug/string (basic_string<>::append, basic_string<>::assign,
	basic_string<>::insert, basic_string<>::replace): Likewise.
	* include/debug/unordered_map
	(unordered_map<>::insert, unordered_multimap<>::insert): Likewise.
	* include/debug/unordered_set
	(unordered_set<>::insert, unordered_multiset<>insert): Likewise.
	* include/debug/vector
	(vector<>::assign, vector<>::insert): Likewise.
	* include/Makefile.am: Add new debug headers.
	* include/Makefile.in: Regenerate.

From-SVN: r225143
This commit is contained in:
François Dumont 2015-06-29 20:17:56 +00:00
parent 755c71faf3
commit 24167c42e6
24 changed files with 904 additions and 246 deletions

View file

@ -1,3 +1,63 @@
2015-06-29 François Dumont <fdumont@gcc.gnu.org>
* include/bits/stl_iterator_base_types.h (_Iter_base): Limit definition
to pre-C++11 mode.
* include/debug/functions.h
(__gnu_debug::__valid_range, __gnu_debug::__base): Move...
* include/debug/safe_iterator.h
(__gnu_debug::_Sequence_traits): New.
(__gnu_debug::__get_distance_from_begin): New.
(__gnu_debug::__get_distance_to_end): New.
(__gnu_debug::_Safe_iterator<>::_M_valid_range): Expose iterator range
distance information. Add optional check_dereferenceable parameter,
default true.
(__gnu_debug::_Distance_precision, __gnu_debug::__get_distance): Move
default definition...
(__gnu_debug::__get_distance): New overload for _Safe_iterator.
(__gnu_debug::__unsafe): Likewise.
* include/debug/helper_functions.h: ...here. New.
(__gnu_debug::__unsafe): New helper function to remove safe iterator
layer.
* include/debug/stl_iterator.h: New. Include latter.
* include/bits/stl_iterator.h: Include latter in debug mode.
* include/debug/stl_iterator.tcc: Adapt.
* include/debug/safe_local_iterator.h (__gnu_debug::__get_distance): Add
overload for _Safe_local_iterator.
(__gnu_debug::__unsafe): Likewise.
* include/debug/safe_local_iterator.tcc: Adapt.
* include/debug/macros.h (__glibcxx_check_valid_range2): New.
(__glibcxx_check_insert_range): Add _Dist parameter.
(__glibcxx_check_insert_range_after): Likewise.
(__glibcxx_check_string, __glibcxx_check_string_len): Implement using
_GLIBCXX_DEBUG_PEDASSERT.
* include/debug/deque (deque<>::assign): Remove iterator debug layer
when possible.
(deque<>::insert): Likewise.
* include/debug/forward_list (__glibcxx_check_valid_fl_range): New.
(forward_list<>::splice_after): Use latter.
(forward_list<>::assign): Remove iterator debug layer when possible.
(forward_list<>::insert_after): Likewise.
(__gnu_debug::_Sequence_traits<>): Partial specialization.
* include/debug/list (list<>::assign): Remove iterator debug layer when
possible.
(list<>::insert): Likewise.
[__gnu_debug::_Sequence_traits<>]: Partial specialization pre C++11 ABI.
* include/debug/map.h (map<>::insert): Remove iterator debug layer when
possible.
* include/debug/multimap.h (multimap<>::insert): Likewise.
* include/debug/set.h (set<>::insert): Likewise.
* include/debug/multiset.h (multiset<>::insert): Likewise.
* include/debug/string (basic_string<>::append, basic_string<>::assign,
basic_string<>::insert, basic_string<>::replace): Likewise.
* include/debug/unordered_map
(unordered_map<>::insert, unordered_multimap<>::insert): Likewise.
* include/debug/unordered_set
(unordered_set<>::insert, unordered_multiset<>insert): Likewise.
* include/debug/vector
(vector<>::assign, vector<>::insert): Likewise.
* include/Makefile.am: Add new debug headers.
* include/Makefile.in: Regenerate.
2015-06-26 Jonathan Wakely <jwakely@redhat.com>
* doc/xml/manual/intro.xml: Document LWG 2108 status.

View file

@ -766,6 +766,7 @@ debug_headers = \
${debug_srcdir}/formatter.h \
${debug_srcdir}/forward_list \
${debug_srcdir}/functions.h \
${debug_srcdir}/helper_functions.h \
${debug_srcdir}/list \
${debug_srcdir}/map \
${debug_srcdir}/macros.h \
@ -785,6 +786,7 @@ debug_headers = \
${debug_srcdir}/safe_unordered_container.tcc \
${debug_srcdir}/set \
${debug_srcdir}/set.h \
${debug_srcdir}/stl_iterator.h \
${debug_srcdir}/string \
${debug_srcdir}/unordered_map \
${debug_srcdir}/unordered_set \

View file

@ -1047,6 +1047,7 @@ debug_headers = \
${debug_srcdir}/formatter.h \
${debug_srcdir}/forward_list \
${debug_srcdir}/functions.h \
${debug_srcdir}/helper_functions.h \
${debug_srcdir}/list \
${debug_srcdir}/map \
${debug_srcdir}/macros.h \
@ -1066,6 +1067,7 @@ debug_headers = \
${debug_srcdir}/safe_unordered_container.tcc \
${debug_srcdir}/set \
${debug_srcdir}/set.h \
${debug_srcdir}/stl_iterator.h \
${debug_srcdir}/string \
${debug_srcdir}/unordered_map \
${debug_srcdir}/unordered_set \

View file

@ -1246,4 +1246,8 @@ _GLIBCXX_END_NAMESPACE_VERSION
#define _GLIBCXX_MAKE_MOVE_IF_NOEXCEPT_ITERATOR(_Iter) (_Iter)
#endif // C++11
#ifdef _GLIBCXX_DEBUG
# include <debug/stl_iterator.h>
#endif
#endif

View file

@ -206,6 +206,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
//@}
#if __cplusplus < 201103L
// If _Iterator has a base returns it otherwise _Iterator is returned
// untouched
template<typename _Iterator, bool _HasBase>
@ -223,6 +224,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
static iterator_type _S_base(_Iterator __it)
{ return __it.base(); }
};
#endif
#if __cplusplus >= 201103L
template<typename _InIter>

View file

@ -169,9 +169,14 @@ namespace __debug
void
assign(_InputIterator __first, _InputIterator __last)
{
__glibcxx_check_valid_range(__first, __last);
_Base::assign(__gnu_debug::__base(__first),
__gnu_debug::__base(__last));
typename __gnu_debug::_Distance_traits<_InputIterator>::__type __dist;
__glibcxx_check_valid_range2(__first, __last, __dist);
if (__dist.second >= __gnu_debug::__dp_sign)
_Base::assign(__gnu_debug::__unsafe(__first),
__gnu_debug::__unsafe(__last));
else
_Base::assign(__first, __last);
this->_M_invalidate_all();
}
@ -460,10 +465,16 @@ namespace __debug
insert(const_iterator __position,
_InputIterator __first, _InputIterator __last)
{
__glibcxx_check_insert_range(__position, __first, __last);
_Base_iterator __res = _Base::insert(__position.base(),
__gnu_debug::__base(__first),
__gnu_debug::__base(__last));
typename __gnu_debug::_Distance_traits<_InputIterator>::__type __dist;
__glibcxx_check_insert_range(__position, __first, __last, __dist);
_Base_iterator __res;
if (__dist.second >= __gnu_debug::__dp_sign)
__res = _Base::insert(__position.base(),
__gnu_debug::__unsafe(__first),
__gnu_debug::__unsafe(__last));
else
__res = _Base::insert(__position.base(), __first, __last);
this->_M_invalidate_all();
return iterator(__res, this);
}
@ -473,9 +484,16 @@ namespace __debug
insert(iterator __position,
_InputIterator __first, _InputIterator __last)
{
__glibcxx_check_insert_range(__position, __first, __last);
_Base::insert(__position.base(), __gnu_debug::__base(__first),
__gnu_debug::__base(__last));
typename __gnu_debug::_Distance_traits<_InputIterator>::__type __dist;
__glibcxx_check_insert_range(__position, __first, __last, __dist);
if (__dist.second >= __gnu_debug::__dp_sign)
_Base::insert(__position.base(),
__gnu_debug::__unsafe(__first),
__gnu_debug::__unsafe(__last));
else
_Base::insert(__position.base(), __first, __last);
this->_M_invalidate_all();
}
#endif

View file

@ -36,6 +36,13 @@
#include <debug/safe_container.h>
#include <debug/safe_iterator.h>
// Special validity check for forward_list ranges.
#define __glibcxx_check_valid_fl_range(_First,_Last,_Dist) \
_GLIBCXX_DEBUG_VERIFY(_First._M_valid_range(_Last, _Dist, false), \
_M_message(__gnu_debug::__msg_valid_range) \
._M_iterator(_First, #_First) \
._M_iterator(_Last, #_Last))
namespace __gnu_debug
{
/// Special iterators swap and invalidation for forward_list because of the
@ -269,9 +276,15 @@ namespace __debug
void
assign(_InputIterator __first, _InputIterator __last)
{
__glibcxx_check_valid_range(__first, __last);
_Base::assign(__gnu_debug::__base(__first),
__gnu_debug::__base(__last));
typename __gnu_debug::_Distance_traits<_InputIterator>::__type __dist;
__glibcxx_check_valid_range2(__first, __last, __dist);
if (__dist.second >= __gnu_debug::__dp_sign)
_Base::assign(__gnu_debug::__unsafe(__first),
__gnu_debug::__unsafe(__last));
else
_Base::assign(__first, __last);
this->_M_invalidate_all();
}
@ -401,11 +414,19 @@ namespace __debug
insert_after(const_iterator __pos,
_InputIterator __first, _InputIterator __last)
{
__glibcxx_check_insert_range_after(__pos, __first, __last);
return iterator(_Base::insert_after(__pos.base(),
__gnu_debug::__base(__first),
__gnu_debug::__base(__last)),
this);
typename __gnu_debug::_Distance_traits<_InputIterator>::__type __dist;
__glibcxx_check_insert_range_after(__pos, __first, __last, __dist);
if (__dist.second >= __gnu_debug::__dp_sign)
return
{
_Base::insert_after(__pos.base(),
__gnu_debug::__unsafe(__first),
__gnu_debug::__unsafe(__last)),
this
};
else
return { _Base::insert_after(__pos.base(), __first, __last), this };
}
iterator
@ -580,9 +601,10 @@ namespace __debug
splice_after(const_iterator __pos, forward_list&& __list,
const_iterator __before, const_iterator __last)
{
typename __gnu_debug::_Distance_traits<const_iterator>::__type __dist;
auto __listptr = std::__addressof(__list);
__glibcxx_check_insert_after(__pos);
__glibcxx_check_valid_range(__before, __last);
__glibcxx_check_valid_fl_range(__before, __last, __dist);
_GLIBCXX_DEBUG_VERIFY(__before._M_attached_to(__listptr),
_M_message(__gnu_debug::__msg_splice_other)
._M_sequence(__list, "list")
@ -801,7 +823,7 @@ namespace __debug
namespace __gnu_debug
{
template<class _Tp, class _Alloc>
template<typename _Tp, typename _Alloc>
struct _BeforeBeginHelper<std::__debug::forward_list<_Tp, _Alloc> >
{
typedef std::__debug::forward_list<_Tp, _Alloc> _Sequence;
@ -820,6 +842,19 @@ namespace __gnu_debug
{ return _S_Is(__it); }
};
template<typename _Tp, typename _Alloc>
struct _Sequence_traits<std::__debug::forward_list<_Tp, _Alloc> >
{
typedef typename std::__debug::forward_list<_Tp, _Alloc>::iterator _It;
static typename _Distance_traits<_It>::__type
_S_size(const std::__debug::forward_list<_Tp, _Alloc>& __seq)
{
return __seq.empty()
? std::make_pair(0, __dp_exact) : std::make_pair(1, __dp_equality);
}
};
#ifndef _GLIBCXX_DEBUG_PEDANTIC
template<class _Tp, class _Alloc>
struct _Insert_range_from_self_is_safe<

View file

@ -29,11 +29,6 @@
#ifndef _GLIBCXX_DEBUG_FUNCTIONS_H
#define _GLIBCXX_DEBUG_FUNCTIONS_H 1
#include <bits/c++config.h>
#include <bits/stl_iterator_base_types.h> // for iterator_traits,
// categories and _Iter_base
#include <bits/cpp_type_traits.h> // for __is_integer
#include <bits/move.h> // for __addressof
#include <bits/stl_function.h> // for less
#if __cplusplus >= 201103L
@ -41,6 +36,7 @@
// conditional.
#endif
#include <debug/helper_functions.h>
#include <debug/formatter.h>
namespace __gnu_debug
@ -85,58 +81,6 @@ namespace __gnu_debug
__check_dereferenceable(const _Tp* __ptr)
{ return __ptr; }
/** If the distance between two random access iterators is
* nonnegative, assume the range is valid.
*/
template<typename _RandomAccessIterator>
inline bool
__valid_range_aux2(const _RandomAccessIterator& __first,
const _RandomAccessIterator& __last,
std::random_access_iterator_tag)
{ return __last - __first >= 0; }
/** Can't test for a valid range with input iterators, because
* iteration may be destructive. So we just assume that the range
* is valid.
*/
template<typename _InputIterator>
inline bool
__valid_range_aux2(const _InputIterator&, const _InputIterator&,
std::input_iterator_tag)
{ return true; }
/** We say that integral types for a valid range, and defer to other
* routines to realize what to do with integral types instead of
* iterators.
*/
template<typename _Integral>
inline bool
__valid_range_aux(const _Integral&, const _Integral&, std::__true_type)
{ return true; }
/** We have iterators, so figure out what kind of iterators that 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, std::__false_type)
{ return __valid_range_aux2(__first, __last,
std::__iterator_category(__first)); }
/** Don't know what these iterators are, or if they are even
* iterators (we may get an integral type for InputIterator), so
* see if they are integral and pass them on to the next phase
* otherwise.
*/
template<typename _InputIterator>
inline bool
__valid_range(const _InputIterator& __first, const _InputIterator& __last)
{
typedef typename std::__is_integer<_InputIterator>::__type _Integral;
return __valid_range_aux(__first, __last, _Integral());
}
/* 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.
@ -500,29 +444,6 @@ namespace __gnu_debug
return __first == __last;
}
// 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>
{ };
/** 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); }
} // namespace __gnu_debug
#endif

View file

@ -0,0 +1,210 @@
// Debugging support implementation -*- C++ -*-
// Copyright (C) 2003-2015 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
// terms of the GNU General Public License as published by the
// Free Software Foundation; either version 3, or (at your option)
// any later version.
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// Under Section 7 of GPL version 3, you are granted additional
// permissions described in the GCC Runtime Library Exception, version
// 3.1, as published by the Free Software Foundation.
// You should have received a copy of the GNU General Public License and
// a copy of the GCC Runtime Library Exception along with this program;
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
// <http://www.gnu.org/licenses/>.
/** @file debug/helper_functions.h
* This file is a GNU debug extension to the Standard C++ Library.
*/
#ifndef _GLIBCXX_DEBUG_HELPER_FUNCTIONS_H
#define _GLIBCXX_DEBUG_HELPER_FUNCTIONS_H 1
#include <bits/stl_iterator_base_types.h> // for iterator_traits,
// categories and _Iter_base
#include <bits/cpp_type_traits.h> // for __is_integer
#include <bits/stl_pair.h> // for pair
namespace __gnu_debug
{
/** The precision to which we can calculate the distance between
* two iterators.
*/
enum _Distance_precision
{
__dp_none, // Not even an iterator type
__dp_equality, //< Can compare iterator equality, only
__dp_sign, //< Can determine equality and ordering
__dp_exact //< Can determine distance precisely
};
template<typename _Iterator,
typename = typename std::__is_integer<_Iterator>::__type>
struct _Distance_traits
{
private:
typedef
typename std::iterator_traits<_Iterator>::difference_type _ItDiffType;
template<typename _DiffType,
typename = typename std::__is_void<_DiffType>::__type>
struct _DiffTraits
{ typedef _DiffType __type; };
template<typename _DiffType>
struct _DiffTraits<_DiffType, std::__true_type>
{ typedef std::ptrdiff_t __type; };
typedef typename _DiffTraits<_ItDiffType>::__type _DiffType;
public:
typedef std::pair<_DiffType, _Distance_precision> __type;
};
template<typename _Integral>
struct _Distance_traits<_Integral, std::__true_type>
{ typedef std::pair<std::ptrdiff_t, _Distance_precision> __type; };
/** Determine the distance between two iterators with some known
* precision.
*/
template<typename _Iterator>
inline typename _Distance_traits<_Iterator>::__type
__get_distance(const _Iterator& __lhs, const _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,
std::input_iterator_tag)
{
if (__lhs == __rhs)
return std::make_pair(0, __dp_exact);
return std::make_pair(1, __dp_equality);
}
template<typename _Iterator>
inline typename _Distance_traits<_Iterator>::__type
__get_distance(const _Iterator& __lhs, const _Iterator& __rhs)
{ return __get_distance(__lhs, __rhs, std::__iterator_category(__lhs)); }
/** We say that integral types for a valid range, and defer to other
* routines to realize what to do with integral types instead of
* iterators.
*/
template<typename _Integral>
inline bool
__valid_range_aux(const _Integral&, const _Integral&,
typename _Distance_traits<_Integral>::__type& __dist,
std::__true_type)
{
__dist = std::make_pair(0, __dp_none);
return true;
}
/** We have iterators, so figure out what kind of iterators that 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,
typename _Distance_traits<_InputIterator>::__type& __dist,
std::__false_type)
{
__dist = __get_distance(__first, __last);
switch (__dist.second)
{
case __dp_none:
break;
case __dp_equality:
if (__dist.first == 0)
return true;
break;
case __dp_sign:
case __dp_exact:
return __dist.first >= 0;
}
return true;
}
/** Don't know what these iterators are, or if they are even
* iterators (we may get an integral type for InputIterator), so
* see if they are integral and pass them on to the next phase
* otherwise.
*/
template<typename _InputIterator>
inline bool
__valid_range(const _InputIterator& __first, const _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 _InputIterator>
inline bool
__valid_range(const _InputIterator& __first, const _InputIterator& __last)
{
typename _Distance_traits<_InputIterator>::__type __dist;
return __valid_range(__first, __last, __dist);
}
#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>
{ };
/** 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
template<typename _Iterator>
inline _Iterator
__base(_Iterator __it)
{ return __it; }
#endif
#if __cplusplus < 201103L
template<typename _Iterator>
struct _Unsafe_type
{ typedef _Iterator _Type; };
#endif
/* Remove debug mode safe iterator layer, if any. */
template<typename _Iterator>
inline _Iterator
__unsafe(_Iterator __it)
{ return __it; }
}
#endif

View file

@ -177,9 +177,15 @@ namespace __debug
void
assign(_InputIterator __first, _InputIterator __last)
{
__glibcxx_check_valid_range(__first, __last);
_Base::assign(__gnu_debug::__base(__first),
__gnu_debug::__base(__last));
typename __gnu_debug::_Distance_traits<_InputIterator>::__type __dist;
__glibcxx_check_valid_range2(__first, __last, __dist);
if (__dist.second >= __gnu_debug::__dp_sign)
_Base::assign(__gnu_debug::__unsafe(__first),
__gnu_debug::__unsafe(__last));
else
_Base::assign(__first, __last);
this->_M_invalidate_all();
}
@ -441,11 +447,18 @@ namespace __debug
insert(const_iterator __position, _InputIterator __first,
_InputIterator __last)
{
__glibcxx_check_insert_range(__position, __first, __last);
return iterator(_Base::insert(__position.base(),
__gnu_debug::__base(__first),
__gnu_debug::__base(__last)),
this);
typename __gnu_debug::_Distance_traits<_InputIterator>::__type __dist;
__glibcxx_check_insert_range(__position, __first, __last, __dist);
if (__dist.second >= __gnu_debug::__dp_sign)
return
{
_Base::insert(__position.base(),
__gnu_debug::__unsafe(__first),
__gnu_debug::__unsafe(__last)),
this
};
else
return { _Base::insert(__position.base(), __first, __last), this };
}
#else
template<class _InputIterator>
@ -453,9 +466,14 @@ namespace __debug
insert(iterator __position, _InputIterator __first,
_InputIterator __last)
{
__glibcxx_check_insert_range(__position, __first, __last);
_Base::insert(__position.base(), __gnu_debug::__base(__first),
__gnu_debug::__base(__last));
typename __gnu_debug::_Distance_traits<_InputIterator>::__type __dist;
__glibcxx_check_insert_range(__position, __first, __last, __dist);
if (__dist.second >= __gnu_debug::__dp_sign)
_Base::insert(__position.base(), __gnu_debug::__unsafe(__first),
__gnu_debug::__unsafe(__last));
else
_Base::insert(__position.base(), __first, __last);
}
#endif
@ -795,13 +813,29 @@ namespace __debug
} // namespace __debug
} // namespace std
#ifndef _GLIBCXX_DEBUG_PEDANTIC
namespace __gnu_debug
{
#ifndef _GLIBCXX_USE_CXX11_ABI
// If not using C++11 list::size() is not in O(1) so we do not use it.
template<typename _Tp, typename _Alloc>
struct _Sequence_traits<std::__debug::list<_Tp, _Alloc> >
{
typedef typename std::__debug::list<_Tp, _Alloc>::iterator _It;
static typename _Distance_traits<_It>::__type
_S_size(const std::__debug::list<_Tp, _Alloc>& __seq)
{
return __seq.empty()
? std::make_pair(0, __dp_exact) : std::make_pair(1, __dp_equality);
}
};
#endif
#ifndef _GLIBCXX_DEBUG_PEDANTIC
template<class _Tp, class _Alloc>
struct _Insert_range_from_self_is_safe<std::__debug::list<_Tp, _Alloc> >
{ enum { __value = 1 }; };
}
#endif
}
#endif

View file

@ -56,6 +56,12 @@ _GLIBCXX_DEBUG_VERIFY(__gnu_debug::__valid_range(_First, _Last), \
._M_iterator(_First, #_First) \
._M_iterator(_Last, #_Last))
#define __glibcxx_check_valid_range2(_First,_Last,_Dist) \
_GLIBCXX_DEBUG_VERIFY(__gnu_debug::__valid_range(_First, _Last, _Dist), \
_M_message(__gnu_debug::__msg_valid_range) \
._M_iterator(_First, #_First) \
._M_iterator(_Last, #_Last))
// Verify that [_First, _Last) forms a non-empty iterator range.
#define __glibcxx_check_non_empty_range(_First,_Last) \
_GLIBCXX_DEBUG_VERIFY(_First != _Last, \
@ -104,8 +110,8 @@ _GLIBCXX_DEBUG_VERIFY(!_Position._M_is_end(), \
* Note that this macro is only valid when the container is a
* _Safe_sequence and the _Position iterator is a _Safe_iterator.
*/
#define __glibcxx_check_insert_range(_Position,_First,_Last) \
__glibcxx_check_valid_range(_First,_Last); \
#define __glibcxx_check_insert_range(_Position,_First,_Last,_Dist) \
__glibcxx_check_valid_range2(_First,_Last,_Dist); \
__glibcxx_check_insert(_Position); \
_GLIBCXX_DEBUG_VERIFY(__gnu_debug::__foreign_iterator(_Position,_First,_Last),\
_M_message(__gnu_debug::__msg_insert_range_from_self)\
@ -123,8 +129,8 @@ _GLIBCXX_DEBUG_VERIFY(__gnu_debug::__foreign_iterator(_Position,_First,_Last),\
* Note that this macro is only valid when the container is a
* _Safe_sequence and the _Position iterator is a _Safe_iterator.
*/
#define __glibcxx_check_insert_range_after(_Position,_First,_Last) \
__glibcxx_check_valid_range(_First,_Last); \
#define __glibcxx_check_insert_range_after(_Position,_First,_Last,_Dist)\
__glibcxx_check_valid_range2(_First,_Last,_Dist); \
__glibcxx_check_insert_after(_Position); \
_GLIBCXX_DEBUG_VERIFY(__gnu_debug::__foreign_iterator(_Position,_First,_Last),\
_M_message(__gnu_debug::__msg_insert_range_from_self)\
@ -352,13 +358,8 @@ _GLIBCXX_DEBUG_VERIFY(_This.get_allocator() == _Other.get_allocator(), \
_M_message(__gnu_debug::__msg_equal_allocs) \
._M_sequence(_This, "this"))
#ifdef _GLIBCXX_DEBUG_PEDANTIC
# define __glibcxx_check_string(_String) _GLIBCXX_DEBUG_ASSERT(_String != 0)
# define __glibcxx_check_string_len(_String,_Len) \
_GLIBCXX_DEBUG_ASSERT(_String != 0 || _Len == 0)
#else
# define __glibcxx_check_string(_String)
# define __glibcxx_check_string_len(_String,_Len)
#endif
#define __glibcxx_check_string(_String) _GLIBCXX_DEBUG_PEDASSERT(_String != 0)
#define __glibcxx_check_string_len(_String,_Len) \
_GLIBCXX_DEBUG_PEDASSERT(_String != 0 || _Len == 0)
#endif

View file

@ -307,9 +307,14 @@ namespace __debug
void
insert(_InputIterator __first, _InputIterator __last)
{
__glibcxx_check_valid_range(__first, __last);
_Base::insert(__gnu_debug::__base(__first),
__gnu_debug::__base(__last));
typename __gnu_debug::_Distance_traits<_InputIterator>::__type __dist;
__glibcxx_check_valid_range2(__first, __last, __dist);
if (__dist.second >= __gnu_debug::__dp_sign)
_Base::insert(__gnu_debug::__unsafe(__first),
__gnu_debug::__unsafe(__last));
else
_Base::insert(__first, __last);
}
#if __cplusplus >= 201103L

View file

@ -286,9 +286,14 @@ namespace __debug
void
insert(_InputIterator __first, _InputIterator __last)
{
__glibcxx_check_valid_range(__first, __last);
_Base::insert(__gnu_debug::__base(__first),
__gnu_debug::__base(__last));
typename __gnu_debug::_Distance_traits<_InputIterator>::__type __dist;
__glibcxx_check_valid_range2(__first, __last, __dist);
if (__dist.second >= __gnu_debug::__dp_sign)
_Base::insert(__gnu_debug::__unsafe(__first),
__gnu_debug::__unsafe(__last));
else
_Base::insert(__first, __last);
}
#if __cplusplus >= 201103L

View file

@ -271,9 +271,14 @@ namespace __debug
void
insert(_InputIterator __first, _InputIterator __last)
{
__glibcxx_check_valid_range(__first, __last);
_Base::insert(__gnu_debug::__base(__first),
__gnu_debug::__base(__last));
typename __gnu_debug::_Distance_traits<_InputIterator>::__type __dist;
__glibcxx_check_valid_range2(__first, __last, __dist);
if (__dist.second >= __gnu_debug::__dp_sign)
_Base::insert(__gnu_debug::__unsafe(__first),
__gnu_debug::__unsafe(__last));
else
_Base::insert(__first, __last);
}
#if __cplusplus >= 201103L

View file

@ -41,7 +41,7 @@ namespace __gnu_debug
/** Helper struct to deal with sequence offering a before_begin
* iterator.
**/
template <typename _Sequence>
template<typename _Sequence>
struct _BeforeBeginHelper
{
template<typename _Iterator>
@ -55,39 +55,17 @@ namespace __gnu_debug
{ return __it.base() == __it._M_get_sequence()->_M_base().begin(); }
};
/** The precision to which we can calculate the distance between
* two iterators.
*/
enum _Distance_precision
/** Sequence traits giving the size of a container if possible. */
template<typename _Sequence>
struct _Sequence_traits
{
__dp_equality, //< Can compare iterator equality, only
__dp_sign, //< Can determine equality and ordering
__dp_exact //< Can determine distance precisely
typedef _Distance_traits<typename _Sequence::iterator> _DistTraits;
static typename _DistTraits::__type
_S_size(const _Sequence& __seq)
{ return std::make_pair(__seq.size(), __dp_exact); }
};
/** Determine the distance between two iterators with some known
* precision.
*/
template<typename _Iterator>
inline std::pair<typename std::iterator_traits<_Iterator>::difference_type,
_Distance_precision>
__get_distance(const _Iterator& __lhs, const _Iterator& __rhs,
std::random_access_iterator_tag)
{ return std::make_pair(__rhs - __lhs, __dp_exact); }
template<typename _Iterator>
inline std::pair<typename std::iterator_traits<_Iterator>::difference_type,
_Distance_precision>
__get_distance(const _Iterator& __lhs, const _Iterator& __rhs,
std::forward_iterator_tag)
{ return std::make_pair(__lhs == __rhs? 0 : 1, __dp_equality); }
template<typename _Iterator>
inline std::pair<typename std::iterator_traits<_Iterator>::difference_type,
_Distance_precision>
__get_distance(const _Iterator& __lhs, const _Iterator& __rhs)
{ return __get_distance(__lhs, __rhs, std::__iterator_category(__lhs)); }
/** \brief Safe iterator wrapper.
*
* The class template %_Safe_iterator is a wrapper around an
@ -476,7 +454,9 @@ namespace __gnu_debug
// Is the iterator range [*this, __rhs) valid?
bool
_M_valid_range(const _Safe_iterator& __rhs) const;
_M_valid_range(const _Safe_iterator& __rhs,
std::pair<difference_type, _Distance_precision>& __dist,
bool __check_dereferenceable = true) const;
// The sequence this iterator references.
typename
@ -768,15 +748,157 @@ namespace __gnu_debug
template<typename _Iterator, typename _Sequence>
inline bool
__valid_range(const _Safe_iterator<_Iterator, _Sequence>& __first,
const _Safe_iterator<_Iterator, _Sequence>& __last)
{ return __first._M_valid_range(__last); }
const _Safe_iterator<_Iterator, _Sequence>& __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;
}
#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)
{ 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> >
{ typedef _Iterator _Type; };
#endif
template<typename _Iterator, typename _Sequence>
inline _Iterator
__unsafe(const _Safe_iterator<_Iterator, _Sequence>& __it)
{ return __it.base(); }
} // namespace __gnu_debug

View file

@ -38,12 +38,14 @@ namespace __gnu_debug
{
if (this->_M_singular())
return false;
if (__n == 0)
return true;
if (__n < 0)
{
std::pair<difference_type, _Distance_precision> __dist =
__get_distance(_M_get_sequence()->_M_base().begin(), base());
__get_distance_from_begin(*this);
bool __ok = ((__dist.second == __dp_exact && __dist.first >= -__n)
|| (__dist.second != __dp_exact && __dist.first > 0));
return __ok;
@ -51,7 +53,7 @@ namespace __gnu_debug
else
{
std::pair<difference_type, _Distance_precision> __dist =
__get_distance(base(), _M_get_sequence()->_M_base().end());
__get_distance_to_end(*this);
bool __ok = ((__dist.second == __dp_exact && __dist.first >= __n)
|| (__dist.second != __dp_exact && __dist.first > 0));
return __ok;
@ -61,37 +63,31 @@ namespace __gnu_debug
template<typename _Iterator, typename _Sequence>
bool
_Safe_iterator<_Iterator, _Sequence>::
_M_valid_range(const _Safe_iterator& __rhs) const
_M_valid_range(const _Safe_iterator& __rhs,
std::pair<difference_type, _Distance_precision>& __dist,
bool __check_dereferenceable) const
{
if (!_M_can_compare(__rhs))
return false;
/* Determine if we can order the iterators without the help of
the container */
std::pair<difference_type, _Distance_precision> __dist =
__get_distance(base(), __rhs.base());
switch (__dist.second) {
case __dp_equality:
if (__dist.first == 0)
return true;
break;
/* Determine iterators order */
__dist = __get_distance(*this, __rhs);
switch (__dist.second)
{
case __dp_equality:
if (__dist.first == 0)
return true;
break;
case __dp_sign:
case __dp_exact:
return __dist.first >= 0;
}
case __dp_sign:
case __dp_exact:
// If range is not empty first iterator must be dereferenceable.
if (__dist.first > 0)
return !__check_dereferenceable || _M_dereferenceable();
return __dist.first == 0;
}
/* We can only test for equality, but check if one of the
iterators is at an extreme. */
/* Optim for classic [begin, it) or [it, end) ranges, limit checks
* when code is valid. Note, for the special case of forward_list,
* before_begin replaces the role of begin. */
if (_M_is_beginnest() || __rhs._M_is_end())
return true;
if (_M_is_end() || __rhs._M_is_beginnest())
return false;
// Assume that this is a valid range; we can't check anything else
// Assume that this is a valid range; we can't check anything else.
return true;
}
} // namespace __gnu_debug

View file

@ -322,7 +322,9 @@ namespace __gnu_debug
// Is the iterator range [*this, __rhs) valid?
bool
_M_valid_range(const _Safe_local_iterator& __rhs) const;
_M_valid_range(const _Safe_local_iterator& __rhs,
std::pair<difference_type,
_Distance_precision>& __dist_info) const;
// The sequence this iterator references.
typename
@ -440,8 +442,66 @@ namespace __gnu_debug
template<typename _Iterator, typename _Sequence>
inline bool
__valid_range(const _Safe_local_iterator<_Iterator, _Sequence>& __first,
const _Safe_local_iterator<_Iterator, _Sequence>& __last)
{ return __first._M_valid_range(__last); }
const _Safe_local_iterator<_Iterator, _Sequence>& __last,
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)
{
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 };
}
#if __cplusplus < 201103L
template<typename _Iterator, typename _Sequence>
struct _Unsafe_type<_Safe_local_iterator<_Iterator, _Sequence> >
{ typedef _Iterator _Type; };
#endif
template<typename _Iterator, typename _Sequence>
inline _Iterator
__unsafe(const _Safe_local_iterator<_Iterator, _Sequence>& __it)
{ return __it.base(); }
} // namespace __gnu_debug
#include <debug/safe_local_iterator.tcc>

View file

@ -34,17 +34,18 @@ namespace __gnu_debug
template<typename _Iterator, typename _Sequence>
bool
_Safe_local_iterator<_Iterator, _Sequence>::
_M_valid_range(const _Safe_local_iterator& __rhs) const
_M_valid_range(const _Safe_local_iterator& __rhs,
std::pair<difference_type, _Distance_precision>& __dist) const
{
if (!_M_can_compare(__rhs))
return false;
if (bucket() != __rhs.bucket())
return false;
/* Determine if we can order the iterators without the help of
the container */
std::pair<difference_type, _Distance_precision> __dist =
__get_distance(base(), __rhs.base());
__dist = __get_distance(*this, __rhs);
switch (__dist.second)
{
case __dp_equality:
@ -57,15 +58,6 @@ namespace __gnu_debug
return __dist.first >= 0;
}
/* We can only test for equality, but check if one of the
iterators is at an extreme. */
/* Optim for classic [begin, it) or [it, end) ranges, limit checks
* when code is valid. */
if (_M_is_begin() || __rhs._M_is_end())
return true;
if (_M_is_end() || __rhs._M_is_begin())
return false;
// Assume that this is a valid range; we can't check anything else
return true;
}

View file

@ -280,9 +280,14 @@ namespace __debug
void
insert(_InputIterator __first, _InputIterator __last)
{
__glibcxx_check_valid_range(__first, __last);
_Base::insert(__gnu_debug::__base(__first),
__gnu_debug::__base(__last));
typename __gnu_debug::_Distance_traits<_InputIterator>::__type __dist;
__glibcxx_check_valid_range2(__first, __last, __dist);
if (__dist.second >= __gnu_debug::__dp_sign)
_Base::insert(__gnu_debug::__unsafe(__first),
__gnu_debug::__unsafe(__last));
else
_Base::insert(__first, __last);
}
#if __cplusplus >= 201103L

View file

@ -0,0 +1,113 @@
// Debugging support implementation -*- C++ -*-
// Copyright (C) 2015 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
// terms of the GNU General Public License as published by the
// Free Software Foundation; either version 3, or (at your option)
// any later version.
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// Under Section 7 of GPL version 3, you are granted additional
// permissions described in the GCC Runtime Library Exception, version
// 3.1, as published by the Free Software Foundation.
// You should have received a copy of the GNU General Public License and
// a copy of the GCC Runtime Library Exception along with this program;
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
// <http://www.gnu.org/licenses/>.
/** @file debug/stl_iterator.h
* This file is a GNU debug extension to the Standard C++ Library.
*/
#ifndef _GLIBCXX_DEBUG_STL_ITERATOR_H
#define _GLIBCXX_DEBUG_STL_ITERATOR_H 1
#include <debug/helper_functions.h>
namespace __gnu_debug
{
// Help Debug mode to see through reverse_iterator.
template<typename _Iterator>
inline bool
__valid_range(const std::reverse_iterator<_Iterator>& __first,
const std::reverse_iterator<_Iterator>& __last,
typename _Distance_traits<_Iterator>::__type& __dist)
{ return __valid_range(__last.base(), __first.base(), __dist); }
template<typename _Iterator>
inline typename _Distance_traits<_Iterator>::__type
__get_distance(const std::reverse_iterator<_Iterator>& __first,
const std::reverse_iterator<_Iterator>& __last)
{ return __get_distance(__last.base(), __first.base()); }
#if __cplusplus < 201103L
template<typename _Iterator>
struct __is_safe_random_iterator<std::reverse_iterator<_Iterator> >
: __is_safe_random_iterator<_Iterator>
{ };
template<typename _Iterator>
struct _Unsafe_type<std::reverse_iterator<_Iterator> >
{
typedef typename _Unsafe_type<_Iterator>::_Type _UnsafeType;
typedef std::reverse_iterator<_UnsafeType> _Type;
};
template<typename _Iterator>
inline std::reverse_iterator<typename _Unsafe_type<_Iterator>::_Type>
__unsafe(const std::reverse_iterator<_Iterator>& __it)
{
typedef typename _Unsafe_type<_Iterator>::_Type _UnsafeType;
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)
-> decltype(std::__make_reverse_iterator(__unsafe(__it.base())))
{ return std::__make_reverse_iterator(__unsafe(__it.base())); }
#endif
#if __cplusplus >= 201103L
// Help Debug mode to see through move_iterator.
template<typename _Iterator>
inline bool
__valid_range(const std::move_iterator<_Iterator>& __first,
const std::move_iterator<_Iterator>& __last,
typename _Distance_traits<_Iterator>::__type& __dist)
{ return __valid_range(__first.base(), __last.base(), __dist); }
template<typename _Iterator>
inline typename _Distance_traits<_Iterator>::__type
__get_distance(const std::move_iterator<_Iterator>& __first,
const std::move_iterator<_Iterator>& __last)
{ return __get_distance(__first.base(), __last.base()); }
template<typename _Iterator>
inline auto
__unsafe(const std::move_iterator<_Iterator>& __it)
-> decltype(std::make_move_iterator(__unsafe(__it.base())))
{ return std::make_move_iterator(__unsafe(__it.base())); }
template<typename _Iterator>
inline auto
__base(const std::move_iterator<_Iterator>& __it)
-> decltype(std::make_move_iterator(__base(__it.base())))
{ return std::make_move_iterator(__base(__it.base())); }
#endif
}
#endif

View file

@ -380,9 +380,15 @@ namespace __gnu_debug
basic_string&
append(_InputIterator __first, _InputIterator __last)
{
__glibcxx_check_valid_range(__first, __last);
_Base::append(__gnu_debug::__base(__first),
__gnu_debug::__base(__last));
typename __gnu_debug::_Distance_traits<_InputIterator>::__type __dist;
__glibcxx_check_valid_range2(__first, __last, __dist);
if (__dist.second >= __dp_sign)
_Base::append(__gnu_debug::__unsafe(__first),
__gnu_debug::__unsafe(__last));
else
_Base::append(__first, __last);
this->_M_invalidate_all();
return *this;
}
@ -452,9 +458,15 @@ namespace __gnu_debug
basic_string&
assign(_InputIterator __first, _InputIterator __last)
{
__glibcxx_check_valid_range(__first, __last);
_Base::assign(__gnu_debug::__base(__first),
__gnu_debug::__base(__last));
typename __gnu_debug::_Distance_traits<_InputIterator>::__type __dist;
__glibcxx_check_valid_range2(__first, __last, __dist);
if (__dist.second >= __dp_sign)
_Base::assign(__gnu_debug::__unsafe(__first),
__gnu_debug::__unsafe(__last));
else
_Base::assign(__first, __last);
this->_M_invalidate_all();
return *this;
}
@ -533,9 +545,15 @@ namespace __gnu_debug
void
insert(iterator __p, _InputIterator __first, _InputIterator __last)
{
__glibcxx_check_insert_range(__p, __first, __last);
_Base::insert(__p.base(), __gnu_debug::__base(__first),
__gnu_debug::__base(__last));
typename __gnu_debug::_Distance_traits<_InputIterator>::__type __dist;
__glibcxx_check_insert_range2(__p, __first, __last, __dist);
if (__dist.second >= __dp_sign)
_Base::insert(__p.base(), __gnu_debug::__unsafe(__first),
__gnu_debug::__unsafe(__last));
else
_Base::insert(__p.base(), __first, __last);
this->_M_invalidate_all();
}
@ -676,8 +694,17 @@ namespace __gnu_debug
_InputIterator __j1, _InputIterator __j2)
{
__glibcxx_check_erase_range(__i1, __i2);
__glibcxx_check_valid_range(__j1, __j2);
_Base::replace(__i1.base(), __i2.base(), __j1, __j2);
typename __gnu_debug::_Distance_traits<_InputIterator>::__type __dist;
__glibcxx_check_valid_range2(__j1, __j2, __dist);
if (__dist.second >= __dp_sign)
_Base::replace(__i1.base(), __i2.base(),
__gnu_debug::__unsafe(__j1),
__gnu_debug::__unsafe(__j2));
else
_Base::replace(__i1.base(), __i2.base(), __j1, __j2);
this->_M_invalidate_all();
return *this;
}

View file

@ -364,10 +364,16 @@ namespace __debug
void
insert(_InputIterator __first, _InputIterator __last)
{
__glibcxx_check_valid_range(__first, __last);
typename __gnu_debug::_Distance_traits<_InputIterator>::__type __dist;
__glibcxx_check_valid_range2(__first, __last, __dist);
size_type __bucket_count = this->bucket_count();
_Base::insert(__gnu_debug::__base(__first),
__gnu_debug::__base(__last));
if (__dist.second >= __gnu_debug::__dp_sign)
_Base::insert(__gnu_debug::__unsafe(__first),
__gnu_debug::__unsafe(__last));
else
_Base::insert(__first, __last);
_M_check_rehashed(__bucket_count);
}
@ -809,10 +815,16 @@ namespace __debug
void
insert(_InputIterator __first, _InputIterator __last)
{
__glibcxx_check_valid_range(__first, __last);
typename __gnu_debug::_Distance_traits<_InputIterator>::__type __dist;
__glibcxx_check_valid_range2(__first, __last, __dist);
size_type __bucket_count = this->bucket_count();
_Base::insert(__gnu_debug::__base(__first),
__gnu_debug::__base(__last));
if (__dist.second >= __gnu_debug::__dp_sign)
_Base::insert(__gnu_debug::__unsafe(__first),
__gnu_debug::__unsafe(__last));
else
_Base::insert(__first, __last);
_M_check_rehashed(__bucket_count);
}

View file

@ -355,10 +355,16 @@ namespace __debug
void
insert(_InputIterator __first, _InputIterator __last)
{
__glibcxx_check_valid_range(__first, __last);
typename __gnu_debug::_Distance_traits<_InputIterator>::__type __dist;
__glibcxx_check_valid_range2(__first, __last, __dist);
size_type __bucket_count = this->bucket_count();
_Base::insert(__gnu_debug::__base(__first),
__gnu_debug::__base(__last));
if (__dist.second >= __gnu_debug::__dp_sign)
_Base::insert(__gnu_debug::__unsafe(__first),
__gnu_debug::__unsafe(__last));
else
_Base::insert(__first, __last);
_M_check_rehashed(__bucket_count);
}
@ -799,10 +805,16 @@ namespace __debug
void
insert(_InputIterator __first, _InputIterator __last)
{
__glibcxx_check_valid_range(__first, __last);
typename __gnu_debug::_Distance_traits<_InputIterator>::__type __dist;
__glibcxx_check_valid_range2(__first, __last, __dist);
size_type __bucket_count = this->bucket_count();
_Base::insert(__gnu_debug::__base(__first),
__gnu_debug::__base(__last));
if (__dist.second >= __gnu_debug::__dp_sign)
_Base::insert(__gnu_debug::__unsafe(__first),
__gnu_debug::__unsafe(__last));
else
_Base::insert(__first, __last);
_M_check_rehashed(__bucket_count);
}

View file

@ -244,9 +244,15 @@ namespace __debug
void
assign(_InputIterator __first, _InputIterator __last)
{
__glibcxx_check_valid_range(__first, __last);
_Base::assign(__gnu_debug::__base(__first),
__gnu_debug::__base(__last));
typename __gnu_debug::_Distance_traits<_InputIterator>::__type __dist;
__glibcxx_check_valid_range2(__first, __last, __dist);
if (__dist.second >= __gnu_debug::__dp_sign)
_Base::assign(__gnu_debug::__unsafe(__first),
__gnu_debug::__unsafe(__last));
else
_Base::assign(__first, __last);
this->_M_invalidate_all();
this->_M_update_guaranteed_capacity();
}
@ -574,16 +580,21 @@ namespace __debug
insert(const_iterator __position,
_InputIterator __first, _InputIterator __last)
{
__glibcxx_check_insert_range(__position, __first, __last);
typename __gnu_debug::_Distance_traits<_InputIterator>::__type __dist;
__glibcxx_check_insert_range(__position, __first, __last, __dist);
/* Hard to guess if invalidation will occur, because __last
- __first can't be calculated in all cases, so we just
punt here by checking if it did occur. */
_Base_iterator __old_begin = _M_base().begin();
difference_type __offset = __position.base() - _Base::cbegin();
_Base_iterator __res = _Base::insert(__position.base(),
__gnu_debug::__base(__first),
__gnu_debug::__base(__last));
_Base_iterator __res;
if (__dist.second >= __gnu_debug::__dp_sign)
__res = _Base::insert(__position.base(),
__gnu_debug::__unsafe(__first),
__gnu_debug::__unsafe(__last));
else
__res = _Base::insert(__position.base(), __first, __last);
if (_M_base().begin() != __old_begin)
this->_M_invalidate_all();
@ -598,15 +609,19 @@ namespace __debug
insert(iterator __position,
_InputIterator __first, _InputIterator __last)
{
__glibcxx_check_insert_range(__position, __first, __last);
typename __gnu_debug::_Distance_traits<_InputIterator>::__type __dist;
__glibcxx_check_insert_range(__position, __first, __last, __dist);
/* Hard to guess if invalidation will occur, because __last
- __first can't be calculated in all cases, so we just
punt here by checking if it did occur. */
_Base_iterator __old_begin = _M_base().begin();
difference_type __offset = __position.base() - _Base::begin();
_Base::insert(__position.base(), __gnu_debug::__base(__first),
__gnu_debug::__base(__last));
if (__dist.second >= __gnu_debug::__dp_sign)
_Base::insert(__position.base(), __gnu_debug::__unsafe(__first),
__gnu_debug::__unsafe(__last));
else
_Base::insert(__position.base(), __first, __last);
if (_M_base().begin() != __old_begin)
this->_M_invalidate_all();