On Thu, 11 Sep 2025, Jonathan Wakely wrote:

> Whenever we use operator+ or similar operators on random access
> iterators we need to be careful to use the iterator's difference_type
> rather than some other integer type. It's not guaranteed that an
> expression with an arbitrary integer type, such as `it + 1u`, has the
> same effects as `it + iter_difference_t<It>(1)`.
> 
> Some of our algorithms need changes to cast values to the correct type,
> or to use std::next or ranges::next instead of `it + n`. Several tests
> also need fixes where the arithmetic occurs directly in the test.
> 
> The __gnu_test::random_access_iterator_wrapper class template is
> adjusted to have deleted operators that make programs ill-formed if the
> argument to relevant operators is not the difference_type. This will
> make it easier to avoid regressing in future.
> 
> libstdc++-v3/ChangeLog:
> 
>       PR libstdc++/121890
>       * include/bits/ranges_algo.h (ranges::rotate, ranges::shuffle)
>       (__insertion_sort, __unguarded_partition_pivot, __introselect):
>       Use ranges::next to advance iterators.
>       (ranges::push_heap, ranges::pop_heap, ranges::partial_sort)
>       (ranges::partial_sort_copy): Use ranges::prev.
>       (__final_insertion_sort): Use iter_difference_t<Iter>
>       for operand of operator+ on iterator.
>       * include/bits/ranges_base.h (ranges::advance): Use iterator's
>       difference_type for all iterator arithmetic.
>       * include/bits/stl_algo.h (__search_n_aux, __rotate)
>       (__insertion_sort, __unguarded_partition_pivot, __introselect)
>       (__final_insertion_sort, for_each_n, random_shuffle): Likewise.
>       Use local variables in __rotate to avoid duplicate expressions.
>       * include/bits/stl_algobase.h (__fill_n_a, __lc_rai::__newlast1):
>       Likewise.
>       * include/bits/stl_heap.h (push_heap): Likewise.
>       (__is_heap_until): Add static_assert.
>       (__is_heap): Convert distance to difference_type.
>       * include/std/functional (boyer_moore_searcher::operator()): Use
>       iterator's difference_type for iterator arithmetic.
>       * testsuite/util/testsuite_iterators.h
>       (random_access_iterator_wrapper): Add deleted overloads of
>       operators that should be called with difference_type.
>       * testsuite/24_iterators/range_operations/advance.cc: Use
>       ranges::next.
>       * testsuite/25_algorithms/heap/constrained.cc: Use ranges::next
>       and ranges::prev.
>       * testsuite/25_algorithms/nth_element/58800.cc: Use std::next.
>       * testsuite/25_algorithms/nth_element/constrained.cc: Use
>       ptrdiff_t for loop variable.
>       * testsuite/25_algorithms/nth_element/random_test.cc: Use
>       iterator's difference_type instead of int.
>       * testsuite/25_algorithms/partial_sort/check_compare_by_value.cc:
>       Use std::next.
>       * testsuite/25_algorithms/partial_sort/constrained.cc: Use
>       ptrdiff_t for loop variable.
>       * testsuite/25_algorithms/partial_sort/random_test.cc: Use
>       iterator's difference_type instead of int.
>       * testsuite/25_algorithms/partial_sort_copy/constrained.cc:
>       Use ptrdiff_t for loop variable.
>       * testsuite/25_algorithms/partial_sort_copy/random_test.cc:
>       Use iterator's difference_type instead of int.
>       * testsuite/std/ranges/adaptors/drop.cc: Use ranges::next.
>       * testsuite/25_algorithms/fill_n/diff_type.cc: New test.
>       * testsuite/25_algorithms/for_each/diff_type.cc: New test.
>       * testsuite/25_algorithms/lexicographical_compare/diff_type.cc:
>       New test.
>       * testsuite/25_algorithms/push_heap/diff_type.cc: New test.
>       * testsuite/25_algorithms/nth_element/diff_type.cc: New test.
>       * testsuite/25_algorithms/rotate/diff_type.cc: New test.
>       * testsuite/25_algorithms/search_n/diff_type.cc: New test.
>       * testsuite/25_algorithms/sort/diff_type.cc: New test.
> ---
> 
> v2: Applied Tomasz's suggestion to use 'p + D(n - 1)' in __rotate
> instead of 'p + n + D(1)'. Also used local variables to store the
> results of those expressions, removing duplicate subexpressions.
> 
>  libstdc++-v3/include/bits/ranges_algo.h       | 56 +++++++------
>  libstdc++-v3/include/bits/ranges_base.h       |  4 +-
>  libstdc++-v3/include/bits/stl_algo.h          | 81 +++++++++++++------
>  libstdc++-v3/include/bits/stl_algobase.h      | 18 +++--
>  libstdc++-v3/include/bits/stl_heap.h          | 18 +++--
>  libstdc++-v3/include/std/functional           |  2 +-
>  .../24_iterators/range_operations/advance.cc  |  2 +-
>  .../25_algorithms/fill_n/diff_type.cc         | 13 +++
>  .../25_algorithms/for_each/diff_type.cc       | 13 +++
>  .../25_algorithms/heap/constrained.cc         | 20 ++---
>  .../lexicographical_compare/diff_type.cc      | 57 +++++++++++++
>  .../25_algorithms/nth_element/58800.cc        |  2 +-
>  .../25_algorithms/nth_element/constrained.cc  |  2 +-
>  .../25_algorithms/nth_element/diff_type.cc    | 13 +++
>  .../25_algorithms/nth_element/random_test.cc  |  4 +-
>  .../partial_sort/check_compare_by_value.cc    |  4 +-
>  .../25_algorithms/partial_sort/constrained.cc |  3 +-
>  .../25_algorithms/partial_sort/random_test.cc |  4 +-
>  .../partial_sort_copy/constrained.cc          |  4 +-
>  .../partial_sort_copy/random_test.cc          |  4 +-
>  .../25_algorithms/push_heap/diff_type.cc      | 13 +++
>  .../25_algorithms/rotate/diff_type.cc         | 13 +++
>  .../25_algorithms/search_n/diff_type.cc       | 13 +++
>  .../testsuite/25_algorithms/sort/diff_type.cc | 13 +++
>  .../testsuite/std/ranges/adaptors/drop.cc     |  2 +-
>  .../testsuite/util/testsuite_iterators.h      | 18 +++++
>  26 files changed, 306 insertions(+), 90 deletions(-)
>  create mode 100644 libstdc++-v3/testsuite/25_algorithms/fill_n/diff_type.cc
>  create mode 100644 libstdc++-v3/testsuite/25_algorithms/for_each/diff_type.cc
>  create mode 100644 
> libstdc++-v3/testsuite/25_algorithms/lexicographical_compare/diff_type.cc
>  create mode 100644 
> libstdc++-v3/testsuite/25_algorithms/nth_element/diff_type.cc
>  create mode 100644 
> libstdc++-v3/testsuite/25_algorithms/push_heap/diff_type.cc
>  create mode 100644 libstdc++-v3/testsuite/25_algorithms/rotate/diff_type.cc
>  create mode 100644 libstdc++-v3/testsuite/25_algorithms/search_n/diff_type.cc
>  create mode 100644 libstdc++-v3/testsuite/25_algorithms/sort/diff_type.cc
> 
> diff --git a/libstdc++-v3/include/bits/ranges_algo.h 
> b/libstdc++-v3/include/bits/ranges_algo.h
> index 6e1e06cb2d0f..65356fd2dfd0 100644
> --- a/libstdc++-v3/include/bits/ranges_algo.h
> +++ b/libstdc++-v3/include/bits/ranges_algo.h
> @@ -1684,8 +1684,9 @@ namespace ranges
>                     if (__k == 1)
>                       {
>                         auto __t = std::move(*__p);
> -                       ranges::move(__p + 1, __p + __n, __p);
> -                       *(__p + __n - 1) = std::move(__t);
> +                       ranges::move(ranges::next(__p),
> +                                    ranges::next(__p, __n), __p);

Does __p + __n actually need to be changed?  __n seems to have the
proper integral type:

  auto __n = __lasti - __first;

If it's for consistency with the __p + 1 change, I'm fine with that,
just double checking.

> +                       *ranges::next(__p, __n - 1) = std::move(__t);
>                         return {std::move(__ret), std::move(__lasti)};
>                       }
>                   auto __q = __p + __k;
> @@ -1709,8 +1710,10 @@ namespace ranges
>                   if constexpr (__is_pod(iter_value_t<_Iter>))
>                     if (__k == 1)
>                       {
> -                       auto __t = std::move(*(__p + __n - 1));
> -                       ranges::move_backward(__p, __p + __n - 1, __p + __n);
> +                       auto __t = std::move(*ranges::next(__p, __n - 1));
> +                       ranges::move_backward(__p,
> +                                             ranges::next(__p, __n - 1),
> +                                             ranges::next(__p, __n));

Same here

Rest of the patch LGTM

>                         *__p = std::move(__t);
>                         return {std::move(__ret), std::move(__lasti)};
>                       }
> @@ -1970,7 +1973,7 @@ namespace ranges
>       if (__urngrange / __urange >= __urange)
>         // I.e. (__urngrange >= __urange * __urange) but without wrap issues.
>         {
> -         _Iter __i = __first + 1;
> +         _Iter __i = ranges::next(__first);
>  
>           // Since we know the range isn't empty, an even number of elements
>           // means an uneven number of elements /to swap/, in which case we
> @@ -1979,7 +1982,7 @@ namespace ranges
>           if ((__urange % 2) == 0)
>             {
>               __distr_type __d{0, 1};
> -             ranges::iter_swap(__i++, __first + __d(__g));
> +             ranges::iter_swap(__i++, ranges::next(__first, __d(__g)));
>             }
>  
>           // Now we know that __last - __i is even, so we do the rest in 
> pairs,
> @@ -1990,11 +1993,11 @@ namespace ranges
>             {
>               const __uc_type __swap_range = __uc_type(__i - __first) + 1;
>  
> -             const pair<__uc_type, __uc_type> __pospos =
> +             const pair<_DistanceType, _DistanceType> __pospos =
>                 __gen_two_uniform_ints(__swap_range, __swap_range + 1, __g);
>  
> -             ranges::iter_swap(__i++, __first + __pospos.first);
> -             ranges::iter_swap(__i++, __first + __pospos.second);
> +             ranges::iter_swap(__i++, ranges::next(__first, __pospos.first));
> +             ranges::iter_swap(__i++, ranges::next(__first, 
> __pospos.second));
>             }
>  
>           return __i;
> @@ -2002,9 +2005,11 @@ namespace ranges
>  
>       __distr_type __d;
>  
> -     _Iter __i = __first + 1;
> +     _Iter __i = ranges::next(__first);
>       for (; __i != __last; ++__i)
> -       ranges::iter_swap(__i, __first + __d(__g, __p_type(0, __i - 
> __first)));
> +       ranges::iter_swap(__i,
> +                         ranges::next(__first,
> +                                      __d(__g, __p_type(0, __i - __first))));
>  
>       return __i;
>        }
> @@ -2060,7 +2065,7 @@ namespace ranges
>         {
>           auto __comp_proj = __detail::__make_comp_proj(__comp, __proj);
>           __detail::__push_heap(__first, (__last - __first) - 1,
> -                               0, ranges::iter_move(__last - 1),
> +                               0, ranges::iter_move(ranges::prev(__last)),
>                                 __comp_proj);
>           return __last;
>         }
> @@ -2137,8 +2142,9 @@ namespace ranges
>         {
>           if (__last - __first > 1)
>             {
> +             auto __back = ranges::prev(__last);
>               auto __comp_proj = __detail::__make_comp_proj(__comp, __proj);
> -             __detail::__pop_heap(__first, __last - 1, __last - 1, 
> __comp_proj);
> +             __detail::__pop_heap(__first, __back, __back, __comp_proj);
>             }
>           return __last;
>         }
> @@ -2356,12 +2362,12 @@ namespace ranges
>       if (__first == __last)
>         return;
>  
> -     for (_Iter __i = __first + 1; __i != __last; ++__i)
> +     for (_Iter __i = ranges::next(__first); __i != __last; ++__i)
>         {
>           if (__comp(*__i, *__first))
>             {
>               iter_value_t<_Iter> __val = ranges::iter_move(__i);
> -             ranges::move_backward(__first, __i, __i + 1);
> +             ranges::move_backward(__first, __i, ranges::next(__i));
>               *__first = std::move(__val);
>             }
>           else
> @@ -2383,10 +2389,11 @@ namespace ranges
>        constexpr void
>        __final_insertion_sort(_Iter __first, _Iter __last, _Comp __comp)
>        {
> -     if (__last - __first > __sort_threshold)
> +     constexpr iter_difference_t<_Iter> __threshold = __sort_threshold;
> +     if (__last - __first > __threshold)
>         {
> -         __detail::__insertion_sort(__first, __first + __sort_threshold, 
> __comp);
> -         __detail::__unguarded_insertion_sort(__first + __sort_threshold, 
> __last,
> +         __detail::__insertion_sort(__first, __first + __threshold, __comp);
> +         __detail::__unguarded_insertion_sort(__first + __threshold, __last,
>                                                __comp);
>         }
>       else
> @@ -2416,8 +2423,10 @@ namespace ranges
>        __unguarded_partition_pivot(_Iter __first, _Iter __last, _Comp __comp)
>        {
>       _Iter __mid = __first + (__last - __first) / 2;
> -     __detail::__move_median_to_first(__first, __first + 1, __mid, __last - 
> 1, __comp);
> -     return __detail::__unguarded_partition(__first + 1, __last, __first, 
> __comp);
> +     __detail::__move_median_to_first(__first, ranges::next(__first), __mid,
> +                                      ranges::prev(__last), __comp);
> +     return __detail::__unguarded_partition(ranges::next(__first), __last,
> +                                            __first, __comp);
>        }
>  
>      template<typename _Iter, typename _Comp>
> @@ -2745,7 +2754,7 @@ namespace ranges
>                           std::__invoke(__proj, *__first)))
>           {
>             ranges::pop_heap(__first, __middle, __comp, __proj);
> -           ranges::iter_swap(__middle-1, __i);
> +           ranges::iter_swap(std::prev(__middle), __i);
>             ranges::push_heap(__first, __middle, __comp, __proj);
>           }
>       ranges::sort_heap(__first, __middle, __comp, __proj);
> @@ -2812,7 +2821,7 @@ namespace ranges
>           {
>             ranges::pop_heap(__result_first, __result_real_last,
>                              __comp, __proj2);
> -           *(__result_real_last-1) = *__first;
> +           *ranges::prev(__result_real_last) = *__first;
>             ranges::push_heap(__result_first, __result_real_last,
>                               __comp, __proj2);
>           }
> @@ -2924,7 +2933,8 @@ namespace ranges
>         {
>           if (__depth_limit == 0)
>             {
> -             __detail::__heap_select(__first, __nth + 1, __last, __comp);
> +             __detail::__heap_select(__first, ranges::next(__nth), __last,
> +                                     __comp);
>               // Place the nth largest element in its final position.
>               ranges::iter_swap(__first, __nth);
>               return;
> diff --git a/libstdc++-v3/include/bits/ranges_base.h 
> b/libstdc++-v3/include/bits/ranges_base.h
> index 27829086a351..1c4bf432c8f4 100644
> --- a/libstdc++-v3/include/bits/ranges_base.h
> +++ b/libstdc++-v3/include/bits/ranges_base.h
> @@ -900,7 +900,7 @@ namespace ranges
>               if constexpr (assignable_from<_It&, _Sent>)
>                 __it = std::move(__bound);
>               else if constexpr (random_access_iterator<_It>)
> -               __it += 0;
> +               __it += iter_difference_t<_It>(0);
>               return __n;
>             }
>           else if (__diff > 0 ? __n >= __diff : __n <= __diff)
> @@ -920,7 +920,7 @@ namespace ranges
>             {
>               // inline any possible side effects of advance(it, n)
>               if constexpr (random_access_iterator<_It>)
> -               __it += 0;
> +               __it += iter_difference_t<_It>(0);
>               return 0;
>             }
>         }
> diff --git a/libstdc++-v3/include/bits/stl_algo.h 
> b/libstdc++-v3/include/bits/stl_algo.h
> index 81a2457ae6f2..78c63e79a279 100644
> --- a/libstdc++-v3/include/bits/stl_algo.h
> +++ b/libstdc++-v3/include/bits/stl_algo.h
> @@ -204,7 +204,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>         while (__unary_pred(--__backTrack))
>           {
>             if (--__remainder == 0)
> -             return (__first - __count); // Success
> +             return __first - _DistanceType(__count); // Success
>           }
>         __remainder = __count + 1 - (__first - __backTrack);
>       }
> @@ -1258,9 +1258,12 @@ _GLIBCXX_BEGIN_INLINE_ABI_NAMESPACE(_V2)
>           {
>             if (__is_pod(_ValueType) && __k == 1)
>               {
> +               _RandomAccessIterator __mid = __p + _Distance(__n - 1);
> +               _RandomAccessIterator __end = __mid;
> +               ++__end;
>                 _ValueType __t = _GLIBCXX_MOVE(*__p);
> -               _GLIBCXX_MOVE3(__p + 1, __p + __n, __p);
> -               *(__p + __n - 1) = _GLIBCXX_MOVE(__t);
> +               _GLIBCXX_MOVE3(__p + _Distance(1), __end, __p);
> +               *__mid = _GLIBCXX_MOVE(__t);
>                 return __ret;
>               }
>             _RandomAccessIterator __q = __p + __k;
> @@ -1281,8 +1284,11 @@ _GLIBCXX_BEGIN_INLINE_ABI_NAMESPACE(_V2)
>             __k = __n - __k;
>             if (__is_pod(_ValueType) && __k == 1)
>               {
> -               _ValueType __t = _GLIBCXX_MOVE(*(__p + __n - 1));
> -               _GLIBCXX_MOVE_BACKWARD3(__p, __p + __n - 1, __p + __n);
> +               _RandomAccessIterator __mid = __p + _Distance(__n - 1);
> +               _RandomAccessIterator __end = __mid;
> +               ++__end;
> +               _ValueType __t = _GLIBCXX_MOVE(*__mid);
> +               _GLIBCXX_MOVE_BACKWARD3(__p, __mid, __end);
>                 *__p = _GLIBCXX_MOVE(__t);
>                 return __ret;
>               }
> @@ -1770,15 +1776,18 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
>      __insertion_sort(_RandomAccessIterator __first,
>                    _RandomAccessIterator __last, _Compare __comp)
>      {
> -      if (__first == __last) return;
> +      if (__first == __last)
> +     return;
>  
> -      for (_RandomAccessIterator __i = __first + 1; __i != __last; ++__i)
> +      typedef iterator_traits<_RandomAccessIterator> _IterTraits;
> +      typedef typename _IterTraits::difference_type _Dist;
> +
> +      for (_RandomAccessIterator __i = __first + _Dist(1); __i != __last; 
> ++__i)
>       {
>         if (__comp(__i, __first))
>           {
> -           typename iterator_traits<_RandomAccessIterator>::value_type
> -             __val = _GLIBCXX_MOVE(*__i);
> -           _GLIBCXX_MOVE_BACKWARD3(__first, __i, __i + 1);
> +           typename _IterTraits::value_type __val = _GLIBCXX_MOVE(*__i);
> +           _GLIBCXX_MOVE_BACKWARD3(__first, __i, __i + _Dist(1));
>             *__first = _GLIBCXX_MOVE(__val);
>           }
>         else
> @@ -1812,10 +1821,13 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
>      __final_insertion_sort(_RandomAccessIterator __first,
>                          _RandomAccessIterator __last, _Compare __comp)
>      {
> -      if (__last - __first > int(_S_threshold))
> +      typename iterator_traits<_RandomAccessIterator>::difference_type
> +     __threshold = _S_threshold;
> +
> +      if (__last - __first > __threshold)
>       {
> -       std::__insertion_sort(__first, __first + int(_S_threshold), __comp);
> -       std::__unguarded_insertion_sort(__first + int(_S_threshold), __last,
> +       std::__insertion_sort(__first, __first + __threshold, __comp);
> +       std::__unguarded_insertion_sort(__first + __threshold, __last,
>                                         __comp);
>       }
>        else
> @@ -1851,10 +1863,14 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
>      __unguarded_partition_pivot(_RandomAccessIterator __first,
>                               _RandomAccessIterator __last, _Compare __comp)
>      {
> -      _RandomAccessIterator __mid = __first + (__last - __first) / 2;
> -      std::__move_median_to_first(__first, __first + 1, __mid, __last - 1,
> +      typedef iterator_traits<_RandomAccessIterator> _IterTraits;
> +      typedef typename _IterTraits::difference_type _Dist;
> +
> +      _RandomAccessIterator __mid = __first + _Dist((__last - __first) / 2);
> +      _RandomAccessIterator __second = __first + _Dist(1);
> +      std::__move_median_to_first(__first, __second, __mid, __last - 
> _Dist(1),
>                                 __comp);
> -      return std::__unguarded_partition(__first + 1, __last, __first, 
> __comp);
> +      return std::__unguarded_partition(__second, __last, __first, __comp);
>      }
>  
>    template<typename _RandomAccessIterator, typename _Compare>
> @@ -1916,11 +1932,14 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
>                 _RandomAccessIterator __last, _Size __depth_limit,
>                 _Compare __comp)
>      {
> +      _RandomAccessIterator __after_nth = __nth;
> +      ++__after_nth;
> +
>        while (__last - __first > 3)
>       {
>         if (__depth_limit == 0)
>           {
> -           std::__heap_select(__first, __nth + 1, __last, __comp);
> +           std::__heap_select(__first, __after_nth, __last, __comp);
>             // Place the nth largest element in its final position.
>             std::iter_swap(__first, __nth);
>             return;
> @@ -3822,7 +3841,8 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
>       {
>         if (__n2 <= 0)
>           return __first;
> -       auto __last = __first + __n2;
> +       typename iterator_traits<_InputIterator>::difference_type __d = __n2;
> +       auto __last = __first + __d;
>         std::for_each(__first, __last, std::move(__f));
>         return __last;
>       }
> @@ -4544,6 +4564,9 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
>        if (__first == __last)
>       return;
>  
> +      typedef typename 
> iterator_traits<_RandomAccessIterator>::difference_type
> +     _Dist;
> +
>  #if RAND_MAX < __INT_MAX__
>        if (__builtin_expect((__last - __first) >= RAND_MAX / 4, 0))
>       {
> @@ -4551,14 +4574,15 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
>         // instead of using rand() for all the random numbers needed.
>         unsigned __xss
>           = (unsigned)std::rand() ^ ((unsigned)std::rand() << 15);
> -       for (_RandomAccessIterator __i = __first + 1; __i != __last; ++__i)
> +       for (_RandomAccessIterator __i = __first + _Dist(1); __i != __last;
> +            ++__i)
>           {
>             __xss += !__xss;
>             __xss ^= __xss << 13;
>             __xss ^= __xss >> 17;
>             __xss ^= __xss << 5;
> -           _RandomAccessIterator __j = __first
> -                                         + (__xss % ((__i - __first) + 1));
> +           _RandomAccessIterator __j
> +             = __first + _Dist(__xss % ((__i - __first) + 1));
>             if (__i != __j)
>               std::iter_swap(__i, __j);
>           }
> @@ -4566,11 +4590,11 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
>       }
>  #endif
>  
> -      for (_RandomAccessIterator __i = __first + 1; __i != __last; ++__i)
> +      for (_RandomAccessIterator __i = __first + _Dist(1); __i != __last; 
> ++__i)
>       {
>         // XXX rand() % N is not uniformly distributed
> -       _RandomAccessIterator __j = __first
> -                                     + (std::rand() % ((__i - __first) + 1));
> +       _RandomAccessIterator __j
> +         = __first + _Dist(std::rand() % ((__i - __first) + 1));
>         if (__i != __j)
>           std::iter_swap(__i, __j);
>       }
> @@ -4611,9 +4635,14 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
>  
>        if (__first == __last)
>       return;
> -      for (_RandomAccessIterator __i = __first + 1; __i != __last; ++__i)
> +
> +      typedef typename 
> iterator_traits<_RandomAccessIterator>::difference_type
> +     _Dist;
> +
> +      for (_RandomAccessIterator __i = __first + _Dist(1); __i != __last; 
> ++__i)
>       {
> -       _RandomAccessIterator __j = __first + __rand((__i - __first) + 1);
> +       _RandomAccessIterator __j
> +         = __first + _Dist(__rand((__i - __first) + 1));
>         if (__i != __j)
>           std::iter_swap(__i, __j);
>       }
> diff --git a/libstdc++-v3/include/bits/stl_algobase.h 
> b/libstdc++-v3/include/bits/stl_algobase.h
> index b104ec2536a0..820091aee2dc 100644
> --- a/libstdc++-v3/include/bits/stl_algobase.h
> +++ b/libstdc++-v3/include/bits/stl_algobase.h
> @@ -1150,10 +1150,12 @@ _GLIBCXX_END_NAMESPACE_CONTAINER
>        if (__n <= 0)
>       return __first;
>  
> -      __glibcxx_requires_can_increment(__first, __n);
> +      typename iterator_traits<_OutputIterator>::difference_type __d = __n;
> +      __glibcxx_requires_can_increment(__first, __d);
>  
> -      std::__fill_a(__first, __first + __n, __value);
> -      return __first + __n;
> +      _OutputIterator __last = __first + __d;
> +      std::__fill_a(__first, __last, __value);
> +      return __last;
>      }
>  
>    /**
> @@ -1310,11 +1312,11 @@ _GLIBCXX_END_NAMESPACE_CONTAINER
>       __newlast1(_RAI1 __first1, _RAI1 __last1,
>                  _RAI2 __first2, _RAI2 __last2)
>       {
> -       const typename iterator_traits<_RAI1>::difference_type
> -         __diff1 = __last1 - __first1;
> -       const typename iterator_traits<_RAI2>::difference_type
> -         __diff2 = __last2 - __first2;
> -       return __diff2 < __diff1 ? __first1 + __diff2 : __last1;
> +       typedef typename iterator_traits<_RAI1>::difference_type _Diff1;
> +       typedef typename iterator_traits<_RAI2>::difference_type _Diff2;
> +       const _Diff1 __diff1 = __last1 - __first1;
> +       const _Diff2 __diff2 = __last2 - __first2;
> +       return __diff2 < __diff1 ? __first1 + _Diff1(__diff2) : __last1;
>       }
>  
>        template<typename _RAI>
> diff --git a/libstdc++-v3/include/bits/stl_heap.h 
> b/libstdc++-v3/include/bits/stl_heap.h
> index 028ac83eeb70..0e9c94c6865b 100644
> --- a/libstdc++-v3/include/bits/stl_heap.h
> +++ b/libstdc++-v3/include/bits/stl_heap.h
> @@ -76,6 +76,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>      __is_heap_until(_RandomAccessIterator __first, _Distance __n,
>                   _Compare& __comp)
>      {
> +#if __cplusplus >= 201103L
> +      using _IterTraits = iterator_traits<_RandomAccessIterator>;
> +      static_assert(is_same<typename _IterTraits::difference_type,
> +                         _Distance>::value,
> +                 "Argument 'n' must be the iterator's difference type");
> +#endif
>        _Distance __parent = 0;
>        for (_Distance __child = 1; __child < __n; ++__child)
>       {
> @@ -94,8 +100,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>      inline bool
>      __is_heap(_RandomAccessIterator __first, _Distance __n)
>      {
> +      typename iterator_traits<_RandomAccessIterator>::difference_type 
> __d(__n);
>        __gnu_cxx::__ops::_Iter_less_iter __comp;
> -      return std::__is_heap_until(__first, __n, __comp) == __n;
> +      return std::__is_heap_until(__first, __d, __comp) == __n;
>      }
>  
>    template<typename _RandomAccessIterator, typename _Compare,
> @@ -104,9 +111,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>      inline bool
>      __is_heap(_RandomAccessIterator __first, _Compare __comp, _Distance __n)
>      {
> +      typename iterator_traits<_RandomAccessIterator>::difference_type 
> __d(__n);
>        typedef __decltype(__comp) _Cmp;
>        __gnu_cxx::__ops::_Iter_comp_iter<_Cmp> __cmp(_GLIBCXX_MOVE(__comp));
> -      return std::__is_heap_until(__first, __n, __cmp) == __n;
> +      return std::__is_heap_until(__first, __d, __cmp) == __n;
>      }
>  
>    template<typename _RandomAccessIterator>
> @@ -175,7 +183,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>        __glibcxx_requires_heap(__first, __last - 1);
>  
>        __gnu_cxx::__ops::_Iter_less_val __comp;
> -      _ValueType __value = _GLIBCXX_MOVE(*(__last - 1));
> +      _ValueType __value = _GLIBCXX_MOVE(*(__last - _DistanceType(1)));
>        std::__push_heap(__first, _DistanceType((__last - __first) - 1),
>                      _DistanceType(0), _GLIBCXX_MOVE(__value), __comp);
>      }
> @@ -208,11 +216,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>           _RandomAccessIterator>)
>        __glibcxx_requires_valid_range(__first, __last);
>        __glibcxx_requires_irreflexive_pred(__first, __last, __comp);
> -      __glibcxx_requires_heap_pred(__first, __last - 1, __comp);
> +      __glibcxx_requires_heap_pred(__first, __last - _DistanceType(1), 
> __comp);
>  
>        __decltype(__gnu_cxx::__ops::__iter_comp_val(_GLIBCXX_MOVE(__comp)))
>       __cmp(_GLIBCXX_MOVE(__comp));
> -      _ValueType __value = _GLIBCXX_MOVE(*(__last - 1));
> +      _ValueType __value = _GLIBCXX_MOVE(*(__last - _DistanceType(1)));
>        std::__push_heap(__first, _DistanceType((__last - __first) - 1),
>                      _DistanceType(0), _GLIBCXX_MOVE(__value), __cmp);
>      }
> diff --git a/libstdc++-v3/include/std/functional 
> b/libstdc++-v3/include/std/functional
> index bf40995659d1..9d3410f3a2cd 100644
> --- a/libstdc++-v3/include/std/functional
> +++ b/libstdc++-v3/include/std/functional
> @@ -1345,7 +1345,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>           }
>         if (__j < 0)
>           {
> -           const auto __match = __first + __i + 1;
> +           const auto __match = __first + __i + __diff_type(1);
>             return std::make_pair(__match, __match + __patlen);
>           }
>         __i += std::max(_M_bad_char_shift(__first[__i]),
> diff --git a/libstdc++-v3/testsuite/24_iterators/range_operations/advance.cc 
> b/libstdc++-v3/testsuite/24_iterators/range_operations/advance.cc
> index 2f48181fb675..8229b1ee6c16 100644
> --- a/libstdc++-v3/testsuite/24_iterators/range_operations/advance.cc
> +++ b/libstdc++-v3/testsuite/24_iterators/range_operations/advance.cc
> @@ -42,7 +42,7 @@ test01()
>    std::ranges::advance(iter, -2);
>    VERIFY( iter == r.begin() );
>  
> -  std::ranges::advance(iter, r.begin() + 1);
> +  std::ranges::advance(iter, std::ranges::next(r.begin()));
>    VERIFY( iter != r.begin() );
>    VERIFY( iter != r.end() );
>    std::ranges::advance(iter, r.begin());
> diff --git a/libstdc++-v3/testsuite/25_algorithms/fill_n/diff_type.cc 
> b/libstdc++-v3/testsuite/25_algorithms/fill_n/diff_type.cc
> new file mode 100644
> index 000000000000..7265d396217d
> --- /dev/null
> +++ b/libstdc++-v3/testsuite/25_algorithms/fill_n/diff_type.cc
> @@ -0,0 +1,13 @@
> +// { dg-do compile { target c++11 } }
> +
> +#include <algorithm>
> +#include <testsuite_iterators.h>
> +
> +void
> +test_pr121890()
> +{
> +  // algorithms do not use iterator's difference_type for arithmetic
> +  int a[1];
> +  __gnu_test::random_access_container<int> c(a);
> +  std::fill_n(c.begin(), 1U, 0);
> +}
> diff --git a/libstdc++-v3/testsuite/25_algorithms/for_each/diff_type.cc 
> b/libstdc++-v3/testsuite/25_algorithms/for_each/diff_type.cc
> new file mode 100644
> index 000000000000..d78ba192fa8f
> --- /dev/null
> +++ b/libstdc++-v3/testsuite/25_algorithms/for_each/diff_type.cc
> @@ -0,0 +1,13 @@
> +// { dg-do compile { target c++17 } }
> +
> +#include <algorithm>
> +#include <testsuite_iterators.h>
> +
> +void
> +test_pr121890()
> +{
> +  // algorithms do not use iterator's difference_type for arithmetic
> +  int a[1];
> +  __gnu_test::random_access_container<int> c(a);
> +  std::for_each_n(c.begin(), 1U, [](int){});
> +}
> diff --git a/libstdc++-v3/testsuite/25_algorithms/heap/constrained.cc 
> b/libstdc++-v3/testsuite/25_algorithms/heap/constrained.cc
> index 5486c8552d03..2f818e2b2870 100644
> --- a/libstdc++-v3/testsuite/25_algorithms/heap/constrained.cc
> +++ b/libstdc++-v3/testsuite/25_algorithms/heap/constrained.cc
> @@ -53,17 +53,17 @@ test01()
>  
>        iter = ranges::pop_heap(rx, pred, proj);
>        VERIFY( iter == rx.end() );
> -      VERIFY( *(iter-1) == 50 );
> -      VERIFY( ranges::is_heap_until(rx, pred, proj) == iter-1 );
> +      VERIFY( *ranges::prev(iter) == 50 );
> +      VERIFY( ranges::is_heap_until(rx, pred, proj) == ranges::prev(iter) );
>  
> -      iter = ranges::pop_heap(rx.begin(), iter-1, pred, proj);
> -      VERIFY( iter+1 == rx.end() );
> -      VERIFY( *(iter-1) == 49 );
> -      VERIFY( ranges::is_heap_until(rx, pred, proj) == iter-1 );
> +      iter = ranges::pop_heap(rx.begin(), ranges::prev(iter), pred, proj);
> +      VERIFY( ranges::next(iter) == rx.end() );
> +      VERIFY( *ranges::prev(iter) == 49 );
> +      VERIFY( ranges::is_heap_until(rx, pred, proj) == ranges::prev(iter) );
>  
> -      *(iter-1) = i;
> +      *ranges::prev(iter) = i;
>        iter = ranges::push_heap(rx.begin(), iter, pred, proj);
> -      VERIFY( iter+1 == rx.end() );
> +      VERIFY( ranges::next(iter) == rx.end() );
>        VERIFY( ranges::is_heap_until(rx, pred, proj) == iter );
>  
>        *iter = 2*i;
> @@ -71,9 +71,9 @@ test01()
>        VERIFY( iter == rx.end() );
>        VERIFY( ranges::is_heap_until(rx, pred, proj) == iter );
>  
> -      *(rx.begin()+1) *= -1;
> +      *ranges::next(rx.begin()) *= -1;
>        VERIFY( !ranges::is_heap(rx, pred, proj) );
> -      *(rx.begin()+1) *= -1;
> +      *ranges::next(rx.begin()) *= -1;
>        VERIFY( ranges::is_heap(rx, pred, proj) );
>  
>        iter = ranges::sort_heap(rx, pred, proj);
> diff --git 
> a/libstdc++-v3/testsuite/25_algorithms/lexicographical_compare/diff_type.cc 
> b/libstdc++-v3/testsuite/25_algorithms/lexicographical_compare/diff_type.cc
> new file mode 100644
> index 000000000000..b790197715b6
> --- /dev/null
> +++ 
> b/libstdc++-v3/testsuite/25_algorithms/lexicographical_compare/diff_type.cc
> @@ -0,0 +1,57 @@
> +// { dg-do compile { target c++11 } }
> +
> +#include <algorithm>
> +#include <testsuite_iterators.h>
> +
> +struct Iter
> +{
> +  using value_type = int;
> +  using difference_type = short;
> +  using iterator_category = std::random_access_iterator_tag;
> +  using pointer = const value_type*;
> +  using reference = const value_type&;
> +
> +  Iter() : p(nullptr) { }
> +  explicit Iter(pointer p) : p(p) { }
> +  reference operator*() const { return *p; }
> +  pointer operator->() const { return p; }
> +  reference operator[](difference_type n) const { return p[n]; }
> +  Iter& operator++() { ++p; return *this; }
> +  Iter& operator--() { --p; return *this; }
> +  Iter operator++(int) { return Iter(p++); }
> +  Iter operator--(int) { return Iter(p--); }
> +  Iter& operator+=(difference_type n) { p += n; return *this; }
> +  Iter& operator-=(difference_type n) { p -= n; return *this; }
> +
> +  friend Iter operator+(Iter i, difference_type n) { return i += n; }
> +  friend Iter operator+(difference_type n, Iter i) { return i += n; }
> +  friend Iter operator-(Iter i, difference_type n) { return i -= n; }
> +  friend difference_type operator-(Iter i, Iter j) { return i.p - j.p; }
> +
> +  template<typename D> void operator[](D) const = delete;
> +  template<typename D> void operator+=(D) = delete;
> +  template<typename D> void operator-=(D) = delete;
> +  template<typename D> friend void operator+(Iter, difference_type) = delete;
> +  template<typename D> friend void operator+(difference_type, Iter) = delete;
> +  template<typename D> friend void operator-(Iter, difference_type) = delete;
> +
> +  friend bool operator==(Iter i, Iter j) { return i.p == j.p; }
> +  friend bool operator!=(Iter i, Iter j) { return i.p != j.p; }
> +  friend bool operator<(Iter i, Iter j) { return i.p < j.p; }
> +  friend bool operator<=(Iter i, Iter j) { return i.p <= j.p; }
> +  friend bool operator>(Iter i, Iter j) { return i.p > j.p; }
> +  friend bool operator>=(Iter i, Iter j) { return i.p >= j.p; }
> +
> +private:
> +  pointer p;
> +};
> +
> +void
> +test_pr121890()
> +{
> +  // algorithms do not use iterator's difference_type for arithmetic
> +  int a[1] = { };
> +  __gnu_test::random_access_container<int> c(a);
> +  (void) std::lexicographical_compare(c.begin(), c.end(), Iter(a), 
> Iter(a+1));
> +  (void) std::lexicographical_compare(Iter(a), Iter(a+1), c.begin(), 
> c.end());
> +}
> diff --git a/libstdc++-v3/testsuite/25_algorithms/nth_element/58800.cc 
> b/libstdc++-v3/testsuite/25_algorithms/nth_element/58800.cc
> index 3989ee0bbb50..ff86c63614f5 100644
> --- a/libstdc++-v3/testsuite/25_algorithms/nth_element/58800.cc
> +++ b/libstdc++-v3/testsuite/25_algorithms/nth_element/58800.cc
> @@ -43,7 +43,7 @@ void test01()
>  
>    Container con(v.data(), v.data() + 7);
>  
> -  std::nth_element(con.begin(), con.begin() + 3, con.end());
> +  std::nth_element(con.begin(), std::next(con.begin(), 3), con.end());
>  }
>  
>  int main()
> diff --git a/libstdc++-v3/testsuite/25_algorithms/nth_element/constrained.cc 
> b/libstdc++-v3/testsuite/25_algorithms/nth_element/constrained.cc
> index 8cb1625dd4d5..8d3a057e93dc 100644
> --- a/libstdc++-v3/testsuite/25_algorithms/nth_element/constrained.cc
> +++ b/libstdc++-v3/testsuite/25_algorithms/nth_element/constrained.cc
> @@ -38,7 +38,7 @@ test01()
>  
>    auto pred = std::greater{};
>    auto proj = [] (int a) { return -a; };
> -  for (int i = 0; i < 50; i++)
> +  for (std::ptrdiff_t i = 0; i < 50; i++)
>      {
>        test_range<int, random_access_iterator_wrapper> rx(x);
>        std::ranlux48_base g(i);
> diff --git a/libstdc++-v3/testsuite/25_algorithms/nth_element/diff_type.cc 
> b/libstdc++-v3/testsuite/25_algorithms/nth_element/diff_type.cc
> new file mode 100644
> index 000000000000..4cc9ca92698a
> --- /dev/null
> +++ b/libstdc++-v3/testsuite/25_algorithms/nth_element/diff_type.cc
> @@ -0,0 +1,13 @@
> +// { dg-do compile { target c++11 } }
> +
> +#include <algorithm>
> +#include <testsuite_iterators.h>
> +
> +void
> +test_pr121890()
> +{
> +  // algorithms do not use iterator's difference_type for arithmetic
> +  int a[1] = { };
> +  __gnu_test::random_access_container<int> c(a);
> +  std::nth_element(c.begin(), c.begin(), c.end());
> +}
> diff --git a/libstdc++-v3/testsuite/25_algorithms/nth_element/random_test.cc 
> b/libstdc++-v3/testsuite/25_algorithms/nth_element/random_test.cc
> index 2e9d4b3b6e1e..9eaef61c1690 100644
> --- a/libstdc++-v3/testsuite/25_algorithms/nth_element/random_test.cc
> +++ b/libstdc++-v3/testsuite/25_algorithms/nth_element/random_test.cc
> @@ -37,9 +37,9 @@ struct testNthElement
>    template<typename Container, typename RandomGen>
>    void operator()(Container con, RandomGen& rg)
>    {
> -    const int size = con.end() - con.begin();
> +    const auto size = con.end() - con.begin();
>      auto dist = std::uniform_int_distribution<>(0, size);
> -    const int element = dist(rg);
> +    const decltype(size) element = dist(rg);
>  
>      std::nth_element(con.begin(), con.begin() + element, con.end());
>  
> diff --git 
> a/libstdc++-v3/testsuite/25_algorithms/partial_sort/check_compare_by_value.cc 
> b/libstdc++-v3/testsuite/25_algorithms/partial_sort/check_compare_by_value.cc
> index 05f4f1cbdb55..e1ba840a5a3c 100644
> --- 
> a/libstdc++-v3/testsuite/25_algorithms/partial_sort/check_compare_by_value.cc
> +++ 
> b/libstdc++-v3/testsuite/25_algorithms/partial_sort/check_compare_by_value.cc
> @@ -43,7 +43,7 @@ test01()
>            17, 8, 18, 9, 19 };
>    const int N = sizeof(s1) / sizeof(V);
>    Container con(s1, s1 + N);
> -  std::partial_sort(con.begin(), con.begin() + 10, con.end());
> +  std::partial_sort(con.begin(), std::next(con.begin(), 10), con.end());
>    VERIFY( s1[0].ok );
>    for(int i = 1; i < 10; ++i)
>      VERIFY( s1[i].val > s1[i - 1].val && s1[i].ok );
> @@ -59,7 +59,7 @@ test02()
>            17, 8, 18, 9, 19 };
>    const int N = sizeof(s1) / sizeof(V);
>    Container con(s1, s1 + N);
> -  std::partial_sort(con.begin(), con.begin() + 10, con.end(),
> +  std::partial_sort(con.begin(), std::next(con.begin(), 10), con.end(),
>                   __gnu_test::order);
>    VERIFY( s1[0].ok );
>    for(int i = 1; i < 10; ++i)
> diff --git a/libstdc++-v3/testsuite/25_algorithms/partial_sort/constrained.cc 
> b/libstdc++-v3/testsuite/25_algorithms/partial_sort/constrained.cc
> index 032ffe75d890..554a8d76a4b8 100644
> --- a/libstdc++-v3/testsuite/25_algorithms/partial_sort/constrained.cc
> +++ b/libstdc++-v3/testsuite/25_algorithms/partial_sort/constrained.cc
> @@ -47,7 +47,8 @@ test01()
>        ranges::shuffle(c, g1);
>        ranges::shuffle(ranges::begin(r), ranges::end(r), g2);
>  
> -      for (unsigned middle = 0; middle < std::min(size, 10U); ++middle)
> +      for (std::ptrdiff_t middle = 0, end = std::min(size, 10U);
> +        middle < end; ++middle)
>       {
>         auto res1 = ranges::partial_sort(c.begin(), c.begin()+middle, c.end(),
>                                          {}, std::negate<>{});
> diff --git a/libstdc++-v3/testsuite/25_algorithms/partial_sort/random_test.cc 
> b/libstdc++-v3/testsuite/25_algorithms/partial_sort/random_test.cc
> index 89eb99266608..4e690008e74a 100644
> --- a/libstdc++-v3/testsuite/25_algorithms/partial_sort/random_test.cc
> +++ b/libstdc++-v3/testsuite/25_algorithms/partial_sort/random_test.cc
> @@ -37,9 +37,9 @@ struct testPartialSort
>    template<typename Container, typename RandomGen>
>    void operator()(Container con, RandomGen& rg)
>    {
> -    const int size = con.end() - con.begin();
> +    const auto size = con.end() - con.begin();
>      auto dist = std::uniform_int_distribution<>(0, size);
> -    const int element = dist(rg);
> +    const decltype(size) element = dist(rg);
>  
>      std::partial_sort(con.begin(), con.begin() + element, con.end());
>  
> diff --git 
> a/libstdc++-v3/testsuite/25_algorithms/partial_sort_copy/constrained.cc 
> b/libstdc++-v3/testsuite/25_algorithms/partial_sort_copy/constrained.cc
> index a0bd48be638b..38b2dda45199 100644
> --- a/libstdc++-v3/testsuite/25_algorithms/partial_sort_copy/constrained.cc
> +++ b/libstdc++-v3/testsuite/25_algorithms/partial_sort_copy/constrained.cc
> @@ -35,7 +35,7 @@ namespace ranges = std::ranges;
>  void
>  test01()
>  {
> -  for (unsigned size = 0; size < 50; ++size)
> +  for (std::ptrdiff_t size = 0; size < 50; ++size)
>      {
>        std::vector<int> vref(size);
>        std::iota(vref.begin(), vref.end(), 0);
> @@ -45,7 +45,7 @@ test01()
>        ranges::shuffle(v1, g1);
>        ranges::shuffle(v2, g2);
>  
> -      for (unsigned middle = 0; middle < 10; ++middle)
> +      for (std::ptrdiff_t middle = 0; middle < 10; ++middle)
>       {
>         test_container<int, forward_iterator_wrapper> c
>           = {v1.data(), v1.data() + size};
> diff --git 
> a/libstdc++-v3/testsuite/25_algorithms/partial_sort_copy/random_test.cc 
> b/libstdc++-v3/testsuite/25_algorithms/partial_sort_copy/random_test.cc
> index 2c0b8bca2bef..be033a240140 100644
> --- a/libstdc++-v3/testsuite/25_algorithms/partial_sort_copy/random_test.cc
> +++ b/libstdc++-v3/testsuite/25_algorithms/partial_sort_copy/random_test.cc
> @@ -38,9 +38,9 @@ struct testPartialSortCopy
>    template<typename Container, typename RandomGen>
>    void operator()(Container con, RandomGen& rg)
>    {
> -    const int size = con.end() - con.begin();
> +    const auto size = con.end() - con.begin();
>      auto dist = std::uniform_int_distribution<>(0, size);
> -    const int element = dist(rg);
> +    const decltype(size) element = dist(rg);
>  
>      std::vector<int> outvec(element + 1); // add +1 to avoid empty issues
>  
> diff --git a/libstdc++-v3/testsuite/25_algorithms/push_heap/diff_type.cc 
> b/libstdc++-v3/testsuite/25_algorithms/push_heap/diff_type.cc
> new file mode 100644
> index 000000000000..ab4587e946d0
> --- /dev/null
> +++ b/libstdc++-v3/testsuite/25_algorithms/push_heap/diff_type.cc
> @@ -0,0 +1,13 @@
> +// { dg-do compile { target c++11 } }
> +
> +#include <algorithm>
> +#include <testsuite_iterators.h>
> +
> +void
> +test_pr121890()
> +{
> +  // algorithms do not use iterator's difference_type for arithmetic
> +  int a[1] = { };
> +  __gnu_test::random_access_container<int> c(a);
> +  std::push_heap(c.begin(), c.end());
> +}
> diff --git a/libstdc++-v3/testsuite/25_algorithms/rotate/diff_type.cc 
> b/libstdc++-v3/testsuite/25_algorithms/rotate/diff_type.cc
> new file mode 100644
> index 000000000000..cbf2958df0fb
> --- /dev/null
> +++ b/libstdc++-v3/testsuite/25_algorithms/rotate/diff_type.cc
> @@ -0,0 +1,13 @@
> +// { dg-do compile { target c++11 } }
> +
> +#include <algorithm>
> +#include <testsuite_iterators.h>
> +
> +void
> +test_pr121890()
> +{
> +  // algorithms do not use iterator's difference_type for arithmetic
> +  int a[1] = { };
> +  __gnu_test::random_access_container<int> c(a);
> +  std::rotate(c.begin(), c.begin(), c.end());
> +}
> diff --git a/libstdc++-v3/testsuite/25_algorithms/search_n/diff_type.cc 
> b/libstdc++-v3/testsuite/25_algorithms/search_n/diff_type.cc
> new file mode 100644
> index 000000000000..20253e9ca2a6
> --- /dev/null
> +++ b/libstdc++-v3/testsuite/25_algorithms/search_n/diff_type.cc
> @@ -0,0 +1,13 @@
> +// { dg-do compile { target c++11 } }
> +
> +#include <algorithm>
> +#include <testsuite_iterators.h>
> +
> +void
> +test_pr121890()
> +{
> +  // algorithms do not use iterator's difference_type for arithmetic
> +  int a[1] = { };
> +  __gnu_test::random_access_container<int> c(a);
> +  (void) std::search_n(c.begin(), c.begin(), 1U, 0);
> +}
> diff --git a/libstdc++-v3/testsuite/25_algorithms/sort/diff_type.cc 
> b/libstdc++-v3/testsuite/25_algorithms/sort/diff_type.cc
> new file mode 100644
> index 000000000000..52a83e88ff81
> --- /dev/null
> +++ b/libstdc++-v3/testsuite/25_algorithms/sort/diff_type.cc
> @@ -0,0 +1,13 @@
> +// { dg-do compile { target c++11 } }
> +
> +#include <algorithm>
> +#include <testsuite_iterators.h>
> +
> +void
> +test_pr121890()
> +{
> +  // algorithms do not use iterator's difference_type for arithmetic
> +  int a[1] = { };
> +  __gnu_test::random_access_container<int> c(a);
> +  std::sort(c.begin(), c.begin());
> +}
> diff --git a/libstdc++-v3/testsuite/std/ranges/adaptors/drop.cc 
> b/libstdc++-v3/testsuite/std/ranges/adaptors/drop.cc
> index 4583fb0e7130..57db806069ed 100644
> --- a/libstdc++-v3/testsuite/std/ranges/adaptors/drop.cc
> +++ b/libstdc++-v3/testsuite/std/ranges/adaptors/drop.cc
> @@ -243,7 +243,7 @@ test08()
>  
>    long b[10]{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
>    test_range<long, ra_test_wrapper> rb(b);
> -  ranges::subrange sized = {rb.begin(), rb.begin()+6};
> +  ranges::subrange sized = {rb.begin(), ranges::next(rb.begin(), 6)};
>    using Sized = decltype(sized);
>    static_assert( ranges::random_access_range<Sized> );
>    static_assert( ranges::sized_range<Sized> );
> diff --git a/libstdc++-v3/testsuite/util/testsuite_iterators.h 
> b/libstdc++-v3/testsuite/util/testsuite_iterators.h
> index acd412af0f22..5bf2e704e843 100644
> --- a/libstdc++-v3/testsuite/util/testsuite_iterators.h
> +++ b/libstdc++-v3/testsuite/util/testsuite_iterators.h
> @@ -607,6 +607,16 @@ namespace __gnu_test
>      T& operator[](std::ptrdiff_t n) const
>      { return *(*this + n); }
>  
> +#if __cplusplus >= 201103L
> +    // Ensure that the iterator's difference_type is always used.
> +    template<typename D> void operator+=(D) = delete;
> +    template<typename D> void operator-=(D) = delete;
> +    template<typename D> void operator[](D) const = delete;
> +    template<typename D>
> +      typename std::enable_if<std::is_integral<D>::value>::type
> +      operator-(D) const = delete;
> +#endif
> +
>      _GLIBCXX14_CONSTEXPR
>      bool operator<(const random_access_iterator_wrapper<T>& in) const
>      {
> @@ -645,6 +655,14 @@ namespace __gnu_test
>      operator+(std::ptrdiff_t n, random_access_iterator_wrapper<T> it)
>      { return it += n; }
>  
> +#if __cplusplus >= 201103L
> +    // Ensure that the iterator's difference_type is always used.
> +    template<typename T, typename D>
> +      void operator+(random_access_iterator_wrapper<T>, D) = delete;
> +    template<typename T, typename D>
> +      void operator+(D, random_access_iterator_wrapper<T>) = delete;
> +#endif
> +
>  
>    /**
>     * @brief A container-type class for holding iterator wrappers
> -- 
> 2.51.0
> 
> 

Reply via email to