[gcc r15-1955] libstdc++: ranges::find needs explicit conversion to size_t [PR115799]
Jonathan Wakely
redi@gcc.gnu.org
Wed Jul 10 21:06:06 GMT 2024
https://gcc.gnu.org/g:cda469a59e222496248025e0834a15d466f79d4a
commit r15-1955-gcda469a59e222496248025e0834a15d466f79d4a
Author: Jonathan Wakely <jwakely@redhat.com>
Date: Mon Jul 8 10:45:52 2024 +0100
libstdc++: ranges::find needs explicit conversion to size_t [PR115799]
For an integer-class type we need to use an explicit conversion to size_t.
libstdc++-v3/ChangeLog:
PR libstdc++/115799
* include/bits/ranges_util.h (__find_fn): Make conversion
from difference type ti size_t explicit.
* testsuite/25_algorithms/find/bytes.cc: Check ranges::find with
__gnu_test::test_contiguous_range.
* testsuite/std/ranges/range.cc: Adjust expected difference_type
for __gnu_test::test_contiguous_range.
* testsuite/util/testsuite_iterators.h (contiguous_iterator_wrapper):
Use __max_diff_type as difference type.
(test_range::sentinel, test_sized_range_sized_sent::sentinel):
Ensure that operator- returns difference_type.
Diff:
---
libstdc++-v3/include/bits/ranges_util.h | 3 +-
libstdc++-v3/testsuite/25_algorithms/find/bytes.cc | 10 ++++++
libstdc++-v3/testsuite/std/ranges/range.cc | 5 ++-
libstdc++-v3/testsuite/util/testsuite_iterators.h | 42 ++++++++++++++++------
4 files changed, 48 insertions(+), 12 deletions(-)
diff --git a/libstdc++-v3/include/bits/ranges_util.h b/libstdc++-v3/include/bits/ranges_util.h
index a1f42875b11d..e6d96073e87b 100644
--- a/libstdc++-v3/include/bits/ranges_util.h
+++ b/libstdc++-v3/include/bits/ranges_util.h
@@ -506,9 +506,10 @@ namespace ranges
if (static_cast<_Vt>(__value) == __value) [[likely]]
if (__n > 0)
{
+ const size_t __nu = static_cast<size_t>(__n);
const int __ival = static_cast<int>(__value);
const void* __p0 = std::to_address(__first);
- if (auto __p1 = __builtin_memchr(__p0, __ival, __n))
+ if (auto __p1 = __builtin_memchr(__p0, __ival, __nu))
__n = (const char*)__p1 - (const char*)__p0;
}
return __first + __n;
diff --git a/libstdc++-v3/testsuite/25_algorithms/find/bytes.cc b/libstdc++-v3/testsuite/25_algorithms/find/bytes.cc
index e1d6c01ab215..03dada0fec75 100644
--- a/libstdc++-v3/testsuite/25_algorithms/find/bytes.cc
+++ b/libstdc++-v3/testsuite/25_algorithms/find/bytes.cc
@@ -114,9 +114,19 @@ test_non_characters()
#endif
}
+#if __cpp_lib_ranges
+void
+test_pr115799c0(__gnu_test::test_contiguous_range<char> r)
+{
+ // Non-common range with integer-class type as difference_type.
+ (void) std::ranges::find(r, 'a');
+}
+#endif
+
void
test_pr115799c2(__gnu_test::input_iterator_wrapper<char> i)
{
+ // Non-contiguous range of character type.
(void) std::find(i, i, 'a');
}
diff --git a/libstdc++-v3/testsuite/std/ranges/range.cc b/libstdc++-v3/testsuite/std/ranges/range.cc
index 760f6ffacfdb..5464a9bf66bc 100644
--- a/libstdc++-v3/testsuite/std/ranges/range.cc
+++ b/libstdc++-v3/testsuite/std/ranges/range.cc
@@ -56,6 +56,7 @@ static_assert( std::ranges::range<test_output_sized_range<int>&> );
using std::same_as;
using C = test_contiguous_range<char>;
+using R = test_random_access_range<char>;
using I = test_input_range<char>;
using O = test_output_range<char>;
@@ -69,7 +70,9 @@ static_assert( same_as<std::ranges::sentinel_t<C>,
static_assert( same_as<std::ranges::sentinel_t<O>,
decltype(std::declval<O&>().end())> );
-static_assert( same_as<std::ranges::range_difference_t<C>,
+static_assert( ! same_as<std::ranges::range_difference_t<C>,
+ std::ptrdiff_t> ); // __detail::__max_diff_type
+static_assert( same_as<std::ranges::range_difference_t<R>,
std::ptrdiff_t> );
static_assert( same_as<std::ranges::range_difference_t<O>,
std::ptrdiff_t> );
diff --git a/libstdc++-v3/testsuite/util/testsuite_iterators.h b/libstdc++-v3/testsuite/util/testsuite_iterators.h
index ec2971284b4c..e7f7abe222d5 100644
--- a/libstdc++-v3/testsuite/util/testsuite_iterators.h
+++ b/libstdc++-v3/testsuite/util/testsuite_iterators.h
@@ -34,6 +34,10 @@
#include <bits/move.h>
#endif
+#if __cplusplus > 201703L
+#include <bits/max_size_type.h>
+#endif
+
#ifndef _TESTSUITE_ITERATORS
#define _TESTSUITE_ITERATORS
@@ -675,6 +679,9 @@ namespace __gnu_test
using iterator_concept = std::contiguous_iterator_tag;
+ // Use an integer-class type to try and break the library code.
+ using difference_type = std::ranges::__detail::__max_diff_type;
+
contiguous_iterator_wrapper&
operator++()
{
@@ -706,27 +713,42 @@ namespace __gnu_test
}
contiguous_iterator_wrapper&
- operator+=(std::ptrdiff_t n)
+ operator+=(difference_type n)
{
- random_access_iterator_wrapper<T>::operator+=(n);
+ auto d = static_cast<std::ptrdiff_t>(n);
+ random_access_iterator_wrapper<T>::operator+=(d);
return *this;
}
friend contiguous_iterator_wrapper
- operator+(contiguous_iterator_wrapper iter, std::ptrdiff_t n)
+ operator+(contiguous_iterator_wrapper iter, difference_type n)
{ return iter += n; }
friend contiguous_iterator_wrapper
- operator+(std::ptrdiff_t n, contiguous_iterator_wrapper iter)
+ operator+(difference_type n, contiguous_iterator_wrapper iter)
{ return iter += n; }
contiguous_iterator_wrapper&
- operator-=(std::ptrdiff_t n)
+ operator-=(difference_type n)
{ return *this += -n; }
friend contiguous_iterator_wrapper
- operator-(contiguous_iterator_wrapper iter, std::ptrdiff_t n)
+ operator-(contiguous_iterator_wrapper iter, difference_type n)
{ return iter -= n; }
+
+ friend difference_type
+ operator-(contiguous_iterator_wrapper l, contiguous_iterator_wrapper r)
+ {
+ const random_access_iterator_wrapper<T>& lbase = l;
+ const random_access_iterator_wrapper<T>& rbase = r;
+ return static_cast<difference_type>(lbase - rbase);
+ }
+
+ decltype(auto) operator[](difference_type n) const
+ {
+ auto d = static_cast<std::ptrdiff_t>(n);
+ return random_access_iterator_wrapper<T>::operator[](d);
+ }
};
template<typename T>
@@ -788,11 +810,11 @@ namespace __gnu_test
friend auto operator-(const sentinel& s, const I& i) noexcept
requires std::random_access_iterator<I>
- { return s.end - i.ptr; }
+ { return std::iter_difference_t<I>(s.end - i.ptr); }
friend auto operator-(const I& i, const sentinel& s) noexcept
requires std::random_access_iterator<I>
- { return i.ptr - s.end; }
+ { return std::iter_difference_t<I>(i.ptr - s.end); }
};
protected:
@@ -890,11 +912,11 @@ namespace __gnu_test
friend std::iter_difference_t<I>
operator-(const sentinel& s, const I& i) noexcept
- { return s.end - i.ptr; }
+ { return std::iter_difference_t<I>(s.end - i.ptr); }
friend std::iter_difference_t<I>
operator-(const I& i, const sentinel& s) noexcept
- { return i.ptr - s.end; }
+ { return std::iter_difference_t<I>(i.ptr - s.end); }
};
auto end() &
More information about the Libstdc++-cvs
mailing list