From patchwork Thu Aug 2 20:16:24 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Fran=C3=A7ois_Dumont?= X-Patchwork-Id: 952960 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=gcc.gnu.org (client-ip=209.132.180.131; helo=sourceware.org; envelope-from=gcc-patches-return-483063-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="RFyQsbGa"; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="MN7rdled"; dkim-atps=neutral Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 41hM0K00Wzz9s0R for ; Fri, 3 Aug 2018 06:17:02 +1000 (AEST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :subject:to:message-id:date:mime-version:content-type; q=dns; s= default; b=lzvP3BVQkbFKpt1u9o9ym6FCAqfeYhugp9WovWtD8bmcBb4QivFlV xYlsYnbALPe5fz1A/hYhhGAKp710iu9/FEFT+yNgphQrEyz782rp5gEE7BfdSOni Qjtcu8rElmtf6p6VEFdSLEw75NA8pmJjcRalyts3pelXHZh/OeREbY= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :subject:to:message-id:date:mime-version:content-type; s= default; bh=YF8nlwNOrVtIgzxaXnXPpDANTyo=; b=RFyQsbGaRimQ5uWhJPLr 65hCBvTYHz1qcbU+P5WrdrmKKyt/DyA5GKU/LD3KxtLoDlgFYFius3Di+Kn2RC/0 keV0So7EF27ljcOITRumLGT6Z1xCmpbwwx4F/z8YIXPARFErQfv9X0HeR0sA1Kef 2Ig1NQx9z+drG8TH0qR2j3w= Received: (qmail 130305 invoked by alias); 2 Aug 2018 20:16:40 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 130267 invoked by uid 89); 2 Aug 2018 20:16:39 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-25.2 required=5.0 tests=AWL, BAYES_00, FREEMAIL_FROM, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, KAM_SHORT, RCVD_IN_DNSWL_NONE, SPF_PASS autolearn=ham version=3.3.2 spammy=Inheritance, ccc, lvalue, value_type X-HELO: mail-wm0-f54.google.com Received: from mail-wm0-f54.google.com (HELO mail-wm0-f54.google.com) (74.125.82.54) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Thu, 02 Aug 2018 20:16:30 +0000 Received: by mail-wm0-f54.google.com with SMTP id y2-v6so3900321wma.1; Thu, 02 Aug 2018 13:16:29 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:subject:to:message-id:date:user-agent:mime-version :content-language; bh=VbDwU7Ft1kNNPdsSdm+wtrbvbamT+bDXZDKjn+Hx1Pc=; b=MN7rdledf9sn7cRr6/lqJx46y/19OrdncIX0DWmw0zQ8D1yURUYyAVAcL1oB5uVI/Z PPhBc06eZC+nIZdj+MZRKL818y3yND1tlY3xpmfy7cIYrRA2Bpn/p64Cd4JYVhX+R/DR mXNcbvGTdaYPjHx1DC2sqnPRLNa4ABCyJkn34KzvY3fdyfwm2ZQwCfnXINg4d3RLlwMi 53LfhP23i2BI7Wp4LgnxwE8IbnU7HnbqAVXjWggqIeKIfz8rrwz2ZFCHqtSxE63s0vDA pPmL51IKRp1skiUau/+hS/fnmTR8/JnhvCLAMHcWXlg1RgC7SRJT5xJGkCLMaSIUG4Mo bZtg== Received: from [192.168.0.22] (arf62-1-82-237-250-248.fbx.proxad.net. [82.237.250.248]) by smtp.googlemail.com with ESMTPSA id b22-v6sm3971711wme.48.2018.08.02.13.16.25 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 02 Aug 2018 13:16:26 -0700 (PDT) From: =?utf-8?q?Fran=C3=A7ois_Dumont?= Subject: PR libstdc++/68222 Hide safe iterator operators To: "libstdc++@gcc.gnu.org" , gcc-patches Message-ID: <5b2fbf84-6530-8aa8-0730-e892e681a12f@gmail.com> Date: Thu, 2 Aug 2018 22:16:24 +0200 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Thunderbird/52.9.1 MIME-Version: 1.0 Hi     Here is a patch to avoid definition of invalid operators on the Debug mode safe iterator type depending on its category.     Even if it is limited to the Debug mode code I would like to have a feedback before committing. Especially on the following points: - _Safe_tagged_iterator: Is the name ok ? - Inheritance between the different _Safe_tagged_iterator instantiations. I am already working on making the operators friends as we discuss in another thread so I might review this design at this moment. - Are concept checks I added to testsuite_containers.h citerator ok ?     This patch also does some cleanup on Debug functions. __check_dereferenceable was not used (anymore maybe) so I removed it. I also prefer to take iterator by value in the fallback implementations like it is done in std algos. Only _Safe_tagged_iterator are taken by lvalue ref as they are quite expensive to copy (mutex lock).     I also attach the ChangeLog entry which is quite big. Tested under Linux x86_64 Debug mode. François 2018-08-03 François Dumont * include/debug/safe_iterator.h (_Safe_tagged_iterator<_It, _Sq, _Cat = typename std::iterator_traits<_It>::iterator_category>): New. (_Safe_iterator<_It, _Sq>::operator++()): Move... (_Safe_tagged_iterator<_It, _Sq, std::forward_iterator_tag> ::operator++()): ...here. (_Safe_iterator<_It, _Sq>::operator++(int)): Move... (_Safe_tagged_iterator<_It, _Sq, std::forward_iterator_tag> ::operator++(int)): ...here. (_Safe_iterator<_It, _Sq>::operator--()): Move... (_Safe_tagged_iterator<_It, _Sq, std::bidirectional_iterator_tag> ::operator--()): ...here. (_Safe_iterator<_It, _Sq>::operator--(int)): Move... (_Safe_tagged_iterator<_It, _Sq, std::bidirectional_iterator_tag> ::operator--(int)): ...here. (_Safe_iterator<_It, _Sq>::operator[](const difference_type&)): Move... (_Safe_tagged_iterator<_It, _Sq, std::random_access_iterator_tag> ::operator[](const difference_type&)): ...here. (_Safe_iterator<_It, _Sq>::operator+=(const difference_type&)): Move... (_Safe_tagged_iterator<_It, _Sq, std::random_access_iterator_tag> ::operator+=(const difference_type&)): ...here. (_Safe_iterator<_It, _Sq>::operator+(const difference_type&)): Move... (_Safe_tagged_iterator<_It, _Sq, std::random_access_iterator_tag> ::operator+(const difference_type&)): ...here. (_Safe_iterator<_It, _Sq>::operator-=(const difference_type&)): Move... (_Safe_tagged_iterator<_It, _Sq, std::random_access_iterator_tag> ::operator-=(const difference_type&)): ...here. (_Safe_iterator<_It, _Sq>::operator-(const difference_type&)): Move... (_Safe_tagged_iterator<_It, _Sq, std::random_access_iterator_tag> ::operator-(const difference_type&)): ...here. (operator==(const _Safe_iterator<>&, const _Safe_iterator<>&)): Replace with... (operator==(const _Safe_tagged_iterator<>&, const _Safe_tagged_iterator<>&): ...that. (operator==(const _Safe_iterator<>&, const _Safe_iterator<>&)): Replace with... (operator==(const _Safe_tagged_iterator<>&, const _Safe_tagged_iterator<>&): ...that. (operator!=(const _Safe_iterator<>&, const _Safe_iterator<>&)): Replace with... (operator!=(const _Safe_tagged_iterator<>&, const _Safe_tagged_iterator<>&): ...that. (operator<(const _Safe_iterator<>&, const _Safe_iterator<>&)): Replace with... (operator<(const _Safe_tagged_iterator<_It, _Sq, std::random_access_iterator_tag>&, const _Safe_tagged_iterator<_It, _Sq, std::random_access_iterator_tag>&)): ...that. (operator<=(const _Safe_iterator<>&, const _Safe_iterator<>&)): Replace with... (operator<=(const _Safe_tagged_iterator<_It, _Sq, std::random_access_iterator_tag>&, const _Safe_tagged_iterator<_It, _Sq, std::random_access_iterator_tag>&)): ...that. (operator>(const _Safe_iterator<>&, const _Safe_iterator<>&)): Replace with... (operator>(const _Safe_tagged_iterator<_It, _Sq, std::random_access_iterator_tag>&, const _Safe_tagged_iterator<_It, _Sq, std::random_access_iterator_tag>&)): ...that. (operator>=(const _Safe_iterator<>&, const _Safe_iterator<>&)): Replace with... (operator>=(const _Safe_tagged_iterator<_It, _Sq, std::random_access_iterator_tag>&, const _Safe_tagged_iterator<_It, _Sq, std::random_access_iterator_tag>&)): ...that. (operator-(const _Safe_iterator<>&, const _Safe_iterator<>&)): Replace with... (operator-(const _Safe_tagged_iterator<_It, _Sq, std::random_access_iterator_tag>&, const _Safe_tagged_iterator<_It, _Sq, std::random_access_iterator_tag>&)): ...that. (operator+(const difference_type&, const _Safe_iterator<>&)): Replace with... (operator+(const difference_type&, const _Safe_tagged_iterator<_It, _Sq, std::random_access_iterator_tag>&)): ...that. * include/debug/deque (std::__debug::deque<>::normal_type): New typedef. (std::__debug::deque<>::iterator): Use _Safe_tagged_iterator. (std::__debug::deque<>::const_iterator): Likewise. * include/debug/forward_list (std::__debug::forward_list<>::normal_type): New typedef. (std::__debug::forward_list<>::iterator): Use _Safe_tagged_iterator. (std::__debug::forward_list<>::const_iterator): Likewise. * include/debug/list (std::__debug::list<>::normal_type): New typedef. (std::__debug::list<>::iterator): Use _Safe_tagged_iterator. (std::__debug::list<>::const_iterator): Likewise. * include/debug/map.h (std::__debug::map<>::normal_type): New typedef. (std::__debug::map<>::iterator): Use _Safe_tagged_iterator. (std::__debug::map<>::const_iterator): Likewise. * include/debug/multimap.h (std::__debug::multimap<>::normal_type): New typedef. (std::__debug::multimap<>::iterator): Use _Safe_tagged_iterator. (std::__debug::multimap<>::const_iterator): Likewise. * include/debug/set.h (std::__debug::set<>::normal_type): New typedef. (std::__debug::set<>::iterator): Use _Safe_tagged_iterator. (std::__debug::set<>::const_iterator): Likewise. * include/debug/multiset.h (std::__debug::multiset<>::normal_type): New typedef. (std::__debug::multiset<>::iterator): Use _Safe_tagged_iterator. (std::__debug::multiset<>::const_iterator): Likewise. * include/debug/string (std::__debug::basic_string<>::normal_type): New typedef. (std::__debug::basic_string<>::iterator): Use _Safe_tagged_iterator. (std::__debug::basic_string<>::const_iterator): Likewise. * include/debug/unordered_map (std::__debug::unordered_map<>::normal_type): New typedef. (std::__debug::unordered_map<>::iterator): Use _Safe_tagged_iterator. (std::__debug::unordered_map<>::const_iterator): Likewise. (std::__debug::unordered_multimap<>::normal_type): New typedef. (std::__debug::unordered_multimap<>::iterator): Use _Safe_tagged_iterator. (std::__debug::unordered_multimap<>::const_iterator): Likewise. * include/debug/unordered_set (std::__debug::unordered_set<>::normal_type): New typedef. (std::__debug::unordered_set<>::iterator): Use _Safe_tagged_iterator. (std::__debug::unordered_set<>::const_iterator): Likewise. (std::__debug::unordered_multiset<>::normal_type): New typedef. (std::__debug::unordered_multiset<>::iterator): Use _Safe_tagged_iterator. (std::__debug::unordered_multiset<>::const_iterator): Likewise. * include/debug/formatter.h: Adapt. * include/debug/helper_functions.h (__get_distance<>(const _Safe_tagged_iterator<>&, const _Safe_tagged_iterator<>&)): New definition. (__get_distance<>(const _Safe_local_iterator<>&, const _Safe_local_iterator<>&)): Likewise. (__valid_range(const _Safe_tagged_iterator<>&, const _Safe_tagged_iterator<>&, typename _Distance_traits<>::__type&): Likewise. (__valid_range(const _Safe_local_iterator<>&, const _Safe_local_iterator<>&, typename _Distance_traits<>::__type&): Likewise. (__can_advance): Adapt. (__is_safe_random_iterator<>): Remove. * include/debug/functions.h: Include . (__check_dereferenceable): Delete. (__foreign_iterator_aux4, __foreign_iterator_aux3): Adapt. (__foreign_iterator_aux2, __foreign_iterator_aux): Adapt. (__foreign_iterator): Adapt. * include/debug/stl_iterator.h (__is_safe_random_iterator>): Remove. (__base(const std::reverse_iterator<_Safe_tagged_iterator<_It, _Sq, std::random_access_iterator_tag>)): New overload. (__niter_base): Adapt. * testsuite/util/testsuite_containers.h: Include . (iterator_concept_checks<_It, _Mutable, _Category>): New. (citerator<_Cont>::forward_members::forward_members()): Instantiate latter for container iterator and const_iterator. * testsuite/23_containers/list/68222_neg.cc: New. * testsuite/23_containers/vector/cons/destructible_debug_neg.cc: Adapt line number. diff --git a/libstdc++-v3/include/debug/deque b/libstdc++-v3/include/debug/deque index 93b82cf..213e23b 100644 --- a/libstdc++-v3/include/debug/deque +++ b/libstdc++-v3/include/debug/deque @@ -57,12 +57,14 @@ namespace __debug typedef __gnu_debug::_Equal_to<_Base_const_iterator> _Equal; public: + typedef _Base normal_type; + typedef typename _Base::reference reference; typedef typename _Base::const_reference const_reference; - typedef __gnu_debug::_Safe_iterator<_Base_iterator, deque> + typedef __gnu_debug::_Safe_tagged_iterator<_Base_iterator, deque> iterator; - typedef __gnu_debug::_Safe_iterator<_Base_const_iterator, deque> + typedef __gnu_debug::_Safe_tagged_iterator<_Base_const_iterator, deque> const_iterator; typedef typename _Base::size_type size_type; diff --git a/libstdc++-v3/include/debug/formatter.h b/libstdc++-v3/include/debug/formatter.h index 7b3c30b..33bc2b2 100644 --- a/libstdc++-v3/include/debug/formatter.h +++ b/libstdc++-v3/include/debug/formatter.h @@ -76,8 +76,8 @@ namespace __gnu_debug class _Safe_sequence_base; - template - class _Safe_iterator; + template + class _Safe_tagged_iterator; template class _Safe_local_iterator; @@ -264,8 +264,9 @@ namespace __gnu_debug _M_variant._M_string._M_value = __value; } - template - _Parameter(_Safe_iterator<_Iterator, _Sequence> const& __it, + template + _Parameter(_Safe_tagged_iterator<_Iterator, _Sequence, + _Category> const& __it, const char* __name, _Is_iterator) : _M_kind(__iterator), _M_variant() { @@ -379,9 +380,10 @@ namespace __gnu_debug = _S_reverse_state(_M_variant._M_iterator._M_state); } - template - _Parameter(std::reverse_iterator<_Safe_iterator<_Iterator, - _Sequence>> const& __it, + template + _Parameter( + std::reverse_iterator<_Safe_tagged_iterator<_Iterator, _Sequence, + _Category>> const& __it, const char* __name, _Is_iterator) : _Parameter(__it.base(), __name, _Is_iterator{}) { @@ -397,9 +399,10 @@ namespace __gnu_debug : _Parameter(__it.base(), __name, _Is_iterator{}) { _M_variant._M_iterator._M_type = _GLIBCXX_TYPEID(__it); } - template - _Parameter(std::move_iterator<_Safe_iterator<_Iterator, - _Sequence>> const& __it, + template + _Parameter( + std::move_iterator<_Safe_tagged_iterator<_Iterator, _Sequence, + _Category>> const& __it, const char* __name, _Is_iterator) : _Parameter(__it.base(), __name, _Is_iterator{}) { diff --git a/libstdc++-v3/include/debug/forward_list b/libstdc++-v3/include/debug/forward_list index 633af1a..6b874db 100644 --- a/libstdc++-v3/include/debug/forward_list +++ b/libstdc++-v3/include/debug/forward_list @@ -194,12 +194,14 @@ namespace __debug typedef typename _Base::const_iterator _Base_const_iterator; public: + typedef _Base normal_type; + typedef typename _Base::reference reference; typedef typename _Base::const_reference const_reference; - typedef __gnu_debug::_Safe_iterator< + typedef __gnu_debug::_Safe_tagged_iterator< _Base_iterator, forward_list> iterator; - typedef __gnu_debug::_Safe_iterator< + typedef __gnu_debug::_Safe_tagged_iterator< _Base_const_iterator, forward_list> const_iterator; typedef typename _Base::size_type size_type; diff --git a/libstdc++-v3/include/debug/functions.h b/libstdc++-v3/include/debug/functions.h index ce501f2..6719703 100644 --- a/libstdc++-v3/include/debug/functions.h +++ b/libstdc++-v3/include/debug/functions.h @@ -31,7 +31,9 @@ #include // for __addressof #include // for less + #if __cplusplus >= 201103L +# include // for __miter_base # include // for is_lvalue_reference and conditional. #endif @@ -64,19 +66,6 @@ namespace __gnu_debug __check_singular(const _Tp* __ptr) { return __ptr == 0; } - /** Assume that some arbitrary iterator is dereferenceable, because we - can't prove that it isn't. */ - template - inline bool - __check_dereferenceable(const _Iterator&) - { return true; } - - /** Non-NULL pointers are dereferenceable. */ - template - inline bool - __check_dereferenceable(const _Tp* __ptr) - { return __ptr; } - /* Checks that [first, last) is a valid range, and then returns * __first. This routine is useful when we can't use a separate * assertion statement because, e.g., we are in a constructor. @@ -95,9 +84,10 @@ namespace __gnu_debug } /* Handle the case where __other is a pointer to _Sequence::value_type. */ - template + template inline bool - __foreign_iterator_aux4(const _Safe_iterator<_Iterator, _Sequence>& __it, + __foreign_iterator_aux4(const _Safe_tagged_iterator<_Iterator, _Sequence, + _Category>& __it, const typename _Sequence::value_type* __other) { typedef const typename _Sequence::value_type* _PointerType; @@ -116,15 +106,18 @@ namespace __gnu_debug } /* Fallback overload for when we can't tell, assume it is valid. */ - template + template inline bool - __foreign_iterator_aux4(const _Safe_iterator<_Iterator, _Sequence>&, ...) + __foreign_iterator_aux4(const _Safe_tagged_iterator<_Iterator, _Sequence, + _Category>&, ...) { return true; } /* Handle sequences with contiguous storage */ - template + template inline bool - __foreign_iterator_aux3(const _Safe_iterator<_Iterator, _Sequence>& __it, + __foreign_iterator_aux3(const _Safe_tagged_iterator<_Iterator, _Sequence, + _Category>& __it, const _InputIterator& __other, const _InputIterator& __other_end, std::__true_type) @@ -137,34 +130,46 @@ namespace __gnu_debug } /* Handle non-contiguous containers, assume it is valid. */ - template + template inline bool - __foreign_iterator_aux3(const _Safe_iterator<_Iterator, _Sequence>&, + __foreign_iterator_aux3(const _Safe_tagged_iterator<_Iterator, _Sequence, + _Category>&, const _InputIterator&, const _InputIterator&, std::__false_type) { return true; } /** Handle debug iterators from the same type of container. */ - template - inline bool - __foreign_iterator_aux2(const _Safe_iterator<_Iterator, _Sequence>& __it, - const _Safe_iterator<_OtherIterator, _Sequence>& __other, - const _Safe_iterator<_OtherIterator, _Sequence>&) + template + inline bool + __foreign_iterator_aux2(const _Safe_tagged_iterator<_Iterator, _Sequence, + _Category>& __it, + const _Safe_tagged_iterator<_OtherIterator, _Sequence, + _Category>& __other, + const _Safe_tagged_iterator<_OtherIterator, _Sequence, + _Category>&) { return __it._M_get_sequence() != __other._M_get_sequence(); } /** Handle debug iterators from different types of container. */ - template - inline bool - __foreign_iterator_aux2(const _Safe_iterator<_Iterator, _Sequence>& __it, - const _Safe_iterator<_OtherIterator, _OtherSequence>&, - const _Safe_iterator<_OtherIterator, _OtherSequence>&) + template + inline bool + __foreign_iterator_aux2(const _Safe_tagged_iterator<_Iterator, _Sequence, + _Category>&, + const _Safe_tagged_iterator<_OtherIterator, _OtherSequence, + _OtherCategory>&, + const _Safe_tagged_iterator<_OtherIterator, _OtherSequence, + _OtherCategory>&) { return true; } /* Handle non-debug iterators. */ - template + template inline bool - __foreign_iterator_aux2(const _Safe_iterator<_Iterator, _Sequence>& __it, + __foreign_iterator_aux2(const _Safe_tagged_iterator<_Iterator, _Sequence, + _Category>& __it, const _InputIterator& __other, const _InputIterator& __other_end) { @@ -181,18 +186,21 @@ namespace __gnu_debug } /* Handle the case where we aren't really inserting a range after all */ - template + template inline bool - __foreign_iterator_aux(const _Safe_iterator<_Iterator, _Sequence>&, + __foreign_iterator_aux(const _Safe_tagged_iterator<_Iterator, _Sequence, + _Category>&, _Integral, _Integral, std::__true_type) { return true; } /* Handle all iterators. */ - template inline bool - __foreign_iterator_aux(const _Safe_iterator<_Iterator, _Sequence>& __it, + __foreign_iterator_aux(const _Safe_tagged_iterator<_Iterator, _Sequence, + _Category>& __it, _InputIterator __other, _InputIterator __other_end, std::__false_type) { @@ -201,10 +209,11 @@ namespace __gnu_debug std::__miter_base(__other_end)); } - template inline bool - __foreign_iterator(const _Safe_iterator<_Iterator, _Sequence>& __it, + __foreign_iterator(const _Safe_tagged_iterator<_Iterator, _Sequence, + _Category>& __it, _InputIterator __other, _InputIterator __other_end) { typedef typename std::__is_integer<_InputIterator>::__type _Integral; diff --git a/libstdc++-v3/include/debug/helper_functions.h b/libstdc++-v3/include/debug/helper_functions.h index 2073df9..67fbd83 100644 --- a/libstdc++-v3/include/debug/helper_functions.h +++ b/libstdc++-v3/include/debug/helper_functions.h @@ -37,8 +37,13 @@ namespace __gnu_debug { + template + class _Safe_tagged_iterator; + +#if __cplusplus >= 201103L template - class _Safe_iterator; + class _Safe_local_iterator; +#endif /** The precision to which we can calculate the distance between * two iterators. @@ -83,13 +88,13 @@ namespace __gnu_debug */ template inline typename _Distance_traits<_Iterator>::__type - __get_distance(const _Iterator& __lhs, const _Iterator& __rhs, + __get_distance(_Iterator __lhs, _Iterator __rhs, std::random_access_iterator_tag) { return std::make_pair(__rhs - __lhs, __dp_exact); } template inline typename _Distance_traits<_Iterator>::__type - __get_distance(const _Iterator& __lhs, const _Iterator& __rhs, + __get_distance(_Iterator __lhs, _Iterator __rhs, std::input_iterator_tag) { if (__lhs == __rhs) @@ -100,16 +105,30 @@ namespace __gnu_debug template inline typename _Distance_traits<_Iterator>::__type - __get_distance(const _Iterator& __lhs, const _Iterator& __rhs) + __get_distance(_Iterator __lhs, _Iterator __rhs) { return __get_distance(__lhs, __rhs, std::__iterator_category(__lhs)); } + template + typename _Distance_traits<_Iterator>::__type + __get_distance(const _Safe_tagged_iterator<_Iterator, _Sequence, + _Category>&, + const _Safe_tagged_iterator<_Iterator, _Sequence, + _Category>&); + +#if __cplusplus >= 201103L + template + typename _Distance_traits<_Iterator>::__type + __get_distance(const _Safe_local_iterator<_Iterator, _Sequence>&, + const _Safe_local_iterator<_Iterator, _Sequence>&); +#endif + /** 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&, + __valid_range_aux(_Integral, _Integral, typename _Distance_traits<_Integral>::__type& __dist, std::__true_type) { @@ -122,8 +141,7 @@ namespace __gnu_debug */ template inline bool - __valid_range_aux(const _InputIterator& __first, - const _InputIterator& __last, + __valid_range_aux(_InputIterator __first, _InputIterator __last, typename _Distance_traits<_InputIterator>::__type& __dist, std::__false_type) { @@ -152,61 +170,73 @@ namespace __gnu_debug */ template inline bool - __valid_range(const _InputIterator& __first, const _InputIterator& __last, + __valid_range(_InputIterator __first, _InputIterator __last, typename _Distance_traits<_InputIterator>::__type& __dist) { typedef typename std::__is_integer<_InputIterator>::__type _Integral; return __valid_range_aux(__first, __last, __dist, _Integral()); } + template + bool + __valid_range(const _Safe_tagged_iterator<_Iterator, _Sequence, + _Category>&, + const _Safe_tagged_iterator<_Iterator, _Sequence, + _Category>&, + typename _Distance_traits<_Iterator>::__type&); + +#if __cplusplus >= 201103L + template + bool + __valid_range(const _Safe_local_iterator<_Iterator, _Sequence>&, + const _Safe_local_iterator<_Iterator, _Sequence>&, + typename _Distance_traits<_Iterator>::__type&); +#endif + template inline bool - __valid_range(const _InputIterator& __first, const _InputIterator& __last) + __valid_range(_InputIterator __first, _InputIterator __last) { typename _Distance_traits<_InputIterator>::__type __dist; return __valid_range(__first, __last, __dist); } + template + bool + __valid_range(const _Safe_tagged_iterator<_Iterator, _Sequence, + _Category>&, + const _Safe_tagged_iterator<_Iterator, _Sequence, + _Category>&); + +#if __cplusplus >= 201103L + template + bool + __valid_range(const _Safe_local_iterator<_Iterator, _Sequence>&, + const _Safe_local_iterator<_Iterator, _Sequence>&); +#endif + // Fallback method, always ok. template inline bool __can_advance(_InputIterator, _Size) { return true; } - template + template bool - __can_advance(const _Safe_iterator<_Iterator, _Sequence>&, _Size); - -#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> - { }; + __can_advance(const _Safe_tagged_iterator<_Iterator, _Sequence, _Category>&, + _Size); /** Helper function to extract base iterator of random access safe iterator - in order to reduce performance impact of debug mode. Limited to random - access iterator because it is the only category for which it is possible - to check for correct iterators order in the __valid_range function - thanks to the < operator. + * 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 diff --git a/libstdc++-v3/include/debug/list b/libstdc++-v3/include/debug/list index bf3179a..dd91d5d 100644 --- a/libstdc++-v3/include/debug/list +++ b/libstdc++-v3/include/debug/list @@ -58,12 +58,14 @@ namespace __debug typedef __gnu_debug::_Not_equal_to<_Base_const_iterator> _Not_equal; public: + typedef _Base normal_type; + typedef typename _Base::reference reference; typedef typename _Base::const_reference const_reference; - typedef __gnu_debug::_Safe_iterator<_Base_iterator, list> + typedef __gnu_debug::_Safe_tagged_iterator<_Base_iterator, list> iterator; - typedef __gnu_debug::_Safe_iterator<_Base_const_iterator, list> + typedef __gnu_debug::_Safe_tagged_iterator<_Base_const_iterator, list> const_iterator; typedef typename _Base::size_type size_type; diff --git a/libstdc++-v3/include/debug/map.h b/libstdc++-v3/include/debug/map.h index 1fd4416..3d0dba2 100644 --- a/libstdc++-v3/include/debug/map.h +++ b/libstdc++-v3/include/debug/map.h @@ -57,6 +57,8 @@ namespace __debug typedef __gnu_debug::_Equal_to<_Base_const_iterator> _Equal; public: + typedef _Base normal_type; + // types: typedef _Key key_type; typedef _Tp mapped_type; @@ -66,9 +68,9 @@ namespace __debug typedef typename _Base::reference reference; typedef typename _Base::const_reference const_reference; - typedef __gnu_debug::_Safe_iterator<_Base_iterator, map> + typedef __gnu_debug::_Safe_tagged_iterator<_Base_iterator, map> iterator; - typedef __gnu_debug::_Safe_iterator<_Base_const_iterator, map> + typedef __gnu_debug::_Safe_tagged_iterator<_Base_const_iterator, map> const_iterator; typedef typename _Base::size_type size_type; diff --git a/libstdc++-v3/include/debug/multimap.h b/libstdc++-v3/include/debug/multimap.h index 0994dc4..7531130 100644 --- a/libstdc++-v3/include/debug/multimap.h +++ b/libstdc++-v3/include/debug/multimap.h @@ -57,6 +57,8 @@ namespace __debug typedef __gnu_debug::_Equal_to<_Base_const_iterator> _Equal; public: + typedef _Base normal_type; + // types: typedef _Key key_type; typedef _Tp mapped_type; @@ -66,10 +68,10 @@ namespace __debug typedef typename _Base::reference reference; typedef typename _Base::const_reference const_reference; - typedef __gnu_debug::_Safe_iterator<_Base_iterator, multimap> + typedef __gnu_debug::_Safe_tagged_iterator<_Base_iterator, multimap> iterator; - typedef __gnu_debug::_Safe_iterator<_Base_const_iterator, - multimap> const_iterator; + typedef __gnu_debug::_Safe_tagged_iterator<_Base_const_iterator, multimap> + const_iterator; typedef typename _Base::size_type size_type; typedef typename _Base::difference_type difference_type; diff --git a/libstdc++-v3/include/debug/multiset.h b/libstdc++-v3/include/debug/multiset.h index 6e4c1b0..b1ed3ca 100644 --- a/libstdc++-v3/include/debug/multiset.h +++ b/libstdc++-v3/include/debug/multiset.h @@ -56,6 +56,8 @@ namespace __debug typedef __gnu_debug::_Equal_to<_Base_const_iterator> _Equal; public: + typedef _Base normal_type; + // types: typedef _Key key_type; typedef _Key value_type; @@ -65,10 +67,10 @@ namespace __debug typedef typename _Base::reference reference; typedef typename _Base::const_reference const_reference; - typedef __gnu_debug::_Safe_iterator<_Base_iterator, multiset> + typedef __gnu_debug::_Safe_tagged_iterator<_Base_iterator, multiset> iterator; - typedef __gnu_debug::_Safe_iterator<_Base_const_iterator, - multiset> const_iterator; + typedef __gnu_debug::_Safe_tagged_iterator<_Base_const_iterator, multiset> + const_iterator; typedef typename _Base::size_type size_type; typedef typename _Base::difference_type difference_type; diff --git a/libstdc++-v3/include/debug/safe_iterator.h b/libstdc++-v3/include/debug/safe_iterator.h index b8256fc..430852c 100644 --- a/libstdc++-v3/include/debug/safe_iterator.h +++ b/libstdc++-v3/include/debug/safe_iterator.h @@ -38,6 +38,9 @@ namespace __gnu_debug { + template + class _Safe_iterator; + /** Helper struct to deal with sequence offering a before_begin * iterator. **/ @@ -76,7 +79,6 @@ namespace __gnu_debug * %_Safe_iterator has member functions for iterator invalidation, * attaching/detaching the iterator from sequences, and querying * the iterator's state. - * * Note that _Iterator must be the first base class so that it gets * initialized before the iterator is being attached to the container's list * of iterators and it is being detached before _Iterator get @@ -89,10 +91,10 @@ namespace __gnu_debug { typedef _Iterator _Iter_base; typedef _Safe_iterator_base _Safe_base; - typedef typename _Sequence::const_iterator _Const_iterator; typedef std::iterator_traits<_Iterator> _Traits; + protected: struct _Attach_single { }; @@ -173,7 +175,7 @@ namespace __gnu_debug _Safe_iterator( const _Safe_iterator<_MutableIterator, typename __gnu_cxx::__enable_if<(std::__are_same<_MutableIterator, - typename _Sequence::iterator::iterator_type>::__value), + typename _Sequence::normal_type::iterator>::__value), _Sequence>::__type>& __x) _GLIBCXX_NOEXCEPT : _Iter_base(__x.base()) { @@ -279,19 +281,306 @@ namespace __gnu_debug return base().operator->(); } + // ------ Utilities ------ + + /// Determine if this is a constant iterator. + static bool + _S_constant() + { + return std::__are_same::__value; + } + + /** + * @brief Return the underlying iterator + */ + _Iterator& + base() _GLIBCXX_NOEXCEPT { return *this; } + + const _Iterator& + base() const _GLIBCXX_NOEXCEPT { return *this; } + + /** + * @brief Conversion to underlying non-debug iterator to allow + * better interaction with non-debug containers. + */ + operator _Iterator() const _GLIBCXX_NOEXCEPT { return *this; } + + /** Attach iterator to the given sequence. */ + void + _M_attach(_Safe_sequence_base* __seq) + { _Safe_base::_M_attach(__seq, _S_constant()); } + + /** Likewise, but not thread-safe. */ + void + _M_attach_single(_Safe_sequence_base* __seq) + { _Safe_base::_M_attach_single(__seq, _S_constant()); } + + /// Is the iterator dereferenceable? + bool + _M_dereferenceable() const + { return !this->_M_singular() && !_M_is_end() && !_M_is_before_begin(); } + + /// Is the iterator before a dereferenceable one? + bool + _M_before_dereferenceable() const + { + if (this->_M_incrementable()) + { + _Iterator __base = base(); + return ++__base != _M_get_sequence()->_M_base().end(); + } + return false; + } + + /// Is the iterator incrementable? + bool + _M_incrementable() const + { return !this->_M_singular() && !_M_is_end(); } + + // Can we advance the iterator @p __n steps (@p __n may be negative) + bool + _M_can_advance(const difference_type& __n) const; + + // Is the iterator range [*this, __rhs) valid? + bool + _M_valid_range(const _Safe_iterator& __rhs, + std::pair& __dist, + bool __check_dereferenceable = true) const; + + // The sequence this iterator references. + typename __gnu_cxx::__conditional_type< + std::__are_same::__value, + const _Sequence*, + _Sequence*>::__type + _M_get_sequence() const + { return static_cast<_Sequence*>(_M_sequence); } + + /// Is this iterator equal to the sequence's begin() iterator? + bool + _M_is_begin() const + { return base() == _M_get_sequence()->_M_base().begin(); } + + /// Is this iterator equal to the sequence's end() iterator? + bool + _M_is_end() const + { return base() == _M_get_sequence()->_M_base().end(); } + + /// Is this iterator equal to the sequence's before_begin() iterator if + /// any? + bool + _M_is_before_begin() const + { return _BeforeBeginHelper<_Sequence>::_S_Is(*this); } + + /// Is this iterator equal to the sequence's before_begin() iterator if + /// any or begin() otherwise? + bool + _M_is_beginnest() const + { return _BeforeBeginHelper<_Sequence>::_S_Is_Beginnest(*this); } + }; + + template::iterator_category> + class _Safe_tagged_iterator; + + template + class _Safe_tagged_iterator<_Iterator, _Sequence, std::forward_iterator_tag> + : public _Safe_iterator<_Iterator, _Sequence> + { + typedef _Safe_iterator<_Iterator, _Sequence> _Safe_base; + + protected: + typedef typename _Safe_base::_Attach_single _Attach_single; + + _Safe_tagged_iterator(const _Iterator& __i, _Safe_sequence_base* __seq, + _Attach_single) + _GLIBCXX_NOEXCEPT + : _Safe_base(__i, __seq, _Attach_single()) + { } + + public: + /// @post the iterator is singular and unattached + _Safe_tagged_iterator() _GLIBCXX_NOEXCEPT { } + + /** + * @brief Safe iterator construction from an unsafe iterator and + * its sequence. + * + * @pre @p seq is not NULL + * @post this is not singular + */ + _Safe_tagged_iterator(const _Iterator& __i, const _Safe_sequence_base* __seq) + _GLIBCXX_NOEXCEPT + : _Safe_base(__i, __seq) + { } + + /** + * @brief Copy construction. + */ + _Safe_tagged_iterator(const _Safe_tagged_iterator& __x) _GLIBCXX_NOEXCEPT + : _Safe_base(__x) + { } + +#if __cplusplus >= 201103L + /** @brief Move construction. */ + _Safe_tagged_iterator(_Safe_tagged_iterator&&) = default; +#endif + + /** + * @brief Converting constructor from a mutable iterator to a + * constant iterator. + */ + template + _Safe_tagged_iterator( + const _Safe_tagged_iterator<_MutableIterator, + typename __gnu_cxx::__enable_if<(std::__are_same<_MutableIterator, + typename _Sequence::normal_type::iterator>::__value), + _Sequence>::__type>& __x) _GLIBCXX_NOEXCEPT + : _Safe_base(__x) + { } + +#if __cplusplus >= 201103L + /** @brief Copy assignment. */ + _Safe_tagged_iterator& + operator=(const _Safe_tagged_iterator&) = default; + + /** @brief Move assignment. */ + _Safe_tagged_iterator& + operator=(_Safe_tagged_iterator&&) = default; +#else + /** + * @brief Copy assignment. + */ + _Safe_tagged_iterator& + operator=(const _Safe_tagged_iterator& __x) _GLIBCXX_NOEXCEPT + { + _Safe_base::operator=(__x); + return *this; + } +#endif + // ------ Input iterator requirements ------ /** * @brief Iterator preincrement * @pre iterator is incrementable */ - _Safe_iterator& + _Safe_tagged_iterator& operator++() _GLIBCXX_NOEXCEPT { _GLIBCXX_DEBUG_VERIFY(this->_M_incrementable(), _M_message(__msg_bad_inc) ._M_iterator(*this, "this")); __gnu_cxx::__scoped_lock __l(this->_M_get_mutex()); - ++base(); + ++this->base(); + return *this; + } + + /** + * @brief Iterator postincrement + * @pre iterator is incrementable + */ + _Safe_tagged_iterator + operator++(int) _GLIBCXX_NOEXCEPT + { + _GLIBCXX_DEBUG_VERIFY(this->_M_incrementable(), + _M_message(__msg_bad_inc) + ._M_iterator(*this, "this")); + __gnu_cxx::__scoped_lock __l(this->_M_get_mutex()); + return _Safe_tagged_iterator(this->base()++, this->_M_sequence, + _Attach_single()); + } + }; + + template + class _Safe_tagged_iterator<_Iterator, _Sequence, + std::bidirectional_iterator_tag> + : public _Safe_tagged_iterator<_Iterator, _Sequence, + std::forward_iterator_tag> + { + typedef _Safe_tagged_iterator<_Iterator, _Sequence, + std::forward_iterator_tag> _Safe_base; + + protected: + typedef typename _Safe_base::_Attach_single _Attach_single; + + _Safe_tagged_iterator(const _Iterator& __i, _Safe_sequence_base* __seq, + _Attach_single) + _GLIBCXX_NOEXCEPT + : _Safe_base(__i, __seq, _Attach_single()) + { } + + public: + /// @post the iterator is singular and unattached + _Safe_tagged_iterator() _GLIBCXX_NOEXCEPT { } + + /** + * @brief Safe iterator construction from an unsafe iterator and + * its sequence. + * + * @pre @p seq is not NULL + * @post this is not singular + */ + _Safe_tagged_iterator(const _Iterator& __i, + const _Safe_sequence_base* __seq) + _GLIBCXX_NOEXCEPT + : _Safe_base(__i, __seq) + { } + + /** + * @brief Copy construction. + */ + _Safe_tagged_iterator(const _Safe_tagged_iterator& __x) _GLIBCXX_NOEXCEPT + : _Safe_base(__x) + { } + +#if __cplusplus >= 201103L + /** @brief Move construction. */ + _Safe_tagged_iterator(_Safe_tagged_iterator&&) = default; +#endif + + /** + * @brief Converting constructor from a mutable iterator to a + * constant iterator. + */ + template + _Safe_tagged_iterator( + const _Safe_tagged_iterator<_MutableIterator, + typename __gnu_cxx::__enable_if<(std::__are_same<_MutableIterator, + typename _Sequence::normal_type::iterator>::__value), + _Sequence>::__type>& __x) _GLIBCXX_NOEXCEPT + : _Safe_base(__x) + { } + +#if __cplusplus >= 201103L + /** @brief Copy assignment. */ + _Safe_tagged_iterator& + operator=(const _Safe_tagged_iterator&) = default; + + /** @brief Move assignment. */ + _Safe_tagged_iterator& + operator=(_Safe_tagged_iterator&&) = default; +#else + /** + * @brief Copy assignment. + */ + _Safe_tagged_iterator& + operator=(const _Safe_tagged_iterator& __x) _GLIBCXX_NOEXCEPT + { + _Safe_base::operator=(__x); + return *this; + } +#endif + + // ------ Input iterator requirements ------ + /** + * @brief Iterator preincrement + * @pre iterator is incrementable + */ + _Safe_tagged_iterator& + operator++() _GLIBCXX_NOEXCEPT + { + _Safe_base::operator++(); return *this; } @@ -299,14 +588,15 @@ namespace __gnu_debug * @brief Iterator postincrement * @pre iterator is incrementable */ - _Safe_iterator + _Safe_tagged_iterator operator++(int) _GLIBCXX_NOEXCEPT { _GLIBCXX_DEBUG_VERIFY(this->_M_incrementable(), _M_message(__msg_bad_inc) ._M_iterator(*this, "this")); __gnu_cxx::__scoped_lock __l(this->_M_get_mutex()); - return _Safe_iterator(base()++, this->_M_sequence, _Attach_single()); + return _Safe_tagged_iterator(this->base()++, this->_M_sequence, + _Attach_single()); } // ------ Bidirectional iterator requirements ------ @@ -314,14 +604,157 @@ namespace __gnu_debug * @brief Iterator predecrement * @pre iterator is decrementable */ - _Safe_iterator& + _Safe_tagged_iterator& operator--() _GLIBCXX_NOEXCEPT { _GLIBCXX_DEBUG_VERIFY(this->_M_decrementable(), _M_message(__msg_bad_dec) ._M_iterator(*this, "this")); __gnu_cxx::__scoped_lock __l(this->_M_get_mutex()); - --base(); + --this->base(); + return *this; + } + + /** + * @brief Iterator postdecrement + * @pre iterator is decrementable + */ + _Safe_tagged_iterator + operator--(int) _GLIBCXX_NOEXCEPT + { + _GLIBCXX_DEBUG_VERIFY(this->_M_decrementable(), + _M_message(__msg_bad_dec) + ._M_iterator(*this, "this")); + __gnu_cxx::__scoped_lock __l(this->_M_get_mutex()); + return _Safe_tagged_iterator(this->base()--, this->_M_sequence, + _Attach_single()); + } + + // ------ Utilities ------ + + // Is the iterator decrementable? + bool + _M_decrementable() const { return !this->_M_singular() && !this->_M_is_begin(); } + }; + + template + class _Safe_tagged_iterator<_Iterator, _Sequence, + std::random_access_iterator_tag> + : public _Safe_tagged_iterator<_Iterator, _Sequence, + std::bidirectional_iterator_tag> + { + typedef _Safe_tagged_iterator<_Iterator, _Sequence, + std::bidirectional_iterator_tag> _Safe_base; + + typedef typename _Safe_base::_Attach_single _Attach_single; + + _Safe_tagged_iterator(const _Iterator& __i, _Safe_sequence_base* __seq, + _Attach_single) + _GLIBCXX_NOEXCEPT + : _Safe_base(__i, __seq, _Attach_single()) + { } + + public: + typedef typename _Safe_base::difference_type difference_type; + typedef typename _Safe_base::reference reference; + + /// @post the iterator is singular and unattached + _Safe_tagged_iterator() _GLIBCXX_NOEXCEPT { } + + /** + * @brief Safe iterator construction from an unsafe iterator and + * its sequence. + * + * @pre @p seq is not NULL + * @post this is not singular + */ + _Safe_tagged_iterator(const _Iterator& __i, + const _Safe_sequence_base* __seq) + _GLIBCXX_NOEXCEPT + : _Safe_base(__i, __seq) + { } + + /** + * @brief Copy construction. + */ + _Safe_tagged_iterator(const _Safe_tagged_iterator& __x) _GLIBCXX_NOEXCEPT + : _Safe_base(__x) + { } + +#if __cplusplus >= 201103L + /** @brief Move construction. */ + _Safe_tagged_iterator(_Safe_tagged_iterator&&) = default; +#endif + + /** + * @brief Converting constructor from a mutable iterator to a + * constant iterator. + */ + template + _Safe_tagged_iterator( + const _Safe_tagged_iterator<_MutableIterator, + typename __gnu_cxx::__enable_if<(std::__are_same<_MutableIterator, + typename _Sequence::normal_type::iterator>::__value), + _Sequence>::__type>& __x) _GLIBCXX_NOEXCEPT + : _Safe_base(__x) + { } + +#if __cplusplus >= 201103L + /** @brief Copy assignment. */ + _Safe_tagged_iterator& + operator=(const _Safe_tagged_iterator&) = default; + + /** @brief Move assignment. */ + _Safe_tagged_iterator& + operator=(_Safe_tagged_iterator&&) = default; +#else + /** + * @brief Copy assignment. + */ + _Safe_tagged_iterator& + operator=(const _Safe_tagged_iterator& __x) _GLIBCXX_NOEXCEPT + { + _Safe_base::operator=(__x); + return *this; + } +#endif + + // ------ Input iterator requirements ------ + /** + * @brief Iterator preincrement + * @pre iterator is incrementable + */ + _Safe_tagged_iterator& + operator++() _GLIBCXX_NOEXCEPT + { + _Safe_base::operator++(); + return *this; + } + + /** + * @brief Iterator postincrement + * @pre iterator is incrementable + */ + _Safe_tagged_iterator + operator++(int) _GLIBCXX_NOEXCEPT + { + _GLIBCXX_DEBUG_VERIFY(this->_M_incrementable(), + _M_message(__msg_bad_inc) + ._M_iterator(*this, "this")); + __gnu_cxx::__scoped_lock __l(this->_M_get_mutex()); + return _Safe_tagged_iterator(this->base()++, this->_M_sequence, + _Attach_single()); + } + + // ------ Bidirectional iterator requirements ------ + /** + * @brief Iterator predecrement + * @pre iterator is decrementable + */ + _Safe_tagged_iterator& + operator--() _GLIBCXX_NOEXCEPT + { + _Safe_base::operator--(); return *this; } @@ -329,14 +762,15 @@ namespace __gnu_debug * @brief Iterator postdecrement * @pre iterator is decrementable */ - _Safe_iterator + _Safe_tagged_iterator operator--(int) _GLIBCXX_NOEXCEPT { _GLIBCXX_DEBUG_VERIFY(this->_M_decrementable(), _M_message(__msg_bad_dec) ._M_iterator(*this, "this")); __gnu_cxx::__scoped_lock __l(this->_M_get_mutex()); - return _Safe_iterator(base()--, this->_M_sequence, _Attach_single()); + return _Safe_tagged_iterator(this->base()--, this->_M_sequence, + _Attach_single()); } // ------ Random access iterator requirements ------ @@ -347,153 +781,54 @@ namespace __gnu_debug && this->_M_can_advance(__n + 1), _M_message(__msg_iter_subscript_oob) ._M_iterator(*this)._M_integer(__n)); - return base()[__n]; + return this->base()[__n]; } - _Safe_iterator& + _Safe_tagged_iterator& operator+=(const difference_type& __n) _GLIBCXX_NOEXCEPT { _GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(__n), _M_message(__msg_advance_oob) ._M_iterator(*this)._M_integer(__n)); __gnu_cxx::__scoped_lock __l(this->_M_get_mutex()); - base() += __n; + this->base() += __n; return *this; } - _Safe_iterator + _Safe_tagged_iterator operator+(const difference_type& __n) const _GLIBCXX_NOEXCEPT { _GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(__n), _M_message(__msg_advance_oob) ._M_iterator(*this)._M_integer(__n)); - return _Safe_iterator(base() + __n, this->_M_sequence); + return _Safe_tagged_iterator(this->base() + __n, this->_M_sequence); } - _Safe_iterator& + _Safe_tagged_iterator& operator-=(const difference_type& __n) _GLIBCXX_NOEXCEPT { _GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(-__n), _M_message(__msg_retreat_oob) ._M_iterator(*this)._M_integer(__n)); __gnu_cxx::__scoped_lock __l(this->_M_get_mutex()); - base() -= __n; + this->base() -= __n; return *this; } - _Safe_iterator + _Safe_tagged_iterator operator-(const difference_type& __n) const _GLIBCXX_NOEXCEPT { _GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(-__n), _M_message(__msg_retreat_oob) ._M_iterator(*this)._M_integer(__n)); - return _Safe_iterator(base() - __n, this->_M_sequence); - } - - // ------ Utilities ------ - - /// Determine if this is a constant iterator. - static bool - _S_constant() - { return std::__are_same<_Const_iterator, _Safe_iterator>::__value; } - - /** - * @brief Return the underlying iterator - */ - _Iterator& - base() _GLIBCXX_NOEXCEPT { return *this; } - - const _Iterator& - base() const _GLIBCXX_NOEXCEPT { return *this; } - - /** - * @brief Conversion to underlying non-debug iterator to allow - * better interaction with non-debug containers. - */ - operator _Iterator() const _GLIBCXX_NOEXCEPT { return *this; } - - /** Attach iterator to the given sequence. */ - void - _M_attach(_Safe_sequence_base* __seq) - { _Safe_base::_M_attach(__seq, _S_constant()); } - - /** Likewise, but not thread-safe. */ - void - _M_attach_single(_Safe_sequence_base* __seq) - { _Safe_base::_M_attach_single(__seq, _S_constant()); } - - /// Is the iterator dereferenceable? - bool - _M_dereferenceable() const - { return !this->_M_singular() && !_M_is_end() && !_M_is_before_begin(); } - - /// Is the iterator before a dereferenceable one? - bool - _M_before_dereferenceable() const - { - if (this->_M_incrementable()) - { - _Iterator __base = base(); - return ++__base != _M_get_sequence()->_M_base().end(); + return _Safe_tagged_iterator(this->base() - __n, this->_M_sequence); } - return false; - } - - /// Is the iterator incrementable? - bool - _M_incrementable() const - { return !this->_M_singular() && !_M_is_end(); } - - // Is the iterator decrementable? - bool - _M_decrementable() const { return !_M_singular() && !_M_is_begin(); } - - // Can we advance the iterator @p __n steps (@p __n may be negative) - bool - _M_can_advance(const difference_type& __n) const; - - // Is the iterator range [*this, __rhs) valid? - bool - _M_valid_range(const _Safe_iterator& __rhs, - std::pair& __dist, - bool __check_dereferenceable = true) const; - - // The sequence this iterator references. - typename - __gnu_cxx::__conditional_type::__value, - const _Sequence*, - _Sequence*>::__type - _M_get_sequence() const - { return static_cast<_Sequence*>(_M_sequence); } - - /// Is this iterator equal to the sequence's begin() iterator? - bool - _M_is_begin() const - { return base() == _M_get_sequence()->_M_base().begin(); } - - /// Is this iterator equal to the sequence's end() iterator? - bool - _M_is_end() const - { return base() == _M_get_sequence()->_M_base().end(); } - - /// Is this iterator equal to the sequence's before_begin() iterator if - /// any? - bool - _M_is_before_begin() const - { return _BeforeBeginHelper<_Sequence>::_S_Is(*this); } - - /// Is this iterator equal to the sequence's before_begin() iterator if - /// any or begin() otherwise? - bool - _M_is_beginnest() const - { return _BeforeBeginHelper<_Sequence>::_S_Is_Beginnest(*this); } }; template inline bool - operator==(const _Safe_iterator<_IteratorL, _Sequence>& __lhs, - const _Safe_iterator<_IteratorR, _Sequence>& __rhs) + operator==(const _Safe_tagged_iterator<_IteratorL, _Sequence>& __lhs, + const _Safe_tagged_iterator<_IteratorR, _Sequence>& __rhs) _GLIBCXX_NOEXCEPT { _GLIBCXX_DEBUG_VERIFY(!__lhs._M_singular() && !__rhs._M_singular(), @@ -509,8 +844,8 @@ namespace __gnu_debug template inline bool - operator==(const _Safe_iterator<_Iterator, _Sequence>& __lhs, - const _Safe_iterator<_Iterator, _Sequence>& __rhs) + operator==(const _Safe_tagged_iterator<_Iterator, _Sequence>& __lhs, + const _Safe_tagged_iterator<_Iterator, _Sequence>& __rhs) _GLIBCXX_NOEXCEPT { _GLIBCXX_DEBUG_VERIFY(!__lhs._M_singular() && !__rhs._M_singular(), @@ -526,8 +861,8 @@ namespace __gnu_debug template inline bool - operator!=(const _Safe_iterator<_IteratorL, _Sequence>& __lhs, - const _Safe_iterator<_IteratorR, _Sequence>& __rhs) + operator!=(const _Safe_tagged_iterator<_IteratorL, _Sequence>& __lhs, + const _Safe_tagged_iterator<_IteratorR, _Sequence>& __rhs) _GLIBCXX_NOEXCEPT { _GLIBCXX_DEBUG_VERIFY(!__lhs._M_singular() && !__rhs._M_singular(), @@ -543,8 +878,8 @@ namespace __gnu_debug template inline bool - operator!=(const _Safe_iterator<_Iterator, _Sequence>& __lhs, - const _Safe_iterator<_Iterator, _Sequence>& __rhs) + operator!=(const _Safe_tagged_iterator<_Iterator, _Sequence>& __lhs, + const _Safe_tagged_iterator<_Iterator, _Sequence>& __rhs) _GLIBCXX_NOEXCEPT { _GLIBCXX_DEBUG_VERIFY(!__lhs._M_singular() && !__rhs._M_singular(), @@ -560,8 +895,10 @@ namespace __gnu_debug template inline bool - operator<(const _Safe_iterator<_IteratorL, _Sequence>& __lhs, - const _Safe_iterator<_IteratorR, _Sequence>& __rhs) + operator<(const _Safe_tagged_iterator<_IteratorL, _Sequence, + std::random_access_iterator_tag>& __lhs, + const _Safe_tagged_iterator<_IteratorR, _Sequence, + std::random_access_iterator_tag>& __rhs) _GLIBCXX_NOEXCEPT { _GLIBCXX_DEBUG_VERIFY(!__lhs._M_singular() && !__rhs._M_singular(), @@ -577,8 +914,10 @@ namespace __gnu_debug template inline bool - operator<(const _Safe_iterator<_Iterator, _Sequence>& __lhs, - const _Safe_iterator<_Iterator, _Sequence>& __rhs) + operator<(const _Safe_tagged_iterator<_Iterator, _Sequence, + std::random_access_iterator_tag>& __lhs, + const _Safe_tagged_iterator<_Iterator, _Sequence, + std::random_access_iterator_tag>& __rhs) _GLIBCXX_NOEXCEPT { _GLIBCXX_DEBUG_VERIFY(!__lhs._M_singular() && !__rhs._M_singular(), @@ -594,8 +933,10 @@ namespace __gnu_debug template inline bool - operator<=(const _Safe_iterator<_IteratorL, _Sequence>& __lhs, - const _Safe_iterator<_IteratorR, _Sequence>& __rhs) + operator<=(const _Safe_tagged_iterator<_IteratorL, _Sequence, + std::random_access_iterator_tag>& __lhs, + const _Safe_tagged_iterator<_IteratorR, _Sequence, + std::random_access_iterator_tag>& __rhs) _GLIBCXX_NOEXCEPT { _GLIBCXX_DEBUG_VERIFY(!__lhs._M_singular() && !__rhs._M_singular(), @@ -611,8 +952,10 @@ namespace __gnu_debug template inline bool - operator<=(const _Safe_iterator<_Iterator, _Sequence>& __lhs, - const _Safe_iterator<_Iterator, _Sequence>& __rhs) + operator<=(const _Safe_tagged_iterator<_Iterator, _Sequence, + std::random_access_iterator_tag>& __lhs, + const _Safe_tagged_iterator<_Iterator, _Sequence, + std::random_access_iterator_tag>& __rhs) _GLIBCXX_NOEXCEPT { _GLIBCXX_DEBUG_VERIFY(!__lhs._M_singular() && !__rhs._M_singular(), @@ -628,8 +971,10 @@ namespace __gnu_debug template inline bool - operator>(const _Safe_iterator<_IteratorL, _Sequence>& __lhs, - const _Safe_iterator<_IteratorR, _Sequence>& __rhs) + operator>(const _Safe_tagged_iterator<_IteratorL, _Sequence, + std::random_access_iterator_tag>& __lhs, + const _Safe_tagged_iterator<_IteratorR, _Sequence, + std::random_access_iterator_tag>& __rhs) _GLIBCXX_NOEXCEPT { _GLIBCXX_DEBUG_VERIFY(!__lhs._M_singular() && !__rhs._M_singular(), @@ -645,8 +990,10 @@ namespace __gnu_debug template inline bool - operator>(const _Safe_iterator<_Iterator, _Sequence>& __lhs, - const _Safe_iterator<_Iterator, _Sequence>& __rhs) + operator>(const _Safe_tagged_iterator<_Iterator, _Sequence, + std::random_access_iterator_tag>& __lhs, + const _Safe_tagged_iterator<_Iterator, _Sequence, + std::random_access_iterator_tag>& __rhs) _GLIBCXX_NOEXCEPT { _GLIBCXX_DEBUG_VERIFY(!__lhs._M_singular() && !__rhs._M_singular(), @@ -662,8 +1009,10 @@ namespace __gnu_debug template inline bool - operator>=(const _Safe_iterator<_IteratorL, _Sequence>& __lhs, - const _Safe_iterator<_IteratorR, _Sequence>& __rhs) + operator>=(const _Safe_tagged_iterator<_IteratorL, _Sequence, + std::random_access_iterator_tag>& __lhs, + const _Safe_tagged_iterator<_IteratorR, _Sequence, + std::random_access_iterator_tag>& __rhs) _GLIBCXX_NOEXCEPT { _GLIBCXX_DEBUG_VERIFY(!__lhs._M_singular() && !__rhs._M_singular(), @@ -679,8 +1028,10 @@ namespace __gnu_debug template inline bool - operator>=(const _Safe_iterator<_Iterator, _Sequence>& __lhs, - const _Safe_iterator<_Iterator, _Sequence>& __rhs) + operator>=(const _Safe_tagged_iterator<_Iterator, _Sequence, + std::random_access_iterator_tag>& __lhs, + const _Safe_tagged_iterator<_Iterator, _Sequence, + std::random_access_iterator_tag>& __rhs) _GLIBCXX_NOEXCEPT { _GLIBCXX_DEBUG_VERIFY(!__lhs._M_singular() && !__rhs._M_singular(), @@ -699,9 +1050,12 @@ namespace __gnu_debug // operators but also operator- must accept mixed iterator/const_iterator // parameters. template - inline typename _Safe_iterator<_IteratorL, _Sequence>::difference_type - operator-(const _Safe_iterator<_IteratorL, _Sequence>& __lhs, - const _Safe_iterator<_IteratorR, _Sequence>& __rhs) + inline typename _Safe_tagged_iterator<_IteratorL, _Sequence, + std::random_access_iterator_tag>::difference_type + operator-(const _Safe_tagged_iterator<_IteratorL, _Sequence, + std::random_access_iterator_tag>& __lhs, + const _Safe_tagged_iterator<_IteratorR, _Sequence, + std::random_access_iterator_tag>& __rhs) _GLIBCXX_NOEXCEPT { _GLIBCXX_DEBUG_VERIFY(!__lhs._M_singular() && !__rhs._M_singular(), @@ -716,9 +1070,12 @@ namespace __gnu_debug } template - inline typename _Safe_iterator<_Iterator, _Sequence>::difference_type - operator-(const _Safe_iterator<_Iterator, _Sequence>& __lhs, - const _Safe_iterator<_Iterator, _Sequence>& __rhs) + inline typename _Safe_tagged_iterator<_Iterator, _Sequence, + std::random_access_iterator_tag>::difference_type + operator-(const _Safe_tagged_iterator<_Iterator, _Sequence, + std::random_access_iterator_tag>& __lhs, + const _Safe_tagged_iterator<_Iterator, _Sequence, + std::random_access_iterator_tag>& __rhs) _GLIBCXX_NOEXCEPT { _GLIBCXX_DEBUG_VERIFY(!__lhs._M_singular() && !__rhs._M_singular(), @@ -733,32 +1090,43 @@ namespace __gnu_debug } template - inline _Safe_iterator<_Iterator, _Sequence> - operator+(typename _Safe_iterator<_Iterator,_Sequence>::difference_type __n, - const _Safe_iterator<_Iterator, _Sequence>& __i) _GLIBCXX_NOEXCEPT + inline _Safe_tagged_iterator<_Iterator, _Sequence, + std::random_access_iterator_tag> + operator+(typename _Safe_tagged_iterator<_Iterator,_Sequence, + std::random_access_iterator_tag>::difference_type __n, + const _Safe_tagged_iterator<_Iterator, _Sequence, + std::random_access_iterator_tag>& __i) + _GLIBCXX_NOEXCEPT { return __i + __n; } - /** Safe iterators know if they are dereferenceable. */ - template - inline bool - __check_dereferenceable(const _Safe_iterator<_Iterator, _Sequence>& __x) - { return __x._M_dereferenceable(); } - /** Safe iterators know how to check if they form a valid range. */ - template + template inline bool - __valid_range(const _Safe_iterator<_Iterator, _Sequence>& __first, - const _Safe_iterator<_Iterator, _Sequence>& __last, + __valid_range(const _Safe_tagged_iterator<_Iterator, _Sequence, + _Category>& __first, + const _Safe_tagged_iterator<_Iterator, _Sequence, + _Category>& __last, typename _Distance_traits<_Iterator>::__type& __dist) { return __first._M_valid_range(__last, __dist); } + template + inline bool + __valid_range(const _Safe_tagged_iterator<_Iterator, _Sequence, + _Category>& __first, + const _Safe_tagged_iterator<_Iterator, _Sequence, + _Category>& __last) + { + typename _Distance_traits<_Iterator>::__type __dist; + return __first._M_valid_range(__last, __dist); + } + /** Safe iterators can help to get better distance knowledge. */ template 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); } + std::random_access_iterator_tag __tag) + { return __get_distance(__first.base(), __last.base(), __tag); } template inline typename _Distance_traits<_Iterator>::__type @@ -814,6 +1182,23 @@ namespace __gnu_debug return std::make_pair(1, __dp_equality); } + template + inline typename _Distance_traits<_Iterator>::__type + __get_distance(const _Safe_tagged_iterator<_Iterator, _Sequence, + _Category>& __lhs, + const _Safe_tagged_iterator<_Iterator, _Sequence, + _Category>& __rhs) + { return __get_distance(__lhs, __rhs, _Category()); } + + template + inline typename _Distance_traits<_Iterator>::__type + __get_distance(const _Safe_iterator<_Iterator, _Sequence>& __lhs, + const _Safe_iterator<_Iterator, _Sequence>& __rhs) + { + return __get_distance(__lhs, __rhs, + std::__iterator_category(__lhs.base())); + } + // Get distance from sequence begin to specified iterator. template inline typename _Distance_traits<_Iterator>::__type @@ -862,47 +1247,29 @@ namespace __gnu_debug return __res; } - template + template inline bool - __can_advance(const _Safe_iterator<_Iterator, _Sequence>& __it, _Size __n) + __can_advance(const _Safe_tagged_iterator<_Iterator, _Sequence, + _Category>& __it, + _Size __n) { return __it._M_can_advance(__n); } -#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) + __base(const _Safe_tagged_iterator<_Iterator, _Sequence, + std::random_access_iterator_tag>& __it) { 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> > + struct _Unsafe_type<_Safe_tagged_iterator<_Iterator, _Sequence> > { typedef _Iterator _Type; }; #endif template inline _Iterator - __unsafe(const _Safe_iterator<_Iterator, _Sequence>& __it) + __unsafe(const _Safe_tagged_iterator<_Iterator, _Sequence>& __it) { return __it.base(); } } // namespace __gnu_debug diff --git a/libstdc++-v3/include/debug/safe_local_iterator.h b/libstdc++-v3/include/debug/safe_local_iterator.h index f9597a6..cbdd8ff 100644 --- a/libstdc++-v3/include/debug/safe_local_iterator.h +++ b/libstdc++-v3/include/debug/safe_local_iterator.h @@ -431,13 +431,6 @@ namespace __gnu_debug return __lhs.base() != __rhs.base(); } - /** Safe local iterators know if they are dereferenceable. */ - template - inline bool - __check_dereferenceable(const _Safe_local_iterator<_Iterator, - _Sequence>& __x) - { return __x._M_dereferenceable(); } - /** Safe local iterators know how to check if they form a valid range. */ template inline bool @@ -446,14 +439,21 @@ namespace __gnu_debug typename _Distance_traits<_Iterator>::__type& __dist_info) { return __first._M_valid_range(__last, __dist_info); } + template + inline bool + __valid_range(const _Safe_local_iterator<_Iterator, _Sequence>& __first, + 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> + inline typename _Distance_traits<_Iterator>::__type __get_distance(const _Safe_local_iterator<_Iterator, _Sequence>& __first, - const _Safe_local_iterator<_Iterator, _Sequence>& __last, - std::input_iterator_tag) + const _Safe_local_iterator<_Iterator, _Sequence>& __last) { if (__first.base() == __last.base()) return { 0, __dp_exact }; diff --git a/libstdc++-v3/include/debug/set.h b/libstdc++-v3/include/debug/set.h index 571cc47..8f3d83a 100644 --- a/libstdc++-v3/include/debug/set.h +++ b/libstdc++-v3/include/debug/set.h @@ -56,6 +56,8 @@ namespace __debug typedef __gnu_debug::_Equal_to<_Base_const_iterator> _Equal; public: + typedef _Base normal_type; + // types: typedef _Key key_type; typedef _Key value_type; @@ -65,9 +67,9 @@ namespace __debug typedef typename _Base::reference reference; typedef typename _Base::const_reference const_reference; - typedef __gnu_debug::_Safe_iterator<_Base_iterator, set> + typedef __gnu_debug::_Safe_tagged_iterator<_Base_iterator, set> iterator; - typedef __gnu_debug::_Safe_iterator<_Base_const_iterator, set> + typedef __gnu_debug::_Safe_tagged_iterator<_Base_const_iterator, set> const_iterator; typedef typename _Base::size_type size_type; diff --git a/libstdc++-v3/include/debug/stl_iterator.h b/libstdc++-v3/include/debug/stl_iterator.h index f20b000..fd20160 100644 --- a/libstdc++-v3/include/debug/stl_iterator.h +++ b/libstdc++-v3/include/debug/stl_iterator.h @@ -52,12 +52,13 @@ namespace __gnu_debug __can_advance(const std::reverse_iterator<_Iterator>& __it, _Size __n) { return __can_advance(__it.base(), -__n); } -#if __cplusplus < 201103L - template - struct __is_safe_random_iterator > - : __is_safe_random_iterator<_Iterator> - { }; + template + inline std::reverse_iterator<_Iterator> + __base(const std::reverse_iterator<_Safe_tagged_iterator< + _Iterator, _Sequence, std::random_access_iterator_tag> >& __it) + { return std::reverse_iterator<_Iterator>(__it.base().base()); } +#if __cplusplus < 201103L template struct _Unsafe_type > { @@ -75,12 +76,6 @@ namespace __gnu_debug #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())); } @@ -124,11 +119,12 @@ namespace std { _GLIBCXX_BEGIN_NAMESPACE_VERSION - template + template _Iterator - __niter_base(const __gnu_debug::_Safe_iterator< + __niter_base(const __gnu_debug::_Safe_tagged_iterator< __gnu_cxx::__normal_iterator<_Iterator, _Container>, - _Sequence>&); + _Sequence, _Category>&); _GLIBCXX_END_NAMESPACE_VERSION } diff --git a/libstdc++-v3/include/debug/string b/libstdc++-v3/include/debug/string index 7fa39e3..3d936ce 100644 --- a/libstdc++-v3/include/debug/string +++ b/libstdc++-v3/include/debug/string @@ -95,6 +95,8 @@ namespace __gnu_debug _Safe; public: + typedef _Base normal_type; + // types: typedef _Traits traits_type; typedef typename _Traits::char_type value_type; @@ -106,9 +108,9 @@ namespace __gnu_debug typedef typename _Base::pointer pointer; typedef typename _Base::const_pointer const_pointer; - typedef __gnu_debug::_Safe_iterator< + typedef __gnu_debug::_Safe_tagged_iterator< typename _Base::iterator, basic_string> iterator; - typedef __gnu_debug::_Safe_iterator< + typedef __gnu_debug::_Safe_tagged_iterator< typename _Base::const_iterator, basic_string> const_iterator; typedef std::reverse_iterator reverse_iterator; diff --git a/libstdc++-v3/include/debug/unordered_map b/libstdc++-v3/include/debug/unordered_map index e4f7c5c..bfc7203 100644 --- a/libstdc++-v3/include/debug/unordered_map +++ b/libstdc++-v3/include/debug/unordered_map @@ -67,6 +67,8 @@ namespace __debug typedef typename _Base::local_iterator _Base_local_iterator; public: + typedef _Base normal_type; + typedef typename _Base::size_type size_type; typedef typename _Base::hasher hasher; typedef typename _Base::key_equal key_equal; @@ -75,9 +77,9 @@ namespace __debug typedef typename _Base::key_type key_type; typedef typename _Base::value_type value_type; - typedef __gnu_debug::_Safe_iterator< + typedef __gnu_debug::_Safe_tagged_iterator< _Base_iterator, unordered_map> iterator; - typedef __gnu_debug::_Safe_iterator< + typedef __gnu_debug::_Safe_tagged_iterator< _Base_const_iterator, unordered_map> const_iterator; typedef __gnu_debug::_Safe_local_iterator< _Base_local_iterator, unordered_map> local_iterator; @@ -753,6 +755,8 @@ namespace __debug typedef typename _Base::local_iterator _Base_local_iterator; public: + typedef _Base normal_type; + typedef typename _Base::size_type size_type; typedef typename _Base::hasher hasher; typedef typename _Base::key_equal key_equal; @@ -761,9 +765,9 @@ namespace __debug typedef typename _Base::key_type key_type; typedef typename _Base::value_type value_type; - typedef __gnu_debug::_Safe_iterator< + typedef __gnu_debug::_Safe_tagged_iterator< _Base_iterator, unordered_multimap> iterator; - typedef __gnu_debug::_Safe_iterator< + typedef __gnu_debug::_Safe_tagged_iterator< _Base_const_iterator, unordered_multimap> const_iterator; typedef __gnu_debug::_Safe_local_iterator< _Base_local_iterator, unordered_multimap> local_iterator; diff --git a/libstdc++-v3/include/debug/unordered_set b/libstdc++-v3/include/debug/unordered_set index adafdb7..586bd18 100644 --- a/libstdc++-v3/include/debug/unordered_set +++ b/libstdc++-v3/include/debug/unordered_set @@ -67,6 +67,8 @@ namespace __debug typedef typename _Base::local_iterator _Base_local_iterator; public: + typedef _Base normal_type; + typedef typename _Base::size_type size_type; typedef typename _Base::hasher hasher; typedef typename _Base::key_equal key_equal; @@ -75,9 +77,9 @@ namespace __debug typedef typename _Base::key_type key_type; typedef typename _Base::value_type value_type; - typedef __gnu_debug::_Safe_iterator< + typedef __gnu_debug::_Safe_tagged_iterator< _Base_iterator, unordered_set> iterator; - typedef __gnu_debug::_Safe_iterator< + typedef __gnu_debug::_Safe_tagged_iterator< _Base_const_iterator, unordered_set> const_iterator; typedef __gnu_debug::_Safe_local_iterator< _Base_local_iterator, unordered_set> local_iterator; @@ -630,6 +632,8 @@ namespace __debug typedef typename _Base::local_iterator _Base_local_iterator; public: + typedef _Base normal_type; + typedef typename _Base::size_type size_type; typedef typename _Base::hasher hasher; typedef typename _Base::key_equal key_equal; @@ -638,9 +642,9 @@ namespace __debug typedef typename _Base::key_type key_type; typedef typename _Base::value_type value_type; - typedef __gnu_debug::_Safe_iterator< + typedef __gnu_debug::_Safe_tagged_iterator< _Base_iterator, unordered_multiset> iterator; - typedef __gnu_debug::_Safe_iterator< + typedef __gnu_debug::_Safe_tagged_iterator< _Base_const_iterator, unordered_multiset> const_iterator; typedef __gnu_debug::_Safe_local_iterator< _Base_local_iterator, unordered_multiset> local_iterator; diff --git a/libstdc++-v3/include/debug/vector b/libstdc++-v3/include/debug/vector index ced5520..624e4ce 100644 --- a/libstdc++-v3/include/debug/vector +++ b/libstdc++-v3/include/debug/vector @@ -128,12 +128,14 @@ namespace __debug typedef __gnu_debug::_Equal_to<_Base_const_iterator> _Equal; public: + typedef _Base normal_type; + typedef typename _Base::reference reference; typedef typename _Base::const_reference const_reference; - typedef __gnu_debug::_Safe_iterator< + typedef __gnu_debug::_Safe_tagged_iterator< _Base_iterator, vector> iterator; - typedef __gnu_debug::_Safe_iterator< + typedef __gnu_debug::_Safe_tagged_iterator< _Base_const_iterator, vector> const_iterator; typedef typename _Base::size_type size_type; @@ -785,11 +787,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return std::hash<_GLIBCXX_STD_C::vector>()(__b); } }; - template + template _Iterator - __niter_base(const __gnu_debug::_Safe_iterator< + __niter_base(const __gnu_debug::_Safe_tagged_iterator< __gnu_cxx::__normal_iterator<_Iterator, _Container>, - _Sequence>& __it) + _Sequence, _Category>& __it) { return std::__niter_base(__it.base()); } _GLIBCXX_END_NAMESPACE_VERSION diff --git a/libstdc++-v3/testsuite/23_containers/list/68222_neg.cc b/libstdc++-v3/testsuite/23_containers/list/68222_neg.cc new file mode 100644 index 0000000..d969b6a --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/list/68222_neg.cc @@ -0,0 +1,37 @@ +// Copyright (C) 2018 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// { dg-do compile { target c++11 } } + +#include + +void +test01() +{ + // A list of int. + const std::list nums = { 1, 2, 3, 4 }; + + // Grab the iterator type. + using list_itr_type = decltype( std::cbegin( nums ) ); + + // Confirm cend returns the same type. + static_assert( std::is_same< decltype( std::cend( nums ) ), list_itr_type >::value, "" ); + + // The list's iterator type provides a well-formed non-member operator-() with valid return type (long int) + using substraction_type + = decltype( std::declval() - std::declval() ); // { dg-error "no match for 'operator-'" } +} diff --git a/libstdc++-v3/testsuite/23_containers/unordered_set/debug/debug_functions.cc b/libstdc++-v3/testsuite/23_containers/unordered_set/debug/debug_functions.cc index 9fb12ed..1d45e74 100644 --- a/libstdc++-v3/testsuite/23_containers/unordered_set/debug/debug_functions.cc +++ b/libstdc++-v3/testsuite/23_containers/unordered_set/debug/debug_functions.cc @@ -21,31 +21,6 @@ #include #include -void test01() -{ - using namespace __gnu_debug; - - std::unordered_set u = { 0, 1, 2 }; - VERIFY( __check_dereferenceable(u.begin()) ); - auto it = u.begin(); - VERIFY( __check_dereferenceable(it) ); - - VERIFY( __check_dereferenceable(u.cbegin()) ); - auto cit = u.begin(); - VERIFY( __check_dereferenceable(cit) ); - - VERIFY( !__check_dereferenceable(u.end()) ); - it = u.end(); - VERIFY( !__check_dereferenceable(it) ); - - auto bucket = u.bucket(0); - VERIFY( __check_dereferenceable(u.begin(bucket)) ); - auto lit = u.begin(bucket); - VERIFY( __check_dereferenceable(lit) ); - - VERIFY( !__check_dereferenceable(u.end(bucket)) ); -} - void test02() { using namespace __gnu_debug; @@ -84,7 +59,6 @@ void test02() int main() { - test01(); test02(); return 0; } diff --git a/libstdc++-v3/testsuite/23_containers/vector/cons/destructible_debug_neg.cc b/libstdc++-v3/testsuite/23_containers/vector/cons/destructible_debug_neg.cc index 5127f51..6490414 100644 --- a/libstdc++-v3/testsuite/23_containers/vector/cons/destructible_debug_neg.cc +++ b/libstdc++-v3/testsuite/23_containers/vector/cons/destructible_debug_neg.cc @@ -45,4 +45,4 @@ test02() // { dg-error "value type is destructible" "" { target *-*-* } 0 } // In Debug Mode the "required from here" errors come from -// { dg-error "required from here" "" { target *-*-* } 155 } +// { dg-error "required from here" "" { target *-*-* } 157 } diff --git a/libstdc++-v3/testsuite/23_containers/vector/debug/debug_functions.cc b/libstdc++-v3/testsuite/23_containers/vector/debug/debug_functions.cc index ea683ee..acbd0d1 100644 --- a/libstdc++-v3/testsuite/23_containers/vector/debug/debug_functions.cc +++ b/libstdc++-v3/testsuite/23_containers/vector/debug/debug_functions.cc @@ -20,28 +20,6 @@ #include #include -void test01() -{ - using namespace __gnu_debug; - - std::vector v1(3, 1); - VERIFY( __check_dereferenceable(v1.begin()) ); - std::vector::iterator it = v1.begin(); - VERIFY( __check_dereferenceable(it) ); - - VERIFY( !__check_dereferenceable(v1.end()) ); - it = v1.end(); - VERIFY( !__check_dereferenceable(it) ); - - const volatile int* pi = 0; - VERIFY( !__check_dereferenceable(pi) ); - - int i; - pi = &i; - - VERIFY( __check_dereferenceable(pi) ); -} - void test02() { using namespace __gnu_debug; @@ -67,7 +45,6 @@ void test02() int main() { - test01(); test02(); return 0; } diff --git a/libstdc++-v3/testsuite/util/testsuite_containers.h b/libstdc++-v3/testsuite/util/testsuite_containers.h index 2dd5a5f..d05d3ac 100644 --- a/libstdc++-v3/testsuite/util/testsuite_containers.h +++ b/libstdc++-v3/testsuite/util/testsuite_containers.h @@ -20,6 +20,7 @@ #ifndef _GLIBCXX_TESTSUITE_CONTAINERS_H #define _GLIBCXX_TESTSUITE_CONTAINERS_H +#include #include #include #include // for rel_ops. @@ -192,6 +193,77 @@ namespace __gnu_test forward_members_unordered(_Tp& container) { } }; + template::iterator_category> + struct iterator_concept_checks; + + template + struct iterator_concept_checks<_Iterator, false, + std::forward_iterator_tag> + { + iterator_concept_checks() + { + using namespace __gnu_cxx; + __function_requires<_ForwardIteratorConcept<_Iterator>>(); + } + }; + + template + struct iterator_concept_checks<_Iterator, true, + std::forward_iterator_tag> + { + iterator_concept_checks() + { + using namespace __gnu_cxx; + __function_requires<_Mutable_ForwardIteratorConcept<_Iterator>>(); + } + }; + + template + struct iterator_concept_checks<_Iterator, false, + std::bidirectional_iterator_tag> + { + iterator_concept_checks() + { + using namespace __gnu_cxx; + __function_requires<_BidirectionalIteratorConcept<_Iterator>>(); + } + }; + + template + struct iterator_concept_checks<_Iterator, true, + std::bidirectional_iterator_tag> + { + iterator_concept_checks() + { + using namespace __gnu_cxx; + __function_requires<_Mutable_BidirectionalIteratorConcept<_Iterator>>(); + } + }; + + template + struct iterator_concept_checks<_Iterator, false, + std::random_access_iterator_tag> + { + iterator_concept_checks() + { + using namespace __gnu_cxx; + __function_requires<_RandomAccessIteratorConcept<_Iterator>>(); + } + }; + + template + struct iterator_concept_checks<_Iterator, true, + std::random_access_iterator_tag> + { + iterator_concept_checks() + { + using namespace __gnu_cxx; + __function_requires<_Mutable_RandomAccessIteratorConcept<_Iterator>>(); + } + }; + template struct citerator { @@ -210,6 +282,11 @@ namespace __gnu_test // when comparing iterators. using namespace std::rel_ops; + iterator_concept_checks cc; + iterator_concept_checks ccc; + assert( _S_container.cbegin() == _S_container.begin() ); assert( _S_container.end() == _S_container.cend() ); assert( _S_container.cbegin() != _S_container.cend() );