]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
libstdc++: Fix constraint for custom integer types in mdspan [PR121061]
authorLuc Grosheintz <luc.grosheintz@gmail.com>
Wed, 16 Jul 2025 13:45:44 +0000 (15:45 +0200)
committerTomasz Kamiński <tkaminsk@redhat.com>
Thu, 17 Jul 2025 14:08:58 +0000 (16:08 +0200)
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<const OtherIndexType&, 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 <jwakely@redhat.com>
Reviewed-by: Tomasz Kamiński <tkaminsk@redhat.com>
Signed-off-by: Luc Grosheintz <luc.grosheintz@gmail.com>
libstdc++-v3/include/std/mdspan
libstdc++-v3/testsuite/23_containers/mdspan/extents/custom_integer.cc
libstdc++-v3/testsuite/23_containers/mdspan/int_like.h
libstdc++-v3/testsuite/23_containers/mdspan/layouts/mapping.cc
libstdc++-v3/testsuite/23_containers/mdspan/layouts/stride.cc
libstdc++-v3/testsuite/23_containers/mdspan/mdspan.cc

index b34116a85e676fb3db1741ab991b89087035a343..930997e95360327f9b5e590d456948e710a9e055 100644 (file)
@@ -288,15 +288,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
            initializer_list{_S_storage::_S_int_cast(__exts)...}))
        { }
 
-      template<__mdspan::__valid_index_type<index_type> _OIndexType, size_t _Nm>
-       requires (_Nm == rank() || _Nm == rank_dynamic())
+      template<typename _OIndexType, size_t _Nm>
+       requires __mdspan::__valid_index_type<const _OIndexType&, index_type>
+         && (_Nm == rank() || _Nm == rank_dynamic())
        constexpr explicit(_Nm != rank_dynamic())
        extents(span<_OIndexType, _Nm> __exts) noexcept
        : _M_exts(span<const _OIndexType, _Nm>(__exts))
        { }
 
-      template<__mdspan::__valid_index_type<index_type> _OIndexType, size_t _Nm>
-       requires (_Nm == rank() || _Nm == rank_dynamic())
+      template<typename _OIndexType, size_t _Nm>
+       requires __mdspan::__valid_index_type<const _OIndexType&, index_type>
+         && (_Nm == rank() || _Nm == rank_dynamic())
        constexpr explicit(_Nm != rank_dynamic())
        extents(const array<_OIndexType, _Nm>& __exts) noexcept
        : _M_exts(span<const _OIndexType, _Nm>(__exts))
@@ -878,7 +880,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       constexpr
       mapping(const mapping&) noexcept = default;
 
-      template<__mdspan::__valid_index_type<index_type> _OIndexType>
+      template<typename _OIndexType>
+       requires __mdspan::__valid_index_type<const _OIndexType&, 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<index_type> _OIndexType>
+      template<typename _OIndexType>
+       requires __mdspan::__valid_index_type<const _OIndexType&, 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<index_type> _OIndexType,
-              size_t _Nm>
-       requires (_Nm == rank() || _Nm == rank_dynamic())
+      template<typename _OIndexType, size_t _Nm>
+       requires __mdspan::__valid_index_type<const _OIndexType&, index_type>
+                && (_Nm == rank() || _Nm == rank_dynamic())
                 && is_constructible_v<mapping_type, extents_type>
                 && is_default_constructible_v<accessor_type>
        constexpr explicit(_Nm != rank_dynamic())
@@ -1145,9 +1149,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
          _M_handle(std::move(__handle))
        { }
 
-      template<__mdspan::__valid_index_type<index_type> _OIndexType,
-              size_t _Nm>
-       requires (_Nm == rank() || _Nm == rank_dynamic())
+      template<typename _OIndexType, size_t _Nm>
+       requires __mdspan::__valid_index_type<const _OIndexType&, index_type>
+                && (_Nm == rank() || _Nm == rank_dynamic())
                 && is_constructible_v<mapping_type, extents_type>
                 && is_default_constructible_v<accessor_type>
        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<index_type> _OIndexType>
+      template<typename _OIndexType>
+       requires __mdspan::__valid_index_type<const _OIndexType&, index_type>
        constexpr reference
        operator[](span<_OIndexType, rank()> __indices) const
        {
@@ -1228,7 +1233,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
          return __call(make_index_sequence<rank()>());
        }
 
-      template<__mdspan::__valid_index_type<index_type> _OIndexType>
+      template<typename _OIndexType>
+       requires __mdspan::__valid_index_type<const _OIndexType&, index_type>
        constexpr reference
        operator[](const array<_OIndexType, rank()>& __indices) const
        { return (*this)[span<const _OIndexType, rank()>(__indices)]; }
index 4f631815b101315b5c6f0a5faacf04355c7621a7..92c2ebb46e1bcd0ba0e4c008997ff87fc27e75da 100644 (file)
@@ -84,6 +84,7 @@ main()
   test_shape_all<int, true>();
   test_shape_all<IntLike, true>();
   test_shape_all<ThrowingInt, false>();
+  test_shape_all<MutatingInt, false>();
 
   test_pack_all<int, true>();
   test_pack_all<IntLike, true>();
index ed45375f98669ca2f4ae0344593d642aff41a0ae..f4f4a7731931f13e8fcd6a9618b6d4c59d0c47cf 100644 (file)
@@ -5,6 +5,7 @@ enum class CustomIndexKind
 {
   Const,
   Throwing,
+  Mutating,
 };
 
 template<CustomIndexKind Kind>
@@ -36,12 +37,18 @@ template<CustomIndexKind Kind>
     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<CustomIndexKind::Const>;
 using ThrowingInt = CustomIndexType<CustomIndexKind::Throwing>;
+using MutatingInt = CustomIndexType<CustomIndexKind::Mutating>;
 
 struct NotIntLike
 { };
index 17f0c00acf293e9aca7bf4ca09c21b0091fdfce6..6742fa11a5149a2af24eece32d494f3c0e54775a 100644 (file)
@@ -180,6 +180,7 @@ template<typename Layout>
     static_assert(has_linear_index<Mapping, int>);
     static_assert(has_linear_index<Mapping, double>);
     static_assert(has_linear_index<Mapping, IntLike>);
+    static_assert(has_linear_index<Mapping, MutatingInt>);
     static_assert(!has_linear_index<Mapping, ThrowingInt>);
     static_assert(!has_linear_index<Mapping, NotIntLike>);
     static_assert(!has_linear_index<Mapping, int, int>);
@@ -194,6 +195,7 @@ template<typename Layout>
     static_assert(has_linear_index<Mapping, int, int>);
     static_assert(has_linear_index<Mapping, double, double>);
     static_assert(has_linear_index<Mapping, IntLike, int>);
+    static_assert(has_linear_index<Mapping, MutatingInt, int>);
     static_assert(!has_linear_index<Mapping, ThrowingInt, int>);
     static_assert(!has_linear_index<Mapping, NotIntLike, int>);
     static_assert(!has_linear_index<Mapping, int, int, int>);
@@ -524,6 +526,7 @@ template<typename Layout>
     if !consteval
       {
        test_linear_index_all<Layout, IntLike>();
+       test_linear_index_all<Layout, MutatingInt>();
       }
 
     test_required_span_size_all<Layout>();
index 1267306fb5c2f79b599a421257ab53faf3a6b286..8d2fad2936f67278b26ccb3eecf000e6e1611d6d 100644 (file)
@@ -65,6 +65,7 @@ test_stride_constructible_all()
   test_stride_constructible<E0, E0, int, 0, true>();
   test_stride_constructible<E0, E0, IntLike, 0, true>();
   test_stride_constructible<E0, E0, ThrowingInt, 0, false>();
+  test_stride_constructible<E0, E0, MutatingInt, 0, false>();
   test_stride_constructible<E0, E0, NotIntLike, 0, false>();
   test_stride_constructible<E1, E1, int, 1, true>();
   test_stride_constructible<E2, E1, int, 1, true>();
index adabb0c663978bce72b13e7552b467c17a8114ed..22ec68ea2d1da462b26e37526f4c66c90a7e98e7 100644 (file)
@@ -693,6 +693,7 @@ main()
   static_assert(test_from_int_like<int, true, true>());
   test_from_int_like<IntLike, true, true>();
   test_from_int_like<ThrowingInt, false, false>();
+  test_from_int_like<MutatingInt, true, false>();
 
   test_from_opaque_accessor();
   test_from_base_class_accessor();
@@ -703,6 +704,7 @@ main()
   static_assert(test_access<int, true, true>());
   test_access<IntLike, true, true>();
   test_access<ThrowingInt, false, false>();
+  test_access<MutatingInt, true, false>();
 
   test_swap();
   static_assert(test_swap());