[libcxx-commits] [libcxx] [libc++][ranges] Resolve LWG4242 (PR #211568)
Lucas Mellone via libcxx-commits
libcxx-commits at lists.llvm.org
Fri Jul 24 01:29:32 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/4] 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/4] 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;
>From d828f029e4f94bbd6db269722fb2d6a8a957f765 Mon Sep 17 00:00:00 2001
From: Lucas Mellone <github.snugness349 at passinbox.com>
Date: Thu, 23 Jul 2026 18:51:47 +0200
Subject: [PATCH 3/4] fix(tentative): check if CI errors are somehow related to
static_cast wording
---
libcxx/include/__iterator/distance.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libcxx/include/__iterator/distance.h b/libcxx/include/__iterator/distance.h
index 029117e2ff5cc..bb3620764f1ce 100644
--- a/libcxx/include/__iterator/distance.h
+++ b/libcxx/include/__iterator/distance.h
@@ -90,7 +90,7 @@ struct __distance {
if constexpr (!is_array_v<remove_reference_t<_Ip>>) {
return __last - __first;
} else {
- return __last - decay_t<_Ip>(__first);
+ return __last - static_cast<decay_t<_Ip>>(__first);
}
}
>From ab8c4dfd9af5a8ad859898fb6e4f3d6e65cb023a Mon Sep 17 00:00:00 2001
From: Lucas Mellone <github.snugness349 at passinbox.com>
Date: Fri, 24 Jul 2026 10:29:08 +0200
Subject: [PATCH 4/4] add: missing includes. remove: unused __remove_cref.h
include
---
libcxx/include/__iterator/distance.h | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/libcxx/include/__iterator/distance.h b/libcxx/include/__iterator/distance.h
index bb3620764f1ce..fba72db022f9a 100644
--- a/libcxx/include/__iterator/distance.h
+++ b/libcxx/include/__iterator/distance.h
@@ -21,8 +21,9 @@
#include <__ranges/concepts.h>
#include <__ranges/size.h>
#include <__type_traits/decay.h>
+#include <__type_traits/is_array.h>
#include <__type_traits/enable_if.h>
-#include <__type_traits/remove_cvref.h>
+#include <__type_traits/remove_reference.h>
#include <__utility/move.h>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
More information about the libcxx-commits
mailing list