aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp/coroutines.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/cp/coroutines.cc')
-rw-r--r--gcc/cp/coroutines.cc63
1 files changed, 27 insertions, 36 deletions
diff --git a/gcc/cp/coroutines.cc b/gcc/cp/coroutines.cc
index 7f5d30c..97eee6e 100644
--- a/gcc/cp/coroutines.cc
+++ b/gcc/cp/coroutines.cc
@@ -2027,8 +2027,10 @@ expand_one_await_expression (tree *expr, tree *await_expr, void *d)
tree awaiter_calls = TREE_OPERAND (saved_co_await, 3);
tree source = TREE_OPERAND (saved_co_await, 4);
- bool is_final = (source
- && TREE_INT_CST_LOW (source) == (int) FINAL_SUSPEND_POINT);
+ bool is_final
+ = (source && TREE_INT_CST_LOW (source) == (int) FINAL_SUSPEND_POINT);
+ bool is_initial
+ = (source && TREE_INT_CST_LOW (source) == (int) INITIAL_SUSPEND_POINT);
/* Build labels for the destinations of the control flow when we are resuming
or destroying. */
@@ -2156,6 +2158,13 @@ expand_one_await_expression (tree *expr, tree *await_expr, void *d)
/* Resume point. */
add_stmt (build_stmt (loc, LABEL_EXPR, resume_label));
+ if (is_initial && data->i_a_r_c)
+ {
+ r = cp_build_modify_expr (loc, data->i_a_r_c, NOP_EXPR, boolean_true_node,
+ tf_warning_or_error);
+ finish_expr_stmt (r);
+ }
+
/* This will produce the value (if one is provided) from the co_await
expression. */
tree resume_call = TREE_VEC_ELT (awaiter_calls, 2); /* await_resume(). */
@@ -2654,8 +2663,12 @@ build_actor_fn (location_t loc, tree coro_frame_type, tree actor, tree fnbody,
/* We've now rewritten the tree and added the initial and final
co_awaits. Now pass over the tree and expand the co_awaits. */
+ tree i_a_r_c = NULL_TREE;
+ if (flag_exceptions)
+ i_a_r_c = coro_build_frame_access_expr (actor_frame, coro_frame_i_a_r_c_id,
+ false, tf_warning_or_error);
- coro_aw_data data = {actor, actor_fp, resume_idx_var, NULL_TREE,
+ coro_aw_data data = {actor, actor_fp, resume_idx_var, i_a_r_c,
ash, del_promise_label, ret_label,
continue_label, restart_dispatch_label, continuation, 2};
cp_walk_tree (&actor_body, await_statement_expander, &data, NULL);
@@ -4014,12 +4027,14 @@ rewrite_param_uses (tree *stmt, int *do_subtree ATTRIBUTE_UNUSED, void *d)
}
/* Build up a set of info that determines how each param copy will be
- handled. */
+ handled. We store this in a hash map so that we can access it from
+ a tree walk callback that re-writes the original parameters to their
+ copies. */
-static void
-analyze_fn_parms (tree orig, hash_map<tree, param_info> *param_uses)
+void
+cp_coroutine_transform::analyze_fn_parms ()
{
- if (!DECL_ARGUMENTS (orig))
+ if (!DECL_ARGUMENTS (orig_fn_decl))
return;
/* Build a hash map with an entry for each param.
@@ -4029,19 +4044,19 @@ analyze_fn_parms (tree orig, hash_map<tree, param_info> *param_uses)
Then a tree list of the uses.
The second two entries start out empty - and only get populated
when we see uses. */
- bool lambda_p = LAMBDA_FUNCTION_P (orig);
+ bool lambda_p = LAMBDA_FUNCTION_P (orig_fn_decl);
/* Count the param copies from 1 as per the std. */
unsigned parm_num = 1;
- for (tree arg = DECL_ARGUMENTS (orig); arg != NULL;
+ for (tree arg = DECL_ARGUMENTS (orig_fn_decl); arg != NULL;
++parm_num, arg = DECL_CHAIN (arg))
{
bool existed;
- param_info &parm = param_uses->get_or_insert (arg, &existed);
+ param_info &parm = param_uses.get_or_insert (arg, &existed);
gcc_checking_assert (!existed);
parm.body_uses = NULL;
tree actual_type = TREE_TYPE (arg);
- actual_type = complete_type_or_else (actual_type, orig);
+ actual_type = complete_type_or_else (actual_type, orig_fn_decl);
if (actual_type == NULL_TREE)
actual_type = error_mark_node;
parm.orig_type = actual_type;
@@ -4435,30 +4450,6 @@ cp_coroutine_transform::wrap_original_function_body ()
tree tcb = build_stmt (loc, TRY_BLOCK, NULL_TREE, NULL_TREE);
add_stmt (tcb);
TRY_STMTS (tcb) = push_stmt_list ();
- if (initial_await != error_mark_node)
- {
- /* Build a compound expression that sets the
- initial-await-resume-called variable true and then calls the
- 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);
- /* In the case that the initial_await returns a target expression
- we might need to look through that to update the await expr. */
- tree iaw = initial_await;
- if (TREE_CODE (iaw) == TARGET_EXPR)
- iaw = TARGET_EXPR_INITIAL (iaw);
- gcc_checking_assert (TREE_CODE (iaw) == CO_AWAIT_EXPR);
- tree vec = TREE_OPERAND (iaw, 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);
- TREE_VEC_ELT (vec, 2) = aw_r;
- }
/* Add the initial await to the start of the user-authored function. */
finish_expr_stmt (initial_await);
/* Append the original function body. */
@@ -5260,7 +5251,7 @@ cp_coroutine_transform::apply_transforms ()
/* Collect information on the original function params and their use in the
function body. */
- analyze_fn_parms (orig_fn_decl, &param_uses);
+ analyze_fn_parms ();
/* Declare the actor and destroyer functions, the following code needs to
see these. */