public inbox for gcc-cvs@sourceware.org help / color / mirror / Atom feed
From: Iain D Sandoe <iains@gcc.gnu.org> To: gcc-cvs@gcc.gnu.org Subject: [gcc r12-6046] coroutines: Handle initial awaiters with non-void returns [PR 100127]. Date: Fri, 17 Dec 2021 16:58:09 +0000 (GMT) [thread overview] Message-ID: <20211217165809.0F0163858412@sourceware.org> (raw) https://gcc.gnu.org/g:2466a8d0dd40d05cb4a239d7d4a21bbd9ffab698 commit r12-6046-g2466a8d0dd40d05cb4a239d7d4a21bbd9ffab698 Author: Iain Sandoe <iain@sandoe.co.uk> Date: Sat Oct 2 17:20:08 2021 +0100 coroutines: Handle initial awaiters with non-void returns [PR 100127]. The way in which a C++20 coroutine is specified discards any value that might be returned from the initial or final await expressions. This ICE was caused by an initial await expression with an await_resume () returning a reference, the function rewrite code was not set up to expect this. Fixed by looking through any indirection present and by explicitly discarding the value, if any, returned by await_resume(). It does not seem useful to make a diagnostic for this, since the user could define a generic awaiter that usefully returns values when used in a different position from the initial (or final) await expressions. Signed-off-by: Iain Sandoe <iain@sandoe.co.uk> PR c++/100127 gcc/cp/ChangeLog: * coroutines.cc (coro_rewrite_function_body): Handle initial await expressions that try to produce a reference value. gcc/testsuite/ChangeLog: * g++.dg/coroutines/pr100127.C: New test. Diff: --- gcc/cp/coroutines.cc | 8 +++- gcc/testsuite/g++.dg/coroutines/pr100127.C | 65 ++++++++++++++++++++++++++++++ 2 files changed, 72 insertions(+), 1 deletion(-) diff --git a/gcc/cp/coroutines.cc b/gcc/cp/coroutines.cc index bcc91739702..25931c92801 100644 --- a/gcc/cp/coroutines.cc +++ b/gcc/cp/coroutines.cc @@ -4211,9 +4211,15 @@ coro_rewrite_function_body (location_t fn_start, tree fnbody, tree orig, { /* Build a compound expression that sets the initial-await-resume-called variable true and then calls the - initial suspend expression await resume. */ + initial suspend expression await resume. + In the case that the user decides to make the initial await + await_resume() return a value, we need to discard it and, it is + a reference type, look past the indirection. */ + if (INDIRECT_REF_P (initial_await)) + initial_await = TREE_OPERAND (initial_await, 0); tree vec = TREE_OPERAND (initial_await, 3); tree aw_r = TREE_VEC_ELT (vec, 2); + aw_r = convert_to_void (aw_r, ICV_STATEMENT, tf_warning_or_error); tree update = build2 (MODIFY_EXPR, boolean_type_node, i_a_r_c, boolean_true_node); aw_r = cp_build_compound_expr (update, aw_r, tf_warning_or_error); diff --git a/gcc/testsuite/g++.dg/coroutines/pr100127.C b/gcc/testsuite/g++.dg/coroutines/pr100127.C new file mode 100644 index 00000000000..374cd710077 --- /dev/null +++ b/gcc/testsuite/g++.dg/coroutines/pr100127.C @@ -0,0 +1,65 @@ +#ifdef __clang__ +#include <experimental/coroutine> +namespace std { + using namespace std::experimental; +} +#else +#include <coroutine> +#endif +#include <optional> + +struct future +{ + using value_type = int; + struct promise_type; + using handle_type = std::coroutine_handle<promise_type>; + + handle_type _coroutine; + + future(handle_type h) : _coroutine{h} {} + + ~future() noexcept{ + if (_coroutine) { + _coroutine.destroy(); + } + } + + value_type get() { + auto ptr = _coroutine.promise()._value; + return *ptr; + } + + struct promise_type { + std::optional<value_type> _value = std::nullopt; + + future get_return_object() { + return future{handle_type::from_promise(*this)}; + } + void return_value(value_type val) { + _value = static_cast<value_type &&>(val); + } + auto initial_suspend() noexcept { + class awaiter { + std::optional<value_type> & value; + public: + explicit awaiter(std::optional<value_type> & val) noexcept : value{val} {} + bool await_ready() noexcept { return value.has_value(); } + void await_suspend(handle_type) noexcept { } + value_type & await_resume() noexcept { return *value; } + }; + + return awaiter{_value}; + } + std::suspend_always final_suspend() noexcept { + return {}; + } + //void return_void() {} + void unhandled_exception() {} + }; +}; + +future create_future() +{ co_return 2021; } + +int main() +{ auto f = create_future(); }
reply other threads:[~2021-12-17 16:58 UTC|newest] Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=20211217165809.0F0163858412@sourceware.org \ --to=iains@gcc.gnu.org \ --cc=gcc-cvs@gcc.gnu.org \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: linkBe sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).