Commit 0666767e by Iain Sandoe

coroutines: Revise await expansions [PR94528]

The expansions for await expressions were specific to particular
cases, this revises it to be more generic.

a: Revise co_await statement walkers.

We want to process the co_awaits one statement at a time.
We also want to be able to determine the insertion points for
new bind scopes needed to cater for temporaries that are
captured by reference and have lifetimes that need extension
to the end of the full expression.  Likewise, the handling of
captured references in the evaluation of conditions might
result in the need to make a frame copy.

This reorganises the statement walking code to make it easier to
extend for these purposes.

b: Factor reference-captured temp code.

We want to be able to use the code that writes a new bind expr
with vars (and their initializers) from several places, so split
that out of the maybe_promote_captured_temps() function into a
new replace_statement_captures ().  Update some comments.

c: Generalize await statement expansion.

This revises the expansion to avoid the need to expand conditionally
on the tree type.  It resolves PR 94528.

gcc/cp/ChangeLog:

2020-04-10  Iain Sandoe  <iain@sandoe.co.uk>

	PR c++/94538
	* coroutines.cc (co_await_expander): Remove.
	(expand_one_await_expression): New.
	(process_one_statement): New.
	(await_statement_expander): New.
	(build_actor_fn): Revise to use per-statement expander.
	(struct susp_frame_data): Reorder and comment.
	(register_awaits): Factor code.
	(replace_statement_captures): New, factored from...
	(maybe_promote_captured_temps):.. here.
	(await_statement_walker): Revise to process per statement.
	(morph_fn_to_coro): Use revised susp_frame_data layout.

gcc/testsuite/ChangeLog:

2020-04-10  Iain Sandoe  <iain@sandoe.co.uk>

	PR c++/94538
	* g++.dg/coroutines/pr94528.C: New test.
parent 62c25d7a
2020-04-10 Iain Sandoe <iain@sandoe.co.uk>
PR c++/94538
* coroutines.cc (co_await_expander): Remove.
(expand_one_await_expression): New.
(process_one_statement): New.
(await_statement_expander): New.
(build_actor_fn): Revise to use per-statement expander.
(struct susp_frame_data): Reorder and comment.
(register_awaits): Factor code.
(replace_statement_captures): New, factored from...
(maybe_promote_captured_temps):.. here.
(await_statement_walker): Revise to process per statement.
(morph_fn_to_coro): Use revised susp_frame_data layout.
2020-04-10 Marek Polacek <polacek@redhat.com> 2020-04-10 Marek Polacek <polacek@redhat.com>
PR c++/94149 PR c++/94149
......
2020-04-10 Iain Sandoe <iain@sandoe.co.uk>
PR c++/94538
* g++.dg/coroutines/pr94528.C: New test.
2020-04-10 Marek Polacek <polacek@redhat.com> 2020-04-10 Marek Polacek <polacek@redhat.com>
PR c++/94149 PR c++/94149
......
// { dg-additional-options "-std=c++20 -fpreprocessed -w" }
namespace std {
inline namespace {
template <typename _Result, typename> struct coroutine_traits {
using promise_type = _Result::promise_type;
};
template <typename = void> struct coroutine_handle;
template <> struct coroutine_handle<> { public: };
template <typename> struct coroutine_handle : coroutine_handle<> {};
struct suspend_always {
bool await_ready();
void await_suspend(coroutine_handle<>);
void await_resume();
};
} // namespace
} // namespace std
namespace coro = std;
namespace cppcoro {
class task {
private:
struct awaitable_base {
coro::coroutine_handle<> m_coroutine;
bool await_ready() const noexcept;
void await_suspend(coro::coroutine_handle<> awaitingCoroutine) noexcept;
};
public:
auto operator co_await() const &noexcept {
struct awaitable : awaitable_base {
decltype(auto) await_resume() {}
};
return awaitable{m_coroutine};
}
private:
coro::coroutine_handle<> m_coroutine;
};
class shared_task;
class shared_task_promise_base {
struct final_awaiter {
bool await_ready() const noexcept;
template <typename PROMISE>
void await_suspend(coro::coroutine_handle<PROMISE> h) noexcept;
void await_resume() noexcept;
};
public:
coro::suspend_always initial_suspend() noexcept;
final_awaiter final_suspend() noexcept;
void unhandled_exception() noexcept;
};
class shared_task_promise : public shared_task_promise_base {
public:
shared_task get_return_object() noexcept;
void return_void() noexcept;
};
class shared_task {
public:
using promise_type = shared_task_promise;
};
auto make_shared_task(cppcoro::task awaitable) -> shared_task {
co_return co_await static_cast<cppcoro::task &&>(awaitable);
}
} // namespace cppcoro
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment