libstdc++: Fix _ForwardIteratorConcept for __gnu_debug::vector<bool>
authorJonathan Wakely <jwakely@redhat.com>
Thu, 30 Sep 2021 10:25:15 +0000 (11:25 +0100)
committerJonathan Wakely <jwakely@redhat.com>
Fri, 1 Oct 2021 14:04:02 +0000 (15:04 +0100)
The recent changes to the _GLIBCXX_CONCEPT_CHECKS checks for forward
iterators don't work for vector<bool> iterators in debug mode, because
the _Safe_iterator specializations don't match the special cases I added
for _Bit_iterator and _Bit_const_iterator.

This refactors the _ForwardIteratorReferenceConcept class template to
identify vector<bool> iterators using a new trait, which also works for
debug iterators.

libstdc++-v3/ChangeLog:

* include/bits/boost_concept_check.h (_Is_vector_bool_iterator):
New trait to identify vector<bool> iterators, including debug
ones.
(_ForwardIteratorReferenceConcept): Add default template
argument using _Is_vector_bool_iterator and use it in partial
specialization for the vector<bool> cases.
(_Mutable_ForwardIteratorReferenceConcept): Likewise.
* testsuite/24_iterators/operations/prev_neg.cc: Adjust dg-error
line number.

libstdc++-v3/include/bits/boost_concept_check.h
libstdc++-v3/testsuite/24_iterators/operations/prev_neg.cc

index 71c99c1..8135251 100644 (file)
 namespace std  _GLIBCXX_VISIBILITY(default)
 {
 _GLIBCXX_BEGIN_NAMESPACE_VERSION
+_GLIBCXX_BEGIN_NAMESPACE_CONTAINER
   struct _Bit_iterator;
   struct _Bit_const_iterator;
+_GLIBCXX_END_NAMESPACE_CONTAINER
 _GLIBCXX_END_NAMESPACE_VERSION
 }
 
+namespace __gnu_debug
+{
+  template<typename _Iterator, typename _Sequence, typename _Category>
+    class _Safe_iterator;
+}
+
 namespace __gnu_cxx _GLIBCXX_VISIBILITY(default)
 {
 _GLIBCXX_BEGIN_NAMESPACE_VERSION
@@ -478,10 +486,32 @@ struct _Aux_require_same<_Tp,_Tp> { typedef _Tp _Type; };
     _ValueT __val() const;
   };
 
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wunused-variable"
+  template<typename _Tp>
+  struct _Is_vector_bool_iterator
+  { static const bool __value = false; };
 
-  template <class _Tp>
+#ifdef _GLIBCXX_DEBUG
+  namespace __cont = ::std::_GLIBCXX_STD_C;
+#else
+  namespace __cont = ::std;
+#endif
+
+  // Trait to identify vector<bool>::iterator
+  template <>
+  struct _Is_vector_bool_iterator<__cont::_Bit_iterator>
+  { static const bool __value = true; };
+
+  // And for vector<bool>::const_iterator.
+  template <>
+  struct _Is_vector_bool_iterator<__cont::_Bit_const_iterator>
+  { static const bool __value = true; };
+
+  // And for __gnu_debug::vector<bool> iterators too.
+  template <typename _It, typename _Seq, typename _Tag>
+  struct _Is_vector_bool_iterator<__gnu_debug::_Safe_iterator<_It, _Seq, _Tag> >
+  : _Is_vector_bool_iterator<_It> { };
+
+  template <class _Tp, bool = _Is_vector_bool_iterator<_Tp>::__value>
   struct _ForwardIteratorReferenceConcept
   {
     void __constraints() {
@@ -493,7 +523,7 @@ struct _Aux_require_same<_Tp,_Tp> { typedef _Tp _Type; };
     }
   };
 
-  template <class _Tp>
+  template <class _Tp, bool = _Is_vector_bool_iterator<_Tp>::__value>
   struct _Mutable_ForwardIteratorReferenceConcept
   {
     void __constraints() {
@@ -503,26 +533,22 @@ struct _Aux_require_same<_Tp,_Tp> { typedef _Tp _Type; };
     }
   };
 
-  // vector<bool>::iterator is not a real forward reference, but pretend it is.
-  template <>
-  struct _ForwardIteratorReferenceConcept<std::_Bit_iterator>
+  // vector<bool> iterators are not real forward iterators, but we ignore that.
+  template <class _Tp>
+  struct _ForwardIteratorReferenceConcept<_Tp, true>
   {
     void __constraints() { }
   };
 
-  // vector<bool>::iterator is not a real forward reference, but pretend it is.
-  template <>
-  struct _Mutable_ForwardIteratorReferenceConcept<std::_Bit_iterator>
+  // vector<bool> iterators are not real forward iterators, but we ignore that.
+  template <class _Tp>
+  struct _Mutable_ForwardIteratorReferenceConcept<_Tp, true>
   {
     void __constraints() { }
   };
 
-  // And vector<bool>::const iterator too.
-  template <>
-  struct _ForwardIteratorReferenceConcept<std::_Bit_const_iterator>
-  {
-    void __constraints() { }
-  };
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-variable"
 
   template <class _Tp>
   struct _ForwardIteratorConcept
index d224919..cc64854 100644 (file)
@@ -38,5 +38,5 @@ test02()
 {
   const Y array[1] = { };
   (void) std::prev(array + 1);
-  // { dg-error "forward_iterator" "" { target *-*-* } 231 }
+  // { dg-error "forward_iterator" "" { target *-*-* } 239 }
 }