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.
This commit is contained in:
parent
5f1db7627f
commit
afffc96a52
2 changed files with 72 additions and 11 deletions
|
@ -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
|
||||
|
||||
|
|
|
@ -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 }
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue