https://github.com/PragmaTwice updated https://github.com/llvm/llvm-project/pull/71819
>From 3e4b73d2aeac411a83dda5cd63eb0572499db467 Mon Sep 17 00:00:00 2001 From: PragmaTwice <tw...@apache.org> Date: Fri, 10 Nov 2023 00:50:24 +0900 Subject: [PATCH 1/7] [libc++] Implement LWG3940 (std::expected<void, E>::value() also needs E to be copy constructible) --- libcxx/docs/Status/Cxx2cIssues.csv | 2 +- libcxx/include/__expected/expected.h | 3 +++ .../observers/value.lwg3940.compile.fail.cpp | 27 +++++++++++++++++++ .../expected.void/observers/value.pass.cpp | 11 -------- 4 files changed, 31 insertions(+), 12 deletions(-) create mode 100644 libcxx/test/std/utilities/expected/expected.void/observers/value.lwg3940.compile.fail.cpp diff --git a/libcxx/docs/Status/Cxx2cIssues.csv b/libcxx/docs/Status/Cxx2cIssues.csv index a928b69ea10c48..099a19d02888f4 100644 --- a/libcxx/docs/Status/Cxx2cIssues.csv +++ b/libcxx/docs/Status/Cxx2cIssues.csv @@ -15,7 +15,7 @@ "`3927 <https://wg21.link/LWG3927>`__","Unclear preconditions for ``operator[]`` for sequence containers","Varna June 2023","|Nothing To Do|","","" "`3935 <https://wg21.link/LWG3935>`__","``template<class X> constexpr complex& operator=(const complex<X>&)`` has no specification","Varna June 2023","|Complete|","3.4","" "`3938 <https://wg21.link/LWG3938>`__","Cannot use ``std::expected`` monadic ops with move-only ``error_type``","Varna June 2023","|Complete|","18.0","" -"`3940 <https://wg21.link/LWG3940>`__","``std::expected<void, E>::value()`` also needs ``E`` to be copy constructible","Varna June 2023","","","" +"`3940 <https://wg21.link/LWG3940>`__","``std::expected<void, E>::value()`` also needs ``E`` to be copy constructible","Varna June 2023","|Complete|","18.0","" "","","","","","" "`3343 <https://wg21.link/LWG3343>`__","Ordering of calls to ``unlock()`` and ``notify_all()`` in Effects element of ``notify_all_at_thread_exit()`` should be reversed","Not Yet Adopted","|Complete|","16.0","" "`3892 <https://wg21.link/LWG3892>`__","Incorrect formatting of nested ranges and tuples","Not Yet Adopted","|Complete|","17.0","|format|" diff --git a/libcxx/include/__expected/expected.h b/libcxx/include/__expected/expected.h index bf16c8f720d268..c6441f1651b085 100644 --- a/libcxx/include/__expected/expected.h +++ b/libcxx/include/__expected/expected.h @@ -1187,12 +1187,15 @@ class expected<_Tp, _Err> { } _LIBCPP_HIDE_FROM_ABI constexpr void value() const& { + static_assert(is_copy_constructible_v<_Err>, "error_type has to be copy constructible"); if (!__has_val_) { std::__throw_bad_expected_access<_Err>(__union_.__unex_); } } _LIBCPP_HIDE_FROM_ABI constexpr void value() && { + static_assert(is_copy_constructible_v<_Err> && is_move_constructible_v<_Err>, + "error_type has to be both copy constructible and move constructible"); if (!__has_val_) { std::__throw_bad_expected_access<_Err>(std::move(__union_.__unex_)); } diff --git a/libcxx/test/std/utilities/expected/expected.void/observers/value.lwg3940.compile.fail.cpp b/libcxx/test/std/utilities/expected/expected.void/observers/value.lwg3940.compile.fail.cpp new file mode 100644 index 00000000000000..37c06e629e9443 --- /dev/null +++ b/libcxx/test/std/utilities/expected/expected.void/observers/value.lwg3940.compile.fail.cpp @@ -0,0 +1,27 @@ +//===----------------------------------------------------------------------===// +// 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 + +// constexpr void value() &&; +// Mandates: is_copy_constructible_v<E> is true and is_move_constructible_v<E> is true. + +#include <expected> + +#include "MoveOnly.h" + +void test() { + // MoveOnly + std::expected<void, MoveOnly> e(std::unexpect, 5); + + // COMPILE FAIL: MoveOnly is not copy constructible + std::move(e).value(); +} + +int main(int, char**) { + test(); +} diff --git a/libcxx/test/std/utilities/expected/expected.void/observers/value.pass.cpp b/libcxx/test/std/utilities/expected/expected.void/observers/value.pass.cpp index 0f02db19c7b75e..a24d67c57e19b5 100644 --- a/libcxx/test/std/utilities/expected/expected.void/observers/value.pass.cpp +++ b/libcxx/test/std/utilities/expected/expected.void/observers/value.pass.cpp @@ -65,17 +65,6 @@ void testException() { } } - // MoveOnly - { - std::expected<void, MoveOnly> e(std::unexpect, 5); - try { - std::move(e).value(); - assert(false); - } catch (const std::bad_expected_access<MoveOnly>& ex) { - assert(ex.error() == 5); - } - } - #endif // TEST_HAS_NO_EXCEPTIONS } >From 2d1c43fa98b3a97f31509e98c3abdd7fe8f62626 Mon Sep 17 00:00:00 2001 From: PragmaTwice <tw...@apache.org> Date: Fri, 10 Nov 2023 19:29:30 +0900 Subject: [PATCH 2/7] [libcxx] format test --- .../expected.void/observers/value.lwg3940.compile.fail.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/libcxx/test/std/utilities/expected/expected.void/observers/value.lwg3940.compile.fail.cpp b/libcxx/test/std/utilities/expected/expected.void/observers/value.lwg3940.compile.fail.cpp index 37c06e629e9443..0f43a45b4eaaa1 100644 --- a/libcxx/test/std/utilities/expected/expected.void/observers/value.lwg3940.compile.fail.cpp +++ b/libcxx/test/std/utilities/expected/expected.void/observers/value.lwg3940.compile.fail.cpp @@ -22,6 +22,4 @@ void test() { std::move(e).value(); } -int main(int, char**) { - test(); -} +int main(int, char**) { test(); } >From 0767b57320aa3433a65761132d57414fe6ffd1ea Mon Sep 17 00:00:00 2001 From: PragmaTwice <tw...@apache.org> Date: Wed, 15 Nov 2023 23:49:52 +0900 Subject: [PATCH 3/7] use .verify.cpp instead of .compile.fail.cpp --- ...e.lwg3940.compile.fail.cpp => value.lwg3940.verify.cpp} | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) rename libcxx/test/std/utilities/expected/expected.void/observers/{value.lwg3940.compile.fail.cpp => value.lwg3940.verify.cpp} (62%) diff --git a/libcxx/test/std/utilities/expected/expected.void/observers/value.lwg3940.compile.fail.cpp b/libcxx/test/std/utilities/expected/expected.void/observers/value.lwg3940.verify.cpp similarity index 62% rename from libcxx/test/std/utilities/expected/expected.void/observers/value.lwg3940.compile.fail.cpp rename to libcxx/test/std/utilities/expected/expected.void/observers/value.lwg3940.verify.cpp index 0f43a45b4eaaa1..da6aeb10a3e40d 100644 --- a/libcxx/test/std/utilities/expected/expected.void/observers/value.lwg3940.compile.fail.cpp +++ b/libcxx/test/std/utilities/expected/expected.void/observers/value.lwg3940.verify.cpp @@ -6,6 +6,7 @@ //===----------------------------------------------------------------------===// // UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 +// ADDITIONAL_COMPILE_FLAGS: -Xclang -verify-ignore-unexpected=error // constexpr void value() &&; // Mandates: is_copy_constructible_v<E> is true and is_move_constructible_v<E> is true. @@ -15,11 +16,11 @@ #include "MoveOnly.h" void test() { - // MoveOnly + // MoveOnly type as error_type std::expected<void, MoveOnly> e(std::unexpect, 5); - // COMPILE FAIL: MoveOnly is not copy constructible - std::move(e).value(); + std::move(e).value(); // expected-note{{in instantiation of member function 'std::expected<void, MoveOnly>::value' requested here}} + // expected-error-re@*:* {{static assertion failed due to requirement 'is_copy_constructible_v<MoveOnly>': error_type has to be both copy constructible and move constructible}} } int main(int, char**) { test(); } >From a5ea3056ec348ca0b576cda84fa99796c0b2b60b Mon Sep 17 00:00:00 2001 From: PragmaTwice <tw...@apache.org> Date: Wed, 15 Nov 2023 23:54:51 +0900 Subject: [PATCH 4/7] format code --- .../expected/expected.void/observers/value.lwg3940.verify.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libcxx/test/std/utilities/expected/expected.void/observers/value.lwg3940.verify.cpp b/libcxx/test/std/utilities/expected/expected.void/observers/value.lwg3940.verify.cpp index da6aeb10a3e40d..c2516119089f9e 100644 --- a/libcxx/test/std/utilities/expected/expected.void/observers/value.lwg3940.verify.cpp +++ b/libcxx/test/std/utilities/expected/expected.void/observers/value.lwg3940.verify.cpp @@ -19,7 +19,8 @@ void test() { // MoveOnly type as error_type std::expected<void, MoveOnly> e(std::unexpect, 5); - std::move(e).value(); // expected-note{{in instantiation of member function 'std::expected<void, MoveOnly>::value' requested here}} + std::move(e) + .value(); // expected-note{{in instantiation of member function 'std::expected<void, MoveOnly>::value' requested here}} // expected-error-re@*:* {{static assertion failed due to requirement 'is_copy_constructible_v<MoveOnly>': error_type has to be both copy constructible and move constructible}} } >From cc857072825b73c34f7cc7c01ff860a7b1dd7cd0 Mon Sep 17 00:00:00 2001 From: PragmaTwice <tw...@apache.org> Date: Thu, 16 Nov 2023 21:52:55 +0900 Subject: [PATCH 5/7] rename & clean up --- .../expected/expected.void}/value.lwg3940.verify.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) rename libcxx/test/{std/utilities/expected/expected.void/observers => libcxx/utilities/expected/expected.void}/value.lwg3940.verify.cpp (63%) diff --git a/libcxx/test/std/utilities/expected/expected.void/observers/value.lwg3940.verify.cpp b/libcxx/test/libcxx/utilities/expected/expected.void/value.lwg3940.verify.cpp similarity index 63% rename from libcxx/test/std/utilities/expected/expected.void/observers/value.lwg3940.verify.cpp rename to libcxx/test/libcxx/utilities/expected/expected.void/value.lwg3940.verify.cpp index c2516119089f9e..33bac465a5eda2 100644 --- a/libcxx/test/std/utilities/expected/expected.void/observers/value.lwg3940.verify.cpp +++ b/libcxx/test/libcxx/utilities/expected/expected.void/value.lwg3940.verify.cpp @@ -6,7 +6,6 @@ //===----------------------------------------------------------------------===// // UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 -// ADDITIONAL_COMPILE_FLAGS: -Xclang -verify-ignore-unexpected=error // constexpr void value() &&; // Mandates: is_copy_constructible_v<E> is true and is_move_constructible_v<E> is true. @@ -20,8 +19,6 @@ void test() { std::expected<void, MoveOnly> e(std::unexpect, 5); std::move(e) - .value(); // expected-note{{in instantiation of member function 'std::expected<void, MoveOnly>::value' requested here}} - // expected-error-re@*:* {{static assertion failed due to requirement 'is_copy_constructible_v<MoveOnly>': error_type has to be both copy constructible and move constructible}} + .value(); // expected-note {{in instantiation of member function 'std::expected<void, MoveOnly>::value' requested here}} + // expected-error@*:* {{static assertion failed due to requirement 'is_copy_constructible_v<MoveOnly>': error_type has to be both copy constructible and move constructible}} } - -int main(int, char**) { test(); } >From 5cf3dc623e5051d402ce4c6d135052c8ef511844 Mon Sep 17 00:00:00 2001 From: PragmaTwice <tw...@apache.org> Date: Wed, 3 Jan 2024 16:16:56 +0800 Subject: [PATCH 7/7] add more tests --- libcxx/include/__expected/expected.h | 2 +- .../expected.void/value.lwg3940.verify.cpp | 25 +++++++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/libcxx/include/__expected/expected.h b/libcxx/include/__expected/expected.h index c6441f1651b085..d91f307ecda1c7 100644 --- a/libcxx/include/__expected/expected.h +++ b/libcxx/include/__expected/expected.h @@ -1187,7 +1187,7 @@ class expected<_Tp, _Err> { } _LIBCPP_HIDE_FROM_ABI constexpr void value() const& { - static_assert(is_copy_constructible_v<_Err>, "error_type has to be copy constructible"); + static_assert(is_copy_constructible_v<_Err>); if (!__has_val_) { std::__throw_bad_expected_access<_Err>(__union_.__unex_); } diff --git a/libcxx/test/libcxx/utilities/expected/expected.void/value.lwg3940.verify.cpp b/libcxx/test/libcxx/utilities/expected/expected.void/value.lwg3940.verify.cpp index 33bac465a5eda2..04e5a5d68f2c25 100644 --- a/libcxx/test/libcxx/utilities/expected/expected.void/value.lwg3940.verify.cpp +++ b/libcxx/test/libcxx/utilities/expected/expected.void/value.lwg3940.verify.cpp @@ -7,6 +7,9 @@ // UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 +// constexpr void value() const &; +// Mandates: is_copy_constructible_v<E> is true. + // constexpr void value() &&; // Mandates: is_copy_constructible_v<E> is true and is_move_constructible_v<E> is true. @@ -14,11 +17,33 @@ #include "MoveOnly.h" +struct CopyOnly { + CopyOnly() = default; + CopyOnly(const CopyOnly&) = default; + CopyOnly(CopyOnly&&) = delete; +}; + void test() { // MoveOnly type as error_type std::expected<void, MoveOnly> e(std::unexpect, 5); + e.value(); // expected-note {{in instantiation of member function 'std::expected<void, MoveOnly>::value' requested here}} + // expected-error@*:* {{static assertion failed due to requirement 'is_copy_constructible_v<MoveOnly>'}} + std::move(e) .value(); // expected-note {{in instantiation of member function 'std::expected<void, MoveOnly>::value' requested here}} // expected-error@*:* {{static assertion failed due to requirement 'is_copy_constructible_v<MoveOnly>': error_type has to be both copy constructible and move constructible}} + + // CopyOnly type as error_type + std::expected<void, CopyOnly> e2(std::unexpect); + + e2.value(); + + std::move(e2) + .value(); // expected-note {{in instantiation of member function 'std::expected<void, CopyOnly>::value' requested here}} + // expected-error@*:* {{static assertion failed due to requirement 'is_move_constructible_v<CopyOnly>': error_type has to be both copy constructible and move constructible}} + + // expected-error@*:* {{call to deleted constructor of 'MoveOnly'}} + // expected-error@*:* {{call to deleted constructor of 'CopyOnly'}} + // expected-error@*:* {{call to deleted constructor of 'CopyOnly'}} } _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits