diff options
author | Jonathan Wakely <jwakely@redhat.com> | 2025-03-05 21:08:21 +0000 |
---|---|---|
committer | Jonathan Wakely <redi@gcc.gnu.org> | 2025-03-07 13:47:05 +0000 |
commit | 9f40ec15a30a248d72c496614d7bcbaa9be8ca49 (patch) | |
tree | 15143339a000cb91e3bd86a1ca6a2c3cc2253935 /libstdc++-v3/testsuite | |
parent | 9798ba2c6b4cccb17277a9d5fc04d285bf48f742 (diff) | |
download | gcc-9f40ec15a30a248d72c496614d7bcbaa9be8ca49.zip gcc-9f40ec15a30a248d72c496614d7bcbaa9be8ca49.tar.gz gcc-9f40ec15a30a248d72c496614d7bcbaa9be8ca49.tar.bz2 |
libstdc++: Add missing static_assert to std::expected<void,E>::value()&&
The r15-2326-gea435261ad58ea change missed a static_assert for
is_move_constructible_v in expected<cv void, E>::value()&&. When
exceptions are enabled, the program is ill-formed if the error type is
not move constructible, because we can't construct the
std::bad_expected_access. But prior to r15-7856-gd87c0d5443ba86, using
-fno-exceptions meant that we never constructed an exception, so didn't
need to copy/move the error value.
So that we don't rely on the r15-7856-gd87c0d5443ba86 change to the
_GLIBCXX_THROW_OR_ABORT macro to consistently enforce the Mandates:
conditions whether exceptions are enabled or not, we should check the
requirement explicitly.
This adds the missing static_assert. It also adds a test that verifies
the Mandates: conditions added by LWG 3843 and 3490 are enforced even
with -fno-exceptions.
libstdc++-v3/ChangeLog:
* include/std/expected (expected<cv void,E>::value()&&):
Add missing static_assert for LWG 3940.
* testsuite/20_util/expected/lwg3843.cc: New test.
Reviewed-by: Tomasz KamiĆski <tkaminsk@redhat.com>
Diffstat (limited to 'libstdc++-v3/testsuite')
-rw-r--r-- | libstdc++-v3/testsuite/20_util/expected/lwg3843.cc | 69 |
1 files changed, 69 insertions, 0 deletions
diff --git a/libstdc++-v3/testsuite/20_util/expected/lwg3843.cc b/libstdc++-v3/testsuite/20_util/expected/lwg3843.cc new file mode 100644 index 0000000..2afb9cc --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/expected/lwg3843.cc @@ -0,0 +1,69 @@ +// { dg-do compile { target c++23 } } +// { dg-options "-fno-exceptions" } + +#include <expected> + +// 3843. std::expected<T,E>::value() & assumes E is copy constructible +void +test_lwg3843() +{ + struct E1 { + E1(int) { } + E1(E1&) { } + E1(const E1&) = delete; + }; + std::expected<int, E1> v1; + v1.value(); // { dg-error "here" } + const auto& v1c = v1; + v1c.value(); // { dg-error "here" } + + struct E2 { + E2(int) { } + E2(const E2&) { } + E2(E2&&) = delete; + }; + std::expected<int, E2> v2; + v2.value(); + std::move(v2).value(); // { dg-error "here" } + const auto& v2c = v2; + v2c.value(); + std::move(v2c).value(); + + struct E3 { + E3(int) { } + E3(const E3&) { } + E3(E3&&) { } + E3(const E3&&) = delete; + }; + std::expected<int, E3> v3; + v3.value(); + std::move(v3).value(); + const auto& v3c = v3; + v3c.value(); + std::move(v3c).value(); // { dg-error "here" } +} + +// 3940. std::expected<void, E>::value() also needs E to be copy constructible +void +test_lwg3940() +{ + struct E1 { + E1(int) { } + E1(E1&) { } + E1(const E1&) = delete; + }; + std::expected<void, E1> v1; + v1.value(); // { dg-error "here" } + + struct E2 { + E2(int) { } + E2(const E2&) { } + E2(E2&&) = delete; + }; + std::expected<void, E2> v2; + std::move(v2).value(); // { dg-error "here" } +} + +// { dg-error "static assertion failed" "" { target *-*-* } 0 } +// { dg-prune-output "use of deleted function" } +// { dg-prune-output "control reaches end of non-void function" } |