On Thu, 11 Sept 2025 at 22:41, Jonathan Wakely <jwak...@redhat.com> 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. Use local variables in
>         rotate to avoid duplicate expressions.
>         (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.
> ---
>
> v3: Change in boyer_moore_searcher suggested by Tomasz. Reverted
> unnecessary ranges::next in ranges::rotate noticed by Patrick, and
> changed it to use local variables as done for std::rotate in v2.

I found one more change that's needed for debug mode:

--- a/libstdc++-v3/include/bits/stl_heap.h
+++ b/libstdc++-v3/include/bits/stl_heap.h
@@ -180,7 +180,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
      __glibcxx_function_requires(_LessThanComparableConcept<_ValueType>)
      __glibcxx_requires_valid_range(__first, __last);
      __glibcxx_requires_irreflexive(__first, __last);
-      __glibcxx_requires_heap(__first, __last - 1);
+      __glibcxx_requires_heap(__first, __last - _DistanceType(1));

      __gnu_cxx::__ops::_Iter_less_val __comp;
      _ValueType __value = _GLIBCXX_MOVE(*(__last - _DistanceType(1)));


I'm also removing all but these two of the new tests:

       * testsuite/25_algorithms/fill_n/diff_type.cc: New test.
       * testsuite/25_algorithms/lexicographical_compare/diff_type.cc

That's because for the other algos the existing tests already use
__gnu_test::random_access_iterator_wrapper and so already fail with
the new deleted operators in that wrapper. So we don't need new tests
to check things that we're already checking.

For fill_n and lexicographical_compare, the existing tests didn't
trigger the deleted operators.

Reply via email to