From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 2122) id 044763856DC5; Sat, 22 Apr 2023 00:22:47 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 044763856DC5 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1682122967; bh=3JQxiz9Y/+v6F6LPDAcw9rVd+QjDWJxY9nO58qtbGSY=; h=From:To:Subject:Date:From; b=fQDywa4XYXPD/KGxKAdVck5c6GipBEa0CepIbNGgoQzve1z0UYso/a6XxnQlFoGvH CI96YhjwcBA9I+KcqA5DAGdEAe24gjCuC5F7PNu5r35Ipu5C6Bj9JLHSh+g/VOhhH+ 3vxyfUdXiVcpux1ol3sFafX529QHYuvWdi0B+wVI= MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Type: text/plain; charset="utf-8" From: Jason Merrill To: gcc-cvs@gcc.gnu.org Subject: [gcc r11-10642] c++: co_await and move-only type [PR105406] X-Act-Checkin: gcc X-Git-Author: Jason Merrill X-Git-Refname: refs/heads/releases/gcc-11 X-Git-Oldrev: 998e77e55126269b3e67b2f05f0f27a421839673 X-Git-Newrev: 657fb0db2648a8cd7ba355fdec570fe2f08448ac Message-Id: <20230422002247.044763856DC5@sourceware.org> Date: Sat, 22 Apr 2023 00:22:47 +0000 (GMT) List-Id: https://gcc.gnu.org/g:657fb0db2648a8cd7ba355fdec570fe2f08448ac commit r11-10642-g657fb0db2648a8cd7ba355fdec570fe2f08448ac Author: Jason Merrill Date: Wed Mar 15 17:02:15 2023 -0400 c++: co_await and move-only type [PR105406] Here we were building a temporary MoveOnlyAwaitable to hold the result of evaluating 'o', but since 'o' is an lvalue we should build a reference instead. PR c++/105406 gcc/cp/ChangeLog: * coroutines.cc (build_co_await): Handle lvalue 'o'. gcc/testsuite/ChangeLog: * g++.dg/coroutines/co-await-moveonly1.C: New test. Diff: --- gcc/cp/coroutines.cc | 9 +++- .../g++.dg/coroutines/co-await-moveonly1.C | 63 ++++++++++++++++++++++ 2 files changed, 71 insertions(+), 1 deletion(-) diff --git a/gcc/cp/coroutines.cc b/gcc/cp/coroutines.cc index ea3850082cf..b20e773bff6 100644 --- a/gcc/cp/coroutines.cc +++ b/gcc/cp/coroutines.cc @@ -1016,9 +1016,13 @@ build_co_await (location_t loc, tree a, suspend_point_kind suspend_kind) } else { - e_proxy = get_awaitable_var (suspend_kind, o_type); + tree p_type = o_type; + if (glvalue_p (o)) + p_type = cp_build_reference_type (p_type, !lvalue_p (o)); + e_proxy = get_awaitable_var (suspend_kind, p_type); o = cp_build_modify_expr (loc, e_proxy, INIT_EXPR, o, tf_warning_or_error); + e_proxy = convert_from_reference (e_proxy); } /* I suppose we could check that this is contextually convertible to bool. */ @@ -1111,6 +1115,9 @@ build_co_await (location_t loc, tree a, suspend_point_kind suspend_kind) } TREE_VEC_ELT (awaiter_calls, 2) = awrs_call; /* await_resume(). */ + if (REFERENCE_REF_P (e_proxy)) + e_proxy = TREE_OPERAND (e_proxy, 0); + tree await_expr = build5_loc (loc, CO_AWAIT_EXPR, TREE_TYPE (TREE_TYPE (awrs_func)), a, e_proxy, o, awaiter_calls, diff --git a/gcc/testsuite/g++.dg/coroutines/co-await-moveonly1.C b/gcc/testsuite/g++.dg/coroutines/co-await-moveonly1.C new file mode 100644 index 00000000000..e2831c104bf --- /dev/null +++ b/gcc/testsuite/g++.dg/coroutines/co-await-moveonly1.C @@ -0,0 +1,63 @@ +// PR c++/105406 +// { dg-do compile { target c++20 } } + +#include +#include + +// A move-only awaitable +class MoveOnlyAwaitable { +public: + MoveOnlyAwaitable() = default; + MoveOnlyAwaitable(MoveOnlyAwaitable &&) = default; + MoveOnlyAwaitable &operator=(MoveOnlyAwaitable &&) = default; + + MoveOnlyAwaitable(const MoveOnlyAwaitable &) = delete; + MoveOnlyAwaitable &operator=(const MoveOnlyAwaitable &) = delete; + + bool await_ready() const noexcept { return false; } + void await_suspend(std::coroutine_handle<>) noexcept {} + void await_resume() {} +}; + +struct task { + struct promise_type { + auto initial_suspend() const { return std::suspend_never{}; } + auto final_suspend() const noexcept { return std::suspend_never(); } + auto get_return_object() { return task{}; } + void return_void() {} + void unhandled_exception() {} + + template + T &&await_transform(T &&t) { + return static_cast(t); + } + + + }; + + bool await_ready() const { return false; } + void await_suspend(std::coroutine_handle<> awaiter) {} + void await_resume() {} +}; + +task myCoroutine() { + // GCC: OK + // clang: OK + { + co_await MoveOnlyAwaitable(); + } + // GCC: OK + // clang: OK + { + auto moveonly = MoveOnlyAwaitable(); + co_await std::move(moveonly); + } + + // GCC <= 11.2: OK + // GCC 11.3:ERROR: error: use of deleted function 'MoveOnlyAwaitable::MoveOnlyAwaitable(const MoveOnlyAwaitable&) + // clang: OK + { + auto moveonly = MoveOnlyAwaitable(); + co_await moveonly; + } +}