[libcxx-commits] [libcxx] [libc++][ranges] Resolve LWG4242 (PR #211568)
Lucas Mellone via libcxx-commits
libcxx-commits at lists.llvm.org
Thu Jul 23 07:43:23 PDT 2026
https://github.com/lknknm updated https://github.com/llvm/llvm-project/pull/211568
>From 8e3559129e89e81f7b8bf0d195222363898ef654 Mon Sep 17 00:00:00 2001
From: Lucas Mellone <github.snugness349 at passinbox.com>
Date: Thu, 23 Jul 2026 15:38:21 +0200
Subject: [PATCH 1/2] resolve: LWG4242
---
libcxx/docs/Status/Cxx26Issues.csv | 2 +-
libcxx/include/__iterator/distance.h | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/libcxx/docs/Status/Cxx26Issues.csv b/libcxx/docs/Status/Cxx26Issues.csv
index 5b046b69d14bd..83ad46827ca18 100644
--- a/libcxx/docs/Status/Cxx26Issues.csv
+++ b/libcxx/docs/Status/Cxx26Issues.csv
@@ -142,7 +142,7 @@
"`LWG4235 <https://wg21.link/LWG4235>`__","``cache_latest_view`` and ``to_input_view`` miss ``reserve_hint``","2025-06 (Sofia)","","","`#148219 <https://github.com/llvm/llvm-project/issues/148219>`__",""
"`LWG4236 <https://wg21.link/LWG4236>`__","``chunk_view::outer-iterator::value_type`` should provide ``reserve_hint``","2025-06 (Sofia)","","","`#148220 <https://github.com/llvm/llvm-project/issues/148220>`__",""
"`LWG4239 <https://wg21.link/LWG4239>`__","``flat_map``'s transparent comparator no longer works for string literals","2025-06 (Sofia)","","","`#148223 <https://github.com/llvm/llvm-project/issues/148223>`__",""
-"`LWG4242 <https://wg21.link/LWG4242>`__","``ranges::distance`` does not work with volatile iterators","2025-06 (Sofia)","","","`#148224 <https://github.com/llvm/llvm-project/issues/148224>`__",""
+"`LWG4242 <https://wg21.link/LWG4242>`__","``ranges::distance`` does not work with volatile iterators","2025-06 (Sofia)","|Complete|","24","`#148224 <https://github.com/llvm/llvm-project/issues/148224>`__",""
"`LWG4245 <https://wg21.link/LWG4245>`__","Operators that interact with ``counted_iterator`` and ``default_sentinel_t`` should be ``noexcept``","2025-06 (Sofia)","","","`#148226 <https://github.com/llvm/llvm-project/issues/148226>`__",""
"`LWG4247 <https://wg21.link/LWG4247>`__","Header ``<stdbit.h>`` is not yet freestanding","2025-06 (Sofia)","","","`#148227 <https://github.com/llvm/llvm-project/issues/148227>`__",""
"","","","","","",""
diff --git a/libcxx/include/__iterator/distance.h b/libcxx/include/__iterator/distance.h
index c7c4ff22d6e9f..029117e2ff5cc 100644
--- a/libcxx/include/__iterator/distance.h
+++ b/libcxx/include/__iterator/distance.h
@@ -87,7 +87,7 @@ struct __distance {
template <class _Ip, sized_sentinel_for<decay_t<_Ip>> _Sp>
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr iter_difference_t<_Ip> operator()(_Ip&& __first, _Sp __last) const {
- if constexpr (sized_sentinel_for<_Sp, __remove_cvref_t<_Ip>>) {
+ if constexpr (!is_array_v<remove_reference_t<_Ip>>) {
return __last - __first;
} else {
return __last - decay_t<_Ip>(__first);
>From 654370a5f26aed08caebe4fbc98f09417e272517 Mon Sep 17 00:00:00 2001
From: Lucas Mellone <github.snugness349 at passinbox.com>
Date: Thu, 23 Jul 2026 15:56:59 +0200
Subject: [PATCH 2/2] add: lwg4242 test case and refactor lwg3664 test case
---
.../iterator_sentinel.pass.cpp | 63 ++++++++++++-------
1 file changed, 40 insertions(+), 23 deletions(-)
diff --git a/libcxx/test/std/iterators/iterator.primitives/range.iter.ops/range.iter.ops.distance/iterator_sentinel.pass.cpp b/libcxx/test/std/iterators/iterator.primitives/range.iter.ops/range.iter.ops.distance/iterator_sentinel.pass.cpp
index 30507c59495ea..37ee37a0e5876 100644
--- a/libcxx/test/std/iterators/iterator.primitives/range.iter.ops/range.iter.ops.distance/iterator_sentinel.pass.cpp
+++ b/libcxx/test/std/iterators/iterator.primitives/range.iter.ops/range.iter.ops.distance/iterator_sentinel.pass.cpp
@@ -199,6 +199,41 @@ static_assert(!std::sized_sentinel_for<EvilSentinel<int*>, const int*>);
static_assert(std::sized_sentinel_for<EvilSentinel<const int*>, int*>);
static_assert(std::sized_sentinel_for<EvilSentinel<const int*>, const int*>);
+// LWG3664: "LWG3392 broke std::ranges::distance(a, a+3)" tests.
+constexpr void test_lwg3664() {
+ {
+ int a[] = {1, 2, 3};
+ assert(std::ranges::distance(a, a + 3) == 3);
+ assert(std::ranges::distance(a, a) == 0);
+ assert(std::ranges::distance(a + 3, a) == -3);
+ }
+ {
+ int a[] = {1, 2, 3};
+ assert(std::ranges::distance(a, EvilSentinel<int*>{a + 3}) == 3);
+ assert(std::ranges::distance(a, EvilSentinel<int*>{a}) == 0);
+ assert(std::ranges::distance(a + 3, EvilSentinel<int*>{a}) == -3);
+ assert(std::ranges::distance(std::move(a), EvilSentinel<int*>{a + 3}) == 3);
+ }
+ {
+ const int a[] = {1, 2, 3};
+ assert(std::ranges::distance(a, EvilSentinel<const int*>{a + 3}) == 3);
+ assert(std::ranges::distance(a, EvilSentinel<const int*>{a}) == 0);
+ assert(std::ranges::distance(a + 3, EvilSentinel<const int*>{a}) == -3);
+ assert(std::ranges::distance(std::move(a), EvilSentinel<const int*>{a + 3}) == 3);
+ static_assert(!std::is_invocable_v<decltype(std::ranges::distance), const int (&)[3], EvilSentinel<int*>>);
+ static_assert(!std::is_invocable_v<decltype(std::ranges::distance), const int (&&)[3], EvilSentinel<int*>>);
+ }
+}
+
+// LWG4242: "ranges::distance does not work with volatile iterators" tests.
+void test_lwg4242() {
+ int arr[] = {1, 2, 3};
+ int* volatile ptr = arr;
+ auto dist = std::distance(ptr, arr + 3);
+ auto r_dist = std::ranges::distance(ptr, arr + 3);
+ assert(dist == r_dist);
+}
+
constexpr bool test() {
{
int a[] = {1, 2, 3};
@@ -284,30 +319,12 @@ constexpr bool test() {
auto view = c | std::views::join;
assert(std::ranges::distance(view.begin(), view.end()) == 30);
}
- if (!TEST_IS_CONSTANT_EVALUATED) // TODO: Use TEST_STD_AT_LEAST_26_OR_RUNTIME_EVALUATED when std::deque is made constexpr
- test_deque();
- {
- int a[] = {1, 2, 3};
- assert(std::ranges::distance(a, a + 3) == 3);
- assert(std::ranges::distance(a, a) == 0);
- assert(std::ranges::distance(a + 3, a) == -3);
- }
- {
- int a[] = {1, 2, 3};
- assert(std::ranges::distance(a, EvilSentinel<int*>{a + 3}) == 3);
- assert(std::ranges::distance(a, EvilSentinel<int*>{a}) == 0);
- assert(std::ranges::distance(a + 3, EvilSentinel<int*>{a}) == -3);
- assert(std::ranges::distance(std::move(a), EvilSentinel<int*>{a + 3}) == 3);
- }
- {
- const int a[] = {1, 2, 3};
- assert(std::ranges::distance(a, EvilSentinel<const int*>{a + 3}) == 3);
- assert(std::ranges::distance(a, EvilSentinel<const int*>{a}) == 0);
- assert(std::ranges::distance(a + 3, EvilSentinel<const int*>{a}) == -3);
- assert(std::ranges::distance(std::move(a), EvilSentinel<const int*>{a + 3}) == 3);
- static_assert(!std::is_invocable_v<decltype(std::ranges::distance), const int (&)[3], EvilSentinel<int*>>);
- static_assert(!std::is_invocable_v<decltype(std::ranges::distance), const int (&&)[3], EvilSentinel<int*>>);
+ test_lwg3664();
+
+ if (!TEST_IS_CONSTANT_EVALUATED) {
+ test_deque(); // TODO: Use TEST_STD_AT_LEAST_26_OR_RUNTIME_EVALUATED when std::deque is made constexpr
+ test_lwg4242();
}
return true;
More information about the libcxx-commits
mailing list