From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by sourceware.org (Postfix) with ESMTP id D7C1B385843B for ; Tue, 28 Sep 2021 19:26:14 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org D7C1B385843B Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-70-6QzprD_EPBa09QIBiRHzlQ-1; Tue, 28 Sep 2021 15:26:12 -0400 X-MC-Unique: 6QzprD_EPBa09QIBiRHzlQ-1 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 0E42118414A1; Tue, 28 Sep 2021 19:26:12 +0000 (UTC) Received: from localhost (unknown [10.33.36.241]) by smtp.corp.redhat.com (Postfix) with ESMTP id 942205D6BA; Tue, 28 Sep 2021 19:26:11 +0000 (UTC) Date: Tue, 28 Sep 2021 20:26:10 +0100 From: Jonathan Wakely To: libstdc++@gcc.gnu.org, gcc-patches@gcc.gnu.org Subject: [committed] libstdc++: Fix concept checks for iterators Message-ID: MIME-Version: 1.0 X-Clacks-Overhead: GNU Terry Pratchett X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Type: multipart/mixed; boundary="LwsOz1mNLElY5R82" Content-Disposition: inline X-Spam-Status: No, score=-13.8 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_DNSWL_LOW, RCVD_IN_MSPIKE_H2, SPF_HELO_NONE, SPF_NONE, TXREP autolearn=ham autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on server2.sourceware.org X-BeenThere: libstdc++@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Libstdc++ mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 28 Sep 2021 19:26:16 -0000 --LwsOz1mNLElY5R82 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline This adds some additional checks the the C++98-style concept checks for iterators, and removes some bogus checks for mutable iterators. Instead of requiring that the result of dereferencing a mutable iterator is assignable (which is a property of the value type, not required for the iterator) check that the reference type is a non-const reference to the value type. Signed-off-by: Jonathan Wakely libstdc++-v3/ChangeLog: * include/bits/boost_concept_check.h (_ForwardIteratorConcept) (_BidirectionalIteratorConcept, _RandomAccessIteratorConcept): Check result types of iterator operations. (_Mutable_ForwardIteratorConcept): Check that iterator's reference type is a reference to its value type. (_Mutable_BidirectionalIteratorConcept): Do not require the value type to be assignable. (_Mutable_RandomAccessIteratorConcept): Likewise. * testsuite/24_iterators/operations/prev_neg.cc: Adjust dg-error line number. Tested x86_64-linux. Committed to trunk. --LwsOz1mNLElY5R82 Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="patch.txt" commit afffc96a5259ba4e3f3cca154dc5ea32a496875e Author: Jonathan Wakely Date: Fri Sep 24 13:56:33 2021 libstdc++: Fix concept checks for iterators This adds some additional checks the the C++98-style concept checks for iterators, and removes some bogus checks for mutable iterators. Instead of requiring that the result of dereferencing a mutable iterator is assignable (which is a property of the value type, not required for the iterator) check that the reference type is a non-const reference to the value type. Signed-off-by: Jonathan Wakely libstdc++-v3/ChangeLog: * include/bits/boost_concept_check.h (_ForwardIteratorConcept) (_BidirectionalIteratorConcept, _RandomAccessIteratorConcept): Check result types of iterator operations. (_Mutable_ForwardIteratorConcept): Check that iterator's reference type is a reference to its value type. (_Mutable_BidirectionalIteratorConcept): Do not require the value type to be assignable. (_Mutable_RandomAccessIteratorConcept): Likewise. * testsuite/24_iterators/operations/prev_neg.cc: Adjust dg-error line number. diff --git a/libstdc++-v3/include/bits/boost_concept_check.h b/libstdc++-v3/include/bits/boost_concept_check.h index ba36c24abec..71c99c13e93 100644 --- a/libstdc++-v3/include/bits/boost_concept_check.h +++ b/libstdc++-v3/include/bits/boost_concept_check.h @@ -44,6 +44,14 @@ #include #include // for traits and tags +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + struct _Bit_iterator; + struct _Bit_const_iterator; +_GLIBCXX_END_NAMESPACE_VERSION +} + namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) { _GLIBCXX_BEGIN_NAMESPACE_VERSION @@ -470,6 +478,52 @@ struct _Aux_require_same<_Tp,_Tp> { typedef _Tp _Type; }; _ValueT __val() const; }; +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-variable" + + template + struct _ForwardIteratorReferenceConcept + { + void __constraints() { +#if __cplusplus >= 201103L + typedef typename std::iterator_traits<_Tp>::reference _Ref; + static_assert(std::is_reference<_Ref>::value, + "reference type of a forward iterator must be a real reference"); +#endif + } + }; + + template + struct _Mutable_ForwardIteratorReferenceConcept + { + void __constraints() { + typedef typename std::iterator_traits<_Tp>::reference _Ref; + typedef typename std::iterator_traits<_Tp>::value_type _Val; + __function_requires< _SameTypeConcept<_Ref, _Val&> >(); + } + }; + + // vector::iterator is not a real forward reference, but pretend it is. + template <> + struct _ForwardIteratorReferenceConcept + { + void __constraints() { } + }; + + // vector::iterator is not a real forward reference, but pretend it is. + template <> + struct _Mutable_ForwardIteratorReferenceConcept + { + void __constraints() { } + }; + + // And vector::const iterator too. + template <> + struct _ForwardIteratorReferenceConcept + { + void __constraints() { } + }; + template struct _ForwardIteratorConcept { @@ -479,8 +533,12 @@ struct _Aux_require_same<_Tp,_Tp> { typedef _Tp _Type; }; __function_requires< _ConvertibleConcept< typename std::iterator_traits<_Tp>::iterator_category, std::forward_iterator_tag> >(); + __function_requires< _ForwardIteratorReferenceConcept<_Tp> >(); + _Tp& __j = ++__i; + const _Tp& __k = __i++; typedef typename std::iterator_traits<_Tp>::reference _Ref; - _Ref __r _IsUnused = *__i; + _Ref __r = *__k; + _Ref __r2 = *__i++; } _Tp __i; }; @@ -490,7 +548,9 @@ struct _Aux_require_same<_Tp,_Tp> { typedef _Tp _Type; }; { void __constraints() { __function_requires< _ForwardIteratorConcept<_Tp> >(); - *__i++ = *__i; // require postincrement and assignment + typedef typename std::iterator_traits<_Tp>::reference _Ref; + typedef typename std::iterator_traits<_Tp>::value_type _Val; + __function_requires< _Mutable_ForwardIteratorReferenceConcept<_Tp> >(); } _Tp __i; }; @@ -503,8 +563,10 @@ struct _Aux_require_same<_Tp,_Tp> { typedef _Tp _Type; }; __function_requires< _ConvertibleConcept< typename std::iterator_traits<_Tp>::iterator_category, std::bidirectional_iterator_tag> >(); - --__i; // require predecrement operator - __i--; // require postdecrement operator + _Tp& __j = --__i; // require predecrement operator + const _Tp& __k = __i--; // require postdecrement operator + typedef typename std::iterator_traits<_Tp>::reference _Ref; + _Ref __r = *__j--; } _Tp __i; }; @@ -515,7 +577,6 @@ struct _Aux_require_same<_Tp,_Tp> { typedef _Tp _Type; }; void __constraints() { __function_requires< _BidirectionalIteratorConcept<_Tp> >(); __function_requires< _Mutable_ForwardIteratorConcept<_Tp> >(); - *__i-- = *__i; // require postdecrement and assignment } _Tp __i; }; @@ -530,16 +591,15 @@ struct _Aux_require_same<_Tp,_Tp> { typedef _Tp _Type; }; __function_requires< _ConvertibleConcept< typename std::iterator_traits<_Tp>::iterator_category, std::random_access_iterator_tag> >(); - // ??? We don't use _Ref, are we just checking for "referenceability"? typedef typename std::iterator_traits<_Tp>::reference _Ref; - __i += __n; // require assignment addition operator + _Tp& __j = __i += __n; // require assignment addition operator __i = __i + __n; __i = __n + __i; // require addition with difference type - __i -= __n; // require assignment subtraction op + _Tp& __k = __i -= __n; // require assignment subtraction op __i = __i - __n; // require subtraction with // difference type __n = __i - __j; // require difference operator - (void)__i[__n]; // require element access operator + _Ref __r = __i[__n]; // require element access operator } _Tp __a, __b; _Tp __i, __j; @@ -552,12 +612,13 @@ struct _Aux_require_same<_Tp,_Tp> { typedef _Tp _Type; }; void __constraints() { __function_requires< _RandomAccessIteratorConcept<_Tp> >(); __function_requires< _Mutable_BidirectionalIteratorConcept<_Tp> >(); - __i[__n] = *__i; // require element access and assignment } _Tp __i; typename std::iterator_traits<_Tp>::difference_type __n; }; +#pragma GCC diagnostic pop + //=========================================================================== // Container Concepts diff --git a/libstdc++-v3/testsuite/24_iterators/operations/prev_neg.cc b/libstdc++-v3/testsuite/24_iterators/operations/prev_neg.cc index cafafc4b651..d22491999a8 100644 --- a/libstdc++-v3/testsuite/24_iterators/operations/prev_neg.cc +++ b/libstdc++-v3/testsuite/24_iterators/operations/prev_neg.cc @@ -38,5 +38,5 @@ test02() { const Y array[1] = { }; (void) std::prev(array + 1); - // { dg-error "forward_iterator" "" { target *-*-* } 223 } + // { dg-error "forward_iterator" "" { target *-*-* } 231 } } --LwsOz1mNLElY5R82--