From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 30447 invoked by alias); 12 Jun 2015 17:12:03 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Received: (qmail 30421 invoked by uid 89); 12 Jun 2015 17:12:02 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-0.8 required=5.0 tests=AWL,BAYES_50,FREEMAIL_FROM,KAM_ASCII_DIVIDERS,RCVD_IN_DNSWL_LOW,SPF_PASS autolearn=no version=3.3.2 X-Spam-User: qpsmtpd, 2 recipients X-HELO: mail-wi0-f176.google.com Received: from mail-wi0-f176.google.com (HELO mail-wi0-f176.google.com) (209.85.212.176) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES128-GCM-SHA256 encrypted) ESMTPS; Fri, 12 Jun 2015 17:11:56 +0000 Received: by wigg3 with SMTP id g3so22656021wig.1; Fri, 12 Jun 2015 10:11:53 -0700 (PDT) X-Received: by 10.194.5.4 with SMTP id o4mr28714550wjo.51.1434129112994; Fri, 12 Jun 2015 10:11:52 -0700 (PDT) Received: from [192.168.0.22] (arf62-1-82-237-250-248.fbx.proxad.net. [82.237.250.248]) by mx.google.com with ESMTPSA id j7sm6691624wjz.11.2015.06.12.10.11.50 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 12 Jun 2015 10:11:51 -0700 (PDT) Message-ID: <557B12D5.7070605@gmail.com> Date: Fri, 12 Jun 2015 18:18:00 -0000 From: =?UTF-8?B?RnJhbsOnb2lzIER1bW9udA==?= User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:31.0) Gecko/20100101 Thunderbird/31.7.0 MIME-Version: 1.0 To: "libstdc++@gcc.gnu.org" , gcc-patches Subject: Debug mode enhancements Content-Type: multipart/mixed; boundary="------------080909080307070604060209" X-SW-Source: 2015-06/txt/msg00945.txt.bz2 This is a multi-part message in MIME format. --------------080909080307070604060209 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit Content-length: 4164 Hi This is a patch to: - Enhance __get_distance to get a better feedback about distance between iterators so that we can take sharper decision about what is right or not. This function is now aware about safe iterators and leverage on those a little like std::distance does with C++ 11 list::iterator. - Make debug mode aware about iterator adapters reverse_iterator and move_iterator. - Thanks to previous points this patch also extend situations where it is possible to remove debug layers on iterators to lower performance hint of this mode. We now detect at runtime if we know enough about the iterator range to get rid of the potential debug layer. For the last point I introduced __gnu_debug::__unsafe which remove debug layer unconditionally in opposition to __gnu_debug::__base which do so only for random access iterator. The latter has been kept to be used in context of constructors. I had to introduced new debug headers to limit impact in stl_iterator.h. We shall not include debug.h here as the purpose is not to inject debug checks in the normal code. Note that the new __get_distance will be very useful to implement proper debug algos Here is the tricky part for me, the ChangeLog entry, much more complicated than the code :-) * 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. * 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. Being fully tested under Linux x86_64. François --------------080909080307070604060209 Content-Type: text/x-patch; name="get_distance.patch" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="get_distance.patch" Content-length: 55689 Index: include/Makefile.am =================================================================== --- include/Makefile.am (revision 224246) +++ include/Makefile.am (working copy) @@ -766,6 +766,7 @@ ${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_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 \ Index: include/Makefile.in =================================================================== --- include/Makefile.in (revision 224246) +++ include/Makefile.in (working copy) @@ -1047,6 +1047,7 @@ ${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_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 \ Index: include/bits/stl_iterator.h =================================================================== --- include/bits/stl_iterator.h (revision 224246) +++ include/bits/stl_iterator.h (working copy) @@ -1246,4 +1246,8 @@ #define _GLIBCXX_MAKE_MOVE_IF_NOEXCEPT_ITERATOR(_Iter) (_Iter) #endif // C++11 +#ifdef _GLIBCXX_DEBUG +# include #endif + +#endif Index: include/bits/stl_iterator_base_types.h =================================================================== --- include/bits/stl_iterator_base_types.h (revision 224246) +++ include/bits/stl_iterator_base_types.h (working copy) @@ -206,6 +206,7 @@ //@} +#if __cplusplus < 201103L // If _Iterator has a base returns it otherwise _Iterator is returned // untouched template @@ -223,6 +224,7 @@ static iterator_type _S_base(_Iterator __it) { return __it.base(); } }; +#endif #if __cplusplus >= 201103L template Index: include/debug/deque =================================================================== --- include/debug/deque (revision 224246) +++ include/debug/deque (working copy) @@ -169,9 +169,14 @@ 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 @@ 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 @@ 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 Index: include/debug/forward_list =================================================================== --- include/debug/forward_list (revision 224246) +++ include/debug/forward_list (working copy) @@ -36,6 +36,13 @@ #include #include +// 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 @@ -266,9 +273,15 @@ 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(); } @@ -398,11 +411,19 @@ 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 @@ -577,8 +598,9 @@ splice_after(const_iterator __pos, forward_list&& __list, const_iterator __before, const_iterator __last) { + typename __gnu_debug::_Distance_traits::__type __dist; __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(&__list), _M_message(__gnu_debug::__msg_splice_other) ._M_sequence(__list, "list") @@ -797,7 +819,7 @@ namespace __gnu_debug { - template + template struct _BeforeBeginHelper > { typedef std::__debug::forward_list<_Tp, _Alloc> _Sequence; @@ -816,6 +838,19 @@ { return _S_Is(__it); } }; + template + struct _Sequence_traits > + { + 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 struct _Insert_range_from_self_is_safe< Index: include/debug/functions.h =================================================================== --- include/debug/functions.h (revision 224246) +++ include/debug/functions.h (working copy) @@ -29,11 +29,6 @@ #ifndef _GLIBCXX_DEBUG_FUNCTIONS_H #define _GLIBCXX_DEBUG_FUNCTIONS_H 1 -#include -#include // for iterator_traits, - // categories and _Iter_base -#include // for __is_integer - #include // for __addressof #include // for less #if __cplusplus >= 201103L @@ -41,6 +36,7 @@ // conditional. #endif +#include #include namespace __gnu_debug @@ -85,58 +81,6 @@ __check_dereferenceable(const _Tp* __ptr) { return __ptr; } - /** If the distance between two random access iterators is - * nonnegative, assume the range is valid. - */ - template - 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 - 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 - 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 - 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 - 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 @@ return __first == __last; } - // Helper struct to detect random access safe iterators. - template - struct __is_safe_random_iterator - { - enum { __value = 0 }; - typedef std::__false_type __type; - }; - - template - 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 - inline typename _Siter_base<_Iterator>::iterator_type - __base(_Iterator __it) - { return _Siter_base<_Iterator>::_S_base(__it); } } // namespace __gnu_debug #endif Index: include/debug/helper_functions.h =================================================================== --- include/debug/helper_functions.h (revision 0) +++ include/debug/helper_functions.h (working copy) @@ -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 +// . + +/** @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 // for iterator_traits, + // categories and _Iter_base +#include // for __is_integer + +#include // 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::__type> + struct _Distance_traits + { + private: + typedef + typename std::iterator_traits<_Iterator>::difference_type _ItDiffType; + + template::__type> + struct _DiffTraits + { typedef _DiffType __type; }; + + template + 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 + struct _Distance_traits<_Integral, std::__true_type> + { typedef std::pair __type; }; + + /** Determine the distance between two iterators with some known + * precision. + */ + template + 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 + 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 + 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 + 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 + 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 + 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 + 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 + struct __is_safe_random_iterator + { + enum { __value = 0 }; + typedef std::__false_type __type; + }; + + template + 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 + inline typename _Siter_base<_Iterator>::iterator_type + __base(_Iterator __it) + { return _Siter_base<_Iterator>::_S_base(__it); } +#else + template + inline _Iterator + __base(_Iterator __it) + { return __it; } +#endif + +#if __cplusplus < 201103L + template + struct _Unsafe_type + { typedef _Iterator _Type; }; +#endif + + /* Remove debug mode safe iterator layer, if any. */ + template + inline _Iterator + __unsafe(_Iterator __it) + { return __it; } +} + +#endif Index: include/debug/list =================================================================== --- include/debug/list (revision 224246) +++ include/debug/list (working copy) @@ -171,9 +171,15 @@ 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(); } @@ -435,11 +441,18 @@ 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 @@ -447,9 +460,14 @@ 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 @@ -788,13 +806,29 @@ } // 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 + struct _Sequence_traits > + { + 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 struct _Insert_range_from_self_is_safe > { enum { __value = 1 }; }; +#endif } -#endif #endif Index: include/debug/macros.h =================================================================== --- include/debug/macros.h (revision 224246) +++ include/debug/macros.h (working copy) @@ -56,6 +56,12 @@ ._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 @@ * 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 @@ * 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)\ Index: include/debug/map.h =================================================================== --- include/debug/map.h (revision 224246) +++ include/debug/map.h (working copy) @@ -307,9 +307,14 @@ 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 Index: include/debug/multimap.h =================================================================== --- include/debug/multimap.h (revision 224246) +++ include/debug/multimap.h (working copy) @@ -286,9 +286,14 @@ 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 Index: include/debug/multiset.h =================================================================== --- include/debug/multiset.h (revision 224246) +++ include/debug/multiset.h (working copy) @@ -271,9 +271,14 @@ 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 Index: include/debug/safe_iterator.h =================================================================== --- include/debug/safe_iterator.h (revision 224246) +++ include/debug/safe_iterator.h (working copy) @@ -41,7 +41,7 @@ /** Helper struct to deal with sequence offering a before_begin * iterator. **/ - template + template struct _BeforeBeginHelper { template @@ -55,39 +55,17 @@ { 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 + 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 _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 - inline std::pair::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 - inline std::pair::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 - inline std::pair::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 @@ // 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& __dist, + bool __check_dereferenceable = true) const; // The sequence this iterator references. typename @@ -768,16 +748,158 @@ template 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 + 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 + 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 + 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 + 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 struct __is_safe_random_iterator<_Safe_iterator<_Iterator, _Sequence> > : std::__are_same:: iterator_category> { }; +#else + template + _Iterator + __base(const _Safe_iterator<_Iterator, _Sequence>& __it, + std::random_access_iterator_tag) + { return __it.base(); } + template + const _Safe_iterator<_Iterator, _Sequence>& + __base(const _Safe_iterator<_Iterator, _Sequence>& __it, + std::input_iterator_tag) + { return __it; } + + template + 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 + struct _Unsafe_type<_Safe_iterator<_Iterator, _Sequence> > + { typedef _Iterator _Type; }; +#endif + + template + inline _Iterator + __unsafe(const _Safe_iterator<_Iterator, _Sequence>& __it) + { return __it.base(); } + } // namespace __gnu_debug #include Index: include/debug/safe_iterator.tcc =================================================================== --- include/debug/safe_iterator.tcc (revision 224246) +++ include/debug/safe_iterator.tcc (working copy) @@ -38,12 +38,14 @@ { if (this->_M_singular()) return false; + if (__n == 0) return true; + if (__n < 0) { std::pair __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 @@ else { std::pair __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 @@ template bool _Safe_iterator<_Iterator, _Sequence>:: - _M_valid_range(const _Safe_iterator& __rhs) const + _M_valid_range(const _Safe_iterator& __rhs, + std::pair& __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 __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 Index: include/debug/safe_local_iterator.h =================================================================== --- include/debug/safe_local_iterator.h (revision 224246) +++ include/debug/safe_local_iterator.h (working copy) @@ -322,7 +322,9 @@ // 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& __dist_info) const; // The sequence this iterator references. typename @@ -440,8 +442,66 @@ template 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 + inline std::pair::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 + struct _Unsafe_type<_Safe_local_iterator<_Iterator, _Sequence> > + { typedef _Iterator _Type; }; +#endif + + template + inline _Iterator + __unsafe(const _Safe_local_iterator<_Iterator, _Sequence>& __it) + { return __it.base(); } + } // namespace __gnu_debug #include Index: include/debug/safe_local_iterator.tcc =================================================================== --- include/debug/safe_local_iterator.tcc (revision 224246) +++ include/debug/safe_local_iterator.tcc (working copy) @@ -34,17 +34,18 @@ template 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& __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 __dist = - __get_distance(base(), __rhs.base()); + __dist = __get_distance(*this, __rhs); switch (__dist.second) { case __dp_equality: @@ -57,15 +58,6 @@ 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; } Index: include/debug/set.h =================================================================== --- include/debug/set.h (revision 224246) +++ include/debug/set.h (working copy) @@ -280,9 +280,14 @@ 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 Index: include/debug/stl_iterator.h =================================================================== --- include/debug/stl_iterator.h (revision 0) +++ include/debug/stl_iterator.h (working copy) @@ -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 +// . + +/** @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 + +namespace __gnu_debug +{ + // Help Debug mode to see through reverse_iterator. + template + 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 + 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 + struct __is_safe_random_iterator > + : __is_safe_random_iterator<_Iterator> + { }; + + template + struct _Unsafe_type > + { + typedef typename _Unsafe_type<_Iterator>::_Type _UnsafeType; + typedef std::reverse_iterator<_UnsafeType> _Type; + }; + + template + inline std::reverse_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 + 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 + 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 + 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 + 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 + 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 + 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 Index: include/debug/string =================================================================== --- include/debug/string (revision 224246) +++ include/debug/string (working copy) @@ -379,9 +379,15 @@ 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; } @@ -451,9 +457,15 @@ 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; } @@ -532,9 +544,15 @@ 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(); } @@ -675,8 +693,17 @@ _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; } Index: include/debug/unordered_map =================================================================== --- include/debug/unordered_map (revision 224246) +++ include/debug/unordered_map (working copy) @@ -364,10 +364,16 @@ 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 @@ 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); } Index: include/debug/unordered_set =================================================================== --- include/debug/unordered_set (revision 224246) +++ include/debug/unordered_set (working copy) @@ -355,10 +355,16 @@ 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 @@ 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); } Index: include/debug/vector =================================================================== --- include/debug/vector (revision 224246) +++ include/debug/vector (working copy) @@ -244,9 +244,15 @@ 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,7 +580,8 @@ 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 @@ -581,9 +588,13 @@ 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,7 +609,8 @@ 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 @@ -605,8 +617,11 @@ 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(); --------------080909080307070604060209--