[libcxx-commits] [libcxx] [libc++] Fix value category issues in `mdspan::operator[]` bounds checking (PR #192269)
via libcxx-commits
libcxx-commits at lists.llvm.org
Sun May 3 17:58:51 PDT 2026
https://github.com/eiytoq updated https://github.com/llvm/llvm-project/pull/192269
>From 322de8969d3f33e4e132f325eb4ba8b8a0a2e4a4 Mon Sep 17 00:00:00 2001
From: eiytoq <eiytoq at outlook.com>
Date: Mon, 4 May 2026 08:57:35 +0800
Subject: [PATCH] [libc++][mdspan] Fix value category issues in
mdspan::operator[] bounds checking
---
libcxx/include/__mdspan/extents.h | 12 ++++++++++++
libcxx/include/__mdspan/mdspan.h | 11 ++++++-----
.../views/mdspan/mdspan/index_operator.pass.cpp | 9 +++++++++
3 files changed, 27 insertions(+), 5 deletions(-)
diff --git a/libcxx/include/__mdspan/extents.h b/libcxx/include/__mdspan/extents.h
index d16bbd2af44f1..379c762ace3ed 100644
--- a/libcxx/include/__mdspan/extents.h
+++ b/libcxx/include/__mdspan/extents.h
@@ -21,12 +21,15 @@
#include <__config>
#include <__concepts/arithmetic.h>
+#include <__concepts/same_as.h>
#include <__type_traits/common_type.h>
#include <__type_traits/integer_traits.h>
#include <__type_traits/is_convertible.h>
#include <__type_traits/is_nothrow_constructible.h>
#include <__type_traits/is_signed.h>
#include <__type_traits/make_unsigned.h>
+#include <__type_traits/remove_cvref.h>
+#include <__utility/forward.h>
#include <__utility/integer_sequence.h>
#include <__utility/unreachable.h>
#include <array>
@@ -433,6 +436,15 @@ class extents {
}
return true;
}
+
+ template <class _OtherIndexType>
+ _LIBCPP_HIDE_FROM_ABI static constexpr auto __index_cast(_OtherIndexType&& __i) noexcept {
+ using _OtherIndex = remove_cvref_t<_OtherIndexType>;
+ if constexpr (integral<_OtherIndex> && !same_as<_OtherIndex, bool>)
+ return __i;
+ else
+ return static_cast<index_type>(std::forward<_OtherIndexType>(__i));
+ }
};
// Recursive helper classes to implement dextents alias for extents
diff --git a/libcxx/include/__mdspan/mdspan.h b/libcxx/include/__mdspan/mdspan.h
index 54685b56a76ff..b3ca2a5bae67d 100644
--- a/libcxx/include/__mdspan/mdspan.h
+++ b/libcxx/include/__mdspan/mdspan.h
@@ -191,11 +191,12 @@ class mdspan {
(is_nothrow_constructible_v<index_type, _OtherIndexTypes> && ...) &&
(sizeof...(_OtherIndexTypes) == rank()))
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr reference operator[](_OtherIndexTypes... __indices) const {
- // Note the standard layouts would also check this, but user provided ones may not, so we
- // check the precondition here
- _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__mdspan_detail::__is_multidimensional_index_in(extents(), __indices...),
- "mdspan: operator[] out of bounds access");
- return __acc_.access(__ptr_, __map_(static_cast<index_type>(std::move(__indices))...));
+ return [&]<class... _IndexTypes>(_IndexTypes... __idxs) -> reference {
+ _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__mdspan_detail::__is_multidimensional_index_in(extents(), __idxs...),
+ "mdspan: operator[] out of bounds access");
+
+ return __acc_.access(__ptr_, __map_(static_cast<index_type>(std::move(__idxs))...));
+ }(extents_type::__index_cast(std::move(__indices))...);
}
template <class _OtherIndexType>
diff --git a/libcxx/test/std/containers/views/mdspan/mdspan/index_operator.pass.cpp b/libcxx/test/std/containers/views/mdspan/mdspan/index_operator.pass.cpp
index c26933e80bfaf..3f20bc886d106 100644
--- a/libcxx/test/std/containers/views/mdspan/mdspan/index_operator.pass.cpp
+++ b/libcxx/test/std/containers/views/mdspan/mdspan/index_operator.pass.cpp
@@ -200,10 +200,19 @@ constexpr void test_layout_large() {
// mapping requirements only require the index operator to mixed integer types not anything convertible to index_type
constexpr void test_index_cast_happens() {}
+struct RValueInt {
+ constexpr operator int() && noexcept { return 0; }
+};
+
constexpr bool test() {
test_layout<std::layout_left>();
test_layout<std::layout_right>();
test_layout<layout_wrapping_integral<4>>();
+
+ int data[1]{};
+ std::mdspan m(data, std::extents<int, 1>{1});
+ TEST_IGNORE_NODISCARD m[RValueInt{}];
+
return true;
}
More information about the libcxx-commits
mailing list