[gcc r12-3939] libstdc++: Fix concept checks for iterators

Jonathan Wakely redi@gcc.gnu.org
Tue Sep 28 19:24:51 GMT 2021


https://gcc.gnu.org/g:afffc96a5259ba4e3f3cca154dc5ea32a496875e

commit r12-3939-gafffc96a5259ba4e3f3cca154dc5ea32a496875e
Author: Jonathan Wakely <jwakely@redhat.com>
Date:   Fri Sep 24 13:56:33 2021 +0100

    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 <jwakely@redhat.com>
    
    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:
---
 libstdc++-v3/include/bits/boost_concept_check.h    | 81 +++++++++++++++++++---
 .../testsuite/24_iterators/operations/prev_neg.cc  |  2 +-
 2 files changed, 72 insertions(+), 11 deletions(-)

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 <bits/c++config.h>
 #include <bits/stl_iterator_base_types.h>    // 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 <class _Tp>
+  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 <class _Tp>
+  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<bool>::iterator is not a real forward reference, but pretend it is.
+  template <>
+  struct _ForwardIteratorReferenceConcept<std::_Bit_iterator>
+  {
+    void __constraints() { }
+  };
+
+  // vector<bool>::iterator is not a real forward reference, but pretend it is.
+  template <>
+  struct _Mutable_ForwardIteratorReferenceConcept<std::_Bit_iterator>
+  {
+    void __constraints() { }
+  };
+
+  // And vector<bool>::const iterator too.
+  template <>
+  struct _ForwardIteratorReferenceConcept<std::_Bit_const_iterator>
+  {
+    void __constraints() { }
+  };
+
   template <class _Tp>
   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 }
 }


More information about the Libstdc++-cvs mailing list