https://gcc.gnu.org/g:cda469a59e222496248025e0834a15d466f79d4a
commit r15-1955-gcda469a59e222496248025e0834a15d466f79d4a Author: Jonathan Wakely <jwak...@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() &