Pushed to trunk.
On Mon, 8 Jul 2024 at 20:44, Jonathan Wakely <jwak...@redhat.com> wrote:
>
> This fixes another problem with my recent changes to use memchr in
> std::find.
>
> Tested x86_64-linux.
>
> -- >8 --
>
> 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.
> ---
> libstdc++-v3/include/bits/ranges_util.h | 3 +-
> .../testsuite/25_algorithms/find/bytes.cc | 10 +++++
> libstdc++-v3/testsuite/std/ranges/range.cc | 5 ++-
> .../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 a1f42875b11..e6d96073e87 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 e1d6c01ab21..03dada0fec7 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 760f6ffacfd..5464a9bf66b 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 ec2971284b4..e7f7abe222d 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() &
> --
> 2.45.2
>