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 } }