[libcxx-commits] [libcxx] [libc++][span] LWG4243: `as_bytes`/`as_writable_bytes` is broken with `span<volatile T>` (PR #200993)
via libcxx-commits
libcxx-commits at lists.llvm.org
Tue Jun 2 01:21:35 PDT 2026
https://github.com/eiytoq updated https://github.com/llvm/llvm-project/pull/200993
>From 7299bacfea3f648bcd9fd4eb377fae5a91aa2db8 Mon Sep 17 00:00:00 2001
From: eiytoq <eiytoq at outlook.com>
Date: Tue, 2 Jun 2026 11:12:13 +0800
Subject: [PATCH 1/4] fix
---
libcxx/include/span | 4 +-
.../span.objectrep/as_bytes.pass.cpp | 10 +--
.../span.objectrep/as_bytes.verify.cpp | 70 +++++++++++++++++++
.../span.objectrep/as_writable_bytes.pass.cpp | 10 +--
.../as_writable_bytes.verify.cpp | 59 ++++++++++++++--
5 files changed, 137 insertions(+), 16 deletions(-)
create mode 100644 libcxx/test/std/containers/views/views.span/span.objectrep/as_bytes.verify.cpp
diff --git a/libcxx/include/span b/libcxx/include/span
index 230ae3fa2b198..1a484478e19da 100644
--- a/libcxx/include/span
+++ b/libcxx/include/span
@@ -172,6 +172,7 @@ template<class R>
# include <__type_traits/is_convertible.h>
# include <__type_traits/is_integral.h>
# include <__type_traits/is_same.h>
+# include <__type_traits/is_volatile.h>
# include <__type_traits/remove_const.h>
# include <__type_traits/remove_cv.h>
# include <__type_traits/remove_cvref.h>
@@ -585,12 +586,13 @@ inline constexpr bool ranges::enable_view<span<_ElementType, _Extent>> = true;
// as_bytes & as_writable_bytes
template <class _Tp, size_t _Extent>
+ requires(!is_volatile_v<_Tp>)
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI auto as_bytes(span<_Tp, _Extent> __s) noexcept {
return __s.__as_bytes();
}
template <class _Tp, size_t _Extent>
- requires(!is_const_v<_Tp>)
+ requires(!is_const_v<_Tp> && !is_volatile_v<_Tp>)
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI auto as_writable_bytes(span<_Tp, _Extent> __s) noexcept {
return __s.__as_writable_bytes();
}
diff --git a/libcxx/test/std/containers/views/views.span/span.objectrep/as_bytes.pass.cpp b/libcxx/test/std/containers/views/views.span/span.objectrep/as_bytes.pass.cpp
index 1b62fb94e9ab2..5c5892bc2567c 100644
--- a/libcxx/test/std/containers/views/views.span/span.objectrep/as_bytes.pass.cpp
+++ b/libcxx/test/std/containers/views/views.span/span.objectrep/as_bytes.pass.cpp
@@ -9,12 +9,12 @@
// <span>
-// template <class ElementType, size_t Extent>
-// span<const byte,
-// Extent == dynamic_extent
-// ? dynamic_extent
-// : sizeof(ElementType) * Extent>
+// template<class ElementType, size_t Extent>
+// span<const byte, Extent == dynamic_extent ? dynamic_extent : sizeof(ElementType) * Extent>
// as_bytes(span<ElementType, Extent> s) noexcept;
+//
+// Constraints:
+// is_volatile_v<ElementType> is false.
#include <cassert>
#include <cstddef>
diff --git a/libcxx/test/std/containers/views/views.span/span.objectrep/as_bytes.verify.cpp b/libcxx/test/std/containers/views/views.span/span.objectrep/as_bytes.verify.cpp
new file mode 100644
index 0000000000000..cdc830884f23c
--- /dev/null
+++ b/libcxx/test/std/containers/views/views.span/span.objectrep/as_bytes.verify.cpp
@@ -0,0 +1,70 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+
+// <span>
+
+// template<class ElementType, size_t Extent>
+// span<const byte, Extent == dynamic_extent ? dynamic_extent : sizeof(ElementType) * Extent>
+// as_bytes(span<ElementType, Extent> s) noexcept;
+//
+// Constraints:
+// is_volatile_v<ElementType> is false.
+
+#include <span>
+#include <string>
+
+#include "test_macros.h"
+
+struct A {};
+
+void f() {
+ std::as_bytes(std::span<volatile int>());
+ // expected-error at -1 {{no matching function for call to 'as_bytes'}}
+ std::as_bytes(std::span<volatile long>());
+ // expected-error at -1 {{no matching function for call to 'as_bytes'}}
+ std::as_bytes(std::span<volatile double>());
+ // expected-error at -1 {{no matching function for call to 'as_bytes'}}
+ std::as_bytes(std::span<volatile A>());
+ // expected-error at -1 {{no matching function for call to 'as_bytes'}}
+ std::as_bytes(std::span<volatile std::string>());
+ // expected-error at -1 {{no matching function for call to 'as_bytes'}}
+
+ std::as_bytes(std::span<const volatile int>());
+ // expected-error at -1 {{no matching function for call to 'as_bytes'}}
+ std::as_bytes(std::span<const volatile long>());
+ // expected-error at -1 {{no matching function for call to 'as_bytes'}}
+ std::as_bytes(std::span<const volatile double>());
+ // expected-error at -1 {{no matching function for call to 'as_bytes'}}
+ std::as_bytes(std::span<const volatile A>());
+ // expected-error at -1 {{no matching function for call to 'as_bytes'}}
+ std::as_bytes(std::span<const volatile std::string>());
+ // expected-error at -1 {{no matching function for call to 'as_bytes'}}
+
+ std::as_bytes(std::span<volatile int, 0>());
+ // expected-error at -1 {{no matching function for call to 'as_bytes'}}
+ std::as_bytes(std::span<volatile long, 0>());
+ // expected-error at -1 {{no matching function for call to 'as_bytes'}}
+ std::as_bytes(std::span<volatile double, 0>());
+ // expected-error at -1 {{no matching function for call to 'as_bytes'}}
+ std::as_bytes(std::span<volatile A, 0>());
+ // expected-error at -1 {{no matching function for call to 'as_bytes'}}
+ std::as_bytes(std::span<volatile std::string, (std::size_t)0>());
+ // expected-error at -1 {{no matching function for call to 'as_bytes'}}
+
+ std::as_bytes(std::span<const volatile int, 0>());
+ // expected-error at -1 {{no matching function for call to 'as_bytes'}}
+ std::as_bytes(std::span<const volatile long, 0>());
+ // expected-error at -1 {{no matching function for call to 'as_bytes'}}
+ std::as_bytes(std::span<const volatile double, 0>());
+ // expected-error at -1 {{no matching function for call to 'as_bytes'}}
+ std::as_bytes(std::span<const volatile A, 0>());
+ // expected-error at -1 {{no matching function for call to 'as_bytes'}}
+ std::as_bytes(std::span<const volatile std::string, (std::size_t)0>());
+ // expected-error at -1 {{no matching function for call to 'as_bytes'}}
+}
diff --git a/libcxx/test/std/containers/views/views.span/span.objectrep/as_writable_bytes.pass.cpp b/libcxx/test/std/containers/views/views.span/span.objectrep/as_writable_bytes.pass.cpp
index 40c6a581e9acf..be58e1f39f97b 100644
--- a/libcxx/test/std/containers/views/views.span/span.objectrep/as_writable_bytes.pass.cpp
+++ b/libcxx/test/std/containers/views/views.span/span.objectrep/as_writable_bytes.pass.cpp
@@ -9,12 +9,12 @@
// <span>
-// template <class ElementType, size_t Extent>
-// span<byte,
-// Extent == dynamic_extent
-// ? dynamic_extent
-// : sizeof(ElementType) * Extent>
+// template<class ElementType, size_t Extent>
+// span<byte, Extent == dynamic_extent ? dynamic_extent : sizeof(ElementType) * Extent>
// as_writable_bytes(span<ElementType, Extent> s) noexcept;
+//
+// Constraints:
+// is_const_v<ElementType> is false and is_volatile_v<ElementType> is false.
#include <cassert>
#include <cstddef>
diff --git a/libcxx/test/std/containers/views/views.span/span.objectrep/as_writable_bytes.verify.cpp b/libcxx/test/std/containers/views/views.span/span.objectrep/as_writable_bytes.verify.cpp
index 9d22641ab2687..12a2229e130a8 100644
--- a/libcxx/test/std/containers/views/views.span/span.objectrep/as_writable_bytes.verify.cpp
+++ b/libcxx/test/std/containers/views/views.span/span.objectrep/as_writable_bytes.verify.cpp
@@ -9,12 +9,12 @@
// <span>
-// template <class ElementType, size_t Extent>
-// span<byte,
-// Extent == dynamic_extent
-// ? dynamic_extent
-// : sizeof(ElementType) * Extent>
+// template<class ElementType, size_t Extent>
+// span<byte, Extent == dynamic_extent ? dynamic_extent : sizeof(ElementType) * Extent>
// as_writable_bytes(span<ElementType, Extent> s) noexcept;
+//
+// Constraints:
+// is_const_v<ElementType> is false and is_volatile_v<ElementType> is false.
#include <span>
#include <string>
@@ -37,6 +37,28 @@ void f() {
std::as_writable_bytes(std::span<const std::string>());
// expected-error at -1 {{no matching function for call to 'as_writable_bytes'}}
+ std::as_writable_bytes(std::span<volatile int>());
+ // expected-error at -1 {{no matching function for call to 'as_writable_bytes'}}
+ std::as_writable_bytes(std::span<volatile long>());
+ // expected-error at -1 {{no matching function for call to 'as_writable_bytes'}}
+ std::as_writable_bytes(std::span<volatile double>());
+ // expected-error at -1 {{no matching function for call to 'as_writable_bytes'}}
+ std::as_writable_bytes(std::span<volatile A>());
+ // expected-error at -1 {{no matching function for call to 'as_writable_bytes'}}
+ std::as_writable_bytes(std::span<volatile std::string>());
+ // expected-error at -1 {{no matching function for call to 'as_writable_bytes'}}
+
+ std::as_writable_bytes(std::span<const volatile int>());
+ // expected-error at -1 {{no matching function for call to 'as_writable_bytes'}}
+ std::as_writable_bytes(std::span<const volatile long>());
+ // expected-error at -1 {{no matching function for call to 'as_writable_bytes'}}
+ std::as_writable_bytes(std::span<const volatile double>());
+ // expected-error at -1 {{no matching function for call to 'as_writable_bytes'}}
+ std::as_writable_bytes(std::span<const volatile A>());
+ // expected-error at -1 {{no matching function for call to 'as_writable_bytes'}}
+ std::as_writable_bytes(std::span<const volatile std::string>());
+ // expected-error at -1 {{no matching function for call to 'as_writable_bytes'}}
+
std::as_writable_bytes(std::span<const int, 0>());
// expected-error at -1 {{no matching function for call to 'as_writable_bytes'}}
std::as_writable_bytes(std::span<const long, 0>());
@@ -48,8 +70,35 @@ void f() {
std::as_writable_bytes(std::span<const std::string, (std::size_t)0>());
// expected-error at -1 {{no matching function for call to 'as_writable_bytes'}}
+ std::as_writable_bytes(std::span<volatile int, 0>());
+ // expected-error at -1 {{no matching function for call to 'as_writable_bytes'}}
+ std::as_writable_bytes(std::span<volatile long, 0>());
+ // expected-error at -1 {{no matching function for call to 'as_writable_bytes'}}
+ std::as_writable_bytes(std::span<volatile double, 0>());
+ // expected-error at -1 {{no matching function for call to 'as_writable_bytes'}}
+ std::as_writable_bytes(std::span<volatile A, 0>());
+ // expected-error at -1 {{no matching function for call to 'as_writable_bytes'}}
+ std::as_writable_bytes(std::span<volatile std::string, (std::size_t)0>());
+ // expected-error at -1 {{no matching function for call to 'as_writable_bytes'}}
+
+ std::as_writable_bytes(std::span<const volatile int, 0>());
+ // expected-error at -1 {{no matching function for call to 'as_writable_bytes'}}
+ std::as_writable_bytes(std::span<const volatile long, 0>());
+ // expected-error at -1 {{no matching function for call to 'as_writable_bytes'}}
+ std::as_writable_bytes(std::span<const volatile double, 0>());
+ // expected-error at -1 {{no matching function for call to 'as_writable_bytes'}}
+ std::as_writable_bytes(std::span<const volatile A, 0>());
+ // expected-error at -1 {{no matching function for call to 'as_writable_bytes'}}
+ std::as_writable_bytes(std::span<const volatile std::string, (std::size_t)0>());
+ // expected-error at -1 {{no matching function for call to 'as_writable_bytes'}}
+
std::as_writable_bytes(std::span<const int>(iArr2, 1));
// expected-error at -1 {{no matching function for call to 'as_writable_bytes'}}
std::as_writable_bytes(std::span<const int, 1>(iArr2 + 5, 1));
// expected-error at -1 {{no matching function for call to 'as_writable_bytes'}}
+
+ std::as_writable_bytes(std::span<const volatile int>(iArr2, 1));
+ // expected-error at -1 {{no matching function for call to 'as_writable_bytes'}}
+ std::as_writable_bytes(std::span<const volatile int, 1>(iArr2 + 5, 1));
+ // expected-error at -1 {{no matching function for call to 'as_writable_bytes'}}
}
>From afa1b1c352f22fd917c06dfe0f53938be02e2808 Mon Sep 17 00:00:00 2001
From: eiytoq <eiytoq at outlook.com>
Date: Tue, 2 Jun 2026 11:22:11 +0800
Subject: [PATCH 2/4] upd Cxx2cIssues.csv
---
libcxx/docs/Status/Cxx2cIssues.csv | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libcxx/docs/Status/Cxx2cIssues.csv b/libcxx/docs/Status/Cxx2cIssues.csv
index 20b0b93eff753..6a836c0491bb6 100644
--- a/libcxx/docs/Status/Cxx2cIssues.csv
+++ b/libcxx/docs/Status/Cxx2cIssues.csv
@@ -157,7 +157,7 @@
"`LWG4137 <https://wg21.link/LWG4137>`__","Fix *Mandates*, *Preconditions*, and *Complexity* elements of [linalg] algorithms","2025-11 (Kona)","","","`#171313 <https://github.com/llvm/llvm-project/issues/171313>`__",""
"`LWG4166 <https://wg21.link/LWG4166>`__","``concat_view::end()`` should be more constrained in order to support noncopyable iterators","2025-11 (Kona)","|Complete|","23","`#171314 <https://github.com/llvm/llvm-project/issues/171314>`__",""
"`LWG4230 <https://wg21.link/LWG4230>`__","``simd<complex>::real/imag`` is overconstrained","2025-11 (Kona)","","","`#171316 <https://github.com/llvm/llvm-project/issues/171316>`__",""
-"`LWG4243 <https://wg21.link/LWG4243>`__","``as_bytes``/``as_writable_bytes`` is broken with ``span<volatile T>``","2025-11 (Kona)","","","`#171317 <https://github.com/llvm/llvm-project/issues/171317>`__",""
+"`LWG4243 <https://wg21.link/LWG4243>`__","``as_bytes``/``as_writable_bytes`` is broken with ``span<volatile T>``","2025-11 (Kona)","|Complete|","23","`#171317 <https://github.com/llvm/llvm-project/issues/171317>`__",""
"`LWG4251 <https://wg21.link/LWG4251>`__","Move assignment for ``indirect`` unnecessarily requires copy construction","2025-11 (Kona)","","","`#171318 <https://github.com/llvm/llvm-project/issues/171318>`__",""
"`LWG4253 <https://wg21.link/LWG4253>`__","``basic_const_iterator`` should provide ``iterator_type``","2025-11 (Kona)","","","`#171319 <https://github.com/llvm/llvm-project/issues/171319>`__",""
"`LWG4255 <https://wg21.link/LWG4255>`__","``move_only_function`` constructor should recognize empty ``copyable_function``\s","2025-11 (Kona)","","","`#171320 <https://github.com/llvm/llvm-project/issues/171320>`__",""
>From 6d647fac9e0d49e1049570f363205b20ff1540b5 Mon Sep 17 00:00:00 2001
From: eiytoq <eiytoq at outlook.com>
Date: Tue, 2 Jun 2026 12:24:42 +0800
Subject: [PATCH 3/4] test
---
.../span.objectrep/as_bytes.pass.cpp | 29 +++++++++++++++++++
.../span.objectrep/as_writable_bytes.pass.cpp | 11 +++++++
2 files changed, 40 insertions(+)
diff --git a/libcxx/test/std/containers/views/views.span/span.objectrep/as_bytes.pass.cpp b/libcxx/test/std/containers/views/views.span/span.objectrep/as_bytes.pass.cpp
index 5c5892bc2567c..f5ab1d46d4c85 100644
--- a/libcxx/test/std/containers/views/views.span/span.objectrep/as_bytes.pass.cpp
+++ b/libcxx/test/std/containers/views/views.span/span.objectrep/as_bytes.pass.cpp
@@ -23,6 +23,11 @@
#include "test_macros.h"
+template <class T, std::size_t Extent = std::dynamic_extent>
+constexpr bool hasAsBytes() {
+ return requires(std::span<T, Extent> s) { std::as_bytes(s); };
+}
+
template <typename Span>
void testRuntimeSpan(Span sp) {
ASSERT_NOEXCEPT(std::as_bytes(sp));
@@ -44,6 +49,30 @@ struct A {};
int iArr2[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
int main(int, char**) {
+ static_assert(hasAsBytes<int>());
+ static_assert(hasAsBytes<long>());
+ static_assert(hasAsBytes<double>());
+ static_assert(hasAsBytes<A>());
+ static_assert(hasAsBytes<std::string>());
+
+ static_assert(hasAsBytes<const int>());
+ static_assert(hasAsBytes<const long>());
+ static_assert(hasAsBytes<const double>());
+ static_assert(hasAsBytes<const A>());
+ static_assert(hasAsBytes<const std::string>());
+
+ static_assert(hasAsBytes<int, 0>());
+ static_assert(hasAsBytes<long, 0>());
+ static_assert(hasAsBytes<double, 0>());
+ static_assert(hasAsBytes<A, 0>());
+ static_assert(hasAsBytes<std::string, 0>());
+
+ static_assert(hasAsBytes<const int, 0>());
+ static_assert(hasAsBytes<const long, 0>());
+ static_assert(hasAsBytes<const double, 0>());
+ static_assert(hasAsBytes<const A, 0>());
+ static_assert(hasAsBytes<const std::string, 0>());
+
testRuntimeSpan(std::span<int>());
testRuntimeSpan(std::span<long>());
testRuntimeSpan(std::span<double>());
diff --git a/libcxx/test/std/containers/views/views.span/span.objectrep/as_writable_bytes.pass.cpp b/libcxx/test/std/containers/views/views.span/span.objectrep/as_writable_bytes.pass.cpp
index be58e1f39f97b..4dd7b5f51af49 100644
--- a/libcxx/test/std/containers/views/views.span/span.objectrep/as_writable_bytes.pass.cpp
+++ b/libcxx/test/std/containers/views/views.span/span.objectrep/as_writable_bytes.pass.cpp
@@ -23,6 +23,11 @@
#include "test_macros.h"
+template <class T, std::size_t Extent = std::dynamic_extent>
+constexpr bool hasAsWritableBytes() {
+ return requires(std::span<T, Extent> s) { std::as_writable_bytes(s); };
+}
+
template <typename Span>
void testRuntimeSpan(Span sp) {
ASSERT_NOEXCEPT(std::as_writable_bytes(sp));
@@ -44,6 +49,12 @@ struct A {};
int iArr2[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
int main(int, char**) {
+ static_assert(hasAsWritableBytes<int>());
+ static_assert(hasAsWritableBytes<long>());
+ static_assert(hasAsWritableBytes<double>());
+ static_assert(hasAsWritableBytes<A>());
+ static_assert(hasAsWritableBytes<std::string>());
+
testRuntimeSpan(std::span<int>());
testRuntimeSpan(std::span<long>());
testRuntimeSpan(std::span<double>());
>From 806c5623d47ce0f5e36506a9cadbcf42e2a494d0 Mon Sep 17 00:00:00 2001
From: eiytoq <eiytoq at outlook.com>
Date: Tue, 2 Jun 2026 16:21:18 +0800
Subject: [PATCH 4/4] test
---
.../span.objectrep/as_bytes.pass.cpp | 78 ++++++++-----
.../span.objectrep/as_bytes.verify.cpp | 70 ------------
.../span.objectrep/as_writable_bytes.pass.cpp | 60 ++++++++--
.../as_writable_bytes.verify.cpp | 104 ------------------
4 files changed, 104 insertions(+), 208 deletions(-)
delete mode 100644 libcxx/test/std/containers/views/views.span/span.objectrep/as_bytes.verify.cpp
delete mode 100644 libcxx/test/std/containers/views/views.span/span.objectrep/as_writable_bytes.verify.cpp
diff --git a/libcxx/test/std/containers/views/views.span/span.objectrep/as_bytes.pass.cpp b/libcxx/test/std/containers/views/views.span/span.objectrep/as_bytes.pass.cpp
index f5ab1d46d4c85..89eda480df688 100644
--- a/libcxx/test/std/containers/views/views.span/span.objectrep/as_bytes.pass.cpp
+++ b/libcxx/test/std/containers/views/views.span/span.objectrep/as_bytes.pass.cpp
@@ -24,9 +24,7 @@
#include "test_macros.h"
template <class T, std::size_t Extent = std::dynamic_extent>
-constexpr bool hasAsBytes() {
- return requires(std::span<T, Extent> s) { std::as_bytes(s); };
-}
+concept hasAsBytes = requires(std::span<T, Extent> s) { std::as_bytes(s); };
template <typename Span>
void testRuntimeSpan(Span sp) {
@@ -48,30 +46,58 @@ void testRuntimeSpan(Span sp) {
struct A {};
int iArr2[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
+void test_constraints() {
+ static_assert(hasAsBytes<int>);
+ static_assert(hasAsBytes<long>);
+ static_assert(hasAsBytes<double>);
+ static_assert(hasAsBytes<A>);
+ static_assert(hasAsBytes<std::string>);
+
+ static_assert(hasAsBytes<const int>);
+ static_assert(hasAsBytes<const long>);
+ static_assert(hasAsBytes<const double>);
+ static_assert(hasAsBytes<const A>);
+ static_assert(hasAsBytes<const std::string>);
+
+ static_assert(!hasAsBytes<volatile int>);
+ static_assert(!hasAsBytes<volatile long>);
+ static_assert(!hasAsBytes<volatile double>);
+ static_assert(!hasAsBytes<volatile A>);
+ static_assert(!hasAsBytes<volatile std::string>);
+
+ static_assert(!hasAsBytes<const volatile int>);
+ static_assert(!hasAsBytes<const volatile long>);
+ static_assert(!hasAsBytes<const volatile double>);
+ static_assert(!hasAsBytes<const volatile A>);
+ static_assert(!hasAsBytes<const volatile std::string>);
+
+ static_assert(hasAsBytes<int, 0>);
+ static_assert(hasAsBytes<long, 0>);
+ static_assert(hasAsBytes<double, 0>);
+ static_assert(hasAsBytes<A, 0>);
+ static_assert(hasAsBytes<std::string, 0>);
+
+ static_assert(hasAsBytes<const int, 0>);
+ static_assert(hasAsBytes<const long, 0>);
+ static_assert(hasAsBytes<const double, 0>);
+ static_assert(hasAsBytes<const A, 0>);
+ static_assert(hasAsBytes<const std::string, 0>);
+
+ static_assert(!hasAsBytes<volatile int, 0>);
+ static_assert(!hasAsBytes<volatile long, 0>);
+ static_assert(!hasAsBytes<volatile double, 0>);
+ static_assert(!hasAsBytes<volatile A, 0>);
+ static_assert(!hasAsBytes<volatile std::string, 0>);
+
+ static_assert(!hasAsBytes<const volatile int, 0>);
+ static_assert(!hasAsBytes<const volatile long, 0>);
+ static_assert(!hasAsBytes<const volatile double, 0>);
+ static_assert(!hasAsBytes<const volatile A, 0>);
+ static_assert(!hasAsBytes<const volatile std::string, 0>);
+}
+
int main(int, char**) {
- static_assert(hasAsBytes<int>());
- static_assert(hasAsBytes<long>());
- static_assert(hasAsBytes<double>());
- static_assert(hasAsBytes<A>());
- static_assert(hasAsBytes<std::string>());
-
- static_assert(hasAsBytes<const int>());
- static_assert(hasAsBytes<const long>());
- static_assert(hasAsBytes<const double>());
- static_assert(hasAsBytes<const A>());
- static_assert(hasAsBytes<const std::string>());
-
- static_assert(hasAsBytes<int, 0>());
- static_assert(hasAsBytes<long, 0>());
- static_assert(hasAsBytes<double, 0>());
- static_assert(hasAsBytes<A, 0>());
- static_assert(hasAsBytes<std::string, 0>());
-
- static_assert(hasAsBytes<const int, 0>());
- static_assert(hasAsBytes<const long, 0>());
- static_assert(hasAsBytes<const double, 0>());
- static_assert(hasAsBytes<const A, 0>());
- static_assert(hasAsBytes<const std::string, 0>());
+ test_constraints();
testRuntimeSpan(std::span<int>());
testRuntimeSpan(std::span<long>());
diff --git a/libcxx/test/std/containers/views/views.span/span.objectrep/as_bytes.verify.cpp b/libcxx/test/std/containers/views/views.span/span.objectrep/as_bytes.verify.cpp
deleted file mode 100644
index cdc830884f23c..0000000000000
--- a/libcxx/test/std/containers/views/views.span/span.objectrep/as_bytes.verify.cpp
+++ /dev/null
@@ -1,70 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-// UNSUPPORTED: c++03, c++11, c++14, c++17
-
-// <span>
-
-// template<class ElementType, size_t Extent>
-// span<const byte, Extent == dynamic_extent ? dynamic_extent : sizeof(ElementType) * Extent>
-// as_bytes(span<ElementType, Extent> s) noexcept;
-//
-// Constraints:
-// is_volatile_v<ElementType> is false.
-
-#include <span>
-#include <string>
-
-#include "test_macros.h"
-
-struct A {};
-
-void f() {
- std::as_bytes(std::span<volatile int>());
- // expected-error at -1 {{no matching function for call to 'as_bytes'}}
- std::as_bytes(std::span<volatile long>());
- // expected-error at -1 {{no matching function for call to 'as_bytes'}}
- std::as_bytes(std::span<volatile double>());
- // expected-error at -1 {{no matching function for call to 'as_bytes'}}
- std::as_bytes(std::span<volatile A>());
- // expected-error at -1 {{no matching function for call to 'as_bytes'}}
- std::as_bytes(std::span<volatile std::string>());
- // expected-error at -1 {{no matching function for call to 'as_bytes'}}
-
- std::as_bytes(std::span<const volatile int>());
- // expected-error at -1 {{no matching function for call to 'as_bytes'}}
- std::as_bytes(std::span<const volatile long>());
- // expected-error at -1 {{no matching function for call to 'as_bytes'}}
- std::as_bytes(std::span<const volatile double>());
- // expected-error at -1 {{no matching function for call to 'as_bytes'}}
- std::as_bytes(std::span<const volatile A>());
- // expected-error at -1 {{no matching function for call to 'as_bytes'}}
- std::as_bytes(std::span<const volatile std::string>());
- // expected-error at -1 {{no matching function for call to 'as_bytes'}}
-
- std::as_bytes(std::span<volatile int, 0>());
- // expected-error at -1 {{no matching function for call to 'as_bytes'}}
- std::as_bytes(std::span<volatile long, 0>());
- // expected-error at -1 {{no matching function for call to 'as_bytes'}}
- std::as_bytes(std::span<volatile double, 0>());
- // expected-error at -1 {{no matching function for call to 'as_bytes'}}
- std::as_bytes(std::span<volatile A, 0>());
- // expected-error at -1 {{no matching function for call to 'as_bytes'}}
- std::as_bytes(std::span<volatile std::string, (std::size_t)0>());
- // expected-error at -1 {{no matching function for call to 'as_bytes'}}
-
- std::as_bytes(std::span<const volatile int, 0>());
- // expected-error at -1 {{no matching function for call to 'as_bytes'}}
- std::as_bytes(std::span<const volatile long, 0>());
- // expected-error at -1 {{no matching function for call to 'as_bytes'}}
- std::as_bytes(std::span<const volatile double, 0>());
- // expected-error at -1 {{no matching function for call to 'as_bytes'}}
- std::as_bytes(std::span<const volatile A, 0>());
- // expected-error at -1 {{no matching function for call to 'as_bytes'}}
- std::as_bytes(std::span<const volatile std::string, (std::size_t)0>());
- // expected-error at -1 {{no matching function for call to 'as_bytes'}}
-}
diff --git a/libcxx/test/std/containers/views/views.span/span.objectrep/as_writable_bytes.pass.cpp b/libcxx/test/std/containers/views/views.span/span.objectrep/as_writable_bytes.pass.cpp
index 4dd7b5f51af49..3ad7cf754049a 100644
--- a/libcxx/test/std/containers/views/views.span/span.objectrep/as_writable_bytes.pass.cpp
+++ b/libcxx/test/std/containers/views/views.span/span.objectrep/as_writable_bytes.pass.cpp
@@ -24,9 +24,7 @@
#include "test_macros.h"
template <class T, std::size_t Extent = std::dynamic_extent>
-constexpr bool hasAsWritableBytes() {
- return requires(std::span<T, Extent> s) { std::as_writable_bytes(s); };
-}
+concept hasAsWritableBytes = requires(std::span<T, Extent> s) { std::as_writable_bytes(s); };
template <typename Span>
void testRuntimeSpan(Span sp) {
@@ -48,12 +46,58 @@ void testRuntimeSpan(Span sp) {
struct A {};
int iArr2[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
+void test_constraints() {
+ static_assert(hasAsWritableBytes<int>);
+ static_assert(hasAsWritableBytes<long>);
+ static_assert(hasAsWritableBytes<double>);
+ static_assert(hasAsWritableBytes<A>);
+ static_assert(hasAsWritableBytes<std::string>);
+
+ static_assert(!hasAsWritableBytes<const int>);
+ static_assert(!hasAsWritableBytes<const long>);
+ static_assert(!hasAsWritableBytes<const double>);
+ static_assert(!hasAsWritableBytes<const A>);
+ static_assert(!hasAsWritableBytes<const std::string>);
+
+ static_assert(!hasAsWritableBytes<volatile int>);
+ static_assert(!hasAsWritableBytes<volatile long>);
+ static_assert(!hasAsWritableBytes<volatile double>);
+ static_assert(!hasAsWritableBytes<volatile A>);
+ static_assert(!hasAsWritableBytes<volatile std::string>);
+
+ static_assert(!hasAsWritableBytes<const volatile int>);
+ static_assert(!hasAsWritableBytes<const volatile long>);
+ static_assert(!hasAsWritableBytes<const volatile double>);
+ static_assert(!hasAsWritableBytes<const volatile A>);
+ static_assert(!hasAsWritableBytes<const volatile std::string>);
+
+ static_assert(hasAsWritableBytes<int, 0>);
+ static_assert(hasAsWritableBytes<long, 0>);
+ static_assert(hasAsWritableBytes<double, 0>);
+ static_assert(hasAsWritableBytes<A, 0>);
+ static_assert(hasAsWritableBytes<std::string, 0>);
+
+ static_assert(!hasAsWritableBytes<const int, 0>);
+ static_assert(!hasAsWritableBytes<const long, 0>);
+ static_assert(!hasAsWritableBytes<const double, 0>);
+ static_assert(!hasAsWritableBytes<const A, 0>);
+ static_assert(!hasAsWritableBytes<const std::string, 0>);
+
+ static_assert(!hasAsWritableBytes<volatile int, 0>);
+ static_assert(!hasAsWritableBytes<volatile long, 0>);
+ static_assert(!hasAsWritableBytes<volatile double, 0>);
+ static_assert(!hasAsWritableBytes<volatile A, 0>);
+ static_assert(!hasAsWritableBytes<volatile std::string, 0>);
+
+ static_assert(!hasAsWritableBytes<const volatile int, 0>);
+ static_assert(!hasAsWritableBytes<const volatile long, 0>);
+ static_assert(!hasAsWritableBytes<const volatile double, 0>);
+ static_assert(!hasAsWritableBytes<const volatile A, 0>);
+ static_assert(!hasAsWritableBytes<const volatile std::string, 0>);
+}
+
int main(int, char**) {
- static_assert(hasAsWritableBytes<int>());
- static_assert(hasAsWritableBytes<long>());
- static_assert(hasAsWritableBytes<double>());
- static_assert(hasAsWritableBytes<A>());
- static_assert(hasAsWritableBytes<std::string>());
+ test_constraints();
testRuntimeSpan(std::span<int>());
testRuntimeSpan(std::span<long>());
diff --git a/libcxx/test/std/containers/views/views.span/span.objectrep/as_writable_bytes.verify.cpp b/libcxx/test/std/containers/views/views.span/span.objectrep/as_writable_bytes.verify.cpp
deleted file mode 100644
index 12a2229e130a8..0000000000000
--- a/libcxx/test/std/containers/views/views.span/span.objectrep/as_writable_bytes.verify.cpp
+++ /dev/null
@@ -1,104 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-// UNSUPPORTED: c++03, c++11, c++14, c++17
-
-// <span>
-
-// template<class ElementType, size_t Extent>
-// span<byte, Extent == dynamic_extent ? dynamic_extent : sizeof(ElementType) * Extent>
-// as_writable_bytes(span<ElementType, Extent> s) noexcept;
-//
-// Constraints:
-// is_const_v<ElementType> is false and is_volatile_v<ElementType> is false.
-
-#include <span>
-#include <string>
-
-#include "test_macros.h"
-
-const int iArr2[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
-
-struct A {};
-
-void f() {
- std::as_writable_bytes(std::span<const int>());
- // expected-error at -1 {{no matching function for call to 'as_writable_bytes'}}
- std::as_writable_bytes(std::span<const long>());
- // expected-error at -1 {{no matching function for call to 'as_writable_bytes'}}
- std::as_writable_bytes(std::span<const double>());
- // expected-error at -1 {{no matching function for call to 'as_writable_bytes'}}
- std::as_writable_bytes(std::span<const A>());
- // expected-error at -1 {{no matching function for call to 'as_writable_bytes'}}
- std::as_writable_bytes(std::span<const std::string>());
- // expected-error at -1 {{no matching function for call to 'as_writable_bytes'}}
-
- std::as_writable_bytes(std::span<volatile int>());
- // expected-error at -1 {{no matching function for call to 'as_writable_bytes'}}
- std::as_writable_bytes(std::span<volatile long>());
- // expected-error at -1 {{no matching function for call to 'as_writable_bytes'}}
- std::as_writable_bytes(std::span<volatile double>());
- // expected-error at -1 {{no matching function for call to 'as_writable_bytes'}}
- std::as_writable_bytes(std::span<volatile A>());
- // expected-error at -1 {{no matching function for call to 'as_writable_bytes'}}
- std::as_writable_bytes(std::span<volatile std::string>());
- // expected-error at -1 {{no matching function for call to 'as_writable_bytes'}}
-
- std::as_writable_bytes(std::span<const volatile int>());
- // expected-error at -1 {{no matching function for call to 'as_writable_bytes'}}
- std::as_writable_bytes(std::span<const volatile long>());
- // expected-error at -1 {{no matching function for call to 'as_writable_bytes'}}
- std::as_writable_bytes(std::span<const volatile double>());
- // expected-error at -1 {{no matching function for call to 'as_writable_bytes'}}
- std::as_writable_bytes(std::span<const volatile A>());
- // expected-error at -1 {{no matching function for call to 'as_writable_bytes'}}
- std::as_writable_bytes(std::span<const volatile std::string>());
- // expected-error at -1 {{no matching function for call to 'as_writable_bytes'}}
-
- std::as_writable_bytes(std::span<const int, 0>());
- // expected-error at -1 {{no matching function for call to 'as_writable_bytes'}}
- std::as_writable_bytes(std::span<const long, 0>());
- // expected-error at -1 {{no matching function for call to 'as_writable_bytes'}}
- std::as_writable_bytes(std::span<const double, 0>());
- // expected-error at -1 {{no matching function for call to 'as_writable_bytes'}}
- std::as_writable_bytes(std::span<const A, 0>());
- // expected-error at -1 {{no matching function for call to 'as_writable_bytes'}}
- std::as_writable_bytes(std::span<const std::string, (std::size_t)0>());
- // expected-error at -1 {{no matching function for call to 'as_writable_bytes'}}
-
- std::as_writable_bytes(std::span<volatile int, 0>());
- // expected-error at -1 {{no matching function for call to 'as_writable_bytes'}}
- std::as_writable_bytes(std::span<volatile long, 0>());
- // expected-error at -1 {{no matching function for call to 'as_writable_bytes'}}
- std::as_writable_bytes(std::span<volatile double, 0>());
- // expected-error at -1 {{no matching function for call to 'as_writable_bytes'}}
- std::as_writable_bytes(std::span<volatile A, 0>());
- // expected-error at -1 {{no matching function for call to 'as_writable_bytes'}}
- std::as_writable_bytes(std::span<volatile std::string, (std::size_t)0>());
- // expected-error at -1 {{no matching function for call to 'as_writable_bytes'}}
-
- std::as_writable_bytes(std::span<const volatile int, 0>());
- // expected-error at -1 {{no matching function for call to 'as_writable_bytes'}}
- std::as_writable_bytes(std::span<const volatile long, 0>());
- // expected-error at -1 {{no matching function for call to 'as_writable_bytes'}}
- std::as_writable_bytes(std::span<const volatile double, 0>());
- // expected-error at -1 {{no matching function for call to 'as_writable_bytes'}}
- std::as_writable_bytes(std::span<const volatile A, 0>());
- // expected-error at -1 {{no matching function for call to 'as_writable_bytes'}}
- std::as_writable_bytes(std::span<const volatile std::string, (std::size_t)0>());
- // expected-error at -1 {{no matching function for call to 'as_writable_bytes'}}
-
- std::as_writable_bytes(std::span<const int>(iArr2, 1));
- // expected-error at -1 {{no matching function for call to 'as_writable_bytes'}}
- std::as_writable_bytes(std::span<const int, 1>(iArr2 + 5, 1));
- // expected-error at -1 {{no matching function for call to 'as_writable_bytes'}}
-
- std::as_writable_bytes(std::span<const volatile int>(iArr2, 1));
- // expected-error at -1 {{no matching function for call to 'as_writable_bytes'}}
- std::as_writable_bytes(std::span<const volatile int, 1>(iArr2 + 5, 1));
- // expected-error at -1 {{no matching function for call to 'as_writable_bytes'}}
-}
More information about the libcxx-commits
mailing list