aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp
diff options
context:
space:
mode:
authorIain Sandoe <iain@sandoe.co.uk>2020-06-02 16:47:54 +0100
committerIain Sandoe <iain@sandoe.co.uk>2020-06-02 19:10:28 +0100
commit324276ff9b1aa5128e5cb9f5d43182d1ebab0752 (patch)
treed38572dea31e7d15363b5f645da700f6c6396638 /gcc/cp
parentce95db102aab4dea9af24a20de78db2f57c0a37b (diff)
downloadgcc-324276ff9b1aa5128e5cb9f5d43182d1ebab0752.zip
gcc-324276ff9b1aa5128e5cb9f5d43182d1ebab0752.tar.gz
gcc-324276ff9b1aa5128e5cb9f5d43182d1ebab0752.tar.bz2
coroutines: Wrap co_await in a target expr where needed [PR95050]
Since the co_await expression is mostly opaque to the existing machinery, we were hiding the details of the await_resume return value. If that needs to be wrapped in a target expression, then emulate this with the whole co_await. Similarly, if the await expression we build in response to co_await p.yield_value (e) is wrapped in a target expression, then we need to transfer that wrapper to the resultant CO_YIELD_EXPR (which is, itself, just a proxy for the underlying co_await). gcc/cp/ChangeLog: PR c++/95050 * coroutines.cc (build_co_await): Wrap the co_await expression in a TARGET_EXPR, where needed. (finish_co_yield_expr): Likewise. gcc/testsuite/ChangeLog: PR c++/95050 * g++.dg/coroutines/pr95050.C: New test.
Diffstat (limited to 'gcc/cp')
-rw-r--r--gcc/cp/coroutines.cc29
1 files changed, 27 insertions, 2 deletions
diff --git a/gcc/cp/coroutines.cc b/gcc/cp/coroutines.cc
index e90387b..e689625 100644
--- a/gcc/cp/coroutines.cc
+++ b/gcc/cp/coroutines.cc
@@ -816,6 +816,12 @@ build_co_await (location_t loc, tree a, suspend_point_kind suspend_kind)
tree awaiter_calls = make_tree_vec (3);
TREE_VEC_ELT (awaiter_calls, 0) = awrd_call; /* await_ready(). */
TREE_VEC_ELT (awaiter_calls, 1) = awsp_call; /* await_suspend(). */
+ tree te = NULL_TREE;
+ if (TREE_CODE (awrs_call) == TARGET_EXPR)
+ {
+ te = awrs_call;
+ awrs_call = TREE_OPERAND (awrs_call, 1);
+ }
TREE_VEC_ELT (awaiter_calls, 2) = awrs_call; /* await_resume(). */
tree await_expr = build5_loc (loc, CO_AWAIT_EXPR,
@@ -823,7 +829,13 @@ build_co_await (location_t loc, tree a, suspend_point_kind suspend_kind)
a, e_proxy, o, awaiter_calls,
build_int_cst (integer_type_node,
(int) suspend_kind));
- return convert_from_reference (await_expr);
+ if (te)
+ {
+ TREE_OPERAND (te, 1) = await_expr;
+ await_expr = te;
+ }
+ tree t = convert_from_reference (await_expr);
+ return t;
}
tree
@@ -960,8 +972,21 @@ finish_co_yield_expr (location_t kw, tree expr)
tree op = build_co_await (kw, yield_call, CO_YIELD_SUSPEND_POINT);
if (op != error_mark_node)
{
- op = build2_loc (kw, CO_YIELD_EXPR, TREE_TYPE (op), expr, op);
+ if (REFERENCE_REF_P (op))
+ op = TREE_OPERAND (op, 0);
+ /* If the await expression is wrapped in a TARGET_EXPR, then transfer
+ that wrapper to the CO_YIELD_EXPR, since this is just a proxy for
+ its contained await. Otherwise, just build the CO_YIELD_EXPR. */
+ if (TREE_CODE (op) == TARGET_EXPR)
+ {
+ tree t = TREE_OPERAND (op, 1);
+ t = build2_loc (kw, CO_YIELD_EXPR, TREE_TYPE (t), expr, t);
+ TREE_OPERAND (op, 1) = t;
+ }
+ else
+ op = build2_loc (kw, CO_YIELD_EXPR, TREE_TYPE (op), expr, op);
TREE_SIDE_EFFECTS (op) = 1;
+ op = convert_from_reference (op);
}
return op;