https://github.com/H-G-Hristov updated https://github.com/llvm/llvm-project/pull/74994
>From 6e26ca239c49e1b7d9ab72217db7339e92df163f Mon Sep 17 00:00:00 2001 From: Zingam <zin...@outlook.com> Date: Sun, 10 Dec 2023 14:16:02 +0200 Subject: [PATCH 01/15] [libc++][span] P2821R5: span.at() --- libcxx/include/span | 30 +++ .../views/views.span/span.elem/at.pass.cpp | 246 ++++++++++++++++++ .../views.span/span.elem/op_idx.pass.cpp | 1 - 3 files changed, 276 insertions(+), 1 deletion(-) create mode 100644 libcxx/test/std/containers/views/views.span/span.elem/at.pass.cpp diff --git a/libcxx/include/span b/libcxx/include/span index 69b0a2875e26cc..b015d7cf1c15b6 100644 --- a/libcxx/include/span +++ b/libcxx/include/span @@ -92,6 +92,7 @@ public: // [span.elem], span element access constexpr reference operator[](size_type idx) const; + constexpr reference at(size_type idx) const; // since C++26 constexpr reference front() const; constexpr reference back() const; constexpr pointer data() const noexcept; @@ -146,6 +147,9 @@ template<class R> #include <__utility/forward.h> #include <array> // for array #include <cstddef> // for byte +#if _LIBCPP_STD_VER >= 26 +# include <stdexcept> +#endif #include <version> // standard-mandated includes @@ -343,6 +347,15 @@ public: return __data_[__idx]; } +# if _LIBCPP_STD_VER >= 26 + _LIBCPP_HIDE_FROM_ABI constexpr reference at(size_type __idx) const { + if (__idx >= size()) { + __throw_out_of_range(); + } + return *(data() + __idx); + } +# endif + _LIBCPP_INLINE_VISIBILITY constexpr reference front() const noexcept { _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "span<T, N>::front() on empty span"); @@ -383,6 +396,10 @@ public: private: pointer __data_; + +# if _LIBCPP_STD_VER >= 26 + _LIBCPP_NORETURN _LIBCPP_HIDE_FROM_ABI void __throw_out_of_range() const { std::__throw_out_of_range("span"); } +# endif }; @@ -510,6 +527,15 @@ public: return __data_[__idx]; } +# if _LIBCPP_STD_VER >= 26 + _LIBCPP_HIDE_FROM_ABI constexpr reference at(size_type __idx) const { + if (__idx >= size()) { + __throw_out_of_range(); + } + return *(data() + __idx); + } +# endif + _LIBCPP_INLINE_VISIBILITY constexpr reference front() const noexcept { _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "span<T>::front() on empty span"); @@ -552,6 +578,10 @@ public: private: pointer __data_; size_type __size_; + +# if _LIBCPP_STD_VER >= 26 + _LIBCPP_NORETURN _LIBCPP_HIDE_FROM_ABI void __throw_out_of_range() const { std::__throw_out_of_range("span"); } +# endif }; template <class _Tp, size_t _Extent> diff --git a/libcxx/test/std/containers/views/views.span/span.elem/at.pass.cpp b/libcxx/test/std/containers/views/views.span/span.elem/at.pass.cpp new file mode 100644 index 00000000000000..2a9ce2baeec1a5 --- /dev/null +++ b/libcxx/test/std/containers/views/views.span/span.elem/at.pass.cpp @@ -0,0 +1,246 @@ +//===----------------------------------------------------------------------===// +// +// 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, c++20, c++23 + +// <span> + +// constexpr reference at(size_type idx) const; // since C++26 + +#include <array> +#include <cassert> +#include <concepts> +#include <span> +#include <stdexcept> +#include <vector> + +#include "test_macros.h" + +// template <typename Span> +// constexpr bool testConstexprSpan(Span sp, std::size_t idx) +// { +// LIBCPP_ASSERT(noexcept(sp[idx])); + +// typename Span::reference r1 = sp[idx]; +// typename Span::reference r2 = *(sp.data() + idx); + +// return r1 == r2; +// } + +// template <typename Span> +// void testRuntimeSpan(Span sp, std::size_t idx) +// { +// LIBCPP_ASSERT(noexcept(sp[idx])); + +// typename Span::reference r1 = sp[idx]; +// typename Span::reference r2 = *(sp.data() + idx); + +// assert(r1 == r2); +// } + +// struct A{}; +// constexpr int iArr1[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; +// int iArr2[] = {10, 11, 12, 13, 14, 15, 16, 17, 18, 19}; + +// int main(int, char**) +// { +// static_assert(testConstexprSpan(std::span<const int>(iArr1, 1), 0), ""); + +// static_assert(testConstexprSpan(std::span<const int>(iArr1, 2), 0), ""); +// static_assert(testConstexprSpan(std::span<const int>(iArr1, 2), 1), ""); + +// static_assert(testConstexprSpan(std::span<const int>(iArr1, 3), 0), ""); +// static_assert(testConstexprSpan(std::span<const int>(iArr1, 3), 1), ""); +// static_assert(testConstexprSpan(std::span<const int>(iArr1, 3), 2), ""); + +// static_assert(testConstexprSpan(std::span<const int>(iArr1, 4), 0), ""); +// static_assert(testConstexprSpan(std::span<const int>(iArr1, 4), 1), ""); +// static_assert(testConstexprSpan(std::span<const int>(iArr1, 4), 2), ""); +// static_assert(testConstexprSpan(std::span<const int>(iArr1, 4), 3), ""); + +// static_assert(testConstexprSpan(std::span<const int, 1>(iArr1, 1), 0), ""); + +// static_assert(testConstexprSpan(std::span<const int, 2>(iArr1, 2), 0), ""); +// static_assert(testConstexprSpan(std::span<const int, 2>(iArr1, 2), 1), ""); + +// static_assert(testConstexprSpan(std::span<const int, 3>(iArr1, 3), 0), ""); +// static_assert(testConstexprSpan(std::span<const int, 3>(iArr1, 3), 1), ""); +// static_assert(testConstexprSpan(std::span<const int, 3>(iArr1, 3), 2), ""); + +// static_assert(testConstexprSpan(std::span<const int, 4>(iArr1, 4), 0), ""); +// static_assert(testConstexprSpan(std::span<const int, 4>(iArr1, 4), 1), ""); +// static_assert(testConstexprSpan(std::span<const int, 4>(iArr1, 4), 2), ""); +// static_assert(testConstexprSpan(std::span<const int, 4>(iArr1, 4), 3), ""); + +// testRuntimeSpan(std::span<int>(iArr2, 1), 0); + +// testRuntimeSpan(std::span<int>(iArr2, 2), 0); +// testRuntimeSpan(std::span<int>(iArr2, 2), 1); + +// testRuntimeSpan(std::span<int>(iArr2, 3), 0); +// testRuntimeSpan(std::span<int>(iArr2, 3), 1); +// testRuntimeSpan(std::span<int>(iArr2, 3), 2); + +// testRuntimeSpan(std::span<int>(iArr2, 4), 0); +// testRuntimeSpan(std::span<int>(iArr2, 4), 1); +// testRuntimeSpan(std::span<int>(iArr2, 4), 2); +// testRuntimeSpan(std::span<int>(iArr2, 4), 3); + +// testRuntimeSpan(std::span<int, 1>(iArr2, 1), 0); + +// testRuntimeSpan(std::span<int, 2>(iArr2, 2), 0); +// testRuntimeSpan(std::span<int, 2>(iArr2, 2), 1); + +// testRuntimeSpan(std::span<int, 3>(iArr2, 3), 0); +// testRuntimeSpan(std::span<int, 3>(iArr2, 3), 1); +// testRuntimeSpan(std::span<int, 3>(iArr2, 3), 2); + +// testRuntimeSpan(std::span<int, 4>(iArr2, 4), 0); +// testRuntimeSpan(std::span<int, 4>(iArr2, 4), 1); +// testRuntimeSpan(std::span<int, 4>(iArr2, 4), 2); +// testRuntimeSpan(std::span<int, 4>(iArr2, 4), 3); + +// std::string s; +// testRuntimeSpan(std::span<std::string> (&s, 1), 0); +// testRuntimeSpan(std::span<std::string, 1>(&s, 1), 0); + +// return 0; +// } + +constexpr bool test() { + // { + // typedef double T; + // typedef std::array<T, 3> C; + // C const c = {1, 2, 3.5}; + // typename C::const_reference r1 = c.at(0); + // assert(r1 == 1); + + // typename C::const_reference r2 = c.at(2); + // assert(r2 == 3.5); + // } + + const auto testSpan = + [](auto span, int idx, int expectedValue) { + { + std::same_as<decltype(span)::reference> elem = span.at(idx); + assert(elem == expectedValue); + } + + { + std::same_as<decltype(span)::const_reference> elem = std::as_const(span).at(idx); + assert(elem == expectedValue); + } + } + + // With static extent + + std::array arr{0, 1, 2, 3, 4, 5, 9084}; + std::span arrSpan{ar}; + + assert(std::dynamic_extent != arrSpan.extent); + + testSpan(arrSpan, 0, 0); + testSpan(arrSpan, 1, 1); + testSpan(arrSpan, 5, 9084); + + { + std::same_as<decltype(arrSpan)::reference> arrElem = arrSpan.at(1); + assert(arrElem == 1); + } + + { + std::same_as<decltype(arrSpan)::const_reference> arrElem = std::as_const(arrSpan).at(1); + assert(arrElem == 1); + } + + // With dynamic extent + + std::vector vec{0, 1, 2, 3, 4, 5}; + std::span vecSpan{vec}; + + assert(std::dynamic_extent == vecSpan.extent) + + { + std::same_as<decltype(vecSpan)::reference> vecElem = vecSpan.at(1); + assert(vec_elem == 1); + } + + { + std::same_as<decltype(vecSpan)::reference> vecElem = std::as_const(vecSpan).at(1); + assert(vec_elem == 1); + } + + return true; +} + +void test_exceptions() { +#ifndef TEST_HAS_NO_EXCEPTIONS + // With static extent + { + const std::array arr{1, 2, 3, 4}; + + try { + TEST_IGNORE_NODISCARD arr.at(4); + assert(false); + } catch (std::out_of_range const&) { + // pass + } catch (...) { + assert(false); + } + } + + { + const std::array<int, 0> arr{}; + + try { + TEST_IGNORE_NODISCARD arr.at(0); + assert(false); + } catch (std::out_of_range const&) { + // pass + } catch (...) { + assert(false); + } + } + + // With dynamic extent + + { + const std::vector vec{1, 2, 3, 4}; + + try { + TEST_IGNORE_NODISCARD vec.at(4); + assert(false); + } catch (std::out_of_range const&) { + // pass + } catch (...) { + assert(false); + } + } + + { + const std::vector<int> vec{}; + + try { + TEST_IGNORE_NODISCARD vec.at(0); + assert(false); + } catch (std::out_of_range const&) { + // pass + } catch (...) { + assert(false); + } + } +#endif +} + +int main(int, char**) { + test(); + test_exceptions(); + static_assert(test()); + + return 0; +} \ No newline at end of file diff --git a/libcxx/test/std/containers/views/views.span/span.elem/op_idx.pass.cpp b/libcxx/test/std/containers/views/views.span/span.elem/op_idx.pass.cpp index e46fd267ef5cc5..b7f36c57585881 100644 --- a/libcxx/test/std/containers/views/views.span/span.elem/op_idx.pass.cpp +++ b/libcxx/test/std/containers/views/views.span/span.elem/op_idx.pass.cpp @@ -41,7 +41,6 @@ void testRuntimeSpan(Span sp, std::size_t idx) assert(r1 == r2); } -struct A{}; constexpr int iArr1[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; int iArr2[] = {10, 11, 12, 13, 14, 15, 16, 17, 18, 19}; >From ed7ee83fa9b10a37295d050e1edc538b05a22504 Mon Sep 17 00:00:00 2001 From: Zingam <zin...@outlook.com> Date: Sun, 10 Dec 2023 16:03:08 +0200 Subject: [PATCH 02/15] Cleanup tests --- libcxx/docs/ReleaseNotes/18.rst | 1 + libcxx/docs/Status/Cxx2cPapers.csv | 2 +- .../views/views.span/span.elem/at.pass.cpp | 139 ++---------------- z_libcxx-dev-tools | 1 + 4 files changed, 18 insertions(+), 125 deletions(-) create mode 160000 z_libcxx-dev-tools diff --git a/libcxx/docs/ReleaseNotes/18.rst b/libcxx/docs/ReleaseNotes/18.rst index abefe4c28ca958..05542f034e63b4 100644 --- a/libcxx/docs/ReleaseNotes/18.rst +++ b/libcxx/docs/ReleaseNotes/18.rst @@ -54,6 +54,7 @@ Implemented Papers - P2871R3 - Remove Deprecated Unicode Conversion Facets from C++26 - P2870R3 - Remove basic_string::reserve() - P2909R4 - Fix formatting of code units as integers (Dude, where’s my ``char``?) +- P2821R5 - span.at() Improvements and New Features diff --git a/libcxx/docs/Status/Cxx2cPapers.csv b/libcxx/docs/Status/Cxx2cPapers.csv index 1d071b7ebcb4a7..b97dc44795ac82 100644 --- a/libcxx/docs/Status/Cxx2cPapers.csv +++ b/libcxx/docs/Status/Cxx2cPapers.csv @@ -35,7 +35,7 @@ "`P2909R4 <https://wg21.link/P2909R4>`__","LWG","Fix formatting of code units as integers (Dude, where’s my ``char``?)","Kona November 2023","|Complete|","18.0","|format| |DR|" "`P0952R2 <https://wg21.link/P0952R2>`__","LWG","A new specification for ``std::generate_canonical``","Kona November 2023","","","" "`P2447R6 <https://wg21.link/P2447R6>`__","LWG","``std::span`` over an initializer list","Kona November 2023","","","" -"`P2821R5 <https://wg21.link/P2821R5>`__","LWG","``span.at()``","Kona November 2023","","","" +"`P2821R5 <https://wg21.link/P2821R5>`__","LWG","``span.at()``","Kona November 2023","|Complete|","18.0","" "`P2868R3 <https://wg21.link/P2868R3>`__","LWG","Remove Deprecated ``std::allocator`` Typedef From C++26","Kona November 2023","","","" "`P2870R3 <https://wg21.link/P2870R3>`__","LWG","Remove ``basic_string::reserve()`` From C++26","Kona November 2023","|Complete|","18.0","" "`P2871R3 <https://wg21.link/P2871R3>`__","LWG","Remove Deprecated Unicode Conversion Facets from C++26","Kona November 2023","|Complete|","18.0","" diff --git a/libcxx/test/std/containers/views/views.span/span.elem/at.pass.cpp b/libcxx/test/std/containers/views/views.span/span.elem/at.pass.cpp index 2a9ce2baeec1a5..8daaa6bb6fa127 100644 --- a/libcxx/test/std/containers/views/views.span/span.elem/at.pass.cpp +++ b/libcxx/test/std/containers/views/views.span/span.elem/at.pass.cpp @@ -17,144 +17,35 @@ #include <concepts> #include <span> #include <stdexcept> +#include <utility> #include <vector> #include "test_macros.h" -// template <typename Span> -// constexpr bool testConstexprSpan(Span sp, std::size_t idx) -// { -// LIBCPP_ASSERT(noexcept(sp[idx])); - -// typename Span::reference r1 = sp[idx]; -// typename Span::reference r2 = *(sp.data() + idx); - -// return r1 == r2; -// } - -// template <typename Span> -// void testRuntimeSpan(Span sp, std::size_t idx) -// { -// LIBCPP_ASSERT(noexcept(sp[idx])); - -// typename Span::reference r1 = sp[idx]; -// typename Span::reference r2 = *(sp.data() + idx); - -// assert(r1 == r2); -// } - -// struct A{}; -// constexpr int iArr1[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; -// int iArr2[] = {10, 11, 12, 13, 14, 15, 16, 17, 18, 19}; - -// int main(int, char**) -// { -// static_assert(testConstexprSpan(std::span<const int>(iArr1, 1), 0), ""); - -// static_assert(testConstexprSpan(std::span<const int>(iArr1, 2), 0), ""); -// static_assert(testConstexprSpan(std::span<const int>(iArr1, 2), 1), ""); - -// static_assert(testConstexprSpan(std::span<const int>(iArr1, 3), 0), ""); -// static_assert(testConstexprSpan(std::span<const int>(iArr1, 3), 1), ""); -// static_assert(testConstexprSpan(std::span<const int>(iArr1, 3), 2), ""); - -// static_assert(testConstexprSpan(std::span<const int>(iArr1, 4), 0), ""); -// static_assert(testConstexprSpan(std::span<const int>(iArr1, 4), 1), ""); -// static_assert(testConstexprSpan(std::span<const int>(iArr1, 4), 2), ""); -// static_assert(testConstexprSpan(std::span<const int>(iArr1, 4), 3), ""); - -// static_assert(testConstexprSpan(std::span<const int, 1>(iArr1, 1), 0), ""); - -// static_assert(testConstexprSpan(std::span<const int, 2>(iArr1, 2), 0), ""); -// static_assert(testConstexprSpan(std::span<const int, 2>(iArr1, 2), 1), ""); - -// static_assert(testConstexprSpan(std::span<const int, 3>(iArr1, 3), 0), ""); -// static_assert(testConstexprSpan(std::span<const int, 3>(iArr1, 3), 1), ""); -// static_assert(testConstexprSpan(std::span<const int, 3>(iArr1, 3), 2), ""); - -// static_assert(testConstexprSpan(std::span<const int, 4>(iArr1, 4), 0), ""); -// static_assert(testConstexprSpan(std::span<const int, 4>(iArr1, 4), 1), ""); -// static_assert(testConstexprSpan(std::span<const int, 4>(iArr1, 4), 2), ""); -// static_assert(testConstexprSpan(std::span<const int, 4>(iArr1, 4), 3), ""); - -// testRuntimeSpan(std::span<int>(iArr2, 1), 0); - -// testRuntimeSpan(std::span<int>(iArr2, 2), 0); -// testRuntimeSpan(std::span<int>(iArr2, 2), 1); - -// testRuntimeSpan(std::span<int>(iArr2, 3), 0); -// testRuntimeSpan(std::span<int>(iArr2, 3), 1); -// testRuntimeSpan(std::span<int>(iArr2, 3), 2); - -// testRuntimeSpan(std::span<int>(iArr2, 4), 0); -// testRuntimeSpan(std::span<int>(iArr2, 4), 1); -// testRuntimeSpan(std::span<int>(iArr2, 4), 2); -// testRuntimeSpan(std::span<int>(iArr2, 4), 3); - -// testRuntimeSpan(std::span<int, 1>(iArr2, 1), 0); - -// testRuntimeSpan(std::span<int, 2>(iArr2, 2), 0); -// testRuntimeSpan(std::span<int, 2>(iArr2, 2), 1); - -// testRuntimeSpan(std::span<int, 3>(iArr2, 3), 0); -// testRuntimeSpan(std::span<int, 3>(iArr2, 3), 1); -// testRuntimeSpan(std::span<int, 3>(iArr2, 3), 2); - -// testRuntimeSpan(std::span<int, 4>(iArr2, 4), 0); -// testRuntimeSpan(std::span<int, 4>(iArr2, 4), 1); -// testRuntimeSpan(std::span<int, 4>(iArr2, 4), 2); -// testRuntimeSpan(std::span<int, 4>(iArr2, 4), 3); - -// std::string s; -// testRuntimeSpan(std::span<std::string> (&s, 1), 0); -// testRuntimeSpan(std::span<std::string, 1>(&s, 1), 0); - -// return 0; -// } +constexpr void testSpan(auto span, int idx, int expectedValue) { + std::same_as<typename decltype(span)::reference> decltype(auto) elem = span.at(idx); + assert(elem == expectedValue); +} constexpr bool test() { - // { - // typedef double T; - // typedef std::array<T, 3> C; - // C const c = {1, 2, 3.5}; - // typename C::const_reference r1 = c.at(0); - // assert(r1 == 1); - - // typename C::const_reference r2 = c.at(2); - // assert(r2 == 3.5); - // } - - const auto testSpan = - [](auto span, int idx, int expectedValue) { - { - std::same_as<decltype(span)::reference> elem = span.at(idx); - assert(elem == expectedValue); - } - - { - std::same_as<decltype(span)::const_reference> elem = std::as_const(span).at(idx); - assert(elem == expectedValue); - } - } - // With static extent std::array arr{0, 1, 2, 3, 4, 5, 9084}; - std::span arrSpan{ar}; + std::span arrSpan{arr}; assert(std::dynamic_extent != arrSpan.extent); testSpan(arrSpan, 0, 0); testSpan(arrSpan, 1, 1); - testSpan(arrSpan, 5, 9084); + testSpan(arrSpan, 6, 9084); { - std::same_as<decltype(arrSpan)::reference> arrElem = arrSpan.at(1); + std::same_as<typename decltype(arrSpan)::reference> decltype(auto) arrElem = arrSpan.at(1); assert(arrElem == 1); } { - std::same_as<decltype(arrSpan)::const_reference> arrElem = std::as_const(arrSpan).at(1); + std::same_as<typename decltype(arrSpan)::reference> decltype(auto) arrElem = std::as_const(arrSpan).at(1); assert(arrElem == 1); } @@ -162,17 +53,17 @@ constexpr bool test() { std::vector vec{0, 1, 2, 3, 4, 5}; std::span vecSpan{vec}; - - assert(std::dynamic_extent == vecSpan.extent) + + assert(std::dynamic_extent == vecSpan.extent); { - std::same_as<decltype(vecSpan)::reference> vecElem = vecSpan.at(1); - assert(vec_elem == 1); + std::same_as<typename decltype(vecSpan)::reference> decltype(auto) vecElem = vecSpan.at(1); + assert(vecElem == 1); } { - std::same_as<decltype(vecSpan)::reference> vecElem = std::as_const(vecSpan).at(1); - assert(vec_elem == 1); + std::same_as<typename decltype(vecSpan)::reference> decltype(auto) vecElem = std::as_const(vecSpan).at(1); + assert(vecElem == 1); } return true; diff --git a/z_libcxx-dev-tools b/z_libcxx-dev-tools new file mode 160000 index 00000000000000..229818e01844e2 --- /dev/null +++ b/z_libcxx-dev-tools @@ -0,0 +1 @@ +Subproject commit 229818e01844e2cad56818bf06703600071848c0 >From f02f8a0e8667fec1e5b5e16a13a9b5e52c52e58d Mon Sep 17 00:00:00 2001 From: Zingam <zin...@outlook.com> Date: Sun, 10 Dec 2023 18:25:42 +0200 Subject: [PATCH 03/15] Removed bad file --- z_libcxx-dev-tools | 1 - 1 file changed, 1 deletion(-) delete mode 160000 z_libcxx-dev-tools diff --git a/z_libcxx-dev-tools b/z_libcxx-dev-tools deleted file mode 160000 index 229818e01844e2..00000000000000 --- a/z_libcxx-dev-tools +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 229818e01844e2cad56818bf06703600071848c0 >From e8e8457304f87e4780144fe3bc3bf918c335b726 Mon Sep 17 00:00:00 2001 From: Zingam <zin...@outlook.com> Date: Sun, 10 Dec 2023 18:31:46 +0200 Subject: [PATCH 04/15] Fixed test_exceptions --- .../views/views.span/span.elem/at.pass.cpp | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/libcxx/test/std/containers/views/views.span/span.elem/at.pass.cpp b/libcxx/test/std/containers/views/views.span/span.elem/at.pass.cpp index 8daaa6bb6fa127..68c2fca62a67cf 100644 --- a/libcxx/test/std/containers/views/views.span/span.elem/at.pass.cpp +++ b/libcxx/test/std/containers/views/views.span/span.elem/at.pass.cpp @@ -73,10 +73,11 @@ void test_exceptions() { #ifndef TEST_HAS_NO_EXCEPTIONS // With static extent { - const std::array arr{1, 2, 3, 4}; + std::array arr{1, 2, 3, 4}; + const std::span arrSpan{arr}; try { - TEST_IGNORE_NODISCARD arr.at(4); + TEST_IGNORE_NODISCARD arrSpan.at(4); assert(false); } catch (std::out_of_range const&) { // pass @@ -86,10 +87,11 @@ void test_exceptions() { } { - const std::array<int, 0> arr{}; + std::array<int, 0> arr{}; + const std::span arrSpan{arr}; try { - TEST_IGNORE_NODISCARD arr.at(0); + TEST_IGNORE_NODISCARD arrSpan.at(0); assert(false); } catch (std::out_of_range const&) { // pass @@ -101,7 +103,8 @@ void test_exceptions() { // With dynamic extent { - const std::vector vec{1, 2, 3, 4}; + std::vector vec{1, 2, 3, 4}; + const std::span vecSpan{vec}; try { TEST_IGNORE_NODISCARD vec.at(4); @@ -114,7 +117,8 @@ void test_exceptions() { } { - const std::vector<int> vec{}; + std::vector<int> vec{}; + const std::span vecSpan{vec}; try { TEST_IGNORE_NODISCARD vec.at(0); @@ -134,4 +138,4 @@ int main(int, char**) { static_assert(test()); return 0; -} \ No newline at end of file +} >From 9340bc0c3be951e6431926ebb8c7f3a5f71a7d1c Mon Sep 17 00:00:00 2001 From: Zingam <zin...@outlook.com> Date: Sun, 10 Dec 2023 19:12:42 +0200 Subject: [PATCH 05/15] Fixed tests --- .../views/views.span/span.elem/at.pass.cpp | 43 ++++++++----------- 1 file changed, 18 insertions(+), 25 deletions(-) diff --git a/libcxx/test/std/containers/views/views.span/span.elem/at.pass.cpp b/libcxx/test/std/containers/views/views.span/span.elem/at.pass.cpp index 68c2fca62a67cf..f3d6fbd9fb28aa 100644 --- a/libcxx/test/std/containers/views/views.span/span.elem/at.pass.cpp +++ b/libcxx/test/std/containers/views/views.span/span.elem/at.pass.cpp @@ -23,8 +23,17 @@ #include "test_macros.h" constexpr void testSpan(auto span, int idx, int expectedValue) { - std::same_as<typename decltype(span)::reference> decltype(auto) elem = span.at(idx); - assert(elem == expectedValue); + // non-const + { + std::same_as<typename decltype(span)::reference> decltype(auto) elem = span.at(idx); + assert(elem == expectedValue); + } + + // const + { + std::same_as<typename decltype(span)::reference> decltype(auto) elem = std::as_const(span).at(idx); + assert(elem == expectedValue); + } } constexpr bool test() { @@ -39,32 +48,16 @@ constexpr bool test() { testSpan(arrSpan, 1, 1); testSpan(arrSpan, 6, 9084); - { - std::same_as<typename decltype(arrSpan)::reference> decltype(auto) arrElem = arrSpan.at(1); - assert(arrElem == 1); - } - - { - std::same_as<typename decltype(arrSpan)::reference> decltype(auto) arrElem = std::as_const(arrSpan).at(1); - assert(arrElem == 1); - } - // With dynamic extent - std::vector vec{0, 1, 2, 3, 4, 5}; + std::vector vec{0, 1, 2, 3, 4, 5, 9084}; std::span vecSpan{vec}; assert(std::dynamic_extent == vecSpan.extent); - { - std::same_as<typename decltype(vecSpan)::reference> decltype(auto) vecElem = vecSpan.at(1); - assert(vecElem == 1); - } - - { - std::same_as<typename decltype(vecSpan)::reference> decltype(auto) vecElem = std::as_const(vecSpan).at(1); - assert(vecElem == 1); - } + testSpan(vecSpan, 0, 0); + testSpan(vecSpan, 1, 1); + testSpan(vecSpan, 6, 9084); return true; } @@ -77,7 +70,7 @@ void test_exceptions() { const std::span arrSpan{arr}; try { - TEST_IGNORE_NODISCARD arrSpan.at(4); + TEST_IGNORE_NODISCARD arrSpan.at(arr.size() + 1); assert(false); } catch (std::out_of_range const&) { // pass @@ -107,7 +100,7 @@ void test_exceptions() { const std::span vecSpan{vec}; try { - TEST_IGNORE_NODISCARD vec.at(4); + TEST_IGNORE_NODISCARD vecSpan.at(vec.size() + 1); assert(false); } catch (std::out_of_range const&) { // pass @@ -121,7 +114,7 @@ void test_exceptions() { const std::span vecSpan{vec}; try { - TEST_IGNORE_NODISCARD vec.at(0); + TEST_IGNORE_NODISCARD vecSpan.at(0); assert(false); } catch (std::out_of_range const&) { // pass >From 431b502a10e9e60462a05de37db3e55cc0ff1e7e Mon Sep 17 00:00:00 2001 From: Zingam <zin...@outlook.com> Date: Sun, 10 Dec 2023 19:19:00 +0200 Subject: [PATCH 06/15] Minor tweaks --- .../views/views.span/span.elem/at.pass.cpp | 34 ++++++++++--------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/libcxx/test/std/containers/views/views.span/span.elem/at.pass.cpp b/libcxx/test/std/containers/views/views.span/span.elem/at.pass.cpp index f3d6fbd9fb28aa..75a45171185cf3 100644 --- a/libcxx/test/std/containers/views/views.span/span.elem/at.pass.cpp +++ b/libcxx/test/std/containers/views/views.span/span.elem/at.pass.cpp @@ -22,7 +22,7 @@ #include "test_macros.h" -constexpr void testSpan(auto span, int idx, int expectedValue) { +constexpr void testSpanAt(auto span, int idx, int expectedValue) { // non-const { std::same_as<typename decltype(span)::reference> decltype(auto) elem = span.at(idx); @@ -38,26 +38,28 @@ constexpr void testSpan(auto span, int idx, int expectedValue) { constexpr bool test() { // With static extent + { + std::array arr{0, 1, 2, 3, 4, 5, 9084}; + std::span arrSpan{arr}; - std::array arr{0, 1, 2, 3, 4, 5, 9084}; - std::span arrSpan{arr}; - - assert(std::dynamic_extent != arrSpan.extent); + assert(std::dynamic_extent != arrSpan.extent); - testSpan(arrSpan, 0, 0); - testSpan(arrSpan, 1, 1); - testSpan(arrSpan, 6, 9084); + testSpanAt(arrSpan, 0, 0); + testSpanAt(arrSpan, 1, 1); + testSpanAt(arrSpan, 6, 9084); + } // With dynamic extent + { + std::vector vec{0, 1, 2, 3, 4, 5, 9084}; + std::span vecSpan{vec}; - std::vector vec{0, 1, 2, 3, 4, 5, 9084}; - std::span vecSpan{vec}; - - assert(std::dynamic_extent == vecSpan.extent); + assert(std::dynamic_extent == vecSpan.extent); - testSpan(vecSpan, 0, 0); - testSpan(vecSpan, 1, 1); - testSpan(vecSpan, 6, 9084); + testSpanAt(vecSpan, 0, 0); + testSpanAt(vecSpan, 1, 1); + testSpanAt(vecSpan, 6, 9084); + } return true; } @@ -122,7 +124,7 @@ void test_exceptions() { assert(false); } } -#endif +#endif // TEST_HAS_NO_EXCEPTIONS } int main(int, char**) { >From 2f52b03bcec7ca93f042be69550659e71098b029 Mon Sep 17 00:00:00 2001 From: Zingam <zin...@outlook.com> Date: Sun, 10 Dec 2023 22:44:28 +0200 Subject: [PATCH 07/15] Adressed review comments --- libcxx/docs/FeatureTestMacroTable.rst | 2 + libcxx/include/span | 28 +++----- libcxx/include/version | 2 + .../views/views.span/span.elem/at.pass.cpp | 70 +++++++++++-------- .../span.version.compile.pass.cpp | 28 ++++++++ .../version.version.compile.pass.cpp | 28 ++++++++ .../generate_feature_test_macro_components.py | 5 ++ z_libcxx-dev-tools | 1 + 8 files changed, 117 insertions(+), 47 deletions(-) create mode 160000 z_libcxx-dev-tools diff --git a/libcxx/docs/FeatureTestMacroTable.rst b/libcxx/docs/FeatureTestMacroTable.rst index d09f65b7cadc0e..75028841fbb7f2 100644 --- a/libcxx/docs/FeatureTestMacroTable.rst +++ b/libcxx/docs/FeatureTestMacroTable.rst @@ -436,6 +436,8 @@ Status --------------------------------------------------- ----------------- ``__cpp_lib_smart_ptr_owner_equality`` *unimplemented* --------------------------------------------------- ----------------- + ``__cpp_lib_span_at`` ``202311L`` + --------------------------------------------------- ----------------- ``__cpp_lib_span_initializer_list`` *unimplemented* --------------------------------------------------- ----------------- ``__cpp_lib_sstream_from_string_view`` *unimplemented* diff --git a/libcxx/include/span b/libcxx/include/span index 9af8dabb3ebd34..8c52b00e4ae967 100644 --- a/libcxx/include/span +++ b/libcxx/include/span @@ -147,9 +147,7 @@ template<class R> #include <__utility/forward.h> #include <array> // for array #include <cstddef> // for byte -#if _LIBCPP_STD_VER >= 26 -# include <stdexcept> -#endif +#include <stdexcept> #include <version> // standard-mandated includes @@ -348,11 +346,11 @@ public: } # if _LIBCPP_STD_VER >= 26 - _LIBCPP_HIDE_FROM_ABI constexpr reference at(size_type __idx) const { - if (__idx >= size()) { - __throw_out_of_range(); + _LIBCPP_HIDE_FROM_ABI constexpr reference at(size_type __index) const { + if (__index >= size()) { + std::__throw_out_of_range("span"); } - return *(data() + __idx); + return __data_[__index]; } # endif @@ -396,10 +394,6 @@ public: private: pointer __data_; - -# if _LIBCPP_STD_VER >= 26 - _LIBCPP_NORETURN _LIBCPP_HIDE_FROM_ABI void __throw_out_of_range() const { std::__throw_out_of_range("span"); } -# endif }; @@ -528,11 +522,11 @@ public: } # if _LIBCPP_STD_VER >= 26 - _LIBCPP_HIDE_FROM_ABI constexpr reference at(size_type __idx) const { - if (__idx >= size()) { - __throw_out_of_range(); + _LIBCPP_HIDE_FROM_ABI constexpr reference at(size_type __index) const { + if (__index >= size()) { + std::__throw_out_of_range("span"); } - return *(data() + __idx); + return __data_[__index]; } # endif @@ -578,10 +572,6 @@ public: private: pointer __data_; size_type __size_; - -# if _LIBCPP_STD_VER >= 26 - _LIBCPP_NORETURN _LIBCPP_HIDE_FROM_ABI void __throw_out_of_range() const { std::__throw_out_of_range("span"); } -# endif }; template <class _Tp, size_t _Extent> diff --git a/libcxx/include/version b/libcxx/include/version index a91c344c436090..0c2cc09e54c763 100644 --- a/libcxx/include/version +++ b/libcxx/include/version @@ -201,6 +201,7 @@ __cpp_lib_smart_ptr_for_overwrite 202002L <memory> __cpp_lib_smart_ptr_owner_equality 202306L <memory> __cpp_lib_source_location 201907L <source_location> __cpp_lib_span 202002L <span> +__cpp_lib_span_at 202311L <span> __cpp_lib_span_initializer_list 202311L <span> __cpp_lib_spanstream 202106L <spanstream> __cpp_lib_ssize 201902L <iterator> @@ -505,6 +506,7 @@ __cpp_lib_within_lifetime 202306L <type_traits> // # define __cpp_lib_rcu 202306L // # define __cpp_lib_saturation_arithmetic 202311L // # define __cpp_lib_smart_ptr_owner_equality 202306L +# define __cpp_lib_span_at 202311L // # define __cpp_lib_span_initializer_list 202311L // # define __cpp_lib_sstream_from_string_view 202306L // # define __cpp_lib_submdspan 202306L diff --git a/libcxx/test/std/containers/views/views.span/span.elem/at.pass.cpp b/libcxx/test/std/containers/views/views.span/span.elem/at.pass.cpp index 75a45171185cf3..fb5519365ae93a 100644 --- a/libcxx/test/std/containers/views/views.span/span.elem/at.pass.cpp +++ b/libcxx/test/std/containers/views/views.span/span.elem/at.pass.cpp @@ -15,23 +15,34 @@ #include <array> #include <cassert> #include <concepts> +#include <limits> #include <span> #include <stdexcept> +#include <string> #include <utility> #include <vector> +#include <iostream> #include "test_macros.h" -constexpr void testSpanAt(auto span, int idx, int expectedValue) { +constexpr void testSpanAt(auto& container, bool hasDynamicExtent, int index, int expectedValue) { + std::span anySpan{container}; + + if (hasDynamicExtent) { + assert(std::dynamic_extent == anySpan.extent); + } else { + assert(std::dynamic_extent != anySpan.extent); + } + // non-const { - std::same_as<typename decltype(span)::reference> decltype(auto) elem = span.at(idx); + std::same_as<typename decltype(anySpan)::reference> decltype(auto) elem = anySpan.at(index); assert(elem == expectedValue); } // const { - std::same_as<typename decltype(span)::reference> decltype(auto) elem = std::as_const(span).at(idx); + std::same_as<typename decltype(anySpan)::reference> decltype(auto) elem = std::as_const(anySpan).at(index); assert(elem == expectedValue); } } @@ -39,26 +50,22 @@ constexpr void testSpanAt(auto span, int idx, int expectedValue) { constexpr bool test() { // With static extent { - std::array arr{0, 1, 2, 3, 4, 5, 9084}; - std::span arrSpan{arr}; + std::array arr{0, 1, 2, 3, 4, 5, 9084, std::numeric_limits<int>::max()}; - assert(std::dynamic_extent != arrSpan.extent); - - testSpanAt(arrSpan, 0, 0); - testSpanAt(arrSpan, 1, 1); - testSpanAt(arrSpan, 6, 9084); + testSpanAt(arr, false, 0, 0); + testSpanAt(arr, false, 1, 1); + testSpanAt(arr, false, 6, 9084); + testSpanAt(arr, false, 7, std::numeric_limits<int>::max()); } // With dynamic extent { - std::vector vec{0, 1, 2, 3, 4, 5, 9084}; - std::span vecSpan{vec}; - - assert(std::dynamic_extent == vecSpan.extent); + std::vector vec{0, 1, 2, 3, 4, 5, 9084, std::numeric_limits<int>::max()}; - testSpanAt(vecSpan, 0, 0); - testSpanAt(vecSpan, 1, 1); - testSpanAt(vecSpan, 6, 9084); + testSpanAt(vec, true, 0, 0); + testSpanAt(vec, true, 1, 1); + testSpanAt(vec, true, 6, 9084); + testSpanAt(vec, true, 7, std::numeric_limits<int>::max()); } return true; @@ -66,16 +73,19 @@ constexpr bool test() { void test_exceptions() { #ifndef TEST_HAS_NO_EXCEPTIONS + using namespace std::string_literals; + // With static extent { - std::array arr{1, 2, 3, 4}; + std::array arr{0, 1, 2, 3, 4, 5, 9084, std::numeric_limits<int>::max()}; const std::span arrSpan{arr}; try { - TEST_IGNORE_NODISCARD arrSpan.at(arr.size() + 1); + std::ignore = arrSpan.at(arr.size()); assert(false); - } catch (std::out_of_range const&) { + } catch (const std::out_of_range& e) { // pass + assert(e.what() == "span"s); } catch (...) { assert(false); } @@ -86,10 +96,11 @@ void test_exceptions() { const std::span arrSpan{arr}; try { - TEST_IGNORE_NODISCARD arrSpan.at(0); + std::ignore = arrSpan.at(0); assert(false); - } catch (std::out_of_range const&) { + } catch (const std::out_of_range& e) { // pass + assert(e.what() == "span"s); } catch (...) { assert(false); } @@ -98,14 +109,15 @@ void test_exceptions() { // With dynamic extent { - std::vector vec{1, 2, 3, 4}; + std::vector vec{0, 1, 2, 3, 4, 5, 9084, std::numeric_limits<int>::max()}; const std::span vecSpan{vec}; try { - TEST_IGNORE_NODISCARD vecSpan.at(vec.size() + 1); + std::ignore = vecSpan.at(vec.size()); assert(false); - } catch (std::out_of_range const&) { + } catch (const std::out_of_range& e) { // pass + assert(e.what() == "span"s); } catch (...) { assert(false); } @@ -116,10 +128,11 @@ void test_exceptions() { const std::span vecSpan{vec}; try { - TEST_IGNORE_NODISCARD vecSpan.at(0); + std::ignore = vecSpan.at(0); assert(false); - } catch (std::out_of_range const&) { + } catch (const std::out_of_range& e) { // pass + assert(e.what() == "span"s); } catch (...) { assert(false); } @@ -129,8 +142,9 @@ void test_exceptions() { int main(int, char**) { test(); - test_exceptions(); static_assert(test()); + test_exceptions(); + return 0; } diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/span.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/span.version.compile.pass.cpp index 355eb1338d945e..dbbbaf4ec7c228 100644 --- a/libcxx/test/std/language.support/support.limits/support.limits.general/span.version.compile.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/span.version.compile.pass.cpp @@ -17,6 +17,7 @@ /* Constant Value __cpp_lib_span 202002L [C++20] + __cpp_lib_span_at 202311L [C++26] __cpp_lib_span_initializer_list 202311L [C++26] */ @@ -29,6 +30,10 @@ # error "__cpp_lib_span should not be defined before c++20" # endif +# ifdef __cpp_lib_span_at +# error "__cpp_lib_span_at should not be defined before c++26" +# endif + # ifdef __cpp_lib_span_initializer_list # error "__cpp_lib_span_initializer_list should not be defined before c++26" # endif @@ -39,6 +44,10 @@ # error "__cpp_lib_span should not be defined before c++20" # endif +# ifdef __cpp_lib_span_at +# error "__cpp_lib_span_at should not be defined before c++26" +# endif + # ifdef __cpp_lib_span_initializer_list # error "__cpp_lib_span_initializer_list should not be defined before c++26" # endif @@ -49,6 +58,10 @@ # error "__cpp_lib_span should not be defined before c++20" # endif +# ifdef __cpp_lib_span_at +# error "__cpp_lib_span_at should not be defined before c++26" +# endif + # ifdef __cpp_lib_span_initializer_list # error "__cpp_lib_span_initializer_list should not be defined before c++26" # endif @@ -62,6 +75,10 @@ # error "__cpp_lib_span should have the value 202002L in c++20" # endif +# ifdef __cpp_lib_span_at +# error "__cpp_lib_span_at should not be defined before c++26" +# endif + # ifdef __cpp_lib_span_initializer_list # error "__cpp_lib_span_initializer_list should not be defined before c++26" # endif @@ -75,6 +92,10 @@ # error "__cpp_lib_span should have the value 202002L in c++23" # endif +# ifdef __cpp_lib_span_at +# error "__cpp_lib_span_at should not be defined before c++26" +# endif + # ifdef __cpp_lib_span_initializer_list # error "__cpp_lib_span_initializer_list should not be defined before c++26" # endif @@ -88,6 +109,13 @@ # error "__cpp_lib_span should have the value 202002L in c++26" # endif +# ifndef __cpp_lib_span_at +# error "__cpp_lib_span_at should be defined in c++26" +# endif +# if __cpp_lib_span_at != 202311L +# error "__cpp_lib_span_at should have the value 202311L in c++26" +# endif + # if !defined(_LIBCPP_VERSION) # ifndef __cpp_lib_span_initializer_list # error "__cpp_lib_span_initializer_list should be defined in c++26" diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp index c0d3d554dcf056..ec2258cbb2c8fd 100644 --- a/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp @@ -186,6 +186,7 @@ __cpp_lib_smart_ptr_owner_equality 202306L [C++26] __cpp_lib_source_location 201907L [C++20] __cpp_lib_span 202002L [C++20] + __cpp_lib_span_at 202311L [C++26] __cpp_lib_span_initializer_list 202311L [C++26] __cpp_lib_spanstream 202106L [C++23] __cpp_lib_ssize 201902L [C++20] @@ -879,6 +880,10 @@ # error "__cpp_lib_span should not be defined before c++20" # endif +# ifdef __cpp_lib_span_at +# error "__cpp_lib_span_at should not be defined before c++26" +# endif + # ifdef __cpp_lib_span_initializer_list # error "__cpp_lib_span_initializer_list should not be defined before c++26" # endif @@ -1716,6 +1721,10 @@ # error "__cpp_lib_span should not be defined before c++20" # endif +# ifdef __cpp_lib_span_at +# error "__cpp_lib_span_at should not be defined before c++26" +# endif + # ifdef __cpp_lib_span_initializer_list # error "__cpp_lib_span_initializer_list should not be defined before c++26" # endif @@ -2733,6 +2742,10 @@ # error "__cpp_lib_span should not be defined before c++20" # endif +# ifdef __cpp_lib_span_at +# error "__cpp_lib_span_at should not be defined before c++26" +# endif + # ifdef __cpp_lib_span_initializer_list # error "__cpp_lib_span_initializer_list should not be defined before c++26" # endif @@ -4029,6 +4042,10 @@ # error "__cpp_lib_span should have the value 202002L in c++20" # endif +# ifdef __cpp_lib_span_at +# error "__cpp_lib_span_at should not be defined before c++26" +# endif + # ifdef __cpp_lib_span_initializer_list # error "__cpp_lib_span_initializer_list should not be defined before c++26" # endif @@ -5547,6 +5564,10 @@ # error "__cpp_lib_span should have the value 202002L in c++23" # endif +# ifdef __cpp_lib_span_at +# error "__cpp_lib_span_at should not be defined before c++26" +# endif + # ifdef __cpp_lib_span_initializer_list # error "__cpp_lib_span_initializer_list should not be defined before c++26" # endif @@ -7284,6 +7305,13 @@ # error "__cpp_lib_span should have the value 202002L in c++26" # endif +# ifndef __cpp_lib_span_at +# error "__cpp_lib_span_at should be defined in c++26" +# endif +# if __cpp_lib_span_at != 202311L +# error "__cpp_lib_span_at should have the value 202311L in c++26" +# endif + # if !defined(_LIBCPP_VERSION) # ifndef __cpp_lib_span_initializer_list # error "__cpp_lib_span_initializer_list should be defined in c++26" diff --git a/libcxx/utils/generate_feature_test_macro_components.py b/libcxx/utils/generate_feature_test_macro_components.py index 6a30324397883a..19018bd05c1931 100755 --- a/libcxx/utils/generate_feature_test_macro_components.py +++ b/libcxx/utils/generate_feature_test_macro_components.py @@ -1082,6 +1082,11 @@ def add_version_header(tc): }, "headers": ["span"], }, + { + "name": "__cpp_lib_span_at", + "values": {"c++26": 202311}, # P2821R3 span.at() + "headers": ["span"], + }, { "name": "__cpp_lib_span_initializer_list", "values": {"c++26": 202311}, # P2447R6 std::span over an initializer list diff --git a/z_libcxx-dev-tools b/z_libcxx-dev-tools new file mode 160000 index 00000000000000..229818e01844e2 --- /dev/null +++ b/z_libcxx-dev-tools @@ -0,0 +1 @@ +Subproject commit 229818e01844e2cad56818bf06703600071848c0 >From f3223eaf5131cae761f287b10d9c9c4725b3bff5 Mon Sep 17 00:00:00 2001 From: Zingam <zin...@outlook.com> Date: Mon, 11 Dec 2023 10:31:05 +0200 Subject: [PATCH 08/15] Refactored test --- .../views/views.span/span.elem/at.pass.cpp | 70 +++++++++++++------ 1 file changed, 49 insertions(+), 21 deletions(-) diff --git a/libcxx/test/std/containers/views/views.span/span.elem/at.pass.cpp b/libcxx/test/std/containers/views/views.span/span.elem/at.pass.cpp index fb5519365ae93a..ffa9e825c6d157 100644 --- a/libcxx/test/std/containers/views/views.span/span.elem/at.pass.cpp +++ b/libcxx/test/std/containers/views/views.span/span.elem/at.pass.cpp @@ -25,24 +25,19 @@ #include "test_macros.h" -constexpr void testSpanAt(auto& container, bool hasDynamicExtent, int index, int expectedValue) { - std::span anySpan{container}; - - if (hasDynamicExtent) { - assert(std::dynamic_extent == anySpan.extent); - } else { - assert(std::dynamic_extent != anySpan.extent); - } - +template <typename ReferenceT> +constexpr void testSpanAt(auto&& anySpan, int index, int expectedValue) { // non-const { - std::same_as<typename decltype(anySpan)::reference> decltype(auto) elem = anySpan.at(index); + // std::same_as<typename decltype(anySpan)::reference> decltype(auto) elem = anySpan.at(index); + std::same_as<ReferenceT> decltype(auto) elem = anySpan.at(index); assert(elem == expectedValue); } // const { - std::same_as<typename decltype(anySpan)::reference> decltype(auto) elem = std::as_const(anySpan).at(index); + // std::same_as<typename decltype(anySpan)::reference> decltype(auto) elem = std::as_const(anySpan).at(index); + std::same_as<ReferenceT> decltype(auto) elem = std::as_const(anySpan).at(index); assert(elem == expectedValue); } } @@ -50,22 +45,36 @@ constexpr void testSpanAt(auto& container, bool hasDynamicExtent, int index, int constexpr bool test() { // With static extent { - std::array arr{0, 1, 2, 3, 4, 5, 9084, std::numeric_limits<int>::max()}; + std::array arr{0, 1, 2, 3, 4, 5, 9084}; + std::span arrSpan{arr}; + + assert(std::dynamic_extent != arrSpan.extent); + + using ReferenceT = typename decltype(arrSpan)::reference; - testSpanAt(arr, false, 0, 0); - testSpanAt(arr, false, 1, 1); - testSpanAt(arr, false, 6, 9084); - testSpanAt(arr, false, 7, std::numeric_limits<int>::max()); + // testSpanAt(arrSpan, 0, 0); + // testSpanAt(arrSpan, 1, 1); + // testSpanAt(arrSpan, 6, 9084); + testSpanAt<ReferenceT>(arrSpan, 0, 0); + testSpanAt<ReferenceT>(arrSpan, 1, 1); + testSpanAt<ReferenceT>(arrSpan, 6, 9084); } // With dynamic extent { - std::vector vec{0, 1, 2, 3, 4, 5, 9084, std::numeric_limits<int>::max()}; + std::vector vec{0, 1, 2, 3, 4, 5, 9084}; + std::span vecSpan{vec}; + + assert(std::dynamic_extent == vecSpan.extent); + + using ReferenceT = typename decltype(vecSpan)::reference; - testSpanAt(vec, true, 0, 0); - testSpanAt(vec, true, 1, 1); - testSpanAt(vec, true, 6, 9084); - testSpanAt(vec, true, 7, std::numeric_limits<int>::max()); + // testSpanAt(vecSpan, 0, 0); + // testSpanAt(vecSpan, 1, 1); + // testSpanAt(vecSpan, 6, 9084); + testSpanAt<ReferenceT>(vecSpan, 0, 0); + testSpanAt<ReferenceT>(vecSpan, 1, 1); + testSpanAt<ReferenceT>(vecSpan, 6, 9084); } return true; @@ -89,6 +98,16 @@ void test_exceptions() { } catch (...) { assert(false); } + + try { + std::ignore = arrSpan.at(arr.size() - 1); + // pass + assert(arrSpan.at(arr.size() - 1) == std::numeric_limits<int>::max()); + } catch (const std::out_of_range&) { + assert(false); + } catch (...) { + assert(false); + } } { @@ -121,6 +140,15 @@ void test_exceptions() { } catch (...) { assert(false); } + + try { + std::ignore = vecSpan.at(vec.size() - 1); + assert(vecSpan.at(vec.size() - 1) == std::numeric_limits<int>::max()); + } catch (const std::out_of_range& e) { + assert(false); + } catch (...) { + assert(false); + } } { >From f03897a231a5fc86797075913b8f57781825791a Mon Sep 17 00:00:00 2001 From: Zingam <zin...@outlook.com> Date: Mon, 11 Dec 2023 10:32:32 +0200 Subject: [PATCH 09/15] Cleaned up --- .../std/containers/views/views.span/span.elem/at.pass.cpp | 8 -------- 1 file changed, 8 deletions(-) diff --git a/libcxx/test/std/containers/views/views.span/span.elem/at.pass.cpp b/libcxx/test/std/containers/views/views.span/span.elem/at.pass.cpp index ffa9e825c6d157..92484f2e4665d3 100644 --- a/libcxx/test/std/containers/views/views.span/span.elem/at.pass.cpp +++ b/libcxx/test/std/containers/views/views.span/span.elem/at.pass.cpp @@ -29,14 +29,12 @@ template <typename ReferenceT> constexpr void testSpanAt(auto&& anySpan, int index, int expectedValue) { // non-const { - // std::same_as<typename decltype(anySpan)::reference> decltype(auto) elem = anySpan.at(index); std::same_as<ReferenceT> decltype(auto) elem = anySpan.at(index); assert(elem == expectedValue); } // const { - // std::same_as<typename decltype(anySpan)::reference> decltype(auto) elem = std::as_const(anySpan).at(index); std::same_as<ReferenceT> decltype(auto) elem = std::as_const(anySpan).at(index); assert(elem == expectedValue); } @@ -52,9 +50,6 @@ constexpr bool test() { using ReferenceT = typename decltype(arrSpan)::reference; - // testSpanAt(arrSpan, 0, 0); - // testSpanAt(arrSpan, 1, 1); - // testSpanAt(arrSpan, 6, 9084); testSpanAt<ReferenceT>(arrSpan, 0, 0); testSpanAt<ReferenceT>(arrSpan, 1, 1); testSpanAt<ReferenceT>(arrSpan, 6, 9084); @@ -69,9 +64,6 @@ constexpr bool test() { using ReferenceT = typename decltype(vecSpan)::reference; - // testSpanAt(vecSpan, 0, 0); - // testSpanAt(vecSpan, 1, 1); - // testSpanAt(vecSpan, 6, 9084); testSpanAt<ReferenceT>(vecSpan, 0, 0); testSpanAt<ReferenceT>(vecSpan, 1, 1); testSpanAt<ReferenceT>(vecSpan, 6, 9084); >From 077500bb21b98a34f80e7984d0bee9aa31d6976d Mon Sep 17 00:00:00 2001 From: Hristo Hristov <zin...@outlook.com> Date: Mon, 11 Dec 2023 14:46:49 +0200 Subject: [PATCH 10/15] Try to fix CI: transitive includes --- libcxx/test/libcxx/transitive_includes/cxx03.csv | 1 + libcxx/test/libcxx/transitive_includes/cxx11.csv | 1 + libcxx/test/libcxx/transitive_includes/cxx14.csv | 1 + libcxx/test/libcxx/transitive_includes/cxx17.csv | 1 + libcxx/test/libcxx/transitive_includes/cxx20.csv | 1 + libcxx/test/libcxx/transitive_includes/cxx23.csv | 1 + libcxx/test/libcxx/transitive_includes/cxx26.csv | 1 + 7 files changed, 7 insertions(+) diff --git a/libcxx/test/libcxx/transitive_includes/cxx03.csv b/libcxx/test/libcxx/transitive_includes/cxx03.csv index 7066de65a91372..20e10744bc00b9 100644 --- a/libcxx/test/libcxx/transitive_includes/cxx03.csv +++ b/libcxx/test/libcxx/transitive_includes/cxx03.csv @@ -739,6 +739,7 @@ span functional span initializer_list span iterator span limits +span stdexcept span type_traits span version sstream cstddef diff --git a/libcxx/test/libcxx/transitive_includes/cxx11.csv b/libcxx/test/libcxx/transitive_includes/cxx11.csv index c4dc664d6ca817..df730b9c03b2bb 100644 --- a/libcxx/test/libcxx/transitive_includes/cxx11.csv +++ b/libcxx/test/libcxx/transitive_includes/cxx11.csv @@ -745,6 +745,7 @@ span functional span initializer_list span iterator span limits +span stdexcept span type_traits span version sstream cstddef diff --git a/libcxx/test/libcxx/transitive_includes/cxx14.csv b/libcxx/test/libcxx/transitive_includes/cxx14.csv index 20ee43722d894b..f53b4dc06c183e 100644 --- a/libcxx/test/libcxx/transitive_includes/cxx14.csv +++ b/libcxx/test/libcxx/transitive_includes/cxx14.csv @@ -747,6 +747,7 @@ span functional span initializer_list span iterator span limits +span stdexcept span type_traits span version sstream cstddef diff --git a/libcxx/test/libcxx/transitive_includes/cxx17.csv b/libcxx/test/libcxx/transitive_includes/cxx17.csv index 20ee43722d894b..f53b4dc06c183e 100644 --- a/libcxx/test/libcxx/transitive_includes/cxx17.csv +++ b/libcxx/test/libcxx/transitive_includes/cxx17.csv @@ -747,6 +747,7 @@ span functional span initializer_list span iterator span limits +span stdexcept span type_traits span version sstream cstddef diff --git a/libcxx/test/libcxx/transitive_includes/cxx20.csv b/libcxx/test/libcxx/transitive_includes/cxx20.csv index d256370aac4a4a..e7b8b0faa465d5 100644 --- a/libcxx/test/libcxx/transitive_includes/cxx20.csv +++ b/libcxx/test/libcxx/transitive_includes/cxx20.csv @@ -752,6 +752,7 @@ span functional span initializer_list span iterator span limits +span stdexcept span type_traits span version sstream cstddef diff --git a/libcxx/test/libcxx/transitive_includes/cxx23.csv b/libcxx/test/libcxx/transitive_includes/cxx23.csv index 9edc283236480e..78148f7e70a758 100644 --- a/libcxx/test/libcxx/transitive_includes/cxx23.csv +++ b/libcxx/test/libcxx/transitive_includes/cxx23.csv @@ -515,6 +515,7 @@ span array span cstddef span initializer_list span limits +span stdexcept span version sstream cstddef sstream istream diff --git a/libcxx/test/libcxx/transitive_includes/cxx26.csv b/libcxx/test/libcxx/transitive_includes/cxx26.csv index 9edc283236480e..78148f7e70a758 100644 --- a/libcxx/test/libcxx/transitive_includes/cxx26.csv +++ b/libcxx/test/libcxx/transitive_includes/cxx26.csv @@ -515,6 +515,7 @@ span array span cstddef span initializer_list span limits +span stdexcept span version sstream cstddef sstream istream >From 86ef4053380ac223f8ff73bbf8454c56e9ab0cf7 Mon Sep 17 00:00:00 2001 From: Hristo Hristov <zin...@outlook.com> Date: Mon, 11 Dec 2023 18:24:45 +0200 Subject: [PATCH 11/15] Try to fix CI - missing header --- .../test/std/containers/views/views.span/span.elem/at.pass.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libcxx/test/std/containers/views/views.span/span.elem/at.pass.cpp b/libcxx/test/std/containers/views/views.span/span.elem/at.pass.cpp index 92484f2e4665d3..758de0f40e1091 100644 --- a/libcxx/test/std/containers/views/views.span/span.elem/at.pass.cpp +++ b/libcxx/test/std/containers/views/views.span/span.elem/at.pass.cpp @@ -19,9 +19,9 @@ #include <span> #include <stdexcept> #include <string> +#include <tuple> #include <utility> #include <vector> -#include <iostream> #include "test_macros.h" >From d9b2a08ed4cfc6a114af055cc69aed9276794b39 Mon Sep 17 00:00:00 2001 From: Zingam <zin...@outlook.com> Date: Mon, 11 Dec 2023 21:09:56 +0200 Subject: [PATCH 12/15] Addressed comment --- libcxx/include/span | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/libcxx/include/span b/libcxx/include/span index 8c52b00e4ae967..24a0057680edee 100644 --- a/libcxx/include/span +++ b/libcxx/include/span @@ -347,9 +347,8 @@ public: # if _LIBCPP_STD_VER >= 26 _LIBCPP_HIDE_FROM_ABI constexpr reference at(size_type __index) const { - if (__index >= size()) { + if (__index >= size()) std::__throw_out_of_range("span"); - } return __data_[__index]; } # endif @@ -523,9 +522,8 @@ public: # if _LIBCPP_STD_VER >= 26 _LIBCPP_HIDE_FROM_ABI constexpr reference at(size_type __index) const { - if (__index >= size()) { + if (__index >= size()) std::__throw_out_of_range("span"); - } return __data_[__index]; } # endif >From 4ef25f7c9d78e42e9fb750ead52c9a30e9d484ea Mon Sep 17 00:00:00 2001 From: Zingam <zin...@outlook.com> Date: Sat, 16 Dec 2023 21:03:57 +0200 Subject: [PATCH 13/15] Removed bad file --- z_libcxx-dev-tools | 1 - 1 file changed, 1 deletion(-) delete mode 160000 z_libcxx-dev-tools diff --git a/z_libcxx-dev-tools b/z_libcxx-dev-tools deleted file mode 160000 index 229818e01844e2..00000000000000 --- a/z_libcxx-dev-tools +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 229818e01844e2cad56818bf06703600071848c0 >From bf43de05db328c7c6093c7323114e12c797f67d9 Mon Sep 17 00:00:00 2001 From: Zingam <zin...@outlook.com> Date: Sat, 16 Dec 2023 21:08:12 +0200 Subject: [PATCH 14/15] Addressed comment --- .../test/std/containers/views/views.span/span.elem/at.pass.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/libcxx/test/std/containers/views/views.span/span.elem/at.pass.cpp b/libcxx/test/std/containers/views/views.span/span.elem/at.pass.cpp index 758de0f40e1091..d5876d406cf525 100644 --- a/libcxx/test/std/containers/views/views.span/span.elem/at.pass.cpp +++ b/libcxx/test/std/containers/views/views.span/span.elem/at.pass.cpp @@ -95,8 +95,6 @@ void test_exceptions() { std::ignore = arrSpan.at(arr.size() - 1); // pass assert(arrSpan.at(arr.size() - 1) == std::numeric_limits<int>::max()); - } catch (const std::out_of_range&) { - assert(false); } catch (...) { assert(false); } >From d279bff68f8a829fd0e75dc4f047b20f4171f19e Mon Sep 17 00:00:00 2001 From: Zingam <zin...@outlook.com> Date: Sun, 17 Dec 2023 18:22:55 +0200 Subject: [PATCH 15/15] Addressed review comments --- .../containers/views/views.span/span.elem/at.pass.cpp | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/libcxx/test/std/containers/views/views.span/span.elem/at.pass.cpp b/libcxx/test/std/containers/views/views.span/span.elem/at.pass.cpp index d5876d406cf525..efe64222bddffa 100644 --- a/libcxx/test/std/containers/views/views.span/span.elem/at.pass.cpp +++ b/libcxx/test/std/containers/views/views.span/span.elem/at.pass.cpp @@ -86,7 +86,7 @@ void test_exceptions() { assert(false); } catch (const std::out_of_range& e) { // pass - assert(e.what() == "span"s); + LIBCPP_ASSERT(e.what() == "span"s); } catch (...) { assert(false); } @@ -109,7 +109,7 @@ void test_exceptions() { assert(false); } catch (const std::out_of_range& e) { // pass - assert(e.what() == "span"s); + LIBCPP_ASSERT(e.what() == "span"s); } catch (...) { assert(false); } @@ -126,7 +126,7 @@ void test_exceptions() { assert(false); } catch (const std::out_of_range& e) { // pass - assert(e.what() == "span"s); + LIBCPP_ASSERT(e.what() == "span"s); } catch (...) { assert(false); } @@ -134,8 +134,6 @@ void test_exceptions() { try { std::ignore = vecSpan.at(vec.size() - 1); assert(vecSpan.at(vec.size() - 1) == std::numeric_limits<int>::max()); - } catch (const std::out_of_range& e) { - assert(false); } catch (...) { assert(false); } @@ -150,7 +148,7 @@ void test_exceptions() { assert(false); } catch (const std::out_of_range& e) { // pass - assert(e.what() == "span"s); + LIBCPP_ASSERT(e.what() == "span"s); } catch (...) { assert(false); } _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits