From: Luc Grosheintz Date: Wed, 16 Jul 2025 13:45:44 +0000 (+0200) Subject: libstdc++: Fix constraint for custom integer types in mdspan [PR121061] X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=1eee8430794f790b6d364603685e70d83d8d42f5;p=thirdparty%2Fgcc.git libstdc++: Fix constraint for custom integer types in mdspan [PR121061] PR121061 consists of two bugs for mdspan related code. This commit fixes the first one. Namely, when passing custom IndexType as an array or span, the conversion to int must be const. Prior to this commit the constraint incorrectly also allowed non-const conversion. This commit updates all related constraints to check __valid_index_type in those cases. Also adds a MutatingInt to int_like.h which only supports non-const conversion to int and updates the tests. PR libstdc++/121061 libstdc++-v3/ChangeLog: * include/std/mdspan (extents::extents): Fix constraint to prevent non-const conversion to index_type. (layout_stride::mapping::mapping): Ditto. (mdspan::mdspan): Ditto. (mdspan::operator[]): Ditto. * testsuite/23_containers/mdspan/extents/custom_integer.cc: Add test for MutatingInt. * testsuite/23_containers/mdspan/int_like.h (MutatingInt): Add. * testsuite/23_containers/mdspan/layouts/mapping.cc: Add test for MutatingInt. * testsuite/23_containers/mdspan/layouts/stride.cc: Ditto. * testsuite/23_containers/mdspan/mdspan.cc: Ditto. Reviewed-by: Jonathan Wakely Reviewed-by: Tomasz KamiƄski Signed-off-by: Luc Grosheintz --- diff --git a/libstdc++-v3/include/std/mdspan b/libstdc++-v3/include/std/mdspan index b34116a85e6..930997e9536 100644 --- a/libstdc++-v3/include/std/mdspan +++ b/libstdc++-v3/include/std/mdspan @@ -288,15 +288,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION initializer_list{_S_storage::_S_int_cast(__exts)...})) { } - template<__mdspan::__valid_index_type _OIndexType, size_t _Nm> - requires (_Nm == rank() || _Nm == rank_dynamic()) + template + requires __mdspan::__valid_index_type + && (_Nm == rank() || _Nm == rank_dynamic()) constexpr explicit(_Nm != rank_dynamic()) extents(span<_OIndexType, _Nm> __exts) noexcept : _M_exts(span(__exts)) { } - template<__mdspan::__valid_index_type _OIndexType, size_t _Nm> - requires (_Nm == rank() || _Nm == rank_dynamic()) + template + requires __mdspan::__valid_index_type + && (_Nm == rank() || _Nm == rank_dynamic()) constexpr explicit(_Nm != rank_dynamic()) extents(const array<_OIndexType, _Nm>& __exts) noexcept : _M_exts(span(__exts)) @@ -878,7 +880,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION constexpr mapping(const mapping&) noexcept = default; - template<__mdspan::__valid_index_type _OIndexType> + template + requires __mdspan::__valid_index_type constexpr mapping(const extents_type& __exts, span<_OIndexType, extents_type::rank()> __strides) noexcept @@ -888,7 +891,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _M_strides[__i] = index_type(as_const(__strides[__i])); } - template<__mdspan::__valid_index_type _OIndexType> + template + requires __mdspan::__valid_index_type constexpr mapping(const extents_type& __exts, const array<_OIndexType, extents_type::rank()>& __strides) @@ -1134,9 +1138,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _M_handle(std::move(__handle)) { } - template<__mdspan::__valid_index_type _OIndexType, - size_t _Nm> - requires (_Nm == rank() || _Nm == rank_dynamic()) + template + requires __mdspan::__valid_index_type + && (_Nm == rank() || _Nm == rank_dynamic()) && is_constructible_v && is_default_constructible_v constexpr explicit(_Nm != rank_dynamic()) @@ -1145,9 +1149,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _M_handle(std::move(__handle)) { } - template<__mdspan::__valid_index_type _OIndexType, - size_t _Nm> - requires (_Nm == rank() || _Nm == rank_dynamic()) + template + requires __mdspan::__valid_index_type + && (_Nm == rank() || _Nm == rank_dynamic()) && is_constructible_v && is_default_constructible_v constexpr explicit(_Nm != rank_dynamic()) @@ -1218,7 +1222,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return _M_accessor.access(_M_handle, __index); } - template<__mdspan::__valid_index_type _OIndexType> + template + requires __mdspan::__valid_index_type constexpr reference operator[](span<_OIndexType, rank()> __indices) const { @@ -1228,7 +1233,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return __call(make_index_sequence()); } - template<__mdspan::__valid_index_type _OIndexType> + template + requires __mdspan::__valid_index_type constexpr reference operator[](const array<_OIndexType, rank()>& __indices) const { return (*this)[span(__indices)]; } diff --git a/libstdc++-v3/testsuite/23_containers/mdspan/extents/custom_integer.cc b/libstdc++-v3/testsuite/23_containers/mdspan/extents/custom_integer.cc index 4f631815b10..92c2ebb46e1 100644 --- a/libstdc++-v3/testsuite/23_containers/mdspan/extents/custom_integer.cc +++ b/libstdc++-v3/testsuite/23_containers/mdspan/extents/custom_integer.cc @@ -84,6 +84,7 @@ main() test_shape_all(); test_shape_all(); test_shape_all(); + test_shape_all(); test_pack_all(); test_pack_all(); diff --git a/libstdc++-v3/testsuite/23_containers/mdspan/int_like.h b/libstdc++-v3/testsuite/23_containers/mdspan/int_like.h index ed45375f986..f4f4a773193 100644 --- a/libstdc++-v3/testsuite/23_containers/mdspan/int_like.h +++ b/libstdc++-v3/testsuite/23_containers/mdspan/int_like.h @@ -5,6 +5,7 @@ enum class CustomIndexKind { Const, Throwing, + Mutating, }; template @@ -36,12 +37,18 @@ template requires (Kind == CustomIndexKind::Throwing) { return _M_i; } + constexpr + operator int() noexcept + requires (Kind == CustomIndexKind::Mutating) + { return _M_i; } + private: int _M_i; }; using IntLike = CustomIndexType; using ThrowingInt = CustomIndexType; +using MutatingInt = CustomIndexType; struct NotIntLike { }; diff --git a/libstdc++-v3/testsuite/23_containers/mdspan/layouts/mapping.cc b/libstdc++-v3/testsuite/23_containers/mdspan/layouts/mapping.cc index 17f0c00acf2..6742fa11a51 100644 --- a/libstdc++-v3/testsuite/23_containers/mdspan/layouts/mapping.cc +++ b/libstdc++-v3/testsuite/23_containers/mdspan/layouts/mapping.cc @@ -180,6 +180,7 @@ template static_assert(has_linear_index); static_assert(has_linear_index); static_assert(has_linear_index); + static_assert(has_linear_index); static_assert(!has_linear_index); static_assert(!has_linear_index); static_assert(!has_linear_index); @@ -194,6 +195,7 @@ template static_assert(has_linear_index); static_assert(has_linear_index); static_assert(has_linear_index); + static_assert(has_linear_index); static_assert(!has_linear_index); static_assert(!has_linear_index); static_assert(!has_linear_index); @@ -524,6 +526,7 @@ template if !consteval { test_linear_index_all(); + test_linear_index_all(); } test_required_span_size_all(); diff --git a/libstdc++-v3/testsuite/23_containers/mdspan/layouts/stride.cc b/libstdc++-v3/testsuite/23_containers/mdspan/layouts/stride.cc index 1267306fb5c..8d2fad2936f 100644 --- a/libstdc++-v3/testsuite/23_containers/mdspan/layouts/stride.cc +++ b/libstdc++-v3/testsuite/23_containers/mdspan/layouts/stride.cc @@ -65,6 +65,7 @@ test_stride_constructible_all() test_stride_constructible(); test_stride_constructible(); test_stride_constructible(); + test_stride_constructible(); test_stride_constructible(); test_stride_constructible(); test_stride_constructible(); diff --git a/libstdc++-v3/testsuite/23_containers/mdspan/mdspan.cc b/libstdc++-v3/testsuite/23_containers/mdspan/mdspan.cc index adabb0c6639..22ec68ea2d1 100644 --- a/libstdc++-v3/testsuite/23_containers/mdspan/mdspan.cc +++ b/libstdc++-v3/testsuite/23_containers/mdspan/mdspan.cc @@ -693,6 +693,7 @@ main() static_assert(test_from_int_like()); test_from_int_like(); test_from_int_like(); + test_from_int_like(); test_from_opaque_accessor(); test_from_base_class_accessor(); @@ -703,6 +704,7 @@ main() static_assert(test_access()); test_access(); test_access(); + test_access(); test_swap(); static_assert(test_swap());