[libcxx-commits] [libcxx] [libc++] Use static_asserts for span::front() and span::back() when possible (PR #119381)
Louis Dionne via libcxx-commits
libcxx-commits at lists.llvm.org
Tue Dec 10 07:03:14 PST 2024
https://github.com/ldionne updated https://github.com/llvm/llvm-project/pull/119381
>From 47719dd54b3cf36aadcc1e8dc8a9742d82ab98ba Mon Sep 17 00:00:00 2001
From: Louis Dionne <ldionne.2 at gmail.com>
Date: Tue, 10 Dec 2024 08:51:38 -0500
Subject: [PATCH] [libc++] Use static_asserts for span::front() and
span::back() when possible
---
libcxx/include/span | 4 +--
.../views.span/span.elem/assert.back.pass.cpp | 23 ++++++-------
.../span.elem/assert.front.pass.cpp | 23 ++++++-------
.../views.span/span.elem/back.verify.cpp | 33 +++++++++++++++++++
.../views.span/span.elem/front.verify.cpp | 33 +++++++++++++++++++
5 files changed, 88 insertions(+), 28 deletions(-)
create mode 100644 libcxx/test/libcxx/containers/views/views.span/span.elem/back.verify.cpp
create mode 100644 libcxx/test/libcxx/containers/views/views.span/span.elem/front.verify.cpp
diff --git a/libcxx/include/span b/libcxx/include/span
index 2d43d1d1079e44..f05a0383a3c6a9 100644
--- a/libcxx/include/span
+++ b/libcxx/include/span
@@ -369,12 +369,12 @@ public:
# endif
_LIBCPP_HIDE_FROM_ABI constexpr reference front() const noexcept {
- _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "span<T, N>::front() on empty span");
+ static_assert(_Extent >= 1, "span<T, N>::front() on empty span");
return __data_[0];
}
_LIBCPP_HIDE_FROM_ABI constexpr reference back() const noexcept {
- _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "span<T, N>::back() on empty span");
+ static_assert(_Extent >= 1, "span<T, N>::back() on empty span");
return __data_[size() - 1];
}
diff --git a/libcxx/test/libcxx/containers/views/views.span/span.elem/assert.back.pass.cpp b/libcxx/test/libcxx/containers/views/views.span/span.elem/assert.back.pass.cpp
index ea98fe81ee2f8a..8d30f9659afe2a 100644
--- a/libcxx/test/libcxx/containers/views/views.span/span.elem/assert.back.pass.cpp
+++ b/libcxx/test/libcxx/containers/views/views.span/span.elem/assert.back.pass.cpp
@@ -5,6 +5,7 @@
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
+
// UNSUPPORTED: c++03, c++11, c++14, c++17
// <span>
@@ -23,17 +24,13 @@
#include "check_assertion.h"
int main(int, char**) {
- {
- std::array<int, 3> array{0, 1, 2};
- std::span<int> const s(array.data(), 0);
- TEST_LIBCPP_ASSERT_FAILURE(s.back(), "span<T>::back() on empty span");
- }
-
- {
- std::array<int, 3> array{0, 1, 2};
- std::span<int, 0> const s(array.data(), 0);
- TEST_LIBCPP_ASSERT_FAILURE(s.back(), "span<T, N>::back() on empty span");
- }
-
- return 0;
+ {
+ std::array<int, 3> array{0, 1, 2};
+ std::span<int> const s(array.data(), 0);
+ TEST_LIBCPP_ASSERT_FAILURE(s.back(), "span<T>::back() on empty span");
+ }
+
+ // back() on a span with a static extent is caught statically and tested in front.verify.cpp
+
+ return 0;
}
diff --git a/libcxx/test/libcxx/containers/views/views.span/span.elem/assert.front.pass.cpp b/libcxx/test/libcxx/containers/views/views.span/span.elem/assert.front.pass.cpp
index 2660ca1f90c141..6e5a4157ba6df2 100644
--- a/libcxx/test/libcxx/containers/views/views.span/span.elem/assert.front.pass.cpp
+++ b/libcxx/test/libcxx/containers/views/views.span/span.elem/assert.front.pass.cpp
@@ -5,6 +5,7 @@
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
+
// UNSUPPORTED: c++03, c++11, c++14, c++17
// <span>
@@ -23,17 +24,13 @@
#include "check_assertion.h"
int main(int, char**) {
- {
- std::array<int, 3> array{0, 1, 2};
- std::span<int> const s(array.data(), 0);
- TEST_LIBCPP_ASSERT_FAILURE(s.front(), "span<T>::front() on empty span");
- }
-
- {
- std::array<int, 3> array{0, 1, 2};
- std::span<int, 0> const s(array.data(), 0);
- TEST_LIBCPP_ASSERT_FAILURE(s.front(), "span<T, N>::front() on empty span");
- }
-
- return 0;
+ {
+ std::array<int, 3> array{0, 1, 2};
+ std::span<int> const s(array.data(), 0);
+ TEST_LIBCPP_ASSERT_FAILURE(s.front(), "span<T>::front() on empty span");
+ }
+
+ // front() on a span with a static extent is caught statically and tested in front.verify.cpp
+
+ return 0;
}
diff --git a/libcxx/test/libcxx/containers/views/views.span/span.elem/back.verify.cpp b/libcxx/test/libcxx/containers/views/views.span/span.elem/back.verify.cpp
new file mode 100644
index 00000000000000..3060db0402a5b8
--- /dev/null
+++ b/libcxx/test/libcxx/containers/views/views.span/span.elem/back.verify.cpp
@@ -0,0 +1,33 @@
+//===----------------------------------------------------------------------===//
+//
+// 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>
+//
+// constexpr reference back() const noexcept;
+
+// Make sure that accessing a statically-sized span out-of-bounds triggers a
+// compile-time error.
+
+#include <array>
+#include <span>
+
+int main(int, char**) {
+ std::array<int, 3> array{0, 1, 2};
+ {
+ std::span<int, 0> const s(array.data(), 0);
+ s.back(); // expected-error at span:* {{span<T, N>::back() on empty span}}
+ }
+ {
+ std::span<int, 3> const s(array.data(), 3);
+ s.back(); // nothing
+ }
+
+ return 0;
+}
diff --git a/libcxx/test/libcxx/containers/views/views.span/span.elem/front.verify.cpp b/libcxx/test/libcxx/containers/views/views.span/span.elem/front.verify.cpp
new file mode 100644
index 00000000000000..793eb70259f70a
--- /dev/null
+++ b/libcxx/test/libcxx/containers/views/views.span/span.elem/front.verify.cpp
@@ -0,0 +1,33 @@
+//===----------------------------------------------------------------------===//
+//
+// 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>
+//
+// constexpr reference front() const noexcept;
+
+// Make sure that accessing a statically-sized span out-of-bounds triggers a
+// compile-time error.
+
+#include <array>
+#include <span>
+
+int main(int, char**) {
+ std::array<int, 3> array{0, 1, 2};
+ {
+ std::span<int, 0> const s(array.data(), 0);
+ s.front(); // expected-error at span:* {{span<T, N>::front() on empty span}}
+ }
+ {
+ std::span<int, 3> const s(array.data(), 3);
+ s.front(); // nothing
+ }
+
+ return 0;
+}
More information about the libcxx-commits
mailing list