Daily bump.
[official-gcc.git] / gcc / cp / coroutines.cc
blob2f45575bd92ce13a435b5c00c264dc45e362752f
1 /* coroutine-specific state, expansions and tests.
3 Copyright (C) 2018-2021 Free Software Foundation, Inc.
5 Contributed by Iain Sandoe <iain@sandoe.co.uk> under contract to Facebook.
7 This file is part of GCC.
9 GCC is free software; you can redistribute it and/or modify it under
10 the terms of the GNU General Public License as published by the Free
11 Software Foundation; either version 3, or (at your option) any later
12 version.
14 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
15 WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 for more details.
19 You should have received a copy of the GNU General Public License
20 along with GCC; see the file COPYING3. If not see
21 <http://www.gnu.org/licenses/>. */
23 #include "config.h"
24 #include "system.h"
25 #include "coretypes.h"
26 #include "target.h"
27 #include "cp-tree.h"
28 #include "stringpool.h"
29 #include "stmt.h"
30 #include "stor-layout.h"
31 #include "tree-iterator.h"
32 #include "tree.h"
33 #include "gcc-rich-location.h"
34 #include "hash-map.h"
36 static bool coro_promise_type_found_p (tree, location_t);
38 /* GCC C++ coroutines implementation.
40 The user authors a function that becomes a coroutine (lazily) by
41 making use of any of the co_await, co_yield or co_return keywords.
43 Unlike a regular function, where the activation record is placed on the
44 stack, and is destroyed on function exit, a coroutine has some state that
45 persists between calls - the coroutine frame (analogous to a stack frame).
47 We transform the user's function into three pieces:
48 1. A so-called ramp function, that establishes the coroutine frame and
49 begins execution of the coroutine.
50 2. An actor function that contains the state machine corresponding to the
51 user's suspend/resume structure.
52 3. A stub function that calls the actor function in 'destroy' mode.
54 The actor function is executed:
55 * from "resume point 0" by the ramp.
56 * from resume point N ( > 0 ) for handle.resume() calls.
57 * from the destroy stub for destroy point N for handle.destroy() calls.
59 The functions in this file carry out the necessary analysis of, and
60 transforms to, the AST to perform this.
62 The C++ coroutine design makes use of some helper functions that are
63 authored in a so-called "promise" class provided by the user.
65 At parse time (or post substitution) the type of the coroutine promise
66 will be determined. At that point, we can look up the required promise
67 class methods and issue diagnostics if they are missing or incorrect. To
68 avoid repeating these actions at code-gen time, we make use of temporary
69 'proxy' variables for the coroutine handle and the promise - which will
70 eventually be instantiated in the coroutine frame.
72 Each of the keywords will expand to a code sequence (although co_yield is
73 just syntactic sugar for a co_await).
75 We defer the analysis and transformation until template expansion is
76 complete so that we have complete types at that time. */
79 /* The state that we collect during parsing (and template expansion) for
80 a coroutine. */
82 struct GTY((for_user)) coroutine_info
84 tree function_decl; /* The original function decl. */
85 tree actor_decl; /* The synthesized actor function. */
86 tree destroy_decl; /* The synthesized destroy function. */
87 tree promise_type; /* The cached promise type for this function. */
88 tree handle_type; /* The cached coroutine handle for this function. */
89 tree self_h_proxy; /* A handle instance that is used as the proxy for the
90 one that will eventually be allocated in the coroutine
91 frame. */
92 tree promise_proxy; /* Likewise, a proxy promise instance. */
93 tree return_void; /* The expression for p.return_void() if it exists. */
94 location_t first_coro_keyword; /* The location of the keyword that made this
95 function into a coroutine. */
96 /* Flags to avoid repeated errors for per-function issues. */
97 bool coro_ret_type_error_emitted;
98 bool coro_promise_error_emitted;
99 bool coro_co_return_error_emitted;
102 struct coroutine_info_hasher : ggc_ptr_hash<coroutine_info>
104 typedef tree compare_type; /* We only compare the function decl. */
105 static inline hashval_t hash (coroutine_info *);
106 static inline hashval_t hash (const compare_type &);
107 static inline bool equal (coroutine_info *, coroutine_info *);
108 static inline bool equal (coroutine_info *, const compare_type &);
111 /* This table holds all the collected coroutine state for coroutines in
112 the current translation unit. */
114 static GTY (()) hash_table<coroutine_info_hasher> *coroutine_info_table;
116 /* We will initialize state lazily. */
117 static bool coro_initialized = false;
119 /* Return a hash value for the entry pointed to by INFO.
120 The compare type is a tree, but the only trees we are going use are
121 function decls. We use the DECL_UID as the hash value since that is
122 stable across PCH. */
124 hashval_t
125 coroutine_info_hasher::hash (coroutine_info *info)
127 return DECL_UID (info->function_decl);
130 /* Return a hash value for the compare value COMP. */
132 hashval_t
133 coroutine_info_hasher::hash (const compare_type& comp)
135 return DECL_UID (comp);
138 /* Return true if the entries pointed to by LHS and RHS are for the
139 same coroutine. */
141 bool
142 coroutine_info_hasher::equal (coroutine_info *lhs, coroutine_info *rhs)
144 return lhs->function_decl == rhs->function_decl;
147 bool
148 coroutine_info_hasher::equal (coroutine_info *lhs, const compare_type& rhs)
150 return lhs->function_decl == rhs;
153 /* Get the existing coroutine_info for FN_DECL, or insert a new one if the
154 entry does not yet exist. */
156 coroutine_info *
157 get_or_insert_coroutine_info (tree fn_decl)
159 gcc_checking_assert (coroutine_info_table != NULL);
161 coroutine_info **slot = coroutine_info_table->find_slot_with_hash
162 (fn_decl, coroutine_info_hasher::hash (fn_decl), INSERT);
164 if (*slot == NULL)
166 *slot = new (ggc_cleared_alloc<coroutine_info> ()) coroutine_info ();
167 (*slot)->function_decl = fn_decl;
170 return *slot;
173 /* Get the existing coroutine_info for FN_DECL, fail if it doesn't exist. */
175 coroutine_info *
176 get_coroutine_info (tree fn_decl)
178 if (coroutine_info_table == NULL)
179 return NULL;
181 coroutine_info **slot = coroutine_info_table->find_slot_with_hash
182 (fn_decl, coroutine_info_hasher::hash (fn_decl), NO_INSERT);
183 if (slot)
184 return *slot;
185 return NULL;
188 /* We will lazily create all the identifiers that are used by coroutines
189 on the first attempt to lookup the traits. */
191 /* Identifiers that are used by all coroutines. */
193 static GTY(()) tree coro_traits_identifier;
194 static GTY(()) tree coro_handle_identifier;
195 static GTY(()) tree coro_promise_type_identifier;
197 /* Required promise method name identifiers. */
199 static GTY(()) tree coro_await_transform_identifier;
200 static GTY(()) tree coro_initial_suspend_identifier;
201 static GTY(()) tree coro_final_suspend_identifier;
202 static GTY(()) tree coro_return_void_identifier;
203 static GTY(()) tree coro_return_value_identifier;
204 static GTY(()) tree coro_yield_value_identifier;
205 static GTY(()) tree coro_resume_identifier;
206 static GTY(()) tree coro_address_identifier;
207 static GTY(()) tree coro_from_address_identifier;
208 static GTY(()) tree coro_get_return_object_identifier;
209 static GTY(()) tree coro_gro_on_allocation_fail_identifier;
210 static GTY(()) tree coro_unhandled_exception_identifier;
212 /* Awaitable methods. */
214 static GTY(()) tree coro_await_ready_identifier;
215 static GTY(()) tree coro_await_suspend_identifier;
216 static GTY(()) tree coro_await_resume_identifier;
218 /* Accessors for the coroutine frame state used by the implementation. */
220 static GTY(()) tree coro_resume_fn_id;
221 static GTY(()) tree coro_destroy_fn_id;
222 static GTY(()) tree coro_promise_id;
223 static GTY(()) tree coro_frame_needs_free_id;
224 static GTY(()) tree coro_resume_index_id;
225 static GTY(()) tree coro_self_handle_id;
226 static GTY(()) tree coro_actor_continue_id;
227 static GTY(()) tree coro_frame_i_a_r_c_id;
229 /* Create the identifiers used by the coroutines library interfaces and
230 the implementation frame state. */
232 static void
233 coro_init_identifiers ()
235 coro_traits_identifier = get_identifier ("coroutine_traits");
236 coro_handle_identifier = get_identifier ("coroutine_handle");
237 coro_promise_type_identifier = get_identifier ("promise_type");
239 coro_await_transform_identifier = get_identifier ("await_transform");
240 coro_initial_suspend_identifier = get_identifier ("initial_suspend");
241 coro_final_suspend_identifier = get_identifier ("final_suspend");
242 coro_return_void_identifier = get_identifier ("return_void");
243 coro_return_value_identifier = get_identifier ("return_value");
244 coro_yield_value_identifier = get_identifier ("yield_value");
245 coro_resume_identifier = get_identifier ("resume");
246 coro_address_identifier = get_identifier ("address");
247 coro_from_address_identifier = get_identifier ("from_address");
248 coro_get_return_object_identifier = get_identifier ("get_return_object");
249 coro_gro_on_allocation_fail_identifier =
250 get_identifier ("get_return_object_on_allocation_failure");
251 coro_unhandled_exception_identifier = get_identifier ("unhandled_exception");
253 coro_await_ready_identifier = get_identifier ("await_ready");
254 coro_await_suspend_identifier = get_identifier ("await_suspend");
255 coro_await_resume_identifier = get_identifier ("await_resume");
257 /* Coroutine state frame field accessors. */
258 coro_resume_fn_id = get_identifier ("_Coro_resume_fn");
259 coro_destroy_fn_id = get_identifier ("_Coro_destroy_fn");
260 coro_promise_id = get_identifier ("_Coro_promise");
261 coro_frame_needs_free_id = get_identifier ("_Coro_frame_needs_free");
262 coro_frame_i_a_r_c_id = get_identifier ("_Coro_initial_await_resume_called");
263 coro_resume_index_id = get_identifier ("_Coro_resume_index");
264 coro_self_handle_id = get_identifier ("_Coro_self_handle");
265 coro_actor_continue_id = get_identifier ("_Coro_actor_continue");
268 /* Trees we only need to set up once. */
270 static GTY(()) tree coro_traits_templ;
271 static GTY(()) tree coro_handle_templ;
272 static GTY(()) tree void_coro_handle_type;
274 /* ================= Parse, Semantics and Type checking ================= */
276 /* This initial set of routines are helper for the parsing and template
277 expansion phases.
279 At the completion of this, we will have completed trees for each of the
280 keywords, but making use of proxy variables for the self-handle and the
281 promise class instance. */
283 /* [coroutine.traits]
284 Lookup the coroutine_traits template decl. */
286 static tree
287 find_coro_traits_template_decl (location_t kw)
289 /* If we are missing fundamental information, such as the traits, (or the
290 declaration found is not a type template), then don't emit an error for
291 every keyword in a TU, just do it once. */
292 static bool traits_error_emitted = false;
294 tree traits_decl = lookup_qualified_name (std_node, coro_traits_identifier,
295 LOOK_want::NORMAL,
296 /*complain=*/!traits_error_emitted);
297 if (traits_decl == error_mark_node
298 || !DECL_TYPE_TEMPLATE_P (traits_decl))
300 if (!traits_error_emitted)
302 gcc_rich_location richloc (kw);
303 error_at (&richloc, "coroutines require a traits template; cannot"
304 " find %<%E::%E%>", std_node, coro_traits_identifier);
305 inform (&richloc, "perhaps %<#include <coroutine>%> is missing");
306 traits_error_emitted = true;
308 return NULL_TREE;
310 else
311 return traits_decl;
314 /* Instantiate Coroutine traits for the function signature. */
316 static tree
317 instantiate_coro_traits (tree fndecl, location_t kw)
319 /* [coroutine.traits.primary]
320 So now build up a type list for the template <typename _R, typename...>.
321 The types are the function's arg types and _R is the function return
322 type. */
324 tree functyp = TREE_TYPE (fndecl);
325 tree arg = DECL_ARGUMENTS (fndecl);
326 tree arg_node = TYPE_ARG_TYPES (functyp);
327 tree argtypes = make_tree_vec (list_length (arg_node)-1);
328 unsigned p = 0;
330 while (arg_node != NULL_TREE && !VOID_TYPE_P (TREE_VALUE (arg_node)))
332 if (is_this_parameter (arg)
333 || DECL_NAME (arg) == closure_identifier)
335 /* We pass a reference to *this to the param preview. */
336 tree ct = TREE_TYPE (TREE_TYPE (arg));
337 TREE_VEC_ELT (argtypes, p++) = cp_build_reference_type (ct, false);
339 else
340 TREE_VEC_ELT (argtypes, p++) = TREE_VALUE (arg_node);
342 arg_node = TREE_CHAIN (arg_node);
343 arg = DECL_CHAIN (arg);
346 tree argtypepack = cxx_make_type (TYPE_ARGUMENT_PACK);
347 SET_ARGUMENT_PACK_ARGS (argtypepack, argtypes);
349 tree targ = make_tree_vec (2);
350 TREE_VEC_ELT (targ, 0) = TREE_TYPE (functyp);
351 TREE_VEC_ELT (targ, 1) = argtypepack;
353 tree traits_class
354 = lookup_template_class (coro_traits_templ, targ,
355 /*in_decl=*/NULL_TREE, /*context=*/NULL_TREE,
356 /*entering scope=*/false, tf_warning_or_error);
358 if (traits_class == error_mark_node)
360 error_at (kw, "cannot instantiate %<coroutine traits%>");
361 return NULL_TREE;
364 return traits_class;
367 /* [coroutine.handle] */
369 static tree
370 find_coro_handle_template_decl (location_t kw)
372 /* As for the coroutine traits, this error is per TU, so only emit
373 it once. */
374 static bool coro_handle_error_emitted = false;
375 tree handle_decl = lookup_qualified_name (std_node, coro_handle_identifier,
376 LOOK_want::NORMAL,
377 !coro_handle_error_emitted);
378 if (handle_decl == error_mark_node
379 || !DECL_CLASS_TEMPLATE_P (handle_decl))
381 if (!coro_handle_error_emitted)
382 error_at (kw, "coroutines require a handle class template;"
383 " cannot find %<%E::%E%>", std_node, coro_handle_identifier);
384 coro_handle_error_emitted = true;
385 return NULL_TREE;
387 else
388 return handle_decl;
391 /* Instantiate the handle template for a given promise type. */
393 static tree
394 instantiate_coro_handle_for_promise_type (location_t kw, tree promise_type)
396 /* So now build up a type list for the template, one entry, the promise. */
397 tree targ = make_tree_vec (1);
398 TREE_VEC_ELT (targ, 0) = promise_type;
399 tree handle_type
400 = lookup_template_class (coro_handle_identifier, targ,
401 /* in_decl=*/NULL_TREE,
402 /* context=*/std_node,
403 /* entering scope=*/false, tf_warning_or_error);
405 if (handle_type == error_mark_node)
407 error_at (kw, "cannot instantiate a %<coroutine handle%> for"
408 " promise type %qT", promise_type);
409 return NULL_TREE;
412 return handle_type;
415 /* Look for the promise_type in the instantiated traits. */
417 static tree
418 find_promise_type (tree traits_class)
420 tree promise_type
421 = lookup_member (traits_class, coro_promise_type_identifier,
422 /* protect=*/1, /*want_type=*/true, tf_warning_or_error);
424 if (promise_type)
425 promise_type
426 = complete_type_or_else (TREE_TYPE (promise_type), promise_type);
428 /* NULL_TREE on fail. */
429 return promise_type;
432 static bool
433 coro_promise_type_found_p (tree fndecl, location_t loc)
435 gcc_assert (fndecl != NULL_TREE);
437 if (!coro_initialized)
439 /* Trees we only need to create once.
440 Set up the identifiers we will use. */
441 coro_init_identifiers ();
443 /* Coroutine traits template. */
444 coro_traits_templ = find_coro_traits_template_decl (loc);
445 if (coro_traits_templ == NULL_TREE)
446 return false;
448 /* coroutine_handle<> template. */
449 coro_handle_templ = find_coro_handle_template_decl (loc);
450 if (coro_handle_templ == NULL_TREE)
451 return false;
453 /* We can also instantiate the void coroutine_handle<> */
454 void_coro_handle_type =
455 instantiate_coro_handle_for_promise_type (loc, NULL_TREE);
456 if (void_coro_handle_type == NULL_TREE)
457 return false;
459 /* A table to hold the state, per coroutine decl. */
460 gcc_checking_assert (coroutine_info_table == NULL);
461 coroutine_info_table =
462 hash_table<coroutine_info_hasher>::create_ggc (11);
464 if (coroutine_info_table == NULL)
465 return false;
467 coro_initialized = true;
470 /* Save the coroutine data on the side to avoid the overhead on every
471 function decl tree. */
473 coroutine_info *coro_info = get_or_insert_coroutine_info (fndecl);
474 /* Without this, we cannot really proceed. */
475 gcc_checking_assert (coro_info);
477 /* If we don't already have a current promise type, try to look it up. */
478 if (coro_info->promise_type == NULL_TREE)
480 /* Get the coroutine traits template class instance for the function
481 signature we have - coroutine_traits <R, ...> */
483 tree templ_class = instantiate_coro_traits (fndecl, loc);
485 /* Find the promise type for that. */
486 coro_info->promise_type = find_promise_type (templ_class);
488 /* If we don't find it, punt on the rest. */
489 if (coro_info->promise_type == NULL_TREE)
491 if (!coro_info->coro_promise_error_emitted)
492 error_at (loc, "unable to find the promise type for"
493 " this coroutine");
494 coro_info->coro_promise_error_emitted = true;
495 return false;
498 /* Test for errors in the promise type that can be determined now. */
499 tree has_ret_void = lookup_member (coro_info->promise_type,
500 coro_return_void_identifier,
501 /*protect=*/1, /*want_type=*/0,
502 tf_none);
503 tree has_ret_val = lookup_member (coro_info->promise_type,
504 coro_return_value_identifier,
505 /*protect=*/1, /*want_type=*/0,
506 tf_none);
507 if (has_ret_void && has_ret_val)
509 location_t ploc = DECL_SOURCE_LOCATION (fndecl);
510 if (!coro_info->coro_co_return_error_emitted)
511 error_at (ploc, "the coroutine promise type %qT declares both"
512 " %<return_value%> and %<return_void%>",
513 coro_info->promise_type);
514 inform (DECL_SOURCE_LOCATION (BASELINK_FUNCTIONS (has_ret_void)),
515 "%<return_void%> declared here");
516 inform (DECL_SOURCE_LOCATION (BASELINK_FUNCTIONS (has_ret_val)),
517 "%<return_value%> declared here");
518 coro_info->coro_co_return_error_emitted = true;
519 return false;
522 /* Try to find the handle type for the promise. */
523 tree handle_type =
524 instantiate_coro_handle_for_promise_type (loc, coro_info->promise_type);
525 if (handle_type == NULL_TREE)
526 return false;
528 /* Complete this, we're going to use it. */
529 coro_info->handle_type = complete_type_or_else (handle_type, fndecl);
531 /* Diagnostic would be emitted by complete_type_or_else. */
532 if (!coro_info->handle_type)
533 return false;
535 /* Build a proxy for a handle to "self" as the param to
536 await_suspend() calls. */
537 coro_info->self_h_proxy
538 = build_lang_decl (VAR_DECL, coro_self_handle_id,
539 coro_info->handle_type);
541 /* Build a proxy for the promise so that we can perform lookups. */
542 coro_info->promise_proxy
543 = build_lang_decl (VAR_DECL, coro_promise_id,
544 coro_info->promise_type);
546 /* Note where we first saw a coroutine keyword. */
547 coro_info->first_coro_keyword = loc;
550 return true;
553 /* Map from actor or destroyer to ramp. */
554 static GTY(()) hash_map<tree, tree> *to_ramp;
556 /* Given a tree that is an actor or destroy, find the ramp function. */
558 tree
559 coro_get_ramp_function (tree decl)
561 if (!to_ramp)
562 return NULL_TREE;
563 tree *p = to_ramp->get (decl);
564 if (p)
565 return *p;
566 return NULL_TREE;
569 /* Given the DECL for a ramp function (the user's original declaration) return
570 the actor function if it has been defined. */
572 tree
573 coro_get_actor_function (tree decl)
575 if (coroutine_info *info = get_coroutine_info (decl))
576 return info->actor_decl;
578 return NULL_TREE;
581 /* Given the DECL for a ramp function (the user's original declaration) return
582 the destroy function if it has been defined. */
584 tree
585 coro_get_destroy_function (tree decl)
587 if (coroutine_info *info = get_coroutine_info (decl))
588 return info->destroy_decl;
590 return NULL_TREE;
593 /* These functions assumes that the caller has verified that the state for
594 the decl has been initialized, we try to minimize work here. */
596 static tree
597 get_coroutine_promise_type (tree decl)
599 if (coroutine_info *info = get_coroutine_info (decl))
600 return info->promise_type;
602 return NULL_TREE;
605 static tree
606 get_coroutine_handle_type (tree decl)
608 if (coroutine_info *info = get_coroutine_info (decl))
609 return info->handle_type;
611 return NULL_TREE;
614 static tree
615 get_coroutine_self_handle_proxy (tree decl)
617 if (coroutine_info *info = get_coroutine_info (decl))
618 return info->self_h_proxy;
620 return NULL_TREE;
623 static tree
624 get_coroutine_promise_proxy (tree decl)
626 if (coroutine_info *info = get_coroutine_info (decl))
627 return info->promise_proxy;
629 return NULL_TREE;
632 static tree
633 lookup_promise_method (tree fndecl, tree member_id, location_t loc,
634 bool musthave)
636 tree promise = get_coroutine_promise_type (fndecl);
637 tree pm_memb
638 = lookup_member (promise, member_id,
639 /*protect=*/1, /*want_type=*/0, tf_warning_or_error);
640 if (musthave && pm_memb == NULL_TREE)
642 error_at (loc, "no member named %qE in %qT", member_id, promise);
643 return error_mark_node;
645 return pm_memb;
648 /* Build an expression of the form p.method (args) where the p is a promise
649 object for the current coroutine.
650 OBJECT is the promise object instance to use, it may be NULL, in which case
651 we will use the promise_proxy instance for this coroutine.
652 ARGS may be NULL, for empty parm lists. */
654 static tree
655 coro_build_promise_expression (tree fn, tree promise_obj, tree member_id,
656 location_t loc, vec<tree, va_gc> **args,
657 bool musthave)
659 tree meth = lookup_promise_method (fn, member_id, loc, musthave);
660 if (meth == error_mark_node)
661 return error_mark_node;
663 /* If we don't find it, and it isn't needed, an empty return is OK. */
664 if (!meth)
665 return NULL_TREE;
667 tree promise
668 = promise_obj ? promise_obj
669 : get_coroutine_promise_proxy (current_function_decl);
670 tree expr;
671 if (BASELINK_P (meth))
672 expr = build_new_method_call (promise, meth, args, NULL_TREE,
673 LOOKUP_NORMAL, NULL, tf_warning_or_error);
674 else
676 expr = build_class_member_access_expr (promise, meth, NULL_TREE,
677 true, tf_warning_or_error);
678 vec<tree, va_gc> *real_args;
679 if (!args)
680 real_args = make_tree_vector ();
681 else
682 real_args = *args;
683 expr = build_op_call (expr, &real_args, tf_warning_or_error);
685 return expr;
688 /* Caching get for the expression p.return_void (). */
690 static tree
691 get_coroutine_return_void_expr (tree decl, location_t loc, bool musthave)
693 if (coroutine_info *info = get_coroutine_info (decl))
695 /* If we don't have it try to build it. */
696 if (!info->return_void)
697 info->return_void
698 = coro_build_promise_expression (current_function_decl, NULL,
699 coro_return_void_identifier,
700 loc, NULL, musthave);
701 /* Don't return an error if it's an optional call. */
702 if (!musthave && info->return_void == error_mark_node)
703 return NULL_TREE;
704 return info->return_void;
706 return musthave ? error_mark_node : NULL_TREE;
709 /* Lookup an Awaitable member, which should be await_ready, await_suspend
710 or await_resume. */
712 static tree
713 lookup_awaitable_member (tree await_type, tree member_id, location_t loc)
715 tree aw_memb
716 = lookup_member (await_type, member_id,
717 /*protect=*/1, /*want_type=*/0, tf_warning_or_error);
718 if (aw_memb == NULL_TREE)
720 error_at (loc, "no member named %qE in %qT", member_id, await_type);
721 return error_mark_node;
723 return aw_memb;
726 /* Here we check the constraints that are common to all keywords (since the
727 presence of a coroutine keyword makes the function into a coroutine). */
729 static bool
730 coro_common_keyword_context_valid_p (tree fndecl, location_t kw_loc,
731 const char *kw_name)
733 if (fndecl == NULL_TREE)
735 error_at (kw_loc, "%qs cannot be used outside a function", kw_name);
736 return false;
739 /* This is arranged in order of prohibitions in the std. */
740 if (DECL_MAIN_P (fndecl))
742 /* [basic.start.main] 3. The function main shall not be a coroutine. */
743 error_at (kw_loc, "%qs cannot be used in the %<main%> function",
744 kw_name);
745 return false;
748 if (DECL_DECLARED_CONSTEXPR_P (fndecl))
750 cp_function_chain->invalid_constexpr = true;
751 if (!is_instantiation_of_constexpr (fndecl))
753 /* [dcl.constexpr] 3.3 it shall not be a coroutine. */
754 error_at (kw_loc, "%qs cannot be used in a %<constexpr%> function",
755 kw_name);
756 return false;
760 if (FNDECL_USED_AUTO (fndecl))
762 /* [dcl.spec.auto] 15. A function declared with a return type that uses
763 a placeholder type shall not be a coroutine. */
764 error_at (kw_loc,
765 "%qs cannot be used in a function with a deduced return type",
766 kw_name);
767 return false;
770 if (varargs_function_p (fndecl))
772 /* [dcl.fct.def.coroutine] The parameter-declaration-clause of the
773 coroutine shall not terminate with an ellipsis that is not part
774 of a parameter-declaration. */
775 error_at (kw_loc,
776 "%qs cannot be used in a varargs function", kw_name);
777 return false;
780 if (DECL_CONSTRUCTOR_P (fndecl))
782 /* [class.ctor] 7. a constructor shall not be a coroutine. */
783 error_at (kw_loc, "%qs cannot be used in a constructor", kw_name);
784 return false;
787 if (DECL_DESTRUCTOR_P (fndecl))
789 /* [class.dtor] 21. a destructor shall not be a coroutine. */
790 error_at (kw_loc, "%qs cannot be used in a destructor", kw_name);
791 return false;
794 return true;
797 /* Here we check the constraints that are not per keyword. */
799 static bool
800 coro_function_valid_p (tree fndecl)
802 location_t f_loc = DECL_SOURCE_LOCATION (fndecl);
804 /* For cases where fundamental information cannot be found, e.g. the
805 coroutine traits are missing, we need to punt early. */
806 if (!coro_promise_type_found_p (fndecl, f_loc))
807 return false;
809 /* Since we think the function is a coroutine, that implies we parsed
810 a keyword that triggered this. Keywords check promise validity for
811 their context and thus the promise type should be known at this point. */
812 if (get_coroutine_handle_type (fndecl) == NULL_TREE
813 || get_coroutine_promise_type (fndecl) == NULL_TREE)
814 return false;
816 if (current_function_returns_value || current_function_returns_null)
818 /* TODO: record or extract positions of returns (and the first coro
819 keyword) so that we can add notes to the diagnostic about where
820 the bad keyword is and what made the function into a coro. */
821 error_at (f_loc, "a %<return%> statement is not allowed in coroutine;"
822 " did you mean %<co_return%>?");
823 return false;
826 return true;
829 enum suspend_point_kind {
830 CO_AWAIT_SUSPEND_POINT = 0,
831 CO_YIELD_SUSPEND_POINT,
832 INITIAL_SUSPEND_POINT,
833 FINAL_SUSPEND_POINT
836 /* Helper function to build a named variable for the temps we use for each
837 await point. The root of the name is determined by SUSPEND_KIND, and
838 the variable is of type V_TYPE. The awaitable number is reset each time
839 we encounter a final suspend. */
841 static tree
842 get_awaitable_var (suspend_point_kind suspend_kind, tree v_type)
844 static int awn = 0;
845 char *buf;
846 switch (suspend_kind)
848 default: buf = xasprintf ("Aw%d", awn++); break;
849 case CO_YIELD_SUSPEND_POINT: buf = xasprintf ("Yd%d", awn++); break;
850 case INITIAL_SUSPEND_POINT: buf = xasprintf ("Is"); break;
851 case FINAL_SUSPEND_POINT: buf = xasprintf ("Fs"); awn = 0; break;
853 tree ret = get_identifier (buf);
854 free (buf);
855 ret = build_lang_decl (VAR_DECL, ret, v_type);
856 DECL_ARTIFICIAL (ret) = true;
857 return ret;
860 /* Helpers to diagnose missing noexcept on final await expressions. */
862 static bool
863 coro_diagnose_throwing_fn (tree fndecl)
865 if (!TYPE_NOTHROW_P (TREE_TYPE (fndecl)))
867 location_t f_loc = cp_expr_loc_or_loc (fndecl,
868 DECL_SOURCE_LOCATION (fndecl));
869 error_at (f_loc, "the expression %qE is required to be non-throwing",
870 fndecl);
871 inform (f_loc, "must be declared with %<noexcept(true)%>");
872 return true;
874 return false;
877 static bool
878 coro_diagnose_throwing_final_aw_expr (tree expr)
880 tree t = TARGET_EXPR_INITIAL (expr);
881 tree fn = NULL_TREE;
882 if (TREE_CODE (t) == CALL_EXPR)
883 fn = CALL_EXPR_FN(t);
884 else if (TREE_CODE (t) == AGGR_INIT_EXPR)
885 fn = AGGR_INIT_EXPR_FN (t);
886 else if (TREE_CODE (t) == CONSTRUCTOR)
887 return false;
888 else
890 gcc_checking_assert (0 && "unhandled expression type");
891 return false;
893 fn = TREE_OPERAND (fn, 0);
894 return coro_diagnose_throwing_fn (fn);
897 /* This performs [expr.await] bullet 3.3 and validates the interface obtained.
898 It is also used to build the initial and final suspend points.
900 'a', 'o' and 'e' are used as per the description in the section noted.
902 A, the original yield/await expr, is found at source location LOC.
904 We will be constructing a CO_AWAIT_EXPR for a suspend point of one of
905 the four suspend_point_kind kinds. This is indicated by SUSPEND_KIND. */
907 static tree
908 build_co_await (location_t loc, tree a, suspend_point_kind suspend_kind)
910 /* Try and overload of operator co_await, .... */
911 tree o;
912 if (MAYBE_CLASS_TYPE_P (TREE_TYPE (a)))
914 o = build_new_op (loc, CO_AWAIT_EXPR, LOOKUP_NORMAL, a, NULL_TREE,
915 NULL_TREE, NULL, tf_warning_or_error);
916 /* If no viable functions are found, o is a. */
917 if (!o || o == error_mark_node)
918 o = a;
919 else if (flag_exceptions && suspend_kind == FINAL_SUSPEND_POINT)
921 /* We found an overload for co_await(), diagnose throwing cases. */
922 if (TREE_CODE (o) == TARGET_EXPR
923 && coro_diagnose_throwing_final_aw_expr (o))
924 return error_mark_node;
926 /* We now know that the final suspend object is distinct from the
927 final awaiter, so check for a non-throwing DTOR where needed. */
928 tree a_type = TREE_TYPE (a);
929 if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (a_type))
930 if (tree dummy
931 = build_special_member_call (a, complete_dtor_identifier,
932 NULL, a_type, LOOKUP_NORMAL,
933 tf_none))
935 if (CONVERT_EXPR_P (dummy))
936 dummy = TREE_OPERAND (dummy, 0);
937 dummy = TREE_OPERAND (CALL_EXPR_FN (dummy), 0);
938 if (coro_diagnose_throwing_fn (dummy))
939 return error_mark_node;
943 else
944 o = a; /* This is most likely about to fail anyway. */
946 tree o_type = TREE_TYPE (o);
947 if (o_type && !VOID_TYPE_P (o_type))
948 o_type = complete_type_or_else (o_type, o);
950 if (!o_type)
951 return error_mark_node;
953 if (TREE_CODE (o_type) != RECORD_TYPE)
955 error_at (loc, "awaitable type %qT is not a structure",
956 o_type);
957 return error_mark_node;
960 /* Check for required awaitable members and their types. */
961 tree awrd_meth
962 = lookup_awaitable_member (o_type, coro_await_ready_identifier, loc);
963 if (!awrd_meth || awrd_meth == error_mark_node)
964 return error_mark_node;
965 tree awsp_meth
966 = lookup_awaitable_member (o_type, coro_await_suspend_identifier, loc);
967 if (!awsp_meth || awsp_meth == error_mark_node)
968 return error_mark_node;
970 /* The type of the co_await is the return type of the awaitable's
971 await_resume, so we need to look that up. */
972 tree awrs_meth
973 = lookup_awaitable_member (o_type, coro_await_resume_identifier, loc);
974 if (!awrs_meth || awrs_meth == error_mark_node)
975 return error_mark_node;
977 /* To complete the lookups, we need an instance of 'e' which is built from
978 'o' according to [expr.await] 3.4.
980 If we need to materialize this as a temporary, then that will have to be
981 'promoted' to a coroutine frame var. However, if the awaitable is a
982 user variable, parameter or comes from a scope outside this function,
983 then we must use it directly - or we will see unnecessary copies.
985 If o is a variable, find the underlying var. */
986 tree e_proxy = STRIP_NOPS (o);
987 if (INDIRECT_REF_P (e_proxy))
988 e_proxy = TREE_OPERAND (e_proxy, 0);
989 while (TREE_CODE (e_proxy) == COMPONENT_REF)
991 e_proxy = TREE_OPERAND (e_proxy, 0);
992 if (INDIRECT_REF_P (e_proxy))
993 e_proxy = TREE_OPERAND (e_proxy, 0);
994 if (TREE_CODE (e_proxy) == CALL_EXPR)
996 /* We could have operator-> here too. */
997 tree op = TREE_OPERAND (CALL_EXPR_FN (e_proxy), 0);
998 if (DECL_OVERLOADED_OPERATOR_P (op)
999 && DECL_OVERLOADED_OPERATOR_IS (op, COMPONENT_REF))
1001 e_proxy = CALL_EXPR_ARG (e_proxy, 0);
1002 STRIP_NOPS (e_proxy);
1003 gcc_checking_assert (TREE_CODE (e_proxy) == ADDR_EXPR);
1004 e_proxy = TREE_OPERAND (e_proxy, 0);
1007 STRIP_NOPS (e_proxy);
1010 /* Only build a temporary if we need it. */
1011 if (TREE_CODE (e_proxy) == PARM_DECL
1012 || (VAR_P (e_proxy) && !is_local_temp (e_proxy)))
1014 e_proxy = o;
1015 o = NULL_TREE; /* The var is already present. */
1017 else
1019 e_proxy = get_awaitable_var (suspend_kind, o_type);
1020 o = cp_build_modify_expr (loc, e_proxy, INIT_EXPR, o,
1021 tf_warning_or_error);
1024 /* I suppose we could check that this is contextually convertible to bool. */
1025 tree awrd_func = NULL_TREE;
1026 tree awrd_call
1027 = build_new_method_call (e_proxy, awrd_meth, NULL, NULL_TREE, LOOKUP_NORMAL,
1028 &awrd_func, tf_warning_or_error);
1030 if (!awrd_func || !awrd_call || awrd_call == error_mark_node)
1031 return error_mark_node;
1033 /* The suspend method may return one of three types:
1034 1. void (no special action needed).
1035 2. bool (if true, we don't need to suspend).
1036 3. a coroutine handle, we execute the handle.resume() call. */
1037 tree awsp_func = NULL_TREE;
1038 tree h_proxy = get_coroutine_self_handle_proxy (current_function_decl);
1039 vec<tree, va_gc> *args = make_tree_vector_single (h_proxy);
1040 tree awsp_call
1041 = build_new_method_call (e_proxy, awsp_meth, &args, NULL_TREE,
1042 LOOKUP_NORMAL, &awsp_func, tf_warning_or_error);
1044 release_tree_vector (args);
1045 if (!awsp_func || !awsp_call || awsp_call == error_mark_node)
1046 return error_mark_node;
1048 bool ok = false;
1049 tree susp_return_type = TREE_TYPE (TREE_TYPE (awsp_func));
1050 if (same_type_p (susp_return_type, void_type_node))
1051 ok = true;
1052 else if (same_type_p (susp_return_type, boolean_type_node))
1053 ok = true;
1054 else if (TREE_CODE (susp_return_type) == RECORD_TYPE
1055 && CLASS_TYPE_P (susp_return_type))
1057 tree tt = CLASSTYPE_TI_TEMPLATE (susp_return_type);
1058 if (tt == coro_handle_templ)
1059 ok = true;
1062 if (!ok)
1064 error_at (loc, "%<await_suspend%> must return %<void%>, %<bool%> or"
1065 " a coroutine handle");
1066 return error_mark_node;
1069 /* Finally, the type of e.await_resume() is the co_await's type. */
1070 tree awrs_func = NULL_TREE;
1071 tree awrs_call
1072 = build_new_method_call (e_proxy, awrs_meth, NULL, NULL_TREE, LOOKUP_NORMAL,
1073 &awrs_func, tf_warning_or_error);
1075 if (!awrs_func || !awrs_call || awrs_call == error_mark_node)
1076 return error_mark_node;
1078 if (flag_exceptions && suspend_kind == FINAL_SUSPEND_POINT)
1080 if (coro_diagnose_throwing_fn (awrd_func))
1081 return error_mark_node;
1082 if (coro_diagnose_throwing_fn (awsp_func))
1083 return error_mark_node;
1084 if (coro_diagnose_throwing_fn (awrs_func))
1085 return error_mark_node;
1086 if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (o_type))
1087 if (tree dummy
1088 = build_special_member_call (e_proxy, complete_dtor_identifier,
1089 NULL, o_type, LOOKUP_NORMAL,
1090 tf_none))
1092 if (CONVERT_EXPR_P (dummy))
1093 dummy = TREE_OPERAND (dummy, 0);
1094 dummy = TREE_OPERAND (CALL_EXPR_FN (dummy), 0);
1095 if (coro_diagnose_throwing_fn (dummy))
1096 return error_mark_node;
1100 /* We now have three call expressions, in terms of the promise, handle and
1101 'e' proxies. Save them in the await expression for later expansion. */
1103 tree awaiter_calls = make_tree_vec (3);
1104 TREE_VEC_ELT (awaiter_calls, 0) = awrd_call; /* await_ready(). */
1105 TREE_VEC_ELT (awaiter_calls, 1) = awsp_call; /* await_suspend(). */
1106 tree te = NULL_TREE;
1107 if (TREE_CODE (awrs_call) == TARGET_EXPR)
1109 te = awrs_call;
1110 awrs_call = TREE_OPERAND (awrs_call, 1);
1112 TREE_VEC_ELT (awaiter_calls, 2) = awrs_call; /* await_resume(). */
1114 tree await_expr = build5_loc (loc, CO_AWAIT_EXPR,
1115 TREE_TYPE (TREE_TYPE (awrs_func)),
1116 a, e_proxy, o, awaiter_calls,
1117 build_int_cst (integer_type_node,
1118 (int) suspend_kind));
1119 if (te)
1121 TREE_OPERAND (te, 1) = await_expr;
1122 await_expr = te;
1124 tree t = convert_from_reference (await_expr);
1125 return t;
1128 tree
1129 finish_co_await_expr (location_t kw, tree expr)
1131 if (!expr || error_operand_p (expr))
1132 return error_mark_node;
1134 if (!coro_common_keyword_context_valid_p (current_function_decl, kw,
1135 "co_await"))
1136 return error_mark_node;
1138 /* The current function has now become a coroutine, if it wasn't already. */
1139 DECL_COROUTINE_P (current_function_decl) = 1;
1141 /* This function will appear to have no return statement, even if it
1142 is declared to return non-void (most likely). This is correct - we
1143 synthesize the return for the ramp in the compiler. So suppress any
1144 extraneous warnings during substitution. */
1145 suppress_warning (current_function_decl, OPT_Wreturn_type);
1147 /* If we don't know the promise type, we can't proceed, build the
1148 co_await with the expression unchanged. */
1149 tree functype = TREE_TYPE (current_function_decl);
1150 if (dependent_type_p (functype) || type_dependent_expression_p (expr))
1151 return build5_loc (kw, CO_AWAIT_EXPR, unknown_type_node, expr,
1152 NULL_TREE, NULL_TREE, NULL_TREE, integer_zero_node);
1154 /* We must be able to look up the "await_transform" method in the scope of
1155 the promise type, and obtain its return type. */
1156 if (!coro_promise_type_found_p (current_function_decl, kw))
1157 return error_mark_node;
1159 /* [expr.await] 3.2
1160 The incoming cast expression might be transformed by a promise
1161 'await_transform()'. */
1162 tree at_meth
1163 = lookup_promise_method (current_function_decl,
1164 coro_await_transform_identifier, kw,
1165 /*musthave=*/false);
1166 if (at_meth == error_mark_node)
1167 return error_mark_node;
1169 tree a = expr;
1170 if (at_meth)
1172 /* try to build a = p.await_transform (e). */
1173 vec<tree, va_gc> *args = make_tree_vector_single (expr);
1174 a = build_new_method_call (get_coroutine_promise_proxy (
1175 current_function_decl),
1176 at_meth, &args, NULL_TREE, LOOKUP_NORMAL,
1177 NULL, tf_warning_or_error);
1179 /* As I read the section.
1180 We saw an await_transform method, so it's mandatory that we replace
1181 expr with p.await_transform (expr), therefore if the method call fails
1182 (presumably, we don't have suitable arguments) then this part of the
1183 process fails. */
1184 if (a == error_mark_node)
1185 return error_mark_node;
1188 /* Now we want to build co_await a. */
1189 tree op = build_co_await (kw, a, CO_AWAIT_SUSPEND_POINT);
1190 if (op != error_mark_node)
1192 TREE_SIDE_EFFECTS (op) = 1;
1193 SET_EXPR_LOCATION (op, kw);
1196 return op;
1199 /* Take the EXPR given and attempt to build:
1200 co_await p.yield_value (expr);
1201 per [expr.yield] para 1. */
1203 tree
1204 finish_co_yield_expr (location_t kw, tree expr)
1206 if (!expr || error_operand_p (expr))
1207 return error_mark_node;
1209 /* Check the general requirements and simple syntax errors. */
1210 if (!coro_common_keyword_context_valid_p (current_function_decl, kw,
1211 "co_yield"))
1212 return error_mark_node;
1214 /* The current function has now become a coroutine, if it wasn't already. */
1215 DECL_COROUTINE_P (current_function_decl) = 1;
1217 /* This function will appear to have no return statement, even if it
1218 is declared to return non-void (most likely). This is correct - we
1219 synthesize the return for the ramp in the compiler. So suppress any
1220 extraneous warnings during substitution. */
1221 suppress_warning (current_function_decl, OPT_Wreturn_type);
1223 /* If we don't know the promise type, we can't proceed, build the
1224 co_await with the expression unchanged. */
1225 tree functype = TREE_TYPE (current_function_decl);
1226 if (dependent_type_p (functype) || type_dependent_expression_p (expr))
1227 return build2_loc (kw, CO_YIELD_EXPR, unknown_type_node, expr, NULL_TREE);
1229 if (!coro_promise_type_found_p (current_function_decl, kw))
1230 /* We must be able to look up the "yield_value" method in the scope of
1231 the promise type, and obtain its return type. */
1232 return error_mark_node;
1234 /* [expr.yield] / 1
1235 Let e be the operand of the yield-expression and p be an lvalue naming
1236 the promise object of the enclosing coroutine, then the yield-expression
1237 is equivalent to the expression co_await p.yield_value(e).
1238 build p.yield_value(e): */
1239 vec<tree, va_gc> *args = make_tree_vector_single (expr);
1240 tree yield_call
1241 = coro_build_promise_expression (current_function_decl, NULL,
1242 coro_yield_value_identifier, kw,
1243 &args, /*musthave=*/true);
1244 release_tree_vector (args);
1246 /* Now build co_await p.yield_value (e).
1247 Noting that for co_yield, there is no evaluation of any potential
1248 promise transform_await(), so we call build_co_await directly. */
1250 tree op = build_co_await (kw, yield_call, CO_YIELD_SUSPEND_POINT);
1251 if (op != error_mark_node)
1253 if (REFERENCE_REF_P (op))
1254 op = TREE_OPERAND (op, 0);
1255 /* If the await expression is wrapped in a TARGET_EXPR, then transfer
1256 that wrapper to the CO_YIELD_EXPR, since this is just a proxy for
1257 its contained await. Otherwise, just build the CO_YIELD_EXPR. */
1258 if (TREE_CODE (op) == TARGET_EXPR)
1260 tree t = TREE_OPERAND (op, 1);
1261 t = build2_loc (kw, CO_YIELD_EXPR, TREE_TYPE (t), expr, t);
1262 TREE_OPERAND (op, 1) = t;
1264 else
1265 op = build2_loc (kw, CO_YIELD_EXPR, TREE_TYPE (op), expr, op);
1266 TREE_SIDE_EFFECTS (op) = 1;
1267 op = convert_from_reference (op);
1270 return op;
1273 /* Check and build a co_return statement.
1274 First that it's valid to have a co_return keyword here.
1275 If it is, then check and build the p.return_{void(),value(expr)}.
1276 These are built against a proxy for the promise, which will be filled
1277 in with the actual frame version when the function is transformed. */
1279 tree
1280 finish_co_return_stmt (location_t kw, tree expr)
1282 if (expr)
1283 STRIP_ANY_LOCATION_WRAPPER (expr);
1285 if (error_operand_p (expr))
1286 return error_mark_node;
1288 /* If it fails the following test, the function is not permitted to be a
1289 coroutine, so the co_return statement is erroneous. */
1290 if (!coro_common_keyword_context_valid_p (current_function_decl, kw,
1291 "co_return"))
1292 return error_mark_node;
1294 /* The current function has now become a coroutine, if it wasn't
1295 already. */
1296 DECL_COROUTINE_P (current_function_decl) = 1;
1298 /* This function will appear to have no return statement, even if it
1299 is declared to return non-void (most likely). This is correct - we
1300 synthesize the return for the ramp in the compiler. So suppress any
1301 extraneous warnings during substitution. */
1302 suppress_warning (current_function_decl, OPT_Wreturn_type);
1304 if (processing_template_decl
1305 && check_for_bare_parameter_packs (expr))
1306 return error_mark_node;
1308 /* If we don't know the promise type, we can't proceed, build the
1309 co_return with the expression unchanged. */
1310 tree functype = TREE_TYPE (current_function_decl);
1311 if (dependent_type_p (functype) || type_dependent_expression_p (expr))
1313 /* co_return expressions are always void type, regardless of the
1314 expression type. */
1315 expr = build2_loc (kw, CO_RETURN_EXPR, void_type_node,
1316 expr, NULL_TREE);
1317 expr = maybe_cleanup_point_expr_void (expr);
1318 return add_stmt (expr);
1321 if (!coro_promise_type_found_p (current_function_decl, kw))
1322 return error_mark_node;
1324 /* Suppress -Wreturn-type for co_return, we need to check indirectly
1325 whether the promise type has a suitable return_void/return_value. */
1326 suppress_warning (current_function_decl, OPT_Wreturn_type);
1328 if (!processing_template_decl && warn_sequence_point)
1329 verify_sequence_points (expr);
1331 if (expr)
1333 /* If we had an id-expression obfuscated by force_paren_expr, we need
1334 to undo it so we can try to treat it as an rvalue below. */
1335 expr = maybe_undo_parenthesized_ref (expr);
1337 if (processing_template_decl)
1338 expr = build_non_dependent_expr (expr);
1340 if (error_operand_p (expr))
1341 return error_mark_node;
1344 /* If the promise object doesn't have the correct return call then
1345 there's a mis-match between the co_return <expr> and this. */
1346 tree co_ret_call = error_mark_node;
1347 if (expr == NULL_TREE || VOID_TYPE_P (TREE_TYPE (expr)))
1348 co_ret_call
1349 = get_coroutine_return_void_expr (current_function_decl, kw, true);
1350 else
1352 /* [class.copy.elision] / 3.
1353 An implicitly movable entity is a variable of automatic storage
1354 duration that is either a non-volatile object or an rvalue reference
1355 to a non-volatile object type. For such objects in the context of
1356 the co_return, the overload resolution should be carried out first
1357 treating the object as an rvalue, if that fails, then we fall back
1358 to regular overload resolution. */
1360 tree arg = expr;
1361 if (tree moved = treat_lvalue_as_rvalue_p (expr, /*return*/true))
1362 arg = moved;
1364 releasing_vec args = make_tree_vector_single (arg);
1365 co_ret_call
1366 = coro_build_promise_expression (current_function_decl, NULL,
1367 coro_return_value_identifier, kw,
1368 &args, /*musthave=*/true);
1371 /* Makes no sense for a co-routine really. */
1372 if (TREE_THIS_VOLATILE (current_function_decl))
1373 warning_at (kw, 0,
1374 "function declared %<noreturn%> has a"
1375 " %<co_return%> statement");
1377 expr = build2_loc (kw, CO_RETURN_EXPR, void_type_node, expr, co_ret_call);
1378 expr = maybe_cleanup_point_expr_void (expr);
1379 return add_stmt (expr);
1382 /* We need to validate the arguments to __builtin_coro_promise, since the
1383 second two must be constant, and the builtins machinery doesn't seem to
1384 deal with that properly. */
1386 tree
1387 coro_validate_builtin_call (tree call, tsubst_flags_t)
1389 tree fn = TREE_OPERAND (CALL_EXPR_FN (call), 0);
1391 gcc_checking_assert (DECL_BUILT_IN_CLASS (fn) == BUILT_IN_NORMAL);
1392 switch (DECL_FUNCTION_CODE (fn))
1394 default:
1395 return call;
1397 case BUILT_IN_CORO_PROMISE:
1399 /* Argument 0 is already checked by the normal built-in machinery
1400 Argument 1 must be a constant of size type. It probably makes
1401 little sense if it's not a power of 2, but that isn't specified
1402 formally. */
1403 tree arg = CALL_EXPR_ARG (call, 1);
1404 location_t loc = EXPR_LOCATION (arg);
1406 /* We expect alignof expressions in templates. */
1407 if (TREE_CODE (arg) == NON_DEPENDENT_EXPR
1408 && TREE_CODE (TREE_OPERAND (arg, 0)) == ALIGNOF_EXPR)
1410 else if (!TREE_CONSTANT (arg))
1412 error_at (loc, "the align argument to %<__builtin_coro_promise%>"
1413 " must be a constant");
1414 return error_mark_node;
1416 /* Argument 2 is the direction - to / from handle address to promise
1417 address. */
1418 arg = CALL_EXPR_ARG (call, 2);
1419 loc = EXPR_LOCATION (arg);
1420 if (!TREE_CONSTANT (arg))
1422 error_at (loc, "the direction argument to"
1423 " %<__builtin_coro_promise%> must be a constant");
1424 return error_mark_node;
1426 return call;
1427 break;
1432 /* ================= Morph and Expand. =================
1434 The entry point here is morph_fn_to_coro () which is called from
1435 finish_function () when we have completed any template expansion.
1437 This is preceded by helper functions that implement the phases below.
1439 The process proceeds in four phases.
1441 A Initial framing.
1442 The user's function body is wrapped in the initial and final suspend
1443 points and we begin building the coroutine frame.
1444 We build empty decls for the actor and destroyer functions at this
1445 time too.
1446 When exceptions are enabled, the user's function body will also be
1447 wrapped in a try-catch block with the catch invoking the promise
1448 class 'unhandled_exception' method.
1450 B Analysis.
1451 The user's function body is analyzed to determine the suspend points,
1452 if any, and to capture local variables that might persist across such
1453 suspensions. In most cases, it is not necessary to capture compiler
1454 temporaries, since the tree-lowering nests the suspensions correctly.
1455 However, in the case of a captured reference, there is a lifetime
1456 extension to the end of the full expression - which can mean across a
1457 suspend point in which case it must be promoted to a frame variable.
1459 At the conclusion of analysis, we have a conservative frame layout and
1460 maps of the local variables to their frame entry points.
1462 C Build the ramp function.
1463 Carry out the allocation for the coroutine frame (NOTE; the actual size
1464 computation is deferred until late in the middle end to allow for future
1465 optimizations that will be allowed to elide unused frame entries).
1466 We build the return object.
1468 D Build and expand the actor and destroyer function bodies.
1469 The destroyer is a trivial shim that sets a bit to indicate that the
1470 destroy dispatcher should be used and then calls into the actor.
1472 The actor function is the implementation of the user's state machine.
1473 The current suspend point is noted in an index.
1474 Each suspend point is encoded as a pair of internal functions, one in
1475 the relevant dispatcher, and one representing the suspend point.
1477 During this process, the user's local variables and the proxies for the
1478 self-handle and the promise class instance are re-written to their
1479 coroutine frame equivalents.
1481 The complete bodies for the ramp, actor and destroy function are passed
1482 back to finish_function for folding and gimplification. */
1484 /* Helpers to build EXPR_STMT and void-cast EXPR_STMT, common ops. */
1486 static tree
1487 coro_build_expr_stmt (tree expr, location_t loc)
1489 return maybe_cleanup_point_expr_void (build_stmt (loc, EXPR_STMT, expr));
1492 static tree
1493 coro_build_cvt_void_expr_stmt (tree expr, location_t loc)
1495 tree t = build1 (CONVERT_EXPR, void_type_node, expr);
1496 return coro_build_expr_stmt (t, loc);
1499 /* Helpers to build an artificial var, with location LOC, NAME and TYPE, in
1500 CTX, and with initializer INIT. */
1502 static tree
1503 coro_build_artificial_var (location_t loc, tree name, tree type, tree ctx,
1504 tree init)
1506 tree res = build_lang_decl (VAR_DECL, name, type);
1507 DECL_SOURCE_LOCATION (res) = loc;
1508 DECL_CONTEXT (res) = ctx;
1509 DECL_ARTIFICIAL (res) = true;
1510 DECL_INITIAL (res) = init;
1511 return res;
1514 static tree
1515 coro_build_artificial_var (location_t loc, const char *name, tree type,
1516 tree ctx, tree init)
1518 return coro_build_artificial_var (loc, get_identifier (name),
1519 type, ctx, init);
1522 /* Helpers for label creation:
1523 1. Create a named label in the specified context. */
1525 static tree
1526 create_anon_label_with_ctx (location_t loc, tree ctx)
1528 tree lab = build_decl (loc, LABEL_DECL, NULL_TREE, void_type_node);
1530 DECL_CONTEXT (lab) = ctx;
1531 DECL_ARTIFICIAL (lab) = true;
1532 DECL_IGNORED_P (lab) = true;
1533 TREE_USED (lab) = true;
1534 return lab;
1537 /* 2. Create a named label in the specified context. */
1539 static tree
1540 create_named_label_with_ctx (location_t loc, const char *name, tree ctx)
1542 tree lab_id = get_identifier (name);
1543 tree lab = define_label (loc, lab_id);
1544 DECL_CONTEXT (lab) = ctx;
1545 DECL_ARTIFICIAL (lab) = true;
1546 TREE_USED (lab) = true;
1547 return lab;
1550 struct proxy_replace
1552 tree from, to;
1555 static tree
1556 replace_proxy (tree *here, int *do_subtree, void *d)
1558 proxy_replace *data = (proxy_replace *) d;
1560 if (*here == data->from)
1562 *here = data->to;
1563 *do_subtree = 0;
1565 else
1566 *do_subtree = 1;
1567 return NULL_TREE;
1570 /* Support for expansion of co_await statements. */
1572 struct coro_aw_data
1574 tree actor_fn; /* Decl for context. */
1575 tree coro_fp; /* Frame pointer var. */
1576 tree resume_idx; /* This is the index var in the frame. */
1577 tree i_a_r_c; /* initial suspend await_resume() was called if true. */
1578 tree self_h; /* This is a handle to the current coro (frame var). */
1579 tree cleanup; /* This is where to go once we complete local destroy. */
1580 tree cororet; /* This is where to go if we suspend. */
1581 tree corocont; /* This is where to go if we continue. */
1582 tree conthand; /* This is the handle for a continuation. */
1583 unsigned index; /* This is our current resume index. */
1586 /* Lightweight search for the first await expression in tree-walk order.
1587 returns:
1588 The first await expression found in STMT.
1589 NULL_TREE if there are none.
1590 So can be used to determine if the statement needs to be processed for
1591 awaits. */
1593 static tree
1594 co_await_find_in_subtree (tree *stmt, int *, void *d)
1596 tree **p = (tree **) d;
1597 if (TREE_CODE (*stmt) == CO_AWAIT_EXPR)
1599 *p = stmt;
1600 return *stmt;
1602 return NULL_TREE;
1605 /* Starting with a statement:
1607 stmt => some tree containing one or more await expressions.
1609 We replace the statement with:
1610 <STATEMENT_LIST> {
1611 initialize awaitable
1612 if (!ready)
1614 suspension context.
1616 resume:
1617 revised statement with one await expression rewritten to its
1618 await_resume() return value.
1621 We then recurse into the initializer and the revised statement
1622 repeating this replacement until there are no more await expressions
1623 in either. */
1625 static tree *
1626 expand_one_await_expression (tree *stmt, tree *await_expr, void *d)
1628 coro_aw_data *data = (coro_aw_data *) d;
1630 tree saved_statement = *stmt;
1631 tree saved_co_await = *await_expr;
1633 tree actor = data->actor_fn;
1634 location_t loc = EXPR_LOCATION (*stmt);
1635 tree var = TREE_OPERAND (saved_co_await, 1); /* frame slot. */
1636 tree expr = TREE_OPERAND (saved_co_await, 2); /* initializer. */
1637 tree awaiter_calls = TREE_OPERAND (saved_co_await, 3);
1639 tree source = TREE_OPERAND (saved_co_await, 4);
1640 bool is_final = (source
1641 && TREE_INT_CST_LOW (source) == (int) FINAL_SUSPEND_POINT);
1642 bool needs_dtor = TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (var));
1643 int resume_point = data->index;
1644 size_t bufsize = sizeof ("destroy.") + 10;
1645 char *buf = (char *) alloca (bufsize);
1646 snprintf (buf, bufsize, "destroy.%d", resume_point);
1647 tree destroy_label = create_named_label_with_ctx (loc, buf, actor);
1648 snprintf (buf, bufsize, "resume.%d", resume_point);
1649 tree resume_label = create_named_label_with_ctx (loc, buf, actor);
1650 tree empty_list = build_empty_stmt (loc);
1652 tree await_type = TREE_TYPE (var);
1653 tree stmt_list = NULL;
1654 tree r;
1655 tree *await_init = NULL;
1657 if (!expr)
1658 needs_dtor = false; /* No need, the var's lifetime is managed elsewhere. */
1659 else
1661 r = coro_build_cvt_void_expr_stmt (expr, loc);
1662 append_to_statement_list_force (r, &stmt_list);
1663 /* We have an initializer, which might itself contain await exprs. */
1664 await_init = tsi_stmt_ptr (tsi_last (stmt_list));
1667 /* Use the await_ready() call to test if we need to suspend. */
1668 tree ready_cond = TREE_VEC_ELT (awaiter_calls, 0); /* await_ready(). */
1669 /* Convert to bool, if necessary. */
1670 if (TREE_CODE (TREE_TYPE (ready_cond)) != BOOLEAN_TYPE)
1671 ready_cond = cp_convert (boolean_type_node, ready_cond,
1672 tf_warning_or_error);
1673 /* Be aggressive in folding here, since there are a significant number of
1674 cases where the ready condition is constant. */
1675 ready_cond = invert_truthvalue_loc (loc, ready_cond);
1676 ready_cond
1677 = build1_loc (loc, CLEANUP_POINT_EXPR, boolean_type_node, ready_cond);
1679 tree body_list = NULL;
1680 tree susp_idx = build_int_cst (short_unsigned_type_node, data->index);
1681 r = build2_loc (loc, MODIFY_EXPR, short_unsigned_type_node, data->resume_idx,
1682 susp_idx);
1683 r = coro_build_cvt_void_expr_stmt (r, loc);
1684 append_to_statement_list (r, &body_list);
1686 /* Find out what we have to do with the awaiter's suspend method.
1687 [expr.await]
1688 (5.1) If the result of await-ready is false, the coroutine is considered
1689 suspended. Then:
1690 (5.1.1) If the type of await-suspend is std::coroutine_handle<Z>,
1691 await-suspend.resume() is evaluated.
1692 (5.1.2) if the type of await-suspend is bool, await-suspend is evaluated,
1693 and the coroutine is resumed if the result is false.
1694 (5.1.3) Otherwise, await-suspend is evaluated. */
1696 tree suspend = TREE_VEC_ELT (awaiter_calls, 1); /* await_suspend(). */
1697 tree susp_type = TREE_TYPE (suspend);
1699 bool is_cont = false;
1700 /* NOTE: final suspend can't resume; the "resume" label in that case
1701 corresponds to implicit destruction. */
1702 if (VOID_TYPE_P (susp_type))
1704 /* We just call await_suspend() and hit the yield. */
1705 suspend = coro_build_cvt_void_expr_stmt (suspend, loc);
1706 append_to_statement_list (suspend, &body_list);
1708 else if (TREE_CODE (susp_type) == BOOLEAN_TYPE)
1710 /* Boolean return, continue if the call returns false. */
1711 suspend = build1_loc (loc, TRUTH_NOT_EXPR, boolean_type_node, suspend);
1712 suspend
1713 = build1_loc (loc, CLEANUP_POINT_EXPR, boolean_type_node, suspend);
1714 tree go_on = build1_loc (loc, GOTO_EXPR, void_type_node, resume_label);
1715 r = build3_loc (loc, COND_EXPR, void_type_node, suspend, go_on,
1716 empty_list);
1717 append_to_statement_list (r, &body_list);
1719 else
1721 r = build1_loc (loc, CONVERT_EXPR, void_coro_handle_type, suspend);
1722 r = build2_loc (loc, INIT_EXPR, void_coro_handle_type, data->conthand, r);
1723 r = build1 (CONVERT_EXPR, void_type_node, r);
1724 append_to_statement_list (r, &body_list);
1725 is_cont = true;
1728 tree d_l = build_address (destroy_label);
1729 tree r_l = build_address (resume_label);
1730 tree susp = build_address (data->cororet);
1731 tree cont = build_address (data->corocont);
1732 tree final_susp = build_int_cst (integer_type_node, is_final ? 1 : 0);
1734 susp_idx = build_int_cst (integer_type_node, data->index);
1736 tree sw = begin_switch_stmt ();
1737 tree cond = build_decl (loc, VAR_DECL, NULL_TREE, integer_type_node);
1738 DECL_ARTIFICIAL (cond) = 1;
1739 DECL_IGNORED_P (cond) = 1;
1740 layout_decl (cond, 0);
1742 r = build_call_expr_internal_loc (loc, IFN_CO_YIELD, integer_type_node, 5,
1743 susp_idx, final_susp, r_l, d_l,
1744 data->coro_fp);
1745 r = build2 (INIT_EXPR, integer_type_node, cond, r);
1746 finish_switch_cond (r, sw);
1747 r = build_case_label (build_int_cst (integer_type_node, 0), NULL_TREE,
1748 create_anon_label_with_ctx (loc, actor));
1749 add_stmt (r); /* case 0: */
1750 /* Implement the suspend, a scope exit without clean ups. */
1751 r = build_call_expr_internal_loc (loc, IFN_CO_SUSPN, void_type_node, 1,
1752 is_cont ? cont : susp);
1753 r = coro_build_cvt_void_expr_stmt (r, loc);
1754 add_stmt (r); /* goto ret; */
1755 r = build_case_label (build_int_cst (integer_type_node, 1), NULL_TREE,
1756 create_anon_label_with_ctx (loc, actor));
1757 add_stmt (r); /* case 1: */
1758 r = build1_loc (loc, GOTO_EXPR, void_type_node, resume_label);
1759 add_stmt (r); /* goto resume; */
1760 r = build_case_label (NULL_TREE, NULL_TREE,
1761 create_anon_label_with_ctx (loc, actor));
1762 add_stmt (r); /* default:; */
1763 r = build1_loc (loc, GOTO_EXPR, void_type_node, destroy_label);
1764 add_stmt (r); /* goto destroy; */
1766 /* part of finish switch. */
1767 SWITCH_STMT_BODY (sw) = pop_stmt_list (SWITCH_STMT_BODY (sw));
1768 pop_switch ();
1769 tree scope = SWITCH_STMT_SCOPE (sw);
1770 SWITCH_STMT_SCOPE (sw) = NULL;
1771 r = do_poplevel (scope);
1772 append_to_statement_list (r, &body_list);
1774 destroy_label = build_stmt (loc, LABEL_EXPR, destroy_label);
1775 append_to_statement_list (destroy_label, &body_list);
1776 if (needs_dtor)
1778 tree dtor = build_special_member_call (var, complete_dtor_identifier,
1779 NULL, await_type, LOOKUP_NORMAL,
1780 tf_warning_or_error);
1781 append_to_statement_list (dtor, &body_list);
1783 r = build1_loc (loc, GOTO_EXPR, void_type_node, data->cleanup);
1784 append_to_statement_list (r, &body_list);
1786 r = build3_loc (loc, COND_EXPR, void_type_node, ready_cond, body_list,
1787 empty_list);
1789 append_to_statement_list (r, &stmt_list);
1791 /* Resume point. */
1792 resume_label = build_stmt (loc, LABEL_EXPR, resume_label);
1793 append_to_statement_list (resume_label, &stmt_list);
1795 /* This will produce the value (if one is provided) from the co_await
1796 expression. */
1797 tree resume_call = TREE_VEC_ELT (awaiter_calls, 2); /* await_resume(). */
1798 if (REFERENCE_REF_P (resume_call))
1799 /* Sink to await_resume call_expr. */
1800 resume_call = TREE_OPERAND (resume_call, 0);
1802 *await_expr = resume_call; /* Replace the co_await expr with its result. */
1803 append_to_statement_list_force (saved_statement, &stmt_list);
1804 /* Get a pointer to the revised statement. */
1805 tree *revised = tsi_stmt_ptr (tsi_last (stmt_list));
1806 if (needs_dtor)
1808 tree dtor = build_special_member_call (var, complete_dtor_identifier,
1809 NULL, await_type, LOOKUP_NORMAL,
1810 tf_warning_or_error);
1811 append_to_statement_list (dtor, &stmt_list);
1813 data->index += 2;
1815 /* Replace the original statement with the expansion. */
1816 *stmt = stmt_list;
1818 /* Now, if the awaitable had an initializer, expand any awaits that might
1819 be embedded in it. */
1820 tree *aw_expr_ptr;
1821 if (await_init &&
1822 cp_walk_tree (await_init, co_await_find_in_subtree, &aw_expr_ptr, NULL))
1823 expand_one_await_expression (await_init, aw_expr_ptr, d);
1825 /* Expand any more await expressions in the the original statement. */
1826 if (cp_walk_tree (revised, co_await_find_in_subtree, &aw_expr_ptr, NULL))
1827 expand_one_await_expression (revised, aw_expr_ptr, d);
1829 return NULL;
1832 /* Check to see if a statement contains at least one await expression, if
1833 so, then process that. */
1835 static tree
1836 process_one_statement (tree *stmt, void *d)
1838 tree *aw_expr_ptr;
1839 if (cp_walk_tree (stmt, co_await_find_in_subtree, &aw_expr_ptr, NULL))
1840 expand_one_await_expression (stmt, aw_expr_ptr, d);
1841 return NULL_TREE;
1844 static tree
1845 await_statement_expander (tree *stmt, int *do_subtree, void *d)
1847 tree res = NULL_TREE;
1849 /* Process a statement at a time. */
1850 if (STATEMENT_CLASS_P (*stmt) || TREE_CODE (*stmt) == BIND_EXPR)
1851 return NULL_TREE; /* Just process the sub-trees. */
1852 else if (TREE_CODE (*stmt) == STATEMENT_LIST)
1854 for (tree &s : tsi_range (*stmt))
1856 res = cp_walk_tree (&s, await_statement_expander,
1857 d, NULL);
1858 if (res)
1859 return res;
1861 *do_subtree = 0; /* Done subtrees. */
1863 else if (EXPR_P (*stmt))
1865 process_one_statement (stmt, d);
1866 *do_subtree = 0; /* Done subtrees. */
1869 /* Continue statement walk, where required. */
1870 return res;
1873 /* Suspend point hash_map. */
1875 struct suspend_point_info
1877 /* coro frame field type. */
1878 tree awaitable_type;
1879 /* coro frame field name. */
1880 tree await_field_id;
1883 static hash_map<tree, suspend_point_info> *suspend_points;
1885 struct await_xform_data
1887 tree actor_fn; /* Decl for context. */
1888 tree actor_frame;
1891 /* When we built the await expressions, we didn't know the coro frame
1892 layout, therefore no idea where to find the promise or where to put
1893 the awaitables. Now we know these things, fill them in. */
1895 static tree
1896 transform_await_expr (tree await_expr, await_xform_data *xform)
1898 suspend_point_info *si = suspend_points->get (await_expr);
1899 location_t loc = EXPR_LOCATION (await_expr);
1900 if (!si)
1902 error_at (loc, "no suspend point info for %qD", await_expr);
1903 return error_mark_node;
1906 /* So, on entry, we have:
1907 in : CO_AWAIT_EXPR (a, e_proxy, o, awr_call_vector, mode)
1908 We no longer need a [it had diagnostic value, maybe?]
1909 We need to replace the e_proxy in the awr_call. */
1911 tree coro_frame_type = TREE_TYPE (xform->actor_frame);
1913 /* If we have a frame var for the awaitable, get a reference to it. */
1914 proxy_replace data;
1915 if (si->await_field_id)
1917 tree as_m
1918 = lookup_member (coro_frame_type, si->await_field_id,
1919 /*protect=*/1, /*want_type=*/0, tf_warning_or_error);
1920 tree as = build_class_member_access_expr (xform->actor_frame, as_m,
1921 NULL_TREE, true,
1922 tf_warning_or_error);
1924 /* Replace references to the instance proxy with the frame entry now
1925 computed. */
1926 data.from = TREE_OPERAND (await_expr, 1);
1927 data.to = as;
1928 cp_walk_tree (&await_expr, replace_proxy, &data, NULL);
1930 /* .. and replace. */
1931 TREE_OPERAND (await_expr, 1) = as;
1934 return await_expr;
1937 /* A wrapper for the transform_await_expr function so that it can be a
1938 callback from cp_walk_tree. */
1940 static tree
1941 transform_await_wrapper (tree *stmt, int *do_subtree, void *d)
1943 /* Set actor function as new DECL_CONTEXT of label_decl. */
1944 struct await_xform_data *xform = (struct await_xform_data *) d;
1945 if (TREE_CODE (*stmt) == LABEL_DECL
1946 && DECL_CONTEXT (*stmt) != xform->actor_fn)
1947 DECL_CONTEXT (*stmt) = xform->actor_fn;
1949 /* We should have already lowered co_yields to their co_await. */
1950 gcc_checking_assert (TREE_CODE (*stmt) != CO_YIELD_EXPR);
1951 if (TREE_CODE (*stmt) != CO_AWAIT_EXPR)
1952 return NULL_TREE;
1954 tree await_expr = *stmt;
1955 *stmt = transform_await_expr (await_expr, xform);
1956 if (*stmt == error_mark_node)
1957 *do_subtree = 0;
1958 return NULL_TREE;
1961 /* This caches information that we determine about function params,
1962 their uses and copies in the coroutine frame. */
1964 struct param_info
1966 tree field_id; /* The name of the copy in the coroutine frame. */
1967 tree copy_var; /* The local var proxy for the frame copy. */
1968 vec<tree *> *body_uses; /* Worklist of uses, void if there are none. */
1969 tree frame_type; /* The type used to represent this parm in the frame. */
1970 tree orig_type; /* The original type of the parm (not as passed). */
1971 tree guard_var; /* If we need a DTOR on exception, this bool guards it. */
1972 tree fr_copy_dtor; /* If we need a DTOR on exception, this is it. */
1973 bool by_ref; /* Was passed by reference. */
1974 bool pt_ref; /* Was a pointer to object. */
1975 bool rv_ref; /* Was an rvalue ref. */
1976 bool trivial_dtor; /* The frame type has a trivial DTOR. */
1977 bool this_ptr; /* Is 'this' */
1978 bool lambda_cobj; /* Lambda capture object */
1981 struct local_var_info
1983 tree field_id;
1984 tree field_idx;
1985 tree frame_type;
1986 bool is_lambda_capture;
1987 bool is_static;
1988 bool has_value_expr_p;
1989 location_t def_loc;
1992 /* For figuring out what local variable usage we have. */
1993 struct local_vars_transform
1995 tree context;
1996 tree actor_frame;
1997 tree coro_frame_type;
1998 location_t loc;
1999 hash_map<tree, local_var_info> *local_var_uses;
2002 static tree
2003 transform_local_var_uses (tree *stmt, int *do_subtree, void *d)
2005 local_vars_transform *lvd = (local_vars_transform *) d;
2007 /* For each var in this bind expr (that has a frame id, which means it was
2008 accessed), build a frame reference and add it as the DECL_VALUE_EXPR. */
2010 if (TREE_CODE (*stmt) == BIND_EXPR)
2012 tree lvar;
2013 for (lvar = BIND_EXPR_VARS (*stmt); lvar != NULL;
2014 lvar = DECL_CHAIN (lvar))
2016 bool existed;
2017 local_var_info &local_var
2018 = lvd->local_var_uses->get_or_insert (lvar, &existed);
2019 gcc_checking_assert (existed);
2021 /* Re-write the variable's context to be in the actor func. */
2022 DECL_CONTEXT (lvar) = lvd->context;
2024 /* For capture proxies, this could include the decl value expr. */
2025 if (local_var.is_lambda_capture || local_var.has_value_expr_p)
2026 continue; /* No frame entry for this. */
2028 /* TODO: implement selective generation of fields when vars are
2029 known not-used. */
2030 if (local_var.field_id == NULL_TREE)
2031 continue; /* Wasn't used. */
2033 tree fld_ref
2034 = lookup_member (lvd->coro_frame_type, local_var.field_id,
2035 /*protect=*/1, /*want_type=*/0,
2036 tf_warning_or_error);
2037 tree fld_idx = build3_loc (lvd->loc, COMPONENT_REF, TREE_TYPE (lvar),
2038 lvd->actor_frame, fld_ref, NULL_TREE);
2039 local_var.field_idx = fld_idx;
2040 SET_DECL_VALUE_EXPR (lvar, fld_idx);
2041 DECL_HAS_VALUE_EXPR_P (lvar) = true;
2043 cp_walk_tree (&BIND_EXPR_BODY (*stmt), transform_local_var_uses, d, NULL);
2044 *do_subtree = 0; /* We've done the body already. */
2045 return NULL_TREE;
2047 return NULL_TREE;
2050 /* A helper to build the frame DTOR.
2051 [dcl.fct.def.coroutine] / 12
2052 The deallocation function’s name is looked up in the scope of the promise
2053 type. If this lookup fails, the deallocation function’s name is looked up
2054 in the global scope. If deallocation function lookup finds both a usual
2055 deallocation function with only a pointer parameter and a usual
2056 deallocation function with both a pointer parameter and a size parameter,
2057 then the selected deallocation function shall be the one with two
2058 parameters. Otherwise, the selected deallocation function shall be the
2059 function with one parameter. If no usual deallocation function is found
2060 the program is ill-formed. The selected deallocation function shall be
2061 called with the address of the block of storage to be reclaimed as its
2062 first argument. If a deallocation function with a parameter of type
2063 std::size_t is used, the size of the block is passed as the corresponding
2064 argument. */
2066 static tree
2067 coro_get_frame_dtor (tree coro_fp, tree orig, tree frame_size,
2068 tree promise_type, location_t loc)
2070 tree del_coro_fr = NULL_TREE;
2071 tree frame_arg = build1 (CONVERT_EXPR, ptr_type_node, coro_fp);
2072 tree delname = ovl_op_identifier (false, DELETE_EXPR);
2073 tree fns = lookup_promise_method (orig, delname, loc,
2074 /*musthave=*/false);
2075 if (fns && BASELINK_P (fns))
2077 /* Look for sized version first, since this takes precedence. */
2078 vec<tree, va_gc> *args = make_tree_vector ();
2079 vec_safe_push (args, frame_arg);
2080 vec_safe_push (args, frame_size);
2081 tree dummy_promise = build_dummy_object (promise_type);
2083 /* It's OK to fail for this one... */
2084 del_coro_fr = build_new_method_call (dummy_promise, fns, &args,
2085 NULL_TREE, LOOKUP_NORMAL, NULL,
2086 tf_none);
2088 if (!del_coro_fr || del_coro_fr == error_mark_node)
2090 release_tree_vector (args);
2091 args = make_tree_vector_single (frame_arg);
2092 del_coro_fr = build_new_method_call (dummy_promise, fns, &args,
2093 NULL_TREE, LOOKUP_NORMAL, NULL,
2094 tf_none);
2097 /* But one of them must succeed, or the program is ill-formed. */
2098 if (!del_coro_fr || del_coro_fr == error_mark_node)
2100 error_at (loc, "%qE is provided by %qT but is not usable with"
2101 " the function signature %qD", delname, promise_type, orig);
2102 del_coro_fr = error_mark_node;
2105 else
2107 del_coro_fr = build_op_delete_call (DELETE_EXPR, frame_arg, frame_size,
2108 /*global_p=*/true, /*placement=*/NULL,
2109 /*alloc_fn=*/NULL,
2110 tf_warning_or_error);
2111 if (!del_coro_fr || del_coro_fr == error_mark_node)
2112 del_coro_fr = error_mark_node;
2114 return del_coro_fr;
2117 /* The actor transform. */
2119 static void
2120 build_actor_fn (location_t loc, tree coro_frame_type, tree actor, tree fnbody,
2121 tree orig, hash_map<tree, local_var_info> *local_var_uses,
2122 vec<tree, va_gc> *param_dtor_list,
2123 tree resume_idx_var, unsigned body_count, tree frame_size)
2125 verify_stmt_tree (fnbody);
2126 /* Some things we inherit from the original function. */
2127 tree handle_type = get_coroutine_handle_type (orig);
2128 tree promise_type = get_coroutine_promise_type (orig);
2129 tree promise_proxy = get_coroutine_promise_proxy (orig);
2131 /* One param, the coro frame pointer. */
2132 tree actor_fp = DECL_ARGUMENTS (actor);
2134 /* We have a definition here. */
2135 TREE_STATIC (actor) = 1;
2137 tree actor_outer = push_stmt_list ();
2138 current_stmt_tree ()->stmts_are_full_exprs_p = 1;
2139 tree stmt = begin_compound_stmt (BCS_FN_BODY);
2141 tree actor_bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
2142 tree top_block = make_node (BLOCK);
2143 BIND_EXPR_BLOCK (actor_bind) = top_block;
2145 tree continuation = coro_build_artificial_var (loc, coro_actor_continue_id,
2146 void_coro_handle_type, actor,
2147 NULL_TREE);
2149 BIND_EXPR_VARS (actor_bind) = continuation;
2150 BLOCK_VARS (top_block) = BIND_EXPR_VARS (actor_bind) ;
2152 /* Link in the block associated with the outer scope of the re-written
2153 function body. */
2154 tree first = expr_first (fnbody);
2155 gcc_checking_assert (first && TREE_CODE (first) == BIND_EXPR);
2156 tree block = BIND_EXPR_BLOCK (first);
2157 gcc_checking_assert (BLOCK_SUPERCONTEXT (block) == NULL_TREE);
2158 gcc_checking_assert (BLOCK_CHAIN (block) == NULL_TREE);
2159 BLOCK_SUPERCONTEXT (block) = top_block;
2160 BLOCK_SUBBLOCKS (top_block) = block;
2162 add_stmt (actor_bind);
2163 tree actor_body = push_stmt_list ();
2165 /* The entry point for the actor code from the ramp. */
2166 tree actor_begin_label
2167 = create_named_label_with_ctx (loc, "actor.begin", actor);
2168 tree actor_frame = build1_loc (loc, INDIRECT_REF, coro_frame_type, actor_fp);
2170 /* Declare the continuation handle. */
2171 add_decl_expr (continuation);
2173 /* Re-write local vars, similarly. */
2174 local_vars_transform xform_vars_data
2175 = {actor, actor_frame, coro_frame_type, loc, local_var_uses};
2176 cp_walk_tree (&fnbody, transform_local_var_uses, &xform_vars_data, NULL);
2178 tree rat_field = lookup_member (coro_frame_type, coro_resume_index_id,
2179 1, 0, tf_warning_or_error);
2180 tree rat = build3 (COMPONENT_REF, short_unsigned_type_node, actor_frame,
2181 rat_field, NULL_TREE);
2183 tree ret_label
2184 = create_named_label_with_ctx (loc, "actor.suspend.ret", actor);
2186 tree continue_label
2187 = create_named_label_with_ctx (loc, "actor.continue.ret", actor);
2189 tree lsb_if = begin_if_stmt ();
2190 tree chkb0 = build2 (BIT_AND_EXPR, short_unsigned_type_node, rat,
2191 build_int_cst (short_unsigned_type_node, 1));
2192 chkb0 = build2 (NE_EXPR, short_unsigned_type_node, chkb0,
2193 build_int_cst (short_unsigned_type_node, 0));
2194 finish_if_stmt_cond (chkb0, lsb_if);
2196 tree destroy_dispatcher = begin_switch_stmt ();
2197 finish_switch_cond (rat, destroy_dispatcher);
2198 tree ddeflab = build_case_label (NULL_TREE, NULL_TREE,
2199 create_anon_label_with_ctx (loc, actor));
2200 add_stmt (ddeflab);
2201 tree b = build_call_expr_loc (loc, builtin_decl_explicit (BUILT_IN_TRAP), 0);
2202 b = coro_build_cvt_void_expr_stmt (b, loc);
2203 add_stmt (b);
2205 /* The destroy point numbered #1 is special, in that it is reached from a
2206 coroutine that is suspended after re-throwing from unhandled_exception().
2207 This label just invokes the cleanup of promise, param copies and the
2208 frame itself. */
2209 tree del_promise_label
2210 = create_named_label_with_ctx (loc, "coro.delete.promise", actor);
2211 b = build_case_label (build_int_cst (short_unsigned_type_node, 1), NULL_TREE,
2212 create_anon_label_with_ctx (loc, actor));
2213 add_stmt (b);
2214 add_stmt (build_stmt (loc, GOTO_EXPR, del_promise_label));
2216 short unsigned lab_num = 3;
2217 for (unsigned destr_pt = 0; destr_pt < body_count; destr_pt++)
2219 tree l_num = build_int_cst (short_unsigned_type_node, lab_num);
2220 b = build_case_label (l_num, NULL_TREE,
2221 create_anon_label_with_ctx (loc, actor));
2222 add_stmt (b);
2223 b = build_call_expr_internal_loc (loc, IFN_CO_ACTOR, void_type_node, 1,
2224 l_num);
2225 b = coro_build_cvt_void_expr_stmt (b, loc);
2226 add_stmt (b);
2227 b = build1 (GOTO_EXPR, void_type_node, CASE_LABEL (ddeflab));
2228 add_stmt (b);
2229 lab_num += 2;
2232 /* Insert the prototype dispatcher. */
2233 finish_switch_stmt (destroy_dispatcher);
2235 finish_then_clause (lsb_if);
2236 begin_else_clause (lsb_if);
2238 tree dispatcher = begin_switch_stmt ();
2239 finish_switch_cond (rat, dispatcher);
2240 b = build_case_label (build_int_cst (short_unsigned_type_node, 0), NULL_TREE,
2241 create_anon_label_with_ctx (loc, actor));
2242 add_stmt (b);
2243 b = build1 (GOTO_EXPR, void_type_node, actor_begin_label);
2244 add_stmt (b);
2246 tree rdeflab = build_case_label (NULL_TREE, NULL_TREE,
2247 create_anon_label_with_ctx (loc, actor));
2248 add_stmt (rdeflab);
2249 b = build_call_expr_loc (loc, builtin_decl_explicit (BUILT_IN_TRAP), 0);
2250 b = coro_build_cvt_void_expr_stmt (b, loc);
2251 add_stmt (b);
2253 lab_num = 2;
2254 /* The final resume should be made to hit the default (trap, UB) entry
2255 although it will be unreachable via the normal entry point, since that
2256 is set to NULL on reaching final suspend. */
2257 for (unsigned resu_pt = 0; resu_pt < body_count; resu_pt++)
2259 tree l_num = build_int_cst (short_unsigned_type_node, lab_num);
2260 b = build_case_label (l_num, NULL_TREE,
2261 create_anon_label_with_ctx (loc, actor));
2262 add_stmt (b);
2263 b = build_call_expr_internal_loc (loc, IFN_CO_ACTOR, void_type_node, 1,
2264 l_num);
2265 b = coro_build_cvt_void_expr_stmt (b, loc);
2266 add_stmt (b);
2267 b = build1 (GOTO_EXPR, void_type_node, CASE_LABEL (rdeflab));
2268 add_stmt (b);
2269 lab_num += 2;
2272 /* Insert the prototype dispatcher. */
2273 finish_switch_stmt (dispatcher);
2274 finish_else_clause (lsb_if);
2276 finish_if_stmt (lsb_if);
2278 tree r = build_stmt (loc, LABEL_EXPR, actor_begin_label);
2279 add_stmt (r);
2281 /* actor's coroutine 'self handle'. */
2282 tree ash_m = lookup_member (coro_frame_type, coro_self_handle_id, 1,
2283 0, tf_warning_or_error);
2284 tree ash = build_class_member_access_expr (actor_frame, ash_m, NULL_TREE,
2285 false, tf_warning_or_error);
2286 /* So construct the self-handle from the frame address. */
2287 tree hfa_m = lookup_member (handle_type, coro_from_address_identifier, 1,
2288 0, tf_warning_or_error);
2290 r = build1 (CONVERT_EXPR, build_pointer_type (void_type_node), actor_fp);
2291 vec<tree, va_gc> *args = make_tree_vector_single (r);
2292 tree hfa = build_new_method_call (ash, hfa_m, &args, NULL_TREE, LOOKUP_NORMAL,
2293 NULL, tf_warning_or_error);
2294 r = build2 (INIT_EXPR, handle_type, ash, hfa);
2295 r = coro_build_cvt_void_expr_stmt (r, loc);
2296 add_stmt (r);
2297 release_tree_vector (args);
2299 /* Now we know the real promise, and enough about the frame layout to
2300 decide where to put things. */
2302 await_xform_data xform = {actor, actor_frame};
2304 /* Transform the await expressions in the function body. Only do each
2305 await tree once! */
2306 hash_set<tree> pset;
2307 cp_walk_tree (&fnbody, transform_await_wrapper, &xform, &pset);
2309 /* Add in our function body with the co_returns rewritten to final form. */
2310 add_stmt (fnbody);
2312 /* now do the tail of the function. */
2313 r = build_stmt (loc, LABEL_EXPR, del_promise_label);
2314 add_stmt (r);
2316 /* Destructors for the things we built explicitly. */
2317 r = build_special_member_call (promise_proxy, complete_dtor_identifier, NULL,
2318 promise_type, LOOKUP_NORMAL,
2319 tf_warning_or_error);
2320 add_stmt (r);
2322 tree del_frame_label
2323 = create_named_label_with_ctx (loc, "coro.delete.frame", actor);
2324 r = build_stmt (loc, LABEL_EXPR, del_frame_label);
2325 add_stmt (r);
2327 /* Here deallocate the frame (if we allocated it), which we will have at
2328 present. */
2329 tree fnf_m
2330 = lookup_member (coro_frame_type, coro_frame_needs_free_id, 1,
2331 0, tf_warning_or_error);
2332 tree fnf2_x = build_class_member_access_expr (actor_frame, fnf_m, NULL_TREE,
2333 false, tf_warning_or_error);
2335 tree need_free_if = begin_if_stmt ();
2336 fnf2_x = build1 (CONVERT_EXPR, integer_type_node, fnf2_x);
2337 tree cmp = build2 (NE_EXPR, integer_type_node, fnf2_x, integer_zero_node);
2338 finish_if_stmt_cond (cmp, need_free_if);
2339 if (param_dtor_list != NULL)
2341 int i;
2342 tree pid;
2343 FOR_EACH_VEC_ELT (*param_dtor_list, i, pid)
2345 tree m
2346 = lookup_member (coro_frame_type, pid, 1, 0, tf_warning_or_error);
2347 tree a = build_class_member_access_expr (actor_frame, m, NULL_TREE,
2348 false, tf_warning_or_error);
2349 tree t = TREE_TYPE (a);
2350 tree dtor;
2351 dtor
2352 = build_special_member_call (a, complete_dtor_identifier, NULL, t,
2353 LOOKUP_NORMAL, tf_warning_or_error);
2354 add_stmt (dtor);
2358 /* Build the frame DTOR. */
2359 tree del_coro_fr = coro_get_frame_dtor (actor_fp, orig, frame_size,
2360 promise_type, loc);
2361 finish_expr_stmt (del_coro_fr);
2362 finish_then_clause (need_free_if);
2363 tree scope = IF_SCOPE (need_free_if);
2364 IF_SCOPE (need_free_if) = NULL;
2365 r = do_poplevel (scope);
2366 add_stmt (r);
2368 /* done. */
2369 r = build_stmt (loc, RETURN_EXPR, NULL);
2370 suppress_warning (r); /* We don't want a warning about this. */
2371 r = maybe_cleanup_point_expr_void (r);
2372 add_stmt (r);
2374 /* This is the suspend return point. */
2375 r = build_stmt (loc, LABEL_EXPR, ret_label);
2376 add_stmt (r);
2378 r = build_stmt (loc, RETURN_EXPR, NULL);
2379 suppress_warning (r); /* We don't want a warning about this. */
2380 r = maybe_cleanup_point_expr_void (r);
2381 add_stmt (r);
2383 /* This is the 'continuation' return point. For such a case we have a coro
2384 handle (from the await_suspend() call) and we want handle.resume() to
2385 execute as a tailcall allowing arbitrary chaining of coroutines. */
2386 r = build_stmt (loc, LABEL_EXPR, continue_label);
2387 add_stmt (r);
2389 /* We want to force a tail-call even for O0/1, so this expands the resume
2390 call into its underlying implementation. */
2391 tree addr = lookup_member (void_coro_handle_type, coro_address_identifier,
2392 1, 0, tf_warning_or_error);
2393 addr = build_new_method_call (continuation, addr, NULL, NULL_TREE,
2394 LOOKUP_NORMAL, NULL, tf_warning_or_error);
2395 tree resume = build_call_expr_loc
2396 (loc, builtin_decl_explicit (BUILT_IN_CORO_RESUME), 1, addr);
2398 /* In order to support an arbitrary number of coroutine continuations,
2399 we must tail call them. However, some targets do not support indirect
2400 tail calls to arbitrary callees. See PR94359. */
2401 CALL_EXPR_TAILCALL (resume) = true;
2402 resume = coro_build_cvt_void_expr_stmt (resume, loc);
2403 add_stmt (resume);
2405 r = build_stmt (loc, RETURN_EXPR, NULL);
2406 gcc_checking_assert (maybe_cleanup_point_expr_void (r) == r);
2407 add_stmt (r);
2409 /* We've now rewritten the tree and added the initial and final
2410 co_awaits. Now pass over the tree and expand the co_awaits. */
2412 coro_aw_data data = {actor, actor_fp, resume_idx_var, NULL_TREE,
2413 ash, del_promise_label, ret_label,
2414 continue_label, continuation, 2};
2415 cp_walk_tree (&actor_body, await_statement_expander, &data, NULL);
2417 BIND_EXPR_BODY (actor_bind) = pop_stmt_list (actor_body);
2418 TREE_SIDE_EFFECTS (actor_bind) = true;
2420 finish_compound_stmt (stmt);
2421 DECL_SAVED_TREE (actor) = pop_stmt_list (actor_outer);
2422 verify_stmt_tree (DECL_SAVED_TREE (actor));
2425 /* The prototype 'destroy' function :
2426 frame->__Coro_resume_index |= 1;
2427 actor (frame); */
2429 static void
2430 build_destroy_fn (location_t loc, tree coro_frame_type, tree destroy,
2431 tree actor)
2433 /* One param, the coro frame pointer. */
2434 tree destr_fp = DECL_ARGUMENTS (destroy);
2436 /* We have a definition here. */
2437 TREE_STATIC (destroy) = 1;
2439 tree destr_outer = push_stmt_list ();
2440 current_stmt_tree ()->stmts_are_full_exprs_p = 1;
2441 tree dstr_stmt = begin_compound_stmt (BCS_FN_BODY);
2443 tree destr_frame = build1 (INDIRECT_REF, coro_frame_type, destr_fp);
2445 tree rat_field = lookup_member (coro_frame_type, coro_resume_index_id,
2446 1, 0, tf_warning_or_error);
2447 tree rat = build3 (COMPONENT_REF, short_unsigned_type_node,
2448 destr_frame, rat_field, NULL_TREE);
2450 /* _resume_at |= 1 */
2451 tree dstr_idx = build2 (BIT_IOR_EXPR, short_unsigned_type_node, rat,
2452 build_int_cst (short_unsigned_type_node, 1));
2453 tree r = build2 (MODIFY_EXPR, short_unsigned_type_node, rat, dstr_idx);
2454 r = coro_build_cvt_void_expr_stmt (r, loc);
2455 add_stmt (r);
2457 /* So .. call the actor .. */
2458 r = build_call_expr_loc (loc, actor, 1, destr_fp);
2459 r = coro_build_cvt_void_expr_stmt (r, loc);
2460 add_stmt (r);
2462 /* done. */
2463 r = build_stmt (loc, RETURN_EXPR, NULL);
2464 r = maybe_cleanup_point_expr_void (r);
2465 add_stmt (r);
2467 finish_compound_stmt (dstr_stmt);
2468 DECL_SAVED_TREE (destroy) = pop_stmt_list (destr_outer);
2471 /* Helper that returns an identifier for an appended extension to the
2472 current un-mangled function name. */
2474 static tree
2475 get_fn_local_identifier (tree orig, const char *append)
2477 /* Figure out the bits we need to generate names for the outlined things
2478 For consistency, this needs to behave the same way as
2479 ASM_FORMAT_PRIVATE_NAME does. */
2480 tree nm = DECL_NAME (orig);
2481 const char *sep, *pfx = "";
2482 #ifndef NO_DOT_IN_LABEL
2483 sep = ".";
2484 #else
2485 #ifndef NO_DOLLAR_IN_LABEL
2486 sep = "$";
2487 #else
2488 sep = "_";
2489 pfx = "__";
2490 #endif
2491 #endif
2493 char *an;
2494 if (DECL_ASSEMBLER_NAME (orig))
2495 an = ACONCAT ((IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (orig)), sep, append,
2496 (char *) 0));
2497 else if (DECL_USE_TEMPLATE (orig) && DECL_TEMPLATE_INFO (orig)
2498 && DECL_TI_ARGS (orig))
2500 tree tpl_args = DECL_TI_ARGS (orig);
2501 an = ACONCAT ((pfx, IDENTIFIER_POINTER (nm), (char *) 0));
2502 for (int i = 0; i < TREE_VEC_LENGTH (tpl_args); ++i)
2504 tree typ = DECL_NAME (TYPE_NAME (TREE_VEC_ELT (tpl_args, i)));
2505 an = ACONCAT ((an, sep, IDENTIFIER_POINTER (typ), (char *) 0));
2507 an = ACONCAT ((an, sep, append, (char *) 0));
2509 else
2510 an = ACONCAT ((pfx, IDENTIFIER_POINTER (nm), sep, append, (char *) 0));
2512 return get_identifier (an);
2515 /* Build an initial or final await initialized from the promise
2516 initial_suspend or final_suspend expression. */
2518 static tree
2519 build_init_or_final_await (location_t loc, bool is_final)
2521 tree suspend_alt = is_final ? coro_final_suspend_identifier
2522 : coro_initial_suspend_identifier;
2524 tree setup_call
2525 = coro_build_promise_expression (current_function_decl, NULL, suspend_alt,
2526 loc, NULL, /*musthave=*/true);
2528 /* Check for noexcept on the final_suspend call. */
2529 if (flag_exceptions && is_final && setup_call != error_mark_node
2530 && coro_diagnose_throwing_final_aw_expr (setup_call))
2531 return error_mark_node;
2533 /* So build the co_await for this */
2534 /* For initial/final suspends the call is "a" per [expr.await] 3.2. */
2535 return build_co_await (loc, setup_call, (is_final ? FINAL_SUSPEND_POINT
2536 : INITIAL_SUSPEND_POINT));
2539 /* Callback to record the essential data for each await point found in the
2540 function. */
2542 static bool
2543 register_await_info (tree await_expr, tree aw_type, tree aw_nam)
2545 bool seen;
2546 suspend_point_info &s
2547 = suspend_points->get_or_insert (await_expr, &seen);
2548 if (seen)
2550 warning_at (EXPR_LOCATION (await_expr), 0, "duplicate info for %qE",
2551 await_expr);
2552 return false;
2554 s.awaitable_type = aw_type;
2555 s.await_field_id = aw_nam;
2556 return true;
2559 /* This data set is used when analyzing statements for await expressions. */
2561 struct susp_frame_data
2563 /* Function-wide. */
2564 tree *field_list; /* The current coroutine frame field list. */
2565 tree handle_type; /* The self-handle type for this coroutine. */
2566 tree fs_label; /* The destination for co_returns. */
2567 vec<tree, va_gc> *block_stack; /* Track block scopes. */
2568 vec<tree, va_gc> *bind_stack; /* Track current bind expr. */
2569 unsigned await_number; /* Which await in the function. */
2570 unsigned cond_number; /* Which replaced condition in the fn. */
2571 /* Temporary values for one statement or expression being analyzed. */
2572 hash_set<tree> captured_temps; /* The suspend captured these temps. */
2573 vec<tree, va_gc> *to_replace; /* The VAR decls to replace. */
2574 hash_set<tree> *truth_aoif_to_expand; /* The set of TRUTH exprs to expand. */
2575 unsigned saw_awaits; /* Count of awaits in this statement */
2576 bool captures_temporary; /* This expr captures temps by ref. */
2577 bool needs_truth_if_exp; /* We must expand a truth_if expression. */
2578 bool has_awaiter_init; /* We must handle initializing an awaiter. */
2581 /* If this is an await expression, then count it (both uniquely within the
2582 function and locally within a single statement). */
2584 static tree
2585 register_awaits (tree *stmt, int *, void *d)
2587 tree aw_expr = *stmt;
2589 /* We should have already lowered co_yields to their co_await. */
2590 gcc_checking_assert (TREE_CODE (aw_expr) != CO_YIELD_EXPR);
2592 if (TREE_CODE (aw_expr) != CO_AWAIT_EXPR)
2593 return NULL_TREE;
2595 /* Count how many awaits the current expression contains. */
2596 susp_frame_data *data = (susp_frame_data *) d;
2597 data->saw_awaits++;
2598 /* Each await suspend context is unique, this is a function-wide value. */
2599 data->await_number++;
2601 /* Awaitables should either be user-locals or promoted to coroutine frame
2602 entries at this point, and their initializers should have been broken
2603 out. */
2604 tree aw = TREE_OPERAND (aw_expr, 1);
2605 gcc_checking_assert (!TREE_OPERAND (aw_expr, 2));
2607 tree aw_field_type = TREE_TYPE (aw);
2608 tree aw_field_nam = NULL_TREE;
2609 register_await_info (aw_expr, aw_field_type, aw_field_nam);
2611 /* Rewrite target expressions on the await_suspend () to remove extraneous
2612 cleanups for the awaitables, which are now promoted to frame vars and
2613 managed via that. */
2614 tree v = TREE_OPERAND (aw_expr, 3);
2615 tree o = TREE_VEC_ELT (v, 1);
2616 if (TREE_CODE (o) == TARGET_EXPR)
2617 TREE_VEC_ELT (v, 1) = get_target_expr (TREE_OPERAND (o, 1));
2618 return NULL_TREE;
2621 /* There are cases where any await expression is relevant. */
2622 static tree
2623 find_any_await (tree *stmt, int *dosub, void *d)
2625 if (TREE_CODE (*stmt) == CO_AWAIT_EXPR)
2627 *dosub = 0; /* We don't need to consider this any further. */
2628 tree **p = (tree **) d;
2629 *p = stmt;
2630 return *stmt;
2632 return NULL_TREE;
2635 static bool
2636 tmp_target_expr_p (tree t)
2638 if (TREE_CODE (t) != TARGET_EXPR)
2639 return false;
2640 tree v = TREE_OPERAND (t, 0);
2641 if (!DECL_ARTIFICIAL (v))
2642 return false;
2643 if (DECL_NAME (v))
2644 return false;
2645 return true;
2648 /* Structure to record sub-expressions that need to be handled by the
2649 statement flattener. */
2651 struct coro_interesting_subtree
2653 tree* entry;
2654 hash_set<tree> *temps_used;
2657 /* tree-walk callback that returns the first encountered sub-expression of
2658 a kind that needs to be handled specifically by the statement flattener. */
2660 static tree
2661 find_interesting_subtree (tree *expr_p, int *dosub, void *d)
2663 tree expr = *expr_p;
2664 coro_interesting_subtree *p = (coro_interesting_subtree *)d;
2665 if (TREE_CODE (expr) == CO_AWAIT_EXPR)
2667 *dosub = 0; /* We don't need to consider this any further. */
2668 if (TREE_OPERAND (expr, 2))
2670 p->entry = expr_p;
2671 return expr;
2674 else if (tmp_target_expr_p (expr)
2675 && !p->temps_used->contains (expr))
2677 p->entry = expr_p;
2678 return expr;
2681 return NULL_TREE;
2684 /* Node for a doubly-linked list of promoted variables and their
2685 initializers. When the initializer is a conditional expression
2686 the 'then' and 'else' clauses are represented by a linked list
2687 attached to then_cl and else_cl respectively. */
2689 struct var_nest_node
2691 var_nest_node () = default;
2692 var_nest_node (tree v, tree i, var_nest_node *p, var_nest_node *n)
2693 : var(v), init(i), prev(p), next(n), then_cl (NULL), else_cl (NULL)
2695 if (p)
2696 p->next = this;
2697 if (n)
2698 n->prev = this;
2700 tree var;
2701 tree init;
2702 var_nest_node *prev;
2703 var_nest_node *next;
2704 var_nest_node *then_cl;
2705 var_nest_node *else_cl;
2708 /* This is called for single statements from the co-await statement walker.
2709 It checks to see if the statement contains any initializers for awaitables
2710 and if any of these capture items by reference. */
2712 static void
2713 flatten_await_stmt (var_nest_node *n, hash_set<tree> *promoted,
2714 hash_set<tree> *temps_used, tree *replace_in)
2716 bool init_expr = false;
2717 switch (TREE_CODE (n->init))
2719 default: break;
2720 /* Compound expressions must be flattened specifically. */
2721 case COMPOUND_EXPR:
2723 tree first = TREE_OPERAND (n->init, 0);
2724 n->init = TREE_OPERAND (n->init, 1);
2725 var_nest_node *ins
2726 = new var_nest_node(NULL_TREE, first, n->prev, n);
2727 /* The compiler (but not the user) can generate temporaries with
2728 uses in the second arm of a compound expr. */
2729 flatten_await_stmt (ins, promoted, temps_used, &n->init);
2730 flatten_await_stmt (n, promoted, temps_used, NULL);
2731 /* The two arms have been processed separately. */
2732 return;
2734 break;
2735 /* Handle conditional expressions. */
2736 case INIT_EXPR:
2737 init_expr = true;
2738 /* FALLTHROUGH */
2739 case MODIFY_EXPR:
2741 tree old_expr = TREE_OPERAND (n->init, 1);
2742 if (TREE_CODE (old_expr) == COMPOUND_EXPR)
2744 tree first = TREE_OPERAND (old_expr, 0);
2745 TREE_OPERAND (n->init, 1) = TREE_OPERAND (old_expr, 1);
2746 var_nest_node *ins
2747 = new var_nest_node(NULL_TREE, first, n->prev, n);
2748 flatten_await_stmt (ins, promoted, temps_used,
2749 &TREE_OPERAND (n->init, 1));
2750 flatten_await_stmt (n, promoted, temps_used, NULL);
2751 return;
2753 if (TREE_CODE (old_expr) != COND_EXPR)
2754 break;
2755 /* Reconstruct x = t ? y : z;
2756 as (void) t ? x = y : x = z; */
2757 tree var = TREE_OPERAND (n->init, 0);
2758 tree var_type = TREE_TYPE (var);
2759 tree cond = COND_EXPR_COND (old_expr);
2760 /* We are allowed a void type throw in one or both of the cond
2761 expr arms. */
2762 tree then_cl = COND_EXPR_THEN (old_expr);
2763 if (!VOID_TYPE_P (TREE_TYPE (then_cl)))
2765 gcc_checking_assert (TREE_CODE (then_cl) != STATEMENT_LIST);
2766 then_cl
2767 = build2 (init_expr ? INIT_EXPR : MODIFY_EXPR, var_type,
2768 var, then_cl);
2770 tree else_cl = COND_EXPR_ELSE (old_expr);
2771 if (!VOID_TYPE_P (TREE_TYPE (else_cl)))
2773 gcc_checking_assert (TREE_CODE (else_cl) != STATEMENT_LIST);
2774 else_cl
2775 = build2 (init_expr ? INIT_EXPR : MODIFY_EXPR, var_type,
2776 var, else_cl);
2778 n->init = build3 (COND_EXPR, var_type, cond, then_cl, else_cl);
2780 /* FALLTHROUGH */
2781 case COND_EXPR:
2783 tree *found;
2784 tree cond = COND_EXPR_COND (n->init);
2785 /* If the condition contains an await expression, then we need to
2786 set that first and use a separate var. */
2787 if (cp_walk_tree (&cond, find_any_await, &found, NULL))
2789 tree cond_type = TREE_TYPE (cond);
2790 tree cond_var = build_lang_decl (VAR_DECL, NULL_TREE, cond_type);
2791 DECL_ARTIFICIAL (cond_var) = true;
2792 layout_decl (cond_var, 0);
2793 gcc_checking_assert (!TYPE_NEEDS_CONSTRUCTING (cond_type));
2794 cond = build2 (INIT_EXPR, cond_type, cond_var, cond);
2795 var_nest_node *ins
2796 = new var_nest_node (cond_var, cond, n->prev, n);
2797 COND_EXPR_COND (n->init) = cond_var;
2798 flatten_await_stmt (ins, promoted, temps_used, NULL);
2801 n->then_cl
2802 = new var_nest_node (n->var, COND_EXPR_THEN (n->init), NULL, NULL);
2803 n->else_cl
2804 = new var_nest_node (n->var, COND_EXPR_ELSE (n->init), NULL, NULL);
2805 flatten_await_stmt (n->then_cl, promoted, temps_used, NULL);
2806 /* Point to the start of the flattened code. */
2807 while (n->then_cl->prev)
2808 n->then_cl = n->then_cl->prev;
2809 flatten_await_stmt (n->else_cl, promoted, temps_used, NULL);
2810 while (n->else_cl->prev)
2811 n->else_cl = n->else_cl->prev;
2812 return;
2814 break;
2816 coro_interesting_subtree v = { NULL, temps_used };
2817 tree t = cp_walk_tree (&n->init, find_interesting_subtree, (void *)&v, NULL);
2818 if (!t)
2819 return;
2820 switch (TREE_CODE (t))
2822 default: break;
2823 case CO_AWAIT_EXPR:
2825 /* Await expressions with initializers have a compiler-temporary
2826 as the awaitable. 'promote' this. */
2827 tree var = TREE_OPERAND (t, 1);
2828 bool already_present = promoted->add (var);
2829 gcc_checking_assert (!already_present);
2830 tree init = TREE_OPERAND (t, 2);
2831 switch (TREE_CODE (init))
2833 default: break;
2834 case INIT_EXPR:
2835 case MODIFY_EXPR:
2837 tree inner = TREE_OPERAND (init, 1);
2838 /* We can have non-lvalue-expressions here, but when we see
2839 a target expression, mark it as already used. */
2840 if (TREE_CODE (inner) == TARGET_EXPR)
2842 temps_used->add (inner);
2843 gcc_checking_assert
2844 (TREE_CODE (TREE_OPERAND (inner, 1)) != COND_EXPR);
2847 break;
2848 case CALL_EXPR:
2849 /* If this is a call and not a CTOR, then we didn't expect it. */
2850 gcc_checking_assert
2851 (DECL_CONSTRUCTOR_P (TREE_OPERAND (CALL_EXPR_FN (init), 0)));
2852 break;
2854 var_nest_node *ins = new var_nest_node (var, init, n->prev, n);
2855 TREE_OPERAND (t, 2) = NULL_TREE;
2856 flatten_await_stmt (ins, promoted, temps_used, NULL);
2857 flatten_await_stmt (n, promoted, temps_used, NULL);
2858 return;
2860 break;
2861 case TARGET_EXPR:
2863 /* We have a temporary; promote it, but allow for the idiom in code
2864 generated by the compiler like
2865 a = (target_expr produces temp, op uses temp). */
2866 tree init = t;
2867 temps_used->add (init);
2868 tree var_type = TREE_TYPE (init);
2869 char *buf = xasprintf ("D.%d", DECL_UID (TREE_OPERAND (init, 0)));
2870 tree var = build_lang_decl (VAR_DECL, get_identifier (buf), var_type);
2871 DECL_ARTIFICIAL (var) = true;
2872 free (buf);
2873 bool already_present = promoted->add (var);
2874 gcc_checking_assert (!already_present);
2875 tree inner = TREE_OPERAND (init, 1);
2876 gcc_checking_assert (TREE_CODE (inner) != COND_EXPR);
2877 init = cp_build_modify_expr (input_location, var, INIT_EXPR, init,
2878 tf_warning_or_error);
2879 /* Simplify for the case that we have an init containing the temp
2880 alone. */
2881 if (t == n->init && n->var == NULL_TREE)
2883 n->var = var;
2884 proxy_replace pr = {TREE_OPERAND (t, 0), var};
2885 cp_walk_tree (&init, replace_proxy, &pr, NULL);
2886 n->init = init;
2887 if (replace_in)
2888 cp_walk_tree (replace_in, replace_proxy, &pr, NULL);
2889 flatten_await_stmt (n, promoted, temps_used, NULL);
2891 else
2893 var_nest_node *ins
2894 = new var_nest_node (var, init, n->prev, n);
2895 /* We have to replace the target expr... */
2896 *v.entry = var;
2897 /* ... and any uses of its var. */
2898 proxy_replace pr = {TREE_OPERAND (t, 0), var};
2899 cp_walk_tree (&n->init, replace_proxy, &pr, NULL);
2900 /* Compiler-generated temporaries can also have uses in
2901 following arms of compound expressions, which will be listed
2902 in 'replace_in' if present. */
2903 if (replace_in)
2904 cp_walk_tree (replace_in, replace_proxy, &pr, NULL);
2905 flatten_await_stmt (ins, promoted, temps_used, NULL);
2906 flatten_await_stmt (n, promoted, temps_used, NULL);
2908 return;
2910 break;
2914 /* Helper for 'process_conditional' that handles recursion into nested
2915 conditionals. */
2917 static void
2918 handle_nested_conditionals (var_nest_node *n, vec<tree>& list,
2919 hash_map<tree, tree>& map)
2923 if (n->var && DECL_NAME (n->var))
2925 list.safe_push (n->var);
2926 if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (n->var)))
2928 bool existed;
2929 tree& flag = map.get_or_insert (n->var, &existed);
2930 if (!existed)
2932 /* We didn't see this var before and it needs a DTOR, so
2933 build a guard variable for it. */
2934 char *nam
2935 = xasprintf ("%s_guard",
2936 IDENTIFIER_POINTER (DECL_NAME (n->var)));
2937 flag = build_lang_decl (VAR_DECL, get_identifier (nam),
2938 boolean_type_node);
2939 free (nam);
2940 DECL_ARTIFICIAL (flag) = true;
2943 /* The initializer for this variable is replaced by a compound
2944 expression that performs the init and then records that the
2945 variable is live (and the DTOR should be run at the scope
2946 exit. */
2947 tree set_flag = build2 (INIT_EXPR, boolean_type_node,
2948 flag, boolean_true_node);
2949 n->init
2950 = build2 (COMPOUND_EXPR, boolean_type_node, n->init, set_flag);
2953 if (TREE_CODE (n->init) == COND_EXPR)
2955 tree new_then = push_stmt_list ();
2956 handle_nested_conditionals (n->then_cl, list, map);
2957 new_then = pop_stmt_list (new_then);
2958 tree new_else = push_stmt_list ();
2959 handle_nested_conditionals (n->else_cl, list, map);
2960 new_else = pop_stmt_list (new_else);
2961 tree new_if
2962 = build4 (IF_STMT, void_type_node, COND_EXPR_COND (n->init),
2963 new_then, new_else, NULL_TREE);
2964 add_stmt (new_if);
2966 else
2967 finish_expr_stmt (n->init);
2968 n = n->next;
2969 } while (n);
2972 /* helper for 'maybe_promote_temps'.
2974 When we have a conditional expression which might embed await expressions
2975 and/or promoted variables, we need to handle it appropriately.
2977 The linked lists for the 'then' and 'else' clauses in a conditional node
2978 identify the promoted variables (but these cannot be wrapped in a regular
2979 cleanup).
2981 So recurse through the lists and build up a composite list of captured vars.
2982 Declare these and any guard variables needed to decide if a DTOR should be
2983 run. Then embed the conditional into a try-finally expression that handles
2984 running each DTOR conditionally on its guard variable. */
2986 static void
2987 process_conditional (var_nest_node *n, tree& vlist)
2989 tree init = n->init;
2990 hash_map<tree, tree> var_flags;
2991 auto_vec<tree> var_list;
2992 tree new_then = push_stmt_list ();
2993 handle_nested_conditionals (n->then_cl, var_list, var_flags);
2994 new_then = pop_stmt_list (new_then);
2995 tree new_else = push_stmt_list ();
2996 handle_nested_conditionals (n->else_cl, var_list, var_flags);
2997 new_else = pop_stmt_list (new_else);
2998 /* Declare the vars. There are two loops so that the boolean flags are
2999 grouped in the frame. */
3000 for (unsigned i = 0; i < var_list.length(); i++)
3002 tree var = var_list[i];
3003 DECL_CHAIN (var) = vlist;
3004 vlist = var;
3005 add_decl_expr (var);
3007 /* Define the guard flags for variables that need a DTOR. */
3008 for (unsigned i = 0; i < var_list.length(); i++)
3010 tree *flag = var_flags.get (var_list[i]);
3011 if (flag)
3013 DECL_INITIAL (*flag) = boolean_false_node;
3014 DECL_CHAIN (*flag) = vlist;
3015 vlist = *flag;
3016 add_decl_expr (*flag);
3019 tree new_if
3020 = build4 (IF_STMT, void_type_node, COND_EXPR_COND (init),
3021 new_then, new_else, NULL_TREE);
3022 /* Build a set of conditional DTORs. */
3023 tree final_actions = push_stmt_list ();
3024 while (!var_list.is_empty())
3026 tree var = var_list.pop ();
3027 tree *flag = var_flags.get (var);
3028 if (!flag)
3029 continue;
3030 tree var_type = TREE_TYPE (var);
3031 tree cleanup
3032 = build_special_member_call (var, complete_dtor_identifier,
3033 NULL, var_type, LOOKUP_NORMAL,
3034 tf_warning_or_error);
3035 tree cond_cleanup = begin_if_stmt ();
3036 finish_if_stmt_cond (*flag, cond_cleanup);
3037 finish_expr_stmt (cleanup);
3038 finish_then_clause (cond_cleanup);
3039 finish_if_stmt (cond_cleanup);
3041 final_actions = pop_stmt_list (final_actions);
3042 tree try_finally
3043 = build2 (TRY_FINALLY_EXPR, void_type_node, new_if, final_actions);
3044 add_stmt (try_finally);
3047 /* Given *STMT, that contains at least one await expression.
3049 The full expression represented in the original source code will contain
3050 suspension points, but it is still required that the lifetime of temporary
3051 values extends to the end of the expression.
3053 We already have a mechanism to 'promote' user-authored local variables
3054 to a coroutine frame counterpart (which allows explicit management of the
3055 lifetime across suspensions). The transform here re-writes STMT into
3056 a bind expression, promotes temporary values into local variables in that
3057 and flattens the statement into a series of cleanups.
3059 Conditional expressions are re-written to regular 'if' statements.
3060 The cleanups for variables initialized inside a conditional (including
3061 nested cases) are wrapped in a try-finally clause, with guard variables
3062 to determine which DTORs need to be run. */
3064 static tree
3065 maybe_promote_temps (tree *stmt, void *d)
3067 susp_frame_data *awpts = (susp_frame_data *) d;
3069 location_t sloc = EXPR_LOCATION (*stmt);
3070 tree expr = *stmt;
3071 /* Strip off uninteresting wrappers. */
3072 if (TREE_CODE (expr) == CLEANUP_POINT_EXPR)
3073 expr = TREE_OPERAND (expr, 0);
3074 if (TREE_CODE (expr) == EXPR_STMT)
3075 expr = EXPR_STMT_EXPR (expr);
3076 if (TREE_CODE (expr) == CONVERT_EXPR
3077 && VOID_TYPE_P (TREE_TYPE (expr)))
3078 expr = TREE_OPERAND (expr, 0);
3079 STRIP_NOPS (expr);
3081 /* We walk the statement trees, flattening it into an ordered list of
3082 variables with initializers and fragments corresponding to compound
3083 expressions, truth or/and if and ternary conditionals. Conditional
3084 expressions carry a nested list of fragments for the then and else
3085 clauses. We anchor to the 'bottom' of the fragment list; we will write
3086 a cleanup nest with one shell for each variable initialized. */
3087 var_nest_node *root = new var_nest_node (NULL_TREE, expr, NULL, NULL);
3088 /* Check to see we didn't promote one twice. */
3089 hash_set<tree> promoted_vars;
3090 hash_set<tree> used_temps;
3091 flatten_await_stmt (root, &promoted_vars, &used_temps, NULL);
3093 gcc_checking_assert (root->next == NULL);
3094 tree vlist = NULL_TREE;
3095 var_nest_node *t = root;
3096 /* We build the bind scope expression from the bottom-up.
3097 EXPR_LIST holds the inner expression nest at the current cleanup
3098 level (becoming the final expression list when we've exhausted the
3099 number of sub-expression fragments). */
3100 tree expr_list = NULL_TREE;
3103 tree new_list = push_stmt_list ();
3104 /* When we have a promoted variable, then add that to the bind scope
3105 and initialize it. When there's no promoted variable, we just need
3106 to run the initializer.
3107 If the initializer is a conditional expression, we need to collect
3108 and declare any promoted variables nested within it. DTORs for such
3109 variables must be run conditionally too. */
3110 if (t->var && DECL_NAME (t->var))
3112 tree var = t->var;
3113 DECL_CHAIN (var) = vlist;
3114 vlist = var;
3115 add_decl_expr (var);
3116 if (TREE_CODE (t->init) == COND_EXPR)
3117 process_conditional (t, vlist);
3118 else
3119 finish_expr_stmt (t->init);
3120 tree var_type = TREE_TYPE (var);
3121 if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (var_type))
3123 tree cleanup
3124 = build_special_member_call (var, complete_dtor_identifier,
3125 NULL, var_type, LOOKUP_NORMAL,
3126 tf_warning_or_error);
3127 tree cl = build_stmt (sloc, CLEANUP_STMT, expr_list, cleanup, var);
3128 add_stmt (cl); /* push this onto the level above. */
3130 else if (expr_list)
3132 if (TREE_CODE (expr_list) != STATEMENT_LIST)
3133 add_stmt (expr_list);
3134 else if (!tsi_end_p (tsi_start (expr_list)))
3135 add_stmt (expr_list);
3138 else
3140 if (TREE_CODE (t->init) == COND_EXPR)
3141 process_conditional (t, vlist);
3142 else
3143 finish_expr_stmt (t->init);
3144 if (expr_list)
3146 if (TREE_CODE (expr_list) != STATEMENT_LIST)
3147 add_stmt (expr_list);
3148 else if (!tsi_end_p (tsi_start (expr_list)))
3149 add_stmt (expr_list);
3152 expr_list = pop_stmt_list (new_list);
3153 var_nest_node *old = t;
3154 t = t->prev;
3155 delete old;
3156 } while (t);
3158 /* Now produce the bind expression containing the 'promoted' temporaries
3159 as its variable list, and the cleanup nest as the statement. */
3160 tree await_bind = build3_loc (sloc, BIND_EXPR, void_type_node,
3161 NULL, NULL, NULL);
3162 BIND_EXPR_BODY (await_bind) = expr_list;
3163 BIND_EXPR_VARS (await_bind) = nreverse (vlist);
3164 tree b_block = make_node (BLOCK);
3165 if (!awpts->block_stack->is_empty ())
3167 tree s_block = awpts->block_stack->last ();
3168 if (s_block)
3170 BLOCK_SUPERCONTEXT (b_block) = s_block;
3171 BLOCK_CHAIN (b_block) = BLOCK_SUBBLOCKS (s_block);
3172 BLOCK_SUBBLOCKS (s_block) = b_block;
3175 BLOCK_VARS (b_block) = BIND_EXPR_VARS (await_bind) ;
3176 BIND_EXPR_BLOCK (await_bind) = b_block;
3177 TREE_SIDE_EFFECTS (await_bind) = TREE_SIDE_EFFECTS (BIND_EXPR_BODY (await_bind));
3178 *stmt = await_bind;
3179 hash_set<tree> visited;
3180 return cp_walk_tree (stmt, register_awaits, d, &visited);
3183 /* Lightweight callback to determine two key factors:
3184 1) If the statement/expression contains any await expressions.
3185 2) If the statement/expression potentially requires a re-write to handle
3186 TRUTH_{AND,OR}IF_EXPRs since, in most cases, they will need expansion
3187 so that the await expressions are not processed in the case of the
3188 short-circuit arm.
3190 CO_YIELD expressions are re-written to their underlying co_await. */
3192 static tree
3193 analyze_expression_awaits (tree *stmt, int *do_subtree, void *d)
3195 susp_frame_data *awpts = (susp_frame_data *) d;
3197 switch (TREE_CODE (*stmt))
3199 default: return NULL_TREE;
3200 case CO_YIELD_EXPR:
3201 /* co_yield is syntactic sugar, re-write it to co_await. */
3202 *stmt = TREE_OPERAND (*stmt, 1);
3203 /* FALLTHROUGH */
3204 case CO_AWAIT_EXPR:
3205 awpts->saw_awaits++;
3206 /* A non-null initializer for the awaiter means we need to expand. */
3207 if (TREE_OPERAND (*stmt, 2))
3208 awpts->has_awaiter_init = true;
3209 break;
3210 case TRUTH_ANDIF_EXPR:
3211 case TRUTH_ORIF_EXPR:
3213 /* We don't need special action for awaits in the always-executed
3214 arm of a TRUTH_IF. */
3215 if (tree res = cp_walk_tree (&TREE_OPERAND (*stmt, 0),
3216 analyze_expression_awaits, d, NULL))
3217 return res;
3218 /* However, if there are await expressions on the conditionally
3219 executed branch, we must expand the TRUTH_IF to ensure that the
3220 expanded await expression control-flow is fully contained in the
3221 conditionally executed code. */
3222 unsigned aw_count = awpts->saw_awaits;
3223 if (tree res = cp_walk_tree (&TREE_OPERAND (*stmt, 1),
3224 analyze_expression_awaits, d, NULL))
3225 return res;
3226 if (awpts->saw_awaits > aw_count)
3228 awpts->truth_aoif_to_expand->add (*stmt);
3229 awpts->needs_truth_if_exp = true;
3231 /* We've done the sub-trees here. */
3232 *do_subtree = 0;
3234 break;
3237 return NULL_TREE; /* Recurse until done. */
3240 /* Given *EXPR
3241 If EXPR contains a TRUTH_{AND,OR}IF_EXPR, TAOIE with an await expr on
3242 the conditionally executed branch, change this in a ternary operator.
3244 bool not_expr = TAOIE == TRUTH_ORIF_EXPR ? NOT : NOP;
3245 not_expr (always-exec expr) ? conditionally-exec expr : not_expr;
3247 Apply this recursively to the condition and the conditionally-exec
3248 branch. */
3250 struct truth_if_transform {
3251 tree *orig_stmt;
3252 tree scratch_var;
3253 hash_set<tree> *truth_aoif_to_expand;
3256 static tree
3257 expand_one_truth_if (tree *expr, int *do_subtree, void *d)
3259 truth_if_transform *xform = (truth_if_transform *) d;
3261 bool needs_not = false;
3262 switch (TREE_CODE (*expr))
3264 default: break;
3265 case TRUTH_ORIF_EXPR:
3266 needs_not = true;
3267 /* FALLTHROUGH */
3268 case TRUTH_ANDIF_EXPR:
3270 if (!xform->truth_aoif_to_expand->contains (*expr))
3271 break;
3273 location_t sloc = EXPR_LOCATION (*expr);
3274 /* Transform truth expression into a cond expression with
3275 * the always-executed arm as the condition.
3276 * the conditionally-executed arm as the then clause.
3277 * the 'else' clause is fixed: 'true' for ||,'false' for &&. */
3278 tree cond = TREE_OPERAND (*expr, 0);
3279 tree test1 = TREE_OPERAND (*expr, 1);
3280 tree fixed = needs_not ? boolean_true_node : boolean_false_node;
3281 if (needs_not)
3282 cond = build1 (TRUTH_NOT_EXPR, boolean_type_node, cond);
3283 tree cond_expr
3284 = build3_loc (sloc, COND_EXPR, boolean_type_node,
3285 cond, test1, fixed);
3286 *expr = cond_expr;
3287 if (tree res = cp_walk_tree (&COND_EXPR_COND (*expr),
3288 expand_one_truth_if, d, NULL))
3289 return res;
3290 if (tree res = cp_walk_tree (&COND_EXPR_THEN (*expr),
3291 expand_one_truth_if, d, NULL))
3292 return res;
3293 /* We've manually processed necessary sub-trees here. */
3294 *do_subtree = 0;
3296 break;
3298 return NULL_TREE;
3301 /* Helper that adds a new variable of VAR_TYPE to a bind scope BIND, the
3302 name is made up from NAM_ROOT, NAM_VERS. */
3304 static tree
3305 add_var_to_bind (tree& bind, tree var_type,
3306 const char *nam_root, unsigned nam_vers)
3308 tree b_vars = BIND_EXPR_VARS (bind);
3309 /* Build a variable to hold the condition, this will be included in the
3310 frame as a local var. */
3311 char *nam = xasprintf ("%s.%d", nam_root, nam_vers);
3312 tree newvar = build_lang_decl (VAR_DECL, get_identifier (nam), var_type);
3313 free (nam);
3314 DECL_CHAIN (newvar) = b_vars;
3315 BIND_EXPR_VARS (bind) = newvar;
3316 return newvar;
3319 /* Helper to build and add if (!cond) break; */
3321 static void
3322 coro_build_add_if_not_cond_break (tree cond)
3324 tree if_stmt = begin_if_stmt ();
3325 tree invert = build1 (TRUTH_NOT_EXPR, boolean_type_node, cond);
3326 finish_if_stmt_cond (invert, if_stmt);
3327 finish_break_stmt ();
3328 finish_then_clause (if_stmt);
3329 finish_if_stmt (if_stmt);
3332 /* Tree walk callback to replace continue statements with goto label. */
3333 static tree
3334 replace_continue (tree *stmt, int *do_subtree, void *d)
3336 tree expr = *stmt;
3337 if (TREE_CODE (expr) == CLEANUP_POINT_EXPR)
3338 expr = TREE_OPERAND (expr, 0);
3339 if (CONVERT_EXPR_P (expr) && VOID_TYPE_P (expr))
3340 expr = TREE_OPERAND (expr, 0);
3341 STRIP_NOPS (expr);
3342 if (!STATEMENT_CLASS_P (expr))
3343 return NULL_TREE;
3345 switch (TREE_CODE (expr))
3347 /* Unless it's a special case, just walk the subtrees as usual. */
3348 default: return NULL_TREE;
3350 case CONTINUE_STMT:
3352 tree *label = (tree *)d;
3353 location_t loc = EXPR_LOCATION (expr);
3354 /* re-write a continue to goto label. */
3355 *stmt = build_stmt (loc, GOTO_EXPR, *label);
3356 *do_subtree = 0;
3357 return NULL_TREE;
3360 /* Statements that do not require recursion. */
3361 case DECL_EXPR:
3362 case BREAK_STMT:
3363 case GOTO_EXPR:
3364 case LABEL_EXPR:
3365 case CASE_LABEL_EXPR:
3366 case ASM_EXPR:
3367 /* These must break recursion. */
3368 case FOR_STMT:
3369 case WHILE_STMT:
3370 case DO_STMT:
3371 *do_subtree = 0;
3372 return NULL_TREE;
3376 /* Tree walk callback to analyze, register and pre-process statements that
3377 contain await expressions. */
3379 static tree
3380 await_statement_walker (tree *stmt, int *do_subtree, void *d)
3382 tree res = NULL_TREE;
3383 susp_frame_data *awpts = (susp_frame_data *) d;
3385 /* Process a statement at a time. */
3386 if (TREE_CODE (*stmt) == BIND_EXPR)
3388 /* For conditional expressions, we might wish to add an artificial var
3389 to their containing bind expr. */
3390 vec_safe_push (awpts->bind_stack, *stmt);
3391 /* We might need to insert a new bind expression, and want to link it
3392 into the correct scope, so keep a note of the current block scope. */
3393 tree blk = BIND_EXPR_BLOCK (*stmt);
3394 vec_safe_push (awpts->block_stack, blk);
3395 res = cp_walk_tree (&BIND_EXPR_BODY (*stmt), await_statement_walker,
3396 d, NULL);
3397 awpts->block_stack->pop ();
3398 awpts->bind_stack->pop ();
3399 *do_subtree = 0; /* Done subtrees. */
3400 return res;
3402 else if (TREE_CODE (*stmt) == STATEMENT_LIST)
3404 for (tree &s : tsi_range (*stmt))
3406 res = cp_walk_tree (&s, await_statement_walker,
3407 d, NULL);
3408 if (res)
3409 return res;
3411 *do_subtree = 0; /* Done subtrees. */
3412 return NULL_TREE;
3415 /* We have something to be handled as a single statement. We have to handle
3416 a few statements specially where await statements have to be moved out of
3417 constructs. */
3418 tree expr = *stmt;
3419 if (TREE_CODE (*stmt) == CLEANUP_POINT_EXPR)
3420 expr = TREE_OPERAND (expr, 0);
3421 STRIP_NOPS (expr);
3423 if (STATEMENT_CLASS_P (expr))
3424 switch (TREE_CODE (expr))
3426 /* Unless it's a special case, just walk the subtrees as usual. */
3427 default: return NULL_TREE;
3429 /* When we have a conditional expression, which contains one or more
3430 await expressions, we have to break the condition out into a
3431 regular statement so that the control flow introduced by the await
3432 transforms can be implemented. */
3433 case IF_STMT:
3435 tree *await_ptr;
3436 hash_set<tree> visited;
3437 /* Transform 'if (cond with awaits) then stmt1 else stmt2' into
3438 bool cond = cond with awaits.
3439 if (cond) then stmt1 else stmt2. */
3440 tree if_stmt = *stmt;
3441 /* We treat the condition as if it was a stand-alone statement,
3442 to see if there are any await expressions which will be analyzed
3443 and registered. */
3444 if (!(cp_walk_tree (&IF_COND (if_stmt),
3445 find_any_await, &await_ptr, &visited)))
3446 return NULL_TREE; /* Nothing special to do here. */
3448 gcc_checking_assert (!awpts->bind_stack->is_empty());
3449 tree& bind_expr = awpts->bind_stack->last ();
3450 tree newvar = add_var_to_bind (bind_expr, boolean_type_node,
3451 "ifcd", awpts->cond_number++);
3452 tree insert_list = push_stmt_list ();
3453 tree cond_inner = IF_COND (if_stmt);
3454 if (TREE_CODE (cond_inner) == CLEANUP_POINT_EXPR)
3455 cond_inner = TREE_OPERAND (cond_inner, 0);
3456 add_decl_expr (newvar);
3457 location_t sloc = EXPR_LOCATION (IF_COND (if_stmt));
3458 /* We want to initialize the new variable with the expression
3459 that contains the await(s) and potentially also needs to
3460 have truth_if expressions expanded. */
3461 tree new_s = build2_loc (sloc, INIT_EXPR, boolean_type_node,
3462 newvar, cond_inner);
3463 finish_expr_stmt (new_s);
3464 IF_COND (if_stmt) = newvar;
3465 add_stmt (if_stmt);
3466 *stmt = pop_stmt_list (insert_list);
3467 /* So now walk the new statement list. */
3468 res = cp_walk_tree (stmt, await_statement_walker, d, NULL);
3469 *do_subtree = 0; /* Done subtrees. */
3470 return res;
3472 break;
3473 case FOR_STMT:
3475 tree *await_ptr;
3476 hash_set<tree> visited;
3477 /* for loops only need special treatment if the condition or the
3478 iteration expression contain a co_await. */
3479 tree for_stmt = *stmt;
3480 /* At present, the FE always generates a separate initializer for
3481 the FOR_INIT_STMT, when the expression has an await. Check that
3482 this assumption holds in the future. */
3483 gcc_checking_assert
3484 (!(cp_walk_tree (&FOR_INIT_STMT (for_stmt), find_any_await,
3485 &await_ptr, &visited)));
3487 visited.empty ();
3488 bool for_cond_await
3489 = cp_walk_tree (&FOR_COND (for_stmt), find_any_await,
3490 &await_ptr, &visited);
3492 visited.empty ();
3493 bool for_expr_await
3494 = cp_walk_tree (&FOR_EXPR (for_stmt), find_any_await,
3495 &await_ptr, &visited);
3497 /* If the condition has an await, then we will need to rewrite the
3498 loop as
3499 for (init expression;true;iteration expression) {
3500 condition = await expression;
3501 if (condition)
3502 break;
3506 if (for_cond_await)
3508 tree insert_list = push_stmt_list ();
3509 /* This will be expanded when the revised body is handled. */
3510 coro_build_add_if_not_cond_break (FOR_COND (for_stmt));
3511 /* .. add the original for body. */
3512 add_stmt (FOR_BODY (for_stmt));
3513 /* To make the new for body. */
3514 FOR_BODY (for_stmt) = pop_stmt_list (insert_list);
3515 FOR_COND (for_stmt) = boolean_true_node;
3517 /* If the iteration expression has an await, it's a bit more
3518 tricky.
3519 for (init expression;condition;) {
3521 iteration_expr_label:
3522 iteration expression with await;
3524 but, then we will need to re-write any continue statements into
3525 'goto iteration_expr_label:'.
3527 if (for_expr_await)
3529 location_t sloc = EXPR_LOCATION (FOR_EXPR (for_stmt));
3530 tree insert_list = push_stmt_list ();
3531 /* The original for body. */
3532 add_stmt (FOR_BODY (for_stmt));
3533 char *buf = xasprintf ("for.iter.expr.%u", awpts->cond_number++);
3534 tree it_expr_label
3535 = create_named_label_with_ctx (sloc, buf, NULL_TREE);
3536 free (buf);
3537 add_stmt (build_stmt (sloc, LABEL_EXPR, it_expr_label));
3538 tree for_expr = FOR_EXPR (for_stmt);
3539 /* Present the iteration expression as a statement. */
3540 if (TREE_CODE (for_expr) == CLEANUP_POINT_EXPR)
3541 for_expr = TREE_OPERAND (for_expr, 0);
3542 STRIP_NOPS (for_expr);
3543 finish_expr_stmt (for_expr);
3544 FOR_EXPR (for_stmt) = NULL_TREE;
3545 FOR_BODY (for_stmt) = pop_stmt_list (insert_list);
3546 /* rewrite continue statements to goto label. */
3547 hash_set<tree> visited_continue;
3548 if ((res = cp_walk_tree (&FOR_BODY (for_stmt),
3549 replace_continue, &it_expr_label, &visited_continue)))
3550 return res;
3553 /* So now walk the body statement (list), if there were no await
3554 expressions, then this handles the original body - and either
3555 way we will have finished with this statement. */
3556 res = cp_walk_tree (&FOR_BODY (for_stmt),
3557 await_statement_walker, d, NULL);
3558 *do_subtree = 0; /* Done subtrees. */
3559 return res;
3561 break;
3562 case WHILE_STMT:
3564 /* We turn 'while (cond with awaits) stmt' into
3565 while (true) {
3566 if (!(cond with awaits))
3567 break;
3568 stmt..
3569 } */
3570 tree *await_ptr;
3571 hash_set<tree> visited;
3572 tree while_stmt = *stmt;
3573 if (!(cp_walk_tree (&WHILE_COND (while_stmt),
3574 find_any_await, &await_ptr, &visited)))
3575 return NULL_TREE; /* Nothing special to do here. */
3577 tree insert_list = push_stmt_list ();
3578 coro_build_add_if_not_cond_break (WHILE_COND (while_stmt));
3579 /* The original while body. */
3580 add_stmt (WHILE_BODY (while_stmt));
3581 /* The new while body. */
3582 WHILE_BODY (while_stmt) = pop_stmt_list (insert_list);
3583 WHILE_COND (while_stmt) = boolean_true_node;
3584 /* So now walk the new statement list. */
3585 res = cp_walk_tree (&WHILE_BODY (while_stmt),
3586 await_statement_walker, d, NULL);
3587 *do_subtree = 0; /* Done subtrees. */
3588 return res;
3590 break;
3591 case DO_STMT:
3593 /* We turn do stmt while (cond with awaits) into:
3594 do {
3595 stmt..
3596 if (!(cond with awaits))
3597 break;
3598 } while (true); */
3599 tree do_stmt = *stmt;
3600 tree *await_ptr;
3601 hash_set<tree> visited;
3602 if (!(cp_walk_tree (&DO_COND (do_stmt),
3603 find_any_await, &await_ptr, &visited)))
3604 return NULL_TREE; /* Nothing special to do here. */
3606 tree insert_list = push_stmt_list ();
3607 /* The original do stmt body. */
3608 add_stmt (DO_BODY (do_stmt));
3609 coro_build_add_if_not_cond_break (DO_COND (do_stmt));
3610 /* The new while body. */
3611 DO_BODY (do_stmt) = pop_stmt_list (insert_list);
3612 DO_COND (do_stmt) = boolean_true_node;
3613 /* So now walk the new statement list. */
3614 res = cp_walk_tree (&DO_BODY (do_stmt), await_statement_walker,
3615 d, NULL);
3616 *do_subtree = 0; /* Done subtrees. */
3617 return res;
3619 break;
3620 case SWITCH_STMT:
3622 /* We turn 'switch (cond with awaits) stmt' into
3623 switch_type cond = cond with awaits
3624 switch (cond) stmt. */
3625 tree sw_stmt = *stmt;
3626 tree *await_ptr;
3627 hash_set<tree> visited;
3628 if (!(cp_walk_tree (&SWITCH_STMT_COND (sw_stmt),
3629 find_any_await, &await_ptr, &visited)))
3630 return NULL_TREE; /* Nothing special to do here. */
3632 gcc_checking_assert (!awpts->bind_stack->is_empty());
3633 /* Build a variable to hold the condition, this will be
3634 included in the frame as a local var. */
3635 tree& bind_expr = awpts->bind_stack->last ();
3636 tree sw_type = SWITCH_STMT_TYPE (sw_stmt);
3637 tree newvar = add_var_to_bind (bind_expr, sw_type, "swch",
3638 awpts->cond_number++);
3639 tree insert_list = push_stmt_list ();
3640 add_decl_expr (newvar);
3642 tree cond_inner = SWITCH_STMT_COND (sw_stmt);
3643 if (TREE_CODE (cond_inner) == CLEANUP_POINT_EXPR)
3644 cond_inner = TREE_OPERAND (cond_inner, 0);
3645 location_t sloc = EXPR_LOCATION (SWITCH_STMT_COND (sw_stmt));
3646 tree new_s = build2_loc (sloc, INIT_EXPR, sw_type, newvar,
3647 cond_inner);
3648 finish_expr_stmt (new_s);
3649 SWITCH_STMT_COND (sw_stmt) = newvar;
3650 /* Now add the switch statement with the condition re-
3651 written to use the local var. */
3652 add_stmt (sw_stmt);
3653 *stmt = pop_stmt_list (insert_list);
3654 /* Process the expanded list. */
3655 res = cp_walk_tree (stmt, await_statement_walker,
3656 d, NULL);
3657 *do_subtree = 0; /* Done subtrees. */
3658 return res;
3660 break;
3661 case CO_RETURN_EXPR:
3663 /* Expand the co_return as per [stmt.return.coroutine]
3664 - for co_return;
3665 { p.return_void (); goto final_suspend; }
3666 - for co_return [void expr];
3667 { expr; p.return_void(); goto final_suspend;}
3668 - for co_return [non void expr];
3669 { p.return_value(expr); goto final_suspend; } */
3670 location_t loc = EXPR_LOCATION (expr);
3671 tree call = TREE_OPERAND (expr, 1);
3672 expr = TREE_OPERAND (expr, 0);
3673 tree ret_list = push_stmt_list ();
3674 /* [stmt.return.coroutine], 2.2
3675 If expr is present and void, it is placed immediately before
3676 the call for return_void; */
3677 if (expr && VOID_TYPE_P (TREE_TYPE (expr)))
3678 finish_expr_stmt (expr);
3679 /* Insert p.return_{void,value(expr)}. */
3680 finish_expr_stmt (call);
3681 TREE_USED (awpts->fs_label) = 1;
3682 add_stmt (build_stmt (loc, GOTO_EXPR, awpts->fs_label));
3683 *stmt = pop_stmt_list (ret_list);
3684 res = cp_walk_tree (stmt, await_statement_walker, d, NULL);
3685 /* Once this is complete, we will have processed subtrees. */
3686 *do_subtree = 0;
3687 return res;
3689 break;
3691 else if (EXPR_P (expr))
3693 hash_set<tree> visited;
3694 tree *await_ptr;
3695 if (!(cp_walk_tree (stmt, find_any_await, &await_ptr, &visited)))
3696 return NULL_TREE; /* Nothing special to do here. */
3698 visited.empty ();
3699 awpts->saw_awaits = 0;
3700 hash_set<tree> truth_aoif_to_expand;
3701 awpts->truth_aoif_to_expand = &truth_aoif_to_expand;
3702 awpts->needs_truth_if_exp = false;
3703 awpts->has_awaiter_init = false;
3704 if ((res = cp_walk_tree (stmt, analyze_expression_awaits, d, &visited)))
3705 return res;
3706 *do_subtree = 0; /* Done subtrees. */
3707 if (!awpts->saw_awaits)
3708 return NULL_TREE; /* Nothing special to do here. */
3710 if (awpts->needs_truth_if_exp)
3712 /* If a truth-and/or-if expression has an await expression in the
3713 conditionally-taken branch, then it must be rewritten into a
3714 regular conditional. */
3715 truth_if_transform xf = {stmt, NULL_TREE, &truth_aoif_to_expand};
3716 if ((res = cp_walk_tree (stmt, expand_one_truth_if, &xf, NULL)))
3717 return res;
3719 /* Process this statement, which contains at least one await expression
3720 to 'promote' temporary values to a coroutine frame slot. */
3721 return maybe_promote_temps (stmt, d);
3723 /* Continue recursion, if needed. */
3724 return res;
3727 /* For figuring out what param usage we have. */
3729 struct param_frame_data
3731 tree *field_list;
3732 hash_map<tree, param_info> *param_uses;
3733 hash_set<tree *> *visited;
3734 location_t loc;
3735 bool param_seen;
3738 /* A tree walk callback that rewrites each parm use to the local variable
3739 that represents its copy in the frame. */
3741 static tree
3742 rewrite_param_uses (tree *stmt, int *do_subtree ATTRIBUTE_UNUSED, void *d)
3744 param_frame_data *data = (param_frame_data *) d;
3746 /* For lambda closure content, we have to look specifically. */
3747 if (TREE_CODE (*stmt) == VAR_DECL && DECL_HAS_VALUE_EXPR_P (*stmt))
3749 tree t = DECL_VALUE_EXPR (*stmt);
3750 return cp_walk_tree (&t, rewrite_param_uses, d, NULL);
3753 if (TREE_CODE (*stmt) != PARM_DECL)
3754 return NULL_TREE;
3756 /* If we already saw the containing expression, then we're done. */
3757 if (data->visited->add (stmt))
3758 return NULL_TREE;
3760 bool existed;
3761 param_info &parm = data->param_uses->get_or_insert (*stmt, &existed);
3762 gcc_checking_assert (existed);
3764 *stmt = parm.copy_var;
3765 return NULL_TREE;
3768 /* Build up a set of info that determines how each param copy will be
3769 handled. */
3771 static hash_map<tree, param_info> *
3772 analyze_fn_parms (tree orig)
3774 if (!DECL_ARGUMENTS (orig))
3775 return NULL;
3777 hash_map<tree, param_info> *param_uses = new hash_map<tree, param_info>;
3779 /* Build a hash map with an entry for each param.
3780 The key is the param tree.
3781 Then we have an entry for the frame field name.
3782 Then a cache for the field ref when we come to use it.
3783 Then a tree list of the uses.
3784 The second two entries start out empty - and only get populated
3785 when we see uses. */
3786 bool lambda_p = LAMBDA_FUNCTION_P (orig);
3788 unsigned no_name_parm = 0;
3789 for (tree arg = DECL_ARGUMENTS (orig); arg != NULL; arg = DECL_CHAIN (arg))
3791 bool existed;
3792 param_info &parm = param_uses->get_or_insert (arg, &existed);
3793 gcc_checking_assert (!existed);
3794 parm.body_uses = NULL;
3795 tree actual_type = TREE_TYPE (arg);
3796 actual_type = complete_type_or_else (actual_type, orig);
3797 if (actual_type == NULL_TREE)
3798 actual_type = error_mark_node;
3799 parm.orig_type = actual_type;
3800 parm.by_ref = parm.pt_ref = parm.rv_ref = false;
3801 if (TREE_CODE (actual_type) == REFERENCE_TYPE)
3803 /* If the user passes by reference, then we will save the
3804 pointer to the original. As noted in
3805 [dcl.fct.def.coroutine] / 13, if the lifetime of the
3806 referenced item ends and then the coroutine is resumed,
3807 we have UB; well, the user asked for it. */
3808 if (TYPE_REF_IS_RVALUE (actual_type))
3809 parm.rv_ref = true;
3810 else
3811 parm.pt_ref = true;
3813 else if (TYPE_REF_P (DECL_ARG_TYPE (arg)))
3814 parm.by_ref = true;
3816 parm.frame_type = actual_type;
3818 parm.this_ptr = is_this_parameter (arg);
3819 parm.lambda_cobj = lambda_p && DECL_NAME (arg) == closure_identifier;
3821 tree name = DECL_NAME (arg);
3822 if (!name)
3824 char *buf = xasprintf ("_Coro_unnamed_parm_%d", no_name_parm++);
3825 name = get_identifier (buf);
3826 free (buf);
3828 parm.field_id = name;
3830 if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (parm.frame_type))
3832 char *buf = xasprintf ("%s%s_live", DECL_NAME (arg) ? "_Coro_" : "",
3833 IDENTIFIER_POINTER (name));
3834 parm.guard_var
3835 = coro_build_artificial_var (UNKNOWN_LOCATION, get_identifier (buf),
3836 boolean_type_node, orig,
3837 boolean_false_node);
3838 free (buf);
3839 parm.trivial_dtor = false;
3841 else
3842 parm.trivial_dtor = true;
3845 return param_uses;
3848 /* Small helper for the repetitive task of adding a new field to the coro
3849 frame type. */
3851 static tree
3852 coro_make_frame_entry (tree *field_list, const char *name, tree fld_type,
3853 location_t loc)
3855 tree id = get_identifier (name);
3856 tree decl = build_decl (loc, FIELD_DECL, id, fld_type);
3857 DECL_CHAIN (decl) = *field_list;
3858 *field_list = decl;
3859 return id;
3862 /* For recording local variable usage. */
3864 struct local_vars_frame_data
3866 tree *field_list;
3867 hash_map<tree, local_var_info> *local_var_uses;
3868 unsigned int nest_depth, bind_indx;
3869 location_t loc;
3870 bool saw_capture;
3871 bool local_var_seen;
3874 /* A tree-walk callback that processes one bind expression noting local
3875 variables, and making a coroutine frame slot available for those that
3876 need it, so that they can be 'promoted' across suspension points. */
3878 static tree
3879 register_local_var_uses (tree *stmt, int *do_subtree, void *d)
3881 local_vars_frame_data *lvd = (local_vars_frame_data *) d;
3883 /* As we enter a bind expression - record the vars there and then recurse.
3884 As we exit drop the nest depth.
3885 The bind index is a growing count of how many bind indices we've seen.
3886 We build a space in the frame for each local var. */
3888 if (TREE_CODE (*stmt) == BIND_EXPR)
3890 tree lvar;
3891 for (lvar = BIND_EXPR_VARS (*stmt); lvar != NULL;
3892 lvar = DECL_CHAIN (lvar))
3894 bool existed;
3895 local_var_info &local_var
3896 = lvd->local_var_uses->get_or_insert (lvar, &existed);
3897 gcc_checking_assert (!existed);
3898 local_var.def_loc = DECL_SOURCE_LOCATION (lvar);
3899 tree lvtype = TREE_TYPE (lvar);
3900 local_var.frame_type = lvtype;
3901 local_var.field_idx = local_var.field_id = NULL_TREE;
3903 /* Make sure that we only present vars to the tests below. */
3904 if (TREE_CODE (lvar) == TYPE_DECL
3905 || TREE_CODE (lvar) == NAMESPACE_DECL)
3906 continue;
3908 /* We don't move static vars into the frame. */
3909 local_var.is_static = TREE_STATIC (lvar);
3910 if (local_var.is_static)
3911 continue;
3913 lvd->local_var_seen = true;
3914 /* If this var is a lambda capture proxy, we want to leave it alone,
3915 and later rewrite the DECL_VALUE_EXPR to indirect through the
3916 frame copy of the pointer to the lambda closure object. */
3917 local_var.is_lambda_capture = is_capture_proxy (lvar);
3918 if (local_var.is_lambda_capture)
3919 continue;
3921 /* If a variable has a value expression, then that's what needs
3922 to be processed. */
3923 local_var.has_value_expr_p = DECL_HAS_VALUE_EXPR_P (lvar);
3924 if (local_var.has_value_expr_p)
3925 continue;
3927 /* Make names depth+index unique, so that we can support nested
3928 scopes with identically named locals and still be able to
3929 identify them in the coroutine frame. */
3930 tree lvname = DECL_NAME (lvar);
3931 char *buf;
3933 /* The outermost bind scope contains the artificial variables that
3934 we inject to implement the coro state machine. We want to be able
3935 to inspect these in debugging. */
3936 if (lvname != NULL_TREE && lvd->nest_depth == 0)
3937 buf = xasprintf ("%s", IDENTIFIER_POINTER (lvname));
3938 else if (lvname != NULL_TREE)
3939 buf = xasprintf ("%s_%u_%u", IDENTIFIER_POINTER (lvname),
3940 lvd->nest_depth, lvd->bind_indx);
3941 else
3942 buf = xasprintf ("_D%u_%u_%u", DECL_UID (lvar), lvd->nest_depth,
3943 lvd->bind_indx);
3944 /* TODO: Figure out if we should build a local type that has any
3945 excess alignment or size from the original decl. */
3946 local_var.field_id
3947 = coro_make_frame_entry (lvd->field_list, buf, lvtype, lvd->loc);
3948 free (buf);
3949 /* We don't walk any of the local var sub-trees, they won't contain
3950 any bind exprs. */
3952 lvd->bind_indx++;
3953 lvd->nest_depth++;
3954 cp_walk_tree (&BIND_EXPR_BODY (*stmt), register_local_var_uses, d, NULL);
3955 *do_subtree = 0; /* We've done this. */
3956 lvd->nest_depth--;
3958 return NULL_TREE;
3961 /* Build, return FUNCTION_DECL node based on ORIG with a type FN_TYPE which has
3962 a single argument of type CORO_FRAME_PTR. Build the actor function if
3963 ACTOR_P is true, otherwise the destroy. */
3965 static tree
3966 coro_build_actor_or_destroy_function (tree orig, tree fn_type,
3967 tree coro_frame_ptr, bool actor_p)
3969 location_t loc = DECL_SOURCE_LOCATION (orig);
3970 tree fn
3971 = build_lang_decl (FUNCTION_DECL, copy_node (DECL_NAME (orig)), fn_type);
3973 /* Allow for locating the ramp (original) function from this one. */
3974 if (!to_ramp)
3975 to_ramp = hash_map<tree, tree>::create_ggc (10);
3976 to_ramp->put (fn, orig);
3978 DECL_CONTEXT (fn) = DECL_CONTEXT (orig);
3979 DECL_SOURCE_LOCATION (fn) = loc;
3980 DECL_ARTIFICIAL (fn) = true;
3981 DECL_INITIAL (fn) = error_mark_node;
3983 tree id = get_identifier ("frame_ptr");
3984 tree fp = build_lang_decl (PARM_DECL, id, coro_frame_ptr);
3985 DECL_CONTEXT (fp) = fn;
3986 DECL_ARG_TYPE (fp) = type_passed_as (coro_frame_ptr);
3987 DECL_ARGUMENTS (fn) = fp;
3989 /* Copy selected attributes from the original function. */
3990 TREE_USED (fn) = TREE_USED (orig);
3991 if (DECL_SECTION_NAME (orig))
3992 set_decl_section_name (fn, orig);
3993 /* Copy any alignment that the FE added. */
3994 if (DECL_ALIGN (orig))
3995 SET_DECL_ALIGN (fn, DECL_ALIGN (orig));
3996 /* Copy any alignment the user added. */
3997 DECL_USER_ALIGN (fn) = DECL_USER_ALIGN (orig);
3998 /* Apply attributes from the original fn. */
3999 DECL_ATTRIBUTES (fn) = copy_list (DECL_ATTRIBUTES (orig));
4001 /* A void return. */
4002 tree resdecl = build_decl (loc, RESULT_DECL, 0, void_type_node);
4003 DECL_CONTEXT (resdecl) = fn;
4004 DECL_ARTIFICIAL (resdecl) = 1;
4005 DECL_IGNORED_P (resdecl) = 1;
4006 DECL_RESULT (fn) = resdecl;
4008 /* This is a coroutine component. */
4009 DECL_COROUTINE_P (fn) = 1;
4011 /* Set up a means to find out if a decl is one of the helpers and, if so,
4012 which one. */
4013 if (coroutine_info *info = get_coroutine_info (orig))
4015 gcc_checking_assert ((actor_p && info->actor_decl == NULL_TREE)
4016 || info->destroy_decl == NULL_TREE);
4017 if (actor_p)
4018 info->actor_decl = fn;
4019 else
4020 info->destroy_decl = fn;
4022 return fn;
4025 /* Re-write the body as per [dcl.fct.def.coroutine] / 5. */
4027 static tree
4028 coro_rewrite_function_body (location_t fn_start, tree fnbody, tree orig,
4029 hash_map<tree, param_info> *param_uses,
4030 tree resume_fn_ptr_type,
4031 tree& resume_idx_var, tree& fs_label)
4033 /* This will be our new outer scope. */
4034 tree update_body = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
4035 tree top_block = make_node (BLOCK);
4036 BIND_EXPR_BLOCK (update_body) = top_block;
4037 BIND_EXPR_BODY (update_body) = push_stmt_list ();
4039 /* If the function has a top level bind expression, then connect that
4040 after first making sure we give it a new block. */
4041 tree first = expr_first (fnbody);
4042 if (first && TREE_CODE (first) == BIND_EXPR)
4044 tree block = BIND_EXPR_BLOCK (first);
4045 gcc_checking_assert (block);
4046 gcc_checking_assert (BLOCK_SUPERCONTEXT (block) == NULL_TREE);
4047 gcc_checking_assert (BLOCK_CHAIN (block) == NULL_TREE);
4048 /* Replace the top block to avoid issues with locations for args
4049 appearing to be in a non-existent place. */
4050 tree replace_blk = make_node (BLOCK);
4051 BLOCK_VARS (replace_blk) = BLOCK_VARS (block);
4052 BLOCK_SUBBLOCKS (replace_blk) = BLOCK_SUBBLOCKS (block);
4053 for (tree b = BLOCK_SUBBLOCKS (replace_blk); b; b = BLOCK_CHAIN (b))
4054 BLOCK_SUPERCONTEXT (b) = replace_blk;
4055 BIND_EXPR_BLOCK (first) = replace_blk;
4056 /* The top block has one child, so far, and we have now got a
4057 superblock. */
4058 BLOCK_SUPERCONTEXT (replace_blk) = top_block;
4059 BLOCK_SUBBLOCKS (top_block) = replace_blk;
4062 /* Wrap the function body in a try {} catch (...) {} block, if exceptions
4063 are enabled. */
4064 tree var_list = NULL_TREE;
4065 tree initial_await = build_init_or_final_await (fn_start, false);
4067 /* [stmt.return.coroutine] / 3
4068 If p.return_void() is a valid expression, flowing off the end of a
4069 coroutine is equivalent to a co_return with no operand; otherwise
4070 flowing off the end of a coroutine results in undefined behavior. */
4071 tree return_void
4072 = get_coroutine_return_void_expr (current_function_decl, fn_start, false);
4074 /* The pointer to the resume function. */
4075 tree resume_fn_ptr
4076 = coro_build_artificial_var (fn_start, coro_resume_fn_id,
4077 resume_fn_ptr_type, orig, NULL_TREE);
4078 DECL_CHAIN (resume_fn_ptr) = var_list;
4079 var_list = resume_fn_ptr;
4080 add_decl_expr (resume_fn_ptr);
4082 /* We will need to be able to set the resume function pointer to nullptr
4083 to signal that the coroutine is 'done'. */
4084 tree zero_resume
4085 = build1 (CONVERT_EXPR, resume_fn_ptr_type, integer_zero_node);
4087 /* The pointer to the destroy function. */
4088 tree var = coro_build_artificial_var (fn_start, coro_destroy_fn_id,
4089 resume_fn_ptr_type, orig, NULL_TREE);
4090 DECL_CHAIN (var) = var_list;
4091 var_list = var;
4092 add_decl_expr (var);
4094 /* The promise was created on demand when parsing we now link it into
4095 our scope. */
4096 tree promise = get_coroutine_promise_proxy (orig);
4097 DECL_CONTEXT (promise) = orig;
4098 DECL_SOURCE_LOCATION (promise) = fn_start;
4099 DECL_CHAIN (promise) = var_list;
4100 var_list = promise;
4101 add_decl_expr (promise);
4103 /* We need a handle to this coroutine, which is passed to every
4104 await_suspend(). This was created on demand when parsing we now link it
4105 into our scope. */
4106 var = get_coroutine_self_handle_proxy (orig);
4107 DECL_CONTEXT (var) = orig;
4108 DECL_SOURCE_LOCATION (var) = fn_start;
4109 DECL_CHAIN (var) = var_list;
4110 var_list = var;
4111 add_decl_expr (var);
4113 /* If we have function parms, then these will be copied to the coroutine
4114 frame. Create a local (proxy) variable for each parm, since the original
4115 parms will be out of scope once the ramp has finished. The proxy vars will
4116 get DECL_VALUE_EXPRs pointing to the frame copies, so that we can interact
4117 with them in the debugger. */
4118 if (param_uses)
4120 gcc_checking_assert (DECL_ARGUMENTS (orig));
4121 /* Add a local var for each parm. */
4122 for (tree arg = DECL_ARGUMENTS (orig); arg != NULL;
4123 arg = DECL_CHAIN (arg))
4125 param_info *parm_i = param_uses->get (arg);
4126 gcc_checking_assert (parm_i);
4127 parm_i->copy_var
4128 = build_lang_decl (VAR_DECL, parm_i->field_id, TREE_TYPE (arg));
4129 DECL_SOURCE_LOCATION (parm_i->copy_var) = DECL_SOURCE_LOCATION (arg);
4130 DECL_CONTEXT (parm_i->copy_var) = orig;
4131 DECL_ARTIFICIAL (parm_i->copy_var) = true;
4132 DECL_CHAIN (parm_i->copy_var) = var_list;
4133 var_list = parm_i->copy_var;
4134 add_decl_expr (parm_i->copy_var);
4137 /* Now replace all uses of the parms in the function body with the proxy
4138 vars. We want to this to apply to every instance of param's use, so
4139 don't include a 'visited' hash_set on the tree walk, however we will
4140 arrange to visit each containing expression only once. */
4141 hash_set<tree *> visited;
4142 param_frame_data param_data = {NULL, param_uses,
4143 &visited, fn_start, false};
4144 cp_walk_tree (&fnbody, rewrite_param_uses, &param_data, NULL);
4147 /* We create a resume index, this is initialized in the ramp. */
4148 resume_idx_var
4149 = coro_build_artificial_var (fn_start, coro_resume_index_id,
4150 short_unsigned_type_node, orig, NULL_TREE);
4151 DECL_CHAIN (resume_idx_var) = var_list;
4152 var_list = resume_idx_var;
4153 add_decl_expr (resume_idx_var);
4155 /* If the coroutine has a frame that needs to be freed, this will be set by
4156 the ramp. */
4157 var = coro_build_artificial_var (fn_start, coro_frame_needs_free_id,
4158 boolean_type_node, orig, NULL_TREE);
4159 DECL_CHAIN (var) = var_list;
4160 var_list = var;
4161 add_decl_expr (var);
4163 if (flag_exceptions)
4165 /* Build promise.unhandled_exception(); */
4166 tree ueh
4167 = coro_build_promise_expression (current_function_decl, promise,
4168 coro_unhandled_exception_identifier,
4169 fn_start, NULL, /*musthave=*/true);
4170 /* Create and initialize the initial-await-resume-called variable per
4171 [dcl.fct.def.coroutine] / 5.3. */
4172 tree i_a_r_c
4173 = coro_build_artificial_var (fn_start, coro_frame_i_a_r_c_id,
4174 boolean_type_node, orig,
4175 boolean_false_node);
4176 DECL_CHAIN (i_a_r_c) = var_list;
4177 var_list = i_a_r_c;
4178 add_decl_expr (i_a_r_c);
4179 /* Start the try-catch. */
4180 tree tcb = build_stmt (fn_start, TRY_BLOCK, NULL_TREE, NULL_TREE);
4181 add_stmt (tcb);
4182 TRY_STMTS (tcb) = push_stmt_list ();
4183 if (initial_await != error_mark_node)
4185 /* Build a compound expression that sets the
4186 initial-await-resume-called variable true and then calls the
4187 initial suspend expression await resume. */
4188 tree vec = TREE_OPERAND (initial_await, 3);
4189 tree aw_r = TREE_VEC_ELT (vec, 2);
4190 tree update = build2 (MODIFY_EXPR, boolean_type_node, i_a_r_c,
4191 boolean_true_node);
4192 aw_r = cp_build_compound_expr (update, aw_r, tf_warning_or_error);
4193 TREE_VEC_ELT (vec, 2) = aw_r;
4195 /* Add the initial await to the start of the user-authored function. */
4196 finish_expr_stmt (initial_await);
4197 /* Append the original function body. */
4198 add_stmt (fnbody);
4199 if (return_void)
4200 add_stmt (return_void);
4201 TRY_STMTS (tcb) = pop_stmt_list (TRY_STMTS (tcb));
4202 TRY_HANDLERS (tcb) = push_stmt_list ();
4203 /* Mimic what the parser does for the catch. */
4204 tree handler = begin_handler ();
4205 finish_handler_parms (NULL_TREE, handler); /* catch (...) */
4207 /* Get the initial await resume called value. */
4208 tree not_iarc_if = begin_if_stmt ();
4209 tree not_iarc = build1_loc (fn_start, TRUTH_NOT_EXPR,
4210 boolean_type_node, i_a_r_c);
4211 finish_if_stmt_cond (not_iarc, not_iarc_if);
4212 /* If the initial await resume called value is false, rethrow... */
4213 tree rethrow = build_throw (fn_start, NULL_TREE);
4214 suppress_warning (rethrow);
4215 finish_expr_stmt (rethrow);
4216 finish_then_clause (not_iarc_if);
4217 tree iarc_scope = IF_SCOPE (not_iarc_if);
4218 IF_SCOPE (not_iarc_if) = NULL;
4219 not_iarc_if = do_poplevel (iarc_scope);
4220 add_stmt (not_iarc_if);
4221 /* ... else call the promise unhandled exception method
4222 but first we set done = true and the resume index to 0.
4223 If the unhandled exception method returns, then we continue
4224 to the final await expression (which duplicates the clearing of
4225 the field). */
4226 tree r = build2 (MODIFY_EXPR, resume_fn_ptr_type, resume_fn_ptr,
4227 zero_resume);
4228 finish_expr_stmt (r);
4229 tree short_zero = build_int_cst (short_unsigned_type_node, 0);
4230 r = build2 (MODIFY_EXPR, short_unsigned_type_node, resume_idx_var,
4231 short_zero);
4232 finish_expr_stmt (r);
4233 finish_expr_stmt (ueh);
4234 finish_handler (handler);
4235 TRY_HANDLERS (tcb) = pop_stmt_list (TRY_HANDLERS (tcb));
4237 else
4239 if (pedantic)
4241 /* We still try to look for the promise method and warn if it's not
4242 present. */
4243 tree ueh_meth
4244 = lookup_promise_method (orig, coro_unhandled_exception_identifier,
4245 fn_start, /*musthave=*/false);
4246 if (!ueh_meth || ueh_meth == error_mark_node)
4247 warning_at (fn_start, 0, "no member named %qE in %qT",
4248 coro_unhandled_exception_identifier,
4249 get_coroutine_promise_type (orig));
4251 /* Else we don't check and don't care if the method is missing..
4252 just add the initial suspend, function and return. */
4253 finish_expr_stmt (initial_await);
4254 /* Append the original function body. */
4255 add_stmt (fnbody);
4256 if (return_void)
4257 add_stmt (return_void);
4260 /* co_return branches to the final_suspend label, so declare that now. */
4261 fs_label
4262 = create_named_label_with_ctx (fn_start, "final.suspend", NULL_TREE);
4263 add_stmt (build_stmt (fn_start, LABEL_EXPR, fs_label));
4265 /* Before entering the final suspend point, we signal that this point has
4266 been reached by setting the resume function pointer to zero (this is
4267 what the 'done()' builtin tests) as per the current ABI. */
4268 zero_resume = build2 (MODIFY_EXPR, resume_fn_ptr_type, resume_fn_ptr,
4269 zero_resume);
4270 finish_expr_stmt (zero_resume);
4271 finish_expr_stmt (build_init_or_final_await (fn_start, true));
4272 BIND_EXPR_BODY (update_body) = pop_stmt_list (BIND_EXPR_BODY (update_body));
4273 BIND_EXPR_VARS (update_body) = nreverse (var_list);
4274 BLOCK_VARS (top_block) = BIND_EXPR_VARS (update_body);
4276 return update_body;
4279 /* Here we:
4280 a) Check that the function and promise type are valid for a
4281 coroutine.
4282 b) Carry out the initial morph to create the skeleton of the
4283 coroutine ramp function and the rewritten body.
4285 Assumptions.
4287 1. We only hit this code once all dependencies are resolved.
4288 2. The function body will be either a bind expr or a statement list
4289 3. That cfun and current_function_decl are valid for the case we're
4290 expanding.
4291 4. 'input_location' will be of the final brace for the function.
4293 We do something like this:
4294 declare a dummy coro frame.
4295 struct _R_frame {
4296 using handle_type = coro::coroutine_handle<coro1::promise_type>;
4297 void (*_Coro_resume_fn)(_R_frame *);
4298 void (*_Coro_destroy_fn)(_R_frame *);
4299 coro1::promise_type _Coro_promise;
4300 bool _Coro_frame_needs_free; free the coro frame mem if set.
4301 bool _Coro_i_a_r_c; [dcl.fct.def.coroutine] / 5.3
4302 short _Coro_resume_index;
4303 handle_type _Coro_self_handle;
4304 parameter copies (were required).
4305 local variables saved (including awaitables)
4306 (maybe) trailing space.
4307 }; */
4309 bool
4310 morph_fn_to_coro (tree orig, tree *resumer, tree *destroyer)
4312 gcc_checking_assert (orig && TREE_CODE (orig) == FUNCTION_DECL);
4314 *resumer = error_mark_node;
4315 *destroyer = error_mark_node;
4316 if (!coro_function_valid_p (orig))
4318 /* For early errors, we do not want a diagnostic about the missing
4319 ramp return value, since the user cannot fix this - a 'return' is
4320 not allowed in a coroutine. */
4321 suppress_warning (orig, OPT_Wreturn_type);
4322 /* Discard the body, we can't process it further. */
4323 pop_stmt_list (DECL_SAVED_TREE (orig));
4324 DECL_SAVED_TREE (orig) = push_stmt_list ();
4325 return false;
4328 /* We can't validly get here with an empty statement list, since there's no
4329 way for the FE to decide it's a coroutine in the absence of any code. */
4330 tree fnbody = pop_stmt_list (DECL_SAVED_TREE (orig));
4331 gcc_checking_assert (fnbody != NULL_TREE);
4333 /* We don't have the locus of the opening brace - it's filled in later (and
4334 there doesn't really seem to be any easy way to get at it).
4335 The closing brace is assumed to be input_location. */
4336 location_t fn_start = DECL_SOURCE_LOCATION (orig);
4337 gcc_rich_location fn_start_loc (fn_start);
4339 /* Initial processing of the function-body.
4340 If we have no expressions or just an error then punt. */
4341 tree body_start = expr_first (fnbody);
4342 if (body_start == NULL_TREE || body_start == error_mark_node)
4344 DECL_SAVED_TREE (orig) = push_stmt_list ();
4345 append_to_statement_list (fnbody, &DECL_SAVED_TREE (orig));
4346 /* Suppress warnings about the missing return value. */
4347 suppress_warning (orig, OPT_Wreturn_type);
4348 return false;
4351 /* So, we've tied off the original user-authored body in fn_body.
4353 Start the replacement synthesized ramp body as newbody.
4354 If we encounter a fatal error we might return a now-empty body.
4356 Note, the returned ramp body is not 'popped', to be compatible with
4357 the way that decl.c handles regular functions, the scope pop is done
4358 in the caller. */
4360 tree newbody = push_stmt_list ();
4361 DECL_SAVED_TREE (orig) = newbody;
4363 /* If our original body is noexcept, then that's what we apply to our
4364 generated ramp, transfer any MUST_NOT_THOW_EXPR to that. */
4365 bool is_noexcept = TREE_CODE (body_start) == MUST_NOT_THROW_EXPR;
4366 if (is_noexcept)
4368 /* The function body we will continue with is the single operand to
4369 the must-not-throw. */
4370 fnbody = TREE_OPERAND (body_start, 0);
4371 /* Transfer the must-not-throw to the ramp body. */
4372 add_stmt (body_start);
4373 /* Re-start the ramp as must-not-throw. */
4374 TREE_OPERAND (body_start, 0) = push_stmt_list ();
4377 /* If the original function has a return value with a non-trivial DTOR
4378 and the body contains a var with a DTOR that might throw, the decl is
4379 marked "throwing_cleanup".
4380 We do not [in the ramp, which is synthesised here], use any body var
4381 types with DTORs that might throw.
4382 The original body is transformed into the actor function which only
4383 contains void returns, and is also wrapped in a try-catch block.
4384 So (a) the 'throwing_cleanup' is not correct for the ramp and (b) we do
4385 not need to transfer it to the actor which only contains void returns. */
4386 cp_function_chain->throwing_cleanup = false;
4388 /* Create the coro frame type, as far as it can be known at this stage.
4389 1. Types we already know. */
4391 tree fn_return_type = TREE_TYPE (TREE_TYPE (orig));
4392 tree handle_type = get_coroutine_handle_type (orig);
4393 tree promise_type = get_coroutine_promise_type (orig);
4395 /* 2. Types we need to define or look up. */
4397 tree fr_name = get_fn_local_identifier (orig, "Frame");
4398 tree coro_frame_type = xref_tag (record_type, fr_name);
4399 DECL_CONTEXT (TYPE_NAME (coro_frame_type)) = current_scope ();
4400 tree coro_frame_ptr = build_pointer_type (coro_frame_type);
4401 tree act_des_fn_type
4402 = build_function_type_list (void_type_node, coro_frame_ptr, NULL_TREE);
4403 tree act_des_fn_ptr = build_pointer_type (act_des_fn_type);
4405 /* Declare the actor and destroyer function. */
4406 tree actor = coro_build_actor_or_destroy_function (orig, act_des_fn_type,
4407 coro_frame_ptr, true);
4408 tree destroy = coro_build_actor_or_destroy_function (orig, act_des_fn_type,
4409 coro_frame_ptr, false);
4411 /* Construct the wrapped function body; we will analyze this to determine
4412 the requirements for the coroutine frame. */
4414 tree resume_idx_var = NULL_TREE;
4415 tree fs_label = NULL_TREE;
4416 hash_map<tree, param_info> *param_uses = analyze_fn_parms (orig);
4418 fnbody = coro_rewrite_function_body (fn_start, fnbody, orig, param_uses,
4419 act_des_fn_ptr,
4420 resume_idx_var, fs_label);
4421 /* Build our dummy coro frame layout. */
4422 coro_frame_type = begin_class_definition (coro_frame_type);
4424 /* The fields for the coro frame. */
4425 tree field_list = NULL_TREE;
4427 /* We need to know, and inspect, each suspend point in the function
4428 in several places. It's convenient to place this map out of line
4429 since it's used from tree walk callbacks. */
4430 suspend_points = new hash_map<tree, suspend_point_info>;
4432 /* Now insert the data for any body await points, at this time we also need
4433 to promote any temporaries that are captured by reference (to regular
4434 vars) they will get added to the coro frame along with other locals. */
4435 susp_frame_data body_aw_points
4436 = {&field_list, handle_type, fs_label, NULL, NULL, 0, 0,
4437 hash_set<tree> (), NULL, NULL, 0, false, false, false};
4438 body_aw_points.block_stack = make_tree_vector ();
4439 body_aw_points.bind_stack = make_tree_vector ();
4440 body_aw_points.to_replace = make_tree_vector ();
4441 cp_walk_tree (&fnbody, await_statement_walker, &body_aw_points, NULL);
4443 /* 4. Now make space for local vars, this is conservative again, and we
4444 would expect to delete unused entries later. */
4445 hash_map<tree, local_var_info> local_var_uses;
4446 local_vars_frame_data local_vars_data
4447 = {&field_list, &local_var_uses, 0, 0, fn_start, false, false};
4448 cp_walk_tree (&fnbody, register_local_var_uses, &local_vars_data, NULL);
4450 /* Tie off the struct for now, so that we can build offsets to the
4451 known entries. */
4452 TYPE_FIELDS (coro_frame_type) = field_list;
4453 TYPE_BINFO (coro_frame_type) = make_tree_binfo (0);
4454 BINFO_OFFSET (TYPE_BINFO (coro_frame_type)) = size_zero_node;
4455 BINFO_TYPE (TYPE_BINFO (coro_frame_type)) = coro_frame_type;
4457 coro_frame_type = finish_struct (coro_frame_type, NULL_TREE);
4459 /* Ramp: */
4460 /* Now build the ramp function pieces. */
4461 tree ramp_bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
4462 add_stmt (ramp_bind);
4463 tree ramp_body = push_stmt_list ();
4465 tree zeroinit = build1_loc (fn_start, CONVERT_EXPR,
4466 coro_frame_ptr, integer_zero_node);
4467 tree coro_fp = coro_build_artificial_var (fn_start, "_Coro_frameptr",
4468 coro_frame_ptr, orig, zeroinit);
4469 tree varlist = coro_fp;
4471 /* To signal that we need to cleanup copied function args. */
4472 if (flag_exceptions && DECL_ARGUMENTS (orig))
4473 for (tree arg = DECL_ARGUMENTS (orig); arg != NULL;
4474 arg = DECL_CHAIN (arg))
4476 param_info *parm_i = param_uses->get (arg);
4477 gcc_checking_assert (parm_i);
4478 if (parm_i->trivial_dtor)
4479 continue;
4480 DECL_CHAIN (parm_i->guard_var) = varlist;
4481 varlist = parm_i->guard_var;
4484 /* Signal that we need to clean up the promise object on exception. */
4485 tree coro_promise_live
4486 = coro_build_artificial_var (fn_start, "_Coro_promise_live",
4487 boolean_type_node, orig, boolean_false_node);
4488 DECL_CHAIN (coro_promise_live) = varlist;
4489 varlist = coro_promise_live;
4491 /* When the get-return-object is in the RETURN slot, we need to arrange for
4492 cleanup on exception. */
4493 tree coro_gro_live
4494 = coro_build_artificial_var (fn_start, "_Coro_gro_live",
4495 boolean_type_node, orig, boolean_false_node);
4497 DECL_CHAIN (coro_gro_live) = varlist;
4498 varlist = coro_gro_live;
4500 /* Collected the scope vars we need ... only one for now. */
4501 BIND_EXPR_VARS (ramp_bind) = nreverse (varlist);
4503 /* We're now going to create a new top level scope block for the ramp
4504 function. */
4505 tree top_block = make_node (BLOCK);
4507 BIND_EXPR_BLOCK (ramp_bind) = top_block;
4508 BLOCK_VARS (top_block) = BIND_EXPR_VARS (ramp_bind);
4509 BLOCK_SUBBLOCKS (top_block) = NULL_TREE;
4511 /* The decl_expr for the coro frame pointer, initialize to zero so that we
4512 can pass it to the IFN_CO_FRAME (since there's no way to pass a type,
4513 directly apparently). This avoids a "used uninitialized" warning. */
4515 add_decl_expr (coro_fp);
4516 if (flag_exceptions && DECL_ARGUMENTS (orig))
4517 for (tree arg = DECL_ARGUMENTS (orig); arg != NULL;
4518 arg = DECL_CHAIN (arg))
4520 param_info *parm_i = param_uses->get (arg);
4521 if (parm_i->trivial_dtor)
4522 continue;
4523 add_decl_expr (parm_i->guard_var);;
4525 add_decl_expr (coro_promise_live);
4526 add_decl_expr (coro_gro_live);
4528 /* The CO_FRAME internal function is a mechanism to allow the middle end
4529 to adjust the allocation in response to optimizations. We provide the
4530 current conservative estimate of the frame size (as per the current)
4531 computed layout. */
4532 tree frame_size = TYPE_SIZE_UNIT (coro_frame_type);
4533 tree resizeable
4534 = build_call_expr_internal_loc (fn_start, IFN_CO_FRAME, size_type_node, 2,
4535 frame_size, coro_fp);
4537 /* [dcl.fct.def.coroutine] / 10 (part1)
4538 The unqualified-id get_return_object_on_allocation_failure is looked up
4539 in the scope of the promise type by class member access lookup. */
4541 /* We don't require this, so coro_build_promise_expression can return NULL,
4542 but, if the lookup succeeds, then the function must be usable. */
4543 tree dummy_promise = build_dummy_object (get_coroutine_promise_type (orig));
4544 tree grooaf
4545 = coro_build_promise_expression (orig, dummy_promise,
4546 coro_gro_on_allocation_fail_identifier,
4547 fn_start, NULL, /*musthave=*/false);
4549 /* however, should that fail, returning an error, the later stages can't
4550 handle the erroneous expression, so we reset the call as if it was
4551 absent. */
4552 if (grooaf == error_mark_node)
4553 grooaf = NULL_TREE;
4555 /* Allocate the frame, this has several possibilities:
4556 [dcl.fct.def.coroutine] / 9 (part 1)
4557 The allocation function’s name is looked up in the scope of the promise
4558 type. It's not a failure for it to be absent see part 4, below. */
4560 tree nwname = ovl_op_identifier (false, NEW_EXPR);
4561 tree new_fn = NULL_TREE;
4563 if (TYPE_HAS_NEW_OPERATOR (promise_type))
4565 tree fns = lookup_promise_method (orig, nwname, fn_start,
4566 /*musthave=*/true);
4567 /* [dcl.fct.def.coroutine] / 9 (part 2)
4568 If the lookup finds an allocation function in the scope of the promise
4569 type, overload resolution is performed on a function call created by
4570 assembling an argument list. The first argument is the amount of space
4571 requested, and has type std::size_t. The succeeding arguments are
4572 those of the original function. */
4573 vec<tree, va_gc> *args = make_tree_vector ();
4574 vec_safe_push (args, resizeable); /* Space needed. */
4576 for (tree arg = DECL_ARGUMENTS (orig); arg != NULL;
4577 arg = DECL_CHAIN (arg))
4579 param_info *parm_i = param_uses->get (arg);
4580 gcc_checking_assert (parm_i);
4581 if (parm_i->this_ptr || parm_i->lambda_cobj)
4583 /* We pass a reference to *this to the allocator lookup. */
4584 tree tt = TREE_TYPE (TREE_TYPE (arg));
4585 tree this_ref = build1 (INDIRECT_REF, tt, arg);
4586 tt = cp_build_reference_type (tt, false);
4587 this_ref = convert_to_reference (tt, this_ref, CONV_STATIC,
4588 LOOKUP_NORMAL , NULL_TREE,
4589 tf_warning_or_error);
4590 vec_safe_push (args, this_ref);
4592 else
4593 vec_safe_push (args, arg);
4596 /* Note the function selected; we test to see if it's NOTHROW. */
4597 tree func;
4598 /* Failure is not an error for this attempt. */
4599 new_fn = build_new_method_call (dummy_promise, fns, &args, NULL,
4600 LOOKUP_NORMAL, &func, tf_none);
4601 release_tree_vector (args);
4603 if (new_fn == error_mark_node)
4605 /* [dcl.fct.def.coroutine] / 9 (part 3)
4606 If no viable function is found, overload resolution is performed
4607 again on a function call created by passing just the amount of
4608 space required as an argument of type std::size_t. */
4609 args = make_tree_vector_single (resizeable); /* Space needed. */
4610 new_fn = build_new_method_call (dummy_promise, fns, &args,
4611 NULL_TREE, LOOKUP_NORMAL, &func,
4612 tf_none);
4613 release_tree_vector (args);
4616 /* However, if the promise provides an operator new, then one of these
4617 two options must be available. */
4618 if (new_fn == error_mark_node)
4620 error_at (fn_start, "%qE is provided by %qT but is not usable with"
4621 " the function signature %qD", nwname, promise_type, orig);
4622 new_fn = error_mark_node;
4624 else if (grooaf && !TYPE_NOTHROW_P (TREE_TYPE (func)))
4625 error_at (fn_start, "%qE is provided by %qT but %qE is not marked"
4626 " %<throw()%> or %<noexcept%>", grooaf, promise_type, nwname);
4627 else if (!grooaf && TYPE_NOTHROW_P (TREE_TYPE (func)))
4628 warning_at (fn_start, 0, "%qE is marked %<throw()%> or %<noexcept%> but"
4629 " no usable %<get_return_object_on_allocation_failure%>"
4630 " is provided by %qT", nwname, promise_type);
4632 else /* No operator new in the promise. */
4634 /* [dcl.fct.def.coroutine] / 9 (part 4)
4635 If this lookup fails, the allocation function’s name is looked up in
4636 the global scope. */
4638 vec<tree, va_gc> *args;
4639 /* build_operator_new_call () will insert size needed as element 0 of
4640 this, and we might need to append the std::nothrow constant. */
4641 vec_alloc (args, 2);
4642 if (grooaf)
4644 /* [dcl.fct.def.coroutine] / 10 (part 2)
4645 If any declarations (of the get return on allocation fail) are
4646 found, then the result of a call to an allocation function used
4647 to obtain storage for the coroutine state is assumed to return
4648 nullptr if it fails to obtain storage and, if a global allocation
4649 function is selected, the ::operator new(size_t, nothrow_t) form
4650 is used. The allocation function used in this case shall have a
4651 non-throwing noexcept-specification. So we need std::nothrow. */
4652 tree std_nt = lookup_qualified_name (std_node,
4653 get_identifier ("nothrow"),
4654 LOOK_want::NORMAL,
4655 /*complain=*/true);
4656 if (!std_nt || std_nt == error_mark_node)
4657 error_at (fn_start, "%qE is provided by %qT but %<std::nothrow%> "
4658 "cannot be found", grooaf, promise_type);
4659 vec_safe_push (args, std_nt);
4662 /* If we get to this point, we must succeed in looking up the global
4663 operator new for the params provided. Extract a simplified version
4664 of the machinery from build_operator_new_call. This can update the
4665 frame size. */
4666 tree cookie = NULL;
4667 new_fn = build_operator_new_call (nwname, &args, &frame_size, &cookie,
4668 /*align_arg=*/NULL,
4669 /*size_check=*/NULL, /*fn=*/NULL,
4670 tf_warning_or_error);
4671 resizeable = build_call_expr_internal_loc
4672 (fn_start, IFN_CO_FRAME, size_type_node, 2, frame_size, coro_fp);
4673 /* If the operator call fails for some reason, then don't try to
4674 amend it. */
4675 if (new_fn != error_mark_node)
4676 CALL_EXPR_ARG (new_fn, 0) = resizeable;
4678 release_tree_vector (args);
4681 tree allocated = build1 (CONVERT_EXPR, coro_frame_ptr, new_fn);
4682 tree r = build2 (INIT_EXPR, TREE_TYPE (coro_fp), coro_fp, allocated);
4683 r = coro_build_cvt_void_expr_stmt (r, fn_start);
4684 add_stmt (r);
4686 /* If the user provided a method to return an object on alloc fail, then
4687 check the returned pointer and call the func if it's null.
4688 Otherwise, no check, and we fail for noexcept/fno-exceptions cases. */
4690 if (grooaf)
4692 /* [dcl.fct.def.coroutine] / 10 (part 3)
4693 If the allocation function returns nullptr,the coroutine returns
4694 control to the caller of the coroutine and the return value is
4695 obtained by a call to T::get_return_object_on_allocation_failure(),
4696 where T is the promise type. */
4698 gcc_checking_assert (same_type_p (fn_return_type, TREE_TYPE (grooaf)));
4699 tree if_stmt = begin_if_stmt ();
4700 tree cond = build1 (CONVERT_EXPR, coro_frame_ptr, integer_zero_node);
4701 cond = build2 (EQ_EXPR, boolean_type_node, coro_fp, cond);
4702 finish_if_stmt_cond (cond, if_stmt);
4703 if (VOID_TYPE_P (fn_return_type))
4705 /* Execute the get-return-object-on-alloc-fail call... */
4706 finish_expr_stmt (grooaf);
4707 /* ... but discard the result, since we return void. */
4708 finish_return_stmt (NULL_TREE);
4710 else
4712 /* Get the fallback return object. */
4713 r = build_cplus_new (fn_return_type, grooaf, tf_warning_or_error);
4714 finish_return_stmt (r);
4716 finish_then_clause (if_stmt);
4717 finish_if_stmt (if_stmt);
4720 /* Up to now any exception thrown will propagate directly to the caller.
4721 This is OK since the only source of such exceptions would be in allocation
4722 of the coroutine frame, and therefore the ramp will not have initialized
4723 any further state. From here, we will track state that needs explicit
4724 destruction in the case that promise or g.r.o setup fails or an exception
4725 is thrown from the initial suspend expression. */
4726 tree ramp_cleanup = NULL_TREE;
4727 if (flag_exceptions)
4729 ramp_cleanup = build_stmt (fn_start, TRY_BLOCK, NULL, NULL);
4730 add_stmt (ramp_cleanup);
4731 TRY_STMTS (ramp_cleanup) = push_stmt_list ();
4734 /* deref the frame pointer, to use in member access code. */
4735 tree deref_fp = build_x_arrow (fn_start, coro_fp, tf_warning_or_error);
4737 /* For now, once allocation has succeeded we always assume that this needs
4738 destruction, there's no impl. for frame allocation elision. */
4739 tree fnf_m = lookup_member (coro_frame_type, coro_frame_needs_free_id,
4740 1, 0,tf_warning_or_error);
4741 tree fnf_x = build_class_member_access_expr (deref_fp, fnf_m, NULL_TREE,
4742 false, tf_warning_or_error);
4743 r = build2 (INIT_EXPR, boolean_type_node, fnf_x, boolean_true_node);
4744 r = coro_build_cvt_void_expr_stmt (r, fn_start);
4745 add_stmt (r);
4747 /* Put the resumer and destroyer functions in. */
4749 tree actor_addr = build1 (ADDR_EXPR, act_des_fn_ptr, actor);
4750 tree resume_m
4751 = lookup_member (coro_frame_type, coro_resume_fn_id,
4752 /*protect=*/1, /*want_type=*/0, tf_warning_or_error);
4753 tree resume_x = build_class_member_access_expr (deref_fp, resume_m, NULL_TREE,
4754 false, tf_warning_or_error);
4755 r = build2_loc (fn_start, INIT_EXPR, act_des_fn_ptr, resume_x, actor_addr);
4756 finish_expr_stmt (r);
4758 tree destroy_addr = build1 (ADDR_EXPR, act_des_fn_ptr, destroy);
4759 tree destroy_m
4760 = lookup_member (coro_frame_type, coro_destroy_fn_id,
4761 /*protect=*/1, /*want_type=*/0, tf_warning_or_error);
4762 tree destroy_x
4763 = build_class_member_access_expr (deref_fp, destroy_m, NULL_TREE, false,
4764 tf_warning_or_error);
4765 r = build2_loc (fn_start, INIT_EXPR, act_des_fn_ptr, destroy_x, destroy_addr);
4766 finish_expr_stmt (r);
4768 /* [dcl.fct.def.coroutine] /13
4769 When a coroutine is invoked, a copy is created for each coroutine
4770 parameter. Each such copy is an object with automatic storage duration
4771 that is direct-initialized from an lvalue referring to the corresponding
4772 parameter if the parameter is an lvalue reference, and from an xvalue
4773 referring to it otherwise. A reference to a parameter in the function-
4774 body of the coroutine and in the call to the coroutine promise
4775 constructor is replaced by a reference to its copy. */
4777 vec<tree, va_gc> *promise_args = NULL; /* So that we can adjust refs. */
4779 /* The initialization and destruction of each parameter copy occurs in the
4780 context of the called coroutine. Initializations of parameter copies are
4781 sequenced before the call to the coroutine promise constructor and
4782 indeterminately sequenced with respect to each other. The lifetime of
4783 parameter copies ends immediately after the lifetime of the coroutine
4784 promise object ends. */
4786 vec<tree, va_gc> *param_dtor_list = NULL;
4788 if (DECL_ARGUMENTS (orig))
4790 promise_args = make_tree_vector ();
4791 for (tree arg = DECL_ARGUMENTS (orig); arg != NULL;
4792 arg = DECL_CHAIN (arg))
4794 bool existed;
4795 param_info &parm = param_uses->get_or_insert (arg, &existed);
4797 tree fld_ref = lookup_member (coro_frame_type, parm.field_id,
4798 /*protect=*/1, /*want_type=*/0,
4799 tf_warning_or_error);
4800 tree fld_idx
4801 = build_class_member_access_expr (deref_fp, fld_ref, NULL_TREE,
4802 false, tf_warning_or_error);
4804 /* Add this to the promise CTOR arguments list, accounting for
4805 refs and special handling for method this ptr. */
4806 if (parm.this_ptr || parm.lambda_cobj)
4808 /* We pass a reference to *this to the param preview. */
4809 tree tt = TREE_TYPE (arg);
4810 gcc_checking_assert (POINTER_TYPE_P (tt));
4811 tree ct = TREE_TYPE (tt);
4812 tree this_ref = build1 (INDIRECT_REF, ct, arg);
4813 tree rt = cp_build_reference_type (ct, false);
4814 this_ref = convert_to_reference (rt, this_ref, CONV_STATIC,
4815 LOOKUP_NORMAL, NULL_TREE,
4816 tf_warning_or_error);
4817 vec_safe_push (promise_args, this_ref);
4819 else if (parm.rv_ref)
4820 vec_safe_push (promise_args, move (fld_idx));
4821 else
4822 vec_safe_push (promise_args, fld_idx);
4824 if (parm.rv_ref || parm.pt_ref)
4825 /* Initialise the frame reference field directly. */
4826 r = cp_build_modify_expr (fn_start, TREE_OPERAND (fld_idx, 0),
4827 INIT_EXPR, arg, tf_warning_or_error);
4828 else
4830 r = forward_parm (arg);
4831 r = cp_build_modify_expr (fn_start, fld_idx, INIT_EXPR, r,
4832 tf_warning_or_error);
4834 finish_expr_stmt (r);
4835 if (!parm.trivial_dtor)
4837 if (param_dtor_list == NULL)
4838 param_dtor_list = make_tree_vector ();
4839 vec_safe_push (param_dtor_list, parm.field_id);
4840 /* Cleanup this frame copy on exception. */
4841 parm.fr_copy_dtor
4842 = build_special_member_call (fld_idx, complete_dtor_identifier,
4843 NULL, parm.frame_type,
4844 LOOKUP_NORMAL,
4845 tf_warning_or_error);
4846 if (flag_exceptions)
4848 /* This var is now live. */
4849 r = build_modify_expr (fn_start, parm.guard_var,
4850 boolean_type_node, INIT_EXPR, fn_start,
4851 boolean_true_node, boolean_type_node);
4852 finish_expr_stmt (r);
4858 /* Set up the promise. */
4859 tree promise_m
4860 = lookup_member (coro_frame_type, coro_promise_id,
4861 /*protect=*/1, /*want_type=*/0, tf_warning_or_error);
4863 tree p = build_class_member_access_expr (deref_fp, promise_m, NULL_TREE,
4864 false, tf_warning_or_error);
4866 tree promise_dtor = NULL_TREE;
4867 if (type_build_ctor_call (promise_type))
4869 /* Do a placement new constructor for the promise type (we never call
4870 the new operator, just the constructor on the object in place in the
4871 frame).
4873 First try to find a constructor with the same parameter list as the
4874 original function (if it has params), failing that find a constructor
4875 with no parameter list. */
4877 if (DECL_ARGUMENTS (orig))
4879 r = build_special_member_call (p, complete_ctor_identifier,
4880 &promise_args, promise_type,
4881 LOOKUP_NORMAL, tf_none);
4882 release_tree_vector (promise_args);
4884 else
4885 r = NULL_TREE;
4887 if (r == NULL_TREE || r == error_mark_node)
4888 r = build_special_member_call (p, complete_ctor_identifier, NULL,
4889 promise_type, LOOKUP_NORMAL,
4890 tf_warning_or_error);
4892 r = coro_build_cvt_void_expr_stmt (r, fn_start);
4893 finish_expr_stmt (r);
4895 r = build_modify_expr (fn_start, coro_promise_live, boolean_type_node,
4896 INIT_EXPR, fn_start, boolean_true_node,
4897 boolean_type_node);
4898 finish_expr_stmt (r);
4900 promise_dtor
4901 = build_special_member_call (p, complete_dtor_identifier,
4902 NULL, promise_type, LOOKUP_NORMAL,
4903 tf_warning_or_error);
4906 /* Set up a new bind context for the GRO. */
4907 tree gro_context_bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
4908 /* Make and connect the scope blocks. */
4909 tree gro_block = make_node (BLOCK);
4910 BLOCK_SUPERCONTEXT (gro_block) = top_block;
4911 BLOCK_SUBBLOCKS (top_block) = gro_block;
4912 BIND_EXPR_BLOCK (gro_context_bind) = gro_block;
4913 add_stmt (gro_context_bind);
4915 tree get_ro
4916 = coro_build_promise_expression (orig, p,
4917 coro_get_return_object_identifier,
4918 fn_start, NULL, /*musthave=*/true);
4919 /* Without a return object we haven't got much clue what's going on. */
4920 if (get_ro == error_mark_node)
4922 BIND_EXPR_BODY (ramp_bind) = pop_stmt_list (ramp_body);
4923 DECL_SAVED_TREE (orig) = newbody;
4924 /* Suppress warnings about the missing return value. */
4925 suppress_warning (orig, OPT_Wreturn_type);
4926 return false;
4929 tree gro_context_body = push_stmt_list ();
4930 tree gro_type = TREE_TYPE (get_ro);
4931 bool gro_is_void_p = VOID_TYPE_P (gro_type);
4933 tree gro = NULL_TREE;
4934 tree gro_bind_vars = NULL_TREE;
4935 /* Used for return objects in the RESULT slot. */
4936 tree gro_ret_dtor = NULL_TREE;
4937 tree gro_cleanup_stmt = NULL_TREE;
4938 /* We have to sequence the call to get_return_object before initial
4939 suspend. */
4940 if (gro_is_void_p)
4941 r = get_ro;
4942 else if (same_type_p (gro_type, fn_return_type))
4944 /* [dcl.fct.def.coroutine] / 7
4945 The expression promise.get_return_object() is used to initialize the
4946 glvalue result or... (see below)
4947 Construct the return result directly. */
4948 if (type_build_ctor_call (gro_type))
4950 vec<tree, va_gc> *arg = make_tree_vector_single (get_ro);
4951 r = build_special_member_call (DECL_RESULT (orig),
4952 complete_ctor_identifier,
4953 &arg, gro_type, LOOKUP_NORMAL,
4954 tf_warning_or_error);
4955 release_tree_vector (arg);
4957 else
4958 r = build2_loc (fn_start, INIT_EXPR, gro_type,
4959 DECL_RESULT (orig), get_ro);
4961 if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (gro_type))
4962 /* If some part of the initalization code (prior to the await_resume
4963 of the initial suspend expression), then we need to clean up the
4964 return value. */
4965 gro_ret_dtor
4966 = build_special_member_call (DECL_RESULT (orig),
4967 complete_dtor_identifier, NULL,
4968 gro_type, LOOKUP_NORMAL,
4969 tf_warning_or_error);
4971 else
4973 /* ... or ... Construct an object that will be used as the single
4974 param to the CTOR for the return object. */
4975 gro = coro_build_artificial_var (fn_start, "_Coro_gro", gro_type, orig,
4976 NULL_TREE);
4977 add_decl_expr (gro);
4978 gro_bind_vars = gro;
4979 r = cp_build_modify_expr (input_location, gro, INIT_EXPR, get_ro,
4980 tf_warning_or_error);
4981 /* The constructed object might require a cleanup. */
4982 if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (gro_type))
4984 gro_cleanup_stmt
4985 = build_special_member_call (gro, complete_dtor_identifier,
4986 NULL, gro_type, LOOKUP_NORMAL,
4987 tf_warning_or_error);
4988 gro_cleanup_stmt = build_stmt (input_location, CLEANUP_STMT, NULL,
4989 gro_cleanup_stmt, gro);
4992 finish_expr_stmt (r);
4994 if (gro_cleanup_stmt && gro_cleanup_stmt != error_mark_node)
4995 CLEANUP_BODY (gro_cleanup_stmt) = push_stmt_list ();
4997 /* If we have a live g.r.o in the return slot, then signal this for exception
4998 cleanup. */
4999 if (gro_ret_dtor)
5001 r = build_modify_expr (fn_start, coro_gro_live, boolean_type_node,
5002 INIT_EXPR, fn_start, boolean_true_node,
5003 boolean_type_node);
5004 finish_expr_stmt (r);
5006 /* Initialize the resume_idx_var to 0, meaning "not started". */
5007 tree resume_idx_m
5008 = lookup_member (coro_frame_type, coro_resume_index_id,
5009 /*protect=*/1, /*want_type=*/0, tf_warning_or_error);
5010 tree resume_idx
5011 = build_class_member_access_expr (deref_fp, resume_idx_m, NULL_TREE, false,
5012 tf_warning_or_error);
5013 r = build_int_cst (short_unsigned_type_node, 0);
5014 r = build2_loc (fn_start, INIT_EXPR, short_unsigned_type_node, resume_idx, r);
5015 r = coro_build_cvt_void_expr_stmt (r, fn_start);
5016 add_stmt (r);
5018 /* So .. call the actor .. */
5019 r = build_call_expr_loc (fn_start, actor, 1, coro_fp);
5020 r = maybe_cleanup_point_expr_void (r);
5021 add_stmt (r);
5023 /* Switch to using 'input_location' as the loc, since we're now more
5024 logically doing things related to the end of the function. */
5026 /* The ramp is done, we just need the return value.
5027 [dcl.fct.def.coroutine] / 7
5028 The expression promise.get_return_object() is used to initialize the
5029 glvalue result or prvalue result object of a call to a coroutine.
5031 If the 'get return object' is non-void, then we built it before the
5032 promise was constructed. We now supply a reference to that var,
5033 either as the return value (if it's the same type) or to the CTOR
5034 for an object of the return type. */
5036 if (same_type_p (gro_type, fn_return_type))
5037 r = gro_is_void_p ? NULL_TREE : DECL_RESULT (orig);
5038 else if (!gro_is_void_p)
5039 /* check_return_expr will automatically return gro as an rvalue via
5040 treat_lvalue_as_rvalue_p. */
5041 r = gro;
5042 else if (CLASS_TYPE_P (fn_return_type))
5044 /* For class type return objects, we can attempt to construct,
5045 even if the gro is void. ??? Citation ??? c++/100476 */
5046 r = build_special_member_call (NULL_TREE,
5047 complete_ctor_identifier, NULL,
5048 fn_return_type, LOOKUP_NORMAL,
5049 tf_warning_or_error);
5050 r = build_cplus_new (fn_return_type, r, tf_warning_or_error);
5052 else
5054 /* We can't initialize a non-class return value from void. */
5055 error_at (input_location, "cannot initialize a return object of type"
5056 " %qT with an rvalue of type %<void%>", fn_return_type);
5057 r = error_mark_node;
5060 finish_return_stmt (r);
5062 if (gro_cleanup_stmt)
5064 CLEANUP_BODY (gro_cleanup_stmt)
5065 = pop_stmt_list (CLEANUP_BODY (gro_cleanup_stmt));
5066 add_stmt (gro_cleanup_stmt);
5069 /* Finish up the ramp function. */
5070 BIND_EXPR_VARS (gro_context_bind) = gro_bind_vars;
5071 BIND_EXPR_BODY (gro_context_bind) = pop_stmt_list (gro_context_body);
5072 TREE_SIDE_EFFECTS (gro_context_bind) = true;
5074 if (flag_exceptions)
5076 TRY_HANDLERS (ramp_cleanup) = push_stmt_list ();
5077 tree handler = begin_handler ();
5078 finish_handler_parms (NULL_TREE, handler); /* catch (...) */
5080 /* If we have a live G.R.O in the return slot, then run its DTOR.
5081 When the return object is constructed from a separate g.r.o, this is
5082 already handled by its regular cleanup. */
5083 if (gro_ret_dtor && gro_ret_dtor != error_mark_node)
5085 tree gro_d_if = begin_if_stmt ();
5086 finish_if_stmt_cond (coro_gro_live, gro_d_if);
5087 finish_expr_stmt (gro_ret_dtor);
5088 finish_then_clause (gro_d_if);
5089 tree gro_d_if_scope = IF_SCOPE (gro_d_if);
5090 IF_SCOPE (gro_d_if) = NULL;
5091 gro_d_if = do_poplevel (gro_d_if_scope);
5092 add_stmt (gro_d_if);
5095 /* If the promise is live, then run its dtor if that's available. */
5096 if (promise_dtor && promise_dtor != error_mark_node)
5098 tree promise_d_if = begin_if_stmt ();
5099 finish_if_stmt_cond (coro_promise_live, promise_d_if);
5100 finish_expr_stmt (promise_dtor);
5101 finish_then_clause (promise_d_if);
5102 tree promise_d_if_scope = IF_SCOPE (promise_d_if);
5103 IF_SCOPE (promise_d_if) = NULL;
5104 promise_d_if = do_poplevel (promise_d_if_scope);
5105 add_stmt (promise_d_if);
5108 /* Clean up any frame copies of parms with non-trivial dtors. */
5109 if (DECL_ARGUMENTS (orig))
5110 for (tree arg = DECL_ARGUMENTS (orig); arg != NULL;
5111 arg = DECL_CHAIN (arg))
5113 param_info *parm_i = param_uses->get (arg);
5114 if (parm_i->trivial_dtor)
5115 continue;
5116 if (parm_i->fr_copy_dtor && parm_i->fr_copy_dtor != error_mark_node)
5118 tree dtor_if = begin_if_stmt ();
5119 finish_if_stmt_cond (parm_i->guard_var, dtor_if);
5120 finish_expr_stmt (parm_i->fr_copy_dtor);
5121 finish_then_clause (dtor_if);
5122 tree parm_d_if_scope = IF_SCOPE (dtor_if);
5123 IF_SCOPE (dtor_if) = NULL;
5124 dtor_if = do_poplevel (parm_d_if_scope);
5125 add_stmt (dtor_if);
5129 /* We always expect to delete the frame. */
5130 tree del_coro_fr = coro_get_frame_dtor (coro_fp, orig, frame_size,
5131 promise_type, fn_start);
5132 finish_expr_stmt (del_coro_fr);
5133 tree rethrow = build_throw (fn_start, NULL_TREE);
5134 suppress_warning (rethrow);
5135 finish_expr_stmt (rethrow);
5136 finish_handler (handler);
5137 TRY_HANDLERS (ramp_cleanup) = pop_stmt_list (TRY_HANDLERS (ramp_cleanup));
5140 BIND_EXPR_BODY (ramp_bind) = pop_stmt_list (ramp_body);
5141 TREE_SIDE_EFFECTS (ramp_bind) = true;
5143 /* Start to build the final functions.
5145 We push_deferring_access_checks to avoid these routines being seen as
5146 nested by the middle end; we are doing the outlining here. */
5148 push_deferring_access_checks (dk_no_check);
5150 /* Build the actor... */
5151 build_actor_fn (fn_start, coro_frame_type, actor, fnbody, orig,
5152 &local_var_uses, param_dtor_list,
5153 resume_idx_var, body_aw_points.await_number, frame_size);
5155 /* Destroyer ... */
5156 build_destroy_fn (fn_start, coro_frame_type, destroy, actor);
5158 pop_deferring_access_checks ();
5160 DECL_SAVED_TREE (orig) = newbody;
5161 /* Link our new functions into the list. */
5162 TREE_CHAIN (destroy) = TREE_CHAIN (orig);
5163 TREE_CHAIN (actor) = destroy;
5164 TREE_CHAIN (orig) = actor;
5166 *resumer = actor;
5167 *destroyer = destroy;
5169 delete suspend_points;
5170 suspend_points = NULL;
5171 return true;
5174 #include "gt-cp-coroutines.h"