Implement the accepted resolution of LWG 4243.

libstdc++-v3/ChangeLog:

        * include/std/span (as_bytes, as_writable_bytes): Add
        constraints to disallow volatile elements, as per LWG 4243.
        * testsuite/23_containers/span/lwg4243.cc: New test.
---

Tested x86_64-linux.

 libstdc++-v3/include/std/span                 |  5 ++-
 .../testsuite/23_containers/span/lwg4243.cc   | 31 +++++++++++++++++++
 2 files changed, 35 insertions(+), 1 deletion(-)
 create mode 100644 libstdc++-v3/testsuite/23_containers/span/lwg4243.cc

diff --git a/libstdc++-v3/include/std/span b/libstdc++-v3/include/std/span
index 8f525d009ff5..a2f338449c8a 100644
--- a/libstdc++-v3/include/std/span
+++ b/libstdc++-v3/include/std/span
@@ -517,7 +517,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     span(_Range &&)
       -> span<remove_reference_t<ranges::range_reference_t<_Range&>>>;
 
+  // _GLIBCXX_RESOLVE_LIB_DEFECTS
+  // 4243. as_bytes/as_writable_bytes is broken with span<volatile T>
   template<typename _Type, size_t _Extent>
+    requires (!is_volatile_v<_Type>)
     [[nodiscard]]
     inline
     span<const byte, _Extent == dynamic_extent
@@ -532,7 +535,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     }
 
   template<typename _Type, size_t _Extent>
-    requires (!is_const_v<_Type>)
+    requires (!is_const_v<_Type> && !is_volatile_v<_Type>)
     inline
     span<byte, _Extent == dynamic_extent
        ? dynamic_extent : _Extent * sizeof(_Type)>
diff --git a/libstdc++-v3/testsuite/23_containers/span/lwg4243.cc 
b/libstdc++-v3/testsuite/23_containers/span/lwg4243.cc
new file mode 100644
index 000000000000..c2c9949319a9
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/span/lwg4243.cc
@@ -0,0 +1,31 @@
+// { dg-do compile { target c++20 } }
+
+// LWG 4243. as_bytes/as_writable_bytes is broken with span<volatile T>
+
+#include <span>
+
+template<typename ElementType, std::size_t Extent = std::dynamic_extent>
+concept can_call_as_bytes
+  = requires (std::span<ElementType, Extent> s) { std::as_bytes(s); };
+
+template<typename ElementType, std::size_t Extent = std::dynamic_extent>
+concept can_call_as_writable_bytes
+  = requires (std::span<ElementType, Extent> s) { std::as_writable_bytes(s); };
+
+static_assert( can_call_as_bytes<int> );
+static_assert( can_call_as_bytes<int, 10> );
+static_assert( can_call_as_bytes<const int> );
+static_assert( can_call_as_bytes<const int, 10> );
+static_assert( can_call_as_writable_bytes<int> );
+static_assert( can_call_as_writable_bytes<int, 10> );
+static_assert( can_call_as_writable_bytes<const int> );
+static_assert( can_call_as_writable_bytes<const int, 10> );
+
+static_assert( ! can_call_as_bytes<volatile int> );
+static_assert( ! can_call_as_bytes<volatile int, 10> );
+static_assert( ! can_call_as_bytes<const volatile int> );
+static_assert( ! can_call_as_bytes<const volatile int, 10> );
+static_assert( ! can_call_as_writable_bytes<volatile int> );
+static_assert( ! can_call_as_writable_bytes<volatile int, 10> );
+static_assert( ! can_call_as_writable_bytes<const volatile int> );
+static_assert( ! can_call_as_writable_bytes<const volatile int, 10> );
-- 
2.53.0

Reply via email to