[libcxx-commits] [libcxx] [libc++][test] Fix assumptions that `std::array` iterators are pointers (PR #74430)

via libcxx-commits libcxx-commits at lists.llvm.org
Tue Dec 5 00:00:27 PST 2023


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-libcxx

Author: Stephan T. Lavavej (StephanTLavavej)

<details>
<summary>Changes</summary>

Found while running libc++'s tests with MSVC's STL, where `std::array` iterators are never pointers.

Most of these changes are reasonably self-explanatory (the `std::array`s are right there, and the sometimes-slightly-wrapped raw pointer types are a short distance away). A couple of changes are less obvious:

---

In `libcxx/test/std/containers/from_range_helpers.h`, `wrap_input()` is called with `Iter` types that are constructible from raw pointers. It's also sometimes called with an `array` as the `input`, so the first overload was implicitly assuming that `array` iterators are pointers. We can fix this assumption by providing a dedicated overload for `array`, just like the one for `vector` immediately below. Finally, `from_range_helpers.h` should explicitly include both `<array>` and `<vector>`, even though they were apparently being dragged in already.

---

In `libcxx/test/std/containers/views/views.span/span.cons/iterator_sentinel.pass.cpp`, fix `throw_operator_minus`. The error was pretty complicated, caused by the concepts machinery noticing that `value_type` and `element_type` were inconsistent. In the template instantiation context, you can see the critical detail that `throw_operator_minus<std::_Array_iterator>` is being formed.

<details><summary>Click to expand error:</summary>

```
D:\GitHub\STL\llvm-project\libcxx\test\std\containers\views\views.span\span.cons\iterator_sentinel.pass.cpp(128,8): error: no matching constructor for initialization of 'std::span<int>'
        (std::span<int>{throw_operator_minus{a.begin()}, throw_operator_minus{a.end()}}));
        ^             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
D:\GitHub\STL\llvm-project\libcxx\test\support\assert_macros.h(129,27): note: expanded from macro 'TEST_VALIDATE_EXCEPTION'
        static_cast<void>(EXPR);                                                                                       \
                            ^~~~
D:\GitHub\STL\out\x64\out\inc\span(328,51): note: candidate constructor template not viable: no known conversion from 'throw_operator_minus<_Array_iterator<int, 1>>' (aka 'throw_operator_minus<std::_Array_iterator<int, 1>>') to 'size_type' (aka 'unsigned long long') for 2nd argument
    constexpr explicit(_Extent != dynamic_extent) span(_It _First, size_type _Count) noexcept // strengthened
                                                    ^
D:\GitHub\STL\out\x64\out\inc\span(339,51): note: candidate template ignored: constraints not satisfied [with _It = throw_operator_minus<_Array_iterator<int, 1>>, _Sentinel = throw_operator_minus<_Array_iterator<int, 1>>]
    constexpr explicit(_Extent != dynamic_extent) span(_It _First, _Sentinel _Last)
                                                    ^
D:\GitHub\STL\out\x64\out\inc\span(338,15): note: because '_Span_compatible_iterator<throw_operator_minus<std::_Array_iterator<int, 1> >, element_type>' evaluated to false
    template <_Span_compatible_iterator<element_type> _It, _Span_compatible_sentinel<_It> _Sentinel>
                ^
D:\GitHub\STL\out\x64\out\inc\span(243,37): note: because 'throw_operator_minus<std::_Array_iterator<int, 1>>' does not satisfy 'contiguous_iterator'
concept _Span_compatible_iterator = contiguous_iterator<_It>
                                    ^
D:\GitHub\STL\out\x64\out\inc\xutility(815,31): note: because 'throw_operator_minus<std::_Array_iterator<int, 1>>' does not satisfy 'random_access_iterator'
concept contiguous_iterator = random_access_iterator<_It>
                                ^
D:\GitHub\STL\out\x64\out\inc\xutility(803,34): note: because 'throw_operator_minus<std::_Array_iterator<int, 1>>' does not satisfy 'bidirectional_iterator'
concept random_access_iterator = bidirectional_iterator<_It>
                                    ^
D:\GitHub\STL\out\x64\out\inc\xutility(796,34): note: because 'throw_operator_minus<std::_Array_iterator<int, 1>>' does not satisfy 'forward_iterator'
concept bidirectional_iterator = forward_iterator<_It> && derived_from<_Iter_concept<_It>, bidirectional_iterator_tag>
                                    ^
D:\GitHub\STL\out\x64\out\inc\xutility(792,28): note: because 'throw_operator_minus<std::_Array_iterator<int, 1>>' does not satisfy 'input_iterator'
concept forward_iterator = input_iterator<_It> && derived_from<_Iter_concept<_It>, forward_iterator_tag>
                            ^
D:\GitHub\STL\out\x64\out\inc\xutility(781,59): note: because 'throw_operator_minus<std::_Array_iterator<int, 1>>' does not satisfy 'indirectly_readable'
concept input_iterator = input_or_output_iterator<_It> && indirectly_readable<_It>
                                                            ^
D:\GitHub\STL\out\x64\out\inc\xutility(694,31): note: because 'remove_cvref_t<throw_operator_minus<_Array_iterator<int, 1>>>' (aka 'throw_operator_minus<std::_Array_iterator<int, 1>>') does not satisfy '_Indirectly_readable_impl'
concept indirectly_readable = _Indirectly_readable_impl<remove_cvref_t<_It>>;
                                ^
D:\GitHub\STL\out\x64\out\inc\__msvc_iter_core.hpp(163,1): note: because 'typename iter_value_t<_It>' would be invalid: no type named 'value_type' in 'std::indirectly_readable_traits<throw_operator_minus<std::_Array_iterator<int, 1>>>'
using iter_value_t = conditional_t<_Is_from_primary<iterator_traits<remove_cvref_t<_Ty>>>,
^
D:\GitHub\STL\out\x64\out\inc\span(353,15): note: candidate constructor template not viable: requires single argument '_Arr', but 2 arguments were provided
    constexpr span(type_identity_t<element_type> (&_Arr)[_Size]) noexcept : _Mybase(_Arr, _Size) {}
                ^
D:\GitHub\STL\out\x64\out\inc\span(358,15): note: candidate constructor template not viable: requires single argument '_Arr', but 2 arguments were provided
    constexpr span(array<_OtherTy, _Size>& _Arr) noexcept : _Mybase(_Arr.data(), _Size) {}
                ^
D:\GitHub\STL\out\x64\out\inc\span(363,15): note: candidate constructor template not viable: requires single argument '_Arr', but 2 arguments were provided
    constexpr span(const array<_OtherTy, _Size>& _Arr) noexcept : _Mybase(_Arr.data(), _Size) {}
                ^
D:\GitHub\STL\out\x64\out\inc\span(366,51): note: candidate constructor template not viable: requires single argument '_Range', but 2 arguments were provided
    constexpr explicit(_Extent != dynamic_extent) span(_Rng&& _Range)
                                                    ^
D:\GitHub\STL\out\x64\out\inc\span(380,5): note: candidate constructor template not viable: requires single argument '_Other', but 2 arguments were provided
    span(const span<_OtherTy, _OtherExtent>& _Other) noexcept
    ^
D:\GitHub\STL\out\x64\out\inc\span(297,7): note: candidate constructor (the implicit copy constructor) not viable: requires 1 argument, but 2 were provided
class span : private _Span_extent_type<_Ty, _Extent> {
        ^
D:\GitHub\STL\out\x64\out\inc\span(297,7): note: candidate constructor (the implicit move constructor) not viable: requires 1 argument, but 2 were provided
D:\GitHub\STL\out\x64\out\inc\span(325,15): note: candidate constructor not viable: requires 0 arguments, but 2 were provided
    constexpr span() noexcept requires (_Extent == 0 || _Extent == dynamic_extent) = default;
                ^
```
</details>

Fortunately, the fix is extremely simple. To produce `element_type` (which retains any cv-qualification, unlike `value_type`), we shouldn't attempt to `remove_pointer` with the iterator type `It`. Instead, we've already obtained the `reference` type, so we can `remove_reference_t`. (This is modern code, where we have access to the alias templates, so I saw no reason to use the older verbose form.)

---

Patch is 31.17 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/74430.diff


13 Files Affected:

- (modified) libcxx/test/std/algorithms/alg.modifying.operations/alg.replace/pstl.replace.pass.cpp (+6-6) 
- (modified) libcxx/test/std/algorithms/alg.modifying.operations/alg.replace/pstl.replace_copy.pass.cpp (+6-6) 
- (modified) libcxx/test/std/algorithms/alg.modifying.operations/alg.replace/pstl.replace_copy_if.pass.cpp (+6-6) 
- (modified) libcxx/test/std/algorithms/alg.modifying.operations/alg.replace/pstl.replace_if.pass.cpp (+6-6) 
- (modified) libcxx/test/std/algorithms/alg.sorting/alg.merge/pstl.merge.pass.cpp (+3-3) 
- (modified) libcxx/test/std/algorithms/alg.sorting/alg.three.way/lexicographical_compare_three_way.pass.cpp (+1-1) 
- (modified) libcxx/test/std/algorithms/alg.sorting/alg.three.way/lexicographical_compare_three_way_comp.pass.cpp (+1-1) 
- (modified) libcxx/test/std/containers/from_range_helpers.h (+9) 
- (modified) libcxx/test/std/containers/views/views.span/span.cons/iterator_sentinel.pass.cpp (+1-1) 
- (modified) libcxx/test/std/ranges/range.adaptors/range.chunk.by/range.chunk.by.iter/compare.pass.cpp (+6-6) 
- (modified) libcxx/test/std/ranges/range.adaptors/range.chunk.by/range.chunk.by.iter/decrement.pass.cpp (+30-30) 
- (modified) libcxx/test/std/ranges/range.adaptors/range.chunk.by/range.chunk.by.iter/deref.pass.cpp (+1-1) 
- (modified) libcxx/test/std/ranges/range.adaptors/range.chunk.by/range.chunk.by.iter/increment.pass.cpp (+25-25) 


``````````diff
diff --git a/libcxx/test/std/algorithms/alg.modifying.operations/alg.replace/pstl.replace.pass.cpp b/libcxx/test/std/algorithms/alg.modifying.operations/alg.replace/pstl.replace.pass.cpp
index 751d6b74b0128..833d5b0f6b2bf 100644
--- a/libcxx/test/std/algorithms/alg.modifying.operations/alg.replace/pstl.replace.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.modifying.operations/alg.replace/pstl.replace.pass.cpp
@@ -29,35 +29,35 @@ struct Test {
   void operator()(ExecutionPolicy&& policy) {
     { // simple test
       std::array a = {1, 2, 3, 4, 5, 6, 7, 8};
-      std::replace(policy, Iter(std::begin(a)), Iter(std::end(a)), 3, 6);
+      std::replace(policy, Iter(std::data(a)), Iter(std::data(a) + std::size(a)), 3, 6);
       assert((a == std::array{1, 2, 6, 4, 5, 6, 7, 8}));
     }
 
     { // empty range works
       std::array<int, 0> a = {};
-      std::replace(policy, Iter(std::begin(a)), Iter(std::end(a)), 3, 6);
+      std::replace(policy, Iter(std::data(a)), Iter(std::data(a) + std::size(a)), 3, 6);
     }
 
     { // non-empty range without a match works
       std::array a = {1, 2};
-      std::replace(policy, Iter(std::begin(a)), Iter(std::end(a)), 3, 6);
+      std::replace(policy, Iter(std::data(a)), Iter(std::data(a) + std::size(a)), 3, 6);
     }
 
     { // single element range works
       std::array a = {3};
-      std::replace(policy, Iter(std::begin(a)), Iter(std::end(a)), 3, 6);
+      std::replace(policy, Iter(std::data(a)), Iter(std::data(a) + std::size(a)), 3, 6);
       assert((a == std::array{6}));
     }
 
     { // two element range works
       std::array a = {3, 4};
-      std::replace(policy, Iter(std::begin(a)), Iter(std::end(a)), 3, 6);
+      std::replace(policy, Iter(std::data(a)), Iter(std::data(a) + std::size(a)), 3, 6);
       assert((a == std::array{6, 4}));
     }
 
     { // multiple matching elements work
       std::array a = {1, 2, 3, 4, 3, 3, 5, 6, 3};
-      std::replace(policy, Iter(std::begin(a)), Iter(std::end(a)), 3, 9);
+      std::replace(policy, Iter(std::data(a)), Iter(std::data(a) + std::size(a)), 3, 9);
       assert((a == std::array{1, 2, 9, 4, 9, 9, 5, 6, 9}));
     }
 
diff --git a/libcxx/test/std/algorithms/alg.modifying.operations/alg.replace/pstl.replace_copy.pass.cpp b/libcxx/test/std/algorithms/alg.modifying.operations/alg.replace/pstl.replace_copy.pass.cpp
index f24bedabebccd..18d4446f5d2a9 100644
--- a/libcxx/test/std/algorithms/alg.modifying.operations/alg.replace/pstl.replace_copy.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.modifying.operations/alg.replace/pstl.replace_copy.pass.cpp
@@ -32,40 +32,40 @@ struct Test {
     { // simple test
       std::array a = {1, 2, 3, 4, 5, 6, 7, 8};
       std::array<int, a.size()> out;
-      std::replace_copy(policy, Iter(std::begin(a)), Iter(std::end(a)), Iter(std::begin(out)), 3, 6);
+      std::replace_copy(policy, Iter(std::data(a)), Iter(std::data(a) + std::size(a)), Iter(std::data(out)), 3, 6);
       assert((out == std::array{1, 2, 6, 4, 5, 6, 7, 8}));
     }
 
     { // empty range works
       std::array<int, 0> a = {};
-      std::replace_copy(policy, Iter(std::begin(a)), Iter(std::end(a)), Iter(std::begin(a)), 3, 6);
+      std::replace_copy(policy, Iter(std::data(a)), Iter(std::data(a) + std::size(a)), Iter(std::data(a)), 3, 6);
     }
 
     { // non-empty range without a match works
       std::array a = {1, 2};
       std::array<int, a.size()> out;
-      std::replace_copy(policy, Iter(std::begin(a)), Iter(std::end(a)), Iter(out.data()), 3, 6);
+      std::replace_copy(policy, Iter(std::data(a)), Iter(std::data(a) + std::size(a)), Iter(out.data()), 3, 6);
       assert((out == std::array{1, 2}));
     }
 
     { // single element range works
       std::array a = {3};
       std::array<int, a.size()> out;
-      std::replace_copy(policy, Iter(std::begin(a)), Iter(std::end(a)), Iter(std::begin(out)), 3, 6);
+      std::replace_copy(policy, Iter(std::data(a)), Iter(std::data(a) + std::size(a)), Iter(std::data(out)), 3, 6);
       assert((out == std::array{6}));
     }
 
     { // two element range works
       std::array a = {3, 4};
       std::array<int, a.size()> out;
-      std::replace_copy(policy, Iter(std::begin(a)), Iter(std::end(a)), Iter(std::begin(out)), 3, 6);
+      std::replace_copy(policy, Iter(std::data(a)), Iter(std::data(a) + std::size(a)), Iter(std::data(out)), 3, 6);
       assert((out == std::array{6, 4}));
     }
 
     { // multiple matching elements work
       std::array a = {1, 2, 3, 4, 3, 3, 5, 6, 3};
       std::array<int, a.size()> out;
-      std::replace_copy(policy, Iter(std::begin(a)), Iter(std::end(a)), Iter(std::begin(out)), 3, 9);
+      std::replace_copy(policy, Iter(std::data(a)), Iter(std::data(a) + std::size(a)), Iter(std::data(out)), 3, 9);
       assert((out == std::array{1, 2, 9, 4, 9, 9, 5, 6, 9}));
     }
 
diff --git a/libcxx/test/std/algorithms/alg.modifying.operations/alg.replace/pstl.replace_copy_if.pass.cpp b/libcxx/test/std/algorithms/alg.modifying.operations/alg.replace/pstl.replace_copy_if.pass.cpp
index f7c746f382d11..89ea1652eb896 100644
--- a/libcxx/test/std/algorithms/alg.modifying.operations/alg.replace/pstl.replace_copy_if.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.modifying.operations/alg.replace/pstl.replace_copy_if.pass.cpp
@@ -34,21 +34,21 @@ struct Test {
       std::array a = {1, 2, 3, 4, 5, 6, 7, 8};
       std::array<int, a.size()> out;
       std::replace_copy_if(
-          policy, Iter(std::begin(a)), Iter(std::end(a)), Iter(std::begin(out)), [](int i) { return i == 3; }, 6);
+          policy, Iter(std::data(a)), Iter(std::data(a) + std::size(a)), Iter(std::data(out)), [](int i) { return i == 3; }, 6);
       assert((out == std::array{1, 2, 6, 4, 5, 6, 7, 8}));
     }
 
     { // empty range works
       std::array<int, 0> a = {};
       std::replace_copy_if(
-          policy, Iter(std::begin(a)), Iter(std::end(a)), Iter(std::begin(a)), [](int i) { return i == 3; }, 6);
+          policy, Iter(std::data(a)), Iter(std::data(a) + std::size(a)), Iter(std::data(a)), [](int i) { return i == 3; }, 6);
     }
 
     { // non-empty range without a match works
       std::array a = {1, 2};
       std::array<int, a.size()> out;
       std::replace_copy_if(
-          policy, Iter(std::begin(a)), Iter(std::end(a)), Iter(out.data()), [](int i) { return i == 3; }, 6);
+          policy, Iter(std::data(a)), Iter(std::data(a) + std::size(a)), Iter(out.data()), [](int i) { return i == 3; }, 6);
       assert((out == std::array{1, 2}));
     }
 
@@ -56,7 +56,7 @@ struct Test {
       std::array a = {3};
       std::array<int, a.size()> out;
       std::replace_copy_if(
-          policy, Iter(std::begin(a)), Iter(std::end(a)), Iter(std::begin(out)), [](int i) { return i == 3; }, 6);
+          policy, Iter(std::data(a)), Iter(std::data(a) + std::size(a)), Iter(std::data(out)), [](int i) { return i == 3; }, 6);
       assert((out == std::array{6}));
     }
 
@@ -64,7 +64,7 @@ struct Test {
       std::array a = {3, 4};
       std::array<int, a.size()> out;
       std::replace_copy_if(
-          policy, Iter(std::begin(a)), Iter(std::end(a)), Iter(std::begin(out)), [](int i) { return i == 3; }, 6);
+          policy, Iter(std::data(a)), Iter(std::data(a) + std::size(a)), Iter(std::data(out)), [](int i) { return i == 3; }, 6);
       assert((out == std::array{6, 4}));
     }
 
@@ -72,7 +72,7 @@ struct Test {
       std::array a = {1, 2, 3, 4, 3, 3, 5, 6, 3};
       std::array<int, a.size()> out;
       std::replace_copy_if(
-          policy, Iter(std::begin(a)), Iter(std::end(a)), Iter(std::begin(out)), [](int i) { return i == 3; }, 9);
+          policy, Iter(std::data(a)), Iter(std::data(a) + std::size(a)), Iter(std::data(out)), [](int i) { return i == 3; }, 9);
       assert((out == std::array{1, 2, 9, 4, 9, 9, 5, 6, 9}));
     }
 
diff --git a/libcxx/test/std/algorithms/alg.modifying.operations/alg.replace/pstl.replace_if.pass.cpp b/libcxx/test/std/algorithms/alg.modifying.operations/alg.replace/pstl.replace_if.pass.cpp
index 3ffc1c021bb9c..99ea5e230835f 100644
--- a/libcxx/test/std/algorithms/alg.modifying.operations/alg.replace/pstl.replace_if.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.modifying.operations/alg.replace/pstl.replace_if.pass.cpp
@@ -30,38 +30,38 @@ struct Test {
     { // simple test
       std::array a = {1, 2, 3, 4, 5, 6, 7, 8};
       std::replace_if(
-          policy, Iter(std::begin(a)), Iter(std::end(a)), [](int i) { return i == 3 || i == 7; }, 6);
+          policy, Iter(std::data(a)), Iter(std::data(a) + std::size(a)), [](int i) { return i == 3 || i == 7; }, 6);
       assert((a == std::array{1, 2, 6, 4, 5, 6, 6, 8}));
     }
 
     { // empty range works
       std::array<int, 0> a = {};
       std::replace_if(
-          policy, Iter(std::begin(a)), Iter(std::end(a)), [](int) { return false; }, 6);
+          policy, Iter(std::data(a)), Iter(std::data(a) + std::size(a)), [](int) { return false; }, 6);
     }
 
     { // non-empty range without a match works
       std::array a = {1, 2};
-      std::replace_if(policy, Iter(std::begin(a)), Iter(std::end(a)), [](int) { return false; }, 6);
+      std::replace_if(policy, Iter(std::data(a)), Iter(std::data(a) + std::size(a)), [](int) { return false; }, 6);
     }
 
     { // single element range works
       std::array a = {3};
       std::replace_if(
-          policy, Iter(std::begin(a)), Iter(std::end(a)), [](int i) { return i == 3; }, 6);
+          policy, Iter(std::data(a)), Iter(std::data(a) + std::size(a)), [](int i) { return i == 3; }, 6);
       assert((a == std::array{6}));
     }
 
     { // two element range works
       std::array a = {3, 4};
       std::replace_if(
-          policy, Iter(std::begin(a)), Iter(std::end(a)), [](int i) { return i == 3; }, 6);
+          policy, Iter(std::data(a)), Iter(std::data(a) + std::size(a)), [](int i) { return i == 3; }, 6);
       assert((a == std::array{6, 4}));
     }
 
     { // multiple matching elements work
       std::array a = {1, 2, 3, 4, 3, 3, 5, 6, 3};
-      std::replace_if(policy, Iter(std::begin(a)), Iter(std::end(a)), [](int i) { return i == 3; }, 9);
+      std::replace_if(policy, Iter(std::data(a)), Iter(std::data(a) + std::size(a)), [](int i) { return i == 3; }, 9);
       assert((a == std::array{1, 2, 9, 4, 9, 9, 5, 6, 9}));
     }
 
diff --git a/libcxx/test/std/algorithms/alg.sorting/alg.merge/pstl.merge.pass.cpp b/libcxx/test/std/algorithms/alg.sorting/alg.merge/pstl.merge.pass.cpp
index 1feadfb377a68..c685bff8f4e9b 100644
--- a/libcxx/test/std/algorithms/alg.sorting/alg.merge/pstl.merge.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.sorting/alg.merge/pstl.merge.pass.cpp
@@ -54,14 +54,14 @@ struct Test {
       std::array<int, 0> b;
       std::array<int, std::size(a) + std::size(b)> out;
       std::merge(
-          policy, Iter1(std::begin(a)), Iter1(std::end(a)), Iter2(std::begin(b)), Iter2(std::end(b)), std::begin(out));
+          policy, Iter1(std::data(a)), Iter1(std::data(a) + std::size(a)), Iter2(std::data(b)), Iter2(std::data(b) + std::size(b)), std::begin(out));
     }
     { // check that it works with the first range being empty
       std::array<int, 0> a;
       int b[] = {2, 4, 6, 8, 10};
       std::array<int, std::size(a) + std::size(b)> out;
       std::merge(
-          policy, Iter1(std::begin(a)), Iter1(std::end(a)), Iter2(std::begin(b)), Iter2(std::end(b)), std::begin(out));
+          policy, Iter1(std::data(a)), Iter1(std::data(a) + std::size(a)), Iter2(std::begin(b)), Iter2(std::end(b)), std::begin(out));
       assert((out == std::array{2, 4, 6, 8, 10}));
     }
 
@@ -70,7 +70,7 @@ struct Test {
       std::array<int, 0> b;
       std::array<int, std::size(a) + std::size(b)> out;
       std::merge(
-          policy, Iter1(std::begin(a)), Iter1(std::end(a)), Iter2(std::begin(b)), Iter2(std::end(b)), std::begin(out));
+          policy, Iter1(std::begin(a)), Iter1(std::end(a)), Iter2(std::data(b)), Iter2(std::data(b) + std::size(b)), std::begin(out));
       assert((out == std::array{2, 4, 6, 8, 10}));
     }
 
diff --git a/libcxx/test/std/algorithms/alg.sorting/alg.three.way/lexicographical_compare_three_way.pass.cpp b/libcxx/test/std/algorithms/alg.sorting/alg.three.way/lexicographical_compare_three_way.pass.cpp
index 0bd1d74529530..17db46edfb218 100644
--- a/libcxx/test/std/algorithms/alg.sorting/alg.three.way/lexicographical_compare_three_way.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.sorting/alg.three.way/lexicographical_compare_three_way.pass.cpp
@@ -28,7 +28,7 @@
 template <typename Iter1, typename Iter2, typename C1, typename C2, typename Order>
 constexpr void test_lexicographical_compare(C1 a, C2 b, Order expected) {
   std::same_as<Order> decltype(auto) result =
-      std::lexicographical_compare_three_way(Iter1{a.begin()}, Iter1{a.end()}, Iter2{b.begin()}, Iter2{b.end()});
+      std::lexicographical_compare_three_way(Iter1{a.data()}, Iter1{a.data() + a.size()}, Iter2{b.data()}, Iter2{b.data() + b.size()});
   assert(expected == result);
 }
 
diff --git a/libcxx/test/std/algorithms/alg.sorting/alg.three.way/lexicographical_compare_three_way_comp.pass.cpp b/libcxx/test/std/algorithms/alg.sorting/alg.three.way/lexicographical_compare_three_way_comp.pass.cpp
index d3c2814d642a7..1f8b18737ada8 100644
--- a/libcxx/test/std/algorithms/alg.sorting/alg.three.way/lexicographical_compare_three_way_comp.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.sorting/alg.three.way/lexicographical_compare_three_way_comp.pass.cpp
@@ -57,7 +57,7 @@ static_assert(has_lexicographical_compare<decltype(compare_int_result)>);
 template <typename Iter1, typename Iter2, typename C1, typename C2, typename Order, typename Comparator>
 constexpr void test_lexicographical_compare(C1 a, C2 b, Comparator comp, Order expected) {
   std::same_as<Order> decltype(auto) result =
-      std::lexicographical_compare_three_way(Iter1{a.begin()}, Iter1{a.end()}, Iter2{b.begin()}, Iter2{b.end()}, comp);
+      std::lexicographical_compare_three_way(Iter1{a.data()}, Iter1{a.data() + a.size()}, Iter2{b.data()}, Iter2{b.data() + b.size()}, comp);
   assert(expected == result);
 }
 
diff --git a/libcxx/test/std/containers/from_range_helpers.h b/libcxx/test/std/containers/from_range_helpers.h
index 7fff99da1e15e..e17ea247618bc 100644
--- a/libcxx/test/std/containers/from_range_helpers.h
+++ b/libcxx/test/std/containers/from_range_helpers.h
@@ -9,9 +9,11 @@
 #ifndef SUPPORT_FROM_RANGE_HELPERS_H
 #define SUPPORT_FROM_RANGE_HELPERS_H
 
+#include <array>
 #include <cstddef>
 #include <iterator>
 #include <type_traits>
+#include <vector>
 
 #include "min_allocator.h"
 #include "test_allocator.h"
@@ -34,6 +36,13 @@ constexpr auto wrap_input(Range&& input) {
   return std::ranges::subrange(std::move(b), std::move(e));
 }
 
+template <class Iter, class Sent, class T, std::size_t N>
+constexpr auto wrap_input(std::array<T, N>& input) {
+  auto b = Iter(input.data());
+  auto e = Sent(Iter(input.data() + input.size()));
+  return std::ranges::subrange(std::move(b), std::move(e));
+}
+
 template <class Iter, class Sent, class T>
 constexpr auto wrap_input(std::vector<T>& input) {
   auto b = Iter(input.data());
diff --git a/libcxx/test/std/containers/views/views.span/span.cons/iterator_sentinel.pass.cpp b/libcxx/test/std/containers/views/views.span/span.cons/iterator_sentinel.pass.cpp
index 4e1db3df5b83b..73b13ccc34cf8 100644
--- a/libcxx/test/std/containers/views/views.span/span.cons/iterator_sentinel.pass.cpp
+++ b/libcxx/test/std/containers/views/views.span/span.cons/iterator_sentinel.pass.cpp
@@ -71,7 +71,7 @@ class throw_operator_minus {
   typedef typename std::iterator_traits<It>::difference_type difference_type;
   typedef It pointer;
   typedef typename std::iterator_traits<It>::reference reference;
-  typedef typename std::remove_pointer<It>::type element_type;
+  typedef std::remove_reference_t<reference> element_type;
 
   throw_operator_minus() : it_() {}
   explicit throw_operator_minus(It it) : it_(it) {}
diff --git a/libcxx/test/std/ranges/range.adaptors/range.chunk.by/range.chunk.by.iter/compare.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.chunk.by/range.chunk.by.iter/compare.pass.cpp
index 38b6346e0061f..a3a51c79ccd12 100644
--- a/libcxx/test/std/ranges/range.adaptors/range.chunk.by/range.chunk.by.iter/compare.pass.cpp
+++ b/libcxx/test/std/ranges/range.adaptors/range.chunk.by/range.chunk.by.iter/compare.pass.cpp
@@ -31,15 +31,15 @@ constexpr void test() {
   using ChunkByView     = std::ranges::chunk_by_view<Underlying, std::ranges::less_equal>;
   using ChunkByIterator = std::ranges::iterator_t<ChunkByView>;
 
-  auto make_chunk_by_view = [](auto begin, auto end) {
-    View view{Iterator(begin), Sentinel(Iterator(end))};
+  auto make_chunk_by_view = [](auto& arr) {
+    View view{Iterator(arr.data()), Sentinel(Iterator(arr.data() + arr.size()))};
     return ChunkByView(std::move(view), std::ranges::less_equal{});
   };
 
   // Test operator==
   {
     std::array array{0, 1, 2};
-    ChunkByView view  = make_chunk_by_view(array.begin(), array.end());
+    ChunkByView view  = make_chunk_by_view(array);
     ChunkByIterator i = view.begin();
     ChunkByIterator j = view.begin();
 
@@ -52,7 +52,7 @@ constexpr void test() {
   // Test synthesized operator!=
   {
     std::array array{0, 1, 2};
-    ChunkByView view  = make_chunk_by_view(array.begin(), array.end());
+    ChunkByView view  = make_chunk_by_view(array);
     ChunkByIterator i = view.begin();
     ChunkByIterator j = view.begin();
 
@@ -65,7 +65,7 @@ constexpr void test() {
   // Test operator== with std::default_sentinel_t
   {
     std::array array{0, 1, 2};
-    ChunkByView view  = make_chunk_by_view(array.begin(), array.end());
+    ChunkByView view  = make_chunk_by_view(array);
     ChunkByIterator i = view.begin();
 
     std::same_as<bool> decltype(auto) result = (i == std::default_sentinel);
@@ -77,7 +77,7 @@ constexpr void test() {
   // Test synthesized operator!= with std::default_sentinel_t
   {
     std::array array{0, 1, 2};
-    ChunkByView view  = make_chunk_by_view(array.begin(), array.end());
+    ChunkByView view  = make_chunk_by_view(array);
     ChunkByIterator i = view.begin();
 
     std::same_as<bool> decltype(auto) result = (i != std::default_sentinel);
diff --git a/libcxx/test/std/ranges/range.adaptors/range.chunk.by/range.chunk.by.iter/decrement.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.chunk.by/range.chunk.by.iter/decrement.pass.cpp
index 167f3f753bfae..a331c794c8815 100644
--- a/libcxx/test/std/ranges/range.adaptors/range.chunk.by/range.chunk.by.iter/decrement.pass.cpp
+++ b/libcxx/test/std/ranges/range.adaptors/range.chunk.by/range.chunk.by.iter/decrement.pass.cpp
@@ -51,107 +51,107 @@ constexpr void test() {
   static_assert(HasPostDecrement<ChunkByIterator>);
   static_assert(HasPreDecrement<ChunkByIterator>);
 
-  auto make_chunk_by_view = [](auto begin, auto end) {
-    View view{Iterator{begin}, Sentinel{Iterator{end}}};
+  auto make_chunk_by_view = [](auto& arr) {
+    View view{Iterator{arr.data()}, Sentinel{Iterator{arr.data() + arr.size()}}};
     return ChunkByView{std::move(view), std::ranges::less_equal{}};
   };
 
   // Test with a single chunk
   {
     std::array array{0, 1, 2, 3, 4};
-    ChunkByView view   = make_chunk_by_view(array.begin(), array.end());
+    ChunkByView view   = make_chunk_by_view(array);
     ChunkByIterator it = std::ranges::next(view.begin(), view.end());
 
     std::same_as<ChunkByIterator&> decltype(auto) result = --it;
     assert(&result == &it);
-    assert(base((*result).begin()) == array.begin());
+    assert(base((*result).begin()) == array.data());
   }
 
   // Test with two chunks
   {
     std::array array{0, 1, 2, 0, 1, 2};
-    ChunkByView view   = make_chunk_by_view(array.begin(), array.end());
+    ChunkByView view   = make_chunk_by_view(array);
     ChunkByIterator it = std::ranges::next(view.begin(), view.end());
 
     std::same_as<ChunkByIterator&> decltype(auto) result = --it;
     assert(&result == &it);
-    assert(base((*result).begin()) == array.begin() + 3);
+    assert(base((*result).begin()) == array.data() + 3);
 
     --it;
-    assert(base((*result).begin()) == array.begin());
+    assert(base((*result).begin()) == array.data());
   }
 
   // Test going forward and then backward on the same iterator
   {
     std::array array{7, 8, 9, 4, 5, 6, 1, 2, 3, 0};
-    ChunkByView view   ...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/74430


More information about the libcxx-commits mailing list