[PATCH v3 2/5] libstdc++: Check prerequisite of extents::extents.

Luc Grosheintz luc.grosheintz@gmail.com
Fri Jul 4 08:29:44 GMT 2025


Previously the prerequisite of the extents ctors that

    static_extent(i) == dynamic_extent || extent(i) == other.extent(i).

was not checked. This commit adds the __glibcxx_assert and test them.

libstdc++-v3/ChangeLog:

	* include/std/mdspan (extents): Check prerequisite of the ctor that
	static_extent(i) == dynamic_extent || extent(i) == other.extent(i).
	* testsuite/23_containers/mdspan/extents/class_mandates_neg.cc:
	Test the implemented prerequisite.

Signed-off-by: Luc Grosheintz <luc.grosheintz@gmail.com>
---
 libstdc++-v3/include/std/mdspan               | 13 +++++++
 .../mdspan/extents/class_mandates_neg.cc      |  2 ++
 .../mdspan/extents/extents_mismatch_neg.cc    | 35 +++++++++++++++++++
 3 files changed, 50 insertions(+)
 create mode 100644 libstdc++-v3/testsuite/23_containers/mdspan/extents/extents_mismatch_neg.cc

diff --git a/libstdc++-v3/include/std/mdspan b/libstdc++-v3/include/std/mdspan
index cf20553aaa5..1d6cdc93d80 100644
--- a/libstdc++-v3/include/std/mdspan
+++ b/libstdc++-v3/include/std/mdspan
@@ -110,10 +110,23 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	    return __se;
 	}
 
+	template<size_t _OtherRank, typename _GetOtherExtent>
+	  constexpr bool
+	  _S_is_compatible_extents(_GetOtherExtent __get_extent) noexcept
+	  {
+	    if constexpr (_OtherRank == _S_rank)
+	      for (size_t __i = 0; __i < _S_rank; ++__i)
+		if (_Extents[__i] != dynamic_extent
+		    && !cmp_equal(_Extents[__i], _S_int_cast(__get_extent(__i))))
+		  return false;
+	    return true;
+	  }
+
 	template<size_t _OtherRank, typename _GetOtherExtent>
 	  constexpr void
 	  _M_init_dynamic_extents(_GetOtherExtent __get_extent) noexcept
 	  {
+	    __glibcxx_assert(_S_is_compatible_extents<_OtherRank>(__get_extent));
 	    for (size_t __i = 0; __i < _S_rank_dynamic; ++__i)
 	      {
 		size_t __di = __i;
diff --git a/libstdc++-v3/testsuite/23_containers/mdspan/extents/class_mandates_neg.cc b/libstdc++-v3/testsuite/23_containers/mdspan/extents/class_mandates_neg.cc
index f9c1c019666..67d18feda96 100644
--- a/libstdc++-v3/testsuite/23_containers/mdspan/extents/class_mandates_neg.cc
+++ b/libstdc++-v3/testsuite/23_containers/mdspan/extents/class_mandates_neg.cc
@@ -7,6 +7,8 @@ std::extents<uint8_t, size_t(1) << 9> e1; // { dg-error "from here" }
 std::extents<char, 1> e2;                 // { dg-error "from here" }
 std::extents<bool, 1> e3;                 // { dg-error "from here" }
 std::extents<double, 1> e4;               // { dg-error "from here" }
+
 // { dg-prune-output "dynamic or representable as IndexType" }
 // { dg-prune-output "signed or unsigned integer" }
 // { dg-prune-output "invalid use of incomplete type" }
+// { dg-prune-output "non-constant condition for static assertion" }
diff --git a/libstdc++-v3/testsuite/23_containers/mdspan/extents/extents_mismatch_neg.cc b/libstdc++-v3/testsuite/23_containers/mdspan/extents/extents_mismatch_neg.cc
new file mode 100644
index 00000000000..b35e5310d41
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/mdspan/extents/extents_mismatch_neg.cc
@@ -0,0 +1,35 @@
+// { dg-do compile { target c++23 } }
+#include<mdspan>
+
+#include <cstdint>
+
+constexpr size_t dyn = std::dynamic_extent;
+
+constexpr bool
+test_dyn2sta_extents_mismatch_00()
+{
+  auto e0 = std::extents<int, dyn>{1};
+  [[maybe_unused]] auto e1 = std::extents<int, 2>{e0};        // { dg-error "expansion of" }
+  return true;
+}
+static_assert(test_dyn2sta_extents_mismatch_00());            // { dg-error "expansion of" }
+
+constexpr bool
+test_dyn2sta_extents_mismatch_01()
+{
+  [[maybe_unused]] auto e = std::extents<int, 1, dyn>{2, 2}; // { dg-error "expansion of" }
+  return true;
+}
+static_assert(test_dyn2sta_extents_mismatch_01());           // { dg-error "expansion of" }
+
+constexpr bool
+test_dyn2sta_extents_mismatch_02()
+{
+  std::array<int, 2> exts{2, 2};
+  [[maybe_unused]] auto e = std::extents<int, 1, dyn>{exts}; // { dg-error "expansion of" }
+  return true;
+}
+static_assert(test_dyn2sta_extents_mismatch_02());           // { dg-error "expansion of" }
+
+// { dg-prune-output "non-constant condition for static assertion" }
+// { dg-prune-output "__glibcxx_assert" }
-- 
2.49.0



More information about the Libstdc++ mailing list