Skip to content
Snippets Groups Projects
Commit 3dbc7721 authored by Iain Sandoe's avatar Iain Sandoe
Browse files

coroutines: Fix handling of conditional statements [PR94288]

Normally, when we find a statement containing an await expression
this will be expanded to a statement list implementing the control
flow implied.  The expansion process successively replaces each
await expression in a statement with the result of its await_resume().

In the case of conditional statements (if, while, do, switch) the
expansion of the condition (or expression in the case of do-while)
cannot take place 'inline', leading to the PR.

The solution is to evaluate the expression separately, and to
transform while and do-while loops into endless loops with a break
on the required condition.

In fixing this, I realised that I'd also made a thinko in the case
of expanding truth-and/or-if expressions, where one arm of the
expression might need to be short-circuited.  The mechanism for
expanding via the tree walk will not work correctly in this case and
we need to pre-expand any truth-and/or-if with an await expression
on its conditionally-taken arm.  This applies to any statement with
truth-and/or-if expressions, so can be handled generically.

gcc/cp/ChangeLog:

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

	PR c++/94288
	* coroutines.cc (await_statement_expander): Simplify cases.
	(struct susp_frame_data): Add fields for truth and/or if
	cases, rename one field.
	(analyze_expression_awaits): New.
	(expand_one_truth_if): New.
	(add_var_to_bind): New helper.
	(coro_build_add_if_not_cond_break): New helper.
	(await_statement_walker): Handle conditional expressions,
	handle expansion of truth-and/or-if cases.
	(bind_expr_find_in_subtree): New, checking-only.
	(coro_body_contains_bind_expr_p): New, checking-only.
	(morph_fn_to_coro): Ensure that we have a top level bind
	expression.

gcc/testsuite/ChangeLog:

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

	PR c++/94288
	* g++.dg/coroutines/torture/co-await-18-if-cond.C: New test.
	* g++.dg/coroutines/torture/co-await-19-while-cond.C: New test.
	* g++.dg/coroutines/torture/co-await-20-do-while-cond.C: New test.
	* g++.dg/coroutines/torture/co-await-21-switch-value.C: New test.
	* g++.dg/coroutines/torture/co-await-22-truth-and-of-if.C: New test.
	* g++.dg/coroutines/torture/co-ret-16-simple-control-flow.C: New test.
parent 7291b2ed
No related branches found
No related tags found
Loading
Loading
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment