Don't warn when alignment of global common data exceeds maximum alignment.
[official-gcc.git] / gcc / cp / coroutines.cc
blob47c79e58db5395fe3049392a67b8750955b6f111
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 /* Create the identifiers used by the coroutines library interfaces. */
220 static void
221 coro_init_identifiers ()
223 coro_traits_identifier = get_identifier ("coroutine_traits");
224 coro_handle_identifier = get_identifier ("coroutine_handle");
225 coro_promise_type_identifier = get_identifier ("promise_type");
227 coro_await_transform_identifier = get_identifier ("await_transform");
228 coro_initial_suspend_identifier = get_identifier ("initial_suspend");
229 coro_final_suspend_identifier = get_identifier ("final_suspend");
230 coro_return_void_identifier = get_identifier ("return_void");
231 coro_return_value_identifier = get_identifier ("return_value");
232 coro_yield_value_identifier = get_identifier ("yield_value");
233 coro_resume_identifier = get_identifier ("resume");
234 coro_address_identifier = get_identifier ("address");
235 coro_from_address_identifier = get_identifier ("from_address");
236 coro_get_return_object_identifier = get_identifier ("get_return_object");
237 coro_gro_on_allocation_fail_identifier =
238 get_identifier ("get_return_object_on_allocation_failure");
239 coro_unhandled_exception_identifier = get_identifier ("unhandled_exception");
241 coro_await_ready_identifier = get_identifier ("await_ready");
242 coro_await_suspend_identifier = get_identifier ("await_suspend");
243 coro_await_resume_identifier = get_identifier ("await_resume");
246 /* Trees we only need to set up once. */
248 static GTY(()) tree coro_traits_templ;
249 static GTY(()) tree coro_handle_templ;
250 static GTY(()) tree void_coro_handle_type;
252 /* ================= Parse, Semantics and Type checking ================= */
254 /* This initial set of routines are helper for the parsing and template
255 expansion phases.
257 At the completion of this, we will have completed trees for each of the
258 keywords, but making use of proxy variables for the self-handle and the
259 promise class instance. */
261 /* [coroutine.traits]
262 Lookup the coroutine_traits template decl. */
264 static tree
265 find_coro_traits_template_decl (location_t kw)
267 /* If we are missing fundamental information, such as the traits, (or the
268 declaration found is not a type template), then don't emit an error for
269 every keyword in a TU, just do it once. */
270 static bool traits_error_emitted = false;
272 tree traits_decl = lookup_qualified_name (std_node, coro_traits_identifier,
273 LOOK_want::NORMAL,
274 /*complain=*/!traits_error_emitted);
275 if (traits_decl == error_mark_node
276 || !DECL_TYPE_TEMPLATE_P (traits_decl))
278 if (!traits_error_emitted)
280 gcc_rich_location richloc (kw);
281 error_at (&richloc, "coroutines require a traits template; cannot"
282 " find %<%E::%E%>", std_node, coro_traits_identifier);
283 inform (&richloc, "perhaps %<#include <coroutine>%> is missing");
284 traits_error_emitted = true;
286 return NULL_TREE;
288 else
289 return traits_decl;
292 /* Instantiate Coroutine traits for the function signature. */
294 static tree
295 instantiate_coro_traits (tree fndecl, location_t kw)
297 /* [coroutine.traits.primary]
298 So now build up a type list for the template <typename _R, typename...>.
299 The types are the function's arg types and _R is the function return
300 type. */
302 tree functyp = TREE_TYPE (fndecl);
303 tree arg = DECL_ARGUMENTS (fndecl);
304 tree arg_node = TYPE_ARG_TYPES (functyp);
305 tree argtypes = make_tree_vec (list_length (arg_node)-1);
306 unsigned p = 0;
308 while (arg_node != NULL_TREE && !VOID_TYPE_P (TREE_VALUE (arg_node)))
310 if (is_this_parameter (arg)
311 || DECL_NAME (arg) == closure_identifier)
313 /* We pass a reference to *this to the param preview. */
314 tree ct = TREE_TYPE (TREE_TYPE (arg));
315 TREE_VEC_ELT (argtypes, p++) = cp_build_reference_type (ct, false);
317 else
318 TREE_VEC_ELT (argtypes, p++) = TREE_VALUE (arg_node);
320 arg_node = TREE_CHAIN (arg_node);
321 arg = DECL_CHAIN (arg);
324 tree argtypepack = cxx_make_type (TYPE_ARGUMENT_PACK);
325 SET_ARGUMENT_PACK_ARGS (argtypepack, argtypes);
327 tree targ = make_tree_vec (2);
328 TREE_VEC_ELT (targ, 0) = TREE_TYPE (functyp);
329 TREE_VEC_ELT (targ, 1) = argtypepack;
331 tree traits_class
332 = lookup_template_class (coro_traits_templ, targ,
333 /*in_decl=*/NULL_TREE, /*context=*/NULL_TREE,
334 /*entering scope=*/false, tf_warning_or_error);
336 if (traits_class == error_mark_node)
338 error_at (kw, "cannot instantiate %<coroutine traits%>");
339 return NULL_TREE;
342 return traits_class;
345 /* [coroutine.handle] */
347 static tree
348 find_coro_handle_template_decl (location_t kw)
350 /* As for the coroutine traits, this error is per TU, so only emit
351 it once. */
352 static bool coro_handle_error_emitted = false;
353 tree handle_decl = lookup_qualified_name (std_node, coro_handle_identifier,
354 LOOK_want::NORMAL,
355 !coro_handle_error_emitted);
356 if (handle_decl == error_mark_node
357 || !DECL_CLASS_TEMPLATE_P (handle_decl))
359 if (!coro_handle_error_emitted)
360 error_at (kw, "coroutines require a handle class template;"
361 " cannot find %<%E::%E%>", std_node, coro_handle_identifier);
362 coro_handle_error_emitted = true;
363 return NULL_TREE;
365 else
366 return handle_decl;
369 /* Instantiate the handle template for a given promise type. */
371 static tree
372 instantiate_coro_handle_for_promise_type (location_t kw, tree promise_type)
374 /* So now build up a type list for the template, one entry, the promise. */
375 tree targ = make_tree_vec (1);
376 TREE_VEC_ELT (targ, 0) = promise_type;
377 tree handle_type
378 = lookup_template_class (coro_handle_identifier, targ,
379 /* in_decl=*/NULL_TREE,
380 /* context=*/std_node,
381 /* entering scope=*/false, tf_warning_or_error);
383 if (handle_type == error_mark_node)
385 error_at (kw, "cannot instantiate a %<coroutine handle%> for"
386 " promise type %qT", promise_type);
387 return NULL_TREE;
390 return handle_type;
393 /* Look for the promise_type in the instantiated traits. */
395 static tree
396 find_promise_type (tree traits_class)
398 tree promise_type
399 = lookup_member (traits_class, coro_promise_type_identifier,
400 /* protect=*/1, /*want_type=*/true, tf_warning_or_error);
402 if (promise_type)
403 promise_type
404 = complete_type_or_else (TREE_TYPE (promise_type), promise_type);
406 /* NULL_TREE on fail. */
407 return promise_type;
410 static bool
411 coro_promise_type_found_p (tree fndecl, location_t loc)
413 gcc_assert (fndecl != NULL_TREE);
415 if (!coro_initialized)
417 /* Trees we only need to create once.
418 Set up the identifiers we will use. */
419 coro_init_identifiers ();
421 /* Coroutine traits template. */
422 coro_traits_templ = find_coro_traits_template_decl (loc);
423 if (coro_traits_templ == NULL_TREE)
424 return false;
426 /* coroutine_handle<> template. */
427 coro_handle_templ = find_coro_handle_template_decl (loc);
428 if (coro_handle_templ == NULL_TREE)
429 return false;
431 /* We can also instantiate the void coroutine_handle<> */
432 void_coro_handle_type =
433 instantiate_coro_handle_for_promise_type (loc, NULL_TREE);
434 if (void_coro_handle_type == NULL_TREE)
435 return false;
437 /* A table to hold the state, per coroutine decl. */
438 gcc_checking_assert (coroutine_info_table == NULL);
439 coroutine_info_table =
440 hash_table<coroutine_info_hasher>::create_ggc (11);
442 if (coroutine_info_table == NULL)
443 return false;
445 coro_initialized = true;
448 /* Save the coroutine data on the side to avoid the overhead on every
449 function decl tree. */
451 coroutine_info *coro_info = get_or_insert_coroutine_info (fndecl);
452 /* Without this, we cannot really proceed. */
453 gcc_checking_assert (coro_info);
455 /* If we don't already have a current promise type, try to look it up. */
456 if (coro_info->promise_type == NULL_TREE)
458 /* Get the coroutine traits template class instance for the function
459 signature we have - coroutine_traits <R, ...> */
461 tree templ_class = instantiate_coro_traits (fndecl, loc);
463 /* Find the promise type for that. */
464 coro_info->promise_type = find_promise_type (templ_class);
466 /* If we don't find it, punt on the rest. */
467 if (coro_info->promise_type == NULL_TREE)
469 if (!coro_info->coro_promise_error_emitted)
470 error_at (loc, "unable to find the promise type for"
471 " this coroutine");
472 coro_info->coro_promise_error_emitted = true;
473 return false;
476 /* Test for errors in the promise type that can be determined now. */
477 tree has_ret_void = lookup_member (coro_info->promise_type,
478 coro_return_void_identifier,
479 /*protect=*/1, /*want_type=*/0,
480 tf_none);
481 tree has_ret_val = lookup_member (coro_info->promise_type,
482 coro_return_value_identifier,
483 /*protect=*/1, /*want_type=*/0,
484 tf_none);
485 if (has_ret_void && has_ret_val)
487 location_t ploc = DECL_SOURCE_LOCATION (fndecl);
488 if (!coro_info->coro_co_return_error_emitted)
489 error_at (ploc, "the coroutine promise type %qT declares both"
490 " %<return_value%> and %<return_void%>",
491 coro_info->promise_type);
492 inform (DECL_SOURCE_LOCATION (BASELINK_FUNCTIONS (has_ret_void)),
493 "%<return_void%> declared here");
494 inform (DECL_SOURCE_LOCATION (BASELINK_FUNCTIONS (has_ret_val)),
495 "%<return_value%> declared here");
496 coro_info->coro_co_return_error_emitted = true;
497 return false;
500 /* Try to find the handle type for the promise. */
501 tree handle_type =
502 instantiate_coro_handle_for_promise_type (loc, coro_info->promise_type);
503 if (handle_type == NULL_TREE)
504 return false;
506 /* Complete this, we're going to use it. */
507 coro_info->handle_type = complete_type_or_else (handle_type, fndecl);
509 /* Diagnostic would be emitted by complete_type_or_else. */
510 if (!coro_info->handle_type)
511 return false;
513 /* Build a proxy for a handle to "self" as the param to
514 await_suspend() calls. */
515 coro_info->self_h_proxy
516 = build_lang_decl (VAR_DECL, get_identifier ("self_h.proxy"),
517 coro_info->handle_type);
519 /* Build a proxy for the promise so that we can perform lookups. */
520 coro_info->promise_proxy
521 = build_lang_decl (VAR_DECL, get_identifier ("promise.proxy"),
522 coro_info->promise_type);
524 /* Note where we first saw a coroutine keyword. */
525 coro_info->first_coro_keyword = loc;
528 return true;
531 /* Map from actor or destroyer to ramp. */
532 static GTY(()) hash_map<tree, tree> *to_ramp;
534 /* Given a tree that is an actor or destroy, find the ramp function. */
536 tree
537 coro_get_ramp_function (tree decl)
539 if (!to_ramp)
540 return NULL_TREE;
541 tree *p = to_ramp->get (decl);
542 if (p)
543 return *p;
544 return NULL_TREE;
547 /* Given the DECL for a ramp function (the user's original declaration) return
548 the actor function if it has been defined. */
550 tree
551 coro_get_actor_function (tree decl)
553 if (coroutine_info *info = get_coroutine_info (decl))
554 return info->actor_decl;
556 return NULL_TREE;
559 /* Given the DECL for a ramp function (the user's original declaration) return
560 the destroy function if it has been defined. */
562 tree
563 coro_get_destroy_function (tree decl)
565 if (coroutine_info *info = get_coroutine_info (decl))
566 return info->destroy_decl;
568 return NULL_TREE;
571 /* These functions assumes that the caller has verified that the state for
572 the decl has been initialized, we try to minimize work here. */
574 static tree
575 get_coroutine_promise_type (tree decl)
577 if (coroutine_info *info = get_coroutine_info (decl))
578 return info->promise_type;
580 return NULL_TREE;
583 static tree
584 get_coroutine_handle_type (tree decl)
586 if (coroutine_info *info = get_coroutine_info (decl))
587 return info->handle_type;
589 return NULL_TREE;
592 static tree
593 get_coroutine_self_handle_proxy (tree decl)
595 if (coroutine_info *info = get_coroutine_info (decl))
596 return info->self_h_proxy;
598 return NULL_TREE;
601 static tree
602 get_coroutine_promise_proxy (tree decl)
604 if (coroutine_info *info = get_coroutine_info (decl))
605 return info->promise_proxy;
607 return NULL_TREE;
610 static tree
611 lookup_promise_method (tree fndecl, tree member_id, location_t loc,
612 bool musthave)
614 tree promise = get_coroutine_promise_type (fndecl);
615 tree pm_memb
616 = lookup_member (promise, member_id,
617 /*protect=*/1, /*want_type=*/0, tf_warning_or_error);
618 if (musthave && pm_memb == NULL_TREE)
620 error_at (loc, "no member named %qE in %qT", member_id, promise);
621 return error_mark_node;
623 return pm_memb;
626 /* Build an expression of the form p.method (args) where the p is a promise
627 object for the current coroutine.
628 OBJECT is the promise object instance to use, it may be NULL, in which case
629 we will use the promise_proxy instance for this coroutine.
630 ARGS may be NULL, for empty parm lists. */
632 static tree
633 coro_build_promise_expression (tree fn, tree promise_obj, tree member_id,
634 location_t loc, vec<tree, va_gc> **args,
635 bool musthave)
637 tree meth = lookup_promise_method (fn, member_id, loc, musthave);
638 if (meth == error_mark_node)
639 return error_mark_node;
641 /* If we don't find it, and it isn't needed, an empty return is OK. */
642 if (!meth)
643 return NULL_TREE;
645 tree promise
646 = promise_obj ? promise_obj
647 : get_coroutine_promise_proxy (current_function_decl);
648 tree expr;
649 if (BASELINK_P (meth))
650 expr = build_new_method_call (promise, meth, args, NULL_TREE,
651 LOOKUP_NORMAL, NULL, tf_warning_or_error);
652 else
654 expr = build_class_member_access_expr (promise, meth, NULL_TREE,
655 true, tf_warning_or_error);
656 vec<tree, va_gc> *real_args;
657 if (!args)
658 real_args = make_tree_vector ();
659 else
660 real_args = *args;
661 expr = build_op_call (expr, &real_args, tf_warning_or_error);
663 return expr;
666 /* Caching get for the expression p.return_void (). */
668 static tree
669 get_coroutine_return_void_expr (tree decl, location_t loc, bool musthave)
671 if (coroutine_info *info = get_coroutine_info (decl))
673 /* If we don't have it try to build it. */
674 if (!info->return_void)
675 info->return_void
676 = coro_build_promise_expression (current_function_decl, NULL,
677 coro_return_void_identifier,
678 loc, NULL, musthave);
679 /* Don't return an error if it's an optional call. */
680 if (!musthave && info->return_void == error_mark_node)
681 return NULL_TREE;
682 return info->return_void;
684 return musthave ? error_mark_node : NULL_TREE;
687 /* Lookup an Awaitable member, which should be await_ready, await_suspend
688 or await_resume. */
690 static tree
691 lookup_awaitable_member (tree await_type, tree member_id, location_t loc)
693 tree aw_memb
694 = lookup_member (await_type, member_id,
695 /*protect=*/1, /*want_type=*/0, tf_warning_or_error);
696 if (aw_memb == NULL_TREE)
698 error_at (loc, "no member named %qE in %qT", member_id, await_type);
699 return error_mark_node;
701 return aw_memb;
704 /* Here we check the constraints that are common to all keywords (since the
705 presence of a coroutine keyword makes the function into a coroutine). */
707 static bool
708 coro_common_keyword_context_valid_p (tree fndecl, location_t kw_loc,
709 const char *kw_name)
711 if (fndecl == NULL_TREE)
713 error_at (kw_loc, "%qs cannot be used outside a function", kw_name);
714 return false;
717 /* This is arranged in order of prohibitions in the std. */
718 if (DECL_MAIN_P (fndecl))
720 /* [basic.start.main] 3. The function main shall not be a coroutine. */
721 error_at (kw_loc, "%qs cannot be used in the %<main%> function",
722 kw_name);
723 return false;
726 if (DECL_DECLARED_CONSTEXPR_P (fndecl))
728 cp_function_chain->invalid_constexpr = true;
729 if (!is_instantiation_of_constexpr (fndecl))
731 /* [dcl.constexpr] 3.3 it shall not be a coroutine. */
732 error_at (kw_loc, "%qs cannot be used in a %<constexpr%> function",
733 kw_name);
734 return false;
738 if (FNDECL_USED_AUTO (fndecl))
740 /* [dcl.spec.auto] 15. A function declared with a return type that uses
741 a placeholder type shall not be a coroutine. */
742 error_at (kw_loc,
743 "%qs cannot be used in a function with a deduced return type",
744 kw_name);
745 return false;
748 if (varargs_function_p (fndecl))
750 /* [dcl.fct.def.coroutine] The parameter-declaration-clause of the
751 coroutine shall not terminate with an ellipsis that is not part
752 of a parameter-declaration. */
753 error_at (kw_loc,
754 "%qs cannot be used in a varargs function", kw_name);
755 return false;
758 if (DECL_CONSTRUCTOR_P (fndecl))
760 /* [class.ctor] 7. a constructor shall not be a coroutine. */
761 error_at (kw_loc, "%qs cannot be used in a constructor", kw_name);
762 return false;
765 if (DECL_DESTRUCTOR_P (fndecl))
767 /* [class.dtor] 21. a destructor shall not be a coroutine. */
768 error_at (kw_loc, "%qs cannot be used in a destructor", kw_name);
769 return false;
772 return true;
775 /* Here we check the constraints that are not per keyword. */
777 static bool
778 coro_function_valid_p (tree fndecl)
780 location_t f_loc = DECL_SOURCE_LOCATION (fndecl);
782 /* For cases where fundamental information cannot be found, e.g. the
783 coroutine traits are missing, we need to punt early. */
784 if (!coro_promise_type_found_p (fndecl, f_loc))
785 return false;
787 /* Since we think the function is a coroutine, that implies we parsed
788 a keyword that triggered this. Keywords check promise validity for
789 their context and thus the promise type should be known at this point. */
790 if (get_coroutine_handle_type (fndecl) == NULL_TREE
791 || get_coroutine_promise_type (fndecl) == NULL_TREE)
792 return false;
794 if (current_function_returns_value || current_function_returns_null)
796 /* TODO: record or extract positions of returns (and the first coro
797 keyword) so that we can add notes to the diagnostic about where
798 the bad keyword is and what made the function into a coro. */
799 error_at (f_loc, "a %<return%> statement is not allowed in coroutine;"
800 " did you mean %<co_return%>?");
801 return false;
804 return true;
807 enum suspend_point_kind {
808 CO_AWAIT_SUSPEND_POINT = 0,
809 CO_YIELD_SUSPEND_POINT,
810 INITIAL_SUSPEND_POINT,
811 FINAL_SUSPEND_POINT
814 /* Helper function to build a named variable for the temps we use for each
815 await point. The root of the name is determined by SUSPEND_KIND, and
816 the variable is of type V_TYPE. The awaitable number is reset each time
817 we encounter a final suspend. */
819 static tree
820 get_awaitable_var (suspend_point_kind suspend_kind, tree v_type)
822 static int awn = 0;
823 char *buf;
824 switch (suspend_kind)
826 default: buf = xasprintf ("Aw%d", awn++); break;
827 case CO_YIELD_SUSPEND_POINT: buf = xasprintf ("Yd%d", awn++); break;
828 case INITIAL_SUSPEND_POINT: buf = xasprintf ("Is"); break;
829 case FINAL_SUSPEND_POINT: buf = xasprintf ("Fs"); awn = 0; break;
831 tree ret = get_identifier (buf);
832 free (buf);
833 ret = build_lang_decl (VAR_DECL, ret, v_type);
834 DECL_ARTIFICIAL (ret) = true;
835 return ret;
838 /* Helpers to diagnose missing noexcept on final await expressions. */
840 static bool
841 coro_diagnose_throwing_fn (tree fndecl)
843 if (!TYPE_NOTHROW_P (TREE_TYPE (fndecl)))
845 location_t f_loc = cp_expr_loc_or_loc (fndecl,
846 DECL_SOURCE_LOCATION (fndecl));
847 error_at (f_loc, "the expression %qE is required to be non-throwing",
848 fndecl);
849 inform (f_loc, "must be declared with %<noexcept(true)%>");
850 return true;
852 return false;
855 static bool
856 coro_diagnose_throwing_final_aw_expr (tree expr)
858 tree t = TARGET_EXPR_INITIAL (expr);
859 tree fn = NULL_TREE;
860 if (TREE_CODE (t) == CALL_EXPR)
861 fn = CALL_EXPR_FN(t);
862 else if (TREE_CODE (t) == AGGR_INIT_EXPR)
863 fn = AGGR_INIT_EXPR_FN (t);
864 else if (TREE_CODE (t) == CONSTRUCTOR)
865 return false;
866 else
868 gcc_checking_assert (0 && "unhandled expression type");
869 return false;
871 fn = TREE_OPERAND (fn, 0);
872 return coro_diagnose_throwing_fn (fn);
875 /* This performs [expr.await] bullet 3.3 and validates the interface obtained.
876 It is also used to build the initial and final suspend points.
878 'a', 'o' and 'e' are used as per the description in the section noted.
880 A, the original yield/await expr, is found at source location LOC.
882 We will be constructing a CO_AWAIT_EXPR for a suspend point of one of
883 the four suspend_point_kind kinds. This is indicated by SUSPEND_KIND. */
885 static tree
886 build_co_await (location_t loc, tree a, suspend_point_kind suspend_kind)
888 /* Try and overload of operator co_await, .... */
889 tree o;
890 if (MAYBE_CLASS_TYPE_P (TREE_TYPE (a)))
892 o = build_new_op (loc, CO_AWAIT_EXPR, LOOKUP_NORMAL, a, NULL_TREE,
893 NULL_TREE, NULL, tf_warning_or_error);
894 /* If no viable functions are found, o is a. */
895 if (!o || o == error_mark_node)
896 o = a;
897 else if (flag_exceptions && suspend_kind == FINAL_SUSPEND_POINT)
899 /* We found an overload for co_await(), diagnose throwing cases. */
900 if (TREE_CODE (o) == TARGET_EXPR
901 && coro_diagnose_throwing_final_aw_expr (o))
902 return error_mark_node;
904 /* We now know that the final suspend object is distinct from the
905 final awaiter, so check for a non-throwing DTOR where needed. */
906 tree a_type = TREE_TYPE (a);
907 if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (a_type))
908 if (tree dummy
909 = build_special_member_call (a, complete_dtor_identifier,
910 NULL, a_type, LOOKUP_NORMAL,
911 tf_none))
913 if (CONVERT_EXPR_P (dummy))
914 dummy = TREE_OPERAND (dummy, 0);
915 dummy = TREE_OPERAND (CALL_EXPR_FN (dummy), 0);
916 if (coro_diagnose_throwing_fn (dummy))
917 return error_mark_node;
921 else
922 o = a; /* This is most likely about to fail anyway. */
924 tree o_type = TREE_TYPE (o);
925 if (o_type && !VOID_TYPE_P (o_type))
926 o_type = complete_type_or_else (o_type, o);
928 if (!o_type)
929 return error_mark_node;
931 if (TREE_CODE (o_type) != RECORD_TYPE)
933 error_at (loc, "awaitable type %qT is not a structure",
934 o_type);
935 return error_mark_node;
938 /* Check for required awaitable members and their types. */
939 tree awrd_meth
940 = lookup_awaitable_member (o_type, coro_await_ready_identifier, loc);
941 if (!awrd_meth || awrd_meth == error_mark_node)
942 return error_mark_node;
943 tree awsp_meth
944 = lookup_awaitable_member (o_type, coro_await_suspend_identifier, loc);
945 if (!awsp_meth || awsp_meth == error_mark_node)
946 return error_mark_node;
948 /* The type of the co_await is the return type of the awaitable's
949 await_resume, so we need to look that up. */
950 tree awrs_meth
951 = lookup_awaitable_member (o_type, coro_await_resume_identifier, loc);
952 if (!awrs_meth || awrs_meth == error_mark_node)
953 return error_mark_node;
955 /* To complete the lookups, we need an instance of 'e' which is built from
956 'o' according to [expr.await] 3.4.
958 If we need to materialize this as a temporary, then that will have to be
959 'promoted' to a coroutine frame var. However, if the awaitable is a
960 user variable, parameter or comes from a scope outside this function,
961 then we must use it directly - or we will see unnecessary copies.
963 If o is a variable, find the underlying var. */
964 tree e_proxy = STRIP_NOPS (o);
965 if (INDIRECT_REF_P (e_proxy))
966 e_proxy = TREE_OPERAND (e_proxy, 0);
967 while (TREE_CODE (e_proxy) == COMPONENT_REF)
969 e_proxy = TREE_OPERAND (e_proxy, 0);
970 if (INDIRECT_REF_P (e_proxy))
971 e_proxy = TREE_OPERAND (e_proxy, 0);
972 if (TREE_CODE (e_proxy) == CALL_EXPR)
974 /* We could have operator-> here too. */
975 tree op = TREE_OPERAND (CALL_EXPR_FN (e_proxy), 0);
976 if (DECL_OVERLOADED_OPERATOR_P (op)
977 && DECL_OVERLOADED_OPERATOR_IS (op, COMPONENT_REF))
979 e_proxy = CALL_EXPR_ARG (e_proxy, 0);
980 STRIP_NOPS (e_proxy);
981 gcc_checking_assert (TREE_CODE (e_proxy) == ADDR_EXPR);
982 e_proxy = TREE_OPERAND (e_proxy, 0);
985 STRIP_NOPS (e_proxy);
988 /* Only build a temporary if we need it. */
989 if (TREE_CODE (e_proxy) == PARM_DECL
990 || (VAR_P (e_proxy) && !is_local_temp (e_proxy)))
992 e_proxy = o;
993 o = NULL_TREE; /* The var is already present. */
995 else
997 e_proxy = get_awaitable_var (suspend_kind, o_type);
998 o = cp_build_modify_expr (loc, e_proxy, INIT_EXPR, o,
999 tf_warning_or_error);
1002 /* I suppose we could check that this is contextually convertible to bool. */
1003 tree awrd_func = NULL_TREE;
1004 tree awrd_call
1005 = build_new_method_call (e_proxy, awrd_meth, NULL, NULL_TREE, LOOKUP_NORMAL,
1006 &awrd_func, tf_warning_or_error);
1008 if (!awrd_func || !awrd_call || awrd_call == error_mark_node)
1009 return error_mark_node;
1011 /* The suspend method may return one of three types:
1012 1. void (no special action needed).
1013 2. bool (if true, we don't need to suspend).
1014 3. a coroutine handle, we execute the handle.resume() call. */
1015 tree awsp_func = NULL_TREE;
1016 tree h_proxy = get_coroutine_self_handle_proxy (current_function_decl);
1017 vec<tree, va_gc> *args = make_tree_vector_single (h_proxy);
1018 tree awsp_call
1019 = build_new_method_call (e_proxy, awsp_meth, &args, NULL_TREE,
1020 LOOKUP_NORMAL, &awsp_func, tf_warning_or_error);
1022 release_tree_vector (args);
1023 if (!awsp_func || !awsp_call || awsp_call == error_mark_node)
1024 return error_mark_node;
1026 bool ok = false;
1027 tree susp_return_type = TREE_TYPE (TREE_TYPE (awsp_func));
1028 if (same_type_p (susp_return_type, void_type_node))
1029 ok = true;
1030 else if (same_type_p (susp_return_type, boolean_type_node))
1031 ok = true;
1032 else if (TREE_CODE (susp_return_type) == RECORD_TYPE
1033 && CLASS_TYPE_P (susp_return_type))
1035 tree tt = CLASSTYPE_TI_TEMPLATE (susp_return_type);
1036 if (tt == coro_handle_templ)
1037 ok = true;
1040 if (!ok)
1042 error_at (loc, "%<await_suspend%> must return %<void%>, %<bool%> or"
1043 " a coroutine handle");
1044 return error_mark_node;
1047 /* Finally, the type of e.await_resume() is the co_await's type. */
1048 tree awrs_func = NULL_TREE;
1049 tree awrs_call
1050 = build_new_method_call (e_proxy, awrs_meth, NULL, NULL_TREE, LOOKUP_NORMAL,
1051 &awrs_func, tf_warning_or_error);
1053 if (!awrs_func || !awrs_call || awrs_call == error_mark_node)
1054 return error_mark_node;
1056 if (flag_exceptions && suspend_kind == FINAL_SUSPEND_POINT)
1058 if (coro_diagnose_throwing_fn (awrd_func))
1059 return error_mark_node;
1060 if (coro_diagnose_throwing_fn (awsp_func))
1061 return error_mark_node;
1062 if (coro_diagnose_throwing_fn (awrs_func))
1063 return error_mark_node;
1064 if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (o_type))
1065 if (tree dummy
1066 = build_special_member_call (e_proxy, complete_dtor_identifier,
1067 NULL, o_type, LOOKUP_NORMAL,
1068 tf_none))
1070 if (CONVERT_EXPR_P (dummy))
1071 dummy = TREE_OPERAND (dummy, 0);
1072 dummy = TREE_OPERAND (CALL_EXPR_FN (dummy), 0);
1073 if (coro_diagnose_throwing_fn (dummy))
1074 return error_mark_node;
1078 /* We now have three call expressions, in terms of the promise, handle and
1079 'e' proxies. Save them in the await expression for later expansion. */
1081 tree awaiter_calls = make_tree_vec (3);
1082 TREE_VEC_ELT (awaiter_calls, 0) = awrd_call; /* await_ready(). */
1083 TREE_VEC_ELT (awaiter_calls, 1) = awsp_call; /* await_suspend(). */
1084 tree te = NULL_TREE;
1085 if (TREE_CODE (awrs_call) == TARGET_EXPR)
1087 te = awrs_call;
1088 awrs_call = TREE_OPERAND (awrs_call, 1);
1090 TREE_VEC_ELT (awaiter_calls, 2) = awrs_call; /* await_resume(). */
1092 tree await_expr = build5_loc (loc, CO_AWAIT_EXPR,
1093 TREE_TYPE (TREE_TYPE (awrs_func)),
1094 a, e_proxy, o, awaiter_calls,
1095 build_int_cst (integer_type_node,
1096 (int) suspend_kind));
1097 if (te)
1099 TREE_OPERAND (te, 1) = await_expr;
1100 await_expr = te;
1102 tree t = convert_from_reference (await_expr);
1103 return t;
1106 tree
1107 finish_co_await_expr (location_t kw, tree expr)
1109 if (!expr || error_operand_p (expr))
1110 return error_mark_node;
1112 if (!coro_common_keyword_context_valid_p (current_function_decl, kw,
1113 "co_await"))
1114 return error_mark_node;
1116 /* The current function has now become a coroutine, if it wasn't already. */
1117 DECL_COROUTINE_P (current_function_decl) = 1;
1119 /* This function will appear to have no return statement, even if it
1120 is declared to return non-void (most likely). This is correct - we
1121 synthesize the return for the ramp in the compiler. So suppress any
1122 extraneous warnings during substitution. */
1123 suppress_warning (current_function_decl, OPT_Wreturn_type);
1125 /* If we don't know the promise type, we can't proceed, build the
1126 co_await with the expression unchanged. */
1127 tree functype = TREE_TYPE (current_function_decl);
1128 if (dependent_type_p (functype) || type_dependent_expression_p (expr))
1129 return build5_loc (kw, CO_AWAIT_EXPR, unknown_type_node, expr,
1130 NULL_TREE, NULL_TREE, NULL_TREE, integer_zero_node);
1132 /* We must be able to look up the "await_transform" method in the scope of
1133 the promise type, and obtain its return type. */
1134 if (!coro_promise_type_found_p (current_function_decl, kw))
1135 return error_mark_node;
1137 /* [expr.await] 3.2
1138 The incoming cast expression might be transformed by a promise
1139 'await_transform()'. */
1140 tree at_meth
1141 = lookup_promise_method (current_function_decl,
1142 coro_await_transform_identifier, kw,
1143 /*musthave=*/false);
1144 if (at_meth == error_mark_node)
1145 return error_mark_node;
1147 tree a = expr;
1148 if (at_meth)
1150 /* try to build a = p.await_transform (e). */
1151 vec<tree, va_gc> *args = make_tree_vector_single (expr);
1152 a = build_new_method_call (get_coroutine_promise_proxy (
1153 current_function_decl),
1154 at_meth, &args, NULL_TREE, LOOKUP_NORMAL,
1155 NULL, tf_warning_or_error);
1157 /* As I read the section.
1158 We saw an await_transform method, so it's mandatory that we replace
1159 expr with p.await_transform (expr), therefore if the method call fails
1160 (presumably, we don't have suitable arguments) then this part of the
1161 process fails. */
1162 if (a == error_mark_node)
1163 return error_mark_node;
1166 /* Now we want to build co_await a. */
1167 tree op = build_co_await (kw, a, CO_AWAIT_SUSPEND_POINT);
1168 if (op != error_mark_node)
1170 TREE_SIDE_EFFECTS (op) = 1;
1171 SET_EXPR_LOCATION (op, kw);
1174 return op;
1177 /* Take the EXPR given and attempt to build:
1178 co_await p.yield_value (expr);
1179 per [expr.yield] para 1. */
1181 tree
1182 finish_co_yield_expr (location_t kw, tree expr)
1184 if (!expr || error_operand_p (expr))
1185 return error_mark_node;
1187 /* Check the general requirements and simple syntax errors. */
1188 if (!coro_common_keyword_context_valid_p (current_function_decl, kw,
1189 "co_yield"))
1190 return error_mark_node;
1192 /* The current function has now become a coroutine, if it wasn't already. */
1193 DECL_COROUTINE_P (current_function_decl) = 1;
1195 /* This function will appear to have no return statement, even if it
1196 is declared to return non-void (most likely). This is correct - we
1197 synthesize the return for the ramp in the compiler. So suppress any
1198 extraneous warnings during substitution. */
1199 suppress_warning (current_function_decl, OPT_Wreturn_type);
1201 /* If we don't know the promise type, we can't proceed, build the
1202 co_await with the expression unchanged. */
1203 tree functype = TREE_TYPE (current_function_decl);
1204 if (dependent_type_p (functype) || type_dependent_expression_p (expr))
1205 return build2_loc (kw, CO_YIELD_EXPR, unknown_type_node, expr, NULL_TREE);
1207 if (!coro_promise_type_found_p (current_function_decl, kw))
1208 /* We must be able to look up the "yield_value" method in the scope of
1209 the promise type, and obtain its return type. */
1210 return error_mark_node;
1212 /* [expr.yield] / 1
1213 Let e be the operand of the yield-expression and p be an lvalue naming
1214 the promise object of the enclosing coroutine, then the yield-expression
1215 is equivalent to the expression co_await p.yield_value(e).
1216 build p.yield_value(e): */
1217 vec<tree, va_gc> *args = make_tree_vector_single (expr);
1218 tree yield_call
1219 = coro_build_promise_expression (current_function_decl, NULL,
1220 coro_yield_value_identifier, kw,
1221 &args, /*musthave=*/true);
1222 release_tree_vector (args);
1224 /* Now build co_await p.yield_value (e).
1225 Noting that for co_yield, there is no evaluation of any potential
1226 promise transform_await(), so we call build_co_await directly. */
1228 tree op = build_co_await (kw, yield_call, CO_YIELD_SUSPEND_POINT);
1229 if (op != error_mark_node)
1231 if (REFERENCE_REF_P (op))
1232 op = TREE_OPERAND (op, 0);
1233 /* If the await expression is wrapped in a TARGET_EXPR, then transfer
1234 that wrapper to the CO_YIELD_EXPR, since this is just a proxy for
1235 its contained await. Otherwise, just build the CO_YIELD_EXPR. */
1236 if (TREE_CODE (op) == TARGET_EXPR)
1238 tree t = TREE_OPERAND (op, 1);
1239 t = build2_loc (kw, CO_YIELD_EXPR, TREE_TYPE (t), expr, t);
1240 TREE_OPERAND (op, 1) = t;
1242 else
1243 op = build2_loc (kw, CO_YIELD_EXPR, TREE_TYPE (op), expr, op);
1244 TREE_SIDE_EFFECTS (op) = 1;
1245 op = convert_from_reference (op);
1248 return op;
1251 /* Check and build a co_return statement.
1252 First that it's valid to have a co_return keyword here.
1253 If it is, then check and build the p.return_{void(),value(expr)}.
1254 These are built against a proxy for the promise, which will be filled
1255 in with the actual frame version when the function is transformed. */
1257 tree
1258 finish_co_return_stmt (location_t kw, tree expr)
1260 if (expr)
1261 STRIP_ANY_LOCATION_WRAPPER (expr);
1263 if (error_operand_p (expr))
1264 return error_mark_node;
1266 /* If it fails the following test, the function is not permitted to be a
1267 coroutine, so the co_return statement is erroneous. */
1268 if (!coro_common_keyword_context_valid_p (current_function_decl, kw,
1269 "co_return"))
1270 return error_mark_node;
1272 /* The current function has now become a coroutine, if it wasn't
1273 already. */
1274 DECL_COROUTINE_P (current_function_decl) = 1;
1276 /* This function will appear to have no return statement, even if it
1277 is declared to return non-void (most likely). This is correct - we
1278 synthesize the return for the ramp in the compiler. So suppress any
1279 extraneous warnings during substitution. */
1280 suppress_warning (current_function_decl, OPT_Wreturn_type);
1282 if (processing_template_decl
1283 && check_for_bare_parameter_packs (expr))
1284 return error_mark_node;
1286 /* If we don't know the promise type, we can't proceed, build the
1287 co_return with the expression unchanged. */
1288 tree functype = TREE_TYPE (current_function_decl);
1289 if (dependent_type_p (functype) || type_dependent_expression_p (expr))
1291 /* co_return expressions are always void type, regardless of the
1292 expression type. */
1293 expr = build2_loc (kw, CO_RETURN_EXPR, void_type_node,
1294 expr, NULL_TREE);
1295 expr = maybe_cleanup_point_expr_void (expr);
1296 return add_stmt (expr);
1299 if (!coro_promise_type_found_p (current_function_decl, kw))
1300 return error_mark_node;
1302 /* Suppress -Wreturn-type for co_return, we need to check indirectly
1303 whether the promise type has a suitable return_void/return_value. */
1304 suppress_warning (current_function_decl, OPT_Wreturn_type);
1306 if (!processing_template_decl && warn_sequence_point)
1307 verify_sequence_points (expr);
1309 if (expr)
1311 /* If we had an id-expression obfuscated by force_paren_expr, we need
1312 to undo it so we can try to treat it as an rvalue below. */
1313 expr = maybe_undo_parenthesized_ref (expr);
1315 if (processing_template_decl)
1316 expr = build_non_dependent_expr (expr);
1318 if (error_operand_p (expr))
1319 return error_mark_node;
1322 /* If the promise object doesn't have the correct return call then
1323 there's a mis-match between the co_return <expr> and this. */
1324 tree co_ret_call = error_mark_node;
1325 if (expr == NULL_TREE || VOID_TYPE_P (TREE_TYPE (expr)))
1326 co_ret_call
1327 = get_coroutine_return_void_expr (current_function_decl, kw, true);
1328 else
1330 /* [class.copy.elision] / 3.
1331 An implicitly movable entity is a variable of automatic storage
1332 duration that is either a non-volatile object or an rvalue reference
1333 to a non-volatile object type. For such objects in the context of
1334 the co_return, the overload resolution should be carried out first
1335 treating the object as an rvalue, if that fails, then we fall back
1336 to regular overload resolution. */
1338 tree arg = expr;
1339 if (tree moved = treat_lvalue_as_rvalue_p (expr, /*return*/true))
1340 arg = moved;
1342 releasing_vec args = make_tree_vector_single (arg);
1343 co_ret_call
1344 = coro_build_promise_expression (current_function_decl, NULL,
1345 coro_return_value_identifier, kw,
1346 &args, /*musthave=*/true);
1349 /* Makes no sense for a co-routine really. */
1350 if (TREE_THIS_VOLATILE (current_function_decl))
1351 warning_at (kw, 0,
1352 "function declared %<noreturn%> has a"
1353 " %<co_return%> statement");
1355 expr = build2_loc (kw, CO_RETURN_EXPR, void_type_node, expr, co_ret_call);
1356 expr = maybe_cleanup_point_expr_void (expr);
1357 return add_stmt (expr);
1360 /* We need to validate the arguments to __builtin_coro_promise, since the
1361 second two must be constant, and the builtins machinery doesn't seem to
1362 deal with that properly. */
1364 tree
1365 coro_validate_builtin_call (tree call, tsubst_flags_t)
1367 tree fn = TREE_OPERAND (CALL_EXPR_FN (call), 0);
1369 gcc_checking_assert (DECL_BUILT_IN_CLASS (fn) == BUILT_IN_NORMAL);
1370 switch (DECL_FUNCTION_CODE (fn))
1372 default:
1373 return call;
1375 case BUILT_IN_CORO_PROMISE:
1377 /* Argument 0 is already checked by the normal built-in machinery
1378 Argument 1 must be a constant of size type. It probably makes
1379 little sense if it's not a power of 2, but that isn't specified
1380 formally. */
1381 tree arg = CALL_EXPR_ARG (call, 1);
1382 location_t loc = EXPR_LOCATION (arg);
1384 /* We expect alignof expressions in templates. */
1385 if (TREE_CODE (arg) == NON_DEPENDENT_EXPR
1386 && TREE_CODE (TREE_OPERAND (arg, 0)) == ALIGNOF_EXPR)
1388 else if (!TREE_CONSTANT (arg))
1390 error_at (loc, "the align argument to %<__builtin_coro_promise%>"
1391 " must be a constant");
1392 return error_mark_node;
1394 /* Argument 2 is the direction - to / from handle address to promise
1395 address. */
1396 arg = CALL_EXPR_ARG (call, 2);
1397 loc = EXPR_LOCATION (arg);
1398 if (!TREE_CONSTANT (arg))
1400 error_at (loc, "the direction argument to"
1401 " %<__builtin_coro_promise%> must be a constant");
1402 return error_mark_node;
1404 return call;
1405 break;
1410 /* ================= Morph and Expand. =================
1412 The entry point here is morph_fn_to_coro () which is called from
1413 finish_function () when we have completed any template expansion.
1415 This is preceded by helper functions that implement the phases below.
1417 The process proceeds in four phases.
1419 A Initial framing.
1420 The user's function body is wrapped in the initial and final suspend
1421 points and we begin building the coroutine frame.
1422 We build empty decls for the actor and destroyer functions at this
1423 time too.
1424 When exceptions are enabled, the user's function body will also be
1425 wrapped in a try-catch block with the catch invoking the promise
1426 class 'unhandled_exception' method.
1428 B Analysis.
1429 The user's function body is analyzed to determine the suspend points,
1430 if any, and to capture local variables that might persist across such
1431 suspensions. In most cases, it is not necessary to capture compiler
1432 temporaries, since the tree-lowering nests the suspensions correctly.
1433 However, in the case of a captured reference, there is a lifetime
1434 extension to the end of the full expression - which can mean across a
1435 suspend point in which case it must be promoted to a frame variable.
1437 At the conclusion of analysis, we have a conservative frame layout and
1438 maps of the local variables to their frame entry points.
1440 C Build the ramp function.
1441 Carry out the allocation for the coroutine frame (NOTE; the actual size
1442 computation is deferred until late in the middle end to allow for future
1443 optimizations that will be allowed to elide unused frame entries).
1444 We build the return object.
1446 D Build and expand the actor and destroyer function bodies.
1447 The destroyer is a trivial shim that sets a bit to indicate that the
1448 destroy dispatcher should be used and then calls into the actor.
1450 The actor function is the implementation of the user's state machine.
1451 The current suspend point is noted in an index.
1452 Each suspend point is encoded as a pair of internal functions, one in
1453 the relevant dispatcher, and one representing the suspend point.
1455 During this process, the user's local variables and the proxies for the
1456 self-handle and the promise class instance are re-written to their
1457 coroutine frame equivalents.
1459 The complete bodies for the ramp, actor and destroy function are passed
1460 back to finish_function for folding and gimplification. */
1462 /* Helpers to build EXPR_STMT and void-cast EXPR_STMT, common ops. */
1464 static tree
1465 coro_build_expr_stmt (tree expr, location_t loc)
1467 return maybe_cleanup_point_expr_void (build_stmt (loc, EXPR_STMT, expr));
1470 static tree
1471 coro_build_cvt_void_expr_stmt (tree expr, location_t loc)
1473 tree t = build1 (CONVERT_EXPR, void_type_node, expr);
1474 return coro_build_expr_stmt (t, loc);
1477 /* Helpers for label creation:
1478 1. Create a named label in the specified context. */
1480 static tree
1481 create_anon_label_with_ctx (location_t loc, tree ctx)
1483 tree lab = build_decl (loc, LABEL_DECL, NULL_TREE, void_type_node);
1485 DECL_CONTEXT (lab) = ctx;
1486 DECL_ARTIFICIAL (lab) = true;
1487 DECL_IGNORED_P (lab) = true;
1488 TREE_USED (lab) = true;
1489 return lab;
1492 /* 2. Create a named label in the specified context. */
1494 static tree
1495 create_named_label_with_ctx (location_t loc, const char *name, tree ctx)
1497 tree lab_id = get_identifier (name);
1498 tree lab = define_label (loc, lab_id);
1499 DECL_CONTEXT (lab) = ctx;
1500 DECL_ARTIFICIAL (lab) = true;
1501 TREE_USED (lab) = true;
1502 return lab;
1505 struct proxy_replace
1507 tree from, to;
1510 static tree
1511 replace_proxy (tree *here, int *do_subtree, void *d)
1513 proxy_replace *data = (proxy_replace *) d;
1515 if (*here == data->from)
1517 *here = data->to;
1518 *do_subtree = 0;
1520 else
1521 *do_subtree = 1;
1522 return NULL_TREE;
1525 /* Support for expansion of co_await statements. */
1527 struct coro_aw_data
1529 tree actor_fn; /* Decl for context. */
1530 tree coro_fp; /* Frame pointer var. */
1531 tree resume_idx; /* This is the index var in the frame. */
1532 tree i_a_r_c; /* initial suspend await_resume() was called if true. */
1533 tree self_h; /* This is a handle to the current coro (frame var). */
1534 tree cleanup; /* This is where to go once we complete local destroy. */
1535 tree cororet; /* This is where to go if we suspend. */
1536 tree corocont; /* This is where to go if we continue. */
1537 tree conthand; /* This is the handle for a continuation. */
1538 unsigned index; /* This is our current resume index. */
1541 /* Lightweight search for the first await expression in tree-walk order.
1542 returns:
1543 The first await expression found in STMT.
1544 NULL_TREE if there are none.
1545 So can be used to determine if the statement needs to be processed for
1546 awaits. */
1548 static tree
1549 co_await_find_in_subtree (tree *stmt, int *, void *d)
1551 tree **p = (tree **) d;
1552 if (TREE_CODE (*stmt) == CO_AWAIT_EXPR)
1554 *p = stmt;
1555 return *stmt;
1557 return NULL_TREE;
1560 /* Starting with a statement:
1562 stmt => some tree containing one or more await expressions.
1564 We replace the statement with:
1565 <STATEMENT_LIST> {
1566 initialize awaitable
1567 if (!ready)
1569 suspension context.
1571 resume:
1572 revised statement with one await expression rewritten to its
1573 await_resume() return value.
1576 We then recurse into the initializer and the revised statement
1577 repeating this replacement until there are no more await expressions
1578 in either. */
1580 static tree *
1581 expand_one_await_expression (tree *stmt, tree *await_expr, void *d)
1583 coro_aw_data *data = (coro_aw_data *) d;
1585 tree saved_statement = *stmt;
1586 tree saved_co_await = *await_expr;
1588 tree actor = data->actor_fn;
1589 location_t loc = EXPR_LOCATION (*stmt);
1590 tree var = TREE_OPERAND (saved_co_await, 1); /* frame slot. */
1591 tree expr = TREE_OPERAND (saved_co_await, 2); /* initializer. */
1592 tree awaiter_calls = TREE_OPERAND (saved_co_await, 3);
1594 tree source = TREE_OPERAND (saved_co_await, 4);
1595 bool is_final = (source
1596 && TREE_INT_CST_LOW (source) == (int) FINAL_SUSPEND_POINT);
1597 bool needs_dtor = TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (var));
1598 int resume_point = data->index;
1599 size_t bufsize = sizeof ("destroy.") + 10;
1600 char *buf = (char *) alloca (bufsize);
1601 snprintf (buf, bufsize, "destroy.%d", resume_point);
1602 tree destroy_label = create_named_label_with_ctx (loc, buf, actor);
1603 snprintf (buf, bufsize, "resume.%d", resume_point);
1604 tree resume_label = create_named_label_with_ctx (loc, buf, actor);
1605 tree empty_list = build_empty_stmt (loc);
1607 tree await_type = TREE_TYPE (var);
1608 tree stmt_list = NULL;
1609 tree r;
1610 tree *await_init = NULL;
1612 if (!expr)
1613 needs_dtor = false; /* No need, the var's lifetime is managed elsewhere. */
1614 else
1616 r = coro_build_cvt_void_expr_stmt (expr, loc);
1617 append_to_statement_list_force (r, &stmt_list);
1618 /* We have an initializer, which might itself contain await exprs. */
1619 await_init = tsi_stmt_ptr (tsi_last (stmt_list));
1622 /* Use the await_ready() call to test if we need to suspend. */
1623 tree ready_cond = TREE_VEC_ELT (awaiter_calls, 0); /* await_ready(). */
1624 /* Convert to bool, if necessary. */
1625 if (TREE_CODE (TREE_TYPE (ready_cond)) != BOOLEAN_TYPE)
1626 ready_cond = cp_convert (boolean_type_node, ready_cond,
1627 tf_warning_or_error);
1628 /* Be aggressive in folding here, since there are a significant number of
1629 cases where the ready condition is constant. */
1630 ready_cond = invert_truthvalue_loc (loc, ready_cond);
1631 ready_cond
1632 = build1_loc (loc, CLEANUP_POINT_EXPR, boolean_type_node, ready_cond);
1634 tree body_list = NULL;
1635 tree susp_idx = build_int_cst (short_unsigned_type_node, data->index);
1636 r = build2_loc (loc, MODIFY_EXPR, short_unsigned_type_node, data->resume_idx,
1637 susp_idx);
1638 r = coro_build_cvt_void_expr_stmt (r, loc);
1639 append_to_statement_list (r, &body_list);
1641 /* Find out what we have to do with the awaiter's suspend method.
1642 [expr.await]
1643 (5.1) If the result of await-ready is false, the coroutine is considered
1644 suspended. Then:
1645 (5.1.1) If the type of await-suspend is std::coroutine_handle<Z>,
1646 await-suspend.resume() is evaluated.
1647 (5.1.2) if the type of await-suspend is bool, await-suspend is evaluated,
1648 and the coroutine is resumed if the result is false.
1649 (5.1.3) Otherwise, await-suspend is evaluated. */
1651 tree suspend = TREE_VEC_ELT (awaiter_calls, 1); /* await_suspend(). */
1652 tree susp_type = TREE_TYPE (suspend);
1654 bool is_cont = false;
1655 /* NOTE: final suspend can't resume; the "resume" label in that case
1656 corresponds to implicit destruction. */
1657 if (VOID_TYPE_P (susp_type))
1659 /* We just call await_suspend() and hit the yield. */
1660 suspend = coro_build_cvt_void_expr_stmt (suspend, loc);
1661 append_to_statement_list (suspend, &body_list);
1663 else if (TREE_CODE (susp_type) == BOOLEAN_TYPE)
1665 /* Boolean return, continue if the call returns false. */
1666 suspend = build1_loc (loc, TRUTH_NOT_EXPR, boolean_type_node, suspend);
1667 suspend
1668 = build1_loc (loc, CLEANUP_POINT_EXPR, boolean_type_node, suspend);
1669 tree go_on = build1_loc (loc, GOTO_EXPR, void_type_node, resume_label);
1670 r = build3_loc (loc, COND_EXPR, void_type_node, suspend, go_on,
1671 empty_list);
1672 append_to_statement_list (r, &body_list);
1674 else
1676 r = build1_loc (loc, CONVERT_EXPR, void_coro_handle_type, suspend);
1677 r = build2_loc (loc, INIT_EXPR, void_coro_handle_type, data->conthand, r);
1678 r = build1 (CONVERT_EXPR, void_type_node, r);
1679 append_to_statement_list (r, &body_list);
1680 is_cont = true;
1683 tree d_l = build_address (destroy_label);
1684 tree r_l = build_address (resume_label);
1685 tree susp = build_address (data->cororet);
1686 tree cont = build_address (data->corocont);
1687 tree final_susp = build_int_cst (integer_type_node, is_final ? 1 : 0);
1689 susp_idx = build_int_cst (integer_type_node, data->index);
1691 tree sw = begin_switch_stmt ();
1692 tree cond = build_decl (loc, VAR_DECL, NULL_TREE, integer_type_node);
1693 DECL_ARTIFICIAL (cond) = 1;
1694 DECL_IGNORED_P (cond) = 1;
1695 layout_decl (cond, 0);
1697 r = build_call_expr_internal_loc (loc, IFN_CO_YIELD, integer_type_node, 5,
1698 susp_idx, final_susp, r_l, d_l,
1699 data->coro_fp);
1700 r = build2 (INIT_EXPR, integer_type_node, cond, r);
1701 finish_switch_cond (r, sw);
1702 r = build_case_label (build_int_cst (integer_type_node, 0), NULL_TREE,
1703 create_anon_label_with_ctx (loc, actor));
1704 add_stmt (r); /* case 0: */
1705 /* Implement the suspend, a scope exit without clean ups. */
1706 r = build_call_expr_internal_loc (loc, IFN_CO_SUSPN, void_type_node, 1,
1707 is_cont ? cont : susp);
1708 r = coro_build_cvt_void_expr_stmt (r, loc);
1709 add_stmt (r); /* goto ret; */
1710 r = build_case_label (build_int_cst (integer_type_node, 1), NULL_TREE,
1711 create_anon_label_with_ctx (loc, actor));
1712 add_stmt (r); /* case 1: */
1713 r = build1_loc (loc, GOTO_EXPR, void_type_node, resume_label);
1714 add_stmt (r); /* goto resume; */
1715 r = build_case_label (NULL_TREE, NULL_TREE,
1716 create_anon_label_with_ctx (loc, actor));
1717 add_stmt (r); /* default:; */
1718 r = build1_loc (loc, GOTO_EXPR, void_type_node, destroy_label);
1719 add_stmt (r); /* goto destroy; */
1721 /* part of finish switch. */
1722 SWITCH_STMT_BODY (sw) = pop_stmt_list (SWITCH_STMT_BODY (sw));
1723 pop_switch ();
1724 tree scope = SWITCH_STMT_SCOPE (sw);
1725 SWITCH_STMT_SCOPE (sw) = NULL;
1726 r = do_poplevel (scope);
1727 append_to_statement_list (r, &body_list);
1729 destroy_label = build_stmt (loc, LABEL_EXPR, destroy_label);
1730 append_to_statement_list (destroy_label, &body_list);
1731 if (needs_dtor)
1733 tree dtor = build_special_member_call (var, complete_dtor_identifier,
1734 NULL, await_type, LOOKUP_NORMAL,
1735 tf_warning_or_error);
1736 append_to_statement_list (dtor, &body_list);
1738 r = build1_loc (loc, GOTO_EXPR, void_type_node, data->cleanup);
1739 append_to_statement_list (r, &body_list);
1741 r = build3_loc (loc, COND_EXPR, void_type_node, ready_cond, body_list,
1742 empty_list);
1744 append_to_statement_list (r, &stmt_list);
1746 /* Resume point. */
1747 resume_label = build_stmt (loc, LABEL_EXPR, resume_label);
1748 append_to_statement_list (resume_label, &stmt_list);
1750 /* This will produce the value (if one is provided) from the co_await
1751 expression. */
1752 tree resume_call = TREE_VEC_ELT (awaiter_calls, 2); /* await_resume(). */
1753 if (REFERENCE_REF_P (resume_call))
1754 /* Sink to await_resume call_expr. */
1755 resume_call = TREE_OPERAND (resume_call, 0);
1757 *await_expr = resume_call; /* Replace the co_await expr with its result. */
1758 append_to_statement_list_force (saved_statement, &stmt_list);
1759 /* Get a pointer to the revised statement. */
1760 tree *revised = tsi_stmt_ptr (tsi_last (stmt_list));
1761 if (needs_dtor)
1763 tree dtor = build_special_member_call (var, complete_dtor_identifier,
1764 NULL, await_type, LOOKUP_NORMAL,
1765 tf_warning_or_error);
1766 append_to_statement_list (dtor, &stmt_list);
1768 data->index += 2;
1770 /* Replace the original statement with the expansion. */
1771 *stmt = stmt_list;
1773 /* Now, if the awaitable had an initializer, expand any awaits that might
1774 be embedded in it. */
1775 tree *aw_expr_ptr;
1776 if (await_init &&
1777 cp_walk_tree (await_init, co_await_find_in_subtree, &aw_expr_ptr, NULL))
1778 expand_one_await_expression (await_init, aw_expr_ptr, d);
1780 /* Expand any more await expressions in the the original statement. */
1781 if (cp_walk_tree (revised, co_await_find_in_subtree, &aw_expr_ptr, NULL))
1782 expand_one_await_expression (revised, aw_expr_ptr, d);
1784 return NULL;
1787 /* Check to see if a statement contains at least one await expression, if
1788 so, then process that. */
1790 static tree
1791 process_one_statement (tree *stmt, void *d)
1793 tree *aw_expr_ptr;
1794 if (cp_walk_tree (stmt, co_await_find_in_subtree, &aw_expr_ptr, NULL))
1795 expand_one_await_expression (stmt, aw_expr_ptr, d);
1796 return NULL_TREE;
1799 static tree
1800 await_statement_expander (tree *stmt, int *do_subtree, void *d)
1802 tree res = NULL_TREE;
1804 /* Process a statement at a time. */
1805 if (STATEMENT_CLASS_P (*stmt) || TREE_CODE (*stmt) == BIND_EXPR)
1806 return NULL_TREE; /* Just process the sub-trees. */
1807 else if (TREE_CODE (*stmt) == STATEMENT_LIST)
1809 for (tree &s : tsi_range (*stmt))
1811 res = cp_walk_tree (&s, await_statement_expander,
1812 d, NULL);
1813 if (res)
1814 return res;
1816 *do_subtree = 0; /* Done subtrees. */
1818 else if (EXPR_P (*stmt))
1820 process_one_statement (stmt, d);
1821 *do_subtree = 0; /* Done subtrees. */
1824 /* Continue statement walk, where required. */
1825 return res;
1828 /* Suspend point hash_map. */
1830 struct suspend_point_info
1832 /* coro frame field type. */
1833 tree awaitable_type;
1834 /* coro frame field name. */
1835 tree await_field_id;
1838 static hash_map<tree, suspend_point_info> *suspend_points;
1840 struct await_xform_data
1842 tree actor_fn; /* Decl for context. */
1843 tree actor_frame;
1844 tree promise_proxy;
1845 tree real_promise;
1846 tree self_h_proxy;
1847 tree real_self_h;
1850 /* When we built the await expressions, we didn't know the coro frame
1851 layout, therefore no idea where to find the promise or where to put
1852 the awaitables. Now we know these things, fill them in. */
1854 static tree
1855 transform_await_expr (tree await_expr, await_xform_data *xform)
1857 suspend_point_info *si = suspend_points->get (await_expr);
1858 location_t loc = EXPR_LOCATION (await_expr);
1859 if (!si)
1861 error_at (loc, "no suspend point info for %qD", await_expr);
1862 return error_mark_node;
1865 /* So, on entry, we have:
1866 in : CO_AWAIT_EXPR (a, e_proxy, o, awr_call_vector, mode)
1867 We no longer need a [it had diagnostic value, maybe?]
1868 We need to replace the promise proxy in all elements
1869 We need to replace the e_proxy in the awr_call. */
1871 tree coro_frame_type = TREE_TYPE (xform->actor_frame);
1873 /* If we have a frame var for the awaitable, get a reference to it. */
1874 proxy_replace data;
1875 if (si->await_field_id)
1877 tree as_m
1878 = lookup_member (coro_frame_type, si->await_field_id,
1879 /*protect=*/1, /*want_type=*/0, tf_warning_or_error);
1880 tree as = build_class_member_access_expr (xform->actor_frame, as_m,
1881 NULL_TREE, true,
1882 tf_warning_or_error);
1884 /* Replace references to the instance proxy with the frame entry now
1885 computed. */
1886 data.from = TREE_OPERAND (await_expr, 1);
1887 data.to = as;
1888 cp_walk_tree (&await_expr, replace_proxy, &data, NULL);
1890 /* .. and replace. */
1891 TREE_OPERAND (await_expr, 1) = as;
1894 /* Now do the self_handle. */
1895 data.from = xform->self_h_proxy;
1896 data.to = xform->real_self_h;
1897 cp_walk_tree (&await_expr, replace_proxy, &data, NULL);
1899 /* Now do the promise. */
1900 data.from = xform->promise_proxy;
1901 data.to = xform->real_promise;
1902 cp_walk_tree (&await_expr, replace_proxy, &data, NULL);
1904 return await_expr;
1907 /* A wrapper for the transform_await_expr function so that it can be a
1908 callback from cp_walk_tree. */
1910 static tree
1911 transform_await_wrapper (tree *stmt, int *do_subtree, void *d)
1913 /* Set actor function as new DECL_CONTEXT of label_decl. */
1914 struct await_xform_data *xform = (struct await_xform_data *) d;
1915 if (TREE_CODE (*stmt) == LABEL_DECL
1916 && DECL_CONTEXT (*stmt) != xform->actor_fn)
1917 DECL_CONTEXT (*stmt) = xform->actor_fn;
1919 /* We should have already lowered co_yields to their co_await. */
1920 gcc_checking_assert (TREE_CODE (*stmt) != CO_YIELD_EXPR);
1921 if (TREE_CODE (*stmt) != CO_AWAIT_EXPR)
1922 return NULL_TREE;
1924 tree await_expr = *stmt;
1925 *stmt = transform_await_expr (await_expr, xform);
1926 if (*stmt == error_mark_node)
1927 *do_subtree = 0;
1928 return NULL_TREE;
1931 /* This caches information that we determine about function params,
1932 their uses and copies in the coroutine frame. */
1934 struct param_info
1936 tree field_id; /* The name of the copy in the coroutine frame. */
1937 vec<tree *> *body_uses; /* Worklist of uses, void if there are none. */
1938 tree frame_type; /* The type used to represent this parm in the frame. */
1939 tree orig_type; /* The original type of the parm (not as passed). */
1940 tree guard_var; /* If we need a DTOR on exception, this bool guards it. */
1941 tree fr_copy_dtor; /* If we need a DTOR on exception, this is it. */
1942 bool by_ref; /* Was passed by reference. */
1943 bool pt_ref; /* Was a pointer to object. */
1944 bool rv_ref; /* Was an rvalue ref. */
1945 bool trivial_dtor; /* The frame type has a trivial DTOR. */
1946 bool this_ptr; /* Is 'this' */
1947 bool lambda_cobj; /* Lambda capture object */
1950 struct local_var_info
1952 tree field_id;
1953 tree field_idx;
1954 tree frame_type;
1955 bool is_lambda_capture;
1956 bool is_static;
1957 bool has_value_expr_p;
1958 location_t def_loc;
1961 /* For figuring out what local variable usage we have. */
1962 struct local_vars_transform
1964 tree context;
1965 tree actor_frame;
1966 tree coro_frame_type;
1967 location_t loc;
1968 hash_map<tree, local_var_info> *local_var_uses;
1971 static tree
1972 transform_local_var_uses (tree *stmt, int *do_subtree, void *d)
1974 local_vars_transform *lvd = (local_vars_transform *) d;
1976 /* For each var in this bind expr (that has a frame id, which means it was
1977 accessed), build a frame reference for each and then walk the bind expr
1978 statements, substituting the frame ref for the original var. */
1980 if (TREE_CODE (*stmt) == BIND_EXPR)
1982 tree lvar;
1983 for (lvar = BIND_EXPR_VARS (*stmt); lvar != NULL;
1984 lvar = DECL_CHAIN (lvar))
1986 bool existed;
1987 local_var_info &local_var
1988 = lvd->local_var_uses->get_or_insert (lvar, &existed);
1989 gcc_checking_assert (existed);
1991 /* Re-write the variable's context to be in the actor func. */
1992 DECL_CONTEXT (lvar) = lvd->context;
1994 /* For capture proxies, this could include the decl value expr. */
1995 if (local_var.is_lambda_capture || local_var.has_value_expr_p)
1997 tree ve = DECL_VALUE_EXPR (lvar);
1998 cp_walk_tree (&ve, transform_local_var_uses, d, NULL);
1999 continue; /* No frame entry for this. */
2002 /* TODO: implement selective generation of fields when vars are
2003 known not-used. */
2004 if (local_var.field_id == NULL_TREE)
2005 continue; /* Wasn't used. */
2007 tree fld_ref
2008 = lookup_member (lvd->coro_frame_type, local_var.field_id,
2009 /*protect=*/1, /*want_type=*/0,
2010 tf_warning_or_error);
2011 tree fld_idx = build3_loc (lvd->loc, COMPONENT_REF, TREE_TYPE (lvar),
2012 lvd->actor_frame, fld_ref, NULL_TREE);
2013 local_var.field_idx = fld_idx;
2015 /* FIXME: we should be able to do this in the loop above, but (at least
2016 for range for) there are cases where the DECL_INITIAL contains
2017 forward references.
2018 So, now we've built the revised var in the frame, substitute uses of
2019 it in initializers and the bind expr body. */
2020 for (lvar = BIND_EXPR_VARS (*stmt); lvar != NULL;
2021 lvar = DECL_CHAIN (lvar))
2023 /* we need to walk some of the decl trees, which might contain
2024 references to vars replaced at a higher level. */
2025 cp_walk_tree (&DECL_INITIAL (lvar), transform_local_var_uses, d,
2026 NULL);
2027 cp_walk_tree (&DECL_SIZE (lvar), transform_local_var_uses, d, NULL);
2028 cp_walk_tree (&DECL_SIZE_UNIT (lvar), transform_local_var_uses, d,
2029 NULL);
2031 cp_walk_tree (&BIND_EXPR_BODY (*stmt), transform_local_var_uses, d, NULL);
2033 /* Now we have processed and removed references to the original vars,
2034 we can drop those from the bind - leaving capture proxies alone. */
2035 for (tree *pvar = &BIND_EXPR_VARS (*stmt); *pvar != NULL;)
2037 bool existed;
2038 local_var_info &local_var
2039 = lvd->local_var_uses->get_or_insert (*pvar, &existed);
2040 gcc_checking_assert (existed);
2042 /* Leave lambda closure captures alone, we replace the *this
2043 pointer with the frame version and let the normal process
2044 deal with the rest.
2045 Likewise, variables with their value found elsewhere.
2046 Skip past unused ones too. */
2047 if (local_var.is_lambda_capture
2048 || local_var.has_value_expr_p
2049 || local_var.field_id == NULL_TREE)
2051 pvar = &DECL_CHAIN (*pvar);
2052 continue;
2055 /* Discard this one, we replaced it. */
2056 *pvar = DECL_CHAIN (*pvar);
2059 *do_subtree = 0; /* We've done the body already. */
2060 return NULL_TREE;
2063 tree var_decl = *stmt;
2064 /* Look inside cleanups, we don't want to wrap a statement list in a
2065 cleanup. */
2066 bool needs_cleanup = true;
2067 if (TREE_CODE (var_decl) == CLEANUP_POINT_EXPR)
2068 var_decl = TREE_OPERAND (var_decl, 0);
2069 else
2070 needs_cleanup = false;
2072 /* Look inside the decl_expr for the actual var. */
2073 bool decl_expr_p = TREE_CODE (var_decl) == DECL_EXPR;
2074 if (decl_expr_p && TREE_CODE (DECL_EXPR_DECL (var_decl)) == VAR_DECL)
2075 var_decl = DECL_EXPR_DECL (var_decl);
2076 else if (TREE_CODE (var_decl) != VAR_DECL)
2077 return NULL_TREE;
2079 /* VAR_DECLs that are not recorded can belong to the proxies we've placed
2080 for the promise and coroutine handle(s), to global vars or to compiler
2081 temporaries. Skip past these, we will handle them later. */
2082 local_var_info *local_var_i = lvd->local_var_uses->get (var_decl);
2084 if (local_var_i == NULL)
2085 return NULL_TREE;
2087 if (local_var_i->is_lambda_capture
2088 || local_var_i->is_static
2089 || local_var_i->has_value_expr_p)
2090 return NULL_TREE;
2092 /* This is our revised 'local' i.e. a frame slot. */
2093 tree revised = local_var_i->field_idx;
2094 gcc_checking_assert (DECL_CONTEXT (var_decl) == lvd->context);
2096 if (decl_expr_p && DECL_INITIAL (var_decl))
2098 location_t loc = DECL_SOURCE_LOCATION (var_decl);
2099 tree r
2100 = cp_build_modify_expr (loc, revised, INIT_EXPR,
2101 DECL_INITIAL (var_decl), tf_warning_or_error);
2102 if (needs_cleanup)
2103 r = coro_build_cvt_void_expr_stmt (r, EXPR_LOCATION (*stmt));
2104 *stmt = r;
2106 else
2107 *stmt = revised;
2109 if (decl_expr_p)
2110 *do_subtree = 0; /* We've accounted for the nested use. */
2111 return NULL_TREE;
2114 /* A helper to build the frame DTOR.
2115 [dcl.fct.def.coroutine] / 12
2116 The deallocation function’s name is looked up in the scope of the promise
2117 type. If this lookup fails, the deallocation function’s name is looked up
2118 in the global scope. If deallocation function lookup finds both a usual
2119 deallocation function with only a pointer parameter and a usual
2120 deallocation function with both a pointer parameter and a size parameter,
2121 then the selected deallocation function shall be the one with two
2122 parameters. Otherwise, the selected deallocation function shall be the
2123 function with one parameter. If no usual deallocation function is found
2124 the program is ill-formed. The selected deallocation function shall be
2125 called with the address of the block of storage to be reclaimed as its
2126 first argument. If a deallocation function with a parameter of type
2127 std::size_t is used, the size of the block is passed as the corresponding
2128 argument. */
2130 static tree
2131 coro_get_frame_dtor (tree coro_fp, tree orig, tree frame_size,
2132 tree promise_type, location_t loc)
2134 tree del_coro_fr = NULL_TREE;
2135 tree frame_arg = build1 (CONVERT_EXPR, ptr_type_node, coro_fp);
2136 tree delname = ovl_op_identifier (false, DELETE_EXPR);
2137 tree fns = lookup_promise_method (orig, delname, loc,
2138 /*musthave=*/false);
2139 if (fns && BASELINK_P (fns))
2141 /* Look for sized version first, since this takes precedence. */
2142 vec<tree, va_gc> *args = make_tree_vector ();
2143 vec_safe_push (args, frame_arg);
2144 vec_safe_push (args, frame_size);
2145 tree dummy_promise = build_dummy_object (promise_type);
2147 /* It's OK to fail for this one... */
2148 del_coro_fr = build_new_method_call (dummy_promise, fns, &args,
2149 NULL_TREE, LOOKUP_NORMAL, NULL,
2150 tf_none);
2152 if (!del_coro_fr || del_coro_fr == error_mark_node)
2154 release_tree_vector (args);
2155 args = make_tree_vector_single (frame_arg);
2156 del_coro_fr = build_new_method_call (dummy_promise, fns, &args,
2157 NULL_TREE, LOOKUP_NORMAL, NULL,
2158 tf_none);
2161 /* But one of them must succeed, or the program is ill-formed. */
2162 if (!del_coro_fr || del_coro_fr == error_mark_node)
2164 error_at (loc, "%qE is provided by %qT but is not usable with"
2165 " the function signature %qD", delname, promise_type, orig);
2166 del_coro_fr = error_mark_node;
2169 else
2171 del_coro_fr = build_op_delete_call (DELETE_EXPR, frame_arg, frame_size,
2172 /*global_p=*/true, /*placement=*/NULL,
2173 /*alloc_fn=*/NULL,
2174 tf_warning_or_error);
2175 if (!del_coro_fr || del_coro_fr == error_mark_node)
2176 del_coro_fr = error_mark_node;
2178 return del_coro_fr;
2181 /* The actor transform. */
2183 static void
2184 build_actor_fn (location_t loc, tree coro_frame_type, tree actor, tree fnbody,
2185 tree orig, hash_map<tree, param_info> *param_uses,
2186 hash_map<tree, local_var_info> *local_var_uses,
2187 vec<tree, va_gc> *param_dtor_list, tree resume_fn_field,
2188 tree resume_idx_field, unsigned body_count, tree frame_size)
2190 verify_stmt_tree (fnbody);
2191 /* Some things we inherit from the original function. */
2192 tree handle_type = get_coroutine_handle_type (orig);
2193 tree self_h_proxy = get_coroutine_self_handle_proxy (orig);
2194 tree promise_type = get_coroutine_promise_type (orig);
2195 tree promise_proxy = get_coroutine_promise_proxy (orig);
2197 /* One param, the coro frame pointer. */
2198 tree actor_fp = DECL_ARGUMENTS (actor);
2200 /* We have a definition here. */
2201 TREE_STATIC (actor) = 1;
2203 tree actor_outer = push_stmt_list ();
2204 current_stmt_tree ()->stmts_are_full_exprs_p = 1;
2205 tree stmt = begin_compound_stmt (BCS_FN_BODY);
2207 tree actor_bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
2208 tree top_block = make_node (BLOCK);
2209 BIND_EXPR_BLOCK (actor_bind) = top_block;
2211 tree continuation = build_lang_decl (VAR_DECL,
2212 get_identifier ("actor.continue"),
2213 void_coro_handle_type);
2214 DECL_ARTIFICIAL (continuation) = 1;
2215 DECL_IGNORED_P (continuation) = 1;
2216 DECL_CONTEXT (continuation) = actor;
2217 BIND_EXPR_VARS (actor_bind) = continuation;
2219 /* Link in the block associated with the outer scope of the re-written
2220 function body. */
2221 tree first = expr_first (fnbody);
2222 gcc_checking_assert (first && TREE_CODE (first) == BIND_EXPR);
2223 tree block = BIND_EXPR_BLOCK (first);
2224 gcc_checking_assert (BLOCK_SUPERCONTEXT (block) == NULL_TREE);
2225 gcc_checking_assert (BLOCK_CHAIN (block) == NULL_TREE);
2226 BLOCK_SUPERCONTEXT (block) = top_block;
2227 BLOCK_SUBBLOCKS (top_block) = block;
2229 add_stmt (actor_bind);
2230 tree actor_body = push_stmt_list ();
2232 /* The entry point for the actor code from the ramp. */
2233 tree actor_begin_label
2234 = create_named_label_with_ctx (loc, "actor.begin", actor);
2235 tree actor_frame = build1_loc (loc, INDIRECT_REF, coro_frame_type, actor_fp);
2237 /* Declare the continuation handle. */
2238 add_decl_expr (continuation);
2240 /* Re-write param references in the body, no code should be generated
2241 here. */
2242 if (DECL_ARGUMENTS (orig))
2244 tree arg;
2245 for (arg = DECL_ARGUMENTS (orig); arg != NULL; arg = DECL_CHAIN (arg))
2247 bool existed;
2248 param_info &parm = param_uses->get_or_insert (arg, &existed);
2249 if (!parm.body_uses)
2250 continue; /* Wasn't used in the original function body. */
2252 tree fld_ref = lookup_member (coro_frame_type, parm.field_id,
2253 /*protect=*/1, /*want_type=*/0,
2254 tf_warning_or_error);
2255 tree fld_idx = build3_loc (loc, COMPONENT_REF, parm.frame_type,
2256 actor_frame, fld_ref, NULL_TREE);
2258 /* We keep these in the frame as a regular pointer, so convert that
2259 back to the type expected. */
2260 if (parm.pt_ref)
2261 fld_idx = build1_loc (loc, CONVERT_EXPR, TREE_TYPE (arg), fld_idx);
2263 int i;
2264 tree *puse;
2265 FOR_EACH_VEC_ELT (*parm.body_uses, i, puse)
2266 *puse = fld_idx;
2270 /* Re-write local vars, similarly. */
2271 local_vars_transform xform_vars_data
2272 = {actor, actor_frame, coro_frame_type, loc, local_var_uses};
2273 cp_walk_tree (&fnbody, transform_local_var_uses, &xform_vars_data, NULL);
2275 tree resume_idx_name = get_identifier ("__resume_at");
2276 tree rat_field = lookup_member (coro_frame_type, resume_idx_name, 1, 0,
2277 tf_warning_or_error);
2278 tree rat = build3 (COMPONENT_REF, short_unsigned_type_node, actor_frame,
2279 rat_field, NULL_TREE);
2281 tree ret_label
2282 = create_named_label_with_ctx (loc, "actor.suspend.ret", actor);
2284 tree continue_label
2285 = create_named_label_with_ctx (loc, "actor.continue.ret", actor);
2287 tree lsb_if = begin_if_stmt ();
2288 tree chkb0 = build2 (BIT_AND_EXPR, short_unsigned_type_node, rat,
2289 build_int_cst (short_unsigned_type_node, 1));
2290 chkb0 = build2 (NE_EXPR, short_unsigned_type_node, chkb0,
2291 build_int_cst (short_unsigned_type_node, 0));
2292 finish_if_stmt_cond (chkb0, lsb_if);
2294 tree destroy_dispatcher = begin_switch_stmt ();
2295 finish_switch_cond (rat, destroy_dispatcher);
2296 tree ddeflab = build_case_label (NULL_TREE, NULL_TREE,
2297 create_anon_label_with_ctx (loc, actor));
2298 add_stmt (ddeflab);
2299 tree b = build_call_expr_loc (loc, builtin_decl_explicit (BUILT_IN_TRAP), 0);
2300 b = coro_build_cvt_void_expr_stmt (b, loc);
2301 add_stmt (b);
2303 /* The destroy point numbered #1 is special, in that it is reached from a
2304 coroutine that is suspended after re-throwing from unhandled_exception().
2305 This label just invokes the cleanup of promise, param copies and the
2306 frame itself. */
2307 tree del_promise_label
2308 = create_named_label_with_ctx (loc, "coro.delete.promise", actor);
2309 b = build_case_label (build_int_cst (short_unsigned_type_node, 1), NULL_TREE,
2310 create_anon_label_with_ctx (loc, actor));
2311 add_stmt (b);
2312 add_stmt (build_stmt (loc, GOTO_EXPR, del_promise_label));
2314 short unsigned lab_num = 3;
2315 for (unsigned destr_pt = 0; destr_pt < body_count; destr_pt++)
2317 tree l_num = build_int_cst (short_unsigned_type_node, lab_num);
2318 b = build_case_label (l_num, NULL_TREE,
2319 create_anon_label_with_ctx (loc, actor));
2320 add_stmt (b);
2321 b = build_call_expr_internal_loc (loc, IFN_CO_ACTOR, void_type_node, 1,
2322 l_num);
2323 b = coro_build_cvt_void_expr_stmt (b, loc);
2324 add_stmt (b);
2325 b = build1 (GOTO_EXPR, void_type_node, CASE_LABEL (ddeflab));
2326 add_stmt (b);
2327 lab_num += 2;
2330 /* Insert the prototype dispatcher. */
2331 finish_switch_stmt (destroy_dispatcher);
2333 finish_then_clause (lsb_if);
2335 tree dispatcher = begin_switch_stmt ();
2336 finish_switch_cond (rat, dispatcher);
2337 b = build_case_label (build_int_cst (short_unsigned_type_node, 0), NULL_TREE,
2338 create_anon_label_with_ctx (loc, actor));
2339 add_stmt (b);
2340 b = build1 (GOTO_EXPR, void_type_node, actor_begin_label);
2341 add_stmt (b);
2343 tree rdeflab = build_case_label (NULL_TREE, NULL_TREE,
2344 create_anon_label_with_ctx (loc, actor));
2345 add_stmt (rdeflab);
2346 b = build_call_expr_loc (loc, builtin_decl_explicit (BUILT_IN_TRAP), 0);
2347 b = coro_build_cvt_void_expr_stmt (b, loc);
2348 add_stmt (b);
2350 lab_num = 2;
2351 /* The final resume should be made to hit the default (trap, UB) entry
2352 although it will be unreachable via the normal entry point, since that
2353 is set to NULL on reaching final suspend. */
2354 for (unsigned resu_pt = 0; resu_pt < body_count; resu_pt++)
2356 tree l_num = build_int_cst (short_unsigned_type_node, lab_num);
2357 b = build_case_label (l_num, NULL_TREE,
2358 create_anon_label_with_ctx (loc, actor));
2359 add_stmt (b);
2360 b = build_call_expr_internal_loc (loc, IFN_CO_ACTOR, void_type_node, 1,
2361 l_num);
2362 b = coro_build_cvt_void_expr_stmt (b, loc);
2363 add_stmt (b);
2364 b = build1 (GOTO_EXPR, void_type_node, CASE_LABEL (rdeflab));
2365 add_stmt (b);
2366 lab_num += 2;
2369 /* Insert the prototype dispatcher. */
2370 finish_switch_stmt (dispatcher);
2372 finish_if_stmt (lsb_if);
2374 tree r = build_stmt (loc, LABEL_EXPR, actor_begin_label);
2375 add_stmt (r);
2377 /* actor's version of the promise. */
2378 tree ap_m = lookup_member (coro_frame_type, get_identifier ("__p"), 1, 0,
2379 tf_warning_or_error);
2380 tree ap = build_class_member_access_expr (actor_frame, ap_m, NULL_TREE, false,
2381 tf_warning_or_error);
2383 /* actor's coroutine 'self handle'. */
2384 tree ash_m = lookup_member (coro_frame_type, get_identifier ("__self_h"), 1,
2385 0, tf_warning_or_error);
2386 tree ash = build_class_member_access_expr (actor_frame, ash_m, NULL_TREE,
2387 false, tf_warning_or_error);
2388 /* So construct the self-handle from the frame address. */
2389 tree hfa_m = lookup_member (handle_type, coro_from_address_identifier, 1,
2390 0, tf_warning_or_error);
2392 r = build1 (CONVERT_EXPR, build_pointer_type (void_type_node), actor_fp);
2393 vec<tree, va_gc> *args = make_tree_vector_single (r);
2394 tree hfa = build_new_method_call (ash, hfa_m, &args, NULL_TREE, LOOKUP_NORMAL,
2395 NULL, tf_warning_or_error);
2396 r = build2 (INIT_EXPR, handle_type, ash, hfa);
2397 r = coro_build_cvt_void_expr_stmt (r, loc);
2398 add_stmt (r);
2399 release_tree_vector (args);
2401 /* Now we know the real promise, and enough about the frame layout to
2402 decide where to put things. */
2404 await_xform_data xform
2405 = {actor, actor_frame, promise_proxy, ap, self_h_proxy, ash};
2407 /* Transform the await expressions in the function body. Only do each
2408 await tree once! */
2409 hash_set<tree> pset;
2410 cp_walk_tree (&fnbody, transform_await_wrapper, &xform, &pset);
2412 /* Now replace the promise proxy with its real value. */
2413 proxy_replace p_data;
2414 p_data.from = promise_proxy;
2415 p_data.to = ap;
2416 cp_walk_tree (&fnbody, replace_proxy, &p_data, NULL);
2418 /* The rewrite of the function adds code to set the __resume field to
2419 nullptr when the coroutine is done and also the index to zero when
2420 calling an unhandled exception. These are represented by two proxies
2421 in the function, so rewrite them to the proper frame access. */
2422 tree resume_m
2423 = lookup_member (coro_frame_type, get_identifier ("__resume"),
2424 /*protect=*/1, /*want_type=*/0, tf_warning_or_error);
2425 tree res_x = build_class_member_access_expr (actor_frame, resume_m, NULL_TREE,
2426 false, tf_warning_or_error);
2427 p_data.from = resume_fn_field;
2428 p_data.to = res_x;
2429 cp_walk_tree (&fnbody, replace_proxy, &p_data, NULL);
2431 p_data.from = resume_idx_field;
2432 p_data.to = rat;
2433 cp_walk_tree (&fnbody, replace_proxy, &p_data, NULL);
2435 /* Add in our function body with the co_returns rewritten to final form. */
2436 add_stmt (fnbody);
2438 /* now do the tail of the function. */
2439 r = build_stmt (loc, LABEL_EXPR, del_promise_label);
2440 add_stmt (r);
2442 /* Destructors for the things we built explicitly. */
2443 r = build_special_member_call (ap, complete_dtor_identifier, NULL,
2444 promise_type, LOOKUP_NORMAL,
2445 tf_warning_or_error);
2446 add_stmt (r);
2448 tree del_frame_label
2449 = create_named_label_with_ctx (loc, "coro.delete.frame", actor);
2450 r = build_stmt (loc, LABEL_EXPR, del_frame_label);
2451 add_stmt (r);
2453 /* Here deallocate the frame (if we allocated it), which we will have at
2454 present. */
2455 tree fnf_m
2456 = lookup_member (coro_frame_type, get_identifier ("__frame_needs_free"), 1,
2457 0, tf_warning_or_error);
2458 tree fnf2_x = build_class_member_access_expr (actor_frame, fnf_m, NULL_TREE,
2459 false, tf_warning_or_error);
2461 tree need_free_if = begin_if_stmt ();
2462 fnf2_x = build1 (CONVERT_EXPR, integer_type_node, fnf2_x);
2463 tree cmp = build2 (NE_EXPR, integer_type_node, fnf2_x, integer_zero_node);
2464 finish_if_stmt_cond (cmp, need_free_if);
2465 if (param_dtor_list != NULL)
2467 int i;
2468 tree pid;
2469 FOR_EACH_VEC_ELT (*param_dtor_list, i, pid)
2471 tree m
2472 = lookup_member (coro_frame_type, pid, 1, 0, tf_warning_or_error);
2473 tree a = build_class_member_access_expr (actor_frame, m, NULL_TREE,
2474 false, tf_warning_or_error);
2475 tree t = TREE_TYPE (a);
2476 tree dtor;
2477 dtor
2478 = build_special_member_call (a, complete_dtor_identifier, NULL, t,
2479 LOOKUP_NORMAL, tf_warning_or_error);
2480 add_stmt (dtor);
2484 /* Build the frame DTOR. */
2485 tree del_coro_fr = coro_get_frame_dtor (actor_fp, orig, frame_size,
2486 promise_type, loc);
2487 finish_expr_stmt (del_coro_fr);
2488 finish_then_clause (need_free_if);
2489 tree scope = IF_SCOPE (need_free_if);
2490 IF_SCOPE (need_free_if) = NULL;
2491 r = do_poplevel (scope);
2492 add_stmt (r);
2494 /* done. */
2495 r = build_stmt (loc, RETURN_EXPR, NULL);
2496 suppress_warning (r); /* We don't want a warning about this. */
2497 r = maybe_cleanup_point_expr_void (r);
2498 add_stmt (r);
2500 /* This is the suspend return point. */
2501 r = build_stmt (loc, LABEL_EXPR, ret_label);
2502 add_stmt (r);
2504 r = build_stmt (loc, RETURN_EXPR, NULL);
2505 suppress_warning (r); /* We don't want a warning about this. */
2506 r = maybe_cleanup_point_expr_void (r);
2507 add_stmt (r);
2509 /* This is the 'continuation' return point. For such a case we have a coro
2510 handle (from the await_suspend() call) and we want handle.resume() to
2511 execute as a tailcall allowing arbitrary chaining of coroutines. */
2512 r = build_stmt (loc, LABEL_EXPR, continue_label);
2513 add_stmt (r);
2515 /* We want to force a tail-call even for O0/1, so this expands the resume
2516 call into its underlying implementation. */
2517 tree addr = lookup_member (void_coro_handle_type, coro_address_identifier,
2518 1, 0, tf_warning_or_error);
2519 addr = build_new_method_call (continuation, addr, NULL, NULL_TREE,
2520 LOOKUP_NORMAL, NULL, tf_warning_or_error);
2521 tree resume = build_call_expr_loc
2522 (loc, builtin_decl_explicit (BUILT_IN_CORO_RESUME), 1, addr);
2524 /* In order to support an arbitrary number of coroutine continuations,
2525 we must tail call them. However, some targets do not support indirect
2526 tail calls to arbitrary callees. See PR94359. */
2527 CALL_EXPR_TAILCALL (resume) = true;
2528 resume = coro_build_cvt_void_expr_stmt (resume, loc);
2529 add_stmt (resume);
2531 r = build_stmt (loc, RETURN_EXPR, NULL);
2532 gcc_checking_assert (maybe_cleanup_point_expr_void (r) == r);
2533 add_stmt (r);
2535 /* We will need to know which resume point number should be encoded. */
2536 tree res_idx_m
2537 = lookup_member (coro_frame_type, resume_idx_name,
2538 /*protect=*/1, /*want_type=*/0, tf_warning_or_error);
2539 tree resume_pt_number
2540 = build_class_member_access_expr (actor_frame, res_idx_m, NULL_TREE, false,
2541 tf_warning_or_error);
2543 /* We've now rewritten the tree and added the initial and final
2544 co_awaits. Now pass over the tree and expand the co_awaits. */
2546 coro_aw_data data = {actor, actor_fp, resume_pt_number, NULL_TREE,
2547 ash, del_promise_label, ret_label,
2548 continue_label, continuation, 2};
2549 cp_walk_tree (&actor_body, await_statement_expander, &data, NULL);
2551 BIND_EXPR_BODY (actor_bind) = pop_stmt_list (actor_body);
2552 TREE_SIDE_EFFECTS (actor_bind) = true;
2554 finish_compound_stmt (stmt);
2555 DECL_SAVED_TREE (actor) = pop_stmt_list (actor_outer);
2556 verify_stmt_tree (DECL_SAVED_TREE (actor));
2559 /* The prototype 'destroy' function :
2560 frame->__resume_at |= 1;
2561 actor (frame); */
2563 static void
2564 build_destroy_fn (location_t loc, tree coro_frame_type, tree destroy,
2565 tree actor)
2567 /* One param, the coro frame pointer. */
2568 tree destr_fp = DECL_ARGUMENTS (destroy);
2570 /* We have a definition here. */
2571 TREE_STATIC (destroy) = 1;
2573 tree destr_outer = push_stmt_list ();
2574 current_stmt_tree ()->stmts_are_full_exprs_p = 1;
2575 tree dstr_stmt = begin_compound_stmt (BCS_FN_BODY);
2577 tree destr_frame = build1 (INDIRECT_REF, coro_frame_type, destr_fp);
2579 tree resume_idx_name = get_identifier ("__resume_at");
2580 tree rat_field = lookup_member (coro_frame_type, resume_idx_name, 1, 0,
2581 tf_warning_or_error);
2582 tree rat = build3 (COMPONENT_REF, short_unsigned_type_node, destr_frame,
2583 rat_field, NULL_TREE);
2585 /* _resume_at |= 1 */
2586 tree dstr_idx = build2 (BIT_IOR_EXPR, short_unsigned_type_node, rat,
2587 build_int_cst (short_unsigned_type_node, 1));
2588 tree r = build2 (MODIFY_EXPR, short_unsigned_type_node, rat, dstr_idx);
2589 r = coro_build_cvt_void_expr_stmt (r, loc);
2590 add_stmt (r);
2592 /* So .. call the actor .. */
2593 r = build_call_expr_loc (loc, actor, 1, destr_fp);
2594 r = coro_build_cvt_void_expr_stmt (r, loc);
2595 add_stmt (r);
2597 /* done. */
2598 r = build_stmt (loc, RETURN_EXPR, NULL);
2599 r = maybe_cleanup_point_expr_void (r);
2600 add_stmt (r);
2602 finish_compound_stmt (dstr_stmt);
2603 DECL_SAVED_TREE (destroy) = pop_stmt_list (destr_outer);
2606 /* Helper that returns an identifier for an appended extension to the
2607 current un-mangled function name. */
2609 static tree
2610 get_fn_local_identifier (tree orig, const char *append)
2612 /* Figure out the bits we need to generate names for the outlined things
2613 For consistency, this needs to behave the same way as
2614 ASM_FORMAT_PRIVATE_NAME does. */
2615 tree nm = DECL_NAME (orig);
2616 const char *sep, *pfx = "";
2617 #ifndef NO_DOT_IN_LABEL
2618 sep = ".";
2619 #else
2620 #ifndef NO_DOLLAR_IN_LABEL
2621 sep = "$";
2622 #else
2623 sep = "_";
2624 pfx = "__";
2625 #endif
2626 #endif
2628 char *an;
2629 if (DECL_ASSEMBLER_NAME (orig))
2630 an = ACONCAT ((IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (orig)), sep, append,
2631 (char *) 0));
2632 else if (DECL_USE_TEMPLATE (orig) && DECL_TEMPLATE_INFO (orig)
2633 && DECL_TI_ARGS (orig))
2635 tree tpl_args = DECL_TI_ARGS (orig);
2636 an = ACONCAT ((pfx, IDENTIFIER_POINTER (nm), (char *) 0));
2637 for (int i = 0; i < TREE_VEC_LENGTH (tpl_args); ++i)
2639 tree typ = DECL_NAME (TYPE_NAME (TREE_VEC_ELT (tpl_args, i)));
2640 an = ACONCAT ((an, sep, IDENTIFIER_POINTER (typ), (char *) 0));
2642 an = ACONCAT ((an, sep, append, (char *) 0));
2644 else
2645 an = ACONCAT ((pfx, IDENTIFIER_POINTER (nm), sep, append, (char *) 0));
2647 return get_identifier (an);
2650 /* Build an initial or final await initialized from the promise
2651 initial_suspend or final_suspend expression. */
2653 static tree
2654 build_init_or_final_await (location_t loc, bool is_final)
2656 tree suspend_alt = is_final ? coro_final_suspend_identifier
2657 : coro_initial_suspend_identifier;
2659 tree setup_call
2660 = coro_build_promise_expression (current_function_decl, NULL, suspend_alt,
2661 loc, NULL, /*musthave=*/true);
2663 /* Check for noexcept on the final_suspend call. */
2664 if (flag_exceptions && is_final && setup_call != error_mark_node
2665 && coro_diagnose_throwing_final_aw_expr (setup_call))
2666 return error_mark_node;
2668 /* So build the co_await for this */
2669 /* For initial/final suspends the call is "a" per [expr.await] 3.2. */
2670 return build_co_await (loc, setup_call, (is_final ? FINAL_SUSPEND_POINT
2671 : INITIAL_SUSPEND_POINT));
2674 /* Callback to record the essential data for each await point found in the
2675 function. */
2677 static bool
2678 register_await_info (tree await_expr, tree aw_type, tree aw_nam)
2680 bool seen;
2681 suspend_point_info &s
2682 = suspend_points->get_or_insert (await_expr, &seen);
2683 if (seen)
2685 warning_at (EXPR_LOCATION (await_expr), 0, "duplicate info for %qE",
2686 await_expr);
2687 return false;
2689 s.awaitable_type = aw_type;
2690 s.await_field_id = aw_nam;
2691 return true;
2694 /* This data set is used when analyzing statements for await expressions. */
2696 struct susp_frame_data
2698 /* Function-wide. */
2699 tree *field_list; /* The current coroutine frame field list. */
2700 tree handle_type; /* The self-handle type for this coroutine. */
2701 tree fs_label; /* The destination for co_returns. */
2702 vec<tree, va_gc> *block_stack; /* Track block scopes. */
2703 vec<tree, va_gc> *bind_stack; /* Track current bind expr. */
2704 unsigned await_number; /* Which await in the function. */
2705 unsigned cond_number; /* Which replaced condition in the fn. */
2706 /* Temporary values for one statement or expression being analyzed. */
2707 hash_set<tree> captured_temps; /* The suspend captured these temps. */
2708 vec<tree, va_gc> *to_replace; /* The VAR decls to replace. */
2709 hash_set<tree> *truth_aoif_to_expand; /* The set of TRUTH exprs to expand. */
2710 unsigned saw_awaits; /* Count of awaits in this statement */
2711 bool captures_temporary; /* This expr captures temps by ref. */
2712 bool needs_truth_if_exp; /* We must expand a truth_if expression. */
2713 bool has_awaiter_init; /* We must handle initializing an awaiter. */
2716 /* If this is an await expression, then count it (both uniquely within the
2717 function and locally within a single statement). */
2719 static tree
2720 register_awaits (tree *stmt, int *, void *d)
2722 tree aw_expr = *stmt;
2724 /* We should have already lowered co_yields to their co_await. */
2725 gcc_checking_assert (TREE_CODE (aw_expr) != CO_YIELD_EXPR);
2727 if (TREE_CODE (aw_expr) != CO_AWAIT_EXPR)
2728 return NULL_TREE;
2730 /* Count how many awaits the current expression contains. */
2731 susp_frame_data *data = (susp_frame_data *) d;
2732 data->saw_awaits++;
2733 /* Each await suspend context is unique, this is a function-wide value. */
2734 data->await_number++;
2736 /* Awaitables should either be user-locals or promoted to coroutine frame
2737 entries at this point, and their initializers should have been broken
2738 out. */
2739 tree aw = TREE_OPERAND (aw_expr, 1);
2740 gcc_checking_assert (!TREE_OPERAND (aw_expr, 2));
2742 tree aw_field_type = TREE_TYPE (aw);
2743 tree aw_field_nam = NULL_TREE;
2744 register_await_info (aw_expr, aw_field_type, aw_field_nam);
2746 /* Rewrite target expressions on the await_suspend () to remove extraneous
2747 cleanups for the awaitables, which are now promoted to frame vars and
2748 managed via that. */
2749 tree v = TREE_OPERAND (aw_expr, 3);
2750 tree o = TREE_VEC_ELT (v, 1);
2751 if (TREE_CODE (o) == TARGET_EXPR)
2752 TREE_VEC_ELT (v, 1) = get_target_expr (TREE_OPERAND (o, 1));
2753 return NULL_TREE;
2756 /* There are cases where any await expression is relevant. */
2757 static tree
2758 find_any_await (tree *stmt, int *dosub, void *d)
2760 if (TREE_CODE (*stmt) == CO_AWAIT_EXPR)
2762 *dosub = 0; /* We don't need to consider this any further. */
2763 tree **p = (tree **) d;
2764 *p = stmt;
2765 return *stmt;
2767 return NULL_TREE;
2770 static bool
2771 tmp_target_expr_p (tree t)
2773 if (TREE_CODE (t) != TARGET_EXPR)
2774 return false;
2775 tree v = TREE_OPERAND (t, 0);
2776 if (!DECL_ARTIFICIAL (v))
2777 return false;
2778 if (DECL_NAME (v))
2779 return false;
2780 return true;
2783 /* Structure to record sub-expressions that need to be handled by the
2784 statement flattener. */
2786 struct coro_interesting_subtree
2788 tree* entry;
2789 hash_set<tree> *temps_used;
2792 /* tree-walk callback that returns the first encountered sub-expression of
2793 a kind that needs to be handled specifically by the statement flattener. */
2795 static tree
2796 find_interesting_subtree (tree *expr_p, int *dosub, void *d)
2798 tree expr = *expr_p;
2799 coro_interesting_subtree *p = (coro_interesting_subtree *)d;
2800 if (TREE_CODE (expr) == CO_AWAIT_EXPR)
2802 *dosub = 0; /* We don't need to consider this any further. */
2803 if (TREE_OPERAND (expr, 2))
2805 p->entry = expr_p;
2806 return expr;
2809 else if (tmp_target_expr_p (expr)
2810 && !p->temps_used->contains (expr))
2812 p->entry = expr_p;
2813 return expr;
2816 return NULL_TREE;
2819 /* Node for a doubly-linked list of promoted variables and their
2820 initializers. When the initializer is a conditional expression
2821 the 'then' and 'else' clauses are represented by a linked list
2822 attached to then_cl and else_cl respectively. */
2824 struct var_nest_node
2826 var_nest_node () = default;
2827 var_nest_node (tree v, tree i, var_nest_node *p, var_nest_node *n)
2828 : var(v), init(i), prev(p), next(n), then_cl (NULL), else_cl (NULL)
2830 if (p)
2831 p->next = this;
2832 if (n)
2833 n->prev = this;
2835 tree var;
2836 tree init;
2837 var_nest_node *prev;
2838 var_nest_node *next;
2839 var_nest_node *then_cl;
2840 var_nest_node *else_cl;
2843 /* This is called for single statements from the co-await statement walker.
2844 It checks to see if the statement contains any initializers for awaitables
2845 and if any of these capture items by reference. */
2847 static void
2848 flatten_await_stmt (var_nest_node *n, hash_set<tree> *promoted,
2849 hash_set<tree> *temps_used, tree *replace_in)
2851 bool init_expr = false;
2852 switch (TREE_CODE (n->init))
2854 default: break;
2855 /* Compound expressions must be flattened specifically. */
2856 case COMPOUND_EXPR:
2858 tree first = TREE_OPERAND (n->init, 0);
2859 n->init = TREE_OPERAND (n->init, 1);
2860 var_nest_node *ins
2861 = new var_nest_node(NULL_TREE, first, n->prev, n);
2862 /* The compiler (but not the user) can generate temporaries with
2863 uses in the second arm of a compound expr. */
2864 flatten_await_stmt (ins, promoted, temps_used, &n->init);
2865 flatten_await_stmt (n, promoted, temps_used, NULL);
2866 /* The two arms have been processed separately. */
2867 return;
2869 break;
2870 /* Handle conditional expressions. */
2871 case INIT_EXPR:
2872 init_expr = true;
2873 /* FALLTHROUGH */
2874 case MODIFY_EXPR:
2876 tree old_expr = TREE_OPERAND (n->init, 1);
2877 if (TREE_CODE (old_expr) == COMPOUND_EXPR)
2879 tree first = TREE_OPERAND (old_expr, 0);
2880 TREE_OPERAND (n->init, 1) = TREE_OPERAND (old_expr, 1);
2881 var_nest_node *ins
2882 = new var_nest_node(NULL_TREE, first, n->prev, n);
2883 flatten_await_stmt (ins, promoted, temps_used,
2884 &TREE_OPERAND (n->init, 1));
2885 flatten_await_stmt (n, promoted, temps_used, NULL);
2886 return;
2888 if (TREE_CODE (old_expr) != COND_EXPR)
2889 break;
2890 /* Reconstruct x = t ? y : z;
2891 as (void) t ? x = y : x = z; */
2892 tree var = TREE_OPERAND (n->init, 0);
2893 tree var_type = TREE_TYPE (var);
2894 tree cond = COND_EXPR_COND (old_expr);
2895 /* We are allowed a void type throw in one or both of the cond
2896 expr arms. */
2897 tree then_cl = COND_EXPR_THEN (old_expr);
2898 if (!VOID_TYPE_P (TREE_TYPE (then_cl)))
2900 gcc_checking_assert (TREE_CODE (then_cl) != STATEMENT_LIST);
2901 then_cl
2902 = build2 (init_expr ? INIT_EXPR : MODIFY_EXPR, var_type,
2903 var, then_cl);
2905 tree else_cl = COND_EXPR_ELSE (old_expr);
2906 if (!VOID_TYPE_P (TREE_TYPE (else_cl)))
2908 gcc_checking_assert (TREE_CODE (then_cl) != STATEMENT_LIST);
2909 else_cl
2910 = build2 (init_expr ? INIT_EXPR : MODIFY_EXPR, var_type,
2911 var, else_cl);
2913 n->init = build3 (COND_EXPR, var_type, cond, then_cl, else_cl);
2915 /* FALLTHROUGH */
2916 case COND_EXPR:
2918 tree *found;
2919 tree cond = COND_EXPR_COND (n->init);
2920 /* If the condition contains an await expression, then we need to
2921 set that first and use a separate var. */
2922 if (cp_walk_tree (&cond, find_any_await, &found, NULL))
2924 tree cond_type = TREE_TYPE (cond);
2925 tree cond_var = build_lang_decl (VAR_DECL, NULL_TREE, cond_type);
2926 DECL_ARTIFICIAL (cond_var) = true;
2927 layout_decl (cond_var, 0);
2928 gcc_checking_assert (!TYPE_NEEDS_CONSTRUCTING (cond_type));
2929 cond = build2 (INIT_EXPR, cond_type, cond_var, cond);
2930 var_nest_node *ins
2931 = new var_nest_node (cond_var, cond, n->prev, n);
2932 COND_EXPR_COND (n->init) = cond_var;
2933 flatten_await_stmt (ins, promoted, temps_used, NULL);
2936 n->then_cl
2937 = new var_nest_node (n->var, COND_EXPR_THEN (n->init), NULL, NULL);
2938 n->else_cl
2939 = new var_nest_node (n->var, COND_EXPR_ELSE (n->init), NULL, NULL);
2940 flatten_await_stmt (n->then_cl, promoted, temps_used, NULL);
2941 /* Point to the start of the flattened code. */
2942 while (n->then_cl->prev)
2943 n->then_cl = n->then_cl->prev;
2944 flatten_await_stmt (n->else_cl, promoted, temps_used, NULL);
2945 while (n->else_cl->prev)
2946 n->else_cl = n->else_cl->prev;
2947 return;
2949 break;
2951 coro_interesting_subtree v = { NULL, temps_used };
2952 tree t = cp_walk_tree (&n->init, find_interesting_subtree, (void *)&v, NULL);
2953 if (!t)
2954 return;
2955 switch (TREE_CODE (t))
2957 default: break;
2958 case CO_AWAIT_EXPR:
2960 /* Await expressions with initializers have a compiler-temporary
2961 as the awaitable. 'promote' this. */
2962 tree var = TREE_OPERAND (t, 1);
2963 bool already_present = promoted->add (var);
2964 gcc_checking_assert (!already_present);
2965 tree init = TREE_OPERAND (t, 2);
2966 switch (TREE_CODE (init))
2968 default: break;
2969 case INIT_EXPR:
2970 case MODIFY_EXPR:
2972 tree inner = TREE_OPERAND (init, 1);
2973 /* We can have non-lvalue-expressions here, but when we see
2974 a target expression, mark it as already used. */
2975 if (TREE_CODE (inner) == TARGET_EXPR)
2977 temps_used->add (inner);
2978 gcc_checking_assert
2979 (TREE_CODE (TREE_OPERAND (inner, 1)) != COND_EXPR);
2982 break;
2983 case CALL_EXPR:
2984 /* If this is a call and not a CTOR, then we didn't expect it. */
2985 gcc_checking_assert
2986 (DECL_CONSTRUCTOR_P (TREE_OPERAND (CALL_EXPR_FN (init), 0)));
2987 break;
2989 var_nest_node *ins = new var_nest_node (var, init, n->prev, n);
2990 TREE_OPERAND (t, 2) = NULL_TREE;
2991 flatten_await_stmt (ins, promoted, temps_used, NULL);
2992 flatten_await_stmt (n, promoted, temps_used, NULL);
2993 return;
2995 break;
2996 case TARGET_EXPR:
2998 /* We have a temporary; promote it, but allow for the idiom in code
2999 generated by the compiler like
3000 a = (target_expr produces temp, op uses temp). */
3001 tree init = t;
3002 temps_used->add (init);
3003 tree var_type = TREE_TYPE (init);
3004 char *buf = xasprintf ("D.%d", DECL_UID (TREE_OPERAND (init, 0)));
3005 tree var = build_lang_decl (VAR_DECL, get_identifier (buf), var_type);
3006 DECL_ARTIFICIAL (var) = true;
3007 free (buf);
3008 bool already_present = promoted->add (var);
3009 gcc_checking_assert (!already_present);
3010 tree inner = TREE_OPERAND (init, 1);
3011 gcc_checking_assert (TREE_CODE (inner) != COND_EXPR);
3012 init = cp_build_modify_expr (input_location, var, INIT_EXPR, init,
3013 tf_warning_or_error);
3014 /* Simplify for the case that we have an init containing the temp
3015 alone. */
3016 if (t == n->init && n->var == NULL_TREE)
3018 n->var = var;
3019 proxy_replace pr = {TREE_OPERAND (t, 0), var};
3020 cp_walk_tree (&init, replace_proxy, &pr, NULL);
3021 n->init = init;
3022 if (replace_in)
3023 cp_walk_tree (replace_in, replace_proxy, &pr, NULL);
3024 flatten_await_stmt (n, promoted, temps_used, NULL);
3026 else
3028 var_nest_node *ins
3029 = new var_nest_node (var, init, n->prev, n);
3030 /* We have to replace the target expr... */
3031 *v.entry = var;
3032 /* ... and any uses of its var. */
3033 proxy_replace pr = {TREE_OPERAND (t, 0), var};
3034 cp_walk_tree (&n->init, replace_proxy, &pr, NULL);
3035 /* Compiler-generated temporaries can also have uses in
3036 following arms of compound expressions, which will be listed
3037 in 'replace_in' if present. */
3038 if (replace_in)
3039 cp_walk_tree (replace_in, replace_proxy, &pr, NULL);
3040 flatten_await_stmt (ins, promoted, temps_used, NULL);
3041 flatten_await_stmt (n, promoted, temps_used, NULL);
3043 return;
3045 break;
3049 /* Helper for 'process_conditional' that handles recursion into nested
3050 conditionals. */
3052 static void
3053 handle_nested_conditionals (var_nest_node *n, vec<tree>& list,
3054 hash_map<tree, tree>& map)
3058 if (n->var && DECL_NAME (n->var))
3060 list.safe_push (n->var);
3061 if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (n->var)))
3063 bool existed;
3064 tree& flag = map.get_or_insert (n->var, &existed);
3065 if (!existed)
3067 /* We didn't see this var before and it needs a DTOR, so
3068 build a guard variable for it. */
3069 char *nam
3070 = xasprintf ("%s_guard",
3071 IDENTIFIER_POINTER (DECL_NAME (n->var)));
3072 flag = build_lang_decl (VAR_DECL, get_identifier (nam),
3073 boolean_type_node);
3074 free (nam);
3075 DECL_ARTIFICIAL (flag) = true;
3078 /* The initializer for this variable is replaced by a compound
3079 expression that performs the init and then records that the
3080 variable is live (and the DTOR should be run at the scope
3081 exit. */
3082 tree set_flag = build2 (INIT_EXPR, boolean_type_node,
3083 flag, boolean_true_node);
3084 n->init
3085 = build2 (COMPOUND_EXPR, boolean_type_node, n->init, set_flag);
3088 if (TREE_CODE (n->init) == COND_EXPR)
3090 tree new_then = push_stmt_list ();
3091 handle_nested_conditionals (n->then_cl, list, map);
3092 new_then = pop_stmt_list (new_then);
3093 tree new_else = push_stmt_list ();
3094 handle_nested_conditionals (n->else_cl, list, map);
3095 new_else = pop_stmt_list (new_else);
3096 tree new_if
3097 = build4 (IF_STMT, void_type_node, COND_EXPR_COND (n->init),
3098 new_then, new_else, NULL_TREE);
3099 add_stmt (new_if);
3101 else
3102 finish_expr_stmt (n->init);
3103 n = n->next;
3104 } while (n);
3107 /* helper for 'maybe_promote_temps'.
3109 When we have a conditional expression which might embed await expressions
3110 and/or promoted variables, we need to handle it appropriately.
3112 The linked lists for the 'then' and 'else' clauses in a conditional node
3113 identify the promoted variables (but these cannot be wrapped in a regular
3114 cleanup).
3116 So recurse through the lists and build up a composite list of captured vars.
3117 Declare these and any guard variables needed to decide if a DTOR should be
3118 run. Then embed the conditional into a try-finally expression that handles
3119 running each DTOR conditionally on its guard variable. */
3121 static void
3122 process_conditional (var_nest_node *n, tree& vlist)
3124 tree init = n->init;
3125 hash_map<tree, tree> var_flags;
3126 auto_vec<tree> var_list;
3127 tree new_then = push_stmt_list ();
3128 handle_nested_conditionals (n->then_cl, var_list, var_flags);
3129 new_then = pop_stmt_list (new_then);
3130 tree new_else = push_stmt_list ();
3131 handle_nested_conditionals (n->else_cl, var_list, var_flags);
3132 new_else = pop_stmt_list (new_else);
3133 /* Declare the vars. There are two loops so that the boolean flags are
3134 grouped in the frame. */
3135 for (unsigned i = 0; i < var_list.length(); i++)
3137 tree var = var_list[i];
3138 DECL_CHAIN (var) = vlist;
3139 vlist = var;
3140 add_decl_expr (var);
3142 /* Define the guard flags for variables that need a DTOR. */
3143 for (unsigned i = 0; i < var_list.length(); i++)
3145 tree *flag = var_flags.get (var_list[i]);
3146 if (flag)
3148 DECL_INITIAL (*flag) = boolean_false_node;
3149 DECL_CHAIN (*flag) = vlist;
3150 vlist = *flag;
3151 add_decl_expr (*flag);
3154 tree new_if
3155 = build4 (IF_STMT, void_type_node, COND_EXPR_COND (init),
3156 new_then, new_else, NULL_TREE);
3157 /* Build a set of conditional DTORs. */
3158 tree final_actions = push_stmt_list ();
3159 while (!var_list.is_empty())
3161 tree var = var_list.pop ();
3162 tree *flag = var_flags.get (var);
3163 if (!flag)
3164 continue;
3165 tree var_type = TREE_TYPE (var);
3166 tree cleanup
3167 = build_special_member_call (var, complete_dtor_identifier,
3168 NULL, var_type, LOOKUP_NORMAL,
3169 tf_warning_or_error);
3170 tree cond_cleanup = begin_if_stmt ();
3171 finish_if_stmt_cond (*flag, cond_cleanup);
3172 finish_expr_stmt (cleanup);
3173 finish_then_clause (cond_cleanup);
3174 finish_if_stmt (cond_cleanup);
3176 final_actions = pop_stmt_list (final_actions);
3177 tree try_finally
3178 = build2 (TRY_FINALLY_EXPR, void_type_node, new_if, final_actions);
3179 add_stmt (try_finally);
3182 /* Given *STMT, that contains at least one await expression.
3184 The full expression represented in the original source code will contain
3185 suspension points, but it is still required that the lifetime of temporary
3186 values extends to the end of the expression.
3188 We already have a mechanism to 'promote' user-authored local variables
3189 to a coroutine frame counterpart (which allows explicit management of the
3190 lifetime across suspensions). The transform here re-writes STMT into
3191 a bind expression, promotes temporary values into local variables in that
3192 and flattens the statement into a series of cleanups.
3194 Conditional expressions are re-written to regular 'if' statements.
3195 The cleanups for variables initialized inside a conditional (including
3196 nested cases) are wrapped in a try-finally clause, with guard variables
3197 to determine which DTORs need to be run. */
3199 static tree
3200 maybe_promote_temps (tree *stmt, void *d)
3202 susp_frame_data *awpts = (susp_frame_data *) d;
3204 location_t sloc = EXPR_LOCATION (*stmt);
3205 tree expr = *stmt;
3206 /* Strip off uninteresting wrappers. */
3207 if (TREE_CODE (expr) == CLEANUP_POINT_EXPR)
3208 expr = TREE_OPERAND (expr, 0);
3209 if (TREE_CODE (expr) == EXPR_STMT)
3210 expr = EXPR_STMT_EXPR (expr);
3211 if (TREE_CODE (expr) == CONVERT_EXPR
3212 && VOID_TYPE_P (TREE_TYPE (expr)))
3213 expr = TREE_OPERAND (expr, 0);
3214 STRIP_NOPS (expr);
3216 /* We walk the statement trees, flattening it into an ordered list of
3217 variables with initializers and fragments corresponding to compound
3218 expressions, truth or/and if and ternary conditionals. Conditional
3219 expressions carry a nested list of fragments for the then and else
3220 clauses. We anchor to the 'bottom' of the fragment list; we will write
3221 a cleanup nest with one shell for each variable initialized. */
3222 var_nest_node *root = new var_nest_node (NULL_TREE, expr, NULL, NULL);
3223 /* Check to see we didn't promote one twice. */
3224 hash_set<tree> promoted_vars;
3225 hash_set<tree> used_temps;
3226 flatten_await_stmt (root, &promoted_vars, &used_temps, NULL);
3228 gcc_checking_assert (root->next == NULL);
3229 tree vlist = NULL_TREE;
3230 var_nest_node *t = root;
3231 /* We build the bind scope expression from the bottom-up.
3232 EXPR_LIST holds the inner expression nest at the current cleanup
3233 level (becoming the final expression list when we've exhausted the
3234 number of sub-expression fragments). */
3235 tree expr_list = NULL_TREE;
3238 tree new_list = push_stmt_list ();
3239 /* When we have a promoted variable, then add that to the bind scope
3240 and initialize it. When there's no promoted variable, we just need
3241 to run the initializer.
3242 If the initializer is a conditional expression, we need to collect
3243 and declare any promoted variables nested within it. DTORs for such
3244 variables must be run conditionally too. */
3245 if (t->var && DECL_NAME (t->var))
3247 tree var = t->var;
3248 DECL_CHAIN (var) = vlist;
3249 vlist = var;
3250 add_decl_expr (var);
3251 if (TREE_CODE (t->init) == COND_EXPR)
3252 process_conditional (t, vlist);
3253 else
3254 finish_expr_stmt (t->init);
3255 tree var_type = TREE_TYPE (var);
3256 if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (var_type))
3258 tree cleanup
3259 = build_special_member_call (var, complete_dtor_identifier,
3260 NULL, var_type, LOOKUP_NORMAL,
3261 tf_warning_or_error);
3262 tree cl = build_stmt (sloc, CLEANUP_STMT, expr_list, cleanup, var);
3263 add_stmt (cl); /* push this onto the level above. */
3265 else if (expr_list)
3267 if (TREE_CODE (expr_list) != STATEMENT_LIST)
3268 add_stmt (expr_list);
3269 else if (!tsi_end_p (tsi_start (expr_list)))
3270 add_stmt (expr_list);
3273 else
3275 if (TREE_CODE (t->init) == COND_EXPR)
3276 process_conditional (t, vlist);
3277 else
3278 finish_expr_stmt (t->init);
3279 if (expr_list)
3281 if (TREE_CODE (expr_list) != STATEMENT_LIST)
3282 add_stmt (expr_list);
3283 else if (!tsi_end_p (tsi_start (expr_list)))
3284 add_stmt (expr_list);
3287 expr_list = pop_stmt_list (new_list);
3288 var_nest_node *old = t;
3289 t = t->prev;
3290 delete old;
3291 } while (t);
3293 /* Now produce the bind expression containing the 'promoted' temporaries
3294 as its variable list, and the cleanup nest as the statement. */
3295 tree await_bind = build3_loc (sloc, BIND_EXPR, void_type_node,
3296 NULL, NULL, NULL);
3297 BIND_EXPR_BODY (await_bind) = expr_list;
3298 BIND_EXPR_VARS (await_bind) = nreverse (vlist);
3299 tree b_block = make_node (BLOCK);
3300 if (!awpts->block_stack->is_empty ())
3302 tree s_block = awpts->block_stack->last ();
3303 if (s_block)
3305 BLOCK_SUPERCONTEXT (b_block) = s_block;
3306 BLOCK_CHAIN (b_block) = BLOCK_SUBBLOCKS (s_block);
3307 BLOCK_SUBBLOCKS (s_block) = b_block;
3310 BLOCK_VARS (b_block) = BIND_EXPR_VARS (await_bind) ;
3311 BIND_EXPR_BLOCK (await_bind) = b_block;
3312 TREE_SIDE_EFFECTS (await_bind) = TREE_SIDE_EFFECTS (BIND_EXPR_BODY (await_bind));
3313 *stmt = await_bind;
3314 hash_set<tree> visited;
3315 return cp_walk_tree (stmt, register_awaits, d, &visited);
3318 /* Lightweight callback to determine two key factors:
3319 1) If the statement/expression contains any await expressions.
3320 2) If the statement/expression potentially requires a re-write to handle
3321 TRUTH_{AND,OR}IF_EXPRs since, in most cases, they will need expansion
3322 so that the await expressions are not processed in the case of the
3323 short-circuit arm.
3325 CO_YIELD expressions are re-written to their underlying co_await. */
3327 static tree
3328 analyze_expression_awaits (tree *stmt, int *do_subtree, void *d)
3330 susp_frame_data *awpts = (susp_frame_data *) d;
3332 switch (TREE_CODE (*stmt))
3334 default: return NULL_TREE;
3335 case CO_YIELD_EXPR:
3336 /* co_yield is syntactic sugar, re-write it to co_await. */
3337 *stmt = TREE_OPERAND (*stmt, 1);
3338 /* FALLTHROUGH */
3339 case CO_AWAIT_EXPR:
3340 awpts->saw_awaits++;
3341 /* A non-null initializer for the awaiter means we need to expand. */
3342 if (TREE_OPERAND (*stmt, 2))
3343 awpts->has_awaiter_init = true;
3344 break;
3345 case TRUTH_ANDIF_EXPR:
3346 case TRUTH_ORIF_EXPR:
3348 /* We don't need special action for awaits in the always-executed
3349 arm of a TRUTH_IF. */
3350 if (tree res = cp_walk_tree (&TREE_OPERAND (*stmt, 0),
3351 analyze_expression_awaits, d, NULL))
3352 return res;
3353 /* However, if there are await expressions on the conditionally
3354 executed branch, we must expand the TRUTH_IF to ensure that the
3355 expanded await expression control-flow is fully contained in the
3356 conditionally executed code. */
3357 unsigned aw_count = awpts->saw_awaits;
3358 if (tree res = cp_walk_tree (&TREE_OPERAND (*stmt, 1),
3359 analyze_expression_awaits, d, NULL))
3360 return res;
3361 if (awpts->saw_awaits > aw_count)
3363 awpts->truth_aoif_to_expand->add (*stmt);
3364 awpts->needs_truth_if_exp = true;
3366 /* We've done the sub-trees here. */
3367 *do_subtree = 0;
3369 break;
3372 return NULL_TREE; /* Recurse until done. */
3375 /* Given *EXPR
3376 If EXPR contains a TRUTH_{AND,OR}IF_EXPR, TAOIE with an await expr on
3377 the conditionally executed branch, change this in a ternary operator.
3379 bool not_expr = TAOIE == TRUTH_ORIF_EXPR ? NOT : NOP;
3380 not_expr (always-exec expr) ? conditionally-exec expr : not_expr;
3382 Apply this recursively to the condition and the conditionally-exec
3383 branch. */
3385 struct truth_if_transform {
3386 tree *orig_stmt;
3387 tree scratch_var;
3388 hash_set<tree> *truth_aoif_to_expand;
3391 static tree
3392 expand_one_truth_if (tree *expr, int *do_subtree, void *d)
3394 truth_if_transform *xform = (truth_if_transform *) d;
3396 bool needs_not = false;
3397 switch (TREE_CODE (*expr))
3399 default: break;
3400 case TRUTH_ORIF_EXPR:
3401 needs_not = true;
3402 /* FALLTHROUGH */
3403 case TRUTH_ANDIF_EXPR:
3405 if (!xform->truth_aoif_to_expand->contains (*expr))
3406 break;
3408 location_t sloc = EXPR_LOCATION (*expr);
3409 /* Transform truth expression into a cond expression with
3410 * the always-executed arm as the condition.
3411 * the conditionally-executed arm as the then clause.
3412 * the 'else' clause is fixed: 'true' for ||,'false' for &&. */
3413 tree cond = TREE_OPERAND (*expr, 0);
3414 tree test1 = TREE_OPERAND (*expr, 1);
3415 tree fixed = needs_not ? boolean_true_node : boolean_false_node;
3416 if (needs_not)
3417 cond = build1 (TRUTH_NOT_EXPR, boolean_type_node, cond);
3418 tree cond_expr
3419 = build3_loc (sloc, COND_EXPR, boolean_type_node,
3420 cond, test1, fixed);
3421 *expr = cond_expr;
3422 if (tree res = cp_walk_tree (&COND_EXPR_COND (*expr),
3423 expand_one_truth_if, d, NULL))
3424 return res;
3425 if (tree res = cp_walk_tree (&COND_EXPR_THEN (*expr),
3426 expand_one_truth_if, d, NULL))
3427 return res;
3428 /* We've manually processed necessary sub-trees here. */
3429 *do_subtree = 0;
3431 break;
3433 return NULL_TREE;
3436 /* Helper that adds a new variable of VAR_TYPE to a bind scope BIND, the
3437 name is made up from NAM_ROOT, NAM_VERS. */
3439 static tree
3440 add_var_to_bind (tree& bind, tree var_type,
3441 const char *nam_root, unsigned nam_vers)
3443 tree b_vars = BIND_EXPR_VARS (bind);
3444 /* Build a variable to hold the condition, this will be included in the
3445 frame as a local var. */
3446 char *nam = xasprintf ("%s.%d", nam_root, nam_vers);
3447 tree newvar = build_lang_decl (VAR_DECL, get_identifier (nam), var_type);
3448 free (nam);
3449 DECL_CHAIN (newvar) = b_vars;
3450 BIND_EXPR_VARS (bind) = newvar;
3451 return newvar;
3454 /* Helper to build and add if (!cond) break; */
3456 static void
3457 coro_build_add_if_not_cond_break (tree cond)
3459 tree if_stmt = begin_if_stmt ();
3460 tree invert = build1 (TRUTH_NOT_EXPR, boolean_type_node, cond);
3461 finish_if_stmt_cond (invert, if_stmt);
3462 finish_break_stmt ();
3463 finish_then_clause (if_stmt);
3464 finish_if_stmt (if_stmt);
3467 /* Tree walk callback to replace continue statements with goto label. */
3468 static tree
3469 replace_continue (tree *stmt, int *do_subtree, void *d)
3471 tree expr = *stmt;
3472 if (TREE_CODE (expr) == CLEANUP_POINT_EXPR)
3473 expr = TREE_OPERAND (expr, 0);
3474 if (CONVERT_EXPR_P (expr) && VOID_TYPE_P (expr))
3475 expr = TREE_OPERAND (expr, 0);
3476 STRIP_NOPS (expr);
3477 if (!STATEMENT_CLASS_P (expr))
3478 return NULL_TREE;
3480 switch (TREE_CODE (expr))
3482 /* Unless it's a special case, just walk the subtrees as usual. */
3483 default: return NULL_TREE;
3485 case CONTINUE_STMT:
3487 tree *label = (tree *)d;
3488 location_t loc = EXPR_LOCATION (expr);
3489 /* re-write a continue to goto label. */
3490 *stmt = build_stmt (loc, GOTO_EXPR, *label);
3491 *do_subtree = 0;
3492 return NULL_TREE;
3495 /* Statements that do not require recursion. */
3496 case DECL_EXPR:
3497 case BREAK_STMT:
3498 case GOTO_EXPR:
3499 case LABEL_EXPR:
3500 case CASE_LABEL_EXPR:
3501 case ASM_EXPR:
3502 /* These must break recursion. */
3503 case FOR_STMT:
3504 case WHILE_STMT:
3505 case DO_STMT:
3506 *do_subtree = 0;
3507 return NULL_TREE;
3511 /* Tree walk callback to analyze, register and pre-process statements that
3512 contain await expressions. */
3514 static tree
3515 await_statement_walker (tree *stmt, int *do_subtree, void *d)
3517 tree res = NULL_TREE;
3518 susp_frame_data *awpts = (susp_frame_data *) d;
3520 /* Process a statement at a time. */
3521 if (TREE_CODE (*stmt) == BIND_EXPR)
3523 /* For conditional expressions, we might wish to add an artificial var
3524 to their containing bind expr. */
3525 vec_safe_push (awpts->bind_stack, *stmt);
3526 /* We might need to insert a new bind expression, and want to link it
3527 into the correct scope, so keep a note of the current block scope. */
3528 tree blk = BIND_EXPR_BLOCK (*stmt);
3529 vec_safe_push (awpts->block_stack, blk);
3530 res = cp_walk_tree (&BIND_EXPR_BODY (*stmt), await_statement_walker,
3531 d, NULL);
3532 awpts->block_stack->pop ();
3533 awpts->bind_stack->pop ();
3534 *do_subtree = 0; /* Done subtrees. */
3535 return res;
3537 else if (TREE_CODE (*stmt) == STATEMENT_LIST)
3539 for (tree &s : tsi_range (*stmt))
3541 res = cp_walk_tree (&s, await_statement_walker,
3542 d, NULL);
3543 if (res)
3544 return res;
3546 *do_subtree = 0; /* Done subtrees. */
3547 return NULL_TREE;
3550 /* We have something to be handled as a single statement. */
3551 bool has_cleanup_wrapper = TREE_CODE (*stmt) == CLEANUP_POINT_EXPR;
3552 hash_set<tree> visited;
3553 awpts->saw_awaits = 0;
3554 hash_set<tree> truth_aoif_to_expand;
3555 awpts->truth_aoif_to_expand = &truth_aoif_to_expand;
3556 awpts->needs_truth_if_exp = false;
3557 awpts->has_awaiter_init = false;
3558 tree expr = *stmt;
3559 if (has_cleanup_wrapper)
3560 expr = TREE_OPERAND (expr, 0);
3561 STRIP_NOPS (expr);
3563 if (STATEMENT_CLASS_P (expr))
3564 switch (TREE_CODE (expr))
3566 /* Unless it's a special case, just walk the subtrees as usual. */
3567 default: return NULL_TREE;
3569 /* When we have a conditional expression, which contains one or more
3570 await expressions, we have to break the condition out into a
3571 regular statement so that the control flow introduced by the await
3572 transforms can be implemented. */
3573 case IF_STMT:
3575 /* Transform 'if (cond with awaits) then stmt1 else stmt2' into
3576 bool cond = cond with awaits.
3577 if (cond) then stmt1 else stmt2. */
3578 tree if_stmt = *stmt;
3579 /* We treat the condition as if it was a stand-alone statement,
3580 to see if there are any await expressions which will be analyzed
3581 and registered. */
3582 if ((res = cp_walk_tree (&IF_COND (if_stmt),
3583 analyze_expression_awaits, d, &visited)))
3584 return res;
3585 if (!awpts->saw_awaits)
3586 return NULL_TREE; /* Nothing special to do here. */
3588 gcc_checking_assert (!awpts->bind_stack->is_empty());
3589 tree& bind_expr = awpts->bind_stack->last ();
3590 tree newvar = add_var_to_bind (bind_expr, boolean_type_node,
3591 "ifcd", awpts->cond_number++);
3592 tree insert_list = push_stmt_list ();
3593 tree cond_inner = IF_COND (if_stmt);
3594 if (TREE_CODE (cond_inner) == CLEANUP_POINT_EXPR)
3595 cond_inner = TREE_OPERAND (cond_inner, 0);
3596 add_decl_expr (newvar);
3597 location_t sloc = EXPR_LOCATION (IF_COND (if_stmt));
3598 /* We want to initialize the new variable with the expression
3599 that contains the await(s) and potentially also needs to
3600 have truth_if expressions expanded. */
3601 tree new_s = build2_loc (sloc, MODIFY_EXPR, boolean_type_node,
3602 newvar, cond_inner);
3603 finish_expr_stmt (new_s);
3604 IF_COND (if_stmt) = newvar;
3605 add_stmt (if_stmt);
3606 *stmt = pop_stmt_list (insert_list);
3607 /* So now walk the new statement list. */
3608 res = cp_walk_tree (stmt, await_statement_walker, d, NULL);
3609 *do_subtree = 0; /* Done subtrees. */
3610 return res;
3612 break;
3613 case FOR_STMT:
3615 /* for loops only need special treatment if the condition or the
3616 iteration expression contain a co_await. */
3617 tree for_stmt = *stmt;
3618 /* Sanity check. */
3619 if ((res = cp_walk_tree (&FOR_INIT_STMT (for_stmt),
3620 analyze_expression_awaits, d, &visited)))
3621 return res;
3622 gcc_checking_assert (!awpts->saw_awaits);
3624 if ((res = cp_walk_tree (&FOR_COND (for_stmt),
3625 analyze_expression_awaits, d, &visited)))
3626 return res;
3627 bool for_cond_await = awpts->saw_awaits != 0;
3628 unsigned save_awaits = awpts->saw_awaits;
3630 if ((res = cp_walk_tree (&FOR_EXPR (for_stmt),
3631 analyze_expression_awaits, d, &visited)))
3632 return res;
3633 bool for_expr_await = awpts->saw_awaits > save_awaits;
3635 /* If the condition has an await, then we will need to rewrite the
3636 loop as
3637 for (init expression;true;iteration expression) {
3638 condition = await expression;
3639 if (condition)
3640 break;
3644 if (for_cond_await)
3646 tree insert_list = push_stmt_list ();
3647 /* This will be expanded when the revised body is handled. */
3648 coro_build_add_if_not_cond_break (FOR_COND (for_stmt));
3649 /* .. add the original for body. */
3650 add_stmt (FOR_BODY (for_stmt));
3651 /* To make the new for body. */
3652 FOR_BODY (for_stmt) = pop_stmt_list (insert_list);
3653 FOR_COND (for_stmt) = boolean_true_node;
3655 /* If the iteration expression has an await, it's a bit more
3656 tricky.
3657 for (init expression;condition;) {
3659 iteration_expr_label:
3660 iteration expression with await;
3662 but, then we will need to re-write any continue statements into
3663 'goto iteration_expr_label:'.
3665 if (for_expr_await)
3667 location_t sloc = EXPR_LOCATION (FOR_EXPR (for_stmt));
3668 tree insert_list = push_stmt_list ();
3669 /* The original for body. */
3670 add_stmt (FOR_BODY (for_stmt));
3671 char *buf = xasprintf ("for.iter.expr.%u", awpts->cond_number++);
3672 tree it_expr_label
3673 = create_named_label_with_ctx (sloc, buf, NULL_TREE);
3674 free (buf);
3675 add_stmt (build_stmt (sloc, LABEL_EXPR, it_expr_label));
3676 add_stmt (FOR_EXPR (for_stmt));
3677 FOR_EXPR (for_stmt) = NULL_TREE;
3678 FOR_BODY (for_stmt) = pop_stmt_list (insert_list);
3679 /* rewrite continue statements to goto label. */
3680 hash_set<tree> visited_continue;
3681 if ((res = cp_walk_tree (&FOR_BODY (for_stmt),
3682 replace_continue, &it_expr_label, &visited_continue)))
3683 return res;
3686 /* So now walk the body statement (list), if there were no await
3687 expressions, then this handles the original body - and either
3688 way we will have finished with this statement. */
3689 res = cp_walk_tree (&FOR_BODY (for_stmt),
3690 await_statement_walker, d, NULL);
3691 *do_subtree = 0; /* Done subtrees. */
3692 return res;
3694 break;
3695 case WHILE_STMT:
3697 /* We turn 'while (cond with awaits) stmt' into
3698 while (true) {
3699 if (!(cond with awaits))
3700 break;
3701 stmt..
3702 } */
3703 tree while_stmt = *stmt;
3704 if ((res = cp_walk_tree (&WHILE_COND (while_stmt),
3705 analyze_expression_awaits, d, &visited)))
3706 return res;
3707 if (!awpts->saw_awaits)
3708 return NULL_TREE; /* Nothing special to do here. */
3710 tree insert_list = push_stmt_list ();
3711 coro_build_add_if_not_cond_break (WHILE_COND (while_stmt));
3712 /* The original while body. */
3713 add_stmt (WHILE_BODY (while_stmt));
3714 /* The new while body. */
3715 WHILE_BODY (while_stmt) = pop_stmt_list (insert_list);
3716 WHILE_COND (while_stmt) = boolean_true_node;
3717 /* So now walk the new statement list. */
3718 res = cp_walk_tree (&WHILE_BODY (while_stmt),
3719 await_statement_walker, d, NULL);
3720 *do_subtree = 0; /* Done subtrees. */
3721 return res;
3723 break;
3724 case DO_STMT:
3726 /* We turn do stmt while (cond with awaits) into:
3727 do {
3728 stmt..
3729 if (!(cond with awaits))
3730 break;
3731 } while (true); */
3732 tree do_stmt = *stmt;
3733 if ((res = cp_walk_tree (&DO_COND (do_stmt),
3734 analyze_expression_awaits, d, &visited)))
3735 return res;
3736 if (!awpts->saw_awaits)
3737 return NULL_TREE; /* Nothing special to do here. */
3739 tree insert_list = push_stmt_list ();
3740 /* The original do stmt body. */
3741 add_stmt (DO_BODY (do_stmt));
3742 coro_build_add_if_not_cond_break (DO_COND (do_stmt));
3743 /* The new while body. */
3744 DO_BODY (do_stmt) = pop_stmt_list (insert_list);
3745 DO_COND (do_stmt) = boolean_true_node;
3746 /* So now walk the new statement list. */
3747 res = cp_walk_tree (&DO_BODY (do_stmt), await_statement_walker,
3748 d, NULL);
3749 *do_subtree = 0; /* Done subtrees. */
3750 return res;
3752 break;
3753 case SWITCH_STMT:
3755 /* We turn 'switch (cond with awaits) stmt' into
3756 switch_type cond = cond with awaits
3757 switch (cond) stmt. */
3758 tree sw_stmt = *stmt;
3759 if ((res = cp_walk_tree (&SWITCH_STMT_COND (sw_stmt),
3760 analyze_expression_awaits, d, &visited)))
3761 return res;
3762 if (!awpts->saw_awaits)
3763 return NULL_TREE; /* Nothing special to do here. */
3765 gcc_checking_assert (!awpts->bind_stack->is_empty());
3766 /* Build a variable to hold the condition, this will be
3767 included in the frame as a local var. */
3768 tree& bind_expr = awpts->bind_stack->last ();
3769 tree sw_type = SWITCH_STMT_TYPE (sw_stmt);
3770 tree newvar = add_var_to_bind (bind_expr, sw_type, "swch",
3771 awpts->cond_number++);
3772 tree insert_list = push_stmt_list ();
3773 add_decl_expr (newvar);
3775 tree cond_inner = SWITCH_STMT_COND (sw_stmt);
3776 if (TREE_CODE (cond_inner) == CLEANUP_POINT_EXPR)
3777 cond_inner = TREE_OPERAND (cond_inner, 0);
3778 location_t sloc = EXPR_LOCATION (SWITCH_STMT_COND (sw_stmt));
3779 tree new_s = build2_loc (sloc, INIT_EXPR, sw_type, newvar,
3780 cond_inner);
3781 finish_expr_stmt (new_s);
3782 SWITCH_STMT_COND (sw_stmt) = newvar;
3783 /* Now add the switch statement with the condition re-
3784 written to use the local var. */
3785 add_stmt (sw_stmt);
3786 *stmt = pop_stmt_list (insert_list);
3787 /* Process the expanded list. */
3788 res = cp_walk_tree (stmt, await_statement_walker,
3789 d, NULL);
3790 *do_subtree = 0; /* Done subtrees. */
3791 return res;
3793 break;
3794 case CO_RETURN_EXPR:
3796 /* Expand the co_return as per [stmt.return.coroutine]
3797 - for co_return;
3798 { p.return_void (); goto final_suspend; }
3799 - for co_return [void expr];
3800 { expr; p.return_void(); goto final_suspend;}
3801 - for co_return [non void expr];
3802 { p.return_value(expr); goto final_suspend; } */
3803 if ((res = cp_walk_tree (stmt, analyze_expression_awaits,
3804 d, &visited)))
3805 return res;
3806 location_t loc = EXPR_LOCATION (expr);
3807 tree call = TREE_OPERAND (expr, 1);
3808 expr = TREE_OPERAND (expr, 0);
3809 tree ret_list = push_stmt_list ();
3810 /* [stmt.return.coroutine], 2.2
3811 If expr is present and void, it is placed immediately before
3812 the call for return_void; */
3813 tree *maybe_await_stmt = NULL;
3814 if (expr && VOID_TYPE_P (TREE_TYPE (expr)))
3816 finish_expr_stmt (expr);
3817 /* If the return argument was a void expression, then any
3818 awaits must be contained in that. */
3819 maybe_await_stmt = tsi_stmt_ptr (tsi_last (ret_list));
3821 /* Insert p.return_{void,value(expr)}. */
3822 finish_expr_stmt (call);
3823 /* Absent a return of a void expression, any awaits must be in
3824 the parameter to return_value(). */
3825 if (!maybe_await_stmt)
3826 maybe_await_stmt = tsi_stmt_ptr (tsi_last (ret_list));
3827 expr = build1_loc (loc, GOTO_EXPR, void_type_node, awpts->fs_label);
3828 finish_expr_stmt (expr);
3829 *stmt = pop_stmt_list (ret_list);
3830 /* Once this is complete, we will have processed subtrees. */
3831 *do_subtree = 0;
3832 if (awpts->saw_awaits)
3834 gcc_checking_assert (maybe_await_stmt);
3835 res = cp_walk_tree (maybe_await_stmt, await_statement_walker,
3836 d, NULL);
3837 if (res)
3838 return res;
3840 return NULL_TREE; /* Done. */
3842 break;
3844 else if (EXPR_P (expr))
3846 if ((res = cp_walk_tree (stmt, analyze_expression_awaits, d, &visited)))
3847 return res;
3848 *do_subtree = 0; /* Done subtrees. */
3849 if (!awpts->saw_awaits)
3850 return NULL_TREE; /* Nothing special to do here. */
3852 if (awpts->needs_truth_if_exp)
3854 /* If a truth-and/or-if expression has an await expression in the
3855 conditionally-taken branch, then it must be rewritten into a
3856 regular conditional. */
3857 truth_if_transform xf = {stmt, NULL_TREE, &truth_aoif_to_expand};
3858 if ((res = cp_walk_tree (stmt, expand_one_truth_if, &xf, NULL)))
3859 return res;
3861 /* Process this statement, which contains at least one await expression
3862 to 'promote' temporary values to a coroutine frame slot. */
3863 return maybe_promote_temps (stmt, d);
3865 /* Continue recursion, if needed. */
3866 return res;
3869 /* For figuring out what param usage we have. */
3871 struct param_frame_data
3873 tree *field_list;
3874 hash_map<tree, param_info> *param_uses;
3875 hash_set<tree *> *visited;
3876 location_t loc;
3877 bool param_seen;
3880 /* A tree-walk callback that records the use of parameters (to allow for
3881 optimizations where handling unused parameters may be omitted). */
3883 static tree
3884 register_param_uses (tree *stmt, int *do_subtree ATTRIBUTE_UNUSED, void *d)
3886 param_frame_data *data = (param_frame_data *) d;
3888 /* For lambda closure content, we have to look specifically. */
3889 if (TREE_CODE (*stmt) == VAR_DECL && DECL_HAS_VALUE_EXPR_P (*stmt))
3891 tree t = DECL_VALUE_EXPR (*stmt);
3892 return cp_walk_tree (&t, register_param_uses, d, NULL);
3895 if (TREE_CODE (*stmt) != PARM_DECL)
3896 return NULL_TREE;
3898 /* If we already saw the containing expression, then we're done. */
3899 if (data->visited->add (stmt))
3900 return NULL_TREE;
3902 bool existed;
3903 param_info &parm = data->param_uses->get_or_insert (*stmt, &existed);
3904 gcc_checking_assert (existed);
3906 if (!parm.body_uses)
3908 vec_alloc (parm.body_uses, 4);
3909 parm.body_uses->quick_push (stmt);
3910 data->param_seen = true;
3912 else
3913 parm.body_uses->safe_push (stmt);
3915 return NULL_TREE;
3918 /* Small helper for the repetitive task of adding a new field to the coro
3919 frame type. */
3921 static tree
3922 coro_make_frame_entry (tree *field_list, const char *name, tree fld_type,
3923 location_t loc)
3925 tree id = get_identifier (name);
3926 tree decl = build_decl (loc, FIELD_DECL, id, fld_type);
3927 DECL_CHAIN (decl) = *field_list;
3928 *field_list = decl;
3929 return id;
3932 /* For recording local variable usage. */
3934 struct local_vars_frame_data
3936 tree *field_list;
3937 hash_map<tree, local_var_info> *local_var_uses;
3938 unsigned int nest_depth, bind_indx;
3939 location_t loc;
3940 bool saw_capture;
3941 bool local_var_seen;
3944 /* A tree-walk callback that processes one bind expression noting local
3945 variables, and making a coroutine frame slot available for those that
3946 need it, so that they can be 'promoted' across suspension points. */
3948 static tree
3949 register_local_var_uses (tree *stmt, int *do_subtree, void *d)
3951 local_vars_frame_data *lvd = (local_vars_frame_data *) d;
3953 /* As we enter a bind expression - record the vars there and then recurse.
3954 As we exit drop the nest depth.
3955 The bind index is a growing count of how many bind indices we've seen.
3956 We build a space in the frame for each local var. */
3958 if (TREE_CODE (*stmt) == BIND_EXPR)
3960 lvd->bind_indx++;
3961 lvd->nest_depth++;
3962 tree lvar;
3963 for (lvar = BIND_EXPR_VARS (*stmt); lvar != NULL;
3964 lvar = DECL_CHAIN (lvar))
3966 bool existed;
3967 local_var_info &local_var
3968 = lvd->local_var_uses->get_or_insert (lvar, &existed);
3969 gcc_checking_assert (!existed);
3970 local_var.def_loc = DECL_SOURCE_LOCATION (lvar);
3971 tree lvtype = TREE_TYPE (lvar);
3972 local_var.frame_type = lvtype;
3973 local_var.field_idx = local_var.field_id = NULL_TREE;
3975 /* Make sure that we only present vars to the tests below. */
3976 if (TREE_CODE (lvar) == TYPE_DECL
3977 || TREE_CODE (lvar) == NAMESPACE_DECL)
3978 continue;
3980 /* We don't move static vars into the frame. */
3981 local_var.is_static = TREE_STATIC (lvar);
3982 if (local_var.is_static)
3983 continue;
3985 lvd->local_var_seen = true;
3986 /* If this var is a lambda capture proxy, we want to leave it alone,
3987 and later rewrite the DECL_VALUE_EXPR to indirect through the
3988 frame copy of the pointer to the lambda closure object. */
3989 local_var.is_lambda_capture = is_capture_proxy (lvar);
3990 if (local_var.is_lambda_capture)
3991 continue;
3993 /* If a variable has a value expression, then that's what needs
3994 to be processed. */
3995 local_var.has_value_expr_p = DECL_HAS_VALUE_EXPR_P (lvar);
3996 if (local_var.has_value_expr_p)
3997 continue;
3999 /* Make names depth+index unique, so that we can support nested
4000 scopes with identically named locals. */
4001 tree lvname = DECL_NAME (lvar);
4002 char *buf;
4003 if (lvname != NULL_TREE)
4004 buf = xasprintf ("__%s.%u.%u", IDENTIFIER_POINTER (lvname),
4005 lvd->nest_depth, lvd->bind_indx);
4006 else
4007 buf = xasprintf ("_D%u.%u.%u", DECL_UID (lvar), lvd->nest_depth,
4008 lvd->bind_indx);
4009 /* TODO: Figure out if we should build a local type that has any
4010 excess alignment or size from the original decl. */
4011 local_var.field_id
4012 = coro_make_frame_entry (lvd->field_list, buf, lvtype, lvd->loc);
4013 free (buf);
4014 /* We don't walk any of the local var sub-trees, they won't contain
4015 any bind exprs. */
4017 cp_walk_tree (&BIND_EXPR_BODY (*stmt), register_local_var_uses, d, NULL);
4018 *do_subtree = 0; /* We've done this. */
4019 lvd->nest_depth--;
4021 return NULL_TREE;
4024 /* Build, return FUNCTION_DECL node based on ORIG with a type FN_TYPE which has
4025 a single argument of type CORO_FRAME_PTR. Build the actor function if
4026 ACTOR_P is true, otherwise the destroy. */
4028 static tree
4029 coro_build_actor_or_destroy_function (tree orig, tree fn_type,
4030 tree coro_frame_ptr, bool actor_p)
4032 location_t loc = DECL_SOURCE_LOCATION (orig);
4033 tree fn
4034 = build_lang_decl (FUNCTION_DECL, copy_node (DECL_NAME (orig)), fn_type);
4036 /* Allow for locating the ramp (original) function from this one. */
4037 if (!to_ramp)
4038 to_ramp = hash_map<tree, tree>::create_ggc (10);
4039 to_ramp->put (fn, orig);
4041 DECL_CONTEXT (fn) = DECL_CONTEXT (orig);
4042 DECL_SOURCE_LOCATION (fn) = loc;
4043 DECL_ARTIFICIAL (fn) = true;
4044 DECL_INITIAL (fn) = error_mark_node;
4046 tree id = get_identifier ("frame_ptr");
4047 tree fp = build_lang_decl (PARM_DECL, id, coro_frame_ptr);
4048 DECL_CONTEXT (fp) = fn;
4049 DECL_ARG_TYPE (fp) = type_passed_as (coro_frame_ptr);
4050 DECL_ARGUMENTS (fn) = fp;
4052 /* Copy selected attributes from the original function. */
4053 TREE_USED (fn) = TREE_USED (orig);
4054 if (DECL_SECTION_NAME (orig))
4055 set_decl_section_name (fn, orig);
4056 /* Copy any alignment that the FE added. */
4057 if (DECL_ALIGN (orig))
4058 SET_DECL_ALIGN (fn, DECL_ALIGN (orig));
4059 /* Copy any alignment the user added. */
4060 DECL_USER_ALIGN (fn) = DECL_USER_ALIGN (orig);
4061 /* Apply attributes from the original fn. */
4062 DECL_ATTRIBUTES (fn) = copy_list (DECL_ATTRIBUTES (orig));
4064 /* A void return. */
4065 tree resdecl = build_decl (loc, RESULT_DECL, 0, void_type_node);
4066 DECL_CONTEXT (resdecl) = fn;
4067 DECL_ARTIFICIAL (resdecl) = 1;
4068 DECL_IGNORED_P (resdecl) = 1;
4069 DECL_RESULT (fn) = resdecl;
4071 /* This is a coroutine component. */
4072 DECL_COROUTINE_P (fn) = 1;
4074 /* Set up a means to find out if a decl is one of the helpers and, if so,
4075 which one. */
4076 if (coroutine_info *info = get_coroutine_info (orig))
4078 gcc_checking_assert ((actor_p && info->actor_decl == NULL_TREE)
4079 || info->destroy_decl == NULL_TREE);
4080 if (actor_p)
4081 info->actor_decl = fn;
4082 else
4083 info->destroy_decl = fn;
4085 return fn;
4088 /* Re-write the body as per [dcl.fct.def.coroutine] / 5. */
4090 static tree
4091 coro_rewrite_function_body (location_t fn_start, tree fnbody, tree orig,
4092 tree resume_fn_ptr_type, tree& resume_fn_field,
4093 tree& resume_idx_field, tree& fs_label)
4095 /* This will be our new outer scope. */
4096 tree update_body = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
4097 tree top_block = make_node (BLOCK);
4098 BIND_EXPR_BLOCK (update_body) = top_block;
4099 BIND_EXPR_BODY (update_body) = push_stmt_list ();
4101 /* If the function has a top level bind expression, then connect that
4102 after first making sure we give it a new block. */
4103 tree first = expr_first (fnbody);
4104 if (first && TREE_CODE (first) == BIND_EXPR)
4106 tree block = BIND_EXPR_BLOCK (first);
4107 gcc_checking_assert (block);
4108 gcc_checking_assert (BLOCK_SUPERCONTEXT (block) == NULL_TREE);
4109 gcc_checking_assert (BLOCK_CHAIN (block) == NULL_TREE);
4110 /* Replace the top block to avoid issues with locations for args
4111 appearing to be in a non-existent place. */
4112 tree replace_blk = make_node (BLOCK);
4113 BLOCK_VARS (replace_blk) = BLOCK_VARS (block);
4114 BLOCK_SUBBLOCKS (replace_blk) = BLOCK_SUBBLOCKS (block);
4115 for (tree b = BLOCK_SUBBLOCKS (replace_blk); b; b = BLOCK_CHAIN (b))
4116 BLOCK_SUPERCONTEXT (b) = replace_blk;
4117 BIND_EXPR_BLOCK (first) = replace_blk;
4118 /* The top block has one child, so far, and we have now got a
4119 superblock. */
4120 BLOCK_SUPERCONTEXT (replace_blk) = top_block;
4121 BLOCK_SUBBLOCKS (top_block) = replace_blk;
4124 /* Wrap the function body in a try {} catch (...) {} block, if exceptions
4125 are enabled. */
4126 tree promise = get_coroutine_promise_proxy (orig);
4127 tree var_list = NULL_TREE;
4128 tree initial_await = build_init_or_final_await (fn_start, false);
4130 /* [stmt.return.coroutine] / 3
4131 If p.return_void() is a valid expression, flowing off the end of a
4132 coroutine is equivalent to a co_return with no operand; otherwise
4133 flowing off the end of a coroutine results in undefined behavior. */
4134 tree return_void
4135 = get_coroutine_return_void_expr (current_function_decl, fn_start, false);
4137 /* We will need to be able to set the resume function pointer to nullptr
4138 to signal that the coroutine is 'done'. */
4139 resume_fn_field
4140 = build_lang_decl (VAR_DECL, get_identifier ("resume.fn.ptr.proxy"),
4141 resume_fn_ptr_type);
4142 DECL_ARTIFICIAL (resume_fn_field) = true;
4143 tree zero_resume
4144 = build1 (CONVERT_EXPR, resume_fn_ptr_type, integer_zero_node);
4145 zero_resume
4146 = build2 (INIT_EXPR, resume_fn_ptr_type, resume_fn_field, zero_resume);
4147 /* Likewise, the resume index needs to be reset. */
4148 resume_idx_field
4149 = build_lang_decl (VAR_DECL, get_identifier ("resume.index.proxy"),
4150 short_unsigned_type_node);
4151 DECL_ARTIFICIAL (resume_idx_field) = true;
4152 tree zero_resume_idx = build_int_cst (short_unsigned_type_node, 0);
4153 zero_resume_idx = build2 (INIT_EXPR, short_unsigned_type_node,
4154 resume_idx_field, zero_resume_idx);
4156 if (flag_exceptions)
4158 /* Build promise.unhandled_exception(); */
4159 tree ueh
4160 = coro_build_promise_expression (current_function_decl, promise,
4161 coro_unhandled_exception_identifier,
4162 fn_start, NULL, /*musthave=*/true);
4163 /* Create and initialize the initial-await-resume-called variable per
4164 [dcl.fct.def.coroutine] / 5.3. */
4165 tree i_a_r_c = build_lang_decl (VAR_DECL, get_identifier ("i_a_r_c"),
4166 boolean_type_node);
4167 DECL_ARTIFICIAL (i_a_r_c) = true;
4168 DECL_CHAIN (i_a_r_c) = var_list;
4169 var_list = i_a_r_c;
4170 DECL_INITIAL (i_a_r_c) = boolean_false_node;
4171 add_decl_expr (i_a_r_c);
4172 /* Start the try-catch. */
4173 tree tcb = build_stmt (fn_start, TRY_BLOCK, NULL_TREE, NULL_TREE);
4174 add_stmt (tcb);
4175 TRY_STMTS (tcb) = push_stmt_list ();
4176 if (initial_await != error_mark_node)
4178 /* Build a compound expression that sets the
4179 initial-await-resume-called variable true and then calls the
4180 initial suspend expression await resume. */
4181 tree vec = TREE_OPERAND (initial_await, 3);
4182 tree aw_r = TREE_VEC_ELT (vec, 2);
4183 tree update = build2 (MODIFY_EXPR, boolean_type_node, i_a_r_c,
4184 boolean_true_node);
4185 aw_r = cp_build_compound_expr (update, aw_r, tf_warning_or_error);
4186 TREE_VEC_ELT (vec, 2) = aw_r;
4188 /* Add the initial await to the start of the user-authored function. */
4189 finish_expr_stmt (initial_await);
4190 /* Append the original function body. */
4191 add_stmt (fnbody);
4192 if (return_void)
4193 add_stmt (return_void);
4194 TRY_STMTS (tcb) = pop_stmt_list (TRY_STMTS (tcb));
4195 TRY_HANDLERS (tcb) = push_stmt_list ();
4196 /* Mimic what the parser does for the catch. */
4197 tree handler = begin_handler ();
4198 finish_handler_parms (NULL_TREE, handler); /* catch (...) */
4200 /* Get the initial await resume called value. */
4201 tree not_iarc_if = begin_if_stmt ();
4202 tree not_iarc = build1_loc (fn_start, TRUTH_NOT_EXPR,
4203 boolean_type_node, i_a_r_c);
4204 finish_if_stmt_cond (not_iarc, not_iarc_if);
4205 /* If the initial await resume called value is false, rethrow... */
4206 tree rethrow = build_throw (fn_start, NULL_TREE);
4207 suppress_warning (rethrow);
4208 finish_expr_stmt (rethrow);
4209 finish_then_clause (not_iarc_if);
4210 tree iarc_scope = IF_SCOPE (not_iarc_if);
4211 IF_SCOPE (not_iarc_if) = NULL;
4212 not_iarc_if = do_poplevel (iarc_scope);
4213 add_stmt (not_iarc_if);
4214 /* ... else call the promise unhandled exception method
4215 but first we set done = true and the resume index to 0.
4216 If the unhandled exception method returns, then we continue
4217 to the final await expression (which duplicates the clearing of
4218 the field). */
4219 finish_expr_stmt (zero_resume);
4220 finish_expr_stmt (zero_resume_idx);
4221 ueh = maybe_cleanup_point_expr_void (ueh);
4222 add_stmt (ueh);
4223 finish_handler (handler);
4224 TRY_HANDLERS (tcb) = pop_stmt_list (TRY_HANDLERS (tcb));
4226 else
4228 if (pedantic)
4230 /* We still try to look for the promise method and warn if it's not
4231 present. */
4232 tree ueh_meth
4233 = lookup_promise_method (orig, coro_unhandled_exception_identifier,
4234 fn_start, /*musthave=*/false);
4235 if (!ueh_meth || ueh_meth == error_mark_node)
4236 warning_at (fn_start, 0, "no member named %qE in %qT",
4237 coro_unhandled_exception_identifier,
4238 get_coroutine_promise_type (orig));
4240 /* Else we don't check and don't care if the method is missing..
4241 just add the initial suspend, function and return. */
4242 finish_expr_stmt (initial_await);
4243 /* Append the original function body. */
4244 add_stmt (fnbody);
4245 if (return_void)
4246 add_stmt (return_void);
4249 /* co_return branches to the final_suspend label, so declare that now. */
4250 fs_label
4251 = create_named_label_with_ctx (fn_start, "final.suspend", NULL_TREE);
4252 add_stmt (build_stmt (fn_start, LABEL_EXPR, fs_label));
4254 /* Before entering the final suspend point, we signal that this point has
4255 been reached by setting the resume function pointer to zero (this is
4256 what the 'done()' builtin tests) as per the current ABI. */
4257 finish_expr_stmt (zero_resume);
4258 finish_expr_stmt (build_init_or_final_await (fn_start, true));
4259 BIND_EXPR_BODY (update_body) = pop_stmt_list (BIND_EXPR_BODY (update_body));
4260 BIND_EXPR_VARS (update_body) = nreverse (var_list);
4261 BLOCK_VARS (top_block) = BIND_EXPR_VARS (update_body);
4263 return update_body;
4266 /* Here we:
4267 a) Check that the function and promise type are valid for a
4268 coroutine.
4269 b) Carry out the initial morph to create the skeleton of the
4270 coroutine ramp function and the rewritten body.
4272 Assumptions.
4274 1. We only hit this code once all dependencies are resolved.
4275 2. The function body will be either a bind expr or a statement list
4276 3. That cfun and current_function_decl are valid for the case we're
4277 expanding.
4278 4. 'input_location' will be of the final brace for the function.
4280 We do something like this:
4281 declare a dummy coro frame.
4282 struct _R_frame {
4283 using handle_type = coro::coroutine_handle<coro1::promise_type>;
4284 void (*__resume)(_R_frame *);
4285 void (*__destroy)(_R_frame *);
4286 coro1::promise_type __p;
4287 bool frame_needs_free; free the coro frame mem if set.
4288 bool i_a_r_c; [dcl.fct.def.coroutine] / 5.3
4289 short __resume_at;
4290 handle_type self_handle;
4291 (maybe) parameter copies.
4292 (maybe) local variables saved (including awaitables)
4293 (maybe) trailing space.
4294 }; */
4296 bool
4297 morph_fn_to_coro (tree orig, tree *resumer, tree *destroyer)
4299 gcc_checking_assert (orig && TREE_CODE (orig) == FUNCTION_DECL);
4301 *resumer = error_mark_node;
4302 *destroyer = error_mark_node;
4303 if (!coro_function_valid_p (orig))
4305 /* For early errors, we do not want a diagnostic about the missing
4306 ramp return value, since the user cannot fix this - a 'return' is
4307 not allowed in a coroutine. */
4308 suppress_warning (orig, OPT_Wreturn_type);
4309 /* Discard the body, we can't process it further. */
4310 pop_stmt_list (DECL_SAVED_TREE (orig));
4311 DECL_SAVED_TREE (orig) = push_stmt_list ();
4312 return false;
4315 /* We can't validly get here with an empty statement list, since there's no
4316 way for the FE to decide it's a coroutine in the absence of any code. */
4317 tree fnbody = pop_stmt_list (DECL_SAVED_TREE (orig));
4318 gcc_checking_assert (fnbody != NULL_TREE);
4320 /* We don't have the locus of the opening brace - it's filled in later (and
4321 there doesn't really seem to be any easy way to get at it).
4322 The closing brace is assumed to be input_location. */
4323 location_t fn_start = DECL_SOURCE_LOCATION (orig);
4324 gcc_rich_location fn_start_loc (fn_start);
4326 /* Initial processing of the function-body.
4327 If we have no expressions or just an error then punt. */
4328 tree body_start = expr_first (fnbody);
4329 if (body_start == NULL_TREE || body_start == error_mark_node)
4331 DECL_SAVED_TREE (orig) = push_stmt_list ();
4332 append_to_statement_list (fnbody, &DECL_SAVED_TREE (orig));
4333 /* Suppress warnings about the missing return value. */
4334 suppress_warning (orig, OPT_Wreturn_type);
4335 return false;
4338 /* So, we've tied off the original user-authored body in fn_body.
4340 Start the replacement synthesized ramp body as newbody.
4341 If we encounter a fatal error we might return a now-empty body.
4343 Note, the returned ramp body is not 'popped', to be compatible with
4344 the way that decl.c handles regular functions, the scope pop is done
4345 in the caller. */
4347 tree newbody = push_stmt_list ();
4348 DECL_SAVED_TREE (orig) = newbody;
4350 /* If our original body is noexcept, then that's what we apply to our
4351 generated ramp, transfer any MUST_NOT_THOW_EXPR to that. */
4352 bool is_noexcept = TREE_CODE (body_start) == MUST_NOT_THROW_EXPR;
4353 if (is_noexcept)
4355 /* The function body we will continue with is the single operand to
4356 the must-not-throw. */
4357 fnbody = TREE_OPERAND (body_start, 0);
4358 /* Transfer the must-not-throw to the ramp body. */
4359 add_stmt (body_start);
4360 /* Re-start the ramp as must-not-throw. */
4361 TREE_OPERAND (body_start, 0) = push_stmt_list ();
4364 /* If the original function has a return value with a non-trivial DTOR
4365 and the body contains a var with a DTOR that might throw, the decl is
4366 marked "throwing_cleanup".
4367 We do not [in the ramp, which is synthesised here], use any body var
4368 types with DTORs that might throw.
4369 The original body is transformed into the actor function which only
4370 contains void returns, and is also wrapped in a try-catch block.
4371 So (a) the 'throwing_cleanup' is not correct for the ramp and (b) we do
4372 not need to transfer it to the actor which only contains void returns. */
4373 cp_function_chain->throwing_cleanup = false;
4375 /* Create the coro frame type, as far as it can be known at this stage.
4376 1. Types we already know. */
4378 tree fn_return_type = TREE_TYPE (TREE_TYPE (orig));
4379 tree handle_type = get_coroutine_handle_type (orig);
4380 tree promise_type = get_coroutine_promise_type (orig);
4382 /* 2. Types we need to define or look up. */
4384 tree fr_name = get_fn_local_identifier (orig, "frame");
4385 tree coro_frame_type = xref_tag (record_type, fr_name);
4386 DECL_CONTEXT (TYPE_NAME (coro_frame_type)) = current_scope ();
4387 tree coro_frame_ptr = build_pointer_type (coro_frame_type);
4388 tree act_des_fn_type
4389 = build_function_type_list (void_type_node, coro_frame_ptr, NULL_TREE);
4390 tree act_des_fn_ptr = build_pointer_type (act_des_fn_type);
4392 /* Declare the actor and destroyer function. */
4393 tree actor = coro_build_actor_or_destroy_function (orig, act_des_fn_type,
4394 coro_frame_ptr, true);
4395 tree destroy = coro_build_actor_or_destroy_function (orig, act_des_fn_type,
4396 coro_frame_ptr, false);
4398 /* Construct the wrapped function body; we will analyze this to determine
4399 the requirements for the coroutine frame. */
4401 tree resume_fn_field = NULL_TREE;
4402 tree resume_idx_field = NULL_TREE;
4403 tree fs_label = NULL_TREE;
4404 fnbody = coro_rewrite_function_body (fn_start, fnbody, orig,
4405 act_des_fn_ptr, resume_fn_field,
4406 resume_idx_field, fs_label);
4407 /* Build our dummy coro frame layout. */
4408 coro_frame_type = begin_class_definition (coro_frame_type);
4410 tree field_list = NULL_TREE;
4411 tree resume_name
4412 = coro_make_frame_entry (&field_list, "__resume",
4413 act_des_fn_ptr, fn_start);
4414 tree destroy_name
4415 = coro_make_frame_entry (&field_list, "__destroy",
4416 act_des_fn_ptr, fn_start);
4417 tree promise_name
4418 = coro_make_frame_entry (&field_list, "__p", promise_type, fn_start);
4419 tree fnf_name = coro_make_frame_entry (&field_list, "__frame_needs_free",
4420 boolean_type_node, fn_start);
4421 tree resume_idx_name
4422 = coro_make_frame_entry (&field_list, "__resume_at",
4423 short_unsigned_type_node, fn_start);
4425 /* We need a handle to this coroutine, which is passed to every
4426 await_suspend(). There's no point in creating it over and over. */
4427 (void) coro_make_frame_entry (&field_list, "__self_h", handle_type, fn_start);
4429 /* Now add in fields for function params (if there are any).
4430 We do not attempt elision of copies at this stage, we do analyze the
4431 uses and build worklists to replace those when the state machine is
4432 lowered. */
4434 hash_map<tree, param_info> *param_uses = NULL;
4435 if (DECL_ARGUMENTS (orig))
4437 /* Build a hash map with an entry for each param.
4438 The key is the param tree.
4439 Then we have an entry for the frame field name.
4440 Then a cache for the field ref when we come to use it.
4441 Then a tree list of the uses.
4442 The second two entries start out empty - and only get populated
4443 when we see uses. */
4444 param_uses = new hash_map<tree, param_info>;
4445 bool lambda_p = LAMBDA_FUNCTION_P (orig);
4447 unsigned no_name_parm = 0;
4448 for (tree arg = DECL_ARGUMENTS (orig); arg != NULL;
4449 arg = DECL_CHAIN (arg))
4451 bool existed;
4452 param_info &parm = param_uses->get_or_insert (arg, &existed);
4453 gcc_checking_assert (!existed);
4454 parm.body_uses = NULL;
4455 tree actual_type = TREE_TYPE (arg);
4456 actual_type = complete_type_or_else (actual_type, orig);
4457 if (actual_type == NULL_TREE)
4458 actual_type = error_mark_node;
4459 parm.orig_type = actual_type;
4460 parm.by_ref = parm.pt_ref = parm.rv_ref = false;
4461 if (TREE_CODE (actual_type) == REFERENCE_TYPE)
4463 /* If the user passes by reference, then we will save the
4464 pointer to the original. As noted in
4465 [dcl.fct.def.coroutine] / 13, if the lifetime of the
4466 referenced item ends and then the coroutine is resumed,
4467 we have UB; well, the user asked for it. */
4468 if (TYPE_REF_IS_RVALUE (actual_type))
4469 parm.rv_ref = true;
4470 else
4471 parm.pt_ref = true;
4473 else if (TYPE_REF_P (DECL_ARG_TYPE (arg)))
4474 parm.by_ref = true;
4476 parm.frame_type = actual_type;
4478 parm.this_ptr = is_this_parameter (arg);
4479 parm.lambda_cobj = lambda_p && DECL_NAME (arg) == closure_identifier;
4481 char *buf;
4482 if (DECL_NAME (arg))
4484 tree pname = DECL_NAME (arg);
4485 buf = xasprintf ("__parm.%s", IDENTIFIER_POINTER (pname));
4487 else
4488 buf = xasprintf ("__unnamed_parm.%d", no_name_parm++);
4490 if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (parm.frame_type))
4492 char *gbuf = xasprintf ("%s.live", buf);
4493 parm.guard_var
4494 = build_lang_decl (VAR_DECL, get_identifier (gbuf),
4495 boolean_type_node);
4496 free (gbuf);
4497 DECL_ARTIFICIAL (parm.guard_var) = true;
4498 DECL_INITIAL (parm.guard_var) = boolean_false_node;
4499 parm.trivial_dtor = false;
4501 else
4502 parm.trivial_dtor = true;
4503 parm.field_id = coro_make_frame_entry
4504 (&field_list, buf, actual_type, DECL_SOURCE_LOCATION (arg));
4505 free (buf);
4508 /* We want to record every instance of param's use, so don't include
4509 a 'visited' hash_set on the tree walk, but only record a containing
4510 expression once. */
4511 hash_set<tree *> visited;
4512 param_frame_data param_data
4513 = {&field_list, param_uses, &visited, fn_start, false};
4514 cp_walk_tree (&fnbody, register_param_uses, &param_data, NULL);
4517 /* We need to know, and inspect, each suspend point in the function
4518 in several places. It's convenient to place this map out of line
4519 since it's used from tree walk callbacks. */
4520 suspend_points = new hash_map<tree, suspend_point_info>;
4522 /* Now insert the data for any body await points, at this time we also need
4523 to promote any temporaries that are captured by reference (to regular
4524 vars) they will get added to the coro frame along with other locals. */
4525 susp_frame_data body_aw_points
4526 = {&field_list, handle_type, fs_label, NULL, NULL, 0, 0,
4527 hash_set<tree> (), NULL, NULL, 0, false, false, false};
4528 body_aw_points.block_stack = make_tree_vector ();
4529 body_aw_points.bind_stack = make_tree_vector ();
4530 body_aw_points.to_replace = make_tree_vector ();
4531 cp_walk_tree (&fnbody, await_statement_walker, &body_aw_points, NULL);
4533 /* 4. Now make space for local vars, this is conservative again, and we
4534 would expect to delete unused entries later. */
4535 hash_map<tree, local_var_info> local_var_uses;
4536 local_vars_frame_data local_vars_data
4537 = {&field_list, &local_var_uses, 0, 0, fn_start, false, false};
4538 cp_walk_tree (&fnbody, register_local_var_uses, &local_vars_data, NULL);
4540 /* Tie off the struct for now, so that we can build offsets to the
4541 known entries. */
4542 TYPE_FIELDS (coro_frame_type) = field_list;
4543 TYPE_BINFO (coro_frame_type) = make_tree_binfo (0);
4544 BINFO_OFFSET (TYPE_BINFO (coro_frame_type)) = size_zero_node;
4545 BINFO_TYPE (TYPE_BINFO (coro_frame_type)) = coro_frame_type;
4547 coro_frame_type = finish_struct (coro_frame_type, NULL_TREE);
4549 /* Ramp: */
4550 /* Now build the ramp function pieces. */
4551 tree ramp_bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
4552 add_stmt (ramp_bind);
4553 tree ramp_body = push_stmt_list ();
4555 tree coro_fp = build_lang_decl (VAR_DECL, get_identifier ("coro.frameptr"),
4556 coro_frame_ptr);
4557 tree varlist = coro_fp;
4559 /* To signal that we need to cleanup copied function args. */
4560 if (flag_exceptions && DECL_ARGUMENTS (orig))
4561 for (tree arg = DECL_ARGUMENTS (orig); arg != NULL;
4562 arg = DECL_CHAIN (arg))
4564 param_info *parm_i = param_uses->get (arg);
4565 gcc_checking_assert (parm_i);
4566 if (parm_i->trivial_dtor)
4567 continue;
4568 DECL_CHAIN (parm_i->guard_var) = varlist;
4569 varlist = parm_i->guard_var;
4572 /* Signal that we need to clean up the promise object on exception. */
4573 tree coro_promise_live
4574 = build_lang_decl (VAR_DECL, get_identifier ("coro.promise.live"),
4575 boolean_type_node);
4576 DECL_ARTIFICIAL (coro_promise_live) = true;
4577 DECL_CHAIN (coro_promise_live) = varlist;
4578 varlist = coro_promise_live;
4579 DECL_INITIAL (coro_promise_live) = boolean_false_node;
4580 /* When the get-return-object is in the RETURN slot, we need to arrange for
4581 cleanup on exception. */
4582 tree coro_gro_live
4583 = build_lang_decl (VAR_DECL, get_identifier ("coro.gro.live"),
4584 boolean_type_node);
4585 DECL_ARTIFICIAL (coro_gro_live) = true;
4586 DECL_CHAIN (coro_gro_live) = varlist;
4587 varlist = coro_gro_live;
4588 DECL_INITIAL (coro_gro_live) = boolean_false_node;
4590 /* Collected the scope vars we need ... only one for now. */
4591 BIND_EXPR_VARS (ramp_bind) = nreverse (varlist);
4593 /* We're now going to create a new top level scope block for the ramp
4594 function. */
4595 tree top_block = make_node (BLOCK);
4597 BIND_EXPR_BLOCK (ramp_bind) = top_block;
4598 BLOCK_VARS (top_block) = BIND_EXPR_VARS (ramp_bind);
4599 BLOCK_SUBBLOCKS (top_block) = NULL_TREE;
4601 /* The decl_expr for the coro frame pointer, initialize to zero so that we
4602 can pass it to the IFN_CO_FRAME (since there's no way to pass a type,
4603 directly apparently). This avoids a "used uninitialized" warning. */
4604 tree zeroinit = build1 (CONVERT_EXPR, coro_frame_ptr, integer_zero_node);
4605 DECL_INITIAL (coro_fp) = zeroinit;
4606 add_decl_expr (coro_fp);
4607 if (flag_exceptions && DECL_ARGUMENTS (orig))
4608 for (tree arg = DECL_ARGUMENTS (orig); arg != NULL;
4609 arg = DECL_CHAIN (arg))
4611 param_info *parm_i = param_uses->get (arg);
4612 if (parm_i->trivial_dtor)
4613 continue;
4614 add_decl_expr (parm_i->guard_var);;
4616 add_decl_expr (coro_promise_live);
4617 add_decl_expr (coro_gro_live);
4619 /* The CO_FRAME internal function is a mechanism to allow the middle end
4620 to adjust the allocation in response to optimizations. We provide the
4621 current conservative estimate of the frame size (as per the current)
4622 computed layout. */
4623 tree frame_size = TYPE_SIZE_UNIT (coro_frame_type);
4624 tree resizeable
4625 = build_call_expr_internal_loc (fn_start, IFN_CO_FRAME, size_type_node, 2,
4626 frame_size, coro_fp);
4628 /* [dcl.fct.def.coroutine] / 10 (part1)
4629 The unqualified-id get_return_object_on_allocation_failure is looked up
4630 in the scope of the promise type by class member access lookup. */
4632 /* We don't require this, so coro_build_promise_expression can return NULL,
4633 but, if the lookup succeeds, then the function must be usable. */
4634 tree dummy_promise = build_dummy_object (get_coroutine_promise_type (orig));
4635 tree grooaf
4636 = coro_build_promise_expression (orig, dummy_promise,
4637 coro_gro_on_allocation_fail_identifier,
4638 fn_start, NULL, /*musthave=*/false);
4640 /* however, should that fail, returning an error, the later stages can't
4641 handle the erroneous expression, so we reset the call as if it was
4642 absent. */
4643 if (grooaf == error_mark_node)
4644 grooaf = NULL_TREE;
4646 /* Allocate the frame, this has several possibilities:
4647 [dcl.fct.def.coroutine] / 9 (part 1)
4648 The allocation function’s name is looked up in the scope of the promise
4649 type. It's not a failure for it to be absent see part 4, below. */
4651 tree nwname = ovl_op_identifier (false, NEW_EXPR);
4652 tree new_fn = NULL_TREE;
4654 if (TYPE_HAS_NEW_OPERATOR (promise_type))
4656 tree fns = lookup_promise_method (orig, nwname, fn_start,
4657 /*musthave=*/true);
4658 /* [dcl.fct.def.coroutine] / 9 (part 2)
4659 If the lookup finds an allocation function in the scope of the promise
4660 type, overload resolution is performed on a function call created by
4661 assembling an argument list. The first argument is the amount of space
4662 requested, and has type std::size_t. The succeeding arguments are
4663 those of the original function. */
4664 vec<tree, va_gc> *args = make_tree_vector ();
4665 vec_safe_push (args, resizeable); /* Space needed. */
4667 for (tree arg = DECL_ARGUMENTS (orig); arg != NULL;
4668 arg = DECL_CHAIN (arg))
4670 param_info *parm_i = param_uses->get (arg);
4671 gcc_checking_assert (parm_i);
4672 if (parm_i->this_ptr || parm_i->lambda_cobj)
4674 /* We pass a reference to *this to the allocator lookup. */
4675 tree tt = TREE_TYPE (TREE_TYPE (arg));
4676 tree this_ref = build1 (INDIRECT_REF, tt, arg);
4677 tt = cp_build_reference_type (tt, false);
4678 this_ref = convert_to_reference (tt, this_ref, CONV_STATIC,
4679 LOOKUP_NORMAL , NULL_TREE,
4680 tf_warning_or_error);
4681 vec_safe_push (args, this_ref);
4683 else
4684 vec_safe_push (args, arg);
4687 /* Note the function selected; we test to see if it's NOTHROW. */
4688 tree func;
4689 /* Failure is not an error for this attempt. */
4690 new_fn = build_new_method_call (dummy_promise, fns, &args, NULL,
4691 LOOKUP_NORMAL, &func, tf_none);
4692 release_tree_vector (args);
4694 if (new_fn == error_mark_node)
4696 /* [dcl.fct.def.coroutine] / 9 (part 3)
4697 If no viable function is found, overload resolution is performed
4698 again on a function call created by passing just the amount of
4699 space required as an argument of type std::size_t. */
4700 args = make_tree_vector_single (resizeable); /* Space needed. */
4701 new_fn = build_new_method_call (dummy_promise, fns, &args,
4702 NULL_TREE, LOOKUP_NORMAL, &func,
4703 tf_none);
4704 release_tree_vector (args);
4707 /* However, if the promise provides an operator new, then one of these
4708 two options must be available. */
4709 if (new_fn == error_mark_node)
4711 error_at (fn_start, "%qE is provided by %qT but is not usable with"
4712 " the function signature %qD", nwname, promise_type, orig);
4713 new_fn = error_mark_node;
4715 else if (grooaf && !TYPE_NOTHROW_P (TREE_TYPE (func)))
4716 error_at (fn_start, "%qE is provided by %qT but %qE is not marked"
4717 " %<throw()%> or %<noexcept%>", grooaf, promise_type, nwname);
4718 else if (!grooaf && TYPE_NOTHROW_P (TREE_TYPE (func)))
4719 warning_at (fn_start, 0, "%qE is marked %<throw()%> or %<noexcept%> but"
4720 " no usable %<get_return_object_on_allocation_failure%>"
4721 " is provided by %qT", nwname, promise_type);
4723 else /* No operator new in the promise. */
4725 /* [dcl.fct.def.coroutine] / 9 (part 4)
4726 If this lookup fails, the allocation function’s name is looked up in
4727 the global scope. */
4729 vec<tree, va_gc> *args;
4730 /* build_operator_new_call () will insert size needed as element 0 of
4731 this, and we might need to append the std::nothrow constant. */
4732 vec_alloc (args, 2);
4733 if (grooaf)
4735 /* [dcl.fct.def.coroutine] / 10 (part 2)
4736 If any declarations (of the get return on allocation fail) are
4737 found, then the result of a call to an allocation function used
4738 to obtain storage for the coroutine state is assumed to return
4739 nullptr if it fails to obtain storage and, if a global allocation
4740 function is selected, the ::operator new(size_t, nothrow_t) form
4741 is used. The allocation function used in this case shall have a
4742 non-throwing noexcept-specification. So we need std::nothrow. */
4743 tree std_nt = lookup_qualified_name (std_node,
4744 get_identifier ("nothrow"),
4745 LOOK_want::NORMAL,
4746 /*complain=*/true);
4747 if (!std_nt || std_nt == error_mark_node)
4748 error_at (fn_start, "%qE is provided by %qT but %<std::nothrow%> "
4749 "cannot be found", grooaf, promise_type);
4750 vec_safe_push (args, std_nt);
4753 /* If we get to this point, we must succeed in looking up the global
4754 operator new for the params provided. Extract a simplified version
4755 of the machinery from build_operator_new_call. This can update the
4756 frame size. */
4757 tree cookie = NULL;
4758 new_fn = build_operator_new_call (nwname, &args, &frame_size, &cookie,
4759 /*align_arg=*/NULL,
4760 /*size_check=*/NULL, /*fn=*/NULL,
4761 tf_warning_or_error);
4762 resizeable = build_call_expr_internal_loc
4763 (fn_start, IFN_CO_FRAME, size_type_node, 2, frame_size, coro_fp);
4764 /* If the operator call fails for some reason, then don't try to
4765 amend it. */
4766 if (new_fn != error_mark_node)
4767 CALL_EXPR_ARG (new_fn, 0) = resizeable;
4769 release_tree_vector (args);
4772 tree allocated = build1 (CONVERT_EXPR, coro_frame_ptr, new_fn);
4773 tree r = build2 (INIT_EXPR, TREE_TYPE (coro_fp), coro_fp, allocated);
4774 r = coro_build_cvt_void_expr_stmt (r, fn_start);
4775 add_stmt (r);
4777 /* If the user provided a method to return an object on alloc fail, then
4778 check the returned pointer and call the func if it's null.
4779 Otherwise, no check, and we fail for noexcept/fno-exceptions cases. */
4781 if (grooaf)
4783 /* [dcl.fct.def.coroutine] / 10 (part 3)
4784 If the allocation function returns nullptr,the coroutine returns
4785 control to the caller of the coroutine and the return value is
4786 obtained by a call to T::get_return_object_on_allocation_failure(),
4787 where T is the promise type. */
4789 gcc_checking_assert (same_type_p (fn_return_type, TREE_TYPE (grooaf)));
4790 tree if_stmt = begin_if_stmt ();
4791 tree cond = build1 (CONVERT_EXPR, coro_frame_ptr, integer_zero_node);
4792 cond = build2 (EQ_EXPR, boolean_type_node, coro_fp, cond);
4793 finish_if_stmt_cond (cond, if_stmt);
4794 if (VOID_TYPE_P (fn_return_type))
4796 /* Execute the get-return-object-on-alloc-fail call... */
4797 finish_expr_stmt (grooaf);
4798 /* ... but discard the result, since we return void. */
4799 finish_return_stmt (NULL_TREE);
4801 else
4803 /* Get the fallback return object. */
4804 r = build_cplus_new (fn_return_type, grooaf, tf_warning_or_error);
4805 finish_return_stmt (r);
4807 finish_then_clause (if_stmt);
4808 finish_if_stmt (if_stmt);
4811 /* Up to now any exception thrown will propagate directly to the caller.
4812 This is OK since the only source of such exceptions would be in allocation
4813 of the coroutine frame, and therefore the ramp will not have initialized
4814 any further state. From here, we will track state that needs explicit
4815 destruction in the case that promise or g.r.o setup fails or an exception
4816 is thrown from the initial suspend expression. */
4817 tree ramp_cleanup = NULL_TREE;
4818 if (flag_exceptions)
4820 ramp_cleanup = build_stmt (fn_start, TRY_BLOCK, NULL, NULL);
4821 add_stmt (ramp_cleanup);
4822 TRY_STMTS (ramp_cleanup) = push_stmt_list ();
4825 /* deref the frame pointer, to use in member access code. */
4826 tree deref_fp = build_x_arrow (fn_start, coro_fp, tf_warning_or_error);
4828 /* For now, once allocation has succeeded we always assume that this needs
4829 destruction, there's no impl. for frame allocation elision. */
4830 tree fnf_m
4831 = lookup_member (coro_frame_type, fnf_name, 1, 0, tf_warning_or_error);
4832 tree fnf_x = build_class_member_access_expr (deref_fp, fnf_m, NULL_TREE,
4833 false, tf_warning_or_error);
4834 r = build2 (INIT_EXPR, boolean_type_node, fnf_x, boolean_true_node);
4835 r = coro_build_cvt_void_expr_stmt (r, fn_start);
4836 add_stmt (r);
4838 /* Put the resumer and destroyer functions in. */
4840 tree actor_addr = build1 (ADDR_EXPR, act_des_fn_ptr, actor);
4841 tree resume_m
4842 = lookup_member (coro_frame_type, resume_name,
4843 /*protect=*/1, /*want_type=*/0, tf_warning_or_error);
4844 tree resume_x = build_class_member_access_expr (deref_fp, resume_m, NULL_TREE,
4845 false, tf_warning_or_error);
4846 r = build2_loc (fn_start, INIT_EXPR, act_des_fn_ptr, resume_x, actor_addr);
4847 r = coro_build_cvt_void_expr_stmt (r, fn_start);
4848 add_stmt (r);
4850 tree destroy_addr = build1 (ADDR_EXPR, act_des_fn_ptr, destroy);
4851 tree destroy_m
4852 = lookup_member (coro_frame_type, destroy_name,
4853 /*protect=*/1, /*want_type=*/0, tf_warning_or_error);
4854 tree destroy_x
4855 = build_class_member_access_expr (deref_fp, destroy_m, NULL_TREE, false,
4856 tf_warning_or_error);
4857 r = build2_loc (fn_start, INIT_EXPR, act_des_fn_ptr, destroy_x, destroy_addr);
4858 r = coro_build_cvt_void_expr_stmt (r, fn_start);
4859 add_stmt (r);
4861 /* [dcl.fct.def.coroutine] /13
4862 When a coroutine is invoked, a copy is created for each coroutine
4863 parameter. Each such copy is an object with automatic storage duration
4864 that is direct-initialized from an lvalue referring to the corresponding
4865 parameter if the parameter is an lvalue reference, and from an xvalue
4866 referring to it otherwise. A reference to a parameter in the function-
4867 body of the coroutine and in the call to the coroutine promise
4868 constructor is replaced by a reference to its copy. */
4870 vec<tree, va_gc> *promise_args = NULL; /* So that we can adjust refs. */
4872 /* The initialization and destruction of each parameter copy occurs in the
4873 context of the called coroutine. Initializations of parameter copies are
4874 sequenced before the call to the coroutine promise constructor and
4875 indeterminately sequenced with respect to each other. The lifetime of
4876 parameter copies ends immediately after the lifetime of the coroutine
4877 promise object ends. */
4879 vec<tree, va_gc> *param_dtor_list = NULL;
4881 if (DECL_ARGUMENTS (orig))
4883 promise_args = make_tree_vector ();
4884 for (tree arg = DECL_ARGUMENTS (orig); arg != NULL;
4885 arg = DECL_CHAIN (arg))
4887 bool existed;
4888 param_info &parm = param_uses->get_or_insert (arg, &existed);
4890 tree fld_ref = lookup_member (coro_frame_type, parm.field_id,
4891 /*protect=*/1, /*want_type=*/0,
4892 tf_warning_or_error);
4893 tree fld_idx
4894 = build_class_member_access_expr (deref_fp, fld_ref, NULL_TREE,
4895 false, tf_warning_or_error);
4897 /* Add this to the promise CTOR arguments list, accounting for
4898 refs and special handling for method this ptr. */
4899 if (parm.this_ptr || parm.lambda_cobj)
4901 /* We pass a reference to *this to the param preview. */
4902 tree tt = TREE_TYPE (arg);
4903 gcc_checking_assert (POINTER_TYPE_P (tt));
4904 tree ct = TREE_TYPE (tt);
4905 tree this_ref = build1 (INDIRECT_REF, ct, arg);
4906 tree rt = cp_build_reference_type (ct, false);
4907 this_ref = convert_to_reference (rt, this_ref, CONV_STATIC,
4908 LOOKUP_NORMAL, NULL_TREE,
4909 tf_warning_or_error);
4910 vec_safe_push (promise_args, this_ref);
4912 else if (parm.rv_ref)
4913 vec_safe_push (promise_args, move (fld_idx));
4914 else
4915 vec_safe_push (promise_args, fld_idx);
4917 if (parm.rv_ref || parm.pt_ref)
4918 /* Initialise the frame reference field directly. */
4919 r = cp_build_modify_expr (fn_start, TREE_OPERAND (fld_idx, 0),
4920 INIT_EXPR, arg, tf_warning_or_error);
4921 else
4923 r = forward_parm (arg);
4924 r = cp_build_modify_expr (fn_start, fld_idx, INIT_EXPR, r,
4925 tf_warning_or_error);
4927 finish_expr_stmt (r);
4928 if (!parm.trivial_dtor)
4930 if (param_dtor_list == NULL)
4931 param_dtor_list = make_tree_vector ();
4932 vec_safe_push (param_dtor_list, parm.field_id);
4933 /* Cleanup this frame copy on exception. */
4934 parm.fr_copy_dtor
4935 = build_special_member_call (fld_idx, complete_dtor_identifier,
4936 NULL, parm.frame_type,
4937 LOOKUP_NORMAL,
4938 tf_warning_or_error);
4939 /* This var is now live. */
4940 r = build_modify_expr (fn_start, parm.guard_var,
4941 boolean_type_node, INIT_EXPR, fn_start,
4942 boolean_true_node, boolean_type_node);
4943 finish_expr_stmt (r);
4948 /* Set up the promise. */
4949 tree promise_m
4950 = lookup_member (coro_frame_type, promise_name,
4951 /*protect=*/1, /*want_type=*/0, tf_warning_or_error);
4953 tree p = build_class_member_access_expr (deref_fp, promise_m, NULL_TREE,
4954 false, tf_warning_or_error);
4956 tree promise_dtor = NULL_TREE;
4957 if (type_build_ctor_call (promise_type))
4959 /* Do a placement new constructor for the promise type (we never call
4960 the new operator, just the constructor on the object in place in the
4961 frame).
4963 First try to find a constructor with the same parameter list as the
4964 original function (if it has params), failing that find a constructor
4965 with no parameter list. */
4967 if (DECL_ARGUMENTS (orig))
4969 r = build_special_member_call (p, complete_ctor_identifier,
4970 &promise_args, promise_type,
4971 LOOKUP_NORMAL, tf_none);
4972 release_tree_vector (promise_args);
4974 else
4975 r = NULL_TREE;
4977 if (r == NULL_TREE || r == error_mark_node)
4978 r = build_special_member_call (p, complete_ctor_identifier, NULL,
4979 promise_type, LOOKUP_NORMAL,
4980 tf_warning_or_error);
4982 r = coro_build_cvt_void_expr_stmt (r, fn_start);
4983 finish_expr_stmt (r);
4985 r = build_modify_expr (fn_start, coro_promise_live, boolean_type_node,
4986 INIT_EXPR, fn_start, boolean_true_node,
4987 boolean_type_node);
4988 finish_expr_stmt (r);
4990 promise_dtor
4991 = build_special_member_call (p, complete_dtor_identifier,
4992 NULL, promise_type, LOOKUP_NORMAL,
4993 tf_warning_or_error);
4996 /* Set up a new bind context for the GRO. */
4997 tree gro_context_bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
4998 /* Make and connect the scope blocks. */
4999 tree gro_block = make_node (BLOCK);
5000 BLOCK_SUPERCONTEXT (gro_block) = top_block;
5001 BLOCK_SUBBLOCKS (top_block) = gro_block;
5002 BIND_EXPR_BLOCK (gro_context_bind) = gro_block;
5003 add_stmt (gro_context_bind);
5005 tree get_ro
5006 = coro_build_promise_expression (orig, p,
5007 coro_get_return_object_identifier,
5008 fn_start, NULL, /*musthave=*/true);
5009 /* Without a return object we haven't got much clue what's going on. */
5010 if (get_ro == error_mark_node)
5012 BIND_EXPR_BODY (ramp_bind) = pop_stmt_list (ramp_body);
5013 DECL_SAVED_TREE (orig) = newbody;
5014 /* Suppress warnings about the missing return value. */
5015 suppress_warning (orig, OPT_Wreturn_type);
5016 return false;
5019 tree gro_context_body = push_stmt_list ();
5020 tree gro_type = TREE_TYPE (get_ro);
5021 bool gro_is_void_p = VOID_TYPE_P (gro_type);
5023 tree gro = NULL_TREE;
5024 tree gro_bind_vars = NULL_TREE;
5025 /* Used for return objects in the RESULT slot. */
5026 tree gro_ret_dtor = NULL_TREE;
5027 tree gro_cleanup_stmt = NULL_TREE;
5028 /* We have to sequence the call to get_return_object before initial
5029 suspend. */
5030 if (gro_is_void_p)
5031 r = get_ro;
5032 else if (same_type_p (gro_type, fn_return_type))
5034 /* [dcl.fct.def.coroutine] / 7
5035 The expression promise.get_return_object() is used to initialize the
5036 glvalue result or... (see below)
5037 Construct the return result directly. */
5038 if (type_build_ctor_call (gro_type))
5040 vec<tree, va_gc> *arg = make_tree_vector_single (get_ro);
5041 r = build_special_member_call (DECL_RESULT (orig),
5042 complete_ctor_identifier,
5043 &arg, gro_type, LOOKUP_NORMAL,
5044 tf_warning_or_error);
5045 release_tree_vector (arg);
5047 else
5048 r = build2_loc (fn_start, INIT_EXPR, gro_type,
5049 DECL_RESULT (orig), get_ro);
5051 if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (gro_type))
5052 /* If some part of the initalization code (prior to the await_resume
5053 of the initial suspend expression), then we need to clean up the
5054 return value. */
5055 gro_ret_dtor
5056 = build_special_member_call (DECL_RESULT (orig),
5057 complete_dtor_identifier, NULL,
5058 gro_type, LOOKUP_NORMAL,
5059 tf_warning_or_error);
5061 else
5063 /* ... or ... Construct an object that will be used as the single
5064 param to the CTOR for the return object. */
5065 gro = build_lang_decl (VAR_DECL, get_identifier ("coro.gro"), gro_type);
5066 DECL_CONTEXT (gro) = current_scope ();
5067 DECL_ARTIFICIAL (gro) = true;
5068 DECL_IGNORED_P (gro) = true;
5069 add_decl_expr (gro);
5070 gro_bind_vars = gro;
5071 r = cp_build_modify_expr (input_location, gro, INIT_EXPR, get_ro,
5072 tf_warning_or_error);
5073 /* The constructed object might require a cleanup. */
5074 if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (gro_type))
5076 gro_cleanup_stmt
5077 = build_special_member_call (gro, complete_dtor_identifier,
5078 NULL, gro_type, LOOKUP_NORMAL,
5079 tf_warning_or_error);
5080 gro_cleanup_stmt = build_stmt (input_location, CLEANUP_STMT, NULL,
5081 gro_cleanup_stmt, gro);
5084 finish_expr_stmt (r);
5086 if (gro_cleanup_stmt && gro_cleanup_stmt != error_mark_node)
5087 CLEANUP_BODY (gro_cleanup_stmt) = push_stmt_list ();
5089 /* If we have a live g.r.o in the return slot, then signal this for exception
5090 cleanup. */
5091 if (gro_ret_dtor)
5093 r = build_modify_expr (fn_start, coro_gro_live, boolean_type_node,
5094 INIT_EXPR, fn_start, boolean_true_node,
5095 boolean_type_node);
5096 finish_expr_stmt (r);
5098 /* Initialize the resume_idx_name to 0, meaning "not started". */
5099 tree resume_idx_m
5100 = lookup_member (coro_frame_type, resume_idx_name,
5101 /*protect=*/1, /*want_type=*/0, tf_warning_or_error);
5102 tree resume_idx
5103 = build_class_member_access_expr (deref_fp, resume_idx_m, NULL_TREE, false,
5104 tf_warning_or_error);
5105 r = build_int_cst (short_unsigned_type_node, 0);
5106 r = build2_loc (fn_start, INIT_EXPR, short_unsigned_type_node, resume_idx, r);
5107 r = coro_build_cvt_void_expr_stmt (r, fn_start);
5108 add_stmt (r);
5110 /* So .. call the actor .. */
5111 r = build_call_expr_loc (fn_start, actor, 1, coro_fp);
5112 r = maybe_cleanup_point_expr_void (r);
5113 add_stmt (r);
5115 /* Switch to using 'input_location' as the loc, since we're now more
5116 logically doing things related to the end of the function. */
5118 /* The ramp is done, we just need the return value.
5119 [dcl.fct.def.coroutine] / 7
5120 The expression promise.get_return_object() is used to initialize the
5121 glvalue result or prvalue result object of a call to a coroutine.
5123 If the 'get return object' is non-void, then we built it before the
5124 promise was constructed. We now supply a reference to that var,
5125 either as the return value (if it's the same type) or to the CTOR
5126 for an object of the return type. */
5128 if (same_type_p (gro_type, fn_return_type))
5129 r = gro_is_void_p ? NULL_TREE : DECL_RESULT (orig);
5130 else if (!gro_is_void_p)
5131 /* check_return_expr will automatically return gro as an rvalue via
5132 treat_lvalue_as_rvalue_p. */
5133 r = gro;
5134 else if (CLASS_TYPE_P (fn_return_type))
5136 /* For class type return objects, we can attempt to construct,
5137 even if the gro is void. ??? Citation ??? c++/100476 */
5138 r = build_special_member_call (NULL_TREE,
5139 complete_ctor_identifier, NULL,
5140 fn_return_type, LOOKUP_NORMAL,
5141 tf_warning_or_error);
5142 r = build_cplus_new (fn_return_type, r, tf_warning_or_error);
5144 else
5146 /* We can't initialize a non-class return value from void. */
5147 error_at (input_location, "cannot initialize a return object of type"
5148 " %qT with an rvalue of type %<void%>", fn_return_type);
5149 r = error_mark_node;
5152 finish_return_stmt (r);
5154 if (gro_cleanup_stmt)
5156 CLEANUP_BODY (gro_cleanup_stmt)
5157 = pop_stmt_list (CLEANUP_BODY (gro_cleanup_stmt));
5158 add_stmt (gro_cleanup_stmt);
5161 /* Finish up the ramp function. */
5162 BIND_EXPR_VARS (gro_context_bind) = gro_bind_vars;
5163 BIND_EXPR_BODY (gro_context_bind) = pop_stmt_list (gro_context_body);
5164 TREE_SIDE_EFFECTS (gro_context_bind) = true;
5166 if (flag_exceptions)
5168 TRY_HANDLERS (ramp_cleanup) = push_stmt_list ();
5169 tree handler = begin_handler ();
5170 finish_handler_parms (NULL_TREE, handler); /* catch (...) */
5172 /* If we have a live G.R.O in the return slot, then run its DTOR.
5173 When the return object is constructed from a separate g.r.o, this is
5174 already handled by its regular cleanup. */
5175 if (gro_ret_dtor && gro_ret_dtor != error_mark_node)
5177 tree gro_d_if = begin_if_stmt ();
5178 finish_if_stmt_cond (coro_gro_live, gro_d_if);
5179 finish_expr_stmt (gro_ret_dtor);
5180 finish_then_clause (gro_d_if);
5181 tree gro_d_if_scope = IF_SCOPE (gro_d_if);
5182 IF_SCOPE (gro_d_if) = NULL;
5183 gro_d_if = do_poplevel (gro_d_if_scope);
5184 add_stmt (gro_d_if);
5187 /* If the promise is live, then run its dtor if that's available. */
5188 if (promise_dtor && promise_dtor != error_mark_node)
5190 tree promise_d_if = begin_if_stmt ();
5191 finish_if_stmt_cond (coro_promise_live, promise_d_if);
5192 finish_expr_stmt (promise_dtor);
5193 finish_then_clause (promise_d_if);
5194 tree promise_d_if_scope = IF_SCOPE (promise_d_if);
5195 IF_SCOPE (promise_d_if) = NULL;
5196 promise_d_if = do_poplevel (promise_d_if_scope);
5197 add_stmt (promise_d_if);
5200 /* Clean up any frame copies of parms with non-trivial dtors. */
5201 if (DECL_ARGUMENTS (orig))
5202 for (tree arg = DECL_ARGUMENTS (orig); arg != NULL;
5203 arg = DECL_CHAIN (arg))
5205 param_info *parm_i = param_uses->get (arg);
5206 if (parm_i->trivial_dtor)
5207 continue;
5208 if (parm_i->fr_copy_dtor && parm_i->fr_copy_dtor != error_mark_node)
5210 tree dtor_if = begin_if_stmt ();
5211 finish_if_stmt_cond (parm_i->guard_var, dtor_if);
5212 finish_expr_stmt (parm_i->fr_copy_dtor);
5213 finish_then_clause (dtor_if);
5214 tree parm_d_if_scope = IF_SCOPE (dtor_if);
5215 IF_SCOPE (dtor_if) = NULL;
5216 dtor_if = do_poplevel (parm_d_if_scope);
5217 add_stmt (dtor_if);
5221 /* We always expect to delete the frame. */
5222 tree del_coro_fr = coro_get_frame_dtor (coro_fp, orig, frame_size,
5223 promise_type, fn_start);
5224 finish_expr_stmt (del_coro_fr);
5225 tree rethrow = build_throw (fn_start, NULL_TREE);
5226 suppress_warning (rethrow);
5227 finish_expr_stmt (rethrow);
5228 finish_handler (handler);
5229 TRY_HANDLERS (ramp_cleanup) = pop_stmt_list (TRY_HANDLERS (ramp_cleanup));
5232 BIND_EXPR_BODY (ramp_bind) = pop_stmt_list (ramp_body);
5233 TREE_SIDE_EFFECTS (ramp_bind) = true;
5235 /* Start to build the final functions.
5237 We push_deferring_access_checks to avoid these routines being seen as
5238 nested by the middle end; we are doing the outlining here. */
5240 push_deferring_access_checks (dk_no_check);
5242 /* Build the actor... */
5243 build_actor_fn (fn_start, coro_frame_type, actor, fnbody, orig, param_uses,
5244 &local_var_uses, param_dtor_list, resume_fn_field,
5245 resume_idx_field, body_aw_points.await_number, frame_size);
5247 /* Destroyer ... */
5248 build_destroy_fn (fn_start, coro_frame_type, destroy, actor);
5250 pop_deferring_access_checks ();
5252 DECL_SAVED_TREE (orig) = newbody;
5253 /* Link our new functions into the list. */
5254 TREE_CHAIN (destroy) = TREE_CHAIN (orig);
5255 TREE_CHAIN (actor) = destroy;
5256 TREE_CHAIN (orig) = actor;
5258 *resumer = actor;
5259 *destroyer = destroy;
5261 delete suspend_points;
5262 suspend_points = NULL;
5263 return true;
5266 #include "gt-cp-coroutines.h"