[libcxx-commits] [libcxx] 8825ce4 - [libc++][ranges] Mark LWG4242 as Resolved (#211568)
via libcxx-commits
libcxx-commits at lists.llvm.org
Sun Aug 9 09:20:41 PDT 2026
Author: Lucas Mellone
Date: 2026-08-10T00:20:35+08:00
New Revision: 8825ce4c6c1213784075bc54909f837d36ab81fa
URL: https://github.com/llvm/llvm-project/commit/8825ce4c6c1213784075bc54909f837d36ab81fa
DIFF: https://github.com/llvm/llvm-project/commit/8825ce4c6c1213784075bc54909f837d36ab81fa.diff
LOG: [libc++][ranges] Mark LWG4242 as Resolved (#211568)
Closes https://github.com/llvm/llvm-project/issues/148224
The current implementation for the `ranges::distance(I&& first, S last)`
overload already sidesteps the `volatile first` with condition
`sized_sentinel_for<_Sp, __remove_cvref_t<_Ip>>`.
In the commit initially implementing `ranges::distance`
(c965d5448ecdf9a5513983862a78a2ba8f7fbab8), the condition was
`sized_sentinel_for<_Sp, __uncvref_t<_Ip>>` and `__uncvref_t` was just
renamed to `__remove_cvref_t` later. Also, given the overload has been
constrained with `sized_sentinel_for<_Sp, decay_t<_Ip>>`, the condition
always gives the same results as `!is_array_v<remove_reference_t<_Ip>>`
that is indicated by the resolution of LWG4242. So it can be considered
that LWG4242 was implemented in libc++ in LLVM 14.
This commit marks LWG4242 as Resolved and organises the test suite to
better represent both LWG3664 and LWG4242 tests in
`libcxx/test/std/iterators/iterator.primitives/range.iter.ops/range.iter.ops.distance/iterator_sentinel.pass.cpp`.
References:
- [LWG4242](https://cplusplus.github.io/LWG/issue4242)
- https://eel.is/c++draft/range.iter.op.distance
Follows-up: https://github.com/llvm/llvm-project/pull/210550
Added:
Modified:
libcxx/docs/Status/Cxx26Issues.csv
libcxx/test/std/iterators/iterator.primitives/range.iter.ops/range.iter.ops.distance/iterator_sentinel.pass.cpp
Removed:
################################################################################
diff --git a/libcxx/docs/Status/Cxx26Issues.csv b/libcxx/docs/Status/Cxx26Issues.csv
index db9bf85b72d4c..6b3b5f61727c7 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|","14","`#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/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