]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
libstdc++: ranges::find needs explicit conversion to size_t [PR115799]
authorJonathan Wakely <jwakely@redhat.com>
Mon, 8 Jul 2024 09:45:52 +0000 (10:45 +0100)
committerJonathan Wakely <redi@gcc.gnu.org>
Wed, 10 Jul 2024 21:05:21 +0000 (22:05 +0100)
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
libstdc++-v3/testsuite/25_algorithms/find/bytes.cc
libstdc++-v3/testsuite/std/ranges/range.cc
libstdc++-v3/testsuite/util/testsuite_iterators.h

index a1f42875b11d9470e5ae91280c5742be449972d1..e6d96073e87b2b7c1d4faceb06e084a02c12b7ec 100644 (file)
@@ -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;
index e1d6c01ab215bdd5b63d307aa0fed1d197017e07..03dada0fec753be3d2650eaebf5c2b085012f700 100644 (file)
@@ -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');
 }
 
index 760f6ffacfdb943b8c38d9a59ef3cd87437f9925..5464a9bf66bc1edf7d0649b05e2f2038652b733d 100644 (file)
@@ -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> );
index ec2971284b4cb8cf372938456ff42166132bebc0..e7f7abe222d54470c0a41e979501d9c6f0bbba8d 100644 (file)
 #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() &