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> );
