[libcxx-commits] [libcxx] [libc++] Fix the mdspan ElementType complete object type mandate (PR #191703)

via libcxx-commits libcxx-commits at lists.llvm.org
Sun Apr 12 22:10:55 PDT 2026


https://github.com/eiytoq updated https://github.com/llvm/llvm-project/pull/191703

>From 60889578fdb7a31740e821b4b6e0ab7d220a486d Mon Sep 17 00:00:00 2001
From: eiytoq <eiytoq at outlook.com>
Date: Sun, 12 Apr 2026 20:25:28 +0800
Subject: [PATCH 1/4] fix

---
 libcxx/include/__mdspan/mdspan.h                    |  4 ++++
 .../views/mdspan/mdspan/element_type.verify.cpp     | 13 +++++++++++++
 2 files changed, 17 insertions(+)

diff --git a/libcxx/include/__mdspan/mdspan.h b/libcxx/include/__mdspan/mdspan.h
index 449baea43f2d7..b8f24b9ac0c31 100644
--- a/libcxx/include/__mdspan/mdspan.h
+++ b/libcxx/include/__mdspan/mdspan.h
@@ -30,6 +30,7 @@
 #include <__type_traits/is_constructible.h>
 #include <__type_traits/is_convertible.h>
 #include <__type_traits/is_nothrow_constructible.h>
+#include <__type_traits/is_object.h>
 #include <__type_traits/is_pointer.h>
 #include <__type_traits/is_same.h>
 #include <__type_traits/rank.h>
@@ -66,6 +67,9 @@ class mdspan {
 private:
   static_assert(__mdspan_detail::__is_extents_v<_Extents>,
                 "mdspan: Extents template parameter must be a specialization of extents.");
+  static_assert(
+      is_object_v<_ElementType> && requires { sizeof(_ElementType); },
+      "mdspan: ElementType template parameter must be a complete object type");
   static_assert(!is_array_v<_ElementType>, "mdspan: ElementType template parameter may not be an array type");
   static_assert(!is_abstract_v<_ElementType>, "mdspan: ElementType template parameter may not be an abstract class");
   static_assert(is_same_v<_ElementType, typename _AccessorPolicy::element_type>,
diff --git a/libcxx/test/std/containers/views/mdspan/mdspan/element_type.verify.cpp b/libcxx/test/std/containers/views/mdspan/mdspan/element_type.verify.cpp
index 9f2730262d953..8196788b1fe77 100644
--- a/libcxx/test/std/containers/views/mdspan/mdspan/element_type.verify.cpp
+++ b/libcxx/test/std/containers/views/mdspan/mdspan/element_type.verify.cpp
@@ -23,6 +23,19 @@ class AbstractClass {
   virtual void method() = 0;
 };
 
+struct BadAccessor {
+  using offset_policy    = BadAccessor;
+  using element_type     = void;
+  using reference        = void;
+  using data_handle_type = element_type*;
+  reference access(data_handle_type, std::size_t) const;
+};
+
+int incomplete_type() {
+  // expected-error-re@*:* {{static assertion failed {{.*}}mdspan: ElementType template parameter must be a complete object type}}
+  [[maybe_unused]] std::mdspan<void, std::dextents<std::size_t, 2>, std::layout_right, BadAccessor> m;
+}
+
 void not_abstract_class() {
   // expected-error-re@*:* {{static assertion failed {{.*}}mdspan: ElementType template parameter may not be an abstract class}}
   [[maybe_unused]] std::mdspan<AbstractClass, std::extents<int>> m;

>From 4dbc5033cfefeea9c65cd3fef058892a43d78e0a Mon Sep 17 00:00:00 2001
From: eiytoq <eiytoq at outlook.com>
Date: Sun, 12 Apr 2026 22:48:12 +0800
Subject: [PATCH 2/4] Addressed comment

Co-authored-by: A. Jiang <de34 at live.cn>
---
 .../std/containers/views/mdspan/mdspan/element_type.verify.cpp  | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libcxx/test/std/containers/views/mdspan/mdspan/element_type.verify.cpp b/libcxx/test/std/containers/views/mdspan/mdspan/element_type.verify.cpp
index 8196788b1fe77..7a6bde5b76367 100644
--- a/libcxx/test/std/containers/views/mdspan/mdspan/element_type.verify.cpp
+++ b/libcxx/test/std/containers/views/mdspan/mdspan/element_type.verify.cpp
@@ -31,7 +31,7 @@ struct BadAccessor {
   reference access(data_handle_type, std::size_t) const;
 };
 
-int incomplete_type() {
+void incomplete_type() {
   // expected-error-re@*:* {{static assertion failed {{.*}}mdspan: ElementType template parameter must be a complete object type}}
   [[maybe_unused]] std::mdspan<void, std::dextents<std::size_t, 2>, std::layout_right, BadAccessor> m;
 }

>From 444d4034dd4c498b1d09c9c7be3169633065e8ea Mon Sep 17 00:00:00 2001
From: eiytoq <eiytoq at outlook.com>
Date: Sun, 12 Apr 2026 23:00:06 +0800
Subject: [PATCH 3/4] add tests

---
 .../mdspan/mdspan/element_type.verify.cpp     | 27 +++++++++++++++++++
 1 file changed, 27 insertions(+)

diff --git a/libcxx/test/std/containers/views/mdspan/mdspan/element_type.verify.cpp b/libcxx/test/std/containers/views/mdspan/mdspan/element_type.verify.cpp
index 7a6bde5b76367..81f8fb290c175 100644
--- a/libcxx/test/std/containers/views/mdspan/mdspan/element_type.verify.cpp
+++ b/libcxx/test/std/containers/views/mdspan/mdspan/element_type.verify.cpp
@@ -31,11 +31,38 @@ struct BadAccessor {
   reference access(data_handle_type, std::size_t) const;
 };
 
+struct RefAccessor {
+  using offset_policy    = RefAccessor;
+  using element_type     = int&;
+  using reference        = int&;
+  using data_handle_type = int*;
+
+  reference access(data_handle_type p, std::size_t i) const { return p[i]; }
+};
+
+struct FuncAccessor {
+  using offset_policy    = FuncAccessor;
+  using element_type     = int();
+  using reference        = int (&)();
+  using data_handle_type = int (*)();
+  reference access(data_handle_type, std::size_t) const;
+};
+
 void incomplete_type() {
   // expected-error-re@*:* {{static assertion failed {{.*}}mdspan: ElementType template parameter must be a complete object type}}
   [[maybe_unused]] std::mdspan<void, std::dextents<std::size_t, 2>, std::layout_right, BadAccessor> m;
 }
 
+void reference_type() {
+  // expected-error-re@*:* {{static assertion failed {{.*}}mdspan: ElementType template parameter must be a complete object type}}
+  [[maybe_unused]] std::mdspan<int&, std::dextents<std::size_t, 2>, std::layout_right, RefAccessor> m;
+}
+
+void function_type() {
+  // expected-error-re@*:* {{static assertion failed {{.*}}mdspan: ElementType template parameter must be a complete object type}}
+  [[maybe_unused]] std::mdspan<int(), std::dextents<std::size_t, 2>, std::layout_right, FuncAccessor> m;
+}
+
 void not_abstract_class() {
   // expected-error-re@*:* {{static assertion failed {{.*}}mdspan: ElementType template parameter may not be an abstract class}}
   [[maybe_unused]] std::mdspan<AbstractClass, std::extents<int>> m;

>From 0c91aaa0abf599067dbaeffd83542b28a5d8c74c Mon Sep 17 00:00:00 2001
From: eiytoq <eiytoq at outlook.com>
Date: Mon, 13 Apr 2026 13:09:51 +0800
Subject: [PATCH 4/4] add tests

---
 .../views/mdspan/mdspan/element_type.verify.cpp  | 16 +++++++++++-----
 1 file changed, 11 insertions(+), 5 deletions(-)

diff --git a/libcxx/test/std/containers/views/mdspan/mdspan/element_type.verify.cpp b/libcxx/test/std/containers/views/mdspan/mdspan/element_type.verify.cpp
index 81f8fb290c175..4fd96cde837ab 100644
--- a/libcxx/test/std/containers/views/mdspan/mdspan/element_type.verify.cpp
+++ b/libcxx/test/std/containers/views/mdspan/mdspan/element_type.verify.cpp
@@ -18,13 +18,15 @@
 
 #include <mdspan>
 
+struct Incomplete;
+
 class AbstractClass {
 public:
   virtual void method() = 0;
 };
 
-struct BadAccessor {
-  using offset_policy    = BadAccessor;
+struct VoidAccessor {
+  using offset_policy    = VoidAccessor;
   using element_type     = void;
   using reference        = void;
   using data_handle_type = element_type*;
@@ -36,7 +38,6 @@ struct RefAccessor {
   using element_type     = int&;
   using reference        = int&;
   using data_handle_type = int*;
-
   reference access(data_handle_type p, std::size_t i) const { return p[i]; }
 };
 
@@ -48,9 +49,14 @@ struct FuncAccessor {
   reference access(data_handle_type, std::size_t) const;
 };
 
-void incomplete_type() {
+void incomplete_object_type() {
+  // expected-error-re@*:* {{static assertion failed {{.*}}mdspan: ElementType template parameter must be a complete object type}}
+  [[maybe_unused]] std::mdspan<Incomplete, std::dextents<std::size_t, 2>> m;
+}
+
+void void_type() {
   // expected-error-re@*:* {{static assertion failed {{.*}}mdspan: ElementType template parameter must be a complete object type}}
-  [[maybe_unused]] std::mdspan<void, std::dextents<std::size_t, 2>, std::layout_right, BadAccessor> m;
+  [[maybe_unused]] std::mdspan<void, std::dextents<std::size_t, 2>, std::layout_right, VoidAccessor> m;
 }
 
 void reference_type() {



More information about the libcxx-commits mailing list