c++: fix broken conversion in coroutines
[official-gcc.git] / gcc / cp / coroutines.cc
blob60b846600b923b30b2d692412d2ca28b66052542
1 /* coroutine-specific state, expansions and tests.
3 Copyright (C) 2018-2022 Free Software Foundation, Inc.
5 Contributed by Iain Sandoe <iain@sandoe.co.uk> under contract to Facebook.
7 This file is part of GCC.
9 GCC is free software; you can redistribute it and/or modify it under
10 the terms of the GNU General Public License as published by the Free
11 Software Foundation; either version 3, or (at your option) any later
12 version.
14 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
15 WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 for more details.
19 You should have received a copy of the GNU General Public License
20 along with GCC; see the file COPYING3. If not see
21 <http://www.gnu.org/licenses/>. */
23 #include "config.h"
24 #include "system.h"
25 #include "coretypes.h"
26 #include "target.h"
27 #include "cp-tree.h"
28 #include "stringpool.h"
29 #include "stmt.h"
30 #include "stor-layout.h"
31 #include "tree-iterator.h"
32 #include "tree.h"
33 #include "gcc-rich-location.h"
34 #include "hash-map.h"
36 static bool coro_promise_type_found_p (tree, location_t);
38 /* GCC C++ coroutines implementation.
40 The user authors a function that becomes a coroutine (lazily) by
41 making use of any of the co_await, co_yield or co_return keywords.
43 Unlike a regular function, where the activation record is placed on the
44 stack, and is destroyed on function exit, a coroutine has some state that
45 persists between calls - the coroutine frame (analogous to a stack frame).
47 We transform the user's function into three pieces:
48 1. A so-called ramp function, that establishes the coroutine frame and
49 begins execution of the coroutine.
50 2. An actor function that contains the state machine corresponding to the
51 user's suspend/resume structure.
52 3. A stub function that calls the actor function in 'destroy' mode.
54 The actor function is executed:
55 * from "resume point 0" by the ramp.
56 * from resume point N ( > 0 ) for handle.resume() calls.
57 * from the destroy stub for destroy point N for handle.destroy() calls.
59 The functions in this file carry out the necessary analysis of, and
60 transforms to, the AST to perform this.
62 The C++ coroutine design makes use of some helper functions that are
63 authored in a so-called "promise" class provided by the user.
65 At parse time (or post substitution) the type of the coroutine promise
66 will be determined. At that point, we can look up the required promise
67 class methods and issue diagnostics if they are missing or incorrect. To
68 avoid repeating these actions at code-gen time, we make use of temporary
69 'proxy' variables for the coroutine handle and the promise - which will
70 eventually be instantiated in the coroutine frame.
72 Each of the keywords will expand to a code sequence (although co_yield is
73 just syntactic sugar for a co_await).
75 We defer the analysis and transformation until template expansion is
76 complete so that we have complete types at that time. */
79 /* The state that we collect during parsing (and template expansion) for
80 a coroutine. */
82 struct GTY((for_user)) coroutine_info
84 tree function_decl; /* The original function decl. */
85 tree actor_decl; /* The synthesized actor function. */
86 tree destroy_decl; /* The synthesized destroy function. */
87 tree promise_type; /* The cached promise type for this function. */
88 tree handle_type; /* The cached coroutine handle for this function. */
89 tree self_h_proxy; /* A handle instance that is used as the proxy for the
90 one that will eventually be allocated in the coroutine
91 frame. */
92 tree promise_proxy; /* Likewise, a proxy promise instance. */
93 tree return_void; /* The expression for p.return_void() if it exists. */
94 location_t first_coro_keyword; /* The location of the keyword that made this
95 function into a coroutine. */
96 /* Flags to avoid repeated errors for per-function issues. */
97 bool coro_ret_type_error_emitted;
98 bool coro_promise_error_emitted;
99 bool coro_co_return_error_emitted;
102 struct coroutine_info_hasher : ggc_ptr_hash<coroutine_info>
104 typedef tree compare_type; /* We only compare the function decl. */
105 static inline hashval_t hash (coroutine_info *);
106 static inline hashval_t hash (const compare_type &);
107 static inline bool equal (coroutine_info *, coroutine_info *);
108 static inline bool equal (coroutine_info *, const compare_type &);
111 /* This table holds all the collected coroutine state for coroutines in
112 the current translation unit. */
114 static GTY (()) hash_table<coroutine_info_hasher> *coroutine_info_table;
116 /* We will initialize state lazily. */
117 static bool coro_initialized = false;
119 /* Return a hash value for the entry pointed to by INFO.
120 The compare type is a tree, but the only trees we are going use are
121 function decls. We use the DECL_UID as the hash value since that is
122 stable across PCH. */
124 hashval_t
125 coroutine_info_hasher::hash (coroutine_info *info)
127 return DECL_UID (info->function_decl);
130 /* Return a hash value for the compare value COMP. */
132 hashval_t
133 coroutine_info_hasher::hash (const compare_type& comp)
135 return DECL_UID (comp);
138 /* Return true if the entries pointed to by LHS and RHS are for the
139 same coroutine. */
141 bool
142 coroutine_info_hasher::equal (coroutine_info *lhs, coroutine_info *rhs)
144 return lhs->function_decl == rhs->function_decl;
147 bool
148 coroutine_info_hasher::equal (coroutine_info *lhs, const compare_type& rhs)
150 return lhs->function_decl == rhs;
153 /* Get the existing coroutine_info for FN_DECL, or insert a new one if the
154 entry does not yet exist. */
156 coroutine_info *
157 get_or_insert_coroutine_info (tree fn_decl)
159 gcc_checking_assert (coroutine_info_table != NULL);
161 coroutine_info **slot = coroutine_info_table->find_slot_with_hash
162 (fn_decl, coroutine_info_hasher::hash (fn_decl), INSERT);
164 if (*slot == NULL)
166 *slot = new (ggc_cleared_alloc<coroutine_info> ()) coroutine_info ();
167 (*slot)->function_decl = fn_decl;
170 return *slot;
173 /* Get the existing coroutine_info for FN_DECL, fail if it doesn't exist. */
175 coroutine_info *
176 get_coroutine_info (tree fn_decl)
178 if (coroutine_info_table == NULL)
179 return NULL;
181 coroutine_info **slot = coroutine_info_table->find_slot_with_hash
182 (fn_decl, coroutine_info_hasher::hash (fn_decl), NO_INSERT);
183 if (slot)
184 return *slot;
185 return NULL;
188 /* We will lazily create all the identifiers that are used by coroutines
189 on the first attempt to lookup the traits. */
191 /* Identifiers that are used by all coroutines. */
193 static GTY(()) tree coro_traits_identifier;
194 static GTY(()) tree coro_handle_identifier;
195 static GTY(()) tree coro_promise_type_identifier;
197 /* Required promise method name identifiers. */
199 static GTY(()) tree coro_await_transform_identifier;
200 static GTY(()) tree coro_initial_suspend_identifier;
201 static GTY(()) tree coro_final_suspend_identifier;
202 static GTY(()) tree coro_return_void_identifier;
203 static GTY(()) tree coro_return_value_identifier;
204 static GTY(()) tree coro_yield_value_identifier;
205 static GTY(()) tree coro_resume_identifier;
206 static GTY(()) tree coro_address_identifier;
207 static GTY(()) tree coro_from_address_identifier;
208 static GTY(()) tree coro_get_return_object_identifier;
209 static GTY(()) tree coro_gro_on_allocation_fail_identifier;
210 static GTY(()) tree coro_unhandled_exception_identifier;
212 /* Awaitable methods. */
214 static GTY(()) tree coro_await_ready_identifier;
215 static GTY(()) tree coro_await_suspend_identifier;
216 static GTY(()) tree coro_await_resume_identifier;
218 /* Accessors for the coroutine frame state used by the implementation. */
220 static GTY(()) tree coro_resume_fn_id;
221 static GTY(()) tree coro_destroy_fn_id;
222 static GTY(()) tree coro_promise_id;
223 static GTY(()) tree coro_frame_needs_free_id;
224 static GTY(()) tree coro_resume_index_id;
225 static GTY(()) tree coro_self_handle_id;
226 static GTY(()) tree coro_actor_continue_id;
227 static GTY(()) tree coro_frame_i_a_r_c_id;
229 /* Create the identifiers used by the coroutines library interfaces and
230 the implementation frame state. */
232 static void
233 coro_init_identifiers ()
235 coro_traits_identifier = get_identifier ("coroutine_traits");
236 coro_handle_identifier = get_identifier ("coroutine_handle");
237 coro_promise_type_identifier = get_identifier ("promise_type");
239 coro_await_transform_identifier = get_identifier ("await_transform");
240 coro_initial_suspend_identifier = get_identifier ("initial_suspend");
241 coro_final_suspend_identifier = get_identifier ("final_suspend");
242 coro_return_void_identifier = get_identifier ("return_void");
243 coro_return_value_identifier = get_identifier ("return_value");
244 coro_yield_value_identifier = get_identifier ("yield_value");
245 coro_resume_identifier = get_identifier ("resume");
246 coro_address_identifier = get_identifier ("address");
247 coro_from_address_identifier = get_identifier ("from_address");
248 coro_get_return_object_identifier = get_identifier ("get_return_object");
249 coro_gro_on_allocation_fail_identifier =
250 get_identifier ("get_return_object_on_allocation_failure");
251 coro_unhandled_exception_identifier = get_identifier ("unhandled_exception");
253 coro_await_ready_identifier = get_identifier ("await_ready");
254 coro_await_suspend_identifier = get_identifier ("await_suspend");
255 coro_await_resume_identifier = get_identifier ("await_resume");
257 /* Coroutine state frame field accessors. */
258 coro_resume_fn_id = get_identifier ("_Coro_resume_fn");
259 coro_destroy_fn_id = get_identifier ("_Coro_destroy_fn");
260 coro_promise_id = get_identifier ("_Coro_promise");
261 coro_frame_needs_free_id = get_identifier ("_Coro_frame_needs_free");
262 coro_frame_i_a_r_c_id = get_identifier ("_Coro_initial_await_resume_called");
263 coro_resume_index_id = get_identifier ("_Coro_resume_index");
264 coro_self_handle_id = get_identifier ("_Coro_self_handle");
265 coro_actor_continue_id = get_identifier ("_Coro_actor_continue");
268 /* Trees we only need to set up once. */
270 static GTY(()) tree coro_traits_templ;
271 static GTY(()) tree coro_handle_templ;
272 static GTY(()) tree void_coro_handle_type;
274 /* ================= Parse, Semantics and Type checking ================= */
276 /* This initial set of routines are helper for the parsing and template
277 expansion phases.
279 At the completion of this, we will have completed trees for each of the
280 keywords, but making use of proxy variables for the self-handle and the
281 promise class instance. */
283 /* [coroutine.traits]
284 Lookup the coroutine_traits template decl. */
286 static tree
287 find_coro_traits_template_decl (location_t kw)
289 /* If we are missing fundamental information, such as the traits, (or the
290 declaration found is not a type template), then don't emit an error for
291 every keyword in a TU, just do it once. */
292 static bool traits_error_emitted = false;
294 tree traits_decl = lookup_qualified_name (std_node, coro_traits_identifier,
295 LOOK_want::NORMAL,
296 /*complain=*/!traits_error_emitted);
297 if (traits_decl == error_mark_node
298 || !DECL_TYPE_TEMPLATE_P (traits_decl))
300 if (!traits_error_emitted)
302 gcc_rich_location richloc (kw);
303 error_at (&richloc, "coroutines require a traits template; cannot"
304 " find %<%E::%E%>", std_node, coro_traits_identifier);
305 inform (&richloc, "perhaps %<#include <coroutine>%> is missing");
306 traits_error_emitted = true;
308 return NULL_TREE;
310 else
311 return traits_decl;
314 /* Instantiate Coroutine traits for the function signature. */
316 static tree
317 instantiate_coro_traits (tree fndecl, location_t kw)
319 /* [coroutine.traits.primary]
320 So now build up a type list for the template <typename _R, typename...>.
321 The types are the function's arg types and _R is the function return
322 type. */
324 tree functyp = TREE_TYPE (fndecl);
325 tree arg = DECL_ARGUMENTS (fndecl);
326 tree arg_node = TYPE_ARG_TYPES (functyp);
327 tree argtypes = make_tree_vec (list_length (arg_node)-1);
328 unsigned p = 0;
330 while (arg_node != NULL_TREE && !VOID_TYPE_P (TREE_VALUE (arg_node)))
332 if (is_this_parameter (arg)
333 || DECL_NAME (arg) == closure_identifier)
335 /* We pass a reference to *this to the param preview. */
336 tree ct = TREE_TYPE (TREE_TYPE (arg));
337 TREE_VEC_ELT (argtypes, p++) = cp_build_reference_type (ct, false);
339 else
340 TREE_VEC_ELT (argtypes, p++) = TREE_VALUE (arg_node);
342 arg_node = TREE_CHAIN (arg_node);
343 arg = DECL_CHAIN (arg);
346 tree argtypepack = cxx_make_type (TYPE_ARGUMENT_PACK);
347 ARGUMENT_PACK_ARGS (argtypepack) = argtypes;
349 tree targ = make_tree_vec (2);
350 TREE_VEC_ELT (targ, 0) = TREE_TYPE (functyp);
351 TREE_VEC_ELT (targ, 1) = argtypepack;
353 tree traits_class
354 = lookup_template_class (coro_traits_templ, targ,
355 /*in_decl=*/NULL_TREE, /*context=*/NULL_TREE,
356 /*entering scope=*/false, tf_warning_or_error);
358 if (traits_class == error_mark_node)
360 error_at (kw, "cannot instantiate %<coroutine traits%>");
361 return NULL_TREE;
364 return traits_class;
367 /* [coroutine.handle] */
369 static tree
370 find_coro_handle_template_decl (location_t kw)
372 /* As for the coroutine traits, this error is per TU, so only emit
373 it once. */
374 static bool coro_handle_error_emitted = false;
375 tree handle_decl = lookup_qualified_name (std_node, coro_handle_identifier,
376 LOOK_want::NORMAL,
377 !coro_handle_error_emitted);
378 if (handle_decl == error_mark_node
379 || !DECL_CLASS_TEMPLATE_P (handle_decl))
381 if (!coro_handle_error_emitted)
382 error_at (kw, "coroutines require a handle class template;"
383 " cannot find %<%E::%E%>", std_node, coro_handle_identifier);
384 coro_handle_error_emitted = true;
385 return NULL_TREE;
387 else
388 return handle_decl;
391 /* Instantiate the handle template for a given promise type. */
393 static tree
394 instantiate_coro_handle_for_promise_type (location_t kw, tree promise_type)
396 /* So now build up a type list for the template, one entry, the promise. */
397 tree targ = make_tree_vec (1);
398 TREE_VEC_ELT (targ, 0) = promise_type;
399 tree handle_type
400 = lookup_template_class (coro_handle_identifier, targ,
401 /* in_decl=*/NULL_TREE,
402 /* context=*/std_node,
403 /* entering scope=*/false, tf_warning_or_error);
405 if (handle_type == error_mark_node)
407 error_at (kw, "cannot instantiate a %<coroutine handle%> for"
408 " promise type %qT", promise_type);
409 return NULL_TREE;
412 return handle_type;
415 /* Look for the promise_type in the instantiated traits. */
417 static tree
418 find_promise_type (tree traits_class)
420 tree promise_type
421 = lookup_member (traits_class, coro_promise_type_identifier,
422 /* protect=*/1, /*want_type=*/true, tf_warning_or_error);
424 if (promise_type)
425 promise_type
426 = complete_type_or_else (TREE_TYPE (promise_type), promise_type);
428 /* NULL_TREE on fail. */
429 return promise_type;
432 static bool
433 coro_promise_type_found_p (tree fndecl, location_t loc)
435 gcc_assert (fndecl != NULL_TREE);
437 if (!coro_initialized)
439 /* Trees we only need to create once.
440 Set up the identifiers we will use. */
441 coro_init_identifiers ();
443 /* Coroutine traits template. */
444 coro_traits_templ = find_coro_traits_template_decl (loc);
445 if (coro_traits_templ == NULL_TREE)
446 return false;
448 /* coroutine_handle<> template. */
449 coro_handle_templ = find_coro_handle_template_decl (loc);
450 if (coro_handle_templ == NULL_TREE)
451 return false;
453 /* We can also instantiate the void coroutine_handle<> */
454 void_coro_handle_type =
455 instantiate_coro_handle_for_promise_type (loc, NULL_TREE);
456 if (void_coro_handle_type == NULL_TREE)
457 return false;
459 /* A table to hold the state, per coroutine decl. */
460 gcc_checking_assert (coroutine_info_table == NULL);
461 coroutine_info_table =
462 hash_table<coroutine_info_hasher>::create_ggc (11);
464 if (coroutine_info_table == NULL)
465 return false;
467 coro_initialized = true;
470 /* Save the coroutine data on the side to avoid the overhead on every
471 function decl tree. */
473 coroutine_info *coro_info = get_or_insert_coroutine_info (fndecl);
474 /* Without this, we cannot really proceed. */
475 gcc_checking_assert (coro_info);
477 /* If we don't already have a current promise type, try to look it up. */
478 if (coro_info->promise_type == NULL_TREE)
480 /* Get the coroutine traits template class instance for the function
481 signature we have - coroutine_traits <R, ...> */
483 tree templ_class = instantiate_coro_traits (fndecl, loc);
485 /* Find the promise type for that. */
486 coro_info->promise_type = find_promise_type (templ_class);
488 /* If we don't find it, punt on the rest. */
489 if (coro_info->promise_type == NULL_TREE)
491 if (!coro_info->coro_promise_error_emitted)
492 error_at (loc, "unable to find the promise type for"
493 " this coroutine");
494 coro_info->coro_promise_error_emitted = true;
495 return false;
498 /* Test for errors in the promise type that can be determined now. */
499 tree has_ret_void = lookup_member (coro_info->promise_type,
500 coro_return_void_identifier,
501 /*protect=*/1, /*want_type=*/0,
502 tf_none);
503 tree has_ret_val = lookup_member (coro_info->promise_type,
504 coro_return_value_identifier,
505 /*protect=*/1, /*want_type=*/0,
506 tf_none);
507 if (has_ret_void && has_ret_val)
509 location_t ploc = DECL_SOURCE_LOCATION (fndecl);
510 if (!coro_info->coro_co_return_error_emitted)
511 error_at (ploc, "the coroutine promise type %qT declares both"
512 " %<return_value%> and %<return_void%>",
513 coro_info->promise_type);
514 inform (DECL_SOURCE_LOCATION (BASELINK_FUNCTIONS (has_ret_void)),
515 "%<return_void%> declared here");
516 has_ret_val = BASELINK_FUNCTIONS (has_ret_val);
517 const char *message = "%<return_value%> declared here";
518 if (TREE_CODE (has_ret_val) == OVERLOAD)
520 has_ret_val = OVL_FIRST (has_ret_val);
521 message = "%<return_value%> first declared here";
523 inform (DECL_SOURCE_LOCATION (has_ret_val), message);
524 coro_info->coro_co_return_error_emitted = true;
525 return false;
528 /* Try to find the handle type for the promise. */
529 tree handle_type =
530 instantiate_coro_handle_for_promise_type (loc, coro_info->promise_type);
531 if (handle_type == NULL_TREE)
532 return false;
534 /* Complete this, we're going to use it. */
535 coro_info->handle_type = complete_type_or_else (handle_type, fndecl);
537 /* Diagnostic would be emitted by complete_type_or_else. */
538 if (!coro_info->handle_type)
539 return false;
541 /* Build a proxy for a handle to "self" as the param to
542 await_suspend() calls. */
543 coro_info->self_h_proxy
544 = build_lang_decl (VAR_DECL, coro_self_handle_id,
545 coro_info->handle_type);
547 /* Build a proxy for the promise so that we can perform lookups. */
548 coro_info->promise_proxy
549 = build_lang_decl (VAR_DECL, coro_promise_id,
550 coro_info->promise_type);
552 /* Note where we first saw a coroutine keyword. */
553 coro_info->first_coro_keyword = loc;
556 return true;
559 /* Map from actor or destroyer to ramp. */
560 static GTY(()) hash_map<tree, tree> *to_ramp;
562 /* Given a tree that is an actor or destroy, find the ramp function. */
564 tree
565 coro_get_ramp_function (tree decl)
567 if (!to_ramp)
568 return NULL_TREE;
569 tree *p = to_ramp->get (decl);
570 if (p)
571 return *p;
572 return NULL_TREE;
575 /* Given the DECL for a ramp function (the user's original declaration) return
576 the actor function if it has been defined. */
578 tree
579 coro_get_actor_function (tree decl)
581 if (coroutine_info *info = get_coroutine_info (decl))
582 return info->actor_decl;
584 return NULL_TREE;
587 /* Given the DECL for a ramp function (the user's original declaration) return
588 the destroy function if it has been defined. */
590 tree
591 coro_get_destroy_function (tree decl)
593 if (coroutine_info *info = get_coroutine_info (decl))
594 return info->destroy_decl;
596 return NULL_TREE;
599 /* These functions assumes that the caller has verified that the state for
600 the decl has been initialized, we try to minimize work here. */
602 static tree
603 get_coroutine_promise_type (tree decl)
605 if (coroutine_info *info = get_coroutine_info (decl))
606 return info->promise_type;
608 return NULL_TREE;
611 static tree
612 get_coroutine_handle_type (tree decl)
614 if (coroutine_info *info = get_coroutine_info (decl))
615 return info->handle_type;
617 return NULL_TREE;
620 static tree
621 get_coroutine_self_handle_proxy (tree decl)
623 if (coroutine_info *info = get_coroutine_info (decl))
624 return info->self_h_proxy;
626 return NULL_TREE;
629 static tree
630 get_coroutine_promise_proxy (tree decl)
632 if (coroutine_info *info = get_coroutine_info (decl))
633 return info->promise_proxy;
635 return NULL_TREE;
638 static tree
639 lookup_promise_method (tree fndecl, tree member_id, location_t loc,
640 bool musthave)
642 tree promise = get_coroutine_promise_type (fndecl);
643 tree pm_memb
644 = lookup_member (promise, member_id,
645 /*protect=*/1, /*want_type=*/0, tf_warning_or_error);
646 if (musthave && pm_memb == NULL_TREE)
648 error_at (loc, "no member named %qE in %qT", member_id, promise);
649 return error_mark_node;
651 return pm_memb;
654 /* Build an expression of the form p.method (args) where the p is a promise
655 object for the current coroutine.
656 OBJECT is the promise object instance to use, it may be NULL, in which case
657 we will use the promise_proxy instance for this coroutine.
658 ARGS may be NULL, for empty parm lists. */
660 static tree
661 coro_build_promise_expression (tree fn, tree promise_obj, tree member_id,
662 location_t loc, vec<tree, va_gc> **args,
663 bool musthave)
665 tree meth = lookup_promise_method (fn, member_id, loc, musthave);
666 if (meth == error_mark_node)
667 return error_mark_node;
669 /* If we don't find it, and it isn't needed, an empty return is OK. */
670 if (!meth)
671 return NULL_TREE;
673 tree promise
674 = promise_obj ? promise_obj
675 : get_coroutine_promise_proxy (current_function_decl);
676 tree expr;
677 if (BASELINK_P (meth))
678 expr = build_new_method_call (promise, meth, args, NULL_TREE,
679 LOOKUP_NORMAL, NULL, tf_warning_or_error);
680 else
682 expr = build_class_member_access_expr (promise, meth, NULL_TREE,
683 true, tf_warning_or_error);
684 vec<tree, va_gc> *real_args;
685 if (!args)
686 real_args = make_tree_vector ();
687 else
688 real_args = *args;
689 expr = build_op_call (expr, &real_args, tf_warning_or_error);
691 return expr;
694 /* Caching get for the expression p.return_void (). */
696 static tree
697 get_coroutine_return_void_expr (tree decl, location_t loc, bool musthave)
699 if (coroutine_info *info = get_coroutine_info (decl))
701 /* If we don't have it try to build it. */
702 if (!info->return_void)
703 info->return_void
704 = coro_build_promise_expression (current_function_decl, NULL,
705 coro_return_void_identifier,
706 loc, NULL, musthave);
707 /* Don't return an error if it's an optional call. */
708 if (!musthave && info->return_void == error_mark_node)
709 return NULL_TREE;
710 return info->return_void;
712 return musthave ? error_mark_node : NULL_TREE;
715 /* Lookup an Awaitable member, which should be await_ready, await_suspend
716 or await_resume. */
718 static tree
719 lookup_awaitable_member (tree await_type, tree member_id, location_t loc)
721 tree aw_memb
722 = lookup_member (await_type, member_id,
723 /*protect=*/1, /*want_type=*/0, tf_warning_or_error);
724 if (aw_memb == NULL_TREE)
726 error_at (loc, "no member named %qE in %qT", member_id, await_type);
727 return error_mark_node;
729 return aw_memb;
732 /* Here we check the constraints that are common to all keywords (since the
733 presence of a coroutine keyword makes the function into a coroutine). */
735 static bool
736 coro_common_keyword_context_valid_p (tree fndecl, location_t kw_loc,
737 const char *kw_name)
739 if (fndecl == NULL_TREE)
741 error_at (kw_loc, "%qs cannot be used outside a function", kw_name);
742 return false;
745 /* This is arranged in order of prohibitions in the std. */
746 if (DECL_MAIN_P (fndecl))
748 /* [basic.start.main] 3. The function main shall not be a coroutine. */
749 error_at (kw_loc, "%qs cannot be used in the %<main%> function",
750 kw_name);
751 return false;
754 if (DECL_DECLARED_CONSTEXPR_P (fndecl))
756 cp_function_chain->invalid_constexpr = true;
757 if (!is_instantiation_of_constexpr (fndecl))
759 /* [dcl.constexpr] 3.3 it shall not be a coroutine. */
760 error_at (kw_loc, "%qs cannot be used in a %<constexpr%> function",
761 kw_name);
762 return false;
766 if (FNDECL_USED_AUTO (fndecl))
768 /* [dcl.spec.auto] 15. A function declared with a return type that uses
769 a placeholder type shall not be a coroutine. */
770 error_at (kw_loc,
771 "%qs cannot be used in a function with a deduced return type",
772 kw_name);
773 return false;
776 if (varargs_function_p (fndecl))
778 /* [dcl.fct.def.coroutine] The parameter-declaration-clause of the
779 coroutine shall not terminate with an ellipsis that is not part
780 of a parameter-declaration. */
781 error_at (kw_loc,
782 "%qs cannot be used in a varargs function", kw_name);
783 return false;
786 if (DECL_CONSTRUCTOR_P (fndecl))
788 /* [class.ctor] 7. a constructor shall not be a coroutine. */
789 error_at (kw_loc, "%qs cannot be used in a constructor", kw_name);
790 return false;
793 if (DECL_DESTRUCTOR_P (fndecl))
795 /* [class.dtor] 21. a destructor shall not be a coroutine. */
796 error_at (kw_loc, "%qs cannot be used in a destructor", kw_name);
797 return false;
800 return true;
803 /* Here we check the constraints that are not per keyword. */
805 static bool
806 coro_function_valid_p (tree fndecl)
808 location_t f_loc = DECL_SOURCE_LOCATION (fndecl);
810 /* For cases where fundamental information cannot be found, e.g. the
811 coroutine traits are missing, we need to punt early. */
812 if (!coro_promise_type_found_p (fndecl, f_loc))
813 return false;
815 /* Since we think the function is a coroutine, that implies we parsed
816 a keyword that triggered this. Keywords check promise validity for
817 their context and thus the promise type should be known at this point. */
818 if (get_coroutine_handle_type (fndecl) == NULL_TREE
819 || get_coroutine_promise_type (fndecl) == NULL_TREE)
820 return false;
822 if (current_function_returns_value || current_function_returns_null)
824 /* TODO: record or extract positions of returns (and the first coro
825 keyword) so that we can add notes to the diagnostic about where
826 the bad keyword is and what made the function into a coro. */
827 error_at (f_loc, "a %<return%> statement is not allowed in coroutine;"
828 " did you mean %<co_return%>?");
829 return false;
832 return true;
835 enum suspend_point_kind {
836 CO_AWAIT_SUSPEND_POINT = 0,
837 CO_YIELD_SUSPEND_POINT,
838 INITIAL_SUSPEND_POINT,
839 FINAL_SUSPEND_POINT
842 /* Helper function to build a named variable for the temps we use for each
843 await point. The root of the name is determined by SUSPEND_KIND, and
844 the variable is of type V_TYPE. The awaitable number is reset each time
845 we encounter a final suspend. */
847 static tree
848 get_awaitable_var (suspend_point_kind suspend_kind, tree v_type)
850 static int awn = 0;
851 char *buf;
852 switch (suspend_kind)
854 default: buf = xasprintf ("Aw%d", awn++); break;
855 case CO_YIELD_SUSPEND_POINT: buf = xasprintf ("Yd%d", awn++); break;
856 case INITIAL_SUSPEND_POINT: buf = xasprintf ("Is"); break;
857 case FINAL_SUSPEND_POINT: buf = xasprintf ("Fs"); awn = 0; break;
859 tree ret = get_identifier (buf);
860 free (buf);
861 ret = build_lang_decl (VAR_DECL, ret, v_type);
862 DECL_ARTIFICIAL (ret) = true;
863 return ret;
866 /* Helpers to diagnose missing noexcept on final await expressions. */
868 static bool
869 coro_diagnose_throwing_fn (tree fndecl)
871 if (!TYPE_NOTHROW_P (TREE_TYPE (fndecl)))
873 location_t f_loc = cp_expr_loc_or_loc (fndecl,
874 DECL_SOURCE_LOCATION (fndecl));
875 error_at (f_loc, "the expression %qE is required to be non-throwing",
876 fndecl);
877 inform (f_loc, "must be declared with %<noexcept(true)%>");
878 return true;
880 return false;
883 static bool
884 coro_diagnose_throwing_final_aw_expr (tree expr)
886 if (TREE_CODE (expr) == TARGET_EXPR)
887 expr = TARGET_EXPR_INITIAL (expr);
888 tree fn = NULL_TREE;
889 if (TREE_CODE (expr) == CALL_EXPR)
890 fn = CALL_EXPR_FN (expr);
891 else if (TREE_CODE (expr) == AGGR_INIT_EXPR)
892 fn = AGGR_INIT_EXPR_FN (expr);
893 else if (TREE_CODE (expr) == CONSTRUCTOR)
894 return false;
895 else
897 gcc_checking_assert (0 && "unhandled expression type");
898 return false;
900 fn = TREE_OPERAND (fn, 0);
901 return coro_diagnose_throwing_fn (fn);
904 /* This performs [expr.await] bullet 3.3 and validates the interface obtained.
905 It is also used to build the initial and final suspend points.
907 'a', 'o' and 'e' are used as per the description in the section noted.
909 A, the original yield/await expr, is found at source location LOC.
911 We will be constructing a CO_AWAIT_EXPR for a suspend point of one of
912 the four suspend_point_kind kinds. This is indicated by SUSPEND_KIND. */
914 static tree
915 build_co_await (location_t loc, tree a, suspend_point_kind suspend_kind)
917 /* Try and overload of operator co_await, .... */
918 tree o;
919 if (MAYBE_CLASS_TYPE_P (TREE_TYPE (a)))
921 o = build_new_op (loc, CO_AWAIT_EXPR, LOOKUP_NORMAL, a, NULL_TREE,
922 NULL_TREE, NULL_TREE, NULL, tf_warning_or_error);
923 /* If no viable functions are found, o is a. */
924 if (!o || o == error_mark_node)
925 o = a;
926 else if (flag_exceptions && suspend_kind == FINAL_SUSPEND_POINT)
928 /* We found an overload for co_await(), diagnose throwing cases. */
929 if (TREE_CODE (o) == TARGET_EXPR
930 && coro_diagnose_throwing_final_aw_expr (o))
931 return error_mark_node;
933 /* We now know that the final suspend object is distinct from the
934 final awaiter, so check for a non-throwing DTOR where needed. */
935 tree a_type = TREE_TYPE (a);
936 if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (a_type))
937 if (tree dummy
938 = build_special_member_call (a, complete_dtor_identifier,
939 NULL, a_type, LOOKUP_NORMAL,
940 tf_none))
942 if (CONVERT_EXPR_P (dummy))
943 dummy = TREE_OPERAND (dummy, 0);
944 dummy = TREE_OPERAND (CALL_EXPR_FN (dummy), 0);
945 if (coro_diagnose_throwing_fn (dummy))
946 return error_mark_node;
950 else
951 o = a; /* This is most likely about to fail anyway. */
953 tree o_type = TREE_TYPE (o);
954 if (o_type && !VOID_TYPE_P (o_type))
955 o_type = complete_type_or_else (o_type, o);
957 if (!o_type)
958 return error_mark_node;
960 if (TREE_CODE (o_type) != RECORD_TYPE)
962 error_at (loc, "awaitable type %qT is not a structure",
963 o_type);
964 return error_mark_node;
967 /* Check for required awaitable members and their types. */
968 tree awrd_meth
969 = lookup_awaitable_member (o_type, coro_await_ready_identifier, loc);
970 if (!awrd_meth || awrd_meth == error_mark_node)
971 return error_mark_node;
972 tree awsp_meth
973 = lookup_awaitable_member (o_type, coro_await_suspend_identifier, loc);
974 if (!awsp_meth || awsp_meth == error_mark_node)
975 return error_mark_node;
977 /* The type of the co_await is the return type of the awaitable's
978 await_resume, so we need to look that up. */
979 tree awrs_meth
980 = lookup_awaitable_member (o_type, coro_await_resume_identifier, loc);
981 if (!awrs_meth || awrs_meth == error_mark_node)
982 return error_mark_node;
984 /* To complete the lookups, we need an instance of 'e' which is built from
985 'o' according to [expr.await] 3.4.
987 If we need to materialize this as a temporary, then that will have to be
988 'promoted' to a coroutine frame var. However, if the awaitable is a
989 user variable, parameter or comes from a scope outside this function,
990 then we must use it directly - or we will see unnecessary copies.
992 If o is a variable, find the underlying var. */
993 tree e_proxy = STRIP_NOPS (o);
994 if (INDIRECT_REF_P (e_proxy))
995 e_proxy = TREE_OPERAND (e_proxy, 0);
996 while (TREE_CODE (e_proxy) == COMPONENT_REF)
998 e_proxy = TREE_OPERAND (e_proxy, 0);
999 if (INDIRECT_REF_P (e_proxy))
1000 e_proxy = TREE_OPERAND (e_proxy, 0);
1001 if (TREE_CODE (e_proxy) == CALL_EXPR)
1003 /* We could have operator-> here too. */
1004 tree op = TREE_OPERAND (CALL_EXPR_FN (e_proxy), 0);
1005 if (DECL_OVERLOADED_OPERATOR_P (op)
1006 && DECL_OVERLOADED_OPERATOR_IS (op, COMPONENT_REF))
1008 e_proxy = CALL_EXPR_ARG (e_proxy, 0);
1009 STRIP_NOPS (e_proxy);
1010 gcc_checking_assert (TREE_CODE (e_proxy) == ADDR_EXPR);
1011 e_proxy = TREE_OPERAND (e_proxy, 0);
1014 STRIP_NOPS (e_proxy);
1017 /* Only build a temporary if we need it. */
1018 STRIP_NOPS (e_proxy);
1019 if (TREE_CODE (e_proxy) == PARM_DECL
1020 || (VAR_P (e_proxy) && !is_local_temp (e_proxy)))
1022 e_proxy = o;
1023 o = NULL_TREE; /* The var is already present. */
1025 else
1027 e_proxy = get_awaitable_var (suspend_kind, o_type);
1028 o = cp_build_modify_expr (loc, e_proxy, INIT_EXPR, o,
1029 tf_warning_or_error);
1032 /* I suppose we could check that this is contextually convertible to bool. */
1033 tree awrd_func = NULL_TREE;
1034 tree awrd_call
1035 = build_new_method_call (e_proxy, awrd_meth, NULL, NULL_TREE, LOOKUP_NORMAL,
1036 &awrd_func, tf_warning_or_error);
1038 if (!awrd_func || !awrd_call || awrd_call == error_mark_node)
1039 return error_mark_node;
1041 /* The suspend method may return one of three types:
1042 1. void (no special action needed).
1043 2. bool (if true, we don't need to suspend).
1044 3. a coroutine handle, we execute the handle.resume() call. */
1045 tree awsp_func = NULL_TREE;
1046 tree h_proxy = get_coroutine_self_handle_proxy (current_function_decl);
1047 vec<tree, va_gc> *args = make_tree_vector_single (h_proxy);
1048 tree awsp_call
1049 = build_new_method_call (e_proxy, awsp_meth, &args, NULL_TREE,
1050 LOOKUP_NORMAL, &awsp_func, tf_warning_or_error);
1052 release_tree_vector (args);
1053 if (!awsp_func || !awsp_call || awsp_call == error_mark_node)
1054 return error_mark_node;
1056 bool ok = false;
1057 tree susp_return_type = TREE_TYPE (TREE_TYPE (awsp_func));
1058 if (same_type_p (susp_return_type, void_type_node))
1059 ok = true;
1060 else if (same_type_p (susp_return_type, boolean_type_node))
1061 ok = true;
1062 else if (TREE_CODE (susp_return_type) == RECORD_TYPE
1063 && CLASS_TYPE_P (susp_return_type)
1064 && CLASSTYPE_TEMPLATE_INFO (susp_return_type))
1066 tree tt = CLASSTYPE_TI_TEMPLATE (susp_return_type);
1067 if (tt == coro_handle_templ)
1068 ok = true;
1071 if (!ok)
1073 error_at (loc, "%<await_suspend%> must return %<void%>, %<bool%> or"
1074 " a coroutine handle");
1075 return error_mark_node;
1078 /* Finally, the type of e.await_resume() is the co_await's type. */
1079 tree awrs_func = NULL_TREE;
1080 tree awrs_call
1081 = build_new_method_call (e_proxy, awrs_meth, NULL, NULL_TREE, LOOKUP_NORMAL,
1082 &awrs_func, tf_warning_or_error);
1084 if (!awrs_func || !awrs_call || awrs_call == error_mark_node)
1085 return error_mark_node;
1087 if (flag_exceptions && suspend_kind == FINAL_SUSPEND_POINT)
1089 if (coro_diagnose_throwing_fn (awrd_func))
1090 return error_mark_node;
1091 if (coro_diagnose_throwing_fn (awsp_func))
1092 return error_mark_node;
1093 if (coro_diagnose_throwing_fn (awrs_func))
1094 return error_mark_node;
1095 if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (o_type))
1096 if (tree dummy
1097 = build_special_member_call (e_proxy, complete_dtor_identifier,
1098 NULL, o_type, LOOKUP_NORMAL,
1099 tf_none))
1101 if (CONVERT_EXPR_P (dummy))
1102 dummy = TREE_OPERAND (dummy, 0);
1103 dummy = TREE_OPERAND (CALL_EXPR_FN (dummy), 0);
1104 if (coro_diagnose_throwing_fn (dummy))
1105 return error_mark_node;
1109 /* We now have three call expressions, in terms of the promise, handle and
1110 'e' proxies. Save them in the await expression for later expansion. */
1112 tree awaiter_calls = make_tree_vec (3);
1113 TREE_VEC_ELT (awaiter_calls, 0) = awrd_call; /* await_ready(). */
1114 TREE_VEC_ELT (awaiter_calls, 1) = awsp_call; /* await_suspend(). */
1115 tree te = NULL_TREE;
1116 if (TREE_CODE (awrs_call) == TARGET_EXPR)
1118 te = awrs_call;
1119 awrs_call = TREE_OPERAND (awrs_call, 1);
1121 TREE_VEC_ELT (awaiter_calls, 2) = awrs_call; /* await_resume(). */
1123 tree await_expr = build5_loc (loc, CO_AWAIT_EXPR,
1124 TREE_TYPE (TREE_TYPE (awrs_func)),
1125 a, e_proxy, o, awaiter_calls,
1126 build_int_cst (integer_type_node,
1127 (int) suspend_kind));
1128 TREE_SIDE_EFFECTS (await_expr) = true;
1129 if (te)
1131 TREE_OPERAND (te, 1) = await_expr;
1132 TREE_SIDE_EFFECTS (te) = true;
1133 await_expr = te;
1135 SET_EXPR_LOCATION (await_expr, loc);
1136 return convert_from_reference (await_expr);
1139 tree
1140 finish_co_await_expr (location_t kw, tree expr)
1142 if (!expr || error_operand_p (expr))
1143 return error_mark_node;
1145 if (!coro_common_keyword_context_valid_p (current_function_decl, kw,
1146 "co_await"))
1147 return error_mark_node;
1149 /* The current function has now become a coroutine, if it wasn't already. */
1150 DECL_COROUTINE_P (current_function_decl) = 1;
1152 /* This function will appear to have no return statement, even if it
1153 is declared to return non-void (most likely). This is correct - we
1154 synthesize the return for the ramp in the compiler. So suppress any
1155 extraneous warnings during substitution. */
1156 suppress_warning (current_function_decl, OPT_Wreturn_type);
1158 /* Defer expansion when we are processing a template.
1159 FIXME: If the coroutine function's type is not dependent, and the operand
1160 is not dependent, we should determine the type of the co_await expression
1161 using the DEPENDENT_EXPR wrapper machinery. That allows us to determine
1162 the subexpression type, but leave its operand unchanged and then
1163 instantiate it later. */
1164 if (processing_template_decl)
1166 tree aw_expr = build5_loc (kw, CO_AWAIT_EXPR, unknown_type_node, expr,
1167 NULL_TREE, NULL_TREE, NULL_TREE,
1168 integer_zero_node);
1169 TREE_SIDE_EFFECTS (aw_expr) = true;
1170 return aw_expr;
1173 /* We must be able to look up the "await_transform" method in the scope of
1174 the promise type, and obtain its return type. */
1175 if (!coro_promise_type_found_p (current_function_decl, kw))
1176 return error_mark_node;
1178 /* [expr.await] 3.2
1179 The incoming cast expression might be transformed by a promise
1180 'await_transform()'. */
1181 tree at_meth
1182 = lookup_promise_method (current_function_decl,
1183 coro_await_transform_identifier, kw,
1184 /*musthave=*/false);
1185 if (at_meth == error_mark_node)
1186 return error_mark_node;
1188 tree a = expr;
1189 if (at_meth)
1191 /* try to build a = p.await_transform (e). */
1192 vec<tree, va_gc> *args = make_tree_vector_single (expr);
1193 a = build_new_method_call (get_coroutine_promise_proxy (
1194 current_function_decl),
1195 at_meth, &args, NULL_TREE, LOOKUP_NORMAL,
1196 NULL, tf_warning_or_error);
1198 /* As I read the section.
1199 We saw an await_transform method, so it's mandatory that we replace
1200 expr with p.await_transform (expr), therefore if the method call fails
1201 (presumably, we don't have suitable arguments) then this part of the
1202 process fails. */
1203 if (a == error_mark_node)
1204 return error_mark_node;
1207 /* Now we want to build co_await a. */
1208 return build_co_await (kw, a, CO_AWAIT_SUSPEND_POINT);
1211 /* Take the EXPR given and attempt to build:
1212 co_await p.yield_value (expr);
1213 per [expr.yield] para 1. */
1215 tree
1216 finish_co_yield_expr (location_t kw, tree expr)
1218 if (!expr || error_operand_p (expr))
1219 return error_mark_node;
1221 /* Check the general requirements and simple syntax errors. */
1222 if (!coro_common_keyword_context_valid_p (current_function_decl, kw,
1223 "co_yield"))
1224 return error_mark_node;
1226 /* The current function has now become a coroutine, if it wasn't already. */
1227 DECL_COROUTINE_P (current_function_decl) = 1;
1229 /* This function will appear to have no return statement, even if it
1230 is declared to return non-void (most likely). This is correct - we
1231 synthesize the return for the ramp in the compiler. So suppress any
1232 extraneous warnings during substitution. */
1233 suppress_warning (current_function_decl, OPT_Wreturn_type);
1235 /* Defer expansion when we are processing a template; see FIXME in the
1236 co_await code. */
1237 if (processing_template_decl)
1238 return build2_loc (kw, CO_YIELD_EXPR, unknown_type_node, expr, NULL_TREE);
1240 if (!coro_promise_type_found_p (current_function_decl, kw))
1241 /* We must be able to look up the "yield_value" method in the scope of
1242 the promise type, and obtain its return type. */
1243 return error_mark_node;
1245 /* [expr.yield] / 1
1246 Let e be the operand of the yield-expression and p be an lvalue naming
1247 the promise object of the enclosing coroutine, then the yield-expression
1248 is equivalent to the expression co_await p.yield_value(e).
1249 build p.yield_value(e): */
1250 vec<tree, va_gc> *args = make_tree_vector_single (expr);
1251 tree yield_call
1252 = coro_build_promise_expression (current_function_decl, NULL,
1253 coro_yield_value_identifier, kw,
1254 &args, /*musthave=*/true);
1255 release_tree_vector (args);
1257 /* Now build co_await p.yield_value (e).
1258 Noting that for co_yield, there is no evaluation of any potential
1259 promise transform_await(), so we call build_co_await directly. */
1261 tree op = build_co_await (kw, yield_call, CO_YIELD_SUSPEND_POINT);
1262 if (op != error_mark_node)
1264 if (REFERENCE_REF_P (op))
1265 op = TREE_OPERAND (op, 0);
1266 /* If the await expression is wrapped in a TARGET_EXPR, then transfer
1267 that wrapper to the CO_YIELD_EXPR, since this is just a proxy for
1268 its contained await. Otherwise, just build the CO_YIELD_EXPR. */
1269 if (TREE_CODE (op) == TARGET_EXPR)
1271 tree t = TREE_OPERAND (op, 1);
1272 t = build2_loc (kw, CO_YIELD_EXPR, TREE_TYPE (t), expr, t);
1273 TREE_OPERAND (op, 1) = t;
1275 else
1276 op = build2_loc (kw, CO_YIELD_EXPR, TREE_TYPE (op), expr, op);
1277 TREE_SIDE_EFFECTS (op) = 1;
1278 op = convert_from_reference (op);
1281 return op;
1284 /* Check and build a co_return statement.
1285 First that it's valid to have a co_return keyword here.
1286 If it is, then check and build the p.return_{void(),value(expr)}.
1287 These are built against a proxy for the promise, which will be filled
1288 in with the actual frame version when the function is transformed. */
1290 tree
1291 finish_co_return_stmt (location_t kw, tree expr)
1293 if (expr)
1294 STRIP_ANY_LOCATION_WRAPPER (expr);
1296 if (error_operand_p (expr))
1297 return error_mark_node;
1299 /* If it fails the following test, the function is not permitted to be a
1300 coroutine, so the co_return statement is erroneous. */
1301 if (!coro_common_keyword_context_valid_p (current_function_decl, kw,
1302 "co_return"))
1303 return error_mark_node;
1305 /* The current function has now become a coroutine, if it wasn't
1306 already. */
1307 DECL_COROUTINE_P (current_function_decl) = 1;
1309 /* This function will appear to have no return statement, even if it
1310 is declared to return non-void (most likely). This is correct - we
1311 synthesize the return for the ramp in the compiler. So suppress any
1312 extraneous warnings during substitution. */
1313 suppress_warning (current_function_decl, OPT_Wreturn_type);
1315 if (processing_template_decl
1316 && check_for_bare_parameter_packs (expr))
1317 return error_mark_node;
1319 /* Defer expansion when we are processing a template; see FIXME in the
1320 co_await code. */
1321 if (processing_template_decl)
1323 /* co_return expressions are always void type, regardless of the
1324 expression type. */
1325 expr = build2_loc (kw, CO_RETURN_EXPR, void_type_node,
1326 expr, NULL_TREE);
1327 expr = maybe_cleanup_point_expr_void (expr);
1328 return add_stmt (expr);
1331 if (!coro_promise_type_found_p (current_function_decl, kw))
1332 return error_mark_node;
1334 /* Suppress -Wreturn-type for co_return, we need to check indirectly
1335 whether the promise type has a suitable return_void/return_value. */
1336 suppress_warning (current_function_decl, OPT_Wreturn_type);
1338 if (!processing_template_decl && warn_sequence_point)
1339 verify_sequence_points (expr);
1341 if (expr)
1343 /* If we had an id-expression obfuscated by force_paren_expr, we need
1344 to undo it so we can try to treat it as an rvalue below. */
1345 expr = maybe_undo_parenthesized_ref (expr);
1347 if (processing_template_decl)
1348 expr = build_non_dependent_expr (expr);
1350 if (error_operand_p (expr))
1351 return error_mark_node;
1354 /* If the promise object doesn't have the correct return call then
1355 there's a mis-match between the co_return <expr> and this. */
1356 tree co_ret_call = error_mark_node;
1357 if (expr == NULL_TREE || VOID_TYPE_P (TREE_TYPE (expr)))
1358 co_ret_call
1359 = get_coroutine_return_void_expr (current_function_decl, kw, true);
1360 else
1362 /* [class.copy.elision] / 3.
1363 An implicitly movable entity is a variable of automatic storage
1364 duration that is either a non-volatile object or an rvalue reference
1365 to a non-volatile object type. For such objects in the context of
1366 the co_return, the overload resolution should be carried out first
1367 treating the object as an rvalue, if that fails, then we fall back
1368 to regular overload resolution. */
1370 tree arg = expr;
1371 if (tree moved = treat_lvalue_as_rvalue_p (expr, /*return*/true))
1372 arg = moved;
1374 releasing_vec args = make_tree_vector_single (arg);
1375 co_ret_call
1376 = coro_build_promise_expression (current_function_decl, NULL,
1377 coro_return_value_identifier, kw,
1378 &args, /*musthave=*/true);
1381 /* Makes no sense for a co-routine really. */
1382 if (TREE_THIS_VOLATILE (current_function_decl))
1383 warning_at (kw, 0,
1384 "function declared %<noreturn%> has a"
1385 " %<co_return%> statement");
1387 expr = build2_loc (kw, CO_RETURN_EXPR, void_type_node, expr, co_ret_call);
1388 expr = maybe_cleanup_point_expr_void (expr);
1389 return add_stmt (expr);
1392 /* We need to validate the arguments to __builtin_coro_promise, since the
1393 second two must be constant, and the builtins machinery doesn't seem to
1394 deal with that properly. */
1396 tree
1397 coro_validate_builtin_call (tree call, tsubst_flags_t)
1399 tree fn = TREE_OPERAND (CALL_EXPR_FN (call), 0);
1401 gcc_checking_assert (DECL_BUILT_IN_CLASS (fn) == BUILT_IN_NORMAL);
1402 switch (DECL_FUNCTION_CODE (fn))
1404 default:
1405 return call;
1407 case BUILT_IN_CORO_PROMISE:
1409 /* Argument 0 is already checked by the normal built-in machinery
1410 Argument 1 must be a constant of size type. It probably makes
1411 little sense if it's not a power of 2, but that isn't specified
1412 formally. */
1413 tree arg = CALL_EXPR_ARG (call, 1);
1414 location_t loc = EXPR_LOCATION (arg);
1416 /* We expect alignof expressions in templates. */
1417 if (TREE_CODE (arg) == NON_DEPENDENT_EXPR
1418 && TREE_CODE (TREE_OPERAND (arg, 0)) == ALIGNOF_EXPR)
1420 else if (!TREE_CONSTANT (arg))
1422 error_at (loc, "the align argument to %<__builtin_coro_promise%>"
1423 " must be a constant");
1424 return error_mark_node;
1426 /* Argument 2 is the direction - to / from handle address to promise
1427 address. */
1428 arg = CALL_EXPR_ARG (call, 2);
1429 loc = EXPR_LOCATION (arg);
1430 if (!TREE_CONSTANT (arg))
1432 error_at (loc, "the direction argument to"
1433 " %<__builtin_coro_promise%> must be a constant");
1434 return error_mark_node;
1436 return call;
1437 break;
1442 /* ================= Morph and Expand. =================
1444 The entry point here is morph_fn_to_coro () which is called from
1445 finish_function () when we have completed any template expansion.
1447 This is preceded by helper functions that implement the phases below.
1449 The process proceeds in four phases.
1451 A Initial framing.
1452 The user's function body is wrapped in the initial and final suspend
1453 points and we begin building the coroutine frame.
1454 We build empty decls for the actor and destroyer functions at this
1455 time too.
1456 When exceptions are enabled, the user's function body will also be
1457 wrapped in a try-catch block with the catch invoking the promise
1458 class 'unhandled_exception' method.
1460 B Analysis.
1461 The user's function body is analyzed to determine the suspend points,
1462 if any, and to capture local variables that might persist across such
1463 suspensions. In most cases, it is not necessary to capture compiler
1464 temporaries, since the tree-lowering nests the suspensions correctly.
1465 However, in the case of a captured reference, there is a lifetime
1466 extension to the end of the full expression - which can mean across a
1467 suspend point in which case it must be promoted to a frame variable.
1469 At the conclusion of analysis, we have a conservative frame layout and
1470 maps of the local variables to their frame entry points.
1472 C Build the ramp function.
1473 Carry out the allocation for the coroutine frame (NOTE; the actual size
1474 computation is deferred until late in the middle end to allow for future
1475 optimizations that will be allowed to elide unused frame entries).
1476 We build the return object.
1478 D Build and expand the actor and destroyer function bodies.
1479 The destroyer is a trivial shim that sets a bit to indicate that the
1480 destroy dispatcher should be used and then calls into the actor.
1482 The actor function is the implementation of the user's state machine.
1483 The current suspend point is noted in an index.
1484 Each suspend point is encoded as a pair of internal functions, one in
1485 the relevant dispatcher, and one representing the suspend point.
1487 During this process, the user's local variables and the proxies for the
1488 self-handle and the promise class instance are re-written to their
1489 coroutine frame equivalents.
1491 The complete bodies for the ramp, actor and destroy function are passed
1492 back to finish_function for folding and gimplification. */
1494 /* Helpers to build EXPR_STMT and void-cast EXPR_STMT, common ops. */
1496 static tree
1497 coro_build_expr_stmt (tree expr, location_t loc)
1499 return maybe_cleanup_point_expr_void (build_stmt (loc, EXPR_STMT, expr));
1502 static tree
1503 coro_build_cvt_void_expr_stmt (tree expr, location_t loc)
1505 tree t = build1 (CONVERT_EXPR, void_type_node, expr);
1506 return coro_build_expr_stmt (t, loc);
1509 /* Helpers to build an artificial var, with location LOC, NAME and TYPE, in
1510 CTX, and with initializer INIT. */
1512 static tree
1513 coro_build_artificial_var (location_t loc, tree name, tree type, tree ctx,
1514 tree init)
1516 tree res = build_lang_decl (VAR_DECL, name, type);
1517 DECL_SOURCE_LOCATION (res) = loc;
1518 DECL_CONTEXT (res) = ctx;
1519 DECL_ARTIFICIAL (res) = true;
1520 DECL_INITIAL (res) = init;
1521 return res;
1524 static tree
1525 coro_build_artificial_var (location_t loc, const char *name, tree type,
1526 tree ctx, tree init)
1528 return coro_build_artificial_var (loc, get_identifier (name),
1529 type, ctx, init);
1532 /* Helpers for label creation:
1533 1. Create a named label in the specified context. */
1535 static tree
1536 create_anon_label_with_ctx (location_t loc, tree ctx)
1538 tree lab = build_decl (loc, LABEL_DECL, NULL_TREE, void_type_node);
1540 DECL_CONTEXT (lab) = ctx;
1541 DECL_ARTIFICIAL (lab) = true;
1542 DECL_IGNORED_P (lab) = true;
1543 TREE_USED (lab) = true;
1544 return lab;
1547 /* 2. Create a named label in the specified context. */
1549 static tree
1550 create_named_label_with_ctx (location_t loc, const char *name, tree ctx)
1552 tree lab_id = get_identifier (name);
1553 tree lab = define_label (loc, lab_id);
1554 DECL_CONTEXT (lab) = ctx;
1555 DECL_ARTIFICIAL (lab) = true;
1556 TREE_USED (lab) = true;
1557 return lab;
1560 struct proxy_replace
1562 tree from, to;
1565 static tree
1566 replace_proxy (tree *here, int *do_subtree, void *d)
1568 proxy_replace *data = (proxy_replace *) d;
1570 if (*here == data->from)
1572 *here = data->to;
1573 *do_subtree = 0;
1575 else
1576 *do_subtree = 1;
1577 return NULL_TREE;
1580 /* Support for expansion of co_await statements. */
1582 struct coro_aw_data
1584 tree actor_fn; /* Decl for context. */
1585 tree coro_fp; /* Frame pointer var. */
1586 tree resume_idx; /* This is the index var in the frame. */
1587 tree i_a_r_c; /* initial suspend await_resume() was called if true. */
1588 tree self_h; /* This is a handle to the current coro (frame var). */
1589 tree cleanup; /* This is where to go once we complete local destroy. */
1590 tree cororet; /* This is where to go if we suspend. */
1591 tree corocont; /* This is where to go if we continue. */
1592 tree conthand; /* This is the handle for a continuation. */
1593 unsigned index; /* This is our current resume index. */
1596 /* Lightweight search for the first await expression in tree-walk order.
1597 returns:
1598 The first await expression found in STMT.
1599 NULL_TREE if there are none.
1600 So can be used to determine if the statement needs to be processed for
1601 awaits. */
1603 static tree
1604 co_await_find_in_subtree (tree *stmt, int *, void *d)
1606 tree **p = (tree **) d;
1607 if (TREE_CODE (*stmt) == CO_AWAIT_EXPR)
1609 *p = stmt;
1610 return *stmt;
1612 return NULL_TREE;
1615 /* Starting with a statement:
1617 stmt => some tree containing one or more await expressions.
1619 We replace the statement with:
1620 <STATEMENT_LIST> {
1621 initialize awaitable
1622 if (!ready)
1624 suspension context.
1626 resume:
1627 revised statement with one await expression rewritten to its
1628 await_resume() return value.
1631 We then recurse into the initializer and the revised statement
1632 repeating this replacement until there are no more await expressions
1633 in either. */
1635 static tree *
1636 expand_one_await_expression (tree *stmt, tree *await_expr, void *d)
1638 coro_aw_data *data = (coro_aw_data *) d;
1640 tree saved_statement = *stmt;
1641 tree saved_co_await = *await_expr;
1643 tree actor = data->actor_fn;
1644 location_t loc = EXPR_LOCATION (*stmt);
1645 tree var = TREE_OPERAND (saved_co_await, 1); /* frame slot. */
1646 tree expr = TREE_OPERAND (saved_co_await, 2); /* initializer. */
1647 tree awaiter_calls = TREE_OPERAND (saved_co_await, 3);
1649 tree source = TREE_OPERAND (saved_co_await, 4);
1650 bool is_final = (source
1651 && TREE_INT_CST_LOW (source) == (int) FINAL_SUSPEND_POINT);
1652 bool needs_dtor = TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (var));
1653 int resume_point = data->index;
1654 size_t bufsize = sizeof ("destroy.") + 10;
1655 char *buf = (char *) alloca (bufsize);
1656 snprintf (buf, bufsize, "destroy.%d", resume_point);
1657 tree destroy_label = create_named_label_with_ctx (loc, buf, actor);
1658 snprintf (buf, bufsize, "resume.%d", resume_point);
1659 tree resume_label = create_named_label_with_ctx (loc, buf, actor);
1660 tree empty_list = build_empty_stmt (loc);
1662 tree await_type = TREE_TYPE (var);
1663 tree stmt_list = NULL;
1664 tree r;
1665 tree *await_init = NULL;
1667 if (!expr)
1668 needs_dtor = false; /* No need, the var's lifetime is managed elsewhere. */
1669 else
1671 r = coro_build_cvt_void_expr_stmt (expr, loc);
1672 append_to_statement_list_force (r, &stmt_list);
1673 /* We have an initializer, which might itself contain await exprs. */
1674 await_init = tsi_stmt_ptr (tsi_last (stmt_list));
1677 /* Use the await_ready() call to test if we need to suspend. */
1678 tree ready_cond = TREE_VEC_ELT (awaiter_calls, 0); /* await_ready(). */
1679 /* Convert to bool, if necessary. */
1680 if (TREE_CODE (TREE_TYPE (ready_cond)) != BOOLEAN_TYPE)
1681 ready_cond = cp_convert (boolean_type_node, ready_cond,
1682 tf_warning_or_error);
1683 /* Be aggressive in folding here, since there are a significant number of
1684 cases where the ready condition is constant. */
1685 ready_cond = invert_truthvalue_loc (loc, ready_cond);
1686 ready_cond
1687 = build1_loc (loc, CLEANUP_POINT_EXPR, boolean_type_node, ready_cond);
1689 tree body_list = NULL;
1690 tree susp_idx = build_int_cst (short_unsigned_type_node, data->index);
1691 r = build2_loc (loc, MODIFY_EXPR, short_unsigned_type_node, data->resume_idx,
1692 susp_idx);
1693 r = coro_build_cvt_void_expr_stmt (r, loc);
1694 append_to_statement_list (r, &body_list);
1696 /* Find out what we have to do with the awaiter's suspend method.
1697 [expr.await]
1698 (5.1) If the result of await-ready is false, the coroutine is considered
1699 suspended. Then:
1700 (5.1.1) If the type of await-suspend is std::coroutine_handle<Z>,
1701 await-suspend.resume() is evaluated.
1702 (5.1.2) if the type of await-suspend is bool, await-suspend is evaluated,
1703 and the coroutine is resumed if the result is false.
1704 (5.1.3) Otherwise, await-suspend is evaluated. */
1706 tree suspend = TREE_VEC_ELT (awaiter_calls, 1); /* await_suspend(). */
1707 tree susp_type = TREE_TYPE (suspend);
1709 bool is_cont = false;
1710 /* NOTE: final suspend can't resume; the "resume" label in that case
1711 corresponds to implicit destruction. */
1712 if (VOID_TYPE_P (susp_type))
1714 /* We just call await_suspend() and hit the yield. */
1715 suspend = coro_build_cvt_void_expr_stmt (suspend, loc);
1716 append_to_statement_list (suspend, &body_list);
1718 else if (TREE_CODE (susp_type) == BOOLEAN_TYPE)
1720 /* Boolean return, continue if the call returns false. */
1721 suspend = build1_loc (loc, TRUTH_NOT_EXPR, boolean_type_node, suspend);
1722 suspend
1723 = build1_loc (loc, CLEANUP_POINT_EXPR, boolean_type_node, suspend);
1724 tree go_on = build1_loc (loc, GOTO_EXPR, void_type_node, resume_label);
1725 r = build3_loc (loc, COND_EXPR, void_type_node, suspend, go_on,
1726 empty_list);
1727 append_to_statement_list (r, &body_list);
1729 else
1731 r = suspend;
1732 if (!same_type_ignoring_top_level_qualifiers_p (susp_type,
1733 void_coro_handle_type))
1734 r = build1_loc (loc, VIEW_CONVERT_EXPR, void_coro_handle_type, r);
1735 r = build2_loc (loc, INIT_EXPR, void_coro_handle_type, data->conthand, r);
1736 r = build1 (CONVERT_EXPR, void_type_node, r);
1737 append_to_statement_list (r, &body_list);
1738 is_cont = true;
1741 tree d_l = build_address (destroy_label);
1742 tree r_l = build_address (resume_label);
1743 tree susp = build_address (data->cororet);
1744 tree cont = build_address (data->corocont);
1745 tree final_susp = build_int_cst (integer_type_node, is_final ? 1 : 0);
1747 susp_idx = build_int_cst (integer_type_node, data->index);
1749 tree sw = begin_switch_stmt ();
1750 tree cond = build_decl (loc, VAR_DECL, NULL_TREE, integer_type_node);
1751 DECL_ARTIFICIAL (cond) = 1;
1752 DECL_IGNORED_P (cond) = 1;
1753 layout_decl (cond, 0);
1755 r = build_call_expr_internal_loc (loc, IFN_CO_YIELD, integer_type_node, 5,
1756 susp_idx, final_susp, r_l, d_l,
1757 data->coro_fp);
1758 r = build2 (INIT_EXPR, integer_type_node, cond, r);
1759 finish_switch_cond (r, sw);
1760 r = build_case_label (build_int_cst (integer_type_node, 0), NULL_TREE,
1761 create_anon_label_with_ctx (loc, actor));
1762 add_stmt (r); /* case 0: */
1763 /* Implement the suspend, a scope exit without clean ups. */
1764 r = build_call_expr_internal_loc (loc, IFN_CO_SUSPN, void_type_node, 1,
1765 is_cont ? cont : susp);
1766 r = coro_build_cvt_void_expr_stmt (r, loc);
1767 add_stmt (r); /* goto ret; */
1768 r = build_case_label (build_int_cst (integer_type_node, 1), NULL_TREE,
1769 create_anon_label_with_ctx (loc, actor));
1770 add_stmt (r); /* case 1: */
1771 r = build1_loc (loc, GOTO_EXPR, void_type_node, resume_label);
1772 add_stmt (r); /* goto resume; */
1773 r = build_case_label (NULL_TREE, NULL_TREE,
1774 create_anon_label_with_ctx (loc, actor));
1775 add_stmt (r); /* default:; */
1776 r = build1_loc (loc, GOTO_EXPR, void_type_node, destroy_label);
1777 add_stmt (r); /* goto destroy; */
1779 /* part of finish switch. */
1780 SWITCH_STMT_BODY (sw) = pop_stmt_list (SWITCH_STMT_BODY (sw));
1781 pop_switch ();
1782 tree scope = SWITCH_STMT_SCOPE (sw);
1783 SWITCH_STMT_SCOPE (sw) = NULL;
1784 r = do_poplevel (scope);
1785 append_to_statement_list (r, &body_list);
1787 destroy_label = build_stmt (loc, LABEL_EXPR, destroy_label);
1788 append_to_statement_list (destroy_label, &body_list);
1789 if (needs_dtor)
1791 tree dtor = build_special_member_call (var, complete_dtor_identifier,
1792 NULL, await_type, LOOKUP_NORMAL,
1793 tf_warning_or_error);
1794 append_to_statement_list (dtor, &body_list);
1796 r = build1_loc (loc, GOTO_EXPR, void_type_node, data->cleanup);
1797 append_to_statement_list (r, &body_list);
1799 r = build3_loc (loc, COND_EXPR, void_type_node, ready_cond, body_list,
1800 empty_list);
1802 append_to_statement_list (r, &stmt_list);
1804 /* Resume point. */
1805 resume_label = build_stmt (loc, LABEL_EXPR, resume_label);
1806 append_to_statement_list (resume_label, &stmt_list);
1808 /* This will produce the value (if one is provided) from the co_await
1809 expression. */
1810 tree resume_call = TREE_VEC_ELT (awaiter_calls, 2); /* await_resume(). */
1811 if (REFERENCE_REF_P (resume_call))
1812 /* Sink to await_resume call_expr. */
1813 resume_call = TREE_OPERAND (resume_call, 0);
1815 *await_expr = resume_call; /* Replace the co_await expr with its result. */
1816 append_to_statement_list_force (saved_statement, &stmt_list);
1817 /* Get a pointer to the revised statement. */
1818 tree *revised = tsi_stmt_ptr (tsi_last (stmt_list));
1819 if (needs_dtor)
1821 tree dtor = build_special_member_call (var, complete_dtor_identifier,
1822 NULL, await_type, LOOKUP_NORMAL,
1823 tf_warning_or_error);
1824 append_to_statement_list (dtor, &stmt_list);
1826 data->index += 2;
1828 /* Replace the original statement with the expansion. */
1829 *stmt = stmt_list;
1831 /* Now, if the awaitable had an initializer, expand any awaits that might
1832 be embedded in it. */
1833 tree *aw_expr_ptr;
1834 if (await_init &&
1835 cp_walk_tree (await_init, co_await_find_in_subtree, &aw_expr_ptr, NULL))
1836 expand_one_await_expression (await_init, aw_expr_ptr, d);
1838 /* Expand any more await expressions in the original statement. */
1839 if (cp_walk_tree (revised, co_await_find_in_subtree, &aw_expr_ptr, NULL))
1840 expand_one_await_expression (revised, aw_expr_ptr, d);
1842 return NULL;
1845 /* Check to see if a statement contains at least one await expression, if
1846 so, then process that. */
1848 static tree
1849 process_one_statement (tree *stmt, void *d)
1851 tree *aw_expr_ptr;
1852 if (cp_walk_tree (stmt, co_await_find_in_subtree, &aw_expr_ptr, NULL))
1853 expand_one_await_expression (stmt, aw_expr_ptr, d);
1854 return NULL_TREE;
1857 static tree
1858 await_statement_expander (tree *stmt, int *do_subtree, void *d)
1860 tree res = NULL_TREE;
1862 /* Process a statement at a time. */
1863 if (STATEMENT_CLASS_P (*stmt) || TREE_CODE (*stmt) == BIND_EXPR)
1864 return NULL_TREE; /* Just process the sub-trees. */
1865 else if (TREE_CODE (*stmt) == STATEMENT_LIST)
1867 for (tree &s : tsi_range (*stmt))
1869 res = cp_walk_tree (&s, await_statement_expander,
1870 d, NULL);
1871 if (res)
1872 return res;
1874 *do_subtree = 0; /* Done subtrees. */
1876 else if (EXPR_P (*stmt))
1878 process_one_statement (stmt, d);
1879 *do_subtree = 0; /* Done subtrees. */
1882 /* Continue statement walk, where required. */
1883 return res;
1886 /* Suspend point hash_map. */
1888 struct suspend_point_info
1890 /* coro frame field type. */
1891 tree awaitable_type;
1892 /* coro frame field name. */
1893 tree await_field_id;
1896 static hash_map<tree, suspend_point_info> *suspend_points;
1898 struct await_xform_data
1900 tree actor_fn; /* Decl for context. */
1901 tree actor_frame;
1904 /* When we built the await expressions, we didn't know the coro frame
1905 layout, therefore no idea where to find the promise or where to put
1906 the awaitables. Now we know these things, fill them in. */
1908 static tree
1909 transform_await_expr (tree await_expr, await_xform_data *xform)
1911 suspend_point_info *si = suspend_points->get (await_expr);
1912 location_t loc = EXPR_LOCATION (await_expr);
1913 if (!si)
1915 error_at (loc, "no suspend point info for %qD", await_expr);
1916 return error_mark_node;
1919 /* So, on entry, we have:
1920 in : CO_AWAIT_EXPR (a, e_proxy, o, awr_call_vector, mode)
1921 We no longer need a [it had diagnostic value, maybe?]
1922 We need to replace the e_proxy in the awr_call. */
1924 tree coro_frame_type = TREE_TYPE (xform->actor_frame);
1926 /* If we have a frame var for the awaitable, get a reference to it. */
1927 proxy_replace data;
1928 if (si->await_field_id)
1930 tree as_m
1931 = lookup_member (coro_frame_type, si->await_field_id,
1932 /*protect=*/1, /*want_type=*/0, tf_warning_or_error);
1933 tree as = build_class_member_access_expr (xform->actor_frame, as_m,
1934 NULL_TREE, true,
1935 tf_warning_or_error);
1937 /* Replace references to the instance proxy with the frame entry now
1938 computed. */
1939 data.from = TREE_OPERAND (await_expr, 1);
1940 data.to = as;
1941 cp_walk_tree (&await_expr, replace_proxy, &data, NULL);
1943 /* .. and replace. */
1944 TREE_OPERAND (await_expr, 1) = as;
1947 return await_expr;
1950 /* A wrapper for the transform_await_expr function so that it can be a
1951 callback from cp_walk_tree. */
1953 static tree
1954 transform_await_wrapper (tree *stmt, int *do_subtree, void *d)
1956 /* Set actor function as new DECL_CONTEXT of label_decl. */
1957 struct await_xform_data *xform = (struct await_xform_data *) d;
1958 if (TREE_CODE (*stmt) == LABEL_DECL
1959 && DECL_CONTEXT (*stmt) != xform->actor_fn)
1960 DECL_CONTEXT (*stmt) = xform->actor_fn;
1962 /* We should have already lowered co_yields to their co_await. */
1963 gcc_checking_assert (TREE_CODE (*stmt) != CO_YIELD_EXPR);
1964 if (TREE_CODE (*stmt) != CO_AWAIT_EXPR)
1965 return NULL_TREE;
1967 tree await_expr = *stmt;
1968 *stmt = transform_await_expr (await_expr, xform);
1969 if (*stmt == error_mark_node)
1970 *do_subtree = 0;
1971 return NULL_TREE;
1974 /* This caches information that we determine about function params,
1975 their uses and copies in the coroutine frame. */
1977 struct param_info
1979 tree field_id; /* The name of the copy in the coroutine frame. */
1980 tree copy_var; /* The local var proxy for the frame copy. */
1981 vec<tree *> *body_uses; /* Worklist of uses, void if there are none. */
1982 tree frame_type; /* The type used to represent this parm in the frame. */
1983 tree orig_type; /* The original type of the parm (not as passed). */
1984 tree guard_var; /* If we need a DTOR on exception, this bool guards it. */
1985 tree fr_copy_dtor; /* If we need a DTOR on exception, this is it. */
1986 bool by_ref; /* Was passed by reference. */
1987 bool pt_ref; /* Was a pointer to object. */
1988 bool rv_ref; /* Was an rvalue ref. */
1989 bool trivial_dtor; /* The frame type has a trivial DTOR. */
1990 bool this_ptr; /* Is 'this' */
1991 bool lambda_cobj; /* Lambda capture object */
1994 struct local_var_info
1996 tree field_id;
1997 tree field_idx;
1998 tree frame_type;
1999 bool is_lambda_capture;
2000 bool is_static;
2001 bool has_value_expr_p;
2002 location_t def_loc;
2005 /* For figuring out what local variable usage we have. */
2006 struct local_vars_transform
2008 tree context;
2009 tree actor_frame;
2010 tree coro_frame_type;
2011 location_t loc;
2012 hash_map<tree, local_var_info> *local_var_uses;
2015 static tree
2016 transform_local_var_uses (tree *stmt, int *do_subtree, void *d)
2018 local_vars_transform *lvd = (local_vars_transform *) d;
2020 /* For each var in this bind expr (that has a frame id, which means it was
2021 accessed), build a frame reference and add it as the DECL_VALUE_EXPR. */
2023 if (TREE_CODE (*stmt) == BIND_EXPR)
2025 tree lvar;
2026 for (lvar = BIND_EXPR_VARS (*stmt); lvar != NULL;
2027 lvar = DECL_CHAIN (lvar))
2029 bool existed;
2030 local_var_info &local_var
2031 = lvd->local_var_uses->get_or_insert (lvar, &existed);
2032 gcc_checking_assert (existed);
2034 /* Re-write the variable's context to be in the actor func. */
2035 DECL_CONTEXT (lvar) = lvd->context;
2037 /* For capture proxies, this could include the decl value expr. */
2038 if (local_var.is_lambda_capture || local_var.has_value_expr_p)
2039 continue; /* No frame entry for this. */
2041 /* TODO: implement selective generation of fields when vars are
2042 known not-used. */
2043 if (local_var.field_id == NULL_TREE)
2044 continue; /* Wasn't used. */
2046 tree fld_ref
2047 = lookup_member (lvd->coro_frame_type, local_var.field_id,
2048 /*protect=*/1, /*want_type=*/0,
2049 tf_warning_or_error);
2050 tree fld_idx = build3_loc (lvd->loc, COMPONENT_REF, TREE_TYPE (lvar),
2051 lvd->actor_frame, fld_ref, NULL_TREE);
2052 local_var.field_idx = fld_idx;
2053 SET_DECL_VALUE_EXPR (lvar, fld_idx);
2054 DECL_HAS_VALUE_EXPR_P (lvar) = true;
2056 cp_walk_tree (&BIND_EXPR_BODY (*stmt), transform_local_var_uses, d, NULL);
2057 *do_subtree = 0; /* We've done the body already. */
2058 return NULL_TREE;
2060 return NULL_TREE;
2063 /* A helper to build the frame DTOR.
2064 [dcl.fct.def.coroutine] / 12
2065 The deallocation function’s name is looked up in the scope of the promise
2066 type. If this lookup fails, the deallocation function’s name is looked up
2067 in the global scope. If deallocation function lookup finds both a usual
2068 deallocation function with only a pointer parameter and a usual
2069 deallocation function with both a pointer parameter and a size parameter,
2070 then the selected deallocation function shall be the one with two
2071 parameters. Otherwise, the selected deallocation function shall be the
2072 function with one parameter. If no usual deallocation function is found
2073 the program is ill-formed. The selected deallocation function shall be
2074 called with the address of the block of storage to be reclaimed as its
2075 first argument. If a deallocation function with a parameter of type
2076 std::size_t is used, the size of the block is passed as the corresponding
2077 argument. */
2079 static tree
2080 coro_get_frame_dtor (tree coro_fp, tree orig, tree frame_size,
2081 tree promise_type, location_t loc)
2083 tree del_coro_fr = NULL_TREE;
2084 tree frame_arg = build1 (CONVERT_EXPR, ptr_type_node, coro_fp);
2085 tree delname = ovl_op_identifier (false, DELETE_EXPR);
2086 tree fns = lookup_promise_method (orig, delname, loc,
2087 /*musthave=*/false);
2088 if (fns && BASELINK_P (fns))
2090 /* Look for sized version first, since this takes precedence. */
2091 vec<tree, va_gc> *args = make_tree_vector ();
2092 vec_safe_push (args, frame_arg);
2093 vec_safe_push (args, frame_size);
2094 tree dummy_promise = build_dummy_object (promise_type);
2096 /* It's OK to fail for this one... */
2097 del_coro_fr = build_new_method_call (dummy_promise, fns, &args,
2098 NULL_TREE, LOOKUP_NORMAL, NULL,
2099 tf_none);
2101 if (!del_coro_fr || del_coro_fr == error_mark_node)
2103 release_tree_vector (args);
2104 args = make_tree_vector_single (frame_arg);
2105 del_coro_fr = build_new_method_call (dummy_promise, fns, &args,
2106 NULL_TREE, LOOKUP_NORMAL, NULL,
2107 tf_none);
2110 /* But one of them must succeed, or the program is ill-formed. */
2111 if (!del_coro_fr || del_coro_fr == error_mark_node)
2113 error_at (loc, "%qE is provided by %qT but is not usable with"
2114 " the function signature %qD", delname, promise_type, orig);
2115 del_coro_fr = error_mark_node;
2118 else
2120 del_coro_fr = build_op_delete_call (DELETE_EXPR, frame_arg, frame_size,
2121 /*global_p=*/true, /*placement=*/NULL,
2122 /*alloc_fn=*/NULL,
2123 tf_warning_or_error);
2124 if (!del_coro_fr || del_coro_fr == error_mark_node)
2125 del_coro_fr = error_mark_node;
2127 return del_coro_fr;
2130 /* The actor transform. */
2132 static void
2133 build_actor_fn (location_t loc, tree coro_frame_type, tree actor, tree fnbody,
2134 tree orig, hash_map<tree, local_var_info> *local_var_uses,
2135 vec<tree, va_gc> *param_dtor_list,
2136 tree resume_idx_var, unsigned body_count, tree frame_size)
2138 verify_stmt_tree (fnbody);
2139 /* Some things we inherit from the original function. */
2140 tree handle_type = get_coroutine_handle_type (orig);
2141 tree promise_type = get_coroutine_promise_type (orig);
2142 tree promise_proxy = get_coroutine_promise_proxy (orig);
2144 /* One param, the coro frame pointer. */
2145 tree actor_fp = DECL_ARGUMENTS (actor);
2147 /* We have a definition here. */
2148 TREE_STATIC (actor) = 1;
2150 tree actor_outer = push_stmt_list ();
2151 current_stmt_tree ()->stmts_are_full_exprs_p = 1;
2152 tree stmt = begin_compound_stmt (BCS_FN_BODY);
2154 tree actor_bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
2155 tree top_block = make_node (BLOCK);
2156 BIND_EXPR_BLOCK (actor_bind) = top_block;
2158 tree continuation = coro_build_artificial_var (loc, coro_actor_continue_id,
2159 void_coro_handle_type, actor,
2160 NULL_TREE);
2162 BIND_EXPR_VARS (actor_bind) = continuation;
2163 BLOCK_VARS (top_block) = BIND_EXPR_VARS (actor_bind) ;
2165 /* Link in the block associated with the outer scope of the re-written
2166 function body. */
2167 tree first = expr_first (fnbody);
2168 gcc_checking_assert (first && TREE_CODE (first) == BIND_EXPR);
2169 tree block = BIND_EXPR_BLOCK (first);
2170 gcc_checking_assert (BLOCK_SUPERCONTEXT (block) == NULL_TREE);
2171 gcc_checking_assert (BLOCK_CHAIN (block) == NULL_TREE);
2172 BLOCK_SUPERCONTEXT (block) = top_block;
2173 BLOCK_SUBBLOCKS (top_block) = block;
2175 add_stmt (actor_bind);
2176 tree actor_body = push_stmt_list ();
2178 /* The entry point for the actor code from the ramp. */
2179 tree actor_begin_label
2180 = create_named_label_with_ctx (loc, "actor.begin", actor);
2181 tree actor_frame = build1_loc (loc, INDIRECT_REF, coro_frame_type, actor_fp);
2183 /* Declare the continuation handle. */
2184 add_decl_expr (continuation);
2186 /* Re-write local vars, similarly. */
2187 local_vars_transform xform_vars_data
2188 = {actor, actor_frame, coro_frame_type, loc, local_var_uses};
2189 cp_walk_tree (&fnbody, transform_local_var_uses, &xform_vars_data, NULL);
2191 tree rat_field = lookup_member (coro_frame_type, coro_resume_index_id,
2192 1, 0, tf_warning_or_error);
2193 tree rat = build3 (COMPONENT_REF, short_unsigned_type_node, actor_frame,
2194 rat_field, NULL_TREE);
2196 tree ret_label
2197 = create_named_label_with_ctx (loc, "actor.suspend.ret", actor);
2199 tree continue_label
2200 = create_named_label_with_ctx (loc, "actor.continue.ret", actor);
2202 tree lsb_if = begin_if_stmt ();
2203 tree chkb0 = build2 (BIT_AND_EXPR, short_unsigned_type_node, rat,
2204 build_int_cst (short_unsigned_type_node, 1));
2205 chkb0 = build2 (NE_EXPR, short_unsigned_type_node, chkb0,
2206 build_int_cst (short_unsigned_type_node, 0));
2207 finish_if_stmt_cond (chkb0, lsb_if);
2209 tree destroy_dispatcher = begin_switch_stmt ();
2210 finish_switch_cond (rat, destroy_dispatcher);
2211 tree ddeflab = build_case_label (NULL_TREE, NULL_TREE,
2212 create_anon_label_with_ctx (loc, actor));
2213 add_stmt (ddeflab);
2214 tree b = build_call_expr_loc (loc, builtin_decl_explicit (BUILT_IN_TRAP), 0);
2215 b = coro_build_cvt_void_expr_stmt (b, loc);
2216 add_stmt (b);
2218 /* The destroy point numbered #1 is special, in that it is reached from a
2219 coroutine that is suspended after re-throwing from unhandled_exception().
2220 This label just invokes the cleanup of promise, param copies and the
2221 frame itself. */
2222 tree del_promise_label
2223 = create_named_label_with_ctx (loc, "coro.delete.promise", actor);
2224 b = build_case_label (build_int_cst (short_unsigned_type_node, 1), NULL_TREE,
2225 create_anon_label_with_ctx (loc, actor));
2226 add_stmt (b);
2227 add_stmt (build_stmt (loc, GOTO_EXPR, del_promise_label));
2229 short unsigned lab_num = 3;
2230 for (unsigned destr_pt = 0; destr_pt < body_count; destr_pt++)
2232 tree l_num = build_int_cst (short_unsigned_type_node, lab_num);
2233 b = build_case_label (l_num, NULL_TREE,
2234 create_anon_label_with_ctx (loc, actor));
2235 add_stmt (b);
2236 b = build_call_expr_internal_loc (loc, IFN_CO_ACTOR, void_type_node, 1,
2237 l_num);
2238 b = coro_build_cvt_void_expr_stmt (b, loc);
2239 add_stmt (b);
2240 b = build1 (GOTO_EXPR, void_type_node, CASE_LABEL (ddeflab));
2241 add_stmt (b);
2242 lab_num += 2;
2245 /* Insert the prototype dispatcher. */
2246 finish_switch_stmt (destroy_dispatcher);
2248 finish_then_clause (lsb_if);
2249 begin_else_clause (lsb_if);
2251 tree dispatcher = begin_switch_stmt ();
2252 finish_switch_cond (rat, dispatcher);
2253 b = build_case_label (build_int_cst (short_unsigned_type_node, 0), NULL_TREE,
2254 create_anon_label_with_ctx (loc, actor));
2255 add_stmt (b);
2256 b = build1 (GOTO_EXPR, void_type_node, actor_begin_label);
2257 add_stmt (b);
2259 tree rdeflab = build_case_label (NULL_TREE, NULL_TREE,
2260 create_anon_label_with_ctx (loc, actor));
2261 add_stmt (rdeflab);
2262 b = build_call_expr_loc (loc, builtin_decl_explicit (BUILT_IN_TRAP), 0);
2263 b = coro_build_cvt_void_expr_stmt (b, loc);
2264 add_stmt (b);
2266 lab_num = 2;
2267 /* The final resume should be made to hit the default (trap, UB) entry
2268 although it will be unreachable via the normal entry point, since that
2269 is set to NULL on reaching final suspend. */
2270 for (unsigned resu_pt = 0; resu_pt < body_count; resu_pt++)
2272 tree l_num = build_int_cst (short_unsigned_type_node, lab_num);
2273 b = build_case_label (l_num, NULL_TREE,
2274 create_anon_label_with_ctx (loc, actor));
2275 add_stmt (b);
2276 b = build_call_expr_internal_loc (loc, IFN_CO_ACTOR, void_type_node, 1,
2277 l_num);
2278 b = coro_build_cvt_void_expr_stmt (b, loc);
2279 add_stmt (b);
2280 b = build1 (GOTO_EXPR, void_type_node, CASE_LABEL (rdeflab));
2281 add_stmt (b);
2282 lab_num += 2;
2285 /* Insert the prototype dispatcher. */
2286 finish_switch_stmt (dispatcher);
2287 finish_else_clause (lsb_if);
2289 finish_if_stmt (lsb_if);
2291 tree r = build_stmt (loc, LABEL_EXPR, actor_begin_label);
2292 add_stmt (r);
2294 /* actor's coroutine 'self handle'. */
2295 tree ash_m = lookup_member (coro_frame_type, coro_self_handle_id, 1,
2296 0, tf_warning_or_error);
2297 tree ash = build_class_member_access_expr (actor_frame, ash_m, NULL_TREE,
2298 false, tf_warning_or_error);
2299 /* So construct the self-handle from the frame address. */
2300 tree hfa_m = lookup_member (handle_type, coro_from_address_identifier, 1,
2301 0, tf_warning_or_error);
2303 r = build1 (CONVERT_EXPR, build_pointer_type (void_type_node), actor_fp);
2304 vec<tree, va_gc> *args = make_tree_vector_single (r);
2305 tree hfa = build_new_method_call (ash, hfa_m, &args, NULL_TREE, LOOKUP_NORMAL,
2306 NULL, tf_warning_or_error);
2307 r = build2 (INIT_EXPR, handle_type, ash, hfa);
2308 r = coro_build_cvt_void_expr_stmt (r, loc);
2309 add_stmt (r);
2310 release_tree_vector (args);
2312 /* Now we know the real promise, and enough about the frame layout to
2313 decide where to put things. */
2315 await_xform_data xform = {actor, actor_frame};
2317 /* Transform the await expressions in the function body. Only do each
2318 await tree once! */
2319 hash_set<tree> pset;
2320 cp_walk_tree (&fnbody, transform_await_wrapper, &xform, &pset);
2322 /* Add in our function body with the co_returns rewritten to final form. */
2323 add_stmt (fnbody);
2325 /* now do the tail of the function. */
2326 r = build_stmt (loc, LABEL_EXPR, del_promise_label);
2327 add_stmt (r);
2329 /* Destructors for the things we built explicitly. */
2330 r = build_special_member_call (promise_proxy, complete_dtor_identifier, NULL,
2331 promise_type, LOOKUP_NORMAL,
2332 tf_warning_or_error);
2333 add_stmt (r);
2335 tree del_frame_label
2336 = create_named_label_with_ctx (loc, "coro.delete.frame", actor);
2337 r = build_stmt (loc, LABEL_EXPR, del_frame_label);
2338 add_stmt (r);
2340 /* Here deallocate the frame (if we allocated it), which we will have at
2341 present. */
2342 tree fnf_m
2343 = lookup_member (coro_frame_type, coro_frame_needs_free_id, 1,
2344 0, tf_warning_or_error);
2345 tree fnf2_x = build_class_member_access_expr (actor_frame, fnf_m, NULL_TREE,
2346 false, tf_warning_or_error);
2348 tree need_free_if = begin_if_stmt ();
2349 fnf2_x = build1 (CONVERT_EXPR, integer_type_node, fnf2_x);
2350 tree cmp = build2 (NE_EXPR, integer_type_node, fnf2_x, integer_zero_node);
2351 finish_if_stmt_cond (cmp, need_free_if);
2352 if (param_dtor_list != NULL)
2354 int i;
2355 tree pid;
2356 FOR_EACH_VEC_ELT (*param_dtor_list, i, pid)
2358 tree m
2359 = lookup_member (coro_frame_type, pid, 1, 0, tf_warning_or_error);
2360 tree a = build_class_member_access_expr (actor_frame, m, NULL_TREE,
2361 false, tf_warning_or_error);
2362 tree t = TREE_TYPE (a);
2363 tree dtor;
2364 dtor
2365 = build_special_member_call (a, complete_dtor_identifier, NULL, t,
2366 LOOKUP_NORMAL, tf_warning_or_error);
2367 add_stmt (dtor);
2371 /* Build the frame DTOR. */
2372 tree del_coro_fr = coro_get_frame_dtor (actor_fp, orig, frame_size,
2373 promise_type, loc);
2374 finish_expr_stmt (del_coro_fr);
2375 finish_then_clause (need_free_if);
2376 tree scope = IF_SCOPE (need_free_if);
2377 IF_SCOPE (need_free_if) = NULL;
2378 r = do_poplevel (scope);
2379 add_stmt (r);
2381 /* done. */
2382 r = build_stmt (loc, RETURN_EXPR, NULL);
2383 suppress_warning (r); /* We don't want a warning about this. */
2384 r = maybe_cleanup_point_expr_void (r);
2385 add_stmt (r);
2387 /* This is the suspend return point. */
2388 r = build_stmt (loc, LABEL_EXPR, ret_label);
2389 add_stmt (r);
2391 r = build_stmt (loc, RETURN_EXPR, NULL);
2392 suppress_warning (r); /* We don't want a warning about this. */
2393 r = maybe_cleanup_point_expr_void (r);
2394 add_stmt (r);
2396 /* This is the 'continuation' return point. For such a case we have a coro
2397 handle (from the await_suspend() call) and we want handle.resume() to
2398 execute as a tailcall allowing arbitrary chaining of coroutines. */
2399 r = build_stmt (loc, LABEL_EXPR, continue_label);
2400 add_stmt (r);
2402 /* We want to force a tail-call even for O0/1, so this expands the resume
2403 call into its underlying implementation. */
2404 tree addr = lookup_member (void_coro_handle_type, coro_address_identifier,
2405 1, 0, tf_warning_or_error);
2406 addr = build_new_method_call (continuation, addr, NULL, NULL_TREE,
2407 LOOKUP_NORMAL, NULL, tf_warning_or_error);
2408 tree resume = build_call_expr_loc
2409 (loc, builtin_decl_explicit (BUILT_IN_CORO_RESUME), 1, addr);
2411 /* In order to support an arbitrary number of coroutine continuations,
2412 we must tail call them. However, some targets do not support indirect
2413 tail calls to arbitrary callees. See PR94359. */
2414 CALL_EXPR_TAILCALL (resume) = true;
2415 resume = coro_build_cvt_void_expr_stmt (resume, loc);
2416 add_stmt (resume);
2418 r = build_stmt (loc, RETURN_EXPR, NULL);
2419 gcc_checking_assert (maybe_cleanup_point_expr_void (r) == r);
2420 add_stmt (r);
2422 /* We've now rewritten the tree and added the initial and final
2423 co_awaits. Now pass over the tree and expand the co_awaits. */
2425 coro_aw_data data = {actor, actor_fp, resume_idx_var, NULL_TREE,
2426 ash, del_promise_label, ret_label,
2427 continue_label, continuation, 2};
2428 cp_walk_tree (&actor_body, await_statement_expander, &data, NULL);
2430 BIND_EXPR_BODY (actor_bind) = pop_stmt_list (actor_body);
2431 TREE_SIDE_EFFECTS (actor_bind) = true;
2433 finish_compound_stmt (stmt);
2434 DECL_SAVED_TREE (actor) = pop_stmt_list (actor_outer);
2435 verify_stmt_tree (DECL_SAVED_TREE (actor));
2438 /* The prototype 'destroy' function :
2439 frame->__Coro_resume_index |= 1;
2440 actor (frame); */
2442 static void
2443 build_destroy_fn (location_t loc, tree coro_frame_type, tree destroy,
2444 tree actor)
2446 /* One param, the coro frame pointer. */
2447 tree destr_fp = DECL_ARGUMENTS (destroy);
2449 /* We have a definition here. */
2450 TREE_STATIC (destroy) = 1;
2452 tree destr_outer = push_stmt_list ();
2453 current_stmt_tree ()->stmts_are_full_exprs_p = 1;
2454 tree dstr_stmt = begin_compound_stmt (BCS_FN_BODY);
2456 tree destr_frame = build1 (INDIRECT_REF, coro_frame_type, destr_fp);
2458 tree rat_field = lookup_member (coro_frame_type, coro_resume_index_id,
2459 1, 0, tf_warning_or_error);
2460 tree rat = build3 (COMPONENT_REF, short_unsigned_type_node,
2461 destr_frame, rat_field, NULL_TREE);
2463 /* _resume_at |= 1 */
2464 tree dstr_idx = build2 (BIT_IOR_EXPR, short_unsigned_type_node, rat,
2465 build_int_cst (short_unsigned_type_node, 1));
2466 tree r = build2 (MODIFY_EXPR, short_unsigned_type_node, rat, dstr_idx);
2467 r = coro_build_cvt_void_expr_stmt (r, loc);
2468 add_stmt (r);
2470 /* So .. call the actor .. */
2471 r = build_call_expr_loc (loc, actor, 1, destr_fp);
2472 r = coro_build_cvt_void_expr_stmt (r, loc);
2473 add_stmt (r);
2475 /* done. */
2476 r = build_stmt (loc, RETURN_EXPR, NULL);
2477 r = maybe_cleanup_point_expr_void (r);
2478 add_stmt (r);
2480 finish_compound_stmt (dstr_stmt);
2481 DECL_SAVED_TREE (destroy) = pop_stmt_list (destr_outer);
2484 /* Helper that returns an identifier for an appended extension to the
2485 current un-mangled function name. */
2487 static tree
2488 get_fn_local_identifier (tree orig, const char *append)
2490 /* Figure out the bits we need to generate names for the outlined things
2491 For consistency, this needs to behave the same way as
2492 ASM_FORMAT_PRIVATE_NAME does. */
2493 tree nm = DECL_NAME (orig);
2494 const char *sep, *pfx = "";
2495 #ifndef NO_DOT_IN_LABEL
2496 sep = ".";
2497 #else
2498 #ifndef NO_DOLLAR_IN_LABEL
2499 sep = "$";
2500 #else
2501 sep = "_";
2502 pfx = "__";
2503 #endif
2504 #endif
2506 char *an;
2507 if (DECL_ASSEMBLER_NAME (orig))
2508 an = ACONCAT ((IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (orig)), sep, append,
2509 (char *) 0));
2510 else if (DECL_USE_TEMPLATE (orig) && DECL_TEMPLATE_INFO (orig)
2511 && DECL_TI_ARGS (orig))
2513 tree tpl_args = DECL_TI_ARGS (orig);
2514 an = ACONCAT ((pfx, IDENTIFIER_POINTER (nm), (char *) 0));
2515 for (int i = 0; i < TREE_VEC_LENGTH (tpl_args); ++i)
2517 tree typ = DECL_NAME (TYPE_NAME (TREE_VEC_ELT (tpl_args, i)));
2518 an = ACONCAT ((an, sep, IDENTIFIER_POINTER (typ), (char *) 0));
2520 an = ACONCAT ((an, sep, append, (char *) 0));
2522 else
2523 an = ACONCAT ((pfx, IDENTIFIER_POINTER (nm), sep, append, (char *) 0));
2525 return get_identifier (an);
2528 /* Build an initial or final await initialized from the promise
2529 initial_suspend or final_suspend expression. */
2531 static tree
2532 build_init_or_final_await (location_t loc, bool is_final)
2534 tree suspend_alt = is_final ? coro_final_suspend_identifier
2535 : coro_initial_suspend_identifier;
2537 tree setup_call
2538 = coro_build_promise_expression (current_function_decl, NULL, suspend_alt,
2539 loc, NULL, /*musthave=*/true);
2541 /* Check for noexcept on the final_suspend call. */
2542 if (flag_exceptions && is_final && setup_call != error_mark_node
2543 && coro_diagnose_throwing_final_aw_expr (setup_call))
2544 return error_mark_node;
2546 /* So build the co_await for this */
2547 /* For initial/final suspends the call is "a" per [expr.await] 3.2. */
2548 return build_co_await (loc, setup_call, (is_final ? FINAL_SUSPEND_POINT
2549 : INITIAL_SUSPEND_POINT));
2552 /* Callback to record the essential data for each await point found in the
2553 function. */
2555 static bool
2556 register_await_info (tree await_expr, tree aw_type, tree aw_nam)
2558 bool seen;
2559 suspend_point_info &s
2560 = suspend_points->get_or_insert (await_expr, &seen);
2561 if (seen)
2563 warning_at (EXPR_LOCATION (await_expr), 0, "duplicate info for %qE",
2564 await_expr);
2565 return false;
2567 s.awaitable_type = aw_type;
2568 s.await_field_id = aw_nam;
2569 return true;
2572 /* This data set is used when analyzing statements for await expressions. */
2574 struct susp_frame_data
2576 /* Function-wide. */
2577 tree *field_list; /* The current coroutine frame field list. */
2578 tree handle_type; /* The self-handle type for this coroutine. */
2579 tree fs_label; /* The destination for co_returns. */
2580 vec<tree, va_gc> *block_stack; /* Track block scopes. */
2581 vec<tree, va_gc> *bind_stack; /* Track current bind expr. */
2582 unsigned await_number; /* Which await in the function. */
2583 unsigned cond_number; /* Which replaced condition in the fn. */
2584 /* Temporary values for one statement or expression being analyzed. */
2585 hash_set<tree> captured_temps; /* The suspend captured these temps. */
2586 vec<tree, va_gc> *to_replace; /* The VAR decls to replace. */
2587 hash_set<tree> *truth_aoif_to_expand; /* The set of TRUTH exprs to expand. */
2588 unsigned saw_awaits; /* Count of awaits in this statement */
2589 bool captures_temporary; /* This expr captures temps by ref. */
2590 bool needs_truth_if_exp; /* We must expand a truth_if expression. */
2591 bool has_awaiter_init; /* We must handle initializing an awaiter. */
2594 /* If this is an await expression, then count it (both uniquely within the
2595 function and locally within a single statement). */
2597 static tree
2598 register_awaits (tree *stmt, int *, void *d)
2600 tree aw_expr = *stmt;
2602 /* We should have already lowered co_yields to their co_await. */
2603 gcc_checking_assert (TREE_CODE (aw_expr) != CO_YIELD_EXPR);
2605 if (TREE_CODE (aw_expr) != CO_AWAIT_EXPR)
2606 return NULL_TREE;
2608 /* Count how many awaits the current expression contains. */
2609 susp_frame_data *data = (susp_frame_data *) d;
2610 data->saw_awaits++;
2611 /* Each await suspend context is unique, this is a function-wide value. */
2612 data->await_number++;
2614 /* Awaitables should either be user-locals or promoted to coroutine frame
2615 entries at this point, and their initializers should have been broken
2616 out. */
2617 tree aw = TREE_OPERAND (aw_expr, 1);
2618 gcc_checking_assert (!TREE_OPERAND (aw_expr, 2));
2620 tree aw_field_type = TREE_TYPE (aw);
2621 tree aw_field_nam = NULL_TREE;
2622 register_await_info (aw_expr, aw_field_type, aw_field_nam);
2624 /* Rewrite target expressions on the await_suspend () to remove extraneous
2625 cleanups for the awaitables, which are now promoted to frame vars and
2626 managed via that. */
2627 tree v = TREE_OPERAND (aw_expr, 3);
2628 tree o = TREE_VEC_ELT (v, 1);
2629 if (TREE_CODE (o) == TARGET_EXPR)
2630 TREE_VEC_ELT (v, 1) = get_target_expr (TREE_OPERAND (o, 1));
2631 return NULL_TREE;
2634 /* There are cases where any await expression is relevant. */
2635 static tree
2636 find_any_await (tree *stmt, int *dosub, void *d)
2638 if (TREE_CODE (*stmt) == CO_AWAIT_EXPR)
2640 *dosub = 0; /* We don't need to consider this any further. */
2641 tree **p = (tree **) d;
2642 *p = stmt;
2643 return *stmt;
2645 return NULL_TREE;
2648 static bool
2649 tmp_target_expr_p (tree t)
2651 if (TREE_CODE (t) != TARGET_EXPR)
2652 return false;
2653 tree v = TREE_OPERAND (t, 0);
2654 if (!DECL_ARTIFICIAL (v))
2655 return false;
2656 if (DECL_NAME (v))
2657 return false;
2658 return true;
2661 /* Structure to record sub-expressions that need to be handled by the
2662 statement flattener. */
2664 struct coro_interesting_subtree
2666 tree* entry;
2667 hash_set<tree> *temps_used;
2670 /* tree-walk callback that returns the first encountered sub-expression of
2671 a kind that needs to be handled specifically by the statement flattener. */
2673 static tree
2674 find_interesting_subtree (tree *expr_p, int *dosub, void *d)
2676 tree expr = *expr_p;
2677 coro_interesting_subtree *p = (coro_interesting_subtree *)d;
2678 if (TREE_CODE (expr) == CO_AWAIT_EXPR)
2680 *dosub = 0; /* We don't need to consider this any further. */
2681 if (TREE_OPERAND (expr, 2))
2683 p->entry = expr_p;
2684 return expr;
2687 else if (tmp_target_expr_p (expr)
2688 && !p->temps_used->contains (expr))
2690 p->entry = expr_p;
2691 return expr;
2694 return NULL_TREE;
2697 /* Node for a doubly-linked list of promoted variables and their
2698 initializers. When the initializer is a conditional expression
2699 the 'then' and 'else' clauses are represented by a linked list
2700 attached to then_cl and else_cl respectively. */
2702 struct var_nest_node
2704 var_nest_node () = default;
2705 var_nest_node (tree v, tree i, var_nest_node *p, var_nest_node *n)
2706 : var(v), init(i), prev(p), next(n), then_cl (NULL), else_cl (NULL)
2708 if (p)
2709 p->next = this;
2710 if (n)
2711 n->prev = this;
2713 tree var;
2714 tree init;
2715 var_nest_node *prev;
2716 var_nest_node *next;
2717 var_nest_node *then_cl;
2718 var_nest_node *else_cl;
2721 /* This is called for single statements from the co-await statement walker.
2722 It checks to see if the statement contains any initializers for awaitables
2723 and if any of these capture items by reference. */
2725 static void
2726 flatten_await_stmt (var_nest_node *n, hash_set<tree> *promoted,
2727 hash_set<tree> *temps_used, tree *replace_in)
2729 bool init_expr = false;
2730 switch (TREE_CODE (n->init))
2732 default: break;
2733 /* Compound expressions must be flattened specifically. */
2734 case COMPOUND_EXPR:
2736 tree first = TREE_OPERAND (n->init, 0);
2737 n->init = TREE_OPERAND (n->init, 1);
2738 var_nest_node *ins
2739 = new var_nest_node(NULL_TREE, first, n->prev, n);
2740 /* The compiler (but not the user) can generate temporaries with
2741 uses in the second arm of a compound expr. */
2742 flatten_await_stmt (ins, promoted, temps_used, &n->init);
2743 flatten_await_stmt (n, promoted, temps_used, NULL);
2744 /* The two arms have been processed separately. */
2745 return;
2747 break;
2748 /* Handle conditional expressions. */
2749 case INIT_EXPR:
2750 init_expr = true;
2751 /* FALLTHROUGH */
2752 case MODIFY_EXPR:
2754 tree old_expr = TREE_OPERAND (n->init, 1);
2755 if (TREE_CODE (old_expr) == COMPOUND_EXPR)
2757 tree first = TREE_OPERAND (old_expr, 0);
2758 TREE_OPERAND (n->init, 1) = TREE_OPERAND (old_expr, 1);
2759 var_nest_node *ins
2760 = new var_nest_node(NULL_TREE, first, n->prev, n);
2761 flatten_await_stmt (ins, promoted, temps_used,
2762 &TREE_OPERAND (n->init, 1));
2763 flatten_await_stmt (n, promoted, temps_used, NULL);
2764 return;
2766 if (TREE_CODE (old_expr) != COND_EXPR)
2767 break;
2768 /* Reconstruct x = t ? y : z;
2769 as (void) t ? x = y : x = z; */
2770 tree var = TREE_OPERAND (n->init, 0);
2771 tree var_type = TREE_TYPE (var);
2772 tree cond = COND_EXPR_COND (old_expr);
2773 /* We are allowed a void type throw in one or both of the cond
2774 expr arms. */
2775 tree then_cl = COND_EXPR_THEN (old_expr);
2776 if (!VOID_TYPE_P (TREE_TYPE (then_cl)))
2778 gcc_checking_assert (TREE_CODE (then_cl) != STATEMENT_LIST);
2779 then_cl
2780 = build2 (init_expr ? INIT_EXPR : MODIFY_EXPR, var_type,
2781 var, then_cl);
2783 tree else_cl = COND_EXPR_ELSE (old_expr);
2784 if (!VOID_TYPE_P (TREE_TYPE (else_cl)))
2786 gcc_checking_assert (TREE_CODE (else_cl) != STATEMENT_LIST);
2787 else_cl
2788 = build2 (init_expr ? INIT_EXPR : MODIFY_EXPR, var_type,
2789 var, else_cl);
2791 n->init = build3 (COND_EXPR, var_type, cond, then_cl, else_cl);
2793 /* FALLTHROUGH */
2794 case COND_EXPR:
2796 tree *found;
2797 tree cond = COND_EXPR_COND (n->init);
2798 /* If the condition contains an await expression, then we need to
2799 set that first and use a separate var. */
2800 if (cp_walk_tree (&cond, find_any_await, &found, NULL))
2802 tree cond_type = TREE_TYPE (cond);
2803 tree cond_var = build_lang_decl (VAR_DECL, NULL_TREE, cond_type);
2804 DECL_ARTIFICIAL (cond_var) = true;
2805 layout_decl (cond_var, 0);
2806 gcc_checking_assert (!TYPE_NEEDS_CONSTRUCTING (cond_type));
2807 cond = build2 (INIT_EXPR, cond_type, cond_var, cond);
2808 var_nest_node *ins
2809 = new var_nest_node (cond_var, cond, n->prev, n);
2810 COND_EXPR_COND (n->init) = cond_var;
2811 flatten_await_stmt (ins, promoted, temps_used, NULL);
2814 n->then_cl
2815 = new var_nest_node (n->var, COND_EXPR_THEN (n->init), NULL, NULL);
2816 n->else_cl
2817 = new var_nest_node (n->var, COND_EXPR_ELSE (n->init), NULL, NULL);
2818 flatten_await_stmt (n->then_cl, promoted, temps_used, NULL);
2819 /* Point to the start of the flattened code. */
2820 while (n->then_cl->prev)
2821 n->then_cl = n->then_cl->prev;
2822 flatten_await_stmt (n->else_cl, promoted, temps_used, NULL);
2823 while (n->else_cl->prev)
2824 n->else_cl = n->else_cl->prev;
2825 return;
2827 break;
2829 coro_interesting_subtree v = { NULL, temps_used };
2830 tree t = cp_walk_tree (&n->init, find_interesting_subtree, (void *)&v, NULL);
2831 if (!t)
2832 return;
2833 switch (TREE_CODE (t))
2835 default: break;
2836 case CO_AWAIT_EXPR:
2838 /* Await expressions with initializers have a compiler-temporary
2839 as the awaitable. 'promote' this. */
2840 tree var = TREE_OPERAND (t, 1);
2841 bool already_present = promoted->add (var);
2842 gcc_checking_assert (!already_present);
2843 tree init = TREE_OPERAND (t, 2);
2844 switch (TREE_CODE (init))
2846 default: break;
2847 case INIT_EXPR:
2848 case MODIFY_EXPR:
2850 tree inner = TREE_OPERAND (init, 1);
2851 /* We can have non-lvalue-expressions here, but when we see
2852 a target expression, mark it as already used. */
2853 if (TREE_CODE (inner) == TARGET_EXPR)
2855 temps_used->add (inner);
2856 gcc_checking_assert
2857 (TREE_CODE (TREE_OPERAND (inner, 1)) != COND_EXPR);
2860 break;
2861 case CALL_EXPR:
2862 /* If this is a call and not a CTOR, then we didn't expect it. */
2863 gcc_checking_assert
2864 (DECL_CONSTRUCTOR_P (TREE_OPERAND (CALL_EXPR_FN (init), 0)));
2865 break;
2867 var_nest_node *ins = new var_nest_node (var, init, n->prev, n);
2868 TREE_OPERAND (t, 2) = NULL_TREE;
2869 flatten_await_stmt (ins, promoted, temps_used, NULL);
2870 flatten_await_stmt (n, promoted, temps_used, NULL);
2871 return;
2873 break;
2874 case TARGET_EXPR:
2876 /* We have a temporary; promote it, but allow for the idiom in code
2877 generated by the compiler like
2878 a = (target_expr produces temp, op uses temp). */
2879 tree init = t;
2880 temps_used->add (init);
2881 tree var_type = TREE_TYPE (init);
2882 char *buf = xasprintf ("D.%d", DECL_UID (TREE_OPERAND (init, 0)));
2883 tree var = build_lang_decl (VAR_DECL, get_identifier (buf), var_type);
2884 DECL_ARTIFICIAL (var) = true;
2885 free (buf);
2886 bool already_present = promoted->add (var);
2887 gcc_checking_assert (!already_present);
2888 tree inner = TREE_OPERAND (init, 1);
2889 gcc_checking_assert (TREE_CODE (inner) != COND_EXPR);
2890 init = cp_build_modify_expr (input_location, var, INIT_EXPR, init,
2891 tf_warning_or_error);
2892 /* Simplify for the case that we have an init containing the temp
2893 alone. */
2894 if (t == n->init && n->var == NULL_TREE)
2896 n->var = var;
2897 proxy_replace pr = {TREE_OPERAND (t, 0), var};
2898 cp_walk_tree (&init, replace_proxy, &pr, NULL);
2899 n->init = init;
2900 if (replace_in)
2901 cp_walk_tree (replace_in, replace_proxy, &pr, NULL);
2902 flatten_await_stmt (n, promoted, temps_used, NULL);
2904 else
2906 var_nest_node *ins
2907 = new var_nest_node (var, init, n->prev, n);
2908 /* We have to replace the target expr... */
2909 *v.entry = var;
2910 /* ... and any uses of its var. */
2911 proxy_replace pr = {TREE_OPERAND (t, 0), var};
2912 cp_walk_tree (&n->init, replace_proxy, &pr, NULL);
2913 /* Compiler-generated temporaries can also have uses in
2914 following arms of compound expressions, which will be listed
2915 in 'replace_in' if present. */
2916 if (replace_in)
2917 cp_walk_tree (replace_in, replace_proxy, &pr, NULL);
2918 flatten_await_stmt (ins, promoted, temps_used, NULL);
2919 flatten_await_stmt (n, promoted, temps_used, NULL);
2921 return;
2923 break;
2927 /* Helper for 'process_conditional' that handles recursion into nested
2928 conditionals. */
2930 static void
2931 handle_nested_conditionals (var_nest_node *n, vec<tree>& list,
2932 hash_map<tree, tree>& map)
2936 if (n->var && DECL_NAME (n->var))
2938 list.safe_push (n->var);
2939 if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (n->var)))
2941 bool existed;
2942 tree& flag = map.get_or_insert (n->var, &existed);
2943 if (!existed)
2945 /* We didn't see this var before and it needs a DTOR, so
2946 build a guard variable for it. */
2947 char *nam
2948 = xasprintf ("%s_guard",
2949 IDENTIFIER_POINTER (DECL_NAME (n->var)));
2950 flag = build_lang_decl (VAR_DECL, get_identifier (nam),
2951 boolean_type_node);
2952 free (nam);
2953 DECL_ARTIFICIAL (flag) = true;
2956 /* The initializer for this variable is replaced by a compound
2957 expression that performs the init and then records that the
2958 variable is live (and the DTOR should be run at the scope
2959 exit. */
2960 tree set_flag = build2 (INIT_EXPR, boolean_type_node,
2961 flag, boolean_true_node);
2962 n->init
2963 = build2 (COMPOUND_EXPR, boolean_type_node, n->init, set_flag);
2966 if (TREE_CODE (n->init) == COND_EXPR)
2968 tree new_then = push_stmt_list ();
2969 handle_nested_conditionals (n->then_cl, list, map);
2970 new_then = pop_stmt_list (new_then);
2971 tree new_else = push_stmt_list ();
2972 handle_nested_conditionals (n->else_cl, list, map);
2973 new_else = pop_stmt_list (new_else);
2974 tree new_if
2975 = build4 (IF_STMT, void_type_node, COND_EXPR_COND (n->init),
2976 new_then, new_else, NULL_TREE);
2977 add_stmt (new_if);
2979 else
2980 finish_expr_stmt (n->init);
2981 n = n->next;
2982 } while (n);
2985 /* helper for 'maybe_promote_temps'.
2987 When we have a conditional expression which might embed await expressions
2988 and/or promoted variables, we need to handle it appropriately.
2990 The linked lists for the 'then' and 'else' clauses in a conditional node
2991 identify the promoted variables (but these cannot be wrapped in a regular
2992 cleanup).
2994 So recurse through the lists and build up a composite list of captured vars.
2995 Declare these and any guard variables needed to decide if a DTOR should be
2996 run. Then embed the conditional into a try-finally expression that handles
2997 running each DTOR conditionally on its guard variable. */
2999 static void
3000 process_conditional (var_nest_node *n, tree& vlist)
3002 tree init = n->init;
3003 hash_map<tree, tree> var_flags;
3004 auto_vec<tree> var_list;
3005 tree new_then = push_stmt_list ();
3006 handle_nested_conditionals (n->then_cl, var_list, var_flags);
3007 new_then = pop_stmt_list (new_then);
3008 tree new_else = push_stmt_list ();
3009 handle_nested_conditionals (n->else_cl, var_list, var_flags);
3010 new_else = pop_stmt_list (new_else);
3011 /* Declare the vars. There are two loops so that the boolean flags are
3012 grouped in the frame. */
3013 for (unsigned i = 0; i < var_list.length(); i++)
3015 tree var = var_list[i];
3016 DECL_CHAIN (var) = vlist;
3017 vlist = var;
3018 add_decl_expr (var);
3020 /* Define the guard flags for variables that need a DTOR. */
3021 for (unsigned i = 0; i < var_list.length(); i++)
3023 tree *flag = var_flags.get (var_list[i]);
3024 if (flag)
3026 DECL_INITIAL (*flag) = boolean_false_node;
3027 DECL_CHAIN (*flag) = vlist;
3028 vlist = *flag;
3029 add_decl_expr (*flag);
3032 tree new_if
3033 = build4 (IF_STMT, void_type_node, COND_EXPR_COND (init),
3034 new_then, new_else, NULL_TREE);
3035 /* Build a set of conditional DTORs. */
3036 tree final_actions = push_stmt_list ();
3037 while (!var_list.is_empty())
3039 tree var = var_list.pop ();
3040 tree *flag = var_flags.get (var);
3041 if (!flag)
3042 continue;
3043 tree var_type = TREE_TYPE (var);
3044 tree cleanup
3045 = build_special_member_call (var, complete_dtor_identifier,
3046 NULL, var_type, LOOKUP_NORMAL,
3047 tf_warning_or_error);
3048 tree cond_cleanup = begin_if_stmt ();
3049 finish_if_stmt_cond (*flag, cond_cleanup);
3050 finish_expr_stmt (cleanup);
3051 finish_then_clause (cond_cleanup);
3052 finish_if_stmt (cond_cleanup);
3054 final_actions = pop_stmt_list (final_actions);
3055 tree try_finally
3056 = build2 (TRY_FINALLY_EXPR, void_type_node, new_if, final_actions);
3057 add_stmt (try_finally);
3060 /* Given *STMT, that contains at least one await expression.
3062 The full expression represented in the original source code will contain
3063 suspension points, but it is still required that the lifetime of temporary
3064 values extends to the end of the expression.
3066 We already have a mechanism to 'promote' user-authored local variables
3067 to a coroutine frame counterpart (which allows explicit management of the
3068 lifetime across suspensions). The transform here re-writes STMT into
3069 a bind expression, promotes temporary values into local variables in that
3070 and flattens the statement into a series of cleanups.
3072 Conditional expressions are re-written to regular 'if' statements.
3073 The cleanups for variables initialized inside a conditional (including
3074 nested cases) are wrapped in a try-finally clause, with guard variables
3075 to determine which DTORs need to be run. */
3077 static tree
3078 maybe_promote_temps (tree *stmt, void *d)
3080 susp_frame_data *awpts = (susp_frame_data *) d;
3082 location_t sloc = EXPR_LOCATION (*stmt);
3083 tree expr = *stmt;
3084 /* Strip off uninteresting wrappers. */
3085 if (TREE_CODE (expr) == CLEANUP_POINT_EXPR)
3086 expr = TREE_OPERAND (expr, 0);
3087 if (TREE_CODE (expr) == EXPR_STMT)
3088 expr = EXPR_STMT_EXPR (expr);
3089 if (TREE_CODE (expr) == CONVERT_EXPR
3090 && VOID_TYPE_P (TREE_TYPE (expr)))
3091 expr = TREE_OPERAND (expr, 0);
3092 STRIP_NOPS (expr);
3094 /* We walk the statement trees, flattening it into an ordered list of
3095 variables with initializers and fragments corresponding to compound
3096 expressions, truth or/and if and ternary conditionals. Conditional
3097 expressions carry a nested list of fragments for the then and else
3098 clauses. We anchor to the 'bottom' of the fragment list; we will write
3099 a cleanup nest with one shell for each variable initialized. */
3100 var_nest_node *root = new var_nest_node (NULL_TREE, expr, NULL, NULL);
3101 /* Check to see we didn't promote one twice. */
3102 hash_set<tree> promoted_vars;
3103 hash_set<tree> used_temps;
3104 flatten_await_stmt (root, &promoted_vars, &used_temps, NULL);
3106 gcc_checking_assert (root->next == NULL);
3107 tree vlist = NULL_TREE;
3108 var_nest_node *t = root;
3109 /* We build the bind scope expression from the bottom-up.
3110 EXPR_LIST holds the inner expression nest at the current cleanup
3111 level (becoming the final expression list when we've exhausted the
3112 number of sub-expression fragments). */
3113 tree expr_list = NULL_TREE;
3116 tree new_list = push_stmt_list ();
3117 /* When we have a promoted variable, then add that to the bind scope
3118 and initialize it. When there's no promoted variable, we just need
3119 to run the initializer.
3120 If the initializer is a conditional expression, we need to collect
3121 and declare any promoted variables nested within it. DTORs for such
3122 variables must be run conditionally too. */
3123 if (t->var)
3125 tree var = t->var;
3126 DECL_CHAIN (var) = vlist;
3127 vlist = var;
3128 add_decl_expr (var);
3129 if (TREE_CODE (t->init) == COND_EXPR)
3130 process_conditional (t, vlist);
3131 else
3132 finish_expr_stmt (t->init);
3133 tree var_type = TREE_TYPE (var);
3134 if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (var_type))
3136 tree cleanup
3137 = build_special_member_call (var, complete_dtor_identifier,
3138 NULL, var_type, LOOKUP_NORMAL,
3139 tf_warning_or_error);
3140 tree cl = build_stmt (sloc, CLEANUP_STMT, expr_list, cleanup, var);
3141 add_stmt (cl); /* push this onto the level above. */
3143 else if (expr_list)
3145 if (TREE_CODE (expr_list) != STATEMENT_LIST)
3146 add_stmt (expr_list);
3147 else if (!tsi_end_p (tsi_start (expr_list)))
3148 add_stmt (expr_list);
3151 else
3153 if (TREE_CODE (t->init) == COND_EXPR)
3154 process_conditional (t, vlist);
3155 else
3156 finish_expr_stmt (t->init);
3157 if (expr_list)
3159 if (TREE_CODE (expr_list) != STATEMENT_LIST)
3160 add_stmt (expr_list);
3161 else if (!tsi_end_p (tsi_start (expr_list)))
3162 add_stmt (expr_list);
3165 expr_list = pop_stmt_list (new_list);
3166 var_nest_node *old = t;
3167 t = t->prev;
3168 delete old;
3169 } while (t);
3171 /* Now produce the bind expression containing the 'promoted' temporaries
3172 as its variable list, and the cleanup nest as the statement. */
3173 tree await_bind = build3_loc (sloc, BIND_EXPR, void_type_node,
3174 NULL, NULL, NULL);
3175 BIND_EXPR_BODY (await_bind) = expr_list;
3176 BIND_EXPR_VARS (await_bind) = nreverse (vlist);
3177 tree b_block = make_node (BLOCK);
3178 if (!awpts->block_stack->is_empty ())
3180 tree s_block = awpts->block_stack->last ();
3181 if (s_block)
3183 BLOCK_SUPERCONTEXT (b_block) = s_block;
3184 BLOCK_CHAIN (b_block) = BLOCK_SUBBLOCKS (s_block);
3185 BLOCK_SUBBLOCKS (s_block) = b_block;
3188 BLOCK_VARS (b_block) = BIND_EXPR_VARS (await_bind) ;
3189 BIND_EXPR_BLOCK (await_bind) = b_block;
3190 TREE_SIDE_EFFECTS (await_bind) = TREE_SIDE_EFFECTS (BIND_EXPR_BODY (await_bind));
3191 *stmt = await_bind;
3192 hash_set<tree> visited;
3193 return cp_walk_tree (stmt, register_awaits, d, &visited);
3196 /* Lightweight callback to determine two key factors:
3197 1) If the statement/expression contains any await expressions.
3198 2) If the statement/expression potentially requires a re-write to handle
3199 TRUTH_{AND,OR}IF_EXPRs since, in most cases, they will need expansion
3200 so that the await expressions are not processed in the case of the
3201 short-circuit arm.
3203 CO_YIELD expressions are re-written to their underlying co_await. */
3205 static tree
3206 analyze_expression_awaits (tree *stmt, int *do_subtree, void *d)
3208 susp_frame_data *awpts = (susp_frame_data *) d;
3210 switch (TREE_CODE (*stmt))
3212 default: return NULL_TREE;
3213 case CO_YIELD_EXPR:
3214 /* co_yield is syntactic sugar, re-write it to co_await. */
3215 *stmt = TREE_OPERAND (*stmt, 1);
3216 /* FALLTHROUGH */
3217 case CO_AWAIT_EXPR:
3218 awpts->saw_awaits++;
3219 /* A non-null initializer for the awaiter means we need to expand. */
3220 if (TREE_OPERAND (*stmt, 2))
3221 awpts->has_awaiter_init = true;
3222 break;
3223 case TRUTH_ANDIF_EXPR:
3224 case TRUTH_ORIF_EXPR:
3226 /* We don't need special action for awaits in the always-executed
3227 arm of a TRUTH_IF. */
3228 if (tree res = cp_walk_tree (&TREE_OPERAND (*stmt, 0),
3229 analyze_expression_awaits, d, NULL))
3230 return res;
3231 /* However, if there are await expressions on the conditionally
3232 executed branch, we must expand the TRUTH_IF to ensure that the
3233 expanded await expression control-flow is fully contained in the
3234 conditionally executed code. */
3235 unsigned aw_count = awpts->saw_awaits;
3236 if (tree res = cp_walk_tree (&TREE_OPERAND (*stmt, 1),
3237 analyze_expression_awaits, d, NULL))
3238 return res;
3239 if (awpts->saw_awaits > aw_count)
3241 awpts->truth_aoif_to_expand->add (*stmt);
3242 awpts->needs_truth_if_exp = true;
3244 /* We've done the sub-trees here. */
3245 *do_subtree = 0;
3247 break;
3250 return NULL_TREE; /* Recurse until done. */
3253 /* Given *EXPR
3254 If EXPR contains a TRUTH_{AND,OR}IF_EXPR, TAOIE with an await expr on
3255 the conditionally executed branch, change this in a ternary operator.
3257 bool not_expr = TAOIE == TRUTH_ORIF_EXPR ? NOT : NOP;
3258 not_expr (always-exec expr) ? conditionally-exec expr : not_expr;
3260 Apply this recursively to the condition and the conditionally-exec
3261 branch. */
3263 struct truth_if_transform {
3264 tree *orig_stmt;
3265 tree scratch_var;
3266 hash_set<tree> *truth_aoif_to_expand;
3269 static tree
3270 expand_one_truth_if (tree *expr, int *do_subtree, void *d)
3272 truth_if_transform *xform = (truth_if_transform *) d;
3274 bool needs_not = false;
3275 switch (TREE_CODE (*expr))
3277 default: break;
3278 case TRUTH_ORIF_EXPR:
3279 needs_not = true;
3280 /* FALLTHROUGH */
3281 case TRUTH_ANDIF_EXPR:
3283 if (!xform->truth_aoif_to_expand->contains (*expr))
3284 break;
3286 location_t sloc = EXPR_LOCATION (*expr);
3287 /* Transform truth expression into a cond expression with
3288 * the always-executed arm as the condition.
3289 * the conditionally-executed arm as the then clause.
3290 * the 'else' clause is fixed: 'true' for ||,'false' for &&. */
3291 tree cond = TREE_OPERAND (*expr, 0);
3292 tree test1 = TREE_OPERAND (*expr, 1);
3293 tree fixed = needs_not ? boolean_true_node : boolean_false_node;
3294 if (needs_not)
3295 cond = build1 (TRUTH_NOT_EXPR, boolean_type_node, cond);
3296 tree cond_expr
3297 = build3_loc (sloc, COND_EXPR, boolean_type_node,
3298 cond, test1, fixed);
3299 *expr = cond_expr;
3300 if (tree res = cp_walk_tree (&COND_EXPR_COND (*expr),
3301 expand_one_truth_if, d, NULL))
3302 return res;
3303 if (tree res = cp_walk_tree (&COND_EXPR_THEN (*expr),
3304 expand_one_truth_if, d, NULL))
3305 return res;
3306 /* We've manually processed necessary sub-trees here. */
3307 *do_subtree = 0;
3309 break;
3311 return NULL_TREE;
3314 /* Helper that adds a new variable of VAR_TYPE to a bind scope BIND, the
3315 name is made up from NAM_ROOT, NAM_VERS. */
3317 static tree
3318 add_var_to_bind (tree& bind, tree var_type,
3319 const char *nam_root, unsigned nam_vers)
3321 tree b_vars = BIND_EXPR_VARS (bind);
3322 /* Build a variable to hold the condition, this will be included in the
3323 frame as a local var. */
3324 char *nam = xasprintf ("__%s_%d", nam_root, nam_vers);
3325 tree newvar = build_lang_decl (VAR_DECL, get_identifier (nam), var_type);
3326 free (nam);
3327 DECL_CHAIN (newvar) = b_vars;
3328 BIND_EXPR_VARS (bind) = newvar;
3329 return newvar;
3332 /* Helper to build and add if (!cond) break; */
3334 static void
3335 coro_build_add_if_not_cond_break (tree cond)
3337 tree if_stmt = begin_if_stmt ();
3338 tree invert = build1 (TRUTH_NOT_EXPR, boolean_type_node, cond);
3339 finish_if_stmt_cond (invert, if_stmt);
3340 finish_break_stmt ();
3341 finish_then_clause (if_stmt);
3342 finish_if_stmt (if_stmt);
3345 /* Tree walk callback to replace continue statements with goto label. */
3346 static tree
3347 replace_continue (tree *stmt, int *do_subtree, void *d)
3349 tree expr = *stmt;
3350 if (TREE_CODE (expr) == CLEANUP_POINT_EXPR)
3351 expr = TREE_OPERAND (expr, 0);
3352 if (CONVERT_EXPR_P (expr) && VOID_TYPE_P (expr))
3353 expr = TREE_OPERAND (expr, 0);
3354 STRIP_NOPS (expr);
3355 if (!STATEMENT_CLASS_P (expr))
3356 return NULL_TREE;
3358 switch (TREE_CODE (expr))
3360 /* Unless it's a special case, just walk the subtrees as usual. */
3361 default: return NULL_TREE;
3363 case CONTINUE_STMT:
3365 tree *label = (tree *)d;
3366 location_t loc = EXPR_LOCATION (expr);
3367 /* re-write a continue to goto label. */
3368 *stmt = build_stmt (loc, GOTO_EXPR, *label);
3369 *do_subtree = 0;
3370 return NULL_TREE;
3373 /* Statements that do not require recursion. */
3374 case DECL_EXPR:
3375 case BREAK_STMT:
3376 case GOTO_EXPR:
3377 case LABEL_EXPR:
3378 case CASE_LABEL_EXPR:
3379 case ASM_EXPR:
3380 /* These must break recursion. */
3381 case FOR_STMT:
3382 case WHILE_STMT:
3383 case DO_STMT:
3384 *do_subtree = 0;
3385 return NULL_TREE;
3389 /* Tree walk callback to analyze, register and pre-process statements that
3390 contain await expressions. */
3392 static tree
3393 await_statement_walker (tree *stmt, int *do_subtree, void *d)
3395 tree res = NULL_TREE;
3396 susp_frame_data *awpts = (susp_frame_data *) d;
3398 /* Process a statement at a time. */
3399 if (TREE_CODE (*stmt) == BIND_EXPR)
3401 /* For conditional expressions, we might wish to add an artificial var
3402 to their containing bind expr. */
3403 vec_safe_push (awpts->bind_stack, *stmt);
3404 /* We might need to insert a new bind expression, and want to link it
3405 into the correct scope, so keep a note of the current block scope. */
3406 tree blk = BIND_EXPR_BLOCK (*stmt);
3407 vec_safe_push (awpts->block_stack, blk);
3408 res = cp_walk_tree (&BIND_EXPR_BODY (*stmt), await_statement_walker,
3409 d, NULL);
3410 awpts->block_stack->pop ();
3411 awpts->bind_stack->pop ();
3412 *do_subtree = 0; /* Done subtrees. */
3413 return res;
3415 else if (TREE_CODE (*stmt) == STATEMENT_LIST)
3417 for (tree &s : tsi_range (*stmt))
3419 res = cp_walk_tree (&s, await_statement_walker,
3420 d, NULL);
3421 if (res)
3422 return res;
3424 *do_subtree = 0; /* Done subtrees. */
3425 return NULL_TREE;
3428 /* We have something to be handled as a single statement. We have to handle
3429 a few statements specially where await statements have to be moved out of
3430 constructs. */
3431 tree expr = *stmt;
3432 if (TREE_CODE (*stmt) == CLEANUP_POINT_EXPR)
3433 expr = TREE_OPERAND (expr, 0);
3434 STRIP_NOPS (expr);
3436 if (STATEMENT_CLASS_P (expr))
3437 switch (TREE_CODE (expr))
3439 /* Unless it's a special case, just walk the subtrees as usual. */
3440 default: return NULL_TREE;
3442 /* When we have a conditional expression, which contains one or more
3443 await expressions, we have to break the condition out into a
3444 regular statement so that the control flow introduced by the await
3445 transforms can be implemented. */
3446 case IF_STMT:
3448 tree *await_ptr;
3449 hash_set<tree> visited;
3450 /* Transform 'if (cond with awaits) then stmt1 else stmt2' into
3451 bool cond = cond with awaits.
3452 if (cond) then stmt1 else stmt2. */
3453 tree if_stmt = *stmt;
3454 /* We treat the condition as if it was a stand-alone statement,
3455 to see if there are any await expressions which will be analyzed
3456 and registered. */
3457 if (!(cp_walk_tree (&IF_COND (if_stmt),
3458 find_any_await, &await_ptr, &visited)))
3459 return NULL_TREE; /* Nothing special to do here. */
3461 gcc_checking_assert (!awpts->bind_stack->is_empty());
3462 tree& bind_expr = awpts->bind_stack->last ();
3463 tree newvar = add_var_to_bind (bind_expr, boolean_type_node,
3464 "ifcd", awpts->cond_number++);
3465 tree insert_list = push_stmt_list ();
3466 tree cond_inner = IF_COND (if_stmt);
3467 if (TREE_CODE (cond_inner) == CLEANUP_POINT_EXPR)
3468 cond_inner = TREE_OPERAND (cond_inner, 0);
3469 add_decl_expr (newvar);
3470 location_t sloc = EXPR_LOCATION (IF_COND (if_stmt));
3471 /* We want to initialize the new variable with the expression
3472 that contains the await(s) and potentially also needs to
3473 have truth_if expressions expanded. */
3474 tree new_s = build2_loc (sloc, INIT_EXPR, boolean_type_node,
3475 newvar, cond_inner);
3476 finish_expr_stmt (new_s);
3477 IF_COND (if_stmt) = newvar;
3478 add_stmt (if_stmt);
3479 *stmt = pop_stmt_list (insert_list);
3480 /* So now walk the new statement list. */
3481 res = cp_walk_tree (stmt, await_statement_walker, d, NULL);
3482 *do_subtree = 0; /* Done subtrees. */
3483 return res;
3485 break;
3486 case FOR_STMT:
3488 tree *await_ptr;
3489 hash_set<tree> visited;
3490 /* for loops only need special treatment if the condition or the
3491 iteration expression contain a co_await. */
3492 tree for_stmt = *stmt;
3493 /* At present, the FE always generates a separate initializer for
3494 the FOR_INIT_STMT, when the expression has an await. Check that
3495 this assumption holds in the future. */
3496 gcc_checking_assert
3497 (!(cp_walk_tree (&FOR_INIT_STMT (for_stmt), find_any_await,
3498 &await_ptr, &visited)));
3500 visited.empty ();
3501 bool for_cond_await
3502 = cp_walk_tree (&FOR_COND (for_stmt), find_any_await,
3503 &await_ptr, &visited);
3505 visited.empty ();
3506 bool for_expr_await
3507 = cp_walk_tree (&FOR_EXPR (for_stmt), find_any_await,
3508 &await_ptr, &visited);
3510 /* If the condition has an await, then we will need to rewrite the
3511 loop as
3512 for (init expression;true;iteration expression) {
3513 condition = await expression;
3514 if (condition)
3515 break;
3519 if (for_cond_await)
3521 tree insert_list = push_stmt_list ();
3522 /* This will be expanded when the revised body is handled. */
3523 coro_build_add_if_not_cond_break (FOR_COND (for_stmt));
3524 /* .. add the original for body. */
3525 add_stmt (FOR_BODY (for_stmt));
3526 /* To make the new for body. */
3527 FOR_BODY (for_stmt) = pop_stmt_list (insert_list);
3528 FOR_COND (for_stmt) = boolean_true_node;
3530 /* If the iteration expression has an await, it's a bit more
3531 tricky.
3532 for (init expression;condition;) {
3534 iteration_expr_label:
3535 iteration expression with await;
3537 but, then we will need to re-write any continue statements into
3538 'goto iteration_expr_label:'.
3540 if (for_expr_await)
3542 location_t sloc = EXPR_LOCATION (FOR_EXPR (for_stmt));
3543 tree insert_list = push_stmt_list ();
3544 /* The original for body. */
3545 add_stmt (FOR_BODY (for_stmt));
3546 char *buf = xasprintf ("for.iter.expr.%u", awpts->cond_number++);
3547 tree it_expr_label
3548 = create_named_label_with_ctx (sloc, buf, NULL_TREE);
3549 free (buf);
3550 add_stmt (build_stmt (sloc, LABEL_EXPR, it_expr_label));
3551 tree for_expr = FOR_EXPR (for_stmt);
3552 /* Present the iteration expression as a statement. */
3553 if (TREE_CODE (for_expr) == CLEANUP_POINT_EXPR)
3554 for_expr = TREE_OPERAND (for_expr, 0);
3555 STRIP_NOPS (for_expr);
3556 finish_expr_stmt (for_expr);
3557 FOR_EXPR (for_stmt) = NULL_TREE;
3558 FOR_BODY (for_stmt) = pop_stmt_list (insert_list);
3559 /* rewrite continue statements to goto label. */
3560 hash_set<tree> visited_continue;
3561 if ((res = cp_walk_tree (&FOR_BODY (for_stmt),
3562 replace_continue, &it_expr_label, &visited_continue)))
3563 return res;
3566 /* So now walk the body statement (list), if there were no await
3567 expressions, then this handles the original body - and either
3568 way we will have finished with this statement. */
3569 res = cp_walk_tree (&FOR_BODY (for_stmt),
3570 await_statement_walker, d, NULL);
3571 *do_subtree = 0; /* Done subtrees. */
3572 return res;
3574 break;
3575 case WHILE_STMT:
3577 /* We turn 'while (cond with awaits) stmt' into
3578 while (true) {
3579 if (!(cond with awaits))
3580 break;
3581 stmt..
3582 } */
3583 tree *await_ptr;
3584 hash_set<tree> visited;
3585 tree while_stmt = *stmt;
3586 if (!(cp_walk_tree (&WHILE_COND (while_stmt),
3587 find_any_await, &await_ptr, &visited)))
3588 return NULL_TREE; /* Nothing special to do here. */
3590 tree insert_list = push_stmt_list ();
3591 coro_build_add_if_not_cond_break (WHILE_COND (while_stmt));
3592 /* The original while body. */
3593 add_stmt (WHILE_BODY (while_stmt));
3594 /* The new while body. */
3595 WHILE_BODY (while_stmt) = pop_stmt_list (insert_list);
3596 WHILE_COND (while_stmt) = boolean_true_node;
3597 /* So now walk the new statement list. */
3598 res = cp_walk_tree (&WHILE_BODY (while_stmt),
3599 await_statement_walker, d, NULL);
3600 *do_subtree = 0; /* Done subtrees. */
3601 return res;
3603 break;
3604 case DO_STMT:
3606 /* We turn do stmt while (cond with awaits) into:
3607 do {
3608 stmt..
3609 if (!(cond with awaits))
3610 break;
3611 } while (true); */
3612 tree do_stmt = *stmt;
3613 tree *await_ptr;
3614 hash_set<tree> visited;
3615 if (!(cp_walk_tree (&DO_COND (do_stmt),
3616 find_any_await, &await_ptr, &visited)))
3617 return NULL_TREE; /* Nothing special to do here. */
3619 tree insert_list = push_stmt_list ();
3620 /* The original do stmt body. */
3621 add_stmt (DO_BODY (do_stmt));
3622 coro_build_add_if_not_cond_break (DO_COND (do_stmt));
3623 /* The new while body. */
3624 DO_BODY (do_stmt) = pop_stmt_list (insert_list);
3625 DO_COND (do_stmt) = boolean_true_node;
3626 /* So now walk the new statement list. */
3627 res = cp_walk_tree (&DO_BODY (do_stmt), await_statement_walker,
3628 d, NULL);
3629 *do_subtree = 0; /* Done subtrees. */
3630 return res;
3632 break;
3633 case SWITCH_STMT:
3635 /* We turn 'switch (cond with awaits) stmt' into
3636 switch_type cond = cond with awaits
3637 switch (cond) stmt. */
3638 tree sw_stmt = *stmt;
3639 tree *await_ptr;
3640 hash_set<tree> visited;
3641 if (!(cp_walk_tree (&SWITCH_STMT_COND (sw_stmt),
3642 find_any_await, &await_ptr, &visited)))
3643 return NULL_TREE; /* Nothing special to do here. */
3645 gcc_checking_assert (!awpts->bind_stack->is_empty());
3646 /* Build a variable to hold the condition, this will be
3647 included in the frame as a local var. */
3648 tree& bind_expr = awpts->bind_stack->last ();
3649 tree sw_type = SWITCH_STMT_TYPE (sw_stmt);
3650 tree newvar = add_var_to_bind (bind_expr, sw_type, "swch",
3651 awpts->cond_number++);
3652 tree insert_list = push_stmt_list ();
3653 add_decl_expr (newvar);
3655 tree cond_inner = SWITCH_STMT_COND (sw_stmt);
3656 if (TREE_CODE (cond_inner) == CLEANUP_POINT_EXPR)
3657 cond_inner = TREE_OPERAND (cond_inner, 0);
3658 location_t sloc = EXPR_LOCATION (SWITCH_STMT_COND (sw_stmt));
3659 tree new_s = build2_loc (sloc, INIT_EXPR, sw_type, newvar,
3660 cond_inner);
3661 finish_expr_stmt (new_s);
3662 SWITCH_STMT_COND (sw_stmt) = newvar;
3663 /* Now add the switch statement with the condition re-
3664 written to use the local var. */
3665 add_stmt (sw_stmt);
3666 *stmt = pop_stmt_list (insert_list);
3667 /* Process the expanded list. */
3668 res = cp_walk_tree (stmt, await_statement_walker,
3669 d, NULL);
3670 *do_subtree = 0; /* Done subtrees. */
3671 return res;
3673 break;
3674 case CO_RETURN_EXPR:
3676 /* Expand the co_return as per [stmt.return.coroutine]
3677 - for co_return;
3678 { p.return_void (); goto final_suspend; }
3679 - for co_return [void expr];
3680 { expr; p.return_void(); goto final_suspend;}
3681 - for co_return [non void expr];
3682 { p.return_value(expr); goto final_suspend; } */
3683 location_t loc = EXPR_LOCATION (expr);
3684 tree call = TREE_OPERAND (expr, 1);
3685 expr = TREE_OPERAND (expr, 0);
3686 tree ret_list = push_stmt_list ();
3687 /* [stmt.return.coroutine], 2.2
3688 If expr is present and void, it is placed immediately before
3689 the call for return_void; */
3690 if (expr && VOID_TYPE_P (TREE_TYPE (expr)))
3691 finish_expr_stmt (expr);
3692 /* Insert p.return_{void,value(expr)}. */
3693 finish_expr_stmt (call);
3694 TREE_USED (awpts->fs_label) = 1;
3695 add_stmt (build_stmt (loc, GOTO_EXPR, awpts->fs_label));
3696 *stmt = pop_stmt_list (ret_list);
3697 res = cp_walk_tree (stmt, await_statement_walker, d, NULL);
3698 /* Once this is complete, we will have processed subtrees. */
3699 *do_subtree = 0;
3700 return res;
3702 break;
3703 case HANDLER:
3705 /* [expr.await] An await-expression shall appear only in a
3706 potentially-evaluated expression within the compound-statement
3707 of a function-body outside of a handler. */
3708 tree *await_ptr;
3709 hash_set<tree> visited;
3710 if (!(cp_walk_tree (&HANDLER_BODY (expr), find_any_await,
3711 &await_ptr, &visited)))
3712 return NULL_TREE; /* All OK. */
3713 location_t loc = EXPR_LOCATION (*await_ptr);
3714 error_at (loc, "await expressions are not permitted in handlers");
3715 return NULL_TREE; /* This is going to fail later anyway. */
3717 break;
3719 else if (EXPR_P (expr))
3721 hash_set<tree> visited;
3722 tree *await_ptr;
3723 if (!(cp_walk_tree (stmt, find_any_await, &await_ptr, &visited)))
3724 return NULL_TREE; /* Nothing special to do here. */
3726 visited.empty ();
3727 awpts->saw_awaits = 0;
3728 hash_set<tree> truth_aoif_to_expand;
3729 awpts->truth_aoif_to_expand = &truth_aoif_to_expand;
3730 awpts->needs_truth_if_exp = false;
3731 awpts->has_awaiter_init = false;
3732 if ((res = cp_walk_tree (stmt, analyze_expression_awaits, d, &visited)))
3733 return res;
3734 *do_subtree = 0; /* Done subtrees. */
3735 if (!awpts->saw_awaits)
3736 return NULL_TREE; /* Nothing special to do here. */
3738 if (awpts->needs_truth_if_exp)
3740 /* If a truth-and/or-if expression has an await expression in the
3741 conditionally-taken branch, then it must be rewritten into a
3742 regular conditional. */
3743 truth_if_transform xf = {stmt, NULL_TREE, &truth_aoif_to_expand};
3744 if ((res = cp_walk_tree (stmt, expand_one_truth_if, &xf, NULL)))
3745 return res;
3747 /* Process this statement, which contains at least one await expression
3748 to 'promote' temporary values to a coroutine frame slot. */
3749 return maybe_promote_temps (stmt, d);
3751 /* Continue recursion, if needed. */
3752 return res;
3755 /* For figuring out what param usage we have. */
3757 struct param_frame_data
3759 tree *field_list;
3760 hash_map<tree, param_info> *param_uses;
3761 hash_set<tree *> *visited;
3762 location_t loc;
3763 bool param_seen;
3766 /* A tree walk callback that rewrites each parm use to the local variable
3767 that represents its copy in the frame. */
3769 static tree
3770 rewrite_param_uses (tree *stmt, int *do_subtree ATTRIBUTE_UNUSED, void *d)
3772 param_frame_data *data = (param_frame_data *) d;
3774 /* For lambda closure content, we have to look specifically. */
3775 if (TREE_CODE (*stmt) == VAR_DECL && DECL_HAS_VALUE_EXPR_P (*stmt))
3777 tree t = DECL_VALUE_EXPR (*stmt);
3778 return cp_walk_tree (&t, rewrite_param_uses, d, NULL);
3781 if (TREE_CODE (*stmt) != PARM_DECL)
3782 return NULL_TREE;
3784 /* If we already saw the containing expression, then we're done. */
3785 if (data->visited->add (stmt))
3786 return NULL_TREE;
3788 bool existed;
3789 param_info &parm = data->param_uses->get_or_insert (*stmt, &existed);
3790 gcc_checking_assert (existed);
3792 *stmt = parm.copy_var;
3793 return NULL_TREE;
3796 /* Build up a set of info that determines how each param copy will be
3797 handled. */
3799 static hash_map<tree, param_info> *
3800 analyze_fn_parms (tree orig)
3802 if (!DECL_ARGUMENTS (orig))
3803 return NULL;
3805 hash_map<tree, param_info> *param_uses = new hash_map<tree, param_info>;
3807 /* Build a hash map with an entry for each param.
3808 The key is the param tree.
3809 Then we have an entry for the frame field name.
3810 Then a cache for the field ref when we come to use it.
3811 Then a tree list of the uses.
3812 The second two entries start out empty - and only get populated
3813 when we see uses. */
3814 bool lambda_p = LAMBDA_FUNCTION_P (orig);
3816 unsigned no_name_parm = 0;
3817 for (tree arg = DECL_ARGUMENTS (orig); arg != NULL; arg = DECL_CHAIN (arg))
3819 bool existed;
3820 param_info &parm = param_uses->get_or_insert (arg, &existed);
3821 gcc_checking_assert (!existed);
3822 parm.body_uses = NULL;
3823 tree actual_type = TREE_TYPE (arg);
3824 actual_type = complete_type_or_else (actual_type, orig);
3825 if (actual_type == NULL_TREE)
3826 actual_type = error_mark_node;
3827 parm.orig_type = actual_type;
3828 parm.by_ref = parm.pt_ref = parm.rv_ref = false;
3829 if (TREE_CODE (actual_type) == REFERENCE_TYPE)
3831 /* If the user passes by reference, then we will save the
3832 pointer to the original. As noted in
3833 [dcl.fct.def.coroutine] / 13, if the lifetime of the
3834 referenced item ends and then the coroutine is resumed,
3835 we have UB; well, the user asked for it. */
3836 if (TYPE_REF_IS_RVALUE (actual_type))
3837 parm.rv_ref = true;
3838 else
3839 parm.pt_ref = true;
3841 else if (TYPE_REF_P (DECL_ARG_TYPE (arg)))
3842 parm.by_ref = true;
3844 parm.frame_type = actual_type;
3846 parm.this_ptr = is_this_parameter (arg);
3847 parm.lambda_cobj = lambda_p && DECL_NAME (arg) == closure_identifier;
3849 tree name = DECL_NAME (arg);
3850 if (!name)
3852 char *buf = xasprintf ("_Coro_unnamed_parm_%d", no_name_parm++);
3853 name = get_identifier (buf);
3854 free (buf);
3856 parm.field_id = name;
3858 if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (parm.frame_type))
3860 char *buf = xasprintf ("%s%s_live", DECL_NAME (arg) ? "_Coro_" : "",
3861 IDENTIFIER_POINTER (name));
3862 parm.guard_var
3863 = coro_build_artificial_var (UNKNOWN_LOCATION, get_identifier (buf),
3864 boolean_type_node, orig,
3865 boolean_false_node);
3866 free (buf);
3867 parm.trivial_dtor = false;
3869 else
3870 parm.trivial_dtor = true;
3873 return param_uses;
3876 /* Small helper for the repetitive task of adding a new field to the coro
3877 frame type. */
3879 static tree
3880 coro_make_frame_entry (tree *field_list, const char *name, tree fld_type,
3881 location_t loc)
3883 tree id = get_identifier (name);
3884 tree decl = build_decl (loc, FIELD_DECL, id, fld_type);
3885 DECL_CHAIN (decl) = *field_list;
3886 *field_list = decl;
3887 return id;
3890 /* For recording local variable usage. */
3892 struct local_vars_frame_data
3894 tree *field_list;
3895 hash_map<tree, local_var_info> *local_var_uses;
3896 unsigned int nest_depth, bind_indx;
3897 location_t loc;
3898 bool saw_capture;
3899 bool local_var_seen;
3902 /* A tree-walk callback that processes one bind expression noting local
3903 variables, and making a coroutine frame slot available for those that
3904 need it, so that they can be 'promoted' across suspension points. */
3906 static tree
3907 register_local_var_uses (tree *stmt, int *do_subtree, void *d)
3909 local_vars_frame_data *lvd = (local_vars_frame_data *) d;
3911 /* As we enter a bind expression - record the vars there and then recurse.
3912 As we exit drop the nest depth.
3913 The bind index is a growing count of how many bind indices we've seen.
3914 We build a space in the frame for each local var. */
3916 if (TREE_CODE (*stmt) == BIND_EXPR)
3918 tree lvar;
3919 unsigned serial = 0;
3920 for (lvar = BIND_EXPR_VARS (*stmt); lvar != NULL;
3921 lvar = DECL_CHAIN (lvar))
3923 bool existed;
3924 local_var_info &local_var
3925 = lvd->local_var_uses->get_or_insert (lvar, &existed);
3926 gcc_checking_assert (!existed);
3927 local_var.def_loc = DECL_SOURCE_LOCATION (lvar);
3928 tree lvtype = TREE_TYPE (lvar);
3929 local_var.frame_type = lvtype;
3930 local_var.field_idx = local_var.field_id = NULL_TREE;
3932 /* Make sure that we only present vars to the tests below. */
3933 if (TREE_CODE (lvar) == TYPE_DECL
3934 || TREE_CODE (lvar) == NAMESPACE_DECL)
3935 continue;
3937 /* We don't move static vars into the frame. */
3938 local_var.is_static = TREE_STATIC (lvar);
3939 if (local_var.is_static)
3940 continue;
3942 poly_uint64 size;
3943 if (TREE_CODE (lvtype) == ARRAY_TYPE
3944 && !poly_int_tree_p (DECL_SIZE_UNIT (lvar), &size))
3946 sorry_at (local_var.def_loc, "variable length arrays are not"
3947 " yet supported in coroutines");
3948 /* Ignore it, this is broken anyway. */
3949 continue;
3952 lvd->local_var_seen = true;
3953 /* If this var is a lambda capture proxy, we want to leave it alone,
3954 and later rewrite the DECL_VALUE_EXPR to indirect through the
3955 frame copy of the pointer to the lambda closure object. */
3956 local_var.is_lambda_capture = is_capture_proxy (lvar);
3957 if (local_var.is_lambda_capture)
3958 continue;
3960 /* If a variable has a value expression, then that's what needs
3961 to be processed. */
3962 local_var.has_value_expr_p = DECL_HAS_VALUE_EXPR_P (lvar);
3963 if (local_var.has_value_expr_p)
3964 continue;
3966 /* Make names depth+index unique, so that we can support nested
3967 scopes with identically named locals and still be able to
3968 identify them in the coroutine frame. */
3969 tree lvname = DECL_NAME (lvar);
3970 char *buf = NULL;
3972 /* The outermost bind scope contains the artificial variables that
3973 we inject to implement the coro state machine. We want to be able
3974 to inspect these in debugging. */
3975 if (lvname != NULL_TREE && lvd->nest_depth == 0)
3976 buf = xasprintf ("%s", IDENTIFIER_POINTER (lvname));
3977 else if (lvname != NULL_TREE)
3978 buf = xasprintf ("%s_%u_%u", IDENTIFIER_POINTER (lvname),
3979 lvd->nest_depth, lvd->bind_indx);
3980 else
3981 buf = xasprintf ("_D%u_%u_%u", lvd->nest_depth, lvd->bind_indx,
3982 serial++);
3984 /* TODO: Figure out if we should build a local type that has any
3985 excess alignment or size from the original decl. */
3986 local_var.field_id = coro_make_frame_entry (lvd->field_list, buf,
3987 lvtype, lvd->loc);
3988 free (buf);
3989 /* We don't walk any of the local var sub-trees, they won't contain
3990 any bind exprs. */
3992 lvd->bind_indx++;
3993 lvd->nest_depth++;
3994 cp_walk_tree (&BIND_EXPR_BODY (*stmt), register_local_var_uses, d, NULL);
3995 *do_subtree = 0; /* We've done this. */
3996 lvd->nest_depth--;
3998 return NULL_TREE;
4001 /* Build, return FUNCTION_DECL node based on ORIG with a type FN_TYPE which has
4002 a single argument of type CORO_FRAME_PTR. Build the actor function if
4003 ACTOR_P is true, otherwise the destroy. */
4005 static tree
4006 coro_build_actor_or_destroy_function (tree orig, tree fn_type,
4007 tree coro_frame_ptr, bool actor_p)
4009 location_t loc = DECL_SOURCE_LOCATION (orig);
4010 tree fn
4011 = build_lang_decl (FUNCTION_DECL, copy_node (DECL_NAME (orig)), fn_type);
4013 /* Allow for locating the ramp (original) function from this one. */
4014 if (!to_ramp)
4015 to_ramp = hash_map<tree, tree>::create_ggc (10);
4016 to_ramp->put (fn, orig);
4018 DECL_CONTEXT (fn) = DECL_CONTEXT (orig);
4019 DECL_SOURCE_LOCATION (fn) = loc;
4020 DECL_ARTIFICIAL (fn) = true;
4021 DECL_INITIAL (fn) = error_mark_node;
4023 tree id = get_identifier ("frame_ptr");
4024 tree fp = build_lang_decl (PARM_DECL, id, coro_frame_ptr);
4025 DECL_CONTEXT (fp) = fn;
4026 DECL_ARG_TYPE (fp) = type_passed_as (coro_frame_ptr);
4027 DECL_ARGUMENTS (fn) = fp;
4029 /* Copy selected attributes from the original function. */
4030 TREE_USED (fn) = TREE_USED (orig);
4031 if (DECL_SECTION_NAME (orig))
4032 set_decl_section_name (fn, orig);
4033 /* Copy any alignment that the FE added. */
4034 if (DECL_ALIGN (orig))
4035 SET_DECL_ALIGN (fn, DECL_ALIGN (orig));
4036 /* Copy any alignment the user added. */
4037 DECL_USER_ALIGN (fn) = DECL_USER_ALIGN (orig);
4038 /* Apply attributes from the original fn. */
4039 DECL_ATTRIBUTES (fn) = copy_list (DECL_ATTRIBUTES (orig));
4041 /* A void return. */
4042 tree resdecl = build_decl (loc, RESULT_DECL, 0, void_type_node);
4043 DECL_CONTEXT (resdecl) = fn;
4044 DECL_ARTIFICIAL (resdecl) = 1;
4045 DECL_IGNORED_P (resdecl) = 1;
4046 DECL_RESULT (fn) = resdecl;
4048 /* This is a coroutine component. */
4049 DECL_COROUTINE_P (fn) = 1;
4051 /* Set up a means to find out if a decl is one of the helpers and, if so,
4052 which one. */
4053 if (coroutine_info *info = get_coroutine_info (orig))
4055 gcc_checking_assert ((actor_p && info->actor_decl == NULL_TREE)
4056 || info->destroy_decl == NULL_TREE);
4057 if (actor_p)
4058 info->actor_decl = fn;
4059 else
4060 info->destroy_decl = fn;
4062 return fn;
4065 /* Re-write the body as per [dcl.fct.def.coroutine] / 5. */
4067 static tree
4068 coro_rewrite_function_body (location_t fn_start, tree fnbody, tree orig,
4069 hash_map<tree, param_info> *param_uses,
4070 tree resume_fn_ptr_type,
4071 tree& resume_idx_var, tree& fs_label)
4073 /* This will be our new outer scope. */
4074 tree update_body = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
4075 tree top_block = make_node (BLOCK);
4076 BIND_EXPR_BLOCK (update_body) = top_block;
4077 BIND_EXPR_BODY (update_body) = push_stmt_list ();
4079 /* If the function has a top level bind expression, then connect that
4080 after first making sure we give it a new block. */
4081 tree first = expr_first (fnbody);
4082 if (first && TREE_CODE (first) == BIND_EXPR)
4084 tree block = BIND_EXPR_BLOCK (first);
4085 gcc_checking_assert (block);
4086 gcc_checking_assert (BLOCK_SUPERCONTEXT (block) == NULL_TREE);
4087 gcc_checking_assert (BLOCK_CHAIN (block) == NULL_TREE);
4088 /* Replace the top block to avoid issues with locations for args
4089 appearing to be in a non-existent place. */
4090 tree replace_blk = make_node (BLOCK);
4091 BLOCK_VARS (replace_blk) = BLOCK_VARS (block);
4092 BLOCK_SUBBLOCKS (replace_blk) = BLOCK_SUBBLOCKS (block);
4093 for (tree b = BLOCK_SUBBLOCKS (replace_blk); b; b = BLOCK_CHAIN (b))
4094 BLOCK_SUPERCONTEXT (b) = replace_blk;
4095 BIND_EXPR_BLOCK (first) = replace_blk;
4096 /* The top block has one child, so far, and we have now got a
4097 superblock. */
4098 BLOCK_SUPERCONTEXT (replace_blk) = top_block;
4099 BLOCK_SUBBLOCKS (top_block) = replace_blk;
4101 else
4103 /* We are missing a top level BIND_EXPR. We need one to ensure that we
4104 don't shuffle around the coroutine frame and corrupt it. */
4105 tree bind_wrap = build3_loc (fn_start, BIND_EXPR, void_type_node,
4106 NULL, NULL, NULL);
4107 BIND_EXPR_BODY (bind_wrap) = fnbody;
4108 fnbody = bind_wrap;
4111 /* Wrap the function body in a try {} catch (...) {} block, if exceptions
4112 are enabled. */
4113 tree var_list = NULL_TREE;
4114 tree initial_await = build_init_or_final_await (fn_start, false);
4116 /* [stmt.return.coroutine] / 3
4117 If p.return_void() is a valid expression, flowing off the end of a
4118 coroutine is equivalent to a co_return with no operand; otherwise
4119 flowing off the end of a coroutine results in undefined behavior. */
4120 tree return_void
4121 = get_coroutine_return_void_expr (current_function_decl, fn_start, false);
4123 /* The pointer to the resume function. */
4124 tree resume_fn_ptr
4125 = coro_build_artificial_var (fn_start, coro_resume_fn_id,
4126 resume_fn_ptr_type, orig, NULL_TREE);
4127 DECL_CHAIN (resume_fn_ptr) = var_list;
4128 var_list = resume_fn_ptr;
4129 add_decl_expr (resume_fn_ptr);
4131 /* We will need to be able to set the resume function pointer to nullptr
4132 to signal that the coroutine is 'done'. */
4133 tree zero_resume
4134 = build1 (CONVERT_EXPR, resume_fn_ptr_type, integer_zero_node);
4136 /* The pointer to the destroy function. */
4137 tree var = coro_build_artificial_var (fn_start, coro_destroy_fn_id,
4138 resume_fn_ptr_type, orig, NULL_TREE);
4139 DECL_CHAIN (var) = var_list;
4140 var_list = var;
4141 add_decl_expr (var);
4143 /* The promise was created on demand when parsing we now link it into
4144 our scope. */
4145 tree promise = get_coroutine_promise_proxy (orig);
4146 DECL_CONTEXT (promise) = orig;
4147 DECL_SOURCE_LOCATION (promise) = fn_start;
4148 DECL_CHAIN (promise) = var_list;
4149 var_list = promise;
4150 add_decl_expr (promise);
4152 /* We need a handle to this coroutine, which is passed to every
4153 await_suspend(). This was created on demand when parsing we now link it
4154 into our scope. */
4155 var = get_coroutine_self_handle_proxy (orig);
4156 DECL_CONTEXT (var) = orig;
4157 DECL_SOURCE_LOCATION (var) = fn_start;
4158 DECL_CHAIN (var) = var_list;
4159 var_list = var;
4160 add_decl_expr (var);
4162 /* If we have function parms, then these will be copied to the coroutine
4163 frame. Create a local (proxy) variable for each parm, since the original
4164 parms will be out of scope once the ramp has finished. The proxy vars will
4165 get DECL_VALUE_EXPRs pointing to the frame copies, so that we can interact
4166 with them in the debugger. */
4167 if (param_uses)
4169 gcc_checking_assert (DECL_ARGUMENTS (orig));
4170 /* Add a local var for each parm. */
4171 for (tree arg = DECL_ARGUMENTS (orig); arg != NULL;
4172 arg = DECL_CHAIN (arg))
4174 param_info *parm_i = param_uses->get (arg);
4175 gcc_checking_assert (parm_i);
4176 parm_i->copy_var
4177 = build_lang_decl (VAR_DECL, parm_i->field_id, TREE_TYPE (arg));
4178 DECL_SOURCE_LOCATION (parm_i->copy_var) = DECL_SOURCE_LOCATION (arg);
4179 DECL_CONTEXT (parm_i->copy_var) = orig;
4180 DECL_ARTIFICIAL (parm_i->copy_var) = true;
4181 DECL_CHAIN (parm_i->copy_var) = var_list;
4182 var_list = parm_i->copy_var;
4183 add_decl_expr (parm_i->copy_var);
4186 /* Now replace all uses of the parms in the function body with the proxy
4187 vars. We want to this to apply to every instance of param's use, so
4188 don't include a 'visited' hash_set on the tree walk, however we will
4189 arrange to visit each containing expression only once. */
4190 hash_set<tree *> visited;
4191 param_frame_data param_data = {NULL, param_uses,
4192 &visited, fn_start, false};
4193 cp_walk_tree (&fnbody, rewrite_param_uses, &param_data, NULL);
4196 /* We create a resume index, this is initialized in the ramp. */
4197 resume_idx_var
4198 = coro_build_artificial_var (fn_start, coro_resume_index_id,
4199 short_unsigned_type_node, orig, NULL_TREE);
4200 DECL_CHAIN (resume_idx_var) = var_list;
4201 var_list = resume_idx_var;
4202 add_decl_expr (resume_idx_var);
4204 /* If the coroutine has a frame that needs to be freed, this will be set by
4205 the ramp. */
4206 var = coro_build_artificial_var (fn_start, coro_frame_needs_free_id,
4207 boolean_type_node, orig, NULL_TREE);
4208 DECL_CHAIN (var) = var_list;
4209 var_list = var;
4210 add_decl_expr (var);
4212 if (flag_exceptions)
4214 /* Build promise.unhandled_exception(); */
4215 tree ueh
4216 = coro_build_promise_expression (current_function_decl, promise,
4217 coro_unhandled_exception_identifier,
4218 fn_start, NULL, /*musthave=*/true);
4219 /* Create and initialize the initial-await-resume-called variable per
4220 [dcl.fct.def.coroutine] / 5.3. */
4221 tree i_a_r_c
4222 = coro_build_artificial_var (fn_start, coro_frame_i_a_r_c_id,
4223 boolean_type_node, orig,
4224 boolean_false_node);
4225 DECL_CHAIN (i_a_r_c) = var_list;
4226 var_list = i_a_r_c;
4227 add_decl_expr (i_a_r_c);
4228 /* Start the try-catch. */
4229 tree tcb = build_stmt (fn_start, TRY_BLOCK, NULL_TREE, NULL_TREE);
4230 add_stmt (tcb);
4231 TRY_STMTS (tcb) = push_stmt_list ();
4232 if (initial_await != error_mark_node)
4234 /* Build a compound expression that sets the
4235 initial-await-resume-called variable true and then calls the
4236 initial suspend expression await resume.
4237 In the case that the user decides to make the initial await
4238 await_resume() return a value, we need to discard it and, it is
4239 a reference type, look past the indirection. */
4240 if (INDIRECT_REF_P (initial_await))
4241 initial_await = TREE_OPERAND (initial_await, 0);
4242 tree vec = TREE_OPERAND (initial_await, 3);
4243 tree aw_r = TREE_VEC_ELT (vec, 2);
4244 aw_r = convert_to_void (aw_r, ICV_STATEMENT, tf_warning_or_error);
4245 tree update = build2 (MODIFY_EXPR, boolean_type_node, i_a_r_c,
4246 boolean_true_node);
4247 aw_r = cp_build_compound_expr (update, aw_r, tf_warning_or_error);
4248 TREE_VEC_ELT (vec, 2) = aw_r;
4250 /* Add the initial await to the start of the user-authored function. */
4251 finish_expr_stmt (initial_await);
4252 /* Append the original function body. */
4253 add_stmt (fnbody);
4254 if (return_void)
4255 add_stmt (return_void);
4256 TRY_STMTS (tcb) = pop_stmt_list (TRY_STMTS (tcb));
4257 TRY_HANDLERS (tcb) = push_stmt_list ();
4258 /* Mimic what the parser does for the catch. */
4259 tree handler = begin_handler ();
4260 finish_handler_parms (NULL_TREE, handler); /* catch (...) */
4262 /* Get the initial await resume called value. */
4263 tree not_iarc_if = begin_if_stmt ();
4264 tree not_iarc = build1_loc (fn_start, TRUTH_NOT_EXPR,
4265 boolean_type_node, i_a_r_c);
4266 finish_if_stmt_cond (not_iarc, not_iarc_if);
4267 /* If the initial await resume called value is false, rethrow... */
4268 tree rethrow = build_throw (fn_start, NULL_TREE);
4269 suppress_warning (rethrow);
4270 finish_expr_stmt (rethrow);
4271 finish_then_clause (not_iarc_if);
4272 tree iarc_scope = IF_SCOPE (not_iarc_if);
4273 IF_SCOPE (not_iarc_if) = NULL;
4274 not_iarc_if = do_poplevel (iarc_scope);
4275 add_stmt (not_iarc_if);
4276 /* ... else call the promise unhandled exception method
4277 but first we set done = true and the resume index to 0.
4278 If the unhandled exception method returns, then we continue
4279 to the final await expression (which duplicates the clearing of
4280 the field). */
4281 tree r = build2 (MODIFY_EXPR, resume_fn_ptr_type, resume_fn_ptr,
4282 zero_resume);
4283 finish_expr_stmt (r);
4284 tree short_zero = build_int_cst (short_unsigned_type_node, 0);
4285 r = build2 (MODIFY_EXPR, short_unsigned_type_node, resume_idx_var,
4286 short_zero);
4287 finish_expr_stmt (r);
4288 finish_expr_stmt (ueh);
4289 finish_handler (handler);
4290 TRY_HANDLERS (tcb) = pop_stmt_list (TRY_HANDLERS (tcb));
4292 else
4294 if (pedantic)
4296 /* We still try to look for the promise method and warn if it's not
4297 present. */
4298 tree ueh_meth
4299 = lookup_promise_method (orig, coro_unhandled_exception_identifier,
4300 fn_start, /*musthave=*/false);
4301 if (!ueh_meth || ueh_meth == error_mark_node)
4302 warning_at (fn_start, 0, "no member named %qE in %qT",
4303 coro_unhandled_exception_identifier,
4304 get_coroutine_promise_type (orig));
4306 /* Else we don't check and don't care if the method is missing..
4307 just add the initial suspend, function and return. */
4308 finish_expr_stmt (initial_await);
4309 /* Append the original function body. */
4310 add_stmt (fnbody);
4311 if (return_void)
4312 add_stmt (return_void);
4315 /* co_return branches to the final_suspend label, so declare that now. */
4316 fs_label
4317 = create_named_label_with_ctx (fn_start, "final.suspend", NULL_TREE);
4318 add_stmt (build_stmt (fn_start, LABEL_EXPR, fs_label));
4320 /* Before entering the final suspend point, we signal that this point has
4321 been reached by setting the resume function pointer to zero (this is
4322 what the 'done()' builtin tests) as per the current ABI. */
4323 zero_resume = build2 (MODIFY_EXPR, resume_fn_ptr_type, resume_fn_ptr,
4324 zero_resume);
4325 finish_expr_stmt (zero_resume);
4326 finish_expr_stmt (build_init_or_final_await (fn_start, true));
4327 BIND_EXPR_BODY (update_body) = pop_stmt_list (BIND_EXPR_BODY (update_body));
4328 BIND_EXPR_VARS (update_body) = nreverse (var_list);
4329 BLOCK_VARS (top_block) = BIND_EXPR_VARS (update_body);
4331 return update_body;
4334 /* Here we:
4335 a) Check that the function and promise type are valid for a
4336 coroutine.
4337 b) Carry out the initial morph to create the skeleton of the
4338 coroutine ramp function and the rewritten body.
4340 Assumptions.
4342 1. We only hit this code once all dependencies are resolved.
4343 2. The function body will be either a bind expr or a statement list
4344 3. That cfun and current_function_decl are valid for the case we're
4345 expanding.
4346 4. 'input_location' will be of the final brace for the function.
4348 We do something like this:
4349 declare a dummy coro frame.
4350 struct _R_frame {
4351 using handle_type = coro::coroutine_handle<coro1::promise_type>;
4352 void (*_Coro_resume_fn)(_R_frame *);
4353 void (*_Coro_destroy_fn)(_R_frame *);
4354 coro1::promise_type _Coro_promise;
4355 bool _Coro_frame_needs_free; free the coro frame mem if set.
4356 bool _Coro_i_a_r_c; [dcl.fct.def.coroutine] / 5.3
4357 short _Coro_resume_index;
4358 handle_type _Coro_self_handle;
4359 parameter copies (were required).
4360 local variables saved (including awaitables)
4361 (maybe) trailing space.
4362 }; */
4364 bool
4365 morph_fn_to_coro (tree orig, tree *resumer, tree *destroyer)
4367 gcc_checking_assert (orig && TREE_CODE (orig) == FUNCTION_DECL);
4369 *resumer = error_mark_node;
4370 *destroyer = error_mark_node;
4371 if (!coro_function_valid_p (orig))
4373 /* For early errors, we do not want a diagnostic about the missing
4374 ramp return value, since the user cannot fix this - a 'return' is
4375 not allowed in a coroutine. */
4376 suppress_warning (orig, OPT_Wreturn_type);
4377 /* Discard the body, we can't process it further. */
4378 pop_stmt_list (DECL_SAVED_TREE (orig));
4379 DECL_SAVED_TREE (orig) = push_stmt_list ();
4380 return false;
4383 /* We can't validly get here with an empty statement list, since there's no
4384 way for the FE to decide it's a coroutine in the absence of any code. */
4385 tree fnbody = pop_stmt_list (DECL_SAVED_TREE (orig));
4386 gcc_checking_assert (fnbody != NULL_TREE);
4388 /* We don't have the locus of the opening brace - it's filled in later (and
4389 there doesn't really seem to be any easy way to get at it).
4390 The closing brace is assumed to be input_location. */
4391 location_t fn_start = DECL_SOURCE_LOCATION (orig);
4392 gcc_rich_location fn_start_loc (fn_start);
4394 /* Initial processing of the function-body.
4395 If we have no expressions or just an error then punt. */
4396 tree body_start = expr_first (fnbody);
4397 if (body_start == NULL_TREE || body_start == error_mark_node)
4399 DECL_SAVED_TREE (orig) = push_stmt_list ();
4400 append_to_statement_list (fnbody, &DECL_SAVED_TREE (orig));
4401 /* Suppress warnings about the missing return value. */
4402 suppress_warning (orig, OPT_Wreturn_type);
4403 return false;
4406 /* So, we've tied off the original user-authored body in fn_body.
4408 Start the replacement synthesized ramp body as newbody.
4409 If we encounter a fatal error we might return a now-empty body.
4411 Note, the returned ramp body is not 'popped', to be compatible with
4412 the way that decl.cc handles regular functions, the scope pop is done
4413 in the caller. */
4415 tree newbody = push_stmt_list ();
4416 DECL_SAVED_TREE (orig) = newbody;
4418 /* If our original body is noexcept, then that's what we apply to our
4419 generated ramp, transfer any MUST_NOT_THOW_EXPR to that. */
4420 bool is_noexcept = TREE_CODE (body_start) == MUST_NOT_THROW_EXPR;
4421 if (is_noexcept)
4423 /* The function body we will continue with is the single operand to
4424 the must-not-throw. */
4425 fnbody = TREE_OPERAND (body_start, 0);
4426 /* Transfer the must-not-throw to the ramp body. */
4427 add_stmt (body_start);
4428 /* Re-start the ramp as must-not-throw. */
4429 TREE_OPERAND (body_start, 0) = push_stmt_list ();
4432 /* If the original function has a return value with a non-trivial DTOR
4433 and the body contains a var with a DTOR that might throw, the decl is
4434 marked "throwing_cleanup".
4435 We do not [in the ramp, which is synthesised here], use any body var
4436 types with DTORs that might throw.
4437 The original body is transformed into the actor function which only
4438 contains void returns, and is also wrapped in a try-catch block.
4439 So (a) the 'throwing_cleanup' is not correct for the ramp and (b) we do
4440 not need to transfer it to the actor which only contains void returns. */
4441 cp_function_chain->throwing_cleanup = false;
4443 /* Create the coro frame type, as far as it can be known at this stage.
4444 1. Types we already know. */
4446 tree fn_return_type = TREE_TYPE (TREE_TYPE (orig));
4447 tree handle_type = get_coroutine_handle_type (orig);
4448 tree promise_type = get_coroutine_promise_type (orig);
4450 /* 2. Types we need to define or look up. */
4452 tree fr_name = get_fn_local_identifier (orig, "Frame");
4453 tree coro_frame_type = xref_tag (record_type, fr_name);
4454 DECL_CONTEXT (TYPE_NAME (coro_frame_type)) = current_scope ();
4455 tree coro_frame_ptr = build_pointer_type (coro_frame_type);
4456 tree act_des_fn_type
4457 = build_function_type_list (void_type_node, coro_frame_ptr, NULL_TREE);
4458 tree act_des_fn_ptr = build_pointer_type (act_des_fn_type);
4460 /* Declare the actor and destroyer function. */
4461 tree actor = coro_build_actor_or_destroy_function (orig, act_des_fn_type,
4462 coro_frame_ptr, true);
4463 tree destroy = coro_build_actor_or_destroy_function (orig, act_des_fn_type,
4464 coro_frame_ptr, false);
4466 /* Construct the wrapped function body; we will analyze this to determine
4467 the requirements for the coroutine frame. */
4469 tree resume_idx_var = NULL_TREE;
4470 tree fs_label = NULL_TREE;
4471 hash_map<tree, param_info> *param_uses = analyze_fn_parms (orig);
4473 fnbody = coro_rewrite_function_body (fn_start, fnbody, orig, param_uses,
4474 act_des_fn_ptr,
4475 resume_idx_var, fs_label);
4476 /* Build our dummy coro frame layout. */
4477 coro_frame_type = begin_class_definition (coro_frame_type);
4479 /* The fields for the coro frame. */
4480 tree field_list = NULL_TREE;
4482 /* We need to know, and inspect, each suspend point in the function
4483 in several places. It's convenient to place this map out of line
4484 since it's used from tree walk callbacks. */
4485 suspend_points = new hash_map<tree, suspend_point_info>;
4487 /* Now insert the data for any body await points, at this time we also need
4488 to promote any temporaries that are captured by reference (to regular
4489 vars) they will get added to the coro frame along with other locals. */
4490 susp_frame_data body_aw_points
4491 = {&field_list, handle_type, fs_label, NULL, NULL, 0, 0,
4492 hash_set<tree> (), NULL, NULL, 0, false, false, false};
4493 body_aw_points.block_stack = make_tree_vector ();
4494 body_aw_points.bind_stack = make_tree_vector ();
4495 body_aw_points.to_replace = make_tree_vector ();
4496 cp_walk_tree (&fnbody, await_statement_walker, &body_aw_points, NULL);
4498 /* 4. Now make space for local vars, this is conservative again, and we
4499 would expect to delete unused entries later. */
4500 hash_map<tree, local_var_info> local_var_uses;
4501 local_vars_frame_data local_vars_data
4502 = {&field_list, &local_var_uses, 0, 0, fn_start, false, false};
4503 cp_walk_tree (&fnbody, register_local_var_uses, &local_vars_data, NULL);
4505 /* Tie off the struct for now, so that we can build offsets to the
4506 known entries. */
4507 TYPE_FIELDS (coro_frame_type) = field_list;
4508 TYPE_BINFO (coro_frame_type) = make_tree_binfo (0);
4509 BINFO_OFFSET (TYPE_BINFO (coro_frame_type)) = size_zero_node;
4510 BINFO_TYPE (TYPE_BINFO (coro_frame_type)) = coro_frame_type;
4512 coro_frame_type = finish_struct (coro_frame_type, NULL_TREE);
4514 /* Ramp: */
4515 /* Now build the ramp function pieces. */
4516 tree ramp_bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
4517 add_stmt (ramp_bind);
4518 tree ramp_body = push_stmt_list ();
4520 tree zeroinit = build1_loc (fn_start, CONVERT_EXPR,
4521 coro_frame_ptr, integer_zero_node);
4522 tree coro_fp = coro_build_artificial_var (fn_start, "_Coro_frameptr",
4523 coro_frame_ptr, orig, zeroinit);
4524 tree varlist = coro_fp;
4526 /* To signal that we need to cleanup copied function args. */
4527 if (flag_exceptions && DECL_ARGUMENTS (orig))
4528 for (tree arg = DECL_ARGUMENTS (orig); arg != NULL;
4529 arg = DECL_CHAIN (arg))
4531 param_info *parm_i = param_uses->get (arg);
4532 gcc_checking_assert (parm_i);
4533 if (parm_i->trivial_dtor)
4534 continue;
4535 DECL_CHAIN (parm_i->guard_var) = varlist;
4536 varlist = parm_i->guard_var;
4539 /* Signal that we need to clean up the promise object on exception. */
4540 tree coro_promise_live
4541 = coro_build_artificial_var (fn_start, "_Coro_promise_live",
4542 boolean_type_node, orig, boolean_false_node);
4543 DECL_CHAIN (coro_promise_live) = varlist;
4544 varlist = coro_promise_live;
4546 /* When the get-return-object is in the RETURN slot, we need to arrange for
4547 cleanup on exception. */
4548 tree coro_gro_live
4549 = coro_build_artificial_var (fn_start, "_Coro_gro_live",
4550 boolean_type_node, orig, boolean_false_node);
4552 DECL_CHAIN (coro_gro_live) = varlist;
4553 varlist = coro_gro_live;
4555 /* Collected the scope vars we need ... only one for now. */
4556 BIND_EXPR_VARS (ramp_bind) = nreverse (varlist);
4558 /* We're now going to create a new top level scope block for the ramp
4559 function. */
4560 tree top_block = make_node (BLOCK);
4562 BIND_EXPR_BLOCK (ramp_bind) = top_block;
4563 BLOCK_VARS (top_block) = BIND_EXPR_VARS (ramp_bind);
4564 BLOCK_SUBBLOCKS (top_block) = NULL_TREE;
4565 current_binding_level->blocks = top_block;
4567 /* The decl_expr for the coro frame pointer, initialize to zero so that we
4568 can pass it to the IFN_CO_FRAME (since there's no way to pass a type,
4569 directly apparently). This avoids a "used uninitialized" warning. */
4571 add_decl_expr (coro_fp);
4572 if (flag_exceptions && DECL_ARGUMENTS (orig))
4573 for (tree arg = DECL_ARGUMENTS (orig); arg != NULL;
4574 arg = DECL_CHAIN (arg))
4576 param_info *parm_i = param_uses->get (arg);
4577 if (parm_i->trivial_dtor)
4578 continue;
4579 add_decl_expr (parm_i->guard_var);;
4581 add_decl_expr (coro_promise_live);
4582 add_decl_expr (coro_gro_live);
4584 /* The CO_FRAME internal function is a mechanism to allow the middle end
4585 to adjust the allocation in response to optimizations. We provide the
4586 current conservative estimate of the frame size (as per the current)
4587 computed layout. */
4588 tree frame_size = TYPE_SIZE_UNIT (coro_frame_type);
4589 tree resizeable
4590 = build_call_expr_internal_loc (fn_start, IFN_CO_FRAME, size_type_node, 2,
4591 frame_size, coro_fp);
4593 /* [dcl.fct.def.coroutine] / 10 (part1)
4594 The unqualified-id get_return_object_on_allocation_failure is looked up
4595 in the scope of the promise type by class member access lookup. */
4597 /* We don't require this, so coro_build_promise_expression can return NULL,
4598 but, if the lookup succeeds, then the function must be usable. */
4599 tree dummy_promise = build_dummy_object (get_coroutine_promise_type (orig));
4600 tree grooaf
4601 = coro_build_promise_expression (orig, dummy_promise,
4602 coro_gro_on_allocation_fail_identifier,
4603 fn_start, NULL, /*musthave=*/false);
4605 /* however, should that fail, returning an error, the later stages can't
4606 handle the erroneous expression, so we reset the call as if it was
4607 absent. */
4608 if (grooaf == error_mark_node)
4609 grooaf = NULL_TREE;
4611 /* Allocate the frame, this has several possibilities:
4612 [dcl.fct.def.coroutine] / 9 (part 1)
4613 The allocation function’s name is looked up in the scope of the promise
4614 type. It's not a failure for it to be absent see part 4, below. */
4616 tree nwname = ovl_op_identifier (false, NEW_EXPR);
4617 tree new_fn = NULL_TREE;
4619 if (TYPE_HAS_NEW_OPERATOR (promise_type))
4621 tree fns = lookup_promise_method (orig, nwname, fn_start,
4622 /*musthave=*/true);
4623 /* [dcl.fct.def.coroutine] / 9 (part 2)
4624 If the lookup finds an allocation function in the scope of the promise
4625 type, overload resolution is performed on a function call created by
4626 assembling an argument list. The first argument is the amount of space
4627 requested, and has type std::size_t. The lvalues p1...pn are the
4628 succeeding arguments.. */
4629 vec<tree, va_gc> *args = make_tree_vector ();
4630 vec_safe_push (args, resizeable); /* Space needed. */
4632 for (tree arg = DECL_ARGUMENTS (orig); arg != NULL;
4633 arg = DECL_CHAIN (arg))
4635 param_info *parm_i = param_uses->get (arg);
4636 gcc_checking_assert (parm_i);
4637 if (parm_i->this_ptr || parm_i->lambda_cobj)
4639 /* We pass a reference to *this to the allocator lookup. */
4640 tree tt = TREE_TYPE (TREE_TYPE (arg));
4641 tree this_ref = build1 (INDIRECT_REF, tt, arg);
4642 tt = cp_build_reference_type (tt, false);
4643 this_ref = convert_to_reference (tt, this_ref, CONV_STATIC,
4644 LOOKUP_NORMAL , NULL_TREE,
4645 tf_warning_or_error);
4646 vec_safe_push (args, convert_from_reference (this_ref));
4648 else
4649 vec_safe_push (args, convert_from_reference (arg));
4652 /* Note the function selected; we test to see if it's NOTHROW. */
4653 tree func;
4654 /* Failure is not an error for this attempt. */
4655 new_fn = build_new_method_call (dummy_promise, fns, &args, NULL,
4656 LOOKUP_NORMAL, &func, tf_none);
4657 release_tree_vector (args);
4659 if (new_fn == error_mark_node)
4661 /* [dcl.fct.def.coroutine] / 9 (part 3)
4662 If no viable function is found, overload resolution is performed
4663 again on a function call created by passing just the amount of
4664 space required as an argument of type std::size_t. */
4665 args = make_tree_vector_single (resizeable); /* Space needed. */
4666 new_fn = build_new_method_call (dummy_promise, fns, &args,
4667 NULL_TREE, LOOKUP_NORMAL, &func,
4668 tf_none);
4669 release_tree_vector (args);
4672 /* However, if the promise provides an operator new, then one of these
4673 two options must be available. */
4674 if (new_fn == error_mark_node)
4676 error_at (fn_start, "%qE is provided by %qT but is not usable with"
4677 " the function signature %qD", nwname, promise_type, orig);
4678 new_fn = error_mark_node;
4680 else if (grooaf && !TYPE_NOTHROW_P (TREE_TYPE (func)))
4681 error_at (fn_start, "%qE is provided by %qT but %qE is not marked"
4682 " %<throw()%> or %<noexcept%>", grooaf, promise_type, nwname);
4683 else if (!grooaf && TYPE_NOTHROW_P (TREE_TYPE (func)))
4684 warning_at (fn_start, 0, "%qE is marked %<throw()%> or %<noexcept%> but"
4685 " no usable %<get_return_object_on_allocation_failure%>"
4686 " is provided by %qT", nwname, promise_type);
4688 else /* No operator new in the promise. */
4690 /* [dcl.fct.def.coroutine] / 9 (part 4)
4691 If this lookup fails, the allocation function’s name is looked up in
4692 the global scope. */
4694 vec<tree, va_gc> *args;
4695 /* build_operator_new_call () will insert size needed as element 0 of
4696 this, and we might need to append the std::nothrow constant. */
4697 vec_alloc (args, 2);
4698 if (grooaf)
4700 /* [dcl.fct.def.coroutine] / 10 (part 2)
4701 If any declarations (of the get return on allocation fail) are
4702 found, then the result of a call to an allocation function used
4703 to obtain storage for the coroutine state is assumed to return
4704 nullptr if it fails to obtain storage and, if a global allocation
4705 function is selected, the ::operator new(size_t, nothrow_t) form
4706 is used. The allocation function used in this case shall have a
4707 non-throwing noexcept-specification. So we need std::nothrow. */
4708 tree std_nt = lookup_qualified_name (std_node,
4709 get_identifier ("nothrow"),
4710 LOOK_want::NORMAL,
4711 /*complain=*/true);
4712 if (!std_nt || std_nt == error_mark_node)
4713 error_at (fn_start, "%qE is provided by %qT but %<std::nothrow%> "
4714 "cannot be found", grooaf, promise_type);
4715 vec_safe_push (args, std_nt);
4718 /* If we get to this point, we must succeed in looking up the global
4719 operator new for the params provided. Extract a simplified version
4720 of the machinery from build_operator_new_call. This can update the
4721 frame size. */
4722 tree cookie = NULL;
4723 new_fn = build_operator_new_call (nwname, &args, &frame_size, &cookie,
4724 /*align_arg=*/NULL,
4725 /*size_check=*/NULL, /*fn=*/NULL,
4726 tf_warning_or_error);
4727 resizeable = build_call_expr_internal_loc
4728 (fn_start, IFN_CO_FRAME, size_type_node, 2, frame_size, coro_fp);
4729 /* If the operator call fails for some reason, then don't try to
4730 amend it. */
4731 if (new_fn != error_mark_node)
4732 CALL_EXPR_ARG (new_fn, 0) = resizeable;
4734 release_tree_vector (args);
4737 tree allocated = build1 (CONVERT_EXPR, coro_frame_ptr, new_fn);
4738 tree r = build2 (INIT_EXPR, TREE_TYPE (coro_fp), coro_fp, allocated);
4739 r = coro_build_cvt_void_expr_stmt (r, fn_start);
4740 add_stmt (r);
4742 /* If the user provided a method to return an object on alloc fail, then
4743 check the returned pointer and call the func if it's null.
4744 Otherwise, no check, and we fail for noexcept/fno-exceptions cases. */
4746 if (grooaf)
4748 /* [dcl.fct.def.coroutine] / 10 (part 3)
4749 If the allocation function returns nullptr,the coroutine returns
4750 control to the caller of the coroutine and the return value is
4751 obtained by a call to T::get_return_object_on_allocation_failure(),
4752 where T is the promise type. */
4754 gcc_checking_assert (same_type_p (fn_return_type, TREE_TYPE (grooaf)));
4755 tree if_stmt = begin_if_stmt ();
4756 tree cond = build1 (CONVERT_EXPR, coro_frame_ptr, integer_zero_node);
4757 cond = build2 (EQ_EXPR, boolean_type_node, coro_fp, cond);
4758 finish_if_stmt_cond (cond, if_stmt);
4759 if (VOID_TYPE_P (fn_return_type))
4761 /* Execute the get-return-object-on-alloc-fail call... */
4762 finish_expr_stmt (grooaf);
4763 /* ... but discard the result, since we return void. */
4764 finish_return_stmt (NULL_TREE);
4766 else
4768 /* Get the fallback return object. */
4769 r = build_cplus_new (fn_return_type, grooaf, tf_warning_or_error);
4770 finish_return_stmt (r);
4772 finish_then_clause (if_stmt);
4773 finish_if_stmt (if_stmt);
4776 /* Up to now any exception thrown will propagate directly to the caller.
4777 This is OK since the only source of such exceptions would be in allocation
4778 of the coroutine frame, and therefore the ramp will not have initialized
4779 any further state. From here, we will track state that needs explicit
4780 destruction in the case that promise or g.r.o setup fails or an exception
4781 is thrown from the initial suspend expression. */
4782 tree ramp_cleanup = NULL_TREE;
4783 if (flag_exceptions)
4785 ramp_cleanup = build_stmt (fn_start, TRY_BLOCK, NULL, NULL);
4786 add_stmt (ramp_cleanup);
4787 TRY_STMTS (ramp_cleanup) = push_stmt_list ();
4790 /* deref the frame pointer, to use in member access code. */
4791 tree deref_fp = build_x_arrow (fn_start, coro_fp, tf_warning_or_error);
4793 /* For now, once allocation has succeeded we always assume that this needs
4794 destruction, there's no impl. for frame allocation elision. */
4795 tree fnf_m = lookup_member (coro_frame_type, coro_frame_needs_free_id,
4796 1, 0,tf_warning_or_error);
4797 tree fnf_x = build_class_member_access_expr (deref_fp, fnf_m, NULL_TREE,
4798 false, tf_warning_or_error);
4799 r = build2 (INIT_EXPR, boolean_type_node, fnf_x, boolean_true_node);
4800 r = coro_build_cvt_void_expr_stmt (r, fn_start);
4801 add_stmt (r);
4803 /* Put the resumer and destroyer functions in. */
4805 tree actor_addr = build1 (ADDR_EXPR, act_des_fn_ptr, actor);
4806 tree resume_m
4807 = lookup_member (coro_frame_type, coro_resume_fn_id,
4808 /*protect=*/1, /*want_type=*/0, tf_warning_or_error);
4809 tree resume_x = build_class_member_access_expr (deref_fp, resume_m, NULL_TREE,
4810 false, tf_warning_or_error);
4811 r = build2_loc (fn_start, INIT_EXPR, act_des_fn_ptr, resume_x, actor_addr);
4812 finish_expr_stmt (r);
4814 tree destroy_addr = build1 (ADDR_EXPR, act_des_fn_ptr, destroy);
4815 tree destroy_m
4816 = lookup_member (coro_frame_type, coro_destroy_fn_id,
4817 /*protect=*/1, /*want_type=*/0, tf_warning_or_error);
4818 tree destroy_x
4819 = build_class_member_access_expr (deref_fp, destroy_m, NULL_TREE, false,
4820 tf_warning_or_error);
4821 r = build2_loc (fn_start, INIT_EXPR, act_des_fn_ptr, destroy_x, destroy_addr);
4822 finish_expr_stmt (r);
4824 /* [dcl.fct.def.coroutine] /13
4825 When a coroutine is invoked, a copy is created for each coroutine
4826 parameter. Each such copy is an object with automatic storage duration
4827 that is direct-initialized from an lvalue referring to the corresponding
4828 parameter if the parameter is an lvalue reference, and from an xvalue
4829 referring to it otherwise. A reference to a parameter in the function-
4830 body of the coroutine and in the call to the coroutine promise
4831 constructor is replaced by a reference to its copy. */
4833 vec<tree, va_gc> *promise_args = NULL; /* So that we can adjust refs. */
4835 /* The initialization and destruction of each parameter copy occurs in the
4836 context of the called coroutine. Initializations of parameter copies are
4837 sequenced before the call to the coroutine promise constructor and
4838 indeterminately sequenced with respect to each other. The lifetime of
4839 parameter copies ends immediately after the lifetime of the coroutine
4840 promise object ends. */
4842 vec<tree, va_gc> *param_dtor_list = NULL;
4844 if (DECL_ARGUMENTS (orig))
4846 promise_args = make_tree_vector ();
4847 for (tree arg = DECL_ARGUMENTS (orig); arg != NULL;
4848 arg = DECL_CHAIN (arg))
4850 bool existed;
4851 param_info &parm = param_uses->get_or_insert (arg, &existed);
4853 tree fld_ref = lookup_member (coro_frame_type, parm.field_id,
4854 /*protect=*/1, /*want_type=*/0,
4855 tf_warning_or_error);
4856 tree fld_idx
4857 = build_class_member_access_expr (deref_fp, fld_ref, NULL_TREE,
4858 false, tf_warning_or_error);
4860 /* Add this to the promise CTOR arguments list, accounting for
4861 refs and special handling for method this ptr. */
4862 if (parm.this_ptr || parm.lambda_cobj)
4864 /* We pass a reference to *this to the param preview. */
4865 tree tt = TREE_TYPE (arg);
4866 gcc_checking_assert (POINTER_TYPE_P (tt));
4867 tree ct = TREE_TYPE (tt);
4868 tree this_ref = build1 (INDIRECT_REF, ct, arg);
4869 tree rt = cp_build_reference_type (ct, false);
4870 this_ref = convert_to_reference (rt, this_ref, CONV_STATIC,
4871 LOOKUP_NORMAL, NULL_TREE,
4872 tf_warning_or_error);
4873 vec_safe_push (promise_args, this_ref);
4875 else if (parm.rv_ref)
4876 vec_safe_push (promise_args, move (fld_idx));
4877 else
4878 vec_safe_push (promise_args, fld_idx);
4880 if (parm.rv_ref || parm.pt_ref)
4881 /* Initialise the frame reference field directly. */
4882 r = cp_build_modify_expr (fn_start, TREE_OPERAND (fld_idx, 0),
4883 INIT_EXPR, arg, tf_warning_or_error);
4884 else
4886 r = forward_parm (arg);
4887 r = cp_build_modify_expr (fn_start, fld_idx, INIT_EXPR, r,
4888 tf_warning_or_error);
4890 finish_expr_stmt (r);
4891 if (!parm.trivial_dtor)
4893 if (param_dtor_list == NULL)
4894 param_dtor_list = make_tree_vector ();
4895 vec_safe_push (param_dtor_list, parm.field_id);
4896 /* Cleanup this frame copy on exception. */
4897 parm.fr_copy_dtor
4898 = build_special_member_call (fld_idx, complete_dtor_identifier,
4899 NULL, parm.frame_type,
4900 LOOKUP_NORMAL,
4901 tf_warning_or_error);
4902 if (flag_exceptions)
4904 /* This var is now live. */
4905 r = build_modify_expr (fn_start, parm.guard_var,
4906 boolean_type_node, INIT_EXPR, fn_start,
4907 boolean_true_node, boolean_type_node);
4908 finish_expr_stmt (r);
4914 /* Set up the promise. */
4915 tree promise_m
4916 = lookup_member (coro_frame_type, coro_promise_id,
4917 /*protect=*/1, /*want_type=*/0, tf_warning_or_error);
4919 tree p = build_class_member_access_expr (deref_fp, promise_m, NULL_TREE,
4920 false, tf_warning_or_error);
4922 tree promise_dtor = NULL_TREE;
4923 if (type_build_ctor_call (promise_type))
4925 /* Do a placement new constructor for the promise type (we never call
4926 the new operator, just the constructor on the object in place in the
4927 frame).
4929 First try to find a constructor with the same parameter list as the
4930 original function (if it has params), failing that find a constructor
4931 with no parameter list. */
4933 if (DECL_ARGUMENTS (orig))
4935 r = build_special_member_call (p, complete_ctor_identifier,
4936 &promise_args, promise_type,
4937 LOOKUP_NORMAL, tf_none);
4938 release_tree_vector (promise_args);
4940 else
4941 r = NULL_TREE;
4943 if (r == NULL_TREE || r == error_mark_node)
4944 r = build_special_member_call (p, complete_ctor_identifier, NULL,
4945 promise_type, LOOKUP_NORMAL,
4946 tf_warning_or_error);
4948 r = coro_build_cvt_void_expr_stmt (r, fn_start);
4949 finish_expr_stmt (r);
4951 r = build_modify_expr (fn_start, coro_promise_live, boolean_type_node,
4952 INIT_EXPR, fn_start, boolean_true_node,
4953 boolean_type_node);
4954 finish_expr_stmt (r);
4956 promise_dtor
4957 = build_special_member_call (p, complete_dtor_identifier,
4958 NULL, promise_type, LOOKUP_NORMAL,
4959 tf_warning_or_error);
4962 /* Set up a new bind context for the GRO. */
4963 tree gro_context_bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
4964 /* Make and connect the scope blocks. */
4965 tree gro_block = make_node (BLOCK);
4966 BLOCK_SUPERCONTEXT (gro_block) = top_block;
4967 BLOCK_SUBBLOCKS (top_block) = gro_block;
4968 BIND_EXPR_BLOCK (gro_context_bind) = gro_block;
4969 add_stmt (gro_context_bind);
4971 tree get_ro
4972 = coro_build_promise_expression (orig, p,
4973 coro_get_return_object_identifier,
4974 fn_start, NULL, /*musthave=*/true);
4975 /* Without a return object we haven't got much clue what's going on. */
4976 if (get_ro == error_mark_node)
4978 BIND_EXPR_BODY (ramp_bind) = pop_stmt_list (ramp_body);
4979 DECL_SAVED_TREE (orig) = newbody;
4980 /* Suppress warnings about the missing return value. */
4981 suppress_warning (orig, OPT_Wreturn_type);
4982 return false;
4985 tree gro_context_body = push_stmt_list ();
4986 tree gro_type = TREE_TYPE (get_ro);
4987 bool gro_is_void_p = VOID_TYPE_P (gro_type);
4989 tree gro = NULL_TREE;
4990 tree gro_bind_vars = NULL_TREE;
4991 /* Used for return objects in the RESULT slot. */
4992 tree gro_ret_dtor = NULL_TREE;
4993 tree gro_cleanup_stmt = NULL_TREE;
4994 /* We have to sequence the call to get_return_object before initial
4995 suspend. */
4996 if (gro_is_void_p)
4997 r = get_ro;
4998 else if (same_type_p (gro_type, fn_return_type))
5000 /* [dcl.fct.def.coroutine] / 7
5001 The expression promise.get_return_object() is used to initialize the
5002 glvalue result or... (see below)
5003 Construct the return result directly. */
5004 if (type_build_ctor_call (gro_type))
5006 vec<tree, va_gc> *arg = make_tree_vector_single (get_ro);
5007 r = build_special_member_call (DECL_RESULT (orig),
5008 complete_ctor_identifier,
5009 &arg, gro_type, LOOKUP_NORMAL,
5010 tf_warning_or_error);
5011 release_tree_vector (arg);
5013 else
5014 r = build2_loc (fn_start, INIT_EXPR, gro_type,
5015 DECL_RESULT (orig), get_ro);
5017 if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (gro_type))
5018 /* If some part of the initalization code (prior to the await_resume
5019 of the initial suspend expression), then we need to clean up the
5020 return value. */
5021 gro_ret_dtor
5022 = build_special_member_call (DECL_RESULT (orig),
5023 complete_dtor_identifier, NULL,
5024 gro_type, LOOKUP_NORMAL,
5025 tf_warning_or_error);
5027 else
5029 /* ... or ... Construct an object that will be used as the single
5030 param to the CTOR for the return object. */
5031 gro = coro_build_artificial_var (fn_start, "_Coro_gro", gro_type, orig,
5032 NULL_TREE);
5033 add_decl_expr (gro);
5034 gro_bind_vars = gro;
5035 r = cp_build_modify_expr (input_location, gro, INIT_EXPR, get_ro,
5036 tf_warning_or_error);
5037 /* The constructed object might require a cleanup. */
5038 if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (gro_type))
5040 gro_cleanup_stmt
5041 = build_special_member_call (gro, complete_dtor_identifier,
5042 NULL, gro_type, LOOKUP_NORMAL,
5043 tf_warning_or_error);
5044 gro_cleanup_stmt = build_stmt (input_location, CLEANUP_STMT, NULL,
5045 gro_cleanup_stmt, gro);
5048 finish_expr_stmt (r);
5050 if (gro_cleanup_stmt && gro_cleanup_stmt != error_mark_node)
5051 CLEANUP_BODY (gro_cleanup_stmt) = push_stmt_list ();
5053 /* If we have a live g.r.o in the return slot, then signal this for exception
5054 cleanup. */
5055 if (gro_ret_dtor)
5057 r = build_modify_expr (fn_start, coro_gro_live, boolean_type_node,
5058 INIT_EXPR, fn_start, boolean_true_node,
5059 boolean_type_node);
5060 finish_expr_stmt (r);
5062 /* Initialize the resume_idx_var to 0, meaning "not started". */
5063 tree resume_idx_m
5064 = lookup_member (coro_frame_type, coro_resume_index_id,
5065 /*protect=*/1, /*want_type=*/0, tf_warning_or_error);
5066 tree resume_idx
5067 = build_class_member_access_expr (deref_fp, resume_idx_m, NULL_TREE, false,
5068 tf_warning_or_error);
5069 r = build_int_cst (short_unsigned_type_node, 0);
5070 r = build2_loc (fn_start, INIT_EXPR, short_unsigned_type_node, resume_idx, r);
5071 r = coro_build_cvt_void_expr_stmt (r, fn_start);
5072 add_stmt (r);
5074 /* So .. call the actor .. */
5075 r = build_call_expr_loc (fn_start, actor, 1, coro_fp);
5076 r = maybe_cleanup_point_expr_void (r);
5077 add_stmt (r);
5079 /* Switch to using 'input_location' as the loc, since we're now more
5080 logically doing things related to the end of the function. */
5082 /* The ramp is done, we just need the return value.
5083 [dcl.fct.def.coroutine] / 7
5084 The expression promise.get_return_object() is used to initialize the
5085 glvalue result or prvalue result object of a call to a coroutine.
5087 If the 'get return object' is non-void, then we built it before the
5088 promise was constructed. We now supply a reference to that var,
5089 either as the return value (if it's the same type) or to the CTOR
5090 for an object of the return type. */
5092 if (same_type_p (gro_type, fn_return_type))
5093 r = gro_is_void_p ? NULL_TREE : DECL_RESULT (orig);
5094 else if (!gro_is_void_p)
5095 /* check_return_expr will automatically return gro as an rvalue via
5096 treat_lvalue_as_rvalue_p. */
5097 r = gro;
5098 else if (CLASS_TYPE_P (fn_return_type))
5100 /* For class type return objects, we can attempt to construct,
5101 even if the gro is void. ??? Citation ??? c++/100476 */
5102 r = build_special_member_call (NULL_TREE,
5103 complete_ctor_identifier, NULL,
5104 fn_return_type, LOOKUP_NORMAL,
5105 tf_warning_or_error);
5106 r = build_cplus_new (fn_return_type, r, tf_warning_or_error);
5108 else
5110 /* We can't initialize a non-class return value from void. */
5111 error_at (input_location, "cannot initialize a return object of type"
5112 " %qT with an rvalue of type %<void%>", fn_return_type);
5113 r = error_mark_node;
5116 finish_return_stmt (r);
5118 if (gro_cleanup_stmt)
5120 CLEANUP_BODY (gro_cleanup_stmt)
5121 = pop_stmt_list (CLEANUP_BODY (gro_cleanup_stmt));
5122 add_stmt (gro_cleanup_stmt);
5125 /* Finish up the ramp function. */
5126 BIND_EXPR_VARS (gro_context_bind) = gro_bind_vars;
5127 BIND_EXPR_BODY (gro_context_bind) = pop_stmt_list (gro_context_body);
5128 TREE_SIDE_EFFECTS (gro_context_bind) = true;
5130 if (flag_exceptions)
5132 TRY_HANDLERS (ramp_cleanup) = push_stmt_list ();
5133 tree handler = begin_handler ();
5134 finish_handler_parms (NULL_TREE, handler); /* catch (...) */
5136 /* If we have a live G.R.O in the return slot, then run its DTOR.
5137 When the return object is constructed from a separate g.r.o, this is
5138 already handled by its regular cleanup. */
5139 if (gro_ret_dtor && gro_ret_dtor != error_mark_node)
5141 tree gro_d_if = begin_if_stmt ();
5142 finish_if_stmt_cond (coro_gro_live, gro_d_if);
5143 finish_expr_stmt (gro_ret_dtor);
5144 finish_then_clause (gro_d_if);
5145 tree gro_d_if_scope = IF_SCOPE (gro_d_if);
5146 IF_SCOPE (gro_d_if) = NULL;
5147 gro_d_if = do_poplevel (gro_d_if_scope);
5148 add_stmt (gro_d_if);
5151 /* If the promise is live, then run its dtor if that's available. */
5152 if (promise_dtor && promise_dtor != error_mark_node)
5154 tree promise_d_if = begin_if_stmt ();
5155 finish_if_stmt_cond (coro_promise_live, promise_d_if);
5156 finish_expr_stmt (promise_dtor);
5157 finish_then_clause (promise_d_if);
5158 tree promise_d_if_scope = IF_SCOPE (promise_d_if);
5159 IF_SCOPE (promise_d_if) = NULL;
5160 promise_d_if = do_poplevel (promise_d_if_scope);
5161 add_stmt (promise_d_if);
5164 /* Clean up any frame copies of parms with non-trivial dtors. */
5165 if (DECL_ARGUMENTS (orig))
5166 for (tree arg = DECL_ARGUMENTS (orig); arg != NULL;
5167 arg = DECL_CHAIN (arg))
5169 param_info *parm_i = param_uses->get (arg);
5170 if (parm_i->trivial_dtor)
5171 continue;
5172 if (parm_i->fr_copy_dtor && parm_i->fr_copy_dtor != error_mark_node)
5174 tree dtor_if = begin_if_stmt ();
5175 finish_if_stmt_cond (parm_i->guard_var, dtor_if);
5176 finish_expr_stmt (parm_i->fr_copy_dtor);
5177 finish_then_clause (dtor_if);
5178 tree parm_d_if_scope = IF_SCOPE (dtor_if);
5179 IF_SCOPE (dtor_if) = NULL;
5180 dtor_if = do_poplevel (parm_d_if_scope);
5181 add_stmt (dtor_if);
5185 /* We always expect to delete the frame. */
5186 tree del_coro_fr = coro_get_frame_dtor (coro_fp, orig, frame_size,
5187 promise_type, fn_start);
5188 finish_expr_stmt (del_coro_fr);
5189 tree rethrow = build_throw (fn_start, NULL_TREE);
5190 suppress_warning (rethrow);
5191 finish_expr_stmt (rethrow);
5192 finish_handler (handler);
5193 TRY_HANDLERS (ramp_cleanup) = pop_stmt_list (TRY_HANDLERS (ramp_cleanup));
5196 BIND_EXPR_BODY (ramp_bind) = pop_stmt_list (ramp_body);
5197 TREE_SIDE_EFFECTS (ramp_bind) = true;
5199 /* Start to build the final functions.
5201 We push_deferring_access_checks to avoid these routines being seen as
5202 nested by the middle end; we are doing the outlining here. */
5204 push_deferring_access_checks (dk_no_check);
5206 /* Build the actor... */
5207 build_actor_fn (fn_start, coro_frame_type, actor, fnbody, orig,
5208 &local_var_uses, param_dtor_list,
5209 resume_idx_var, body_aw_points.await_number, frame_size);
5211 /* Destroyer ... */
5212 build_destroy_fn (fn_start, coro_frame_type, destroy, actor);
5214 pop_deferring_access_checks ();
5216 DECL_SAVED_TREE (orig) = newbody;
5217 /* Link our new functions into the list. */
5218 TREE_CHAIN (destroy) = TREE_CHAIN (orig);
5219 TREE_CHAIN (actor) = destroy;
5220 TREE_CHAIN (orig) = actor;
5222 *resumer = actor;
5223 *destroyer = destroy;
5225 delete suspend_points;
5226 suspend_points = NULL;
5227 return true;
5230 #include "gt-cp-coroutines.h"