https://gcc.gnu.org/g:a4f807e74118302319ec99adefd0646a9e7a1d34

commit r16-7987-ga4f807e74118302319ec99adefd0646a9e7a1d34
Author: Jonathan Wakely <[email protected]>
Date:   Tue Mar 10 16:00:40 2026 +0000

    libstdc++: Constrain std::as_bytes to disallow span<volatile T>
    
    Implement the accepted resolution of LWG 4243, approved in Kona 2025.
    
    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.
    
    Reviewed-by: Tomasz KamiƄski <[email protected]>

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

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..26bb53d8739b
--- /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); };
+
+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_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> );
+
+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_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_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> );

Reply via email to