]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/cp/coroutines.cc
c++: More simplification of name_lookup api
[thirdparty/gcc.git] / gcc / cp / coroutines.cc
1 /* coroutine-specific state, expansions and tests.
2
3 Copyright (C) 2018-2020 Free Software Foundation, Inc.
4
5 Contributed by Iain Sandoe <iain@sandoe.co.uk> under contract to Facebook.
6
7 This file is part of GCC.
8
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.
13
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.
18
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/>. */
22
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"
35
36 static bool coro_promise_type_found_p (tree, location_t);
37
38 /* GCC C++ coroutines implementation.
39
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.
42
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).
46
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.
53
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.
58
59 The functions in this file carry out the necessary analysis of, and
60 transforms to, the AST to perform this.
61
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.
64
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.
71
72 Each of the keywords will expand to a code sequence (although co_yield is
73 just syntactic sugar for a co_await).
74
75 We defer the analysis and transformation until template expansion is
76 complete so that we have complete types at that time. */
77
78
79 /* The state that we collect during parsing (and template expansion) for
80 a coroutine. */
81
82 struct GTY((for_user)) coroutine_info
83 {
84 tree function_decl; /* The original function decl. */
85 tree promise_type; /* The cached promise type for this function. */
86 tree handle_type; /* The cached coroutine handle for this function. */
87 tree self_h_proxy; /* A handle instance that is used as the proxy for the
88 one that will eventually be allocated in the coroutine
89 frame. */
90 tree promise_proxy; /* Likewise, a proxy promise instance. */
91 tree return_void; /* The expression for p.return_void() if it exists. */
92 location_t first_coro_keyword; /* The location of the keyword that made this
93 function into a coroutine. */
94 /* Flags to avoid repeated errors for per-function issues. */
95 bool coro_ret_type_error_emitted;
96 bool coro_promise_error_emitted;
97 };
98
99 struct coroutine_info_hasher : ggc_ptr_hash<coroutine_info>
100 {
101 typedef tree compare_type; /* We only compare the function decl. */
102 static inline hashval_t hash (coroutine_info *);
103 static inline hashval_t hash (const compare_type &);
104 static inline bool equal (coroutine_info *, coroutine_info *);
105 static inline bool equal (coroutine_info *, const compare_type &);
106 };
107
108 /* This table holds all the collected coroutine state for coroutines in
109 the current translation unit. */
110
111 static GTY (()) hash_table<coroutine_info_hasher> *coroutine_info_table;
112
113 /* We will initialize state lazily. */
114 static bool coro_initialized = false;
115
116 /* Return a hash value for the entry pointed to by INFO.
117 The compare type is a tree, but the only trees we are going use are
118 function decls. We use the DECL_UID as the hash value since that is
119 stable across PCH. */
120
121 hashval_t
122 coroutine_info_hasher::hash (coroutine_info *info)
123 {
124 return DECL_UID (info->function_decl);
125 }
126
127 /* Return a hash value for the compare value COMP. */
128
129 hashval_t
130 coroutine_info_hasher::hash (const compare_type& comp)
131 {
132 return DECL_UID (comp);
133 }
134
135 /* Return true if the entries pointed to by LHS and RHS are for the
136 same coroutine. */
137
138 bool
139 coroutine_info_hasher::equal (coroutine_info *lhs, coroutine_info *rhs)
140 {
141 return lhs->function_decl == rhs->function_decl;
142 }
143
144 bool
145 coroutine_info_hasher::equal (coroutine_info *lhs, const compare_type& rhs)
146 {
147 return lhs->function_decl == rhs;
148 }
149
150 /* Get the existing coroutine_info for FN_DECL, or insert a new one if the
151 entry does not yet exist. */
152
153 coroutine_info *
154 get_or_insert_coroutine_info (tree fn_decl)
155 {
156 gcc_checking_assert (coroutine_info_table != NULL);
157
158 coroutine_info **slot = coroutine_info_table->find_slot_with_hash
159 (fn_decl, coroutine_info_hasher::hash (fn_decl), INSERT);
160
161 if (*slot == NULL)
162 {
163 *slot = new (ggc_cleared_alloc<coroutine_info> ()) coroutine_info ();
164 (*slot)->function_decl = fn_decl;
165 }
166
167 return *slot;
168 }
169
170 /* Get the existing coroutine_info for FN_DECL, fail if it doesn't exist. */
171
172 coroutine_info *
173 get_coroutine_info (tree fn_decl)
174 {
175 if (coroutine_info_table == NULL)
176 return NULL;
177
178 coroutine_info **slot = coroutine_info_table->find_slot_with_hash
179 (fn_decl, coroutine_info_hasher::hash (fn_decl), NO_INSERT);
180 if (slot)
181 return *slot;
182 return NULL;
183 }
184
185 /* We will lazily create all the identifiers that are used by coroutines
186 on the first attempt to lookup the traits. */
187
188 /* Identifiers that are used by all coroutines. */
189
190 static GTY(()) tree coro_traits_identifier;
191 static GTY(()) tree coro_handle_identifier;
192 static GTY(()) tree coro_promise_type_identifier;
193
194 /* Required promise method name identifiers. */
195
196 static GTY(()) tree coro_await_transform_identifier;
197 static GTY(()) tree coro_initial_suspend_identifier;
198 static GTY(()) tree coro_final_suspend_identifier;
199 static GTY(()) tree coro_return_void_identifier;
200 static GTY(()) tree coro_return_value_identifier;
201 static GTY(()) tree coro_yield_value_identifier;
202 static GTY(()) tree coro_resume_identifier;
203 static GTY(()) tree coro_address_identifier;
204 static GTY(()) tree coro_from_address_identifier;
205 static GTY(()) tree coro_get_return_object_identifier;
206 static GTY(()) tree coro_gro_on_allocation_fail_identifier;
207 static GTY(()) tree coro_unhandled_exception_identifier;
208
209 /* Awaitable methods. */
210
211 static GTY(()) tree coro_await_ready_identifier;
212 static GTY(()) tree coro_await_suspend_identifier;
213 static GTY(()) tree coro_await_resume_identifier;
214
215 /* Create the identifiers used by the coroutines library interfaces. */
216
217 static void
218 coro_init_identifiers ()
219 {
220 coro_traits_identifier = get_identifier ("coroutine_traits");
221 coro_handle_identifier = get_identifier ("coroutine_handle");
222 coro_promise_type_identifier = get_identifier ("promise_type");
223
224 coro_await_transform_identifier = get_identifier ("await_transform");
225 coro_initial_suspend_identifier = get_identifier ("initial_suspend");
226 coro_final_suspend_identifier = get_identifier ("final_suspend");
227 coro_return_void_identifier = get_identifier ("return_void");
228 coro_return_value_identifier = get_identifier ("return_value");
229 coro_yield_value_identifier = get_identifier ("yield_value");
230 coro_resume_identifier = get_identifier ("resume");
231 coro_address_identifier = get_identifier ("address");
232 coro_from_address_identifier = get_identifier ("from_address");
233 coro_get_return_object_identifier = get_identifier ("get_return_object");
234 coro_gro_on_allocation_fail_identifier =
235 get_identifier ("get_return_object_on_allocation_failure");
236 coro_unhandled_exception_identifier = get_identifier ("unhandled_exception");
237
238 coro_await_ready_identifier = get_identifier ("await_ready");
239 coro_await_suspend_identifier = get_identifier ("await_suspend");
240 coro_await_resume_identifier = get_identifier ("await_resume");
241 }
242
243 /* Trees we only need to set up once. */
244
245 static GTY(()) tree coro_traits_templ;
246 static GTY(()) tree coro_handle_templ;
247 static GTY(()) tree void_coro_handle_type;
248
249 /* ================= Parse, Semantics and Type checking ================= */
250
251 /* This initial set of routines are helper for the parsing and template
252 expansion phases.
253
254 At the completion of this, we will have completed trees for each of the
255 keywords, but making use of proxy variables for the self-handle and the
256 promise class instance. */
257
258 /* [coroutine.traits]
259 Lookup the coroutine_traits template decl. */
260
261 static tree
262 find_coro_traits_template_decl (location_t kw)
263 {
264 /* If we are missing fundamental information, such as the traits, (or the
265 declaration found is not a type template), then don't emit an error for
266 every keyword in a TU, just do it once. */
267 static bool traits_error_emitted = false;
268
269 tree traits_decl = lookup_qualified_name (std_node, coro_traits_identifier,
270 LOOK_want::NORMAL,
271 /*complain=*/!traits_error_emitted);
272 if (traits_decl == error_mark_node
273 || !DECL_TYPE_TEMPLATE_P (traits_decl))
274 {
275 if (!traits_error_emitted)
276 {
277 gcc_rich_location richloc (kw);
278 error_at (&richloc, "coroutines require a traits template; cannot"
279 " find %<%E::%E%>", std_node, coro_traits_identifier);
280 inform (&richloc, "perhaps %<#include <coroutine>%> is missing");
281 traits_error_emitted = true;
282 }
283 return NULL_TREE;
284 }
285 else
286 return traits_decl;
287 }
288
289 /* Instantiate Coroutine traits for the function signature. */
290
291 static tree
292 instantiate_coro_traits (tree fndecl, location_t kw)
293 {
294 /* [coroutine.traits.primary]
295 So now build up a type list for the template <typename _R, typename...>.
296 The types are the function's arg types and _R is the function return
297 type. */
298
299 tree functyp = TREE_TYPE (fndecl);
300 tree arg = DECL_ARGUMENTS (fndecl);
301 tree arg_node = TYPE_ARG_TYPES (functyp);
302 tree argtypes = make_tree_vec (list_length (arg_node)-1);
303 unsigned p = 0;
304
305 while (arg_node != NULL_TREE && !VOID_TYPE_P (TREE_VALUE (arg_node)))
306 {
307 if (is_this_parameter (arg)
308 || DECL_NAME (arg) == closure_identifier)
309 {
310 /* We pass a reference to *this to the param preview. */
311 tree ct = TREE_TYPE (TREE_TYPE (arg));
312 TREE_VEC_ELT (argtypes, p++) = cp_build_reference_type (ct, false);
313 }
314 else
315 TREE_VEC_ELT (argtypes, p++) = TREE_VALUE (arg_node);
316
317 arg_node = TREE_CHAIN (arg_node);
318 arg = DECL_CHAIN (arg);
319 }
320
321 tree argtypepack = cxx_make_type (TYPE_ARGUMENT_PACK);
322 SET_ARGUMENT_PACK_ARGS (argtypepack, argtypes);
323
324 tree targ = make_tree_vec (2);
325 TREE_VEC_ELT (targ, 0) = TREE_TYPE (functyp);
326 TREE_VEC_ELT (targ, 1) = argtypepack;
327
328 tree traits_class
329 = lookup_template_class (coro_traits_templ, targ,
330 /*in_decl=*/NULL_TREE, /*context=*/NULL_TREE,
331 /*entering scope=*/false, tf_warning_or_error);
332
333 if (traits_class == error_mark_node)
334 {
335 error_at (kw, "cannot instantiate %<coroutine traits%>");
336 return NULL_TREE;
337 }
338
339 return traits_class;
340 }
341
342 /* [coroutine.handle] */
343
344 static tree
345 find_coro_handle_template_decl (location_t kw)
346 {
347 /* As for the coroutine traits, this error is per TU, so only emit
348 it once. */
349 static bool coro_handle_error_emitted = false;
350 tree handle_decl = lookup_qualified_name (std_node, coro_handle_identifier,
351 LOOK_want::NORMAL,
352 !coro_handle_error_emitted);
353 if (handle_decl == error_mark_node
354 || !DECL_CLASS_TEMPLATE_P (handle_decl))
355 {
356 if (!coro_handle_error_emitted)
357 error_at (kw, "coroutines require a handle class template;"
358 " cannot find %<%E::%E%>", std_node, coro_handle_identifier);
359 coro_handle_error_emitted = true;
360 return NULL_TREE;
361 }
362 else
363 return handle_decl;
364 }
365
366 /* Instantiate the handle template for a given promise type. */
367
368 static tree
369 instantiate_coro_handle_for_promise_type (location_t kw, tree promise_type)
370 {
371 /* So now build up a type list for the template, one entry, the promise. */
372 tree targ = make_tree_vec (1);
373 TREE_VEC_ELT (targ, 0) = promise_type;
374 tree handle_type
375 = lookup_template_class (coro_handle_identifier, targ,
376 /* in_decl=*/NULL_TREE,
377 /* context=*/std_node,
378 /* entering scope=*/false, tf_warning_or_error);
379
380 if (handle_type == error_mark_node)
381 {
382 error_at (kw, "cannot instantiate a %<coroutine handle%> for"
383 " promise type %qT", promise_type);
384 return NULL_TREE;
385 }
386
387 return handle_type;
388 }
389
390 /* Look for the promise_type in the instantiated traits. */
391
392 static tree
393 find_promise_type (tree traits_class)
394 {
395 tree promise_type
396 = lookup_member (traits_class, coro_promise_type_identifier,
397 /* protect=*/1, /*want_type=*/true, tf_warning_or_error);
398
399 if (promise_type)
400 promise_type
401 = complete_type_or_else (TREE_TYPE (promise_type), promise_type);
402
403 /* NULL_TREE on fail. */
404 return promise_type;
405 }
406
407 static bool
408 coro_promise_type_found_p (tree fndecl, location_t loc)
409 {
410 gcc_assert (fndecl != NULL_TREE);
411
412 if (!coro_initialized)
413 {
414 /* Trees we only need to create once.
415 Set up the identifiers we will use. */
416 coro_init_identifiers ();
417
418 /* Coroutine traits template. */
419 coro_traits_templ = find_coro_traits_template_decl (loc);
420 if (coro_traits_templ == NULL_TREE)
421 return false;
422
423 /* coroutine_handle<> template. */
424 coro_handle_templ = find_coro_handle_template_decl (loc);
425 if (coro_handle_templ == NULL_TREE)
426 return false;
427
428 /* We can also instantiate the void coroutine_handle<> */
429 void_coro_handle_type =
430 instantiate_coro_handle_for_promise_type (loc, NULL_TREE);
431 if (void_coro_handle_type == NULL_TREE)
432 return false;
433
434 /* A table to hold the state, per coroutine decl. */
435 gcc_checking_assert (coroutine_info_table == NULL);
436 coroutine_info_table =
437 hash_table<coroutine_info_hasher>::create_ggc (11);
438
439 if (coroutine_info_table == NULL)
440 return false;
441
442 coro_initialized = true;
443 }
444
445 /* Save the coroutine data on the side to avoid the overhead on every
446 function decl tree. */
447
448 coroutine_info *coro_info = get_or_insert_coroutine_info (fndecl);
449 /* Without this, we cannot really proceed. */
450 gcc_checking_assert (coro_info);
451
452 /* If we don't already have a current promise type, try to look it up. */
453 if (coro_info->promise_type == NULL_TREE)
454 {
455 /* Get the coroutine traits template class instance for the function
456 signature we have - coroutine_traits <R, ...> */
457
458 tree templ_class = instantiate_coro_traits (fndecl, loc);
459
460 /* Find the promise type for that. */
461 coro_info->promise_type = find_promise_type (templ_class);
462
463 /* If we don't find it, punt on the rest. */
464 if (coro_info->promise_type == NULL_TREE)
465 {
466 if (!coro_info->coro_promise_error_emitted)
467 error_at (loc, "unable to find the promise type for"
468 " this coroutine");
469 coro_info->coro_promise_error_emitted = true;
470 return false;
471 }
472
473 /* Try to find the handle type for the promise. */
474 tree handle_type =
475 instantiate_coro_handle_for_promise_type (loc, coro_info->promise_type);
476 if (handle_type == NULL_TREE)
477 return false;
478
479 /* Complete this, we're going to use it. */
480 coro_info->handle_type = complete_type_or_else (handle_type, fndecl);
481
482 /* Diagnostic would be emitted by complete_type_or_else. */
483 if (!coro_info->handle_type)
484 return false;
485
486 /* Build a proxy for a handle to "self" as the param to
487 await_suspend() calls. */
488 coro_info->self_h_proxy
489 = build_lang_decl (VAR_DECL, get_identifier ("self_h.proxy"),
490 coro_info->handle_type);
491
492 /* Build a proxy for the promise so that we can perform lookups. */
493 coro_info->promise_proxy
494 = build_lang_decl (VAR_DECL, get_identifier ("promise.proxy"),
495 coro_info->promise_type);
496
497 /* Note where we first saw a coroutine keyword. */
498 coro_info->first_coro_keyword = loc;
499 }
500
501 return true;
502 }
503
504 /* These functions assumes that the caller has verified that the state for
505 the decl has been initialized, we try to minimize work here. */
506
507 static tree
508 get_coroutine_promise_type (tree decl)
509 {
510 if (coroutine_info *info = get_coroutine_info (decl))
511 return info->promise_type;
512
513 return NULL_TREE;
514 }
515
516 static tree
517 get_coroutine_handle_type (tree decl)
518 {
519 if (coroutine_info *info = get_coroutine_info (decl))
520 return info->handle_type;
521
522 return NULL_TREE;
523 }
524
525 static tree
526 get_coroutine_self_handle_proxy (tree decl)
527 {
528 if (coroutine_info *info = get_coroutine_info (decl))
529 return info->self_h_proxy;
530
531 return NULL_TREE;
532 }
533
534 static tree
535 get_coroutine_promise_proxy (tree decl)
536 {
537 if (coroutine_info *info = get_coroutine_info (decl))
538 return info->promise_proxy;
539
540 return NULL_TREE;
541 }
542
543 static tree
544 lookup_promise_method (tree fndecl, tree member_id, location_t loc,
545 bool musthave)
546 {
547 tree promise = get_coroutine_promise_type (fndecl);
548 tree pm_memb
549 = lookup_member (promise, member_id,
550 /*protect=*/1, /*want_type=*/0, tf_warning_or_error);
551 if (musthave && pm_memb == NULL_TREE)
552 {
553 error_at (loc, "no member named %qE in %qT", member_id, promise);
554 return error_mark_node;
555 }
556 return pm_memb;
557 }
558
559 /* Build an expression of the form p.method (args) where the p is a promise
560 object for the current coroutine.
561 OBJECT is the promise object instance to use, it may be NULL, in which case
562 we will use the promise_proxy instance for this coroutine.
563 ARGS may be NULL, for empty parm lists. */
564
565 static tree
566 coro_build_promise_expression (tree fn, tree promise_obj, tree member_id,
567 location_t loc, vec<tree, va_gc> **args,
568 bool musthave)
569 {
570 tree meth = lookup_promise_method (fn, member_id, loc, musthave);
571 if (meth == error_mark_node)
572 return error_mark_node;
573
574 /* If we don't find it, and it isn't needed, an empty return is OK. */
575 if (!meth)
576 return NULL_TREE;
577
578 tree promise
579 = promise_obj ? promise_obj
580 : get_coroutine_promise_proxy (current_function_decl);
581 tree expr;
582 if (BASELINK_P (meth))
583 expr = build_new_method_call (promise, meth, args, NULL_TREE,
584 LOOKUP_NORMAL, NULL, tf_warning_or_error);
585 else
586 {
587 expr = build_class_member_access_expr (promise, meth, NULL_TREE,
588 true, tf_warning_or_error);
589 vec<tree, va_gc> *real_args;
590 if (!args)
591 real_args = make_tree_vector ();
592 else
593 real_args = *args;
594 expr = build_op_call (expr, &real_args, tf_warning_or_error);
595 }
596 return expr;
597 }
598
599 /* Caching get for the expression p.return_void (). */
600
601 static tree
602 get_coroutine_return_void_expr (tree decl, location_t loc, bool musthave)
603 {
604 if (coroutine_info *info = get_coroutine_info (decl))
605 {
606 /* If we don't have it try to build it. */
607 if (!info->return_void)
608 info->return_void
609 = coro_build_promise_expression (current_function_decl, NULL,
610 coro_return_void_identifier,
611 loc, NULL, musthave);
612 /* Don't return an error if it's an optional call. */
613 if (!musthave && info->return_void == error_mark_node)
614 return NULL_TREE;
615 return info->return_void;
616 }
617 return musthave ? error_mark_node : NULL_TREE;
618 }
619
620 /* Lookup an Awaitable member, which should be await_ready, await_suspend
621 or await_resume. */
622
623 static tree
624 lookup_awaitable_member (tree await_type, tree member_id, location_t loc)
625 {
626 tree aw_memb
627 = lookup_member (await_type, member_id,
628 /*protect=*/1, /*want_type=*/0, tf_warning_or_error);
629 if (aw_memb == NULL_TREE)
630 {
631 error_at (loc, "no member named %qE in %qT", member_id, await_type);
632 return error_mark_node;
633 }
634 return aw_memb;
635 }
636
637 /* Here we check the constraints that are common to all keywords (since the
638 presence of a coroutine keyword makes the function into a coroutine). */
639
640 static bool
641 coro_common_keyword_context_valid_p (tree fndecl, location_t kw_loc,
642 const char *kw_name)
643 {
644 if (fndecl == NULL_TREE)
645 {
646 error_at (kw_loc, "%qs cannot be used outside a function", kw_name);
647 return false;
648 }
649
650 /* This is arranged in order of prohibitions in the std. */
651 if (DECL_MAIN_P (fndecl))
652 {
653 /* [basic.start.main] 3. The function main shall not be a coroutine. */
654 error_at (kw_loc, "%qs cannot be used in the %<main%> function",
655 kw_name);
656 return false;
657 }
658
659 if (DECL_DECLARED_CONSTEXPR_P (fndecl))
660 {
661 /* [dcl.constexpr] 3.3 it shall not be a coroutine. */
662 error_at (kw_loc, "%qs cannot be used in a %<constexpr%> function",
663 kw_name);
664 cp_function_chain->invalid_constexpr = true;
665 return false;
666 }
667
668 if (FNDECL_USED_AUTO (fndecl))
669 {
670 /* [dcl.spec.auto] 15. A function declared with a return type that uses
671 a placeholder type shall not be a coroutine. */
672 error_at (kw_loc,
673 "%qs cannot be used in a function with a deduced return type",
674 kw_name);
675 return false;
676 }
677
678 if (varargs_function_p (fndecl))
679 {
680 /* [dcl.fct.def.coroutine] The parameter-declaration-clause of the
681 coroutine shall not terminate with an ellipsis that is not part
682 of a parameter-declaration. */
683 error_at (kw_loc,
684 "%qs cannot be used in a varargs function", kw_name);
685 return false;
686 }
687
688 if (DECL_CONSTRUCTOR_P (fndecl))
689 {
690 /* [class.ctor] 7. a constructor shall not be a coroutine. */
691 error_at (kw_loc, "%qs cannot be used in a constructor", kw_name);
692 return false;
693 }
694
695 if (DECL_DESTRUCTOR_P (fndecl))
696 {
697 /* [class.dtor] 21. a destructor shall not be a coroutine. */
698 error_at (kw_loc, "%qs cannot be used in a destructor", kw_name);
699 return false;
700 }
701
702 return true;
703 }
704
705 /* Here we check the constraints that are not per keyword. */
706
707 static bool
708 coro_function_valid_p (tree fndecl)
709 {
710 location_t f_loc = DECL_SOURCE_LOCATION (fndecl);
711
712 /* For cases where fundamental information cannot be found, e.g. the
713 coroutine traits are missing, we need to punt early. */
714 if (!coro_promise_type_found_p (fndecl, f_loc))
715 return false;
716
717 /* Since we think the function is a coroutine, that implies we parsed
718 a keyword that triggered this. Keywords check promise validity for
719 their context and thus the promise type should be known at this point. */
720 if (get_coroutine_handle_type (fndecl) == NULL_TREE
721 || get_coroutine_promise_type (fndecl) == NULL_TREE)
722 return false;
723
724 if (current_function_returns_value || current_function_returns_null)
725 {
726 /* TODO: record or extract positions of returns (and the first coro
727 keyword) so that we can add notes to the diagnostic about where
728 the bad keyword is and what made the function into a coro. */
729 error_at (f_loc, "a %<return%> statement is not allowed in coroutine;"
730 " did you mean %<co_return%>?");
731 return false;
732 }
733
734 return true;
735 }
736
737 enum suspend_point_kind {
738 CO_AWAIT_SUSPEND_POINT = 0,
739 CO_YIELD_SUSPEND_POINT,
740 INITIAL_SUSPEND_POINT,
741 FINAL_SUSPEND_POINT
742 };
743
744 /* Helper function to build a named variable for the temps we use for each
745 await point. The root of the name is determined by SUSPEND_KIND, and
746 the variable is of type V_TYPE. The awaitable number is reset each time
747 we encounter a final suspend. */
748
749 static tree
750 get_awaitable_var (suspend_point_kind suspend_kind, tree v_type)
751 {
752 static int awn = 0;
753 char *buf;
754 switch (suspend_kind)
755 {
756 default: buf = xasprintf ("Aw%d", awn++); break;
757 case CO_YIELD_SUSPEND_POINT: buf = xasprintf ("Yd%d", awn++); break;
758 case INITIAL_SUSPEND_POINT: buf = xasprintf ("Is"); break;
759 case FINAL_SUSPEND_POINT: buf = xasprintf ("Fs"); awn = 0; break;
760 }
761 tree ret = get_identifier (buf);
762 free (buf);
763 ret = build_lang_decl (VAR_DECL, ret, v_type);
764 DECL_ARTIFICIAL (ret) = true;
765 return ret;
766 }
767
768 /* This performs [expr.await] bullet 3.3 and validates the interface obtained.
769 It is also used to build the initial and final suspend points.
770
771 'a', 'o' and 'e' are used as per the description in the section noted.
772
773 A, the original yield/await expr, is found at source location LOC.
774
775 We will be constructing a CO_AWAIT_EXPR for a suspend point of one of
776 the four suspend_point_kind kinds. This is indicated by SUSPEND_KIND. */
777
778 static tree
779 build_co_await (location_t loc, tree a, suspend_point_kind suspend_kind)
780 {
781 /* Try and overload of operator co_await, .... */
782 tree o;
783 if (MAYBE_CLASS_TYPE_P (TREE_TYPE (a)))
784 {
785 o = build_new_op (loc, CO_AWAIT_EXPR, LOOKUP_NORMAL, a, NULL_TREE,
786 NULL_TREE, NULL, tf_warning_or_error);
787 /* If no viable functions are found, o is a. */
788 if (!o || o == error_mark_node)
789 o = a;
790 }
791 else
792 o = a; /* This is most likely about to fail anyway. */
793
794 tree o_type = TREE_TYPE (o);
795 if (o_type && !VOID_TYPE_P (o_type))
796 o_type = complete_type_or_else (o_type, o);
797
798 if (!o_type)
799 return error_mark_node;
800
801 if (TREE_CODE (o_type) != RECORD_TYPE)
802 {
803 error_at (loc, "awaitable type %qT is not a structure",
804 o_type);
805 return error_mark_node;
806 }
807
808 /* Check for required awaitable members and their types. */
809 tree awrd_meth
810 = lookup_awaitable_member (o_type, coro_await_ready_identifier, loc);
811 if (!awrd_meth || awrd_meth == error_mark_node)
812 return error_mark_node;
813 tree awsp_meth
814 = lookup_awaitable_member (o_type, coro_await_suspend_identifier, loc);
815 if (!awsp_meth || awsp_meth == error_mark_node)
816 return error_mark_node;
817
818 /* The type of the co_await is the return type of the awaitable's
819 await_resume, so we need to look that up. */
820 tree awrs_meth
821 = lookup_awaitable_member (o_type, coro_await_resume_identifier, loc);
822 if (!awrs_meth || awrs_meth == error_mark_node)
823 return error_mark_node;
824
825 /* To complete the lookups, we need an instance of 'e' which is built from
826 'o' according to [expr.await] 3.4.
827
828 If we need to materialize this as a temporary, then that will have to be
829 'promoted' to a coroutine frame var. However, if the awaitable is a
830 user variable, parameter or comes from a scope outside this function,
831 then we must use it directly - or we will see unnecessary copies.
832
833 If o is a variable, find the underlying var. */
834 tree e_proxy = STRIP_NOPS (o);
835 if (INDIRECT_REF_P (e_proxy))
836 e_proxy = TREE_OPERAND (e_proxy, 0);
837 while (TREE_CODE (e_proxy) == COMPONENT_REF)
838 {
839 e_proxy = TREE_OPERAND (e_proxy, 0);
840 if (INDIRECT_REF_P (e_proxy))
841 e_proxy = TREE_OPERAND (e_proxy, 0);
842 if (TREE_CODE (e_proxy) == CALL_EXPR)
843 {
844 /* We could have operator-> here too. */
845 tree op = TREE_OPERAND (CALL_EXPR_FN (e_proxy), 0);
846 if (DECL_OVERLOADED_OPERATOR_P (op)
847 && DECL_OVERLOADED_OPERATOR_IS (op, COMPONENT_REF))
848 {
849 e_proxy = CALL_EXPR_ARG (e_proxy, 0);
850 STRIP_NOPS (e_proxy);
851 gcc_checking_assert (TREE_CODE (e_proxy) == ADDR_EXPR);
852 e_proxy = TREE_OPERAND (e_proxy, 0);
853 }
854 }
855 STRIP_NOPS (e_proxy);
856 }
857
858 /* Only build a temporary if we need it. */
859 if (TREE_CODE (e_proxy) == PARM_DECL
860 || (VAR_P (e_proxy) && !is_local_temp (e_proxy)))
861 {
862 e_proxy = o;
863 o = NULL_TREE; /* The var is already present. */
864 }
865 else if (CLASS_TYPE_P (o_type) || TYPE_NEEDS_CONSTRUCTING (o_type))
866 {
867 e_proxy = get_awaitable_var (suspend_kind, o_type);
868 releasing_vec arg (make_tree_vector_single (rvalue (o)));
869 o = build_special_member_call (e_proxy, complete_ctor_identifier,
870 &arg, o_type, LOOKUP_NORMAL,
871 tf_warning_or_error);
872 }
873 else
874 {
875 e_proxy = get_awaitable_var (suspend_kind, o_type);
876 o = build2 (INIT_EXPR, o_type, e_proxy, rvalue (o));
877 }
878
879 /* I suppose we could check that this is contextually convertible to bool. */
880 tree awrd_func = NULL_TREE;
881 tree awrd_call
882 = build_new_method_call (e_proxy, awrd_meth, NULL, NULL_TREE, LOOKUP_NORMAL,
883 &awrd_func, tf_warning_or_error);
884
885 if (!awrd_func || !awrd_call || awrd_call == error_mark_node)
886 return error_mark_node;
887
888 /* The suspend method may return one of three types:
889 1. void (no special action needed).
890 2. bool (if true, we don't need to suspend).
891 3. a coroutine handle, we execute the handle.resume() call. */
892 tree awsp_func = NULL_TREE;
893 tree h_proxy = get_coroutine_self_handle_proxy (current_function_decl);
894 vec<tree, va_gc> *args = make_tree_vector_single (h_proxy);
895 tree awsp_call
896 = build_new_method_call (e_proxy, awsp_meth, &args, NULL_TREE,
897 LOOKUP_NORMAL, &awsp_func, tf_warning_or_error);
898
899 release_tree_vector (args);
900 if (!awsp_func || !awsp_call || awsp_call == error_mark_node)
901 return error_mark_node;
902
903 bool ok = false;
904 tree susp_return_type = TREE_TYPE (TREE_TYPE (awsp_func));
905 if (same_type_p (susp_return_type, void_type_node))
906 ok = true;
907 else if (same_type_p (susp_return_type, boolean_type_node))
908 ok = true;
909 else if (TREE_CODE (susp_return_type) == RECORD_TYPE
910 && CLASS_TYPE_P (susp_return_type))
911 {
912 tree tt = CLASSTYPE_TI_TEMPLATE (susp_return_type);
913 if (tt == coro_handle_templ)
914 ok = true;
915 }
916
917 if (!ok)
918 {
919 error_at (loc, "%<await_suspend%> must return %<void%>, %<bool%> or"
920 " a coroutine handle");
921 return error_mark_node;
922 }
923
924 /* Finally, the type of e.await_resume() is the co_await's type. */
925 tree awrs_func = NULL_TREE;
926 tree awrs_call
927 = build_new_method_call (e_proxy, awrs_meth, NULL, NULL_TREE, LOOKUP_NORMAL,
928 &awrs_func, tf_warning_or_error);
929
930 if (!awrs_func || !awrs_call || awrs_call == error_mark_node)
931 return error_mark_node;
932
933 /* We now have three call expressions, in terms of the promise, handle and
934 'e' proxies. Save them in the await expression for later expansion. */
935
936 tree awaiter_calls = make_tree_vec (3);
937 TREE_VEC_ELT (awaiter_calls, 0) = awrd_call; /* await_ready(). */
938 TREE_VEC_ELT (awaiter_calls, 1) = awsp_call; /* await_suspend(). */
939 tree te = NULL_TREE;
940 if (TREE_CODE (awrs_call) == TARGET_EXPR)
941 {
942 te = awrs_call;
943 awrs_call = TREE_OPERAND (awrs_call, 1);
944 }
945 TREE_VEC_ELT (awaiter_calls, 2) = awrs_call; /* await_resume(). */
946
947 tree await_expr = build5_loc (loc, CO_AWAIT_EXPR,
948 TREE_TYPE (TREE_TYPE (awrs_func)),
949 a, e_proxy, o, awaiter_calls,
950 build_int_cst (integer_type_node,
951 (int) suspend_kind));
952 if (te)
953 {
954 TREE_OPERAND (te, 1) = await_expr;
955 await_expr = te;
956 }
957 tree t = convert_from_reference (await_expr);
958 return t;
959 }
960
961 tree
962 finish_co_await_expr (location_t kw, tree expr)
963 {
964 if (!expr || error_operand_p (expr))
965 return error_mark_node;
966
967 if (!coro_common_keyword_context_valid_p (current_function_decl, kw,
968 "co_await"))
969 return error_mark_node;
970
971 /* The current function has now become a coroutine, if it wasn't already. */
972 DECL_COROUTINE_P (current_function_decl) = 1;
973
974 /* This function will appear to have no return statement, even if it
975 is declared to return non-void (most likely). This is correct - we
976 synthesize the return for the ramp in the compiler. So suppress any
977 extraneous warnings during substitution. */
978 TREE_NO_WARNING (current_function_decl) = true;
979
980 /* If we don't know the promise type, we can't proceed, build the
981 co_await with the expression unchanged. */
982 tree functype = TREE_TYPE (current_function_decl);
983 if (dependent_type_p (functype) || type_dependent_expression_p (expr))
984 return build5_loc (kw, CO_AWAIT_EXPR, unknown_type_node, expr,
985 NULL_TREE, NULL_TREE, NULL_TREE, integer_zero_node);
986
987 /* We must be able to look up the "await_transform" method in the scope of
988 the promise type, and obtain its return type. */
989 if (!coro_promise_type_found_p (current_function_decl, kw))
990 return error_mark_node;
991
992 /* [expr.await] 3.2
993 The incoming cast expression might be transformed by a promise
994 'await_transform()'. */
995 tree at_meth
996 = lookup_promise_method (current_function_decl,
997 coro_await_transform_identifier, kw,
998 /*musthave=*/false);
999 if (at_meth == error_mark_node)
1000 return error_mark_node;
1001
1002 tree a = expr;
1003 if (at_meth)
1004 {
1005 /* try to build a = p.await_transform (e). */
1006 vec<tree, va_gc> *args = make_tree_vector_single (expr);
1007 a = build_new_method_call (get_coroutine_promise_proxy (
1008 current_function_decl),
1009 at_meth, &args, NULL_TREE, LOOKUP_NORMAL,
1010 NULL, tf_warning_or_error);
1011
1012 /* As I read the section.
1013 We saw an await_transform method, so it's mandatory that we replace
1014 expr with p.await_transform (expr), therefore if the method call fails
1015 (presumably, we don't have suitable arguments) then this part of the
1016 process fails. */
1017 if (a == error_mark_node)
1018 return error_mark_node;
1019 }
1020
1021 /* Now we want to build co_await a. */
1022 tree op = build_co_await (kw, a, CO_AWAIT_SUSPEND_POINT);
1023 if (op != error_mark_node)
1024 {
1025 TREE_SIDE_EFFECTS (op) = 1;
1026 SET_EXPR_LOCATION (op, kw);
1027 }
1028
1029 return op;
1030 }
1031
1032 /* Take the EXPR given and attempt to build:
1033 co_await p.yield_value (expr);
1034 per [expr.yield] para 1. */
1035
1036 tree
1037 finish_co_yield_expr (location_t kw, tree expr)
1038 {
1039 if (!expr || error_operand_p (expr))
1040 return error_mark_node;
1041
1042 /* Check the general requirements and simple syntax errors. */
1043 if (!coro_common_keyword_context_valid_p (current_function_decl, kw,
1044 "co_yield"))
1045 return error_mark_node;
1046
1047 /* The current function has now become a coroutine, if it wasn't already. */
1048 DECL_COROUTINE_P (current_function_decl) = 1;
1049
1050 /* This function will appear to have no return statement, even if it
1051 is declared to return non-void (most likely). This is correct - we
1052 synthesize the return for the ramp in the compiler. So suppress any
1053 extraneous warnings during substitution. */
1054 TREE_NO_WARNING (current_function_decl) = true;
1055
1056 /* If we don't know the promise type, we can't proceed, build the
1057 co_await with the expression unchanged. */
1058 tree functype = TREE_TYPE (current_function_decl);
1059 if (dependent_type_p (functype) || type_dependent_expression_p (expr))
1060 return build2_loc (kw, CO_YIELD_EXPR, unknown_type_node, expr, NULL_TREE);
1061
1062 if (!coro_promise_type_found_p (current_function_decl, kw))
1063 /* We must be able to look up the "yield_value" method in the scope of
1064 the promise type, and obtain its return type. */
1065 return error_mark_node;
1066
1067 /* [expr.yield] / 1
1068 Let e be the operand of the yield-expression and p be an lvalue naming
1069 the promise object of the enclosing coroutine, then the yield-expression
1070 is equivalent to the expression co_await p.yield_value(e).
1071 build p.yield_value(e): */
1072 vec<tree, va_gc> *args = make_tree_vector_single (expr);
1073 tree yield_call
1074 = coro_build_promise_expression (current_function_decl, NULL,
1075 coro_yield_value_identifier, kw,
1076 &args, /*musthave=*/true);
1077 release_tree_vector (args);
1078
1079 /* Now build co_await p.yield_value (e).
1080 Noting that for co_yield, there is no evaluation of any potential
1081 promise transform_await(), so we call build_co_await directly. */
1082
1083 tree op = build_co_await (kw, yield_call, CO_YIELD_SUSPEND_POINT);
1084 if (op != error_mark_node)
1085 {
1086 if (REFERENCE_REF_P (op))
1087 op = TREE_OPERAND (op, 0);
1088 /* If the await expression is wrapped in a TARGET_EXPR, then transfer
1089 that wrapper to the CO_YIELD_EXPR, since this is just a proxy for
1090 its contained await. Otherwise, just build the CO_YIELD_EXPR. */
1091 if (TREE_CODE (op) == TARGET_EXPR)
1092 {
1093 tree t = TREE_OPERAND (op, 1);
1094 t = build2_loc (kw, CO_YIELD_EXPR, TREE_TYPE (t), expr, t);
1095 TREE_OPERAND (op, 1) = t;
1096 }
1097 else
1098 op = build2_loc (kw, CO_YIELD_EXPR, TREE_TYPE (op), expr, op);
1099 TREE_SIDE_EFFECTS (op) = 1;
1100 op = convert_from_reference (op);
1101 }
1102
1103 return op;
1104 }
1105
1106 /* Check and build a co_return statement.
1107 First that it's valid to have a co_return keyword here.
1108 If it is, then check and build the p.return_{void(),value(expr)}.
1109 These are built against a proxy for the promise, which will be filled
1110 in with the actual frame version when the function is transformed. */
1111
1112 tree
1113 finish_co_return_stmt (location_t kw, tree expr)
1114 {
1115 if (expr)
1116 STRIP_ANY_LOCATION_WRAPPER (expr);
1117
1118 if (error_operand_p (expr))
1119 return error_mark_node;
1120
1121 /* If it fails the following test, the function is not permitted to be a
1122 coroutine, so the co_return statement is erroneous. */
1123 if (!coro_common_keyword_context_valid_p (current_function_decl, kw,
1124 "co_return"))
1125 return error_mark_node;
1126
1127 /* The current function has now become a coroutine, if it wasn't
1128 already. */
1129 DECL_COROUTINE_P (current_function_decl) = 1;
1130
1131 /* This function will appear to have no return statement, even if it
1132 is declared to return non-void (most likely). This is correct - we
1133 synthesize the return for the ramp in the compiler. So suppress any
1134 extraneous warnings during substitution. */
1135 TREE_NO_WARNING (current_function_decl) = true;
1136
1137 if (processing_template_decl
1138 && check_for_bare_parameter_packs (expr))
1139 return error_mark_node;
1140
1141 /* If we don't know the promise type, we can't proceed, build the
1142 co_return with the expression unchanged. */
1143 tree functype = TREE_TYPE (current_function_decl);
1144 if (dependent_type_p (functype) || type_dependent_expression_p (expr))
1145 {
1146 /* co_return expressions are always void type, regardless of the
1147 expression type. */
1148 expr = build2_loc (kw, CO_RETURN_EXPR, void_type_node,
1149 expr, NULL_TREE);
1150 expr = maybe_cleanup_point_expr_void (expr);
1151 return add_stmt (expr);
1152 }
1153
1154 if (!coro_promise_type_found_p (current_function_decl, kw))
1155 return error_mark_node;
1156
1157 /* Suppress -Wreturn-type for co_return, we need to check indirectly
1158 whether the promise type has a suitable return_void/return_value. */
1159 TREE_NO_WARNING (current_function_decl) = true;
1160
1161 if (!processing_template_decl && warn_sequence_point)
1162 verify_sequence_points (expr);
1163
1164 if (expr)
1165 {
1166 /* If we had an id-expression obfuscated by force_paren_expr, we need
1167 to undo it so we can try to treat it as an rvalue below. */
1168 expr = maybe_undo_parenthesized_ref (expr);
1169
1170 if (processing_template_decl)
1171 expr = build_non_dependent_expr (expr);
1172
1173 if (error_operand_p (expr))
1174 return error_mark_node;
1175 }
1176
1177 /* If the promise object doesn't have the correct return call then
1178 there's a mis-match between the co_return <expr> and this. */
1179 tree co_ret_call = error_mark_node;
1180 if (expr == NULL_TREE || VOID_TYPE_P (TREE_TYPE (expr)))
1181 co_ret_call
1182 = get_coroutine_return_void_expr (current_function_decl, kw, true);
1183 else
1184 {
1185 /* [class.copy.elision] / 3.
1186 An implicitly movable entity is a variable of automatic storage
1187 duration that is either a non-volatile object or an rvalue reference
1188 to a non-volatile object type. For such objects in the context of
1189 the co_return, the overload resolution should be carried out first
1190 treating the object as an rvalue, if that fails, then we fall back
1191 to regular overload resolution. */
1192
1193 tree arg = expr;
1194 if (tree moved = treat_lvalue_as_rvalue_p (expr, /*return*/true))
1195 arg = moved;
1196
1197 releasing_vec args = make_tree_vector_single (arg);
1198 co_ret_call
1199 = coro_build_promise_expression (current_function_decl, NULL,
1200 coro_return_value_identifier, kw,
1201 &args, /*musthave=*/true);
1202 }
1203
1204 /* Makes no sense for a co-routine really. */
1205 if (TREE_THIS_VOLATILE (current_function_decl))
1206 warning_at (kw, 0,
1207 "function declared %<noreturn%> has a"
1208 " %<co_return%> statement");
1209
1210 expr = build2_loc (kw, CO_RETURN_EXPR, void_type_node, expr, co_ret_call);
1211 expr = maybe_cleanup_point_expr_void (expr);
1212 return add_stmt (expr);
1213 }
1214
1215 /* We need to validate the arguments to __builtin_coro_promise, since the
1216 second two must be constant, and the builtins machinery doesn't seem to
1217 deal with that properly. */
1218
1219 tree
1220 coro_validate_builtin_call (tree call, tsubst_flags_t)
1221 {
1222 tree fn = TREE_OPERAND (CALL_EXPR_FN (call), 0);
1223
1224 gcc_checking_assert (DECL_BUILT_IN_CLASS (fn) == BUILT_IN_NORMAL);
1225 switch (DECL_FUNCTION_CODE (fn))
1226 {
1227 default:
1228 return call;
1229
1230 case BUILT_IN_CORO_PROMISE:
1231 {
1232 /* Argument 0 is already checked by the normal built-in machinery
1233 Argument 1 must be a constant of size type. It probably makes
1234 little sense if it's not a power of 2, but that isn't specified
1235 formally. */
1236 tree arg = CALL_EXPR_ARG (call, 1);
1237 location_t loc = EXPR_LOCATION (arg);
1238
1239 /* We expect alignof expressions in templates. */
1240 if (TREE_CODE (arg) == NON_DEPENDENT_EXPR
1241 && TREE_CODE (TREE_OPERAND (arg, 0)) == ALIGNOF_EXPR)
1242 ;
1243 else if (!TREE_CONSTANT (arg))
1244 {
1245 error_at (loc, "the align argument to %<__builtin_coro_promise%>"
1246 " must be a constant");
1247 return error_mark_node;
1248 }
1249 /* Argument 2 is the direction - to / from handle address to promise
1250 address. */
1251 arg = CALL_EXPR_ARG (call, 2);
1252 loc = EXPR_LOCATION (arg);
1253 if (!TREE_CONSTANT (arg))
1254 {
1255 error_at (loc, "the direction argument to"
1256 " %<__builtin_coro_promise%> must be a constant");
1257 return error_mark_node;
1258 }
1259 return call;
1260 break;
1261 }
1262 }
1263 }
1264
1265 /* ================= Morph and Expand. =================
1266
1267 The entry point here is morph_fn_to_coro () which is called from
1268 finish_function () when we have completed any template expansion.
1269
1270 This is preceded by helper functions that implement the phases below.
1271
1272 The process proceeds in four phases.
1273
1274 A Initial framing.
1275 The user's function body is wrapped in the initial and final suspend
1276 points and we begin building the coroutine frame.
1277 We build empty decls for the actor and destroyer functions at this
1278 time too.
1279 When exceptions are enabled, the user's function body will also be
1280 wrapped in a try-catch block with the catch invoking the promise
1281 class 'unhandled_exception' method.
1282
1283 B Analysis.
1284 The user's function body is analyzed to determine the suspend points,
1285 if any, and to capture local variables that might persist across such
1286 suspensions. In most cases, it is not necessary to capture compiler
1287 temporaries, since the tree-lowering nests the suspensions correctly.
1288 However, in the case of a captured reference, there is a lifetime
1289 extension to the end of the full expression - which can mean across a
1290 suspend point in which case it must be promoted to a frame variable.
1291
1292 At the conclusion of analysis, we have a conservative frame layout and
1293 maps of the local variables to their frame entry points.
1294
1295 C Build the ramp function.
1296 Carry out the allocation for the coroutine frame (NOTE; the actual size
1297 computation is deferred until late in the middle end to allow for future
1298 optimizations that will be allowed to elide unused frame entries).
1299 We build the return object.
1300
1301 D Build and expand the actor and destroyer function bodies.
1302 The destroyer is a trivial shim that sets a bit to indicate that the
1303 destroy dispatcher should be used and then calls into the actor.
1304
1305 The actor function is the implementation of the user's state machine.
1306 The current suspend point is noted in an index.
1307 Each suspend point is encoded as a pair of internal functions, one in
1308 the relevant dispatcher, and one representing the suspend point.
1309
1310 During this process, the user's local variables and the proxies for the
1311 self-handle and the promise class instance are re-written to their
1312 coroutine frame equivalents.
1313
1314 The complete bodies for the ramp, actor and destroy function are passed
1315 back to finish_function for folding and gimplification. */
1316
1317 /* Helpers to build EXPR_STMT and void-cast EXPR_STMT, common ops. */
1318
1319 static tree
1320 coro_build_expr_stmt (tree expr, location_t loc)
1321 {
1322 return maybe_cleanup_point_expr_void (build_stmt (loc, EXPR_STMT, expr));
1323 }
1324
1325 static tree
1326 coro_build_cvt_void_expr_stmt (tree expr, location_t loc)
1327 {
1328 tree t = build1 (CONVERT_EXPR, void_type_node, expr);
1329 return coro_build_expr_stmt (t, loc);
1330 }
1331
1332 /* Helpers for label creation:
1333 1. Create a named label in the specified context. */
1334
1335 static tree
1336 create_anon_label_with_ctx (location_t loc, tree ctx)
1337 {
1338 tree lab = build_decl (loc, LABEL_DECL, NULL_TREE, void_type_node);
1339
1340 DECL_CONTEXT (lab) = ctx;
1341 DECL_ARTIFICIAL (lab) = true;
1342 DECL_IGNORED_P (lab) = true;
1343 TREE_USED (lab) = true;
1344 return lab;
1345 }
1346
1347 /* 2. Create a named label in the specified context. */
1348
1349 static tree
1350 create_named_label_with_ctx (location_t loc, const char *name, tree ctx)
1351 {
1352 tree lab_id = get_identifier (name);
1353 tree lab = define_label (loc, lab_id);
1354 DECL_CONTEXT (lab) = ctx;
1355 DECL_ARTIFICIAL (lab) = true;
1356 TREE_USED (lab) = true;
1357 return lab;
1358 }
1359
1360 struct proxy_replace
1361 {
1362 tree from, to;
1363 };
1364
1365 static tree
1366 replace_proxy (tree *here, int *do_subtree, void *d)
1367 {
1368 proxy_replace *data = (proxy_replace *) d;
1369
1370 if (*here == data->from)
1371 {
1372 *here = data->to;
1373 *do_subtree = 0;
1374 }
1375 else
1376 *do_subtree = 1;
1377 return NULL_TREE;
1378 }
1379
1380 /* Support for expansion of co_await statements. */
1381
1382 struct coro_aw_data
1383 {
1384 tree actor_fn; /* Decl for context. */
1385 tree coro_fp; /* Frame pointer var. */
1386 tree resume_idx; /* This is the index var in the frame. */
1387 tree i_a_r_c; /* initial suspend await_resume() was called if true. */
1388 tree self_h; /* This is a handle to the current coro (frame var). */
1389 tree cleanup; /* This is where to go once we complete local destroy. */
1390 tree cororet; /* This is where to go if we suspend. */
1391 tree corocont; /* This is where to go if we continue. */
1392 tree conthand; /* This is the handle for a continuation. */
1393 unsigned index; /* This is our current resume index. */
1394 };
1395
1396 /* Lightweight search for the first await expression in tree-walk order.
1397 returns:
1398 The first await expression found in STMT.
1399 NULL_TREE if there are none.
1400 So can be used to determine if the statement needs to be processed for
1401 awaits. */
1402
1403 static tree
1404 co_await_find_in_subtree (tree *stmt, int *, void *d)
1405 {
1406 tree **p = (tree **) d;
1407 if (TREE_CODE (*stmt) == CO_AWAIT_EXPR)
1408 {
1409 *p = stmt;
1410 return *stmt;
1411 }
1412 return NULL_TREE;
1413 }
1414
1415 /* Starting with a statement:
1416
1417 stmt => some tree containing one or more await expressions.
1418
1419 We replace the statement with:
1420 <STATEMENT_LIST> {
1421 initialize awaitable
1422 if (!ready)
1423 {
1424 suspension context.
1425 }
1426 resume:
1427 revised statement with one await expression rewritten to its
1428 await_resume() return value.
1429 }
1430
1431 We then recurse into the initializer and the revised statement
1432 repeating this replacement until there are no more await expressions
1433 in either. */
1434
1435 static tree *
1436 expand_one_await_expression (tree *stmt, tree *await_expr, void *d)
1437 {
1438 coro_aw_data *data = (coro_aw_data *) d;
1439
1440 tree saved_statement = *stmt;
1441 tree saved_co_await = *await_expr;
1442
1443 tree actor = data->actor_fn;
1444 location_t loc = EXPR_LOCATION (*stmt);
1445 tree var = TREE_OPERAND (saved_co_await, 1); /* frame slot. */
1446 tree expr = TREE_OPERAND (saved_co_await, 2); /* initializer. */
1447 tree awaiter_calls = TREE_OPERAND (saved_co_await, 3);
1448
1449 tree source = TREE_OPERAND (saved_co_await, 4);
1450 bool is_final = (source
1451 && TREE_INT_CST_LOW (source) == (int) FINAL_SUSPEND_POINT);
1452 bool needs_dtor = TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (var));
1453 int resume_point = data->index;
1454 size_t bufsize = sizeof ("destroy.") + 10;
1455 char *buf = (char *) alloca (bufsize);
1456 snprintf (buf, bufsize, "destroy.%d", resume_point);
1457 tree destroy_label = create_named_label_with_ctx (loc, buf, actor);
1458 snprintf (buf, bufsize, "resume.%d", resume_point);
1459 tree resume_label = create_named_label_with_ctx (loc, buf, actor);
1460 tree empty_list = build_empty_stmt (loc);
1461
1462 tree await_type = TREE_TYPE (var);
1463 tree stmt_list = NULL;
1464 tree r;
1465 tree *await_init = NULL;
1466
1467 if (!expr)
1468 needs_dtor = false; /* No need, the var's lifetime is managed elsewhere. */
1469 else
1470 {
1471 r = coro_build_cvt_void_expr_stmt (expr, loc);
1472 append_to_statement_list_force (r, &stmt_list);
1473 /* We have an initializer, which might itself contain await exprs. */
1474 await_init = tsi_stmt_ptr (tsi_last (stmt_list));
1475 }
1476
1477 /* Use the await_ready() call to test if we need to suspend. */
1478 tree ready_cond = TREE_VEC_ELT (awaiter_calls, 0); /* await_ready(). */
1479 ready_cond = build1_loc (loc, TRUTH_NOT_EXPR, boolean_type_node, ready_cond);
1480 ready_cond
1481 = build1_loc (loc, CLEANUP_POINT_EXPR, boolean_type_node, ready_cond);
1482
1483 tree body_list = NULL;
1484 tree susp_idx = build_int_cst (short_unsigned_type_node, data->index);
1485 r = build2_loc (loc, MODIFY_EXPR, short_unsigned_type_node, data->resume_idx,
1486 susp_idx);
1487 r = coro_build_cvt_void_expr_stmt (r, loc);
1488 append_to_statement_list (r, &body_list);
1489
1490 /* Find out what we have to do with the awaiter's suspend method.
1491 [expr.await]
1492 (5.1) If the result of await-ready is false, the coroutine is considered
1493 suspended. Then:
1494 (5.1.1) If the type of await-suspend is std::coroutine_handle<Z>,
1495 await-suspend.resume() is evaluated.
1496 (5.1.2) if the type of await-suspend is bool, await-suspend is evaluated,
1497 and the coroutine is resumed if the result is false.
1498 (5.1.3) Otherwise, await-suspend is evaluated. */
1499
1500 tree suspend = TREE_VEC_ELT (awaiter_calls, 1); /* await_suspend(). */
1501 tree susp_type = TREE_TYPE (suspend);
1502
1503 bool is_cont = false;
1504 /* NOTE: final suspend can't resume; the "resume" label in that case
1505 corresponds to implicit destruction. */
1506 if (VOID_TYPE_P (susp_type))
1507 {
1508 /* We just call await_suspend() and hit the yield. */
1509 suspend = coro_build_cvt_void_expr_stmt (suspend, loc);
1510 append_to_statement_list (suspend, &body_list);
1511 }
1512 else if (TREE_CODE (susp_type) == BOOLEAN_TYPE)
1513 {
1514 /* Boolean return, continue if the call returns false. */
1515 suspend = build1_loc (loc, TRUTH_NOT_EXPR, boolean_type_node, suspend);
1516 suspend
1517 = build1_loc (loc, CLEANUP_POINT_EXPR, boolean_type_node, suspend);
1518 tree go_on = build1_loc (loc, GOTO_EXPR, void_type_node, resume_label);
1519 r = build3_loc (loc, COND_EXPR, void_type_node, suspend, go_on,
1520 empty_list);
1521 append_to_statement_list (r, &body_list);
1522 }
1523 else
1524 {
1525 r = build1_loc (loc, CONVERT_EXPR, void_coro_handle_type, suspend);
1526 r = build2_loc (loc, INIT_EXPR, void_coro_handle_type, data->conthand, r);
1527 r = build1 (CONVERT_EXPR, void_type_node, r);
1528 append_to_statement_list (r, &body_list);
1529 is_cont = true;
1530 }
1531
1532 tree d_l = build_address (destroy_label);
1533 tree r_l = build_address (resume_label);
1534 tree susp = build_address (data->cororet);
1535 tree cont = build_address (data->corocont);
1536 tree final_susp = build_int_cst (integer_type_node, is_final ? 1 : 0);
1537
1538 susp_idx = build_int_cst (integer_type_node, data->index);
1539
1540 tree sw = begin_switch_stmt ();
1541 tree cond = build_decl (loc, VAR_DECL, NULL_TREE, integer_type_node);
1542 DECL_ARTIFICIAL (cond) = 1;
1543 DECL_IGNORED_P (cond) = 1;
1544 layout_decl (cond, 0);
1545
1546 r = build_call_expr_internal_loc (loc, IFN_CO_YIELD, integer_type_node, 5,
1547 susp_idx, final_susp, r_l, d_l,
1548 data->coro_fp);
1549 r = build2 (INIT_EXPR, integer_type_node, cond, r);
1550 finish_switch_cond (r, sw);
1551 r = build_case_label (build_int_cst (integer_type_node, 0), NULL_TREE,
1552 create_anon_label_with_ctx (loc, actor));
1553 add_stmt (r); /* case 0: */
1554 /* Implement the suspend, a scope exit without clean ups. */
1555 r = build_call_expr_internal_loc (loc, IFN_CO_SUSPN, void_type_node, 1,
1556 is_cont ? cont : susp);
1557 r = coro_build_cvt_void_expr_stmt (r, loc);
1558 add_stmt (r); /* goto ret; */
1559 r = build_case_label (build_int_cst (integer_type_node, 1), NULL_TREE,
1560 create_anon_label_with_ctx (loc, actor));
1561 add_stmt (r); /* case 1: */
1562 r = build1_loc (loc, GOTO_EXPR, void_type_node, resume_label);
1563 add_stmt (r); /* goto resume; */
1564 r = build_case_label (NULL_TREE, NULL_TREE,
1565 create_anon_label_with_ctx (loc, actor));
1566 add_stmt (r); /* default:; */
1567 r = build1_loc (loc, GOTO_EXPR, void_type_node, destroy_label);
1568 add_stmt (r); /* goto destroy; */
1569
1570 /* part of finish switch. */
1571 SWITCH_STMT_BODY (sw) = pop_stmt_list (SWITCH_STMT_BODY (sw));
1572 pop_switch ();
1573 tree scope = SWITCH_STMT_SCOPE (sw);
1574 SWITCH_STMT_SCOPE (sw) = NULL;
1575 r = do_poplevel (scope);
1576 append_to_statement_list (r, &body_list);
1577
1578 destroy_label = build_stmt (loc, LABEL_EXPR, destroy_label);
1579 append_to_statement_list (destroy_label, &body_list);
1580 if (needs_dtor)
1581 {
1582 tree dtor = build_special_member_call (var, complete_dtor_identifier,
1583 NULL, await_type, LOOKUP_NORMAL,
1584 tf_warning_or_error);
1585 append_to_statement_list (dtor, &body_list);
1586 }
1587 r = build1_loc (loc, GOTO_EXPR, void_type_node, data->cleanup);
1588 append_to_statement_list (r, &body_list);
1589
1590 r = build3_loc (loc, COND_EXPR, void_type_node, ready_cond, body_list,
1591 empty_list);
1592
1593 append_to_statement_list (r, &stmt_list);
1594
1595 /* Resume point. */
1596 resume_label = build_stmt (loc, LABEL_EXPR, resume_label);
1597 append_to_statement_list (resume_label, &stmt_list);
1598
1599 /* This will produce the value (if one is provided) from the co_await
1600 expression. */
1601 tree resume_call = TREE_VEC_ELT (awaiter_calls, 2); /* await_resume(). */
1602 if (REFERENCE_REF_P (resume_call))
1603 /* Sink to await_resume call_expr. */
1604 resume_call = TREE_OPERAND (resume_call, 0);
1605
1606 *await_expr = resume_call; /* Replace the co_await expr with its result. */
1607 append_to_statement_list_force (saved_statement, &stmt_list);
1608 /* Get a pointer to the revised statement. */
1609 tree *revised = tsi_stmt_ptr (tsi_last (stmt_list));
1610 if (needs_dtor)
1611 {
1612 tree dtor = build_special_member_call (var, complete_dtor_identifier,
1613 NULL, await_type, LOOKUP_NORMAL,
1614 tf_warning_or_error);
1615 append_to_statement_list (dtor, &stmt_list);
1616 }
1617 data->index += 2;
1618
1619 /* Replace the original statement with the expansion. */
1620 *stmt = stmt_list;
1621
1622 /* Now, if the awaitable had an initializer, expand any awaits that might
1623 be embedded in it. */
1624 tree *aw_expr_ptr;
1625 if (await_init &&
1626 cp_walk_tree (await_init, co_await_find_in_subtree, &aw_expr_ptr, NULL))
1627 expand_one_await_expression (await_init, aw_expr_ptr, d);
1628
1629 /* Expand any more await expressions in the the original statement. */
1630 if (cp_walk_tree (revised, co_await_find_in_subtree, &aw_expr_ptr, NULL))
1631 expand_one_await_expression (revised, aw_expr_ptr, d);
1632
1633 return NULL;
1634 }
1635
1636 /* Check to see if a statement contains at least one await expression, if
1637 so, then process that. */
1638
1639 static tree
1640 process_one_statement (tree *stmt, void *d)
1641 {
1642 tree *aw_expr_ptr;
1643 if (cp_walk_tree (stmt, co_await_find_in_subtree, &aw_expr_ptr, NULL))
1644 expand_one_await_expression (stmt, aw_expr_ptr, d);
1645 return NULL_TREE;
1646 }
1647
1648 static tree
1649 await_statement_expander (tree *stmt, int *do_subtree, void *d)
1650 {
1651 tree res = NULL_TREE;
1652
1653 /* Process a statement at a time. */
1654 if (STATEMENT_CLASS_P (*stmt) || TREE_CODE (*stmt) == BIND_EXPR)
1655 return NULL_TREE; /* Just process the sub-trees. */
1656 else if (TREE_CODE (*stmt) == STATEMENT_LIST)
1657 {
1658 tree_stmt_iterator i;
1659 for (i = tsi_start (*stmt); !tsi_end_p (i); tsi_next (&i))
1660 {
1661 res = cp_walk_tree (tsi_stmt_ptr (i), await_statement_expander,
1662 d, NULL);
1663 if (res)
1664 return res;
1665 }
1666 *do_subtree = 0; /* Done subtrees. */
1667 }
1668 else if (EXPR_P (*stmt))
1669 {
1670 process_one_statement (stmt, d);
1671 *do_subtree = 0; /* Done subtrees. */
1672 }
1673
1674 /* Continue statement walk, where required. */
1675 return res;
1676 }
1677
1678 /* Suspend point hash_map. */
1679
1680 struct suspend_point_info
1681 {
1682 /* coro frame field type. */
1683 tree awaitable_type;
1684 /* coro frame field name. */
1685 tree await_field_id;
1686 };
1687
1688 static hash_map<tree, suspend_point_info> *suspend_points;
1689
1690 struct await_xform_data
1691 {
1692 tree actor_fn; /* Decl for context. */
1693 tree actor_frame;
1694 tree promise_proxy;
1695 tree real_promise;
1696 tree self_h_proxy;
1697 tree real_self_h;
1698 };
1699
1700 /* When we built the await expressions, we didn't know the coro frame
1701 layout, therefore no idea where to find the promise or where to put
1702 the awaitables. Now we know these things, fill them in. */
1703
1704 static tree
1705 transform_await_expr (tree await_expr, await_xform_data *xform)
1706 {
1707 suspend_point_info *si = suspend_points->get (await_expr);
1708 location_t loc = EXPR_LOCATION (await_expr);
1709 if (!si)
1710 {
1711 error_at (loc, "no suspend point info for %qD", await_expr);
1712 return error_mark_node;
1713 }
1714
1715 /* So, on entry, we have:
1716 in : CO_AWAIT_EXPR (a, e_proxy, o, awr_call_vector, mode)
1717 We no longer need a [it had diagnostic value, maybe?]
1718 We need to replace the promise proxy in all elements
1719 We need to replace the e_proxy in the awr_call. */
1720
1721 tree coro_frame_type = TREE_TYPE (xform->actor_frame);
1722
1723 /* If we have a frame var for the awaitable, get a reference to it. */
1724 proxy_replace data;
1725 if (si->await_field_id)
1726 {
1727 tree as_m
1728 = lookup_member (coro_frame_type, si->await_field_id,
1729 /*protect=*/1, /*want_type=*/0, tf_warning_or_error);
1730 tree as = build_class_member_access_expr (xform->actor_frame, as_m,
1731 NULL_TREE, true,
1732 tf_warning_or_error);
1733
1734 /* Replace references to the instance proxy with the frame entry now
1735 computed. */
1736 data.from = TREE_OPERAND (await_expr, 1);
1737 data.to = as;
1738 cp_walk_tree (&await_expr, replace_proxy, &data, NULL);
1739
1740 /* .. and replace. */
1741 TREE_OPERAND (await_expr, 1) = as;
1742 }
1743
1744 /* Now do the self_handle. */
1745 data.from = xform->self_h_proxy;
1746 data.to = xform->real_self_h;
1747 cp_walk_tree (&await_expr, replace_proxy, &data, NULL);
1748
1749 /* Now do the promise. */
1750 data.from = xform->promise_proxy;
1751 data.to = xform->real_promise;
1752 cp_walk_tree (&await_expr, replace_proxy, &data, NULL);
1753
1754 return await_expr;
1755 }
1756
1757 /* A wrapper for the transform_await_expr function so that it can be a
1758 callback from cp_walk_tree. */
1759
1760 static tree
1761 transform_await_wrapper (tree *stmt, int *do_subtree, void *d)
1762 {
1763 /* Set actor function as new DECL_CONTEXT of label_decl. */
1764 struct await_xform_data *xform = (struct await_xform_data *) d;
1765 if (TREE_CODE (*stmt) == LABEL_DECL
1766 && DECL_CONTEXT (*stmt) != xform->actor_fn)
1767 DECL_CONTEXT (*stmt) = xform->actor_fn;
1768
1769 /* We should have already lowered co_yields to their co_await. */
1770 gcc_checking_assert (TREE_CODE (*stmt) != CO_YIELD_EXPR);
1771 if (TREE_CODE (*stmt) != CO_AWAIT_EXPR)
1772 return NULL_TREE;
1773
1774 tree await_expr = *stmt;
1775 *stmt = transform_await_expr (await_expr, xform);
1776 if (*stmt == error_mark_node)
1777 *do_subtree = 0;
1778 return NULL_TREE;
1779 }
1780
1781 /* This caches information that we determine about function params,
1782 their uses and copies in the coroutine frame. */
1783
1784 struct param_info
1785 {
1786 tree field_id; /* The name of the copy in the coroutine frame. */
1787 vec<tree *> *body_uses; /* Worklist of uses, void if there are none. */
1788 tree frame_type; /* The type used to represent this parm in the frame. */
1789 tree orig_type; /* The original type of the parm (not as passed). */
1790 bool by_ref; /* Was passed by reference. */
1791 bool pt_ref; /* Was a pointer to object. */
1792 bool trivial_dtor; /* The frame type has a trivial DTOR. */
1793 bool this_ptr; /* Is 'this' */
1794 bool lambda_cobj; /* Lambda capture object */
1795 };
1796
1797 struct local_var_info
1798 {
1799 tree field_id;
1800 tree field_idx;
1801 tree frame_type;
1802 bool is_lambda_capture;
1803 bool is_static;
1804 bool has_value_expr_p;
1805 location_t def_loc;
1806 };
1807
1808 /* For figuring out what local variable usage we have. */
1809 struct local_vars_transform
1810 {
1811 tree context;
1812 tree actor_frame;
1813 tree coro_frame_type;
1814 location_t loc;
1815 hash_map<tree, local_var_info> *local_var_uses;
1816 };
1817
1818 static tree
1819 transform_local_var_uses (tree *stmt, int *do_subtree, void *d)
1820 {
1821 local_vars_transform *lvd = (local_vars_transform *) d;
1822
1823 /* For each var in this bind expr (that has a frame id, which means it was
1824 accessed), build a frame reference for each and then walk the bind expr
1825 statements, substituting the frame ref for the original var. */
1826
1827 if (TREE_CODE (*stmt) == BIND_EXPR)
1828 {
1829 tree lvar;
1830 for (lvar = BIND_EXPR_VARS (*stmt); lvar != NULL;
1831 lvar = DECL_CHAIN (lvar))
1832 {
1833 bool existed;
1834 local_var_info &local_var
1835 = lvd->local_var_uses->get_or_insert (lvar, &existed);
1836 gcc_checking_assert (existed);
1837
1838 /* Re-write the variable's context to be in the actor func. */
1839 DECL_CONTEXT (lvar) = lvd->context;
1840
1841 /* For capture proxies, this could include the decl value expr. */
1842 if (local_var.is_lambda_capture || local_var.has_value_expr_p)
1843 {
1844 tree ve = DECL_VALUE_EXPR (lvar);
1845 cp_walk_tree (&ve, transform_local_var_uses, d, NULL);
1846 continue; /* No frame entry for this. */
1847 }
1848
1849 /* TODO: implement selective generation of fields when vars are
1850 known not-used. */
1851 if (local_var.field_id == NULL_TREE)
1852 continue; /* Wasn't used. */
1853
1854 tree fld_ref
1855 = lookup_member (lvd->coro_frame_type, local_var.field_id,
1856 /*protect=*/1, /*want_type=*/0,
1857 tf_warning_or_error);
1858 tree fld_idx = build3_loc (lvd->loc, COMPONENT_REF, TREE_TYPE (lvar),
1859 lvd->actor_frame, fld_ref, NULL_TREE);
1860 local_var.field_idx = fld_idx;
1861 }
1862 /* FIXME: we should be able to do this in the loop above, but (at least
1863 for range for) there are cases where the DECL_INITIAL contains
1864 forward references.
1865 So, now we've built the revised var in the frame, substitute uses of
1866 it in initializers and the bind expr body. */
1867 for (lvar = BIND_EXPR_VARS (*stmt); lvar != NULL;
1868 lvar = DECL_CHAIN (lvar))
1869 {
1870 /* we need to walk some of the decl trees, which might contain
1871 references to vars replaced at a higher level. */
1872 cp_walk_tree (&DECL_INITIAL (lvar), transform_local_var_uses, d,
1873 NULL);
1874 cp_walk_tree (&DECL_SIZE (lvar), transform_local_var_uses, d, NULL);
1875 cp_walk_tree (&DECL_SIZE_UNIT (lvar), transform_local_var_uses, d,
1876 NULL);
1877 }
1878 cp_walk_tree (&BIND_EXPR_BODY (*stmt), transform_local_var_uses, d, NULL);
1879
1880 /* Now we have processed and removed references to the original vars,
1881 we can drop those from the bind - leaving capture proxies alone. */
1882 for (tree *pvar = &BIND_EXPR_VARS (*stmt); *pvar != NULL;)
1883 {
1884 bool existed;
1885 local_var_info &local_var
1886 = lvd->local_var_uses->get_or_insert (*pvar, &existed);
1887 gcc_checking_assert (existed);
1888
1889 /* Leave lambda closure captures alone, we replace the *this
1890 pointer with the frame version and let the normal process
1891 deal with the rest.
1892 Likewise, variables with their value found elsewhere.
1893 Skip past unused ones too. */
1894 if (local_var.is_lambda_capture
1895 || local_var.has_value_expr_p
1896 || local_var.field_id == NULL_TREE)
1897 {
1898 pvar = &DECL_CHAIN (*pvar);
1899 continue;
1900 }
1901
1902 /* Discard this one, we replaced it. */
1903 *pvar = DECL_CHAIN (*pvar);
1904 }
1905
1906 *do_subtree = 0; /* We've done the body already. */
1907 return NULL_TREE;
1908 }
1909
1910 tree var_decl = *stmt;
1911 /* Look inside cleanups, we don't want to wrap a statement list in a
1912 cleanup. */
1913 bool needs_cleanup = true;
1914 if (TREE_CODE (var_decl) == CLEANUP_POINT_EXPR)
1915 var_decl = TREE_OPERAND (var_decl, 0);
1916 else
1917 needs_cleanup = false;
1918
1919 /* Look inside the decl_expr for the actual var. */
1920 bool decl_expr_p = TREE_CODE (var_decl) == DECL_EXPR;
1921 if (decl_expr_p && TREE_CODE (DECL_EXPR_DECL (var_decl)) == VAR_DECL)
1922 var_decl = DECL_EXPR_DECL (var_decl);
1923 else if (TREE_CODE (var_decl) != VAR_DECL)
1924 return NULL_TREE;
1925
1926 /* VAR_DECLs that are not recorded can belong to the proxies we've placed
1927 for the promise and coroutine handle(s), to global vars or to compiler
1928 temporaries. Skip past these, we will handle them later. */
1929 local_var_info *local_var_i = lvd->local_var_uses->get (var_decl);
1930
1931 if (local_var_i == NULL)
1932 return NULL_TREE;
1933
1934 if (local_var_i->is_lambda_capture
1935 || local_var_i->is_static
1936 || local_var_i->has_value_expr_p)
1937 return NULL_TREE;
1938
1939 /* This is our revised 'local' i.e. a frame slot. */
1940 tree revised = local_var_i->field_idx;
1941 gcc_checking_assert (DECL_CONTEXT (var_decl) == lvd->context);
1942
1943 if (decl_expr_p && DECL_INITIAL (var_decl))
1944 {
1945 location_t loc = DECL_SOURCE_LOCATION (var_decl);
1946 tree r
1947 = cp_build_modify_expr (loc, revised, INIT_EXPR,
1948 DECL_INITIAL (var_decl), tf_warning_or_error);
1949 if (needs_cleanup)
1950 r = coro_build_cvt_void_expr_stmt (r, EXPR_LOCATION (*stmt));
1951 *stmt = r;
1952 }
1953 else
1954 *stmt = revised;
1955
1956 if (decl_expr_p)
1957 *do_subtree = 0; /* We've accounted for the nested use. */
1958 return NULL_TREE;
1959 }
1960
1961 /* The actor transform. */
1962
1963 static void
1964 build_actor_fn (location_t loc, tree coro_frame_type, tree actor, tree fnbody,
1965 tree orig, hash_map<tree, param_info> *param_uses,
1966 hash_map<tree, local_var_info> *local_var_uses,
1967 vec<tree, va_gc> *param_dtor_list, tree resume_fn_field,
1968 unsigned body_count, tree frame_size)
1969 {
1970 verify_stmt_tree (fnbody);
1971 /* Some things we inherit from the original function. */
1972 tree handle_type = get_coroutine_handle_type (orig);
1973 tree self_h_proxy = get_coroutine_self_handle_proxy (orig);
1974 tree promise_type = get_coroutine_promise_type (orig);
1975 tree promise_proxy = get_coroutine_promise_proxy (orig);
1976
1977 /* One param, the coro frame pointer. */
1978 tree actor_fp = DECL_ARGUMENTS (actor);
1979
1980 /* A void return. */
1981 tree resdecl = build_decl (loc, RESULT_DECL, 0, void_type_node);
1982 DECL_ARTIFICIAL (resdecl) = 1;
1983 DECL_IGNORED_P (resdecl) = 1;
1984 DECL_RESULT (actor) = resdecl;
1985 DECL_COROUTINE_P (actor) = 1;
1986
1987 /* We have a definition here. */
1988 TREE_STATIC (actor) = 1;
1989
1990 tree actor_outer = push_stmt_list ();
1991 current_stmt_tree ()->stmts_are_full_exprs_p = 1;
1992 tree stmt = begin_compound_stmt (BCS_FN_BODY);
1993
1994 tree actor_bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
1995 tree top_block = make_node (BLOCK);
1996 BIND_EXPR_BLOCK (actor_bind) = top_block;
1997
1998 tree continuation = build_lang_decl (VAR_DECL,
1999 get_identifier ("actor.continue"),
2000 void_coro_handle_type);
2001 DECL_ARTIFICIAL (continuation) = 1;
2002 DECL_IGNORED_P (continuation) = 1;
2003 DECL_CONTEXT (continuation) = actor;
2004 BIND_EXPR_VARS (actor_bind) = continuation;
2005
2006 /* Link in the block associated with the outer scope of the re-written
2007 function body. */
2008 tree first = expr_first (fnbody);
2009 gcc_checking_assert (first && TREE_CODE (first) == BIND_EXPR);
2010 tree block = BIND_EXPR_BLOCK (first);
2011 gcc_checking_assert (BLOCK_SUPERCONTEXT (block) == NULL_TREE);
2012 gcc_checking_assert (BLOCK_CHAIN (block) == NULL_TREE);
2013 BLOCK_SUPERCONTEXT (block) = top_block;
2014 BLOCK_SUBBLOCKS (top_block) = block;
2015
2016 add_stmt (actor_bind);
2017 tree actor_body = push_stmt_list ();
2018
2019 /* The entry point for the actor code from the ramp. */
2020 tree actor_begin_label
2021 = create_named_label_with_ctx (loc, "actor.begin", actor);
2022 tree actor_frame = build1_loc (loc, INDIRECT_REF, coro_frame_type, actor_fp);
2023
2024 /* Declare the continuation handle. */
2025 add_decl_expr (continuation);
2026
2027 /* Re-write param references in the body, no code should be generated
2028 here. */
2029 if (DECL_ARGUMENTS (orig))
2030 {
2031 tree arg;
2032 for (arg = DECL_ARGUMENTS (orig); arg != NULL; arg = DECL_CHAIN (arg))
2033 {
2034 bool existed;
2035 param_info &parm = param_uses->get_or_insert (arg, &existed);
2036 if (!parm.body_uses)
2037 continue; /* Wasn't used in the original function body. */
2038
2039 tree fld_ref = lookup_member (coro_frame_type, parm.field_id,
2040 /*protect=*/1, /*want_type=*/0,
2041 tf_warning_or_error);
2042 tree fld_idx = build3_loc (loc, COMPONENT_REF, parm.frame_type,
2043 actor_frame, fld_ref, NULL_TREE);
2044
2045 /* We keep these in the frame as a regular pointer, so convert that
2046 back to the type expected. */
2047 if (parm.pt_ref)
2048 fld_idx = build1_loc (loc, CONVERT_EXPR, TREE_TYPE (arg), fld_idx);
2049
2050 int i;
2051 tree *puse;
2052 FOR_EACH_VEC_ELT (*parm.body_uses, i, puse)
2053 *puse = fld_idx;
2054 }
2055 }
2056
2057 /* Re-write local vars, similarly. */
2058 local_vars_transform xform_vars_data
2059 = {actor, actor_frame, coro_frame_type, loc, local_var_uses};
2060 cp_walk_tree (&fnbody, transform_local_var_uses, &xform_vars_data, NULL);
2061
2062 tree resume_idx_name = get_identifier ("__resume_at");
2063 tree rat_field = lookup_member (coro_frame_type, resume_idx_name, 1, 0,
2064 tf_warning_or_error);
2065 tree rat = build3 (COMPONENT_REF, short_unsigned_type_node, actor_frame,
2066 rat_field, NULL_TREE);
2067
2068 tree ret_label
2069 = create_named_label_with_ctx (loc, "actor.suspend.ret", actor);
2070
2071 tree continue_label
2072 = create_named_label_with_ctx (loc, "actor.continue.ret", actor);
2073
2074 tree lsb_if = begin_if_stmt ();
2075 tree chkb0 = build2 (BIT_AND_EXPR, short_unsigned_type_node, rat,
2076 build_int_cst (short_unsigned_type_node, 1));
2077 chkb0 = build2 (NE_EXPR, short_unsigned_type_node, chkb0,
2078 build_int_cst (short_unsigned_type_node, 0));
2079 finish_if_stmt_cond (chkb0, lsb_if);
2080
2081 tree destroy_dispatcher = begin_switch_stmt ();
2082 finish_switch_cond (rat, destroy_dispatcher);
2083 tree ddeflab = build_case_label (NULL_TREE, NULL_TREE,
2084 create_anon_label_with_ctx (loc, actor));
2085 add_stmt (ddeflab);
2086 tree b = build_call_expr_loc (loc, builtin_decl_explicit (BUILT_IN_TRAP), 0);
2087 b = coro_build_cvt_void_expr_stmt (b, loc);
2088 add_stmt (b);
2089
2090 short unsigned lab_num = 3;
2091 for (unsigned destr_pt = 0; destr_pt < body_count; destr_pt++)
2092 {
2093 tree l_num = build_int_cst (short_unsigned_type_node, lab_num);
2094 b = build_case_label (l_num, NULL_TREE,
2095 create_anon_label_with_ctx (loc, actor));
2096 add_stmt (b);
2097 b = build_call_expr_internal_loc (loc, IFN_CO_ACTOR, void_type_node, 1,
2098 l_num);
2099 b = coro_build_cvt_void_expr_stmt (b, loc);
2100 add_stmt (b);
2101 b = build1 (GOTO_EXPR, void_type_node, CASE_LABEL (ddeflab));
2102 add_stmt (b);
2103 lab_num += 2;
2104 }
2105
2106 /* Insert the prototype dispatcher. */
2107 finish_switch_stmt (destroy_dispatcher);
2108
2109 finish_then_clause (lsb_if);
2110
2111 tree dispatcher = begin_switch_stmt ();
2112 finish_switch_cond (rat, dispatcher);
2113 b = build_case_label (build_int_cst (short_unsigned_type_node, 0), NULL_TREE,
2114 create_anon_label_with_ctx (loc, actor));
2115 add_stmt (b);
2116 b = build1 (GOTO_EXPR, void_type_node, actor_begin_label);
2117 add_stmt (b);
2118
2119 tree rdeflab = build_case_label (NULL_TREE, NULL_TREE,
2120 create_anon_label_with_ctx (loc, actor));
2121 add_stmt (rdeflab);
2122 b = build_call_expr_loc (loc, builtin_decl_explicit (BUILT_IN_TRAP), 0);
2123 b = coro_build_cvt_void_expr_stmt (b, loc);
2124 add_stmt (b);
2125
2126 lab_num = 2;
2127 /* The final resume should be made to hit the default (trap, UB) entry
2128 although it will be unreachable via the normal entry point, since that
2129 is set to NULL on reaching final suspend. */
2130 for (unsigned resu_pt = 0; resu_pt < body_count; resu_pt++)
2131 {
2132 tree l_num = build_int_cst (short_unsigned_type_node, lab_num);
2133 b = build_case_label (l_num, NULL_TREE,
2134 create_anon_label_with_ctx (loc, actor));
2135 add_stmt (b);
2136 b = build_call_expr_internal_loc (loc, IFN_CO_ACTOR, void_type_node, 1,
2137 l_num);
2138 b = coro_build_cvt_void_expr_stmt (b, loc);
2139 add_stmt (b);
2140 b = build1 (GOTO_EXPR, void_type_node, CASE_LABEL (rdeflab));
2141 add_stmt (b);
2142 lab_num += 2;
2143 }
2144
2145 /* Insert the prototype dispatcher. */
2146 finish_switch_stmt (dispatcher);
2147
2148 finish_if_stmt (lsb_if);
2149
2150 tree r = build_stmt (loc, LABEL_EXPR, actor_begin_label);
2151 add_stmt (r);
2152
2153 /* actor's version of the promise. */
2154 tree ap_m = lookup_member (coro_frame_type, get_identifier ("__p"), 1, 0,
2155 tf_warning_or_error);
2156 tree ap = build_class_member_access_expr (actor_frame, ap_m, NULL_TREE, false,
2157 tf_warning_or_error);
2158
2159 /* actor's coroutine 'self handle'. */
2160 tree ash_m = lookup_member (coro_frame_type, get_identifier ("__self_h"), 1,
2161 0, tf_warning_or_error);
2162 tree ash = build_class_member_access_expr (actor_frame, ash_m, NULL_TREE,
2163 false, tf_warning_or_error);
2164 /* So construct the self-handle from the frame address. */
2165 tree hfa_m = lookup_member (handle_type, coro_from_address_identifier, 1,
2166 0, tf_warning_or_error);
2167
2168 r = build1 (CONVERT_EXPR, build_pointer_type (void_type_node), actor_fp);
2169 vec<tree, va_gc> *args = make_tree_vector_single (r);
2170 tree hfa = build_new_method_call (ash, hfa_m, &args, NULL_TREE, LOOKUP_NORMAL,
2171 NULL, tf_warning_or_error);
2172 r = build2 (INIT_EXPR, handle_type, ash, hfa);
2173 r = coro_build_cvt_void_expr_stmt (r, loc);
2174 add_stmt (r);
2175 release_tree_vector (args);
2176
2177 /* Now we know the real promise, and enough about the frame layout to
2178 decide where to put things. */
2179
2180 await_xform_data xform
2181 = {actor, actor_frame, promise_proxy, ap, self_h_proxy, ash};
2182
2183 /* Transform the await expressions in the function body. Only do each
2184 await tree once! */
2185 hash_set<tree> pset;
2186 cp_walk_tree (&fnbody, transform_await_wrapper, &xform, &pset);
2187
2188 /* Now replace the promise proxy with its real value. */
2189 proxy_replace p_data;
2190 p_data.from = promise_proxy;
2191 p_data.to = ap;
2192 cp_walk_tree (&fnbody, replace_proxy, &p_data, NULL);
2193
2194 /* Set the actor pointer to null, so that 'done' will work.
2195 Resume from here is UB anyway - although a 'ready' await will
2196 branch to the final resume, and fall through to the destroy. */
2197 tree resume_m
2198 = lookup_member (coro_frame_type, get_identifier ("__resume"),
2199 /*protect=*/1, /*want_type=*/0, tf_warning_or_error);
2200 tree res_x = build_class_member_access_expr (actor_frame, resume_m, NULL_TREE,
2201 false, tf_warning_or_error);
2202 p_data.from = resume_fn_field;
2203 p_data.to = res_x;
2204 cp_walk_tree (&fnbody, replace_proxy, &p_data, NULL);
2205
2206 /* Add in our function body with the co_returns rewritten to final form. */
2207 add_stmt (fnbody);
2208
2209 /* now do the tail of the function. */
2210 tree del_promise_label
2211 = create_named_label_with_ctx (loc, "coro.delete.promise", actor);
2212 r = build_stmt (loc, LABEL_EXPR, del_promise_label);
2213 add_stmt (r);
2214
2215 /* Destructors for the things we built explicitly. */
2216 r = build_special_member_call (ap, complete_dtor_identifier, NULL,
2217 promise_type, LOOKUP_NORMAL,
2218 tf_warning_or_error);
2219 add_stmt (r);
2220
2221 tree del_frame_label
2222 = create_named_label_with_ctx (loc, "coro.delete.frame", actor);
2223 r = build_stmt (loc, LABEL_EXPR, del_frame_label);
2224 add_stmt (r);
2225
2226 /* Here deallocate the frame (if we allocated it), which we will have at
2227 present. */
2228 tree fnf_m
2229 = lookup_member (coro_frame_type, get_identifier ("__frame_needs_free"), 1,
2230 0, tf_warning_or_error);
2231 tree fnf2_x = build_class_member_access_expr (actor_frame, fnf_m, NULL_TREE,
2232 false, tf_warning_or_error);
2233
2234 tree need_free_if = begin_if_stmt ();
2235 fnf2_x = build1 (CONVERT_EXPR, integer_type_node, fnf2_x);
2236 tree cmp = build2 (NE_EXPR, integer_type_node, fnf2_x, integer_zero_node);
2237 finish_if_stmt_cond (cmp, need_free_if);
2238 if (param_dtor_list != NULL)
2239 {
2240 int i;
2241 tree pid;
2242 FOR_EACH_VEC_ELT (*param_dtor_list, i, pid)
2243 {
2244 tree m
2245 = lookup_member (coro_frame_type, pid, 1, 0, tf_warning_or_error);
2246 tree a = build_class_member_access_expr (actor_frame, m, NULL_TREE,
2247 false, tf_warning_or_error);
2248 tree t = TREE_TYPE (a);
2249 tree dtor;
2250 dtor
2251 = build_special_member_call (a, complete_dtor_identifier, NULL, t,
2252 LOOKUP_NORMAL, tf_warning_or_error);
2253 add_stmt (dtor);
2254 }
2255 }
2256
2257 /* [dcl.fct.def.coroutine] / 12
2258 The deallocation function’s name is looked up in the scope of the promise
2259 type. If this lookup fails, the deallocation function’s name is looked up
2260 in the global scope. If deallocation function lookup finds both a usual
2261 deallocation function with only a pointer parameter and a usual
2262 deallocation function with both a pointer parameter and a size parameter,
2263 then the selected deallocation function shall be the one with two
2264 parameters. Otherwise, the selected deallocation function shall be the
2265 function with one parameter. If no usual deallocation function is found
2266 the program is ill-formed. The selected deallocation function shall be
2267 called with the address of the block of storage to be reclaimed as its
2268 first argument. If a deallocation function with a parameter of type
2269 std::size_t is used, the size of the block is passed as the corresponding
2270 argument. */
2271
2272 tree del_coro_fr = NULL_TREE;
2273 tree frame_arg = build1 (CONVERT_EXPR, ptr_type_node, actor_fp);
2274
2275 tree delname = ovl_op_identifier (false, DELETE_EXPR);
2276 tree fns = lookup_promise_method (orig, delname, loc, /*musthave=*/false);
2277 if (fns && BASELINK_P (fns))
2278 {
2279 /* Look for sized version first, since this takes precedence. */
2280 vec<tree, va_gc> *args = make_tree_vector ();
2281 vec_safe_push (args, frame_arg);
2282 vec_safe_push (args, frame_size);
2283 tree dummy_promise = build_dummy_object (promise_type);
2284
2285 /* It's OK to fail for this one... */
2286 del_coro_fr = build_new_method_call (dummy_promise, fns, &args,
2287 NULL_TREE, LOOKUP_NORMAL, NULL,
2288 tf_none);
2289
2290 if (!del_coro_fr || del_coro_fr == error_mark_node)
2291 {
2292 release_tree_vector (args);
2293 args = make_tree_vector_single (frame_arg);
2294 del_coro_fr = build_new_method_call (dummy_promise, fns, &args,
2295 NULL_TREE, LOOKUP_NORMAL, NULL,
2296 tf_none);
2297 }
2298
2299 /* But one of them must succeed, or the program is ill-formed. */
2300 if (!del_coro_fr || del_coro_fr == error_mark_node)
2301 {
2302 error_at (loc, "%qE is provided by %qT but is not usable with"
2303 " the function signature %qD", delname, promise_type, orig);
2304 del_coro_fr = error_mark_node;
2305 }
2306 }
2307 else
2308 {
2309 del_coro_fr = build_op_delete_call (DELETE_EXPR, frame_arg, frame_size,
2310 /*global_p=*/true, /*placement=*/NULL,
2311 /*alloc_fn=*/NULL,
2312 tf_warning_or_error);
2313 if (!del_coro_fr || del_coro_fr == error_mark_node)
2314 del_coro_fr = error_mark_node;
2315 }
2316
2317 del_coro_fr = coro_build_cvt_void_expr_stmt (del_coro_fr, loc);
2318 add_stmt (del_coro_fr);
2319 finish_then_clause (need_free_if);
2320 tree scope = IF_SCOPE (need_free_if);
2321 IF_SCOPE (need_free_if) = NULL;
2322 r = do_poplevel (scope);
2323 add_stmt (r);
2324
2325 /* done. */
2326 r = build_stmt (loc, RETURN_EXPR, NULL);
2327 TREE_NO_WARNING (r) |= 1; /* We don't want a warning about this. */
2328 r = maybe_cleanup_point_expr_void (r);
2329 add_stmt (r);
2330
2331 /* This is the suspend return point. */
2332 r = build_stmt (loc, LABEL_EXPR, ret_label);
2333 add_stmt (r);
2334
2335 r = build_stmt (loc, RETURN_EXPR, NULL);
2336 TREE_NO_WARNING (r) |= 1; /* We don't want a warning about this. */
2337 r = maybe_cleanup_point_expr_void (r);
2338 add_stmt (r);
2339
2340 /* This is the 'continuation' return point. For such a case we have a coro
2341 handle (from the await_suspend() call) and we want handle.resume() to
2342 execute as a tailcall allowing arbitrary chaining of coroutines. */
2343 r = build_stmt (loc, LABEL_EXPR, continue_label);
2344 add_stmt (r);
2345
2346 /* We want to force a tail-call even for O0/1, so this expands the resume
2347 call into its underlying implementation. */
2348 tree addr = lookup_member (void_coro_handle_type, coro_address_identifier,
2349 1, 0, tf_warning_or_error);
2350 addr = build_new_method_call (continuation, addr, NULL, NULL_TREE,
2351 LOOKUP_NORMAL, NULL, tf_warning_or_error);
2352 tree resume = build_call_expr_loc
2353 (loc, builtin_decl_explicit (BUILT_IN_CORO_RESUME), 1, addr);
2354
2355 /* In order to support an arbitrary number of coroutine continuations,
2356 we must tail call them. However, some targets do not support indirect
2357 tail calls to arbitrary callees. See PR94359. */
2358 CALL_EXPR_TAILCALL (resume) = true;
2359 resume = coro_build_cvt_void_expr_stmt (resume, loc);
2360 add_stmt (resume);
2361
2362 r = build_stmt (loc, RETURN_EXPR, NULL);
2363 gcc_checking_assert (maybe_cleanup_point_expr_void (r) == r);
2364 add_stmt (r);
2365
2366 /* We will need to know which resume point number should be encoded. */
2367 tree res_idx_m
2368 = lookup_member (coro_frame_type, resume_idx_name,
2369 /*protect=*/1, /*want_type=*/0, tf_warning_or_error);
2370 tree resume_pt_number
2371 = build_class_member_access_expr (actor_frame, res_idx_m, NULL_TREE, false,
2372 tf_warning_or_error);
2373
2374 /* We've now rewritten the tree and added the initial and final
2375 co_awaits. Now pass over the tree and expand the co_awaits. */
2376
2377 coro_aw_data data = {actor, actor_fp, resume_pt_number, NULL_TREE,
2378 ash, del_promise_label, ret_label,
2379 continue_label, continuation, 2};
2380 cp_walk_tree (&actor_body, await_statement_expander, &data, NULL);
2381
2382 BIND_EXPR_BODY (actor_bind) = pop_stmt_list (actor_body);
2383 TREE_SIDE_EFFECTS (actor_bind) = true;
2384
2385 finish_compound_stmt (stmt);
2386 DECL_SAVED_TREE (actor) = pop_stmt_list (actor_outer);
2387 verify_stmt_tree (DECL_SAVED_TREE (actor));
2388 }
2389
2390 /* The prototype 'destroy' function :
2391 frame->__resume_at |= 1;
2392 actor (frame); */
2393
2394 static void
2395 build_destroy_fn (location_t loc, tree coro_frame_type, tree destroy,
2396 tree actor)
2397 {
2398 /* One param, the coro frame pointer. */
2399 tree destr_fp = DECL_ARGUMENTS (destroy);
2400
2401 /* A void return. */
2402 tree resdecl = build_decl (loc, RESULT_DECL, 0, void_type_node);
2403 DECL_ARTIFICIAL (resdecl) = 1;
2404 DECL_IGNORED_P (resdecl) = 1;
2405 DECL_RESULT (destroy) = resdecl;
2406
2407 /* We have a definition here. */
2408 TREE_STATIC (destroy) = 1;
2409 DECL_COROUTINE_P (destroy) = 1;
2410
2411 tree destr_outer = push_stmt_list ();
2412 current_stmt_tree ()->stmts_are_full_exprs_p = 1;
2413 tree dstr_stmt = begin_compound_stmt (BCS_FN_BODY);
2414
2415 tree destr_frame = build1 (INDIRECT_REF, coro_frame_type, destr_fp);
2416
2417 tree resume_idx_name = get_identifier ("__resume_at");
2418 tree rat_field = lookup_member (coro_frame_type, resume_idx_name, 1, 0,
2419 tf_warning_or_error);
2420 tree rat = build3 (COMPONENT_REF, short_unsigned_type_node, destr_frame,
2421 rat_field, NULL_TREE);
2422
2423 /* _resume_at |= 1 */
2424 tree dstr_idx = build2 (BIT_IOR_EXPR, short_unsigned_type_node, rat,
2425 build_int_cst (short_unsigned_type_node, 1));
2426 tree r = build2 (MODIFY_EXPR, short_unsigned_type_node, rat, dstr_idx);
2427 r = coro_build_cvt_void_expr_stmt (r, loc);
2428 add_stmt (r);
2429
2430 /* So .. call the actor .. */
2431 r = build_call_expr_loc (loc, actor, 1, destr_fp);
2432 r = coro_build_cvt_void_expr_stmt (r, loc);
2433 add_stmt (r);
2434
2435 /* done. */
2436 r = build_stmt (loc, RETURN_EXPR, NULL);
2437 r = maybe_cleanup_point_expr_void (r);
2438 add_stmt (r);
2439
2440 finish_compound_stmt (dstr_stmt);
2441 DECL_SAVED_TREE (destroy) = pop_stmt_list (destr_outer);
2442 }
2443
2444 /* Helper that returns an identifier for an appended extension to the
2445 current un-mangled function name. */
2446
2447 static tree
2448 get_fn_local_identifier (tree orig, const char *append)
2449 {
2450 /* Figure out the bits we need to generate names for the outlined things
2451 For consistency, this needs to behave the same way as
2452 ASM_FORMAT_PRIVATE_NAME does. */
2453 tree nm = DECL_NAME (orig);
2454 const char *sep, *pfx = "";
2455 #ifndef NO_DOT_IN_LABEL
2456 sep = ".";
2457 #else
2458 #ifndef NO_DOLLAR_IN_LABEL
2459 sep = "$";
2460 #else
2461 sep = "_";
2462 pfx = "__";
2463 #endif
2464 #endif
2465
2466 char *an;
2467 if (DECL_ASSEMBLER_NAME (orig))
2468 an = ACONCAT ((IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (orig)), sep, append,
2469 (char *) 0));
2470 else if (DECL_USE_TEMPLATE (orig) && DECL_TEMPLATE_INFO (orig)
2471 && DECL_TI_ARGS (orig))
2472 {
2473 tree tpl_args = DECL_TI_ARGS (orig);
2474 an = ACONCAT ((pfx, IDENTIFIER_POINTER (nm), (char *) 0));
2475 for (int i = 0; i < TREE_VEC_LENGTH (tpl_args); ++i)
2476 {
2477 tree typ = DECL_NAME (TYPE_NAME (TREE_VEC_ELT (tpl_args, i)));
2478 an = ACONCAT ((an, sep, IDENTIFIER_POINTER (typ), (char *) 0));
2479 }
2480 an = ACONCAT ((an, sep, append, (char *) 0));
2481 }
2482 else
2483 an = ACONCAT ((pfx, IDENTIFIER_POINTER (nm), sep, append, (char *) 0));
2484
2485 return get_identifier (an);
2486 }
2487
2488 /* Build an initial or final await initialized from the promise
2489 initial_suspend or final_suspend expression. */
2490
2491 static tree
2492 build_init_or_final_await (location_t loc, bool is_final)
2493 {
2494 tree suspend_alt = is_final ? coro_final_suspend_identifier
2495 : coro_initial_suspend_identifier;
2496
2497 tree setup_call
2498 = coro_build_promise_expression (current_function_decl, NULL, suspend_alt,
2499 loc, NULL, /*musthave=*/true);
2500
2501 /* So build the co_await for this */
2502 /* For initial/final suspends the call is "a" per [expr.await] 3.2. */
2503 return build_co_await (loc, setup_call, (is_final ? FINAL_SUSPEND_POINT
2504 : INITIAL_SUSPEND_POINT));
2505 }
2506
2507 /* Callback to record the essential data for each await point found in the
2508 function. */
2509
2510 static bool
2511 register_await_info (tree await_expr, tree aw_type, tree aw_nam)
2512 {
2513 bool seen;
2514 suspend_point_info &s
2515 = suspend_points->get_or_insert (await_expr, &seen);
2516 if (seen)
2517 {
2518 warning_at (EXPR_LOCATION (await_expr), 0, "duplicate info for %qE",
2519 await_expr);
2520 return false;
2521 }
2522 s.awaitable_type = aw_type;
2523 s.await_field_id = aw_nam;
2524 return true;
2525 }
2526
2527 /* This data set is used when analyzing statements for await expressions. */
2528
2529 struct susp_frame_data
2530 {
2531 /* Function-wide. */
2532 tree *field_list; /* The current coroutine frame field list. */
2533 tree handle_type; /* The self-handle type for this coroutine. */
2534 tree fs_label; /* The destination for co_returns. */
2535 vec<tree, va_gc> *block_stack; /* Track block scopes. */
2536 vec<tree, va_gc> *bind_stack; /* Track current bind expr. */
2537 unsigned await_number; /* Which await in the function. */
2538 unsigned cond_number; /* Which replaced condition in the fn. */
2539 /* Temporary values for one statement or expression being analyzed. */
2540 hash_set<tree> captured_temps; /* The suspend captured these temps. */
2541 vec<tree, va_gc> *to_replace; /* The VAR decls to replace. */
2542 hash_set<tree> *truth_aoif_to_expand; /* The set of TRUTH exprs to expand. */
2543 unsigned saw_awaits; /* Count of awaits in this statement */
2544 bool captures_temporary; /* This expr captures temps by ref. */
2545 bool needs_truth_if_exp; /* We must expand a truth_if expression. */
2546 bool has_awaiter_init; /* We must handle initializing an awaiter. */
2547 };
2548
2549 /* If this is an await expression, then count it (both uniquely within the
2550 function and locally within a single statement). */
2551
2552 static tree
2553 register_awaits (tree *stmt, int *, void *d)
2554 {
2555 tree aw_expr = *stmt;
2556
2557 /* We should have already lowered co_yields to their co_await. */
2558 gcc_checking_assert (TREE_CODE (aw_expr) != CO_YIELD_EXPR);
2559
2560 if (TREE_CODE (aw_expr) != CO_AWAIT_EXPR)
2561 return NULL_TREE;
2562
2563 /* Count how many awaits the current expression contains. */
2564 susp_frame_data *data = (susp_frame_data *) d;
2565 data->saw_awaits++;
2566 /* Each await suspend context is unique, this is a function-wide value. */
2567 data->await_number++;
2568
2569 /* Awaitables should either be user-locals or promoted to coroutine frame
2570 entries at this point, and their initializers should have been broken
2571 out. */
2572 tree aw = TREE_OPERAND (aw_expr, 1);
2573 gcc_checking_assert (!TREE_OPERAND (aw_expr, 2));
2574
2575 tree aw_field_type = TREE_TYPE (aw);
2576 tree aw_field_nam = NULL_TREE;
2577 register_await_info (aw_expr, aw_field_type, aw_field_nam);
2578
2579 /* Rewrite target expressions on the await_suspend () to remove extraneous
2580 cleanups for the awaitables, which are now promoted to frame vars and
2581 managed via that. */
2582 tree v = TREE_OPERAND (aw_expr, 3);
2583 tree o = TREE_VEC_ELT (v, 1);
2584 if (TREE_CODE (o) == TARGET_EXPR)
2585 TREE_VEC_ELT (v, 1) = get_target_expr (TREE_OPERAND (o, 1));
2586 return NULL_TREE;
2587 }
2588
2589 /* There are cases where any await expression is relevant. */
2590 static tree
2591 find_any_await (tree *stmt, int *dosub, void *d)
2592 {
2593 if (TREE_CODE (*stmt) == CO_AWAIT_EXPR)
2594 {
2595 *dosub = 0; /* We don't need to consider this any further. */
2596 tree **p = (tree **) d;
2597 *p = stmt;
2598 return *stmt;
2599 }
2600 return NULL_TREE;
2601 }
2602
2603 static bool
2604 tmp_target_expr_p (tree t)
2605 {
2606 if (TREE_CODE (t) != TARGET_EXPR)
2607 return false;
2608 tree v = TREE_OPERAND (t, 0);
2609 if (!DECL_ARTIFICIAL (v))
2610 return false;
2611 if (DECL_NAME (v))
2612 return false;
2613 return true;
2614 }
2615
2616 /* Structure to record sub-expressions that need to be handled by the
2617 statement flattener. */
2618
2619 struct coro_interesting_subtree
2620 {
2621 tree* entry;
2622 hash_set<tree> *temps_used;
2623 };
2624
2625 /* tree-walk callback that returns the first encountered sub-expression of
2626 a kind that needs to be handled specifically by the statement flattener. */
2627
2628 static tree
2629 find_interesting_subtree (tree *expr_p, int *dosub, void *d)
2630 {
2631 tree expr = *expr_p;
2632 coro_interesting_subtree *p = (coro_interesting_subtree *)d;
2633 if (TREE_CODE (expr) == CO_AWAIT_EXPR)
2634 {
2635 *dosub = 0; /* We don't need to consider this any further. */
2636 if (TREE_OPERAND (expr, 2))
2637 {
2638 p->entry = expr_p;
2639 return expr;
2640 }
2641 }
2642 else if (tmp_target_expr_p (expr)
2643 && !p->temps_used->contains (expr))
2644 {
2645 p->entry = expr_p;
2646 return expr;
2647 }
2648
2649 return NULL_TREE;
2650 }
2651
2652 /* Node for a doubly-linked list of promoted variables and their
2653 initializers. When the initializer is a conditional expression
2654 the 'then' and 'else' clauses are represented by a linked list
2655 attached to then_cl and else_cl respectively. */
2656
2657 struct var_nest_node
2658 {
2659 var_nest_node () = default;
2660 var_nest_node (tree v, tree i, var_nest_node *p, var_nest_node *n)
2661 : var(v), init(i), prev(p), next(n)
2662 {
2663 if (p)
2664 p->next = this;
2665 if (n)
2666 n->prev = this;
2667 }
2668 tree var;
2669 tree init;
2670 var_nest_node *prev;
2671 var_nest_node *next;
2672 var_nest_node *then_cl;
2673 var_nest_node *else_cl;
2674 };
2675
2676 /* This is called for single statements from the co-await statement walker.
2677 It checks to see if the statement contains any initializers for awaitables
2678 and if any of these capture items by reference. */
2679
2680 static void
2681 flatten_await_stmt (var_nest_node *n, hash_set<tree> *promoted,
2682 hash_set<tree> *temps_used, tree *replace_in)
2683 {
2684 bool init_expr = false;
2685 switch (TREE_CODE (n->init))
2686 {
2687 default: break;
2688 /* Compound expressions must be flattened specifically. */
2689 case COMPOUND_EXPR:
2690 {
2691 tree first = TREE_OPERAND (n->init, 0);
2692 n->init = TREE_OPERAND (n->init, 1);
2693 var_nest_node *ins
2694 = new var_nest_node(NULL_TREE, first, n->prev, n);
2695 /* The compiler (but not the user) can generate temporaries with
2696 uses in the second arm of a compound expr. */
2697 flatten_await_stmt (ins, promoted, temps_used, &n->init);
2698 flatten_await_stmt (n, promoted, temps_used, NULL);
2699 /* The two arms have been processed separately. */
2700 return;
2701 }
2702 break;
2703 /* Handle conditional expressions. */
2704 case INIT_EXPR:
2705 init_expr = true;
2706 /* FALLTHROUGH */
2707 case MODIFY_EXPR:
2708 {
2709 tree old_expr = TREE_OPERAND (n->init, 1);
2710 if (TREE_CODE (old_expr) == COMPOUND_EXPR)
2711 {
2712 tree first = TREE_OPERAND (old_expr, 0);
2713 TREE_OPERAND (n->init, 1) = TREE_OPERAND (old_expr, 1);
2714 var_nest_node *ins
2715 = new var_nest_node(NULL_TREE, first, n->prev, n);
2716 flatten_await_stmt (ins, promoted, temps_used,
2717 &TREE_OPERAND (n->init, 1));
2718 flatten_await_stmt (n, promoted, temps_used, NULL);
2719 return;
2720 }
2721 if (TREE_CODE (old_expr) != COND_EXPR)
2722 break;
2723 /* Reconstruct x = t ? y : z;
2724 as (void) t ? x = y : x = z; */
2725 tree var = TREE_OPERAND (n->init, 0);
2726 tree var_type = TREE_TYPE (var);
2727 tree cond = COND_EXPR_COND (old_expr);
2728 /* We are allowed a void type throw in one or both of the cond
2729 expr arms. */
2730 tree then_cl = COND_EXPR_THEN (old_expr);
2731 if (!VOID_TYPE_P (TREE_TYPE (then_cl)))
2732 {
2733 gcc_checking_assert (TREE_CODE (then_cl) != STATEMENT_LIST);
2734 then_cl
2735 = build2 (init_expr ? INIT_EXPR : MODIFY_EXPR, var_type,
2736 var, then_cl);
2737 }
2738 tree else_cl = COND_EXPR_ELSE (old_expr);
2739 if (!VOID_TYPE_P (TREE_TYPE (else_cl)))
2740 {
2741 gcc_checking_assert (TREE_CODE (then_cl) != STATEMENT_LIST);
2742 else_cl
2743 = build2 (init_expr ? INIT_EXPR : MODIFY_EXPR, var_type,
2744 var, else_cl);
2745 }
2746 n->init = build3 (COND_EXPR, var_type, cond, then_cl, else_cl);
2747 }
2748 /* FALLTHROUGH */
2749 case COND_EXPR:
2750 {
2751 tree *found;
2752 tree cond = COND_EXPR_COND (n->init);
2753 /* If the condition contains an await expression, then we need to
2754 set that first and use a separate var. */
2755 if (cp_walk_tree (&cond, find_any_await, &found, NULL))
2756 {
2757 tree cond_type = TREE_TYPE (cond);
2758 tree cond_var = build_lang_decl (VAR_DECL, NULL_TREE, cond_type);
2759 DECL_ARTIFICIAL (cond_var) = true;
2760 layout_decl (cond_var, 0);
2761 gcc_checking_assert (!TYPE_NEEDS_CONSTRUCTING (cond_type));
2762 cond = build2 (INIT_EXPR, cond_type, cond_var, cond);
2763 var_nest_node *ins
2764 = new var_nest_node (cond_var, cond, n->prev, n);
2765 COND_EXPR_COND (n->init) = cond_var;
2766 flatten_await_stmt (ins, promoted, temps_used, NULL);
2767 }
2768
2769 n->then_cl
2770 = new var_nest_node (n->var, COND_EXPR_THEN (n->init), NULL, NULL);
2771 n->else_cl
2772 = new var_nest_node (n->var, COND_EXPR_ELSE (n->init), NULL, NULL);
2773 flatten_await_stmt (n->then_cl, promoted, temps_used, NULL);
2774 /* Point to the start of the flattened code. */
2775 while (n->then_cl->prev)
2776 n->then_cl = n->then_cl->prev;
2777 flatten_await_stmt (n->else_cl, promoted, temps_used, NULL);
2778 while (n->else_cl->prev)
2779 n->else_cl = n->else_cl->prev;
2780 return;
2781 }
2782 break;
2783 }
2784 coro_interesting_subtree v = { NULL, temps_used };
2785 tree t = cp_walk_tree (&n->init, find_interesting_subtree, (void *)&v, NULL);
2786 if (!t)
2787 return;
2788 switch (TREE_CODE (t))
2789 {
2790 default: break;
2791 case CO_AWAIT_EXPR:
2792 {
2793 /* Await expressions with initializers have a compiler-temporary
2794 as the awaitable. 'promote' this. */
2795 tree var = TREE_OPERAND (t, 1);
2796 bool already_present = promoted->add (var);
2797 gcc_checking_assert (!already_present);
2798 tree init = TREE_OPERAND (t, 2);
2799 switch (TREE_CODE (init))
2800 {
2801 default: break;
2802 case INIT_EXPR:
2803 case MODIFY_EXPR:
2804 {
2805 tree inner = TREE_OPERAND (init, 1);
2806 /* We can have non-lvalue-expressions here, but when we see
2807 a target expression, mark it as already used. */
2808 if (TREE_CODE (inner) == TARGET_EXPR)
2809 {
2810 temps_used->add (inner);
2811 gcc_checking_assert
2812 (TREE_CODE (TREE_OPERAND (inner, 1)) != COND_EXPR);
2813 }
2814 }
2815 break;
2816 case CALL_EXPR:
2817 /* If this is a call and not a CTOR, then we didn't expect it. */
2818 gcc_checking_assert
2819 (DECL_CONSTRUCTOR_P (TREE_OPERAND (CALL_EXPR_FN (init), 0)));
2820 break;
2821 }
2822 var_nest_node *ins = new var_nest_node (var, init, n->prev, n);
2823 TREE_OPERAND (t, 2) = NULL_TREE;
2824 flatten_await_stmt (ins, promoted, temps_used, NULL);
2825 flatten_await_stmt (n, promoted, temps_used, NULL);
2826 return;
2827 }
2828 break;
2829 case TARGET_EXPR:
2830 {
2831 /* We have a temporary; promote it. */
2832 tree init = t;
2833 temps_used->add (init);
2834 tree var_type = TREE_TYPE (init);
2835 char *buf = xasprintf ("D.%d", DECL_UID (TREE_OPERAND (init, 0)));
2836 tree var = build_lang_decl (VAR_DECL, get_identifier (buf), var_type);
2837 DECL_ARTIFICIAL (var) = true;
2838 free (buf);
2839 bool already_present = promoted->add (var);
2840 gcc_checking_assert (!already_present);
2841 tree inner = TREE_OPERAND (init, 1);
2842 gcc_checking_assert (TREE_CODE (inner) != COND_EXPR);
2843 if (TYPE_NEEDS_CONSTRUCTING (var_type))
2844 {
2845 releasing_vec p_in (make_tree_vector_single (init));
2846 init = build_special_member_call (var, complete_ctor_identifier,
2847 &p_in, var_type, LOOKUP_NORMAL,
2848 tf_warning_or_error);
2849 }
2850 else
2851 init = build2 (INIT_EXPR, var_type, var, init);
2852 var_nest_node *ins
2853 = new var_nest_node (var, init, n->prev, n);
2854 /* We have to replace the target expr... */
2855 proxy_replace pr = {TREE_OPERAND (t, 0), var};
2856 *v.entry = var;
2857 /* ... and any uses of its var. */
2858 cp_walk_tree (&n->init, replace_proxy, &pr, NULL);
2859 /* Compiler-generated temporaries can also have uses in following
2860 arms of compound expressions, which will be listed in 'replace_in'
2861 if present. */
2862 if (replace_in)
2863 cp_walk_tree (replace_in, replace_proxy, &pr, NULL);
2864 flatten_await_stmt (ins, promoted, temps_used, NULL);
2865 flatten_await_stmt (n, promoted, temps_used, NULL);
2866 return;
2867 }
2868 break;
2869 }
2870 }
2871
2872 /* Helper for 'process_conditional' that handles recursion into nested
2873 conditionals. */
2874
2875 static void
2876 handle_nested_conditionals (var_nest_node *n, vec<tree>& list,
2877 hash_map<tree, tree>& map)
2878 {
2879 do
2880 {
2881 if (n->var && DECL_NAME (n->var))
2882 {
2883 list.safe_push (n->var);
2884 if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (n->var)))
2885 {
2886 bool existed;
2887 tree& flag = map.get_or_insert (n->var, &existed);
2888 if (!existed)
2889 {
2890 /* We didn't see this var before and it needs a DTOR, so
2891 build a guard variable for it. */
2892 char *nam
2893 = xasprintf ("%s_guard",
2894 IDENTIFIER_POINTER (DECL_NAME (n->var)));
2895 flag = build_lang_decl (VAR_DECL, get_identifier (nam),
2896 boolean_type_node);
2897 free (nam);
2898 DECL_ARTIFICIAL (flag) = true;
2899 }
2900
2901 /* The initializer for this variable is replaced by a compound
2902 expression that performs the init and then records that the
2903 variable is live (and the DTOR should be run at the scope
2904 exit. */
2905 tree set_flag = build2 (INIT_EXPR, boolean_type_node,
2906 flag, boolean_true_node);
2907 n->init
2908 = build2 (COMPOUND_EXPR, boolean_type_node, n->init, set_flag);
2909 }
2910 }
2911 if (TREE_CODE (n->init) == COND_EXPR)
2912 {
2913 tree new_then = push_stmt_list ();
2914 handle_nested_conditionals (n->then_cl, list, map);
2915 new_then = pop_stmt_list (new_then);
2916 tree new_else = push_stmt_list ();
2917 handle_nested_conditionals (n->else_cl, list, map);
2918 new_else = pop_stmt_list (new_else);
2919 tree new_if
2920 = build4 (IF_STMT, void_type_node, COND_EXPR_COND (n->init),
2921 new_then, new_else, NULL_TREE);
2922 add_stmt (new_if);
2923 }
2924 else
2925 finish_expr_stmt (n->init);
2926 n = n->next;
2927 } while (n);
2928 }
2929
2930 /* helper for 'maybe_promote_temps'.
2931
2932 When we have a conditional expression which might embed await expressions
2933 and/or promoted variables, we need to handle it appropriately.
2934
2935 The linked lists for the 'then' and 'else' clauses in a conditional node
2936 identify the promoted variables (but these cannot be wrapped in a regular
2937 cleanup).
2938
2939 So recurse through the lists and build up a composite list of captured vars.
2940 Declare these and any guard variables needed to decide if a DTOR should be
2941 run. Then embed the conditional into a try-finally expression that handles
2942 running each DTOR conditionally on its guard variable. */
2943
2944 static void
2945 process_conditional (var_nest_node *n, tree& vlist)
2946 {
2947 tree init = n->init;
2948 hash_map<tree, tree> var_flags;
2949 vec<tree> var_list = vNULL;
2950 tree new_then = push_stmt_list ();
2951 handle_nested_conditionals (n->then_cl, var_list, var_flags);
2952 new_then = pop_stmt_list (new_then);
2953 tree new_else = push_stmt_list ();
2954 handle_nested_conditionals (n->else_cl, var_list, var_flags);
2955 new_else = pop_stmt_list (new_else);
2956 /* Declare the vars. There are two loops so that the boolean flags are
2957 grouped in the frame. */
2958 for (unsigned i = 0; i < var_list.length(); i++)
2959 {
2960 tree var = var_list[i];
2961 DECL_CHAIN (var) = vlist;
2962 vlist = var;
2963 add_decl_expr (var);
2964 }
2965 /* Define the guard flags for variables that need a DTOR. */
2966 for (unsigned i = 0; i < var_list.length(); i++)
2967 {
2968 tree *flag = var_flags.get (var_list[i]);
2969 if (flag)
2970 {
2971 DECL_INITIAL (*flag) = boolean_false_node;
2972 DECL_CHAIN (*flag) = vlist;
2973 vlist = *flag;
2974 add_decl_expr (*flag);
2975 }
2976 }
2977 tree new_if
2978 = build4 (IF_STMT, void_type_node, COND_EXPR_COND (init),
2979 new_then, new_else, NULL_TREE);
2980 /* Build a set of conditional DTORs. */
2981 tree final_actions = push_stmt_list ();
2982 while (!var_list.is_empty())
2983 {
2984 tree var = var_list.pop ();
2985 tree *flag = var_flags.get (var);
2986 if (!flag)
2987 continue;
2988 tree var_type = TREE_TYPE (var);
2989 tree cleanup
2990 = build_special_member_call (var, complete_dtor_identifier,
2991 NULL, var_type, LOOKUP_NORMAL,
2992 tf_warning_or_error);
2993 tree cond_cleanup = begin_if_stmt ();
2994 finish_if_stmt_cond (*flag, cond_cleanup);
2995 finish_expr_stmt (cleanup);
2996 finish_then_clause (cond_cleanup);
2997 finish_if_stmt (cond_cleanup);
2998 }
2999 final_actions = pop_stmt_list (final_actions);
3000 tree try_finally
3001 = build2 (TRY_FINALLY_EXPR, void_type_node, new_if, final_actions);
3002 add_stmt (try_finally);
3003 }
3004
3005 /* Given *STMT, that contains at least one await expression.
3006
3007 The full expression represented in the original source code will contain
3008 suspension points, but it is still required that the lifetime of temporary
3009 values extends to the end of the expression.
3010
3011 We already have a mechanism to 'promote' user-authored local variables
3012 to a coroutine frame counterpart (which allows explicit management of the
3013 lifetime across suspensions). The transform here re-writes STMT into
3014 a bind expression, promotes temporary values into local variables in that
3015 and flattens the statement into a series of cleanups.
3016
3017 Conditional expressions are re-written to regular 'if' statements.
3018 The cleanups for variables initialized inside a conditional (including
3019 nested cases) are wrapped in a try-finally clause, with guard variables
3020 to determine which DTORs need to be run. */
3021
3022 static tree
3023 maybe_promote_temps (tree *stmt, void *d)
3024 {
3025 susp_frame_data *awpts = (susp_frame_data *) d;
3026
3027 location_t sloc = EXPR_LOCATION (*stmt);
3028 tree expr = *stmt;
3029 /* Strip off uninteresting wrappers. */
3030 if (TREE_CODE (expr) == CLEANUP_POINT_EXPR)
3031 expr = TREE_OPERAND (expr, 0);
3032 if (TREE_CODE (expr) == EXPR_STMT)
3033 expr = EXPR_STMT_EXPR (expr);
3034 if (TREE_CODE (expr) == CONVERT_EXPR
3035 && VOID_TYPE_P (TREE_TYPE (expr)))
3036 expr = TREE_OPERAND (expr, 0);
3037 STRIP_NOPS (expr);
3038
3039 /* We walk the statement trees, flattening it into an ordered list of
3040 variables with initializers and fragments corresponding to compound
3041 expressions, truth or/and if and ternary conditionals. Conditional
3042 expressions carry a nested list of fragments for the then and else
3043 clauses. We anchor to the 'bottom' of the fragment list; we will write
3044 a cleanup nest with one shell for each variable initialized. */
3045 var_nest_node *root = new var_nest_node (NULL_TREE, expr, NULL, NULL);
3046 /* Check to see we didn't promote one twice. */
3047 hash_set<tree> promoted_vars;
3048 hash_set<tree> used_temps;
3049 flatten_await_stmt (root, &promoted_vars, &used_temps, NULL);
3050
3051 gcc_checking_assert (root->next == NULL);
3052 tree vlist = NULL_TREE;
3053 var_nest_node *t = root;
3054 gcc_checking_assert (!t->var);
3055 /* We build the bind scope expression from the bottom-up.
3056 EXPR_LIST holds the inner expression nest at the current cleanup
3057 level (becoming the final expression list when we've exhausted the
3058 number of sub-expression fragments). */
3059 tree expr_list = NULL_TREE;
3060 do
3061 {
3062 tree new_list = push_stmt_list ();
3063 /* When we have a promoted variable, then add that to the bind scope
3064 and initialize it. When there's no promoted variable, we just need
3065 to run the initializer.
3066 If the initializer is a conditional expression, we need to collect
3067 and declare any promoted variables nested within it. DTORs for such
3068 variables must be run conditionally too. */
3069 if (t->var && DECL_NAME (t->var))
3070 {
3071 tree var = t->var;
3072 DECL_CHAIN (var) = vlist;
3073 vlist = var;
3074 add_decl_expr (var);
3075 if (TREE_CODE (t->init) == COND_EXPR)
3076 process_conditional (t, vlist);
3077 else
3078 finish_expr_stmt (t->init);
3079 tree var_type = TREE_TYPE (var);
3080 if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (var_type))
3081 {
3082 tree cleanup
3083 = build_special_member_call (var, complete_dtor_identifier,
3084 NULL, var_type, LOOKUP_NORMAL,
3085 tf_warning_or_error);
3086 tree cl = build_stmt (sloc, CLEANUP_STMT, expr_list, cleanup, var);
3087 add_stmt (cl); /* push this onto the level above. */
3088 }
3089 else if (expr_list)
3090 add_stmt (expr_list);
3091 else
3092 gcc_unreachable ();
3093 }
3094 else
3095 {
3096 if (TREE_CODE (t->init) == COND_EXPR)
3097 process_conditional (t, vlist);
3098 else
3099 finish_expr_stmt (t->init);
3100 if (expr_list)
3101 add_stmt (expr_list);
3102 }
3103 expr_list = pop_stmt_list (new_list);
3104 var_nest_node *old = t;
3105 t = t->prev;
3106 delete old;
3107 } while (t);
3108
3109 /* Now produce the bind expression containing the 'promoted' temporaries
3110 as its variable list, and the cleanup nest as the statement. */
3111 tree await_bind = build3_loc (sloc, BIND_EXPR, void_type_node,
3112 NULL, NULL, NULL);
3113 BIND_EXPR_BODY (await_bind) = expr_list;
3114 BIND_EXPR_VARS (await_bind) = nreverse (vlist);
3115 tree b_block = make_node (BLOCK);
3116 if (!awpts->block_stack->is_empty ())
3117 {
3118 tree s_block = awpts->block_stack->last ();
3119 if (s_block)
3120 {
3121 BLOCK_SUPERCONTEXT (b_block) = s_block;
3122 BLOCK_CHAIN (b_block) = BLOCK_SUBBLOCKS (s_block);
3123 BLOCK_SUBBLOCKS (s_block) = b_block;
3124 }
3125 }
3126 BLOCK_VARS (b_block) = BIND_EXPR_VARS (await_bind) ;
3127 BIND_EXPR_BLOCK (await_bind) = b_block;
3128 TREE_SIDE_EFFECTS (await_bind) = TREE_SIDE_EFFECTS (BIND_EXPR_BODY (await_bind));
3129 *stmt = await_bind;
3130 hash_set<tree> visited;
3131 return cp_walk_tree (stmt, register_awaits, d, &visited);
3132 }
3133
3134 /* Lightweight callback to determine two key factors:
3135 1) If the statement/expression contains any await expressions.
3136 2) If the statement/expression potentially requires a re-write to handle
3137 TRUTH_{AND,OR}IF_EXPRs since, in most cases, they will need expansion
3138 so that the await expressions are not processed in the case of the
3139 short-circuit arm.
3140
3141 CO_YIELD expressions are re-written to their underlying co_await. */
3142
3143 static tree
3144 analyze_expression_awaits (tree *stmt, int *do_subtree, void *d)
3145 {
3146 susp_frame_data *awpts = (susp_frame_data *) d;
3147
3148 switch (TREE_CODE (*stmt))
3149 {
3150 default: return NULL_TREE;
3151 case CO_YIELD_EXPR:
3152 /* co_yield is syntactic sugar, re-write it to co_await. */
3153 *stmt = TREE_OPERAND (*stmt, 1);
3154 /* FALLTHROUGH */
3155 case CO_AWAIT_EXPR:
3156 awpts->saw_awaits++;
3157 /* A non-null initializer for the awaiter means we need to expand. */
3158 if (TREE_OPERAND (*stmt, 2))
3159 awpts->has_awaiter_init = true;
3160 break;
3161 case TRUTH_ANDIF_EXPR:
3162 case TRUTH_ORIF_EXPR:
3163 {
3164 /* We don't need special action for awaits in the always-executed
3165 arm of a TRUTH_IF. */
3166 if (tree res = cp_walk_tree (&TREE_OPERAND (*stmt, 0),
3167 analyze_expression_awaits, d, NULL))
3168 return res;
3169 /* However, if there are await expressions on the conditionally
3170 executed branch, we must expand the TRUTH_IF to ensure that the
3171 expanded await expression control-flow is fully contained in the
3172 conditionally executed code. */
3173 unsigned aw_count = awpts->saw_awaits;
3174 if (tree res = cp_walk_tree (&TREE_OPERAND (*stmt, 1),
3175 analyze_expression_awaits, d, NULL))
3176 return res;
3177 if (awpts->saw_awaits > aw_count)
3178 {
3179 awpts->truth_aoif_to_expand->add (*stmt);
3180 awpts->needs_truth_if_exp = true;
3181 }
3182 /* We've done the sub-trees here. */
3183 *do_subtree = 0;
3184 }
3185 break;
3186 }
3187
3188 return NULL_TREE; /* Recurse until done. */
3189 }
3190
3191 /* Given *EXPR
3192 If EXPR contains a TRUTH_{AND,OR}IF_EXPR, TAOIE with an await expr on
3193 the conditionally executed branch, change this in a ternary operator.
3194
3195 bool not_expr = TAOIE == TRUTH_ORIF_EXPR ? NOT : NOP;
3196 not_expr (always-exec expr) ? conditionally-exec expr : not_expr;
3197
3198 Apply this recursively to the condition and the conditionally-exec
3199 branch. */
3200
3201 struct truth_if_transform {
3202 tree *orig_stmt;
3203 tree scratch_var;
3204 hash_set<tree> *truth_aoif_to_expand;
3205 };
3206
3207 static tree
3208 expand_one_truth_if (tree *expr, int *do_subtree, void *d)
3209 {
3210 truth_if_transform *xform = (truth_if_transform *) d;
3211
3212 bool needs_not = false;
3213 switch (TREE_CODE (*expr))
3214 {
3215 default: break;
3216 case TRUTH_ORIF_EXPR:
3217 needs_not = true;
3218 /* FALLTHROUGH */
3219 case TRUTH_ANDIF_EXPR:
3220 {
3221 if (!xform->truth_aoif_to_expand->contains (*expr))
3222 break;
3223
3224 location_t sloc = EXPR_LOCATION (*expr);
3225 /* Transform truth expression into a cond expression with
3226 * the always-executed arm as the condition.
3227 * the conditionally-executed arm as the then clause.
3228 * the 'else' clause is fixed: 'true' for ||,'false' for &&. */
3229 tree cond = TREE_OPERAND (*expr, 0);
3230 tree test1 = TREE_OPERAND (*expr, 1);
3231 tree fixed = needs_not ? boolean_true_node : boolean_false_node;
3232 if (needs_not)
3233 cond = build1 (TRUTH_NOT_EXPR, boolean_type_node, cond);
3234 tree cond_expr
3235 = build3_loc (sloc, COND_EXPR, boolean_type_node,
3236 cond, test1, fixed);
3237 *expr = cond_expr;
3238 if (tree res = cp_walk_tree (&COND_EXPR_COND (*expr),
3239 expand_one_truth_if, d, NULL))
3240 return res;
3241 if (tree res = cp_walk_tree (&COND_EXPR_THEN (*expr),
3242 expand_one_truth_if, d, NULL))
3243 return res;
3244 /* We've manually processed necessary sub-trees here. */
3245 *do_subtree = 0;
3246 }
3247 break;
3248 }
3249 return NULL_TREE;
3250 }
3251
3252 /* Helper that adds a new variable of VAR_TYPE to a bind scope BIND, the
3253 name is made up from NAM_ROOT, NAM_VERS. */
3254
3255 static tree
3256 add_var_to_bind (tree& bind, tree var_type,
3257 const char *nam_root, unsigned nam_vers)
3258 {
3259 tree b_vars = BIND_EXPR_VARS (bind);
3260 /* Build a variable to hold the condition, this will be included in the
3261 frame as a local var. */
3262 char *nam = xasprintf ("%s.%d", nam_root, nam_vers);
3263 tree newvar = build_lang_decl (VAR_DECL, get_identifier (nam), var_type);
3264 free (nam);
3265 DECL_CHAIN (newvar) = b_vars;
3266 BIND_EXPR_VARS (bind) = newvar;
3267 return newvar;
3268 }
3269
3270 /* Helper to build and add if (!cond) break; */
3271
3272 static void
3273 coro_build_add_if_not_cond_break (tree cond)
3274 {
3275 tree if_stmt = begin_if_stmt ();
3276 tree invert = build1 (TRUTH_NOT_EXPR, boolean_type_node, cond);
3277 finish_if_stmt_cond (invert, if_stmt);
3278 finish_break_stmt ();
3279 finish_then_clause (if_stmt);
3280 finish_if_stmt (if_stmt);
3281 }
3282
3283 /* Tree walk callback to analyze, register and pre-process statements that
3284 contain await expressions. */
3285
3286 static tree
3287 await_statement_walker (tree *stmt, int *do_subtree, void *d)
3288 {
3289 tree res = NULL_TREE;
3290 susp_frame_data *awpts = (susp_frame_data *) d;
3291
3292 /* Process a statement at a time. */
3293 if (TREE_CODE (*stmt) == BIND_EXPR)
3294 {
3295 /* For conditional expressions, we might wish to add an artificial var
3296 to their containing bind expr. */
3297 vec_safe_push (awpts->bind_stack, *stmt);
3298 /* We might need to insert a new bind expression, and want to link it
3299 into the correct scope, so keep a note of the current block scope. */
3300 tree blk = BIND_EXPR_BLOCK (*stmt);
3301 vec_safe_push (awpts->block_stack, blk);
3302 res = cp_walk_tree (&BIND_EXPR_BODY (*stmt), await_statement_walker,
3303 d, NULL);
3304 awpts->block_stack->pop ();
3305 awpts->bind_stack->pop ();
3306 *do_subtree = 0; /* Done subtrees. */
3307 return res;
3308 }
3309 else if (TREE_CODE (*stmt) == STATEMENT_LIST)
3310 {
3311 tree_stmt_iterator i;
3312 for (i = tsi_start (*stmt); !tsi_end_p (i); tsi_next (&i))
3313 {
3314 res = cp_walk_tree (tsi_stmt_ptr (i), await_statement_walker,
3315 d, NULL);
3316 if (res)
3317 return res;
3318 }
3319 *do_subtree = 0; /* Done subtrees. */
3320 return NULL_TREE;
3321 }
3322
3323 /* We have something to be handled as a single statement. */
3324 bool has_cleanup_wrapper = TREE_CODE (*stmt) == CLEANUP_POINT_EXPR;
3325 hash_set<tree> visited;
3326 awpts->saw_awaits = 0;
3327 hash_set<tree> truth_aoif_to_expand;
3328 awpts->truth_aoif_to_expand = &truth_aoif_to_expand;
3329 awpts->needs_truth_if_exp = false;
3330 awpts->has_awaiter_init = false;
3331 tree expr = *stmt;
3332 if (has_cleanup_wrapper)
3333 expr = TREE_OPERAND (expr, 0);
3334 STRIP_NOPS (expr);
3335
3336 if (STATEMENT_CLASS_P (expr))
3337 switch (TREE_CODE (expr))
3338 {
3339 /* Unless it's a special case, just walk the subtrees as usual. */
3340 default: return NULL_TREE;
3341
3342 /* When we have a conditional expression, which contains one or more
3343 await expressions, we have to break the condition out into a
3344 regular statement so that the control flow introduced by the await
3345 transforms can be implemented. */
3346 case IF_STMT:
3347 {
3348 /* Transform 'if (cond with awaits) then stmt1 else stmt2' into
3349 bool cond = cond with awaits.
3350 if (cond) then stmt1 else stmt2. */
3351 tree if_stmt = *stmt;
3352 /* We treat the condition as if it was a stand-alone statement,
3353 to see if there are any await expressions which will be analyzed
3354 and registered. */
3355 if ((res = cp_walk_tree (&IF_COND (if_stmt),
3356 analyze_expression_awaits, d, &visited)))
3357 return res;
3358 if (!awpts->saw_awaits)
3359 return NULL_TREE; /* Nothing special to do here. */
3360
3361 gcc_checking_assert (!awpts->bind_stack->is_empty());
3362 tree& bind_expr = awpts->bind_stack->last ();
3363 tree newvar = add_var_to_bind (bind_expr, boolean_type_node,
3364 "ifcd", awpts->cond_number++);
3365 tree insert_list = push_stmt_list ();
3366 tree cond_inner = IF_COND (if_stmt);
3367 if (TREE_CODE (cond_inner) == CLEANUP_POINT_EXPR)
3368 cond_inner = TREE_OPERAND (cond_inner, 0);
3369 add_decl_expr (newvar);
3370 location_t sloc = EXPR_LOCATION (IF_COND (if_stmt));
3371 /* We want to initialize the new variable with the expression
3372 that contains the await(s) and potentially also needs to
3373 have truth_if expressions expanded. */
3374 tree new_s = build2_loc (sloc, MODIFY_EXPR, boolean_type_node,
3375 newvar, cond_inner);
3376 finish_expr_stmt (new_s);
3377 IF_COND (if_stmt) = newvar;
3378 add_stmt (if_stmt);
3379 *stmt = pop_stmt_list (insert_list);
3380 /* So now walk the new statement list. */
3381 res = cp_walk_tree (stmt, await_statement_walker, d, NULL);
3382 *do_subtree = 0; /* Done subtrees. */
3383 return res;
3384 }
3385 break;
3386 case WHILE_STMT:
3387 {
3388 /* We turn 'while (cond with awaits) stmt' into
3389 while (true) {
3390 if (!(cond with awaits))
3391 break;
3392 stmt..
3393 } */
3394 tree while_stmt = *stmt;
3395 if ((res = cp_walk_tree (&WHILE_COND (while_stmt),
3396 analyze_expression_awaits, d, &visited)))
3397 return res;
3398 if (!awpts->saw_awaits)
3399 return NULL_TREE; /* Nothing special to do here. */
3400
3401 tree insert_list = push_stmt_list ();
3402 coro_build_add_if_not_cond_break (WHILE_COND (while_stmt));
3403 /* The original while body. */
3404 add_stmt (WHILE_BODY (while_stmt));
3405 /* The new while body. */
3406 WHILE_BODY (while_stmt) = pop_stmt_list (insert_list);
3407 WHILE_COND (while_stmt) = boolean_true_node;
3408 /* So now walk the new statement list. */
3409 res = cp_walk_tree (&WHILE_BODY (while_stmt),
3410 await_statement_walker, d, NULL);
3411 *do_subtree = 0; /* Done subtrees. */
3412 return res;
3413 }
3414 break;
3415 case DO_STMT:
3416 {
3417 /* We turn do stmt while (cond with awaits) into:
3418 do {
3419 stmt..
3420 if (!(cond with awaits))
3421 break;
3422 } while (true); */
3423 tree do_stmt = *stmt;
3424 if ((res = cp_walk_tree (&DO_COND (do_stmt),
3425 analyze_expression_awaits, d, &visited)))
3426 return res;
3427 if (!awpts->saw_awaits)
3428 return NULL_TREE; /* Nothing special to do here. */
3429
3430 tree insert_list = push_stmt_list ();
3431 /* The original do stmt body. */
3432 add_stmt (DO_BODY (do_stmt));
3433 coro_build_add_if_not_cond_break (DO_COND (do_stmt));
3434 /* The new while body. */
3435 DO_BODY (do_stmt) = pop_stmt_list (insert_list);
3436 DO_COND (do_stmt) = boolean_true_node;
3437 /* So now walk the new statement list. */
3438 res = cp_walk_tree (&DO_BODY (do_stmt), await_statement_walker,
3439 d, NULL);
3440 *do_subtree = 0; /* Done subtrees. */
3441 return res;
3442 }
3443 break;
3444 case SWITCH_STMT:
3445 {
3446 /* We turn 'switch (cond with awaits) stmt' into
3447 switch_type cond = cond with awaits
3448 switch (cond) stmt. */
3449 tree sw_stmt = *stmt;
3450 if ((res = cp_walk_tree (&SWITCH_STMT_COND (sw_stmt),
3451 analyze_expression_awaits, d, &visited)))
3452 return res;
3453 if (!awpts->saw_awaits)
3454 return NULL_TREE; /* Nothing special to do here. */
3455
3456 gcc_checking_assert (!awpts->bind_stack->is_empty());
3457 /* Build a variable to hold the condition, this will be
3458 included in the frame as a local var. */
3459 tree& bind_expr = awpts->bind_stack->last ();
3460 tree sw_type = SWITCH_STMT_TYPE (sw_stmt);
3461 tree newvar = add_var_to_bind (bind_expr, sw_type, "swch",
3462 awpts->cond_number++);
3463 tree insert_list = push_stmt_list ();
3464 add_decl_expr (newvar);
3465
3466 tree cond_inner = SWITCH_STMT_COND (sw_stmt);
3467 if (TREE_CODE (cond_inner) == CLEANUP_POINT_EXPR)
3468 cond_inner = TREE_OPERAND (cond_inner, 0);
3469 location_t sloc = EXPR_LOCATION (SWITCH_STMT_COND (sw_stmt));
3470 tree new_s = build2_loc (sloc, INIT_EXPR, sw_type, newvar,
3471 cond_inner);
3472 finish_expr_stmt (new_s);
3473 SWITCH_STMT_COND (sw_stmt) = newvar;
3474 /* Now add the switch statement with the condition re-
3475 written to use the local var. */
3476 add_stmt (sw_stmt);
3477 *stmt = pop_stmt_list (insert_list);
3478 /* Process the expanded list. */
3479 res = cp_walk_tree (stmt, await_statement_walker,
3480 d, NULL);
3481 *do_subtree = 0; /* Done subtrees. */
3482 return res;
3483 }
3484 break;
3485 case CO_RETURN_EXPR:
3486 {
3487 /* Expand the co_return as per [stmt.return.coroutine]
3488 - for co_return;
3489 { p.return_void (); goto final_suspend; }
3490 - for co_return [void expr];
3491 { expr; p.return_void(); goto final_suspend;}
3492 - for co_return [non void expr];
3493 { p.return_value(expr); goto final_suspend; } */
3494 if ((res = cp_walk_tree (stmt, analyze_expression_awaits,
3495 d, &visited)))
3496 return res;
3497 location_t loc = EXPR_LOCATION (expr);
3498 tree call = TREE_OPERAND (expr, 1);
3499 expr = TREE_OPERAND (expr, 0);
3500 tree ret_list = push_stmt_list ();
3501 /* [stmt.return.coroutine], 2.2
3502 If expr is present and void, it is placed immediately before
3503 the call for return_void; */
3504 tree *maybe_await_stmt = NULL;
3505 if (expr && VOID_TYPE_P (TREE_TYPE (expr)))
3506 {
3507 finish_expr_stmt (expr);
3508 /* If the return argument was a void expression, then any
3509 awaits must be contained in that. */
3510 maybe_await_stmt = tsi_stmt_ptr (tsi_last (ret_list));
3511 }
3512 /* Insert p.return_{void,value(expr)}. */
3513 finish_expr_stmt (call);
3514 /* Absent a return of a void expression, any awaits must be in
3515 the parameter to return_value(). */
3516 if (!maybe_await_stmt)
3517 maybe_await_stmt = tsi_stmt_ptr (tsi_last (ret_list));
3518 expr = build1_loc (loc, GOTO_EXPR, void_type_node, awpts->fs_label);
3519 finish_expr_stmt (expr);
3520 *stmt = pop_stmt_list (ret_list);
3521 /* Once this is complete, we will have processed subtrees. */
3522 *do_subtree = 0;
3523 if (awpts->saw_awaits)
3524 {
3525 gcc_checking_assert (maybe_await_stmt);
3526 res = cp_walk_tree (maybe_await_stmt, await_statement_walker,
3527 d, NULL);
3528 if (res)
3529 return res;
3530 }
3531 return NULL_TREE; /* Done. */
3532 }
3533 break;
3534 }
3535 else if (EXPR_P (expr))
3536 {
3537 if ((res = cp_walk_tree (stmt, analyze_expression_awaits, d, &visited)))
3538 return res;
3539 *do_subtree = 0; /* Done subtrees. */
3540 if (!awpts->saw_awaits)
3541 return NULL_TREE; /* Nothing special to do here. */
3542
3543 if (awpts->needs_truth_if_exp)
3544 {
3545 /* If a truth-and/or-if expression has an await expression in the
3546 conditionally-taken branch, then it must be rewritten into a
3547 regular conditional. */
3548 truth_if_transform xf = {stmt, NULL_TREE, &truth_aoif_to_expand};
3549 if ((res = cp_walk_tree (stmt, expand_one_truth_if, &xf, NULL)))
3550 return res;
3551 }
3552 /* Process this statement, which contains at least one await expression
3553 to 'promote' temporary values to a coroutine frame slot. */
3554 return maybe_promote_temps (stmt, d);
3555 }
3556 /* Continue recursion, if needed. */
3557 return res;
3558 }
3559
3560 /* For figuring out what param usage we have. */
3561
3562 struct param_frame_data
3563 {
3564 tree *field_list;
3565 hash_map<tree, param_info> *param_uses;
3566 hash_set<tree *> *visited;
3567 location_t loc;
3568 bool param_seen;
3569 };
3570
3571 /* A tree-walk callback that records the use of parameters (to allow for
3572 optimizations where handling unused parameters may be omitted). */
3573
3574 static tree
3575 register_param_uses (tree *stmt, int *do_subtree ATTRIBUTE_UNUSED, void *d)
3576 {
3577 param_frame_data *data = (param_frame_data *) d;
3578
3579 /* For lambda closure content, we have to look specifically. */
3580 if (TREE_CODE (*stmt) == VAR_DECL && DECL_HAS_VALUE_EXPR_P (*stmt))
3581 {
3582 tree t = DECL_VALUE_EXPR (*stmt);
3583 return cp_walk_tree (&t, register_param_uses, d, NULL);
3584 }
3585
3586 if (TREE_CODE (*stmt) != PARM_DECL)
3587 return NULL_TREE;
3588
3589 /* If we already saw the containing expression, then we're done. */
3590 if (data->visited->add (stmt))
3591 return NULL_TREE;
3592
3593 bool existed;
3594 param_info &parm = data->param_uses->get_or_insert (*stmt, &existed);
3595 gcc_checking_assert (existed);
3596
3597 if (!parm.body_uses)
3598 {
3599 vec_alloc (parm.body_uses, 4);
3600 parm.body_uses->quick_push (stmt);
3601 data->param_seen = true;
3602 }
3603 else
3604 parm.body_uses->safe_push (stmt);
3605
3606 return NULL_TREE;
3607 }
3608
3609 /* Small helper for the repetitive task of adding a new field to the coro
3610 frame type. */
3611
3612 static tree
3613 coro_make_frame_entry (tree *field_list, const char *name, tree fld_type,
3614 location_t loc)
3615 {
3616 tree id = get_identifier (name);
3617 tree decl = build_decl (loc, FIELD_DECL, id, fld_type);
3618 DECL_CHAIN (decl) = *field_list;
3619 *field_list = decl;
3620 return id;
3621 }
3622
3623 /* For recording local variable usage. */
3624
3625 struct local_vars_frame_data
3626 {
3627 tree *field_list;
3628 hash_map<tree, local_var_info> *local_var_uses;
3629 unsigned int nest_depth, bind_indx;
3630 location_t loc;
3631 bool saw_capture;
3632 bool local_var_seen;
3633 };
3634
3635 /* A tree-walk callback that processes one bind expression noting local
3636 variables, and making a coroutine frame slot available for those that
3637 need it, so that they can be 'promoted' across suspension points. */
3638
3639 static tree
3640 register_local_var_uses (tree *stmt, int *do_subtree, void *d)
3641 {
3642 local_vars_frame_data *lvd = (local_vars_frame_data *) d;
3643
3644 /* As we enter a bind expression - record the vars there and then recurse.
3645 As we exit drop the nest depth.
3646 The bind index is a growing count of how many bind indices we've seen.
3647 We build a space in the frame for each local var. */
3648
3649 if (TREE_CODE (*stmt) == BIND_EXPR)
3650 {
3651 lvd->bind_indx++;
3652 lvd->nest_depth++;
3653 tree lvar;
3654 for (lvar = BIND_EXPR_VARS (*stmt); lvar != NULL;
3655 lvar = DECL_CHAIN (lvar))
3656 {
3657 bool existed;
3658 local_var_info &local_var
3659 = lvd->local_var_uses->get_or_insert (lvar, &existed);
3660 gcc_checking_assert (!existed);
3661 local_var.def_loc = DECL_SOURCE_LOCATION (lvar);
3662 tree lvtype = TREE_TYPE (lvar);
3663 local_var.frame_type = lvtype;
3664 local_var.field_idx = local_var.field_id = NULL_TREE;
3665
3666 /* Make sure that we only present vars to the tests below. */
3667 if (TREE_CODE (lvar) == TYPE_DECL
3668 || TREE_CODE (lvar) == NAMESPACE_DECL)
3669 continue;
3670
3671 /* We don't move static vars into the frame. */
3672 local_var.is_static = TREE_STATIC (lvar);
3673 if (local_var.is_static)
3674 continue;
3675
3676 lvd->local_var_seen = true;
3677 /* If this var is a lambda capture proxy, we want to leave it alone,
3678 and later rewrite the DECL_VALUE_EXPR to indirect through the
3679 frame copy of the pointer to the lambda closure object. */
3680 local_var.is_lambda_capture = is_capture_proxy (lvar);
3681 if (local_var.is_lambda_capture)
3682 continue;
3683
3684 /* If a variable has a value expression, then that's what needs
3685 to be processed. */
3686 local_var.has_value_expr_p = DECL_HAS_VALUE_EXPR_P (lvar);
3687 if (local_var.has_value_expr_p)
3688 continue;
3689
3690 /* Make names depth+index unique, so that we can support nested
3691 scopes with identically named locals. */
3692 tree lvname = DECL_NAME (lvar);
3693 char *buf;
3694 if (lvname != NULL_TREE)
3695 buf = xasprintf ("__%s.%u.%u", IDENTIFIER_POINTER (lvname),
3696 lvd->nest_depth, lvd->bind_indx);
3697 else
3698 buf = xasprintf ("_D%u.%u.%u", DECL_UID (lvar), lvd->nest_depth,
3699 lvd->bind_indx);
3700 /* TODO: Figure out if we should build a local type that has any
3701 excess alignment or size from the original decl. */
3702 local_var.field_id
3703 = coro_make_frame_entry (lvd->field_list, buf, lvtype, lvd->loc);
3704 free (buf);
3705 /* We don't walk any of the local var sub-trees, they won't contain
3706 any bind exprs. */
3707 }
3708 cp_walk_tree (&BIND_EXPR_BODY (*stmt), register_local_var_uses, d, NULL);
3709 *do_subtree = 0; /* We've done this. */
3710 lvd->nest_depth--;
3711 }
3712 return NULL_TREE;
3713 }
3714
3715 /* Build, return FUNCTION_DECL node with its coroutine frame pointer argument
3716 for either actor or destroy functions. */
3717
3718 static tree
3719 act_des_fn (tree orig, tree fn_type, tree coro_frame_ptr, const char* name)
3720 {
3721 tree fn_name = get_fn_local_identifier (orig, name);
3722 tree fn = build_lang_decl (FUNCTION_DECL, fn_name, fn_type);
3723 DECL_CONTEXT (fn) = DECL_CONTEXT (orig);
3724 DECL_ARTIFICIAL (fn) = true;
3725 DECL_INITIAL (fn) = error_mark_node;
3726 tree id = get_identifier ("frame_ptr");
3727 tree fp = build_lang_decl (PARM_DECL, id, coro_frame_ptr);
3728 DECL_CONTEXT (fp) = fn;
3729 DECL_ARG_TYPE (fp) = type_passed_as (coro_frame_ptr);
3730 DECL_ARGUMENTS (fn) = fp;
3731 /* Copy selected attributes from the original function. */
3732 TREE_USED (fn) = TREE_USED (orig);
3733 if (DECL_SECTION_NAME (orig))
3734 set_decl_section_name (fn, DECL_SECTION_NAME (orig));
3735 /* Copy any alignment that the FE added. */
3736 if (DECL_ALIGN (orig))
3737 SET_DECL_ALIGN (fn, DECL_ALIGN (orig));
3738 /* Copy any alignment the user added. */
3739 DECL_USER_ALIGN (fn) = DECL_USER_ALIGN (orig);
3740 /* Apply attributes from the original fn. */
3741 DECL_ATTRIBUTES (fn) = copy_list (DECL_ATTRIBUTES (orig));
3742 return fn;
3743 }
3744
3745 /* Re-write the body as per [dcl.fct.def.coroutine] / 5. */
3746
3747 static tree
3748 coro_rewrite_function_body (location_t fn_start, tree fnbody,
3749 tree orig, tree resume_fn_ptr_type,
3750 tree& resume_fn_field, tree& fs_label)
3751 {
3752 /* This will be our new outer scope. */
3753 tree update_body = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
3754 tree top_block = make_node (BLOCK);
3755 BIND_EXPR_BLOCK (update_body) = top_block;
3756 BIND_EXPR_BODY (update_body) = push_stmt_list ();
3757
3758 /* If the function has a top level bind expression, then connect that
3759 after first making sure we give it a new block. */
3760 tree first = expr_first (fnbody);
3761 if (first && TREE_CODE (first) == BIND_EXPR)
3762 {
3763 tree block = BIND_EXPR_BLOCK (first);
3764 gcc_checking_assert (block);
3765 gcc_checking_assert (BLOCK_SUPERCONTEXT (block) == NULL_TREE);
3766 gcc_checking_assert (BLOCK_CHAIN (block) == NULL_TREE);
3767 /* Replace the top block to avoid issues with locations for args
3768 appearing to be in a non-existent place. */
3769 tree replace_blk = make_node (BLOCK);
3770 BLOCK_VARS (replace_blk) = BLOCK_VARS (block);
3771 BLOCK_SUBBLOCKS (replace_blk) = BLOCK_SUBBLOCKS (block);
3772 for (tree b = BLOCK_SUBBLOCKS (replace_blk); b; b = BLOCK_CHAIN (b))
3773 BLOCK_SUPERCONTEXT (b) = replace_blk;
3774 BIND_EXPR_BLOCK (first) = replace_blk;
3775 /* The top block has one child, so far, and we have now got a
3776 superblock. */
3777 BLOCK_SUPERCONTEXT (block) = top_block;
3778 BLOCK_SUBBLOCKS (top_block) = block;
3779 }
3780
3781 /* Wrap the function body in a try {} catch (...) {} block, if exceptions
3782 are enabled. */
3783 tree promise = get_coroutine_promise_proxy (orig);
3784 tree var_list = NULL_TREE;
3785 tree initial_await = build_init_or_final_await (fn_start, false);
3786
3787 /* [stmt.return.coroutine] / 3
3788 If p.return_void() is a valid expression, flowing off the end of a
3789 coroutine is equivalent to a co_return with no operand; otherwise
3790 flowing off the end of a coroutine results in undefined behavior. */
3791 tree return_void
3792 = get_coroutine_return_void_expr (current_function_decl, fn_start, false);
3793
3794 if (flag_exceptions)
3795 {
3796 /* Build promise.unhandled_exception(); */
3797 tree ueh
3798 = coro_build_promise_expression (current_function_decl, promise,
3799 coro_unhandled_exception_identifier,
3800 fn_start, NULL, /*musthave=*/true);
3801 /* Create and initialize the initial-await-resume-called variable per
3802 [dcl.fct.def.coroutine] / 5.3. */
3803 tree i_a_r_c = build_lang_decl (VAR_DECL, get_identifier ("i_a_r_c"),
3804 boolean_type_node);
3805 DECL_ARTIFICIAL (i_a_r_c) = true;
3806 DECL_CHAIN (i_a_r_c) = var_list;
3807 var_list = i_a_r_c;
3808 DECL_INITIAL (i_a_r_c) = boolean_false_node;
3809 add_decl_expr (i_a_r_c);
3810 /* Start the try-catch. */
3811 tree tcb = build_stmt (fn_start, TRY_BLOCK, NULL_TREE, NULL_TREE);
3812 add_stmt (tcb);
3813 TRY_STMTS (tcb) = push_stmt_list ();
3814 if (initial_await != error_mark_node)
3815 {
3816 /* Build a compound expression that sets the
3817 initial-await-resume-called variable true and then calls the
3818 initial suspend expression await resume. */
3819 tree vec = TREE_OPERAND (initial_await, 3);
3820 tree aw_r = TREE_VEC_ELT (vec, 2);
3821 tree update = build2 (MODIFY_EXPR, boolean_type_node, i_a_r_c,
3822 boolean_true_node);
3823 aw_r = cp_build_compound_expr (update, aw_r, tf_warning_or_error);
3824 TREE_VEC_ELT (vec, 2) = aw_r;
3825 }
3826 /* Add the initial await to the start of the user-authored function. */
3827 finish_expr_stmt (initial_await);
3828 /* Append the original function body. */
3829 add_stmt (fnbody);
3830 if (return_void)
3831 add_stmt (return_void);
3832 TRY_STMTS (tcb) = pop_stmt_list (TRY_STMTS (tcb));
3833 TRY_HANDLERS (tcb) = push_stmt_list ();
3834 /* Mimic what the parser does for the catch. */
3835 tree handler = begin_handler ();
3836 finish_handler_parms (NULL_TREE, handler); /* catch (...) */
3837
3838 /* Get the initial await resume called value. */
3839 tree not_iarc_if = begin_if_stmt ();
3840 tree not_iarc = build1_loc (fn_start, TRUTH_NOT_EXPR,
3841 boolean_type_node, i_a_r_c);
3842 finish_if_stmt_cond (not_iarc, not_iarc_if);
3843 /* If the initial await resume called value is false, rethrow... */
3844 tree rethrow = build_throw (fn_start, NULL_TREE);
3845 TREE_NO_WARNING (rethrow) = true;
3846 finish_expr_stmt (rethrow);
3847 finish_then_clause (not_iarc_if);
3848 tree iarc_scope = IF_SCOPE (not_iarc_if);
3849 IF_SCOPE (not_iarc_if) = NULL;
3850 not_iarc_if = do_poplevel (iarc_scope);
3851 add_stmt (not_iarc_if);
3852 /* ... else call the promise unhandled exception method. */
3853 ueh = maybe_cleanup_point_expr_void (ueh);
3854 add_stmt (ueh);
3855 finish_handler (handler);
3856 TRY_HANDLERS (tcb) = pop_stmt_list (TRY_HANDLERS (tcb));
3857 }
3858 else
3859 {
3860 if (pedantic)
3861 {
3862 /* We still try to look for the promise method and warn if it's not
3863 present. */
3864 tree ueh_meth
3865 = lookup_promise_method (orig, coro_unhandled_exception_identifier,
3866 fn_start, /*musthave=*/false);
3867 if (!ueh_meth || ueh_meth == error_mark_node)
3868 warning_at (fn_start, 0, "no member named %qE in %qT",
3869 coro_unhandled_exception_identifier,
3870 get_coroutine_promise_type (orig));
3871 }
3872 /* Else we don't check and don't care if the method is missing..
3873 just add the initial suspend, function and return. */
3874 finish_expr_stmt (initial_await);
3875 /* Append the original function body. */
3876 add_stmt (fnbody);
3877 if (return_void)
3878 add_stmt (return_void);
3879 }
3880
3881 /* co_return branches to the final_suspend label, so declare that now. */
3882 fs_label
3883 = create_named_label_with_ctx (fn_start, "final.suspend", NULL_TREE);
3884 add_stmt (build_stmt (fn_start, LABEL_EXPR, fs_label));
3885
3886 /* Before entering the final suspend point, we signal that this point has
3887 been reached by setting the resume function pointer to zero (this is
3888 what the 'done()' builtin tests) as per the current ABI. */
3889 resume_fn_field
3890 = build_lang_decl (VAR_DECL, get_identifier ("resume.fn.ptr.proxy"),
3891 resume_fn_ptr_type);
3892 DECL_ARTIFICIAL (resume_fn_field) = true;
3893 tree zero_resume
3894 = build1 (CONVERT_EXPR, resume_fn_ptr_type, integer_zero_node);
3895 zero_resume
3896 = build2 (INIT_EXPR, resume_fn_ptr_type, resume_fn_field, zero_resume);
3897 finish_expr_stmt (zero_resume);
3898 finish_expr_stmt (build_init_or_final_await (fn_start, true));
3899 BIND_EXPR_BODY (update_body) = pop_stmt_list (BIND_EXPR_BODY (update_body));
3900 BIND_EXPR_VARS (update_body) = nreverse (var_list);
3901 BLOCK_VARS (top_block) = BIND_EXPR_VARS (update_body);
3902
3903 return update_body;
3904 }
3905
3906 /* Here we:
3907 a) Check that the function and promise type are valid for a
3908 coroutine.
3909 b) Carry out the initial morph to create the skeleton of the
3910 coroutine ramp function and the rewritten body.
3911
3912 Assumptions.
3913
3914 1. We only hit this code once all dependencies are resolved.
3915 2. The function body will be either a bind expr or a statement list
3916 3. That cfun and current_function_decl are valid for the case we're
3917 expanding.
3918 4. 'input_location' will be of the final brace for the function.
3919
3920 We do something like this:
3921 declare a dummy coro frame.
3922 struct _R_frame {
3923 using handle_type = coro::coroutine_handle<coro1::promise_type>;
3924 void (*__resume)(_R_frame *);
3925 void (*__destroy)(_R_frame *);
3926 coro1::promise_type __p;
3927 bool frame_needs_free; free the coro frame mem if set.
3928 bool i_a_r_c; [dcl.fct.def.coroutine] / 5.3
3929 short __resume_at;
3930 handle_type self_handle;
3931 (maybe) parameter copies.
3932 (maybe) local variables saved (including awaitables)
3933 (maybe) trailing space.
3934 }; */
3935
3936 bool
3937 morph_fn_to_coro (tree orig, tree *resumer, tree *destroyer)
3938 {
3939 gcc_checking_assert (orig && TREE_CODE (orig) == FUNCTION_DECL);
3940
3941 *resumer = error_mark_node;
3942 *destroyer = error_mark_node;
3943 if (!coro_function_valid_p (orig))
3944 {
3945 /* For early errors, we do not want a diagnostic about the missing
3946 ramp return value, since the user cannot fix this - a 'return' is
3947 not allowed in a coroutine. */
3948 TREE_NO_WARNING (orig) = true;
3949 /* Discard the body, we can't process it further. */
3950 pop_stmt_list (DECL_SAVED_TREE (orig));
3951 DECL_SAVED_TREE (orig) = push_stmt_list ();
3952 return false;
3953 }
3954
3955 /* We can't validly get here with an empty statement list, since there's no
3956 way for the FE to decide it's a coroutine in the absence of any code. */
3957 tree fnbody = pop_stmt_list (DECL_SAVED_TREE (orig));
3958 gcc_checking_assert (fnbody != NULL_TREE);
3959
3960 /* We don't have the locus of the opening brace - it's filled in later (and
3961 there doesn't really seem to be any easy way to get at it).
3962 The closing brace is assumed to be input_location. */
3963 location_t fn_start = DECL_SOURCE_LOCATION (orig);
3964 gcc_rich_location fn_start_loc (fn_start);
3965
3966 /* Initial processing of the function-body.
3967 If we have no expressions or just an error then punt. */
3968 tree body_start = expr_first (fnbody);
3969 if (body_start == NULL_TREE || body_start == error_mark_node)
3970 {
3971 DECL_SAVED_TREE (orig) = push_stmt_list ();
3972 append_to_statement_list (fnbody, &DECL_SAVED_TREE (orig));
3973 /* Suppress warnings about the missing return value. */
3974 TREE_NO_WARNING (orig) = true;
3975 return false;
3976 }
3977
3978 /* So, we've tied off the original user-authored body in fn_body.
3979
3980 Start the replacement synthesized ramp body as newbody.
3981 If we encounter a fatal error we might return a now-empty body.
3982
3983 Note, the returned ramp body is not 'popped', to be compatible with
3984 the way that decl.c handles regular functions, the scope pop is done
3985 in the caller. */
3986
3987 tree newbody = push_stmt_list ();
3988 DECL_SAVED_TREE (orig) = newbody;
3989
3990 /* If our original body is noexcept, then that's what we apply to our
3991 generated ramp, transfer any MUST_NOT_THOW_EXPR to that. */
3992 bool is_noexcept = TREE_CODE (body_start) == MUST_NOT_THROW_EXPR;
3993 if (is_noexcept)
3994 {
3995 /* The function body we will continue with is the single operand to
3996 the must-not-throw. */
3997 fnbody = TREE_OPERAND (body_start, 0);
3998 /* Transfer the must-not-throw to the ramp body. */
3999 add_stmt (body_start);
4000 /* Re-start the ramp as must-not-throw. */
4001 TREE_OPERAND (body_start, 0) = push_stmt_list ();
4002 }
4003
4004 /* Create the coro frame type, as far as it can be known at this stage.
4005 1. Types we already know. */
4006
4007 tree fn_return_type = TREE_TYPE (TREE_TYPE (orig));
4008 tree handle_type = get_coroutine_handle_type (orig);
4009 tree promise_type = get_coroutine_promise_type (orig);
4010
4011 /* 2. Types we need to define or look up. */
4012
4013 tree fr_name = get_fn_local_identifier (orig, "frame");
4014 tree coro_frame_type = xref_tag (record_type, fr_name, ts_current, false);
4015 DECL_CONTEXT (TYPE_NAME (coro_frame_type)) = current_scope ();
4016 tree coro_frame_ptr = build_pointer_type (coro_frame_type);
4017 tree act_des_fn_type
4018 = build_function_type_list (void_type_node, coro_frame_ptr, NULL_TREE);
4019 tree act_des_fn_ptr = build_pointer_type (act_des_fn_type);
4020
4021 /* Declare the actor and destroyer function. */
4022 tree actor = act_des_fn (orig, act_des_fn_type, coro_frame_ptr, "actor");
4023 tree destroy = act_des_fn (orig, act_des_fn_type, coro_frame_ptr, "destroy");
4024
4025 /* Construct the wrapped function body; we will analyze this to determine
4026 the requirements for the coroutine frame. */
4027
4028 tree resume_fn_field = NULL_TREE;
4029 tree fs_label = NULL_TREE;
4030 fnbody = coro_rewrite_function_body (fn_start, fnbody, orig, act_des_fn_ptr,
4031 resume_fn_field, fs_label);
4032 /* Build our dummy coro frame layout. */
4033 coro_frame_type = begin_class_definition (coro_frame_type);
4034
4035 tree field_list = NULL_TREE;
4036 tree resume_name
4037 = coro_make_frame_entry (&field_list, "__resume",
4038 act_des_fn_ptr, fn_start);
4039 tree destroy_name
4040 = coro_make_frame_entry (&field_list, "__destroy",
4041 act_des_fn_ptr, fn_start);
4042 tree promise_name
4043 = coro_make_frame_entry (&field_list, "__p", promise_type, fn_start);
4044 tree fnf_name = coro_make_frame_entry (&field_list, "__frame_needs_free",
4045 boolean_type_node, fn_start);
4046 tree resume_idx_name
4047 = coro_make_frame_entry (&field_list, "__resume_at",
4048 short_unsigned_type_node, fn_start);
4049
4050 /* We need a handle to this coroutine, which is passed to every
4051 await_suspend(). There's no point in creating it over and over. */
4052 (void) coro_make_frame_entry (&field_list, "__self_h", handle_type, fn_start);
4053
4054 /* Now add in fields for function params (if there are any).
4055 We do not attempt elision of copies at this stage, we do analyze the
4056 uses and build worklists to replace those when the state machine is
4057 lowered. */
4058
4059 hash_map<tree, param_info> *param_uses = NULL;
4060 if (DECL_ARGUMENTS (orig))
4061 {
4062 /* Build a hash map with an entry for each param.
4063 The key is the param tree.
4064 Then we have an entry for the frame field name.
4065 Then a cache for the field ref when we come to use it.
4066 Then a tree list of the uses.
4067 The second two entries start out empty - and only get populated
4068 when we see uses. */
4069 param_uses = new hash_map<tree, param_info>;
4070 bool lambda_p = LAMBDA_FUNCTION_P (orig);
4071
4072 unsigned no_name_parm = 0;
4073 for (tree arg = DECL_ARGUMENTS (orig); arg != NULL;
4074 arg = DECL_CHAIN (arg))
4075 {
4076 bool existed;
4077 param_info &parm = param_uses->get_or_insert (arg, &existed);
4078 gcc_checking_assert (!existed);
4079 parm.body_uses = NULL;
4080 tree actual_type = TREE_TYPE (arg);
4081 actual_type = complete_type_or_else (actual_type, orig);
4082 if (actual_type == NULL_TREE)
4083 actual_type = error_mark_node;
4084 parm.orig_type = actual_type;
4085 parm.by_ref = parm.pt_ref = false;
4086 if (TREE_CODE (actual_type) == REFERENCE_TYPE)
4087 {
4088 /* If the user passes by reference, then we will save the
4089 pointer to the original. As noted in
4090 [dcl.fct.def.coroutine] / 13, if the lifetime of the
4091 referenced item ends and then the coroutine is resumed,
4092 we have UB; well, the user asked for it. */
4093 actual_type = build_pointer_type (TREE_TYPE (actual_type));
4094 parm.pt_ref = true;
4095 }
4096 else if (TYPE_REF_P (DECL_ARG_TYPE (arg)))
4097 parm.by_ref = true;
4098
4099 parm.frame_type = actual_type;
4100
4101 parm.this_ptr = is_this_parameter (arg);
4102 parm.lambda_cobj = lambda_p && DECL_NAME (arg) == closure_identifier;
4103
4104 parm.trivial_dtor = TYPE_HAS_TRIVIAL_DESTRUCTOR (parm.frame_type);
4105 char *buf;
4106 if (DECL_NAME (arg))
4107 {
4108 tree pname = DECL_NAME (arg);
4109 buf = xasprintf ("__parm.%s", IDENTIFIER_POINTER (pname));
4110 }
4111 else
4112 buf = xasprintf ("__unnamed_parm.%d", no_name_parm++);
4113 parm.field_id = coro_make_frame_entry
4114 (&field_list, buf, actual_type, DECL_SOURCE_LOCATION (arg));
4115 free (buf);
4116 }
4117
4118 /* We want to record every instance of param's use, so don't include
4119 a 'visited' hash_set on the tree walk, but only record a containing
4120 expression once. */
4121 hash_set<tree *> visited;
4122 param_frame_data param_data
4123 = {&field_list, param_uses, &visited, fn_start, false};
4124 cp_walk_tree (&fnbody, register_param_uses, &param_data, NULL);
4125 }
4126
4127 /* We need to know, and inspect, each suspend point in the function
4128 in several places. It's convenient to place this map out of line
4129 since it's used from tree walk callbacks. */
4130 suspend_points = new hash_map<tree, suspend_point_info>;
4131
4132 /* Now insert the data for any body await points, at this time we also need
4133 to promote any temporaries that are captured by reference (to regular
4134 vars) they will get added to the coro frame along with other locals. */
4135 susp_frame_data body_aw_points
4136 = {&field_list, handle_type, fs_label, NULL, NULL, 0, 0,
4137 hash_set<tree> (), NULL, NULL, 0, false, false, false};
4138 body_aw_points.block_stack = make_tree_vector ();
4139 body_aw_points.bind_stack = make_tree_vector ();
4140 body_aw_points.to_replace = make_tree_vector ();
4141 cp_walk_tree (&fnbody, await_statement_walker, &body_aw_points, NULL);
4142
4143 /* 4. Now make space for local vars, this is conservative again, and we
4144 would expect to delete unused entries later. */
4145 hash_map<tree, local_var_info> local_var_uses;
4146 local_vars_frame_data local_vars_data
4147 = {&field_list, &local_var_uses, 0, 0, fn_start, false, false};
4148 cp_walk_tree (&fnbody, register_local_var_uses, &local_vars_data, NULL);
4149
4150 /* Tie off the struct for now, so that we can build offsets to the
4151 known entries. */
4152 TYPE_FIELDS (coro_frame_type) = field_list;
4153 TYPE_BINFO (coro_frame_type) = make_tree_binfo (0);
4154 BINFO_OFFSET (TYPE_BINFO (coro_frame_type)) = size_zero_node;
4155 BINFO_TYPE (TYPE_BINFO (coro_frame_type)) = coro_frame_type;
4156
4157 coro_frame_type = finish_struct (coro_frame_type, NULL_TREE);
4158
4159 /* Ramp: */
4160 /* Now build the ramp function pieces. */
4161 tree ramp_bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
4162 add_stmt (ramp_bind);
4163 tree ramp_body = push_stmt_list ();
4164
4165 tree coro_fp = build_lang_decl (VAR_DECL, get_identifier ("coro.frameptr"),
4166 coro_frame_ptr);
4167 tree varlist = coro_fp;
4168
4169 /* Collected the scope vars we need ... only one for now. */
4170 BIND_EXPR_VARS (ramp_bind) = nreverse (varlist);
4171
4172 /* We're now going to create a new top level scope block for the ramp
4173 function. */
4174 tree top_block = make_node (BLOCK);
4175
4176 BIND_EXPR_BLOCK (ramp_bind) = top_block;
4177 BLOCK_VARS (top_block) = BIND_EXPR_VARS (ramp_bind);
4178 BLOCK_SUBBLOCKS (top_block) = NULL_TREE;
4179
4180 /* The decl_expr for the coro frame pointer, initialize to zero so that we
4181 can pass it to the IFN_CO_FRAME (since there's no way to pass a type,
4182 directly apparently). This avoids a "used uninitialized" warning. */
4183 tree zeroinit = build1 (CONVERT_EXPR, coro_frame_ptr, integer_zero_node);
4184 DECL_INITIAL (coro_fp) = zeroinit;
4185 add_decl_expr (coro_fp);
4186
4187 /* The CO_FRAME internal function is a mechanism to allow the middle end
4188 to adjust the allocation in response to optimizations. We provide the
4189 current conservative estimate of the frame size (as per the current)
4190 computed layout. */
4191 tree frame_size = TYPE_SIZE_UNIT (coro_frame_type);
4192 tree resizeable
4193 = build_call_expr_internal_loc (fn_start, IFN_CO_FRAME, size_type_node, 2,
4194 frame_size, coro_fp);
4195
4196 /* [dcl.fct.def.coroutine] / 10 (part1)
4197 The unqualified-id get_return_object_on_allocation_failure is looked up
4198 in the scope of the promise type by class member access lookup. */
4199
4200 /* We don't require this, so coro_build_promise_expression can return NULL,
4201 but, if the lookup succeeds, then the function must be usable. */
4202 tree dummy_promise = build_dummy_object (get_coroutine_promise_type (orig));
4203 tree grooaf
4204 = coro_build_promise_expression (orig, dummy_promise,
4205 coro_gro_on_allocation_fail_identifier,
4206 fn_start, NULL, /*musthave=*/false);
4207
4208 /* however, should that fail, returning an error, the later stages can't
4209 handle the erroneous expression, so we reset the call as if it was
4210 absent. */
4211 if (grooaf == error_mark_node)
4212 grooaf = NULL_TREE;
4213
4214 /* Allocate the frame, this has several possibilities:
4215 [dcl.fct.def.coroutine] / 9 (part 1)
4216 The allocation function’s name is looked up in the scope of the promise
4217 type. It's not a failure for it to be absent see part 4, below. */
4218
4219 tree nwname = ovl_op_identifier (false, NEW_EXPR);
4220 tree new_fn = NULL_TREE;
4221
4222 if (TYPE_HAS_NEW_OPERATOR (promise_type))
4223 {
4224 tree fns = lookup_promise_method (orig, nwname, fn_start,
4225 /*musthave=*/true);
4226 /* [dcl.fct.def.coroutine] / 9 (part 2)
4227 If the lookup finds an allocation function in the scope of the promise
4228 type, overload resolution is performed on a function call created by
4229 assembling an argument list. The first argument is the amount of space
4230 requested, and has type std::size_t. The succeeding arguments are
4231 those of the original function. */
4232 vec<tree, va_gc> *args = make_tree_vector ();
4233 vec_safe_push (args, resizeable); /* Space needed. */
4234
4235 for (tree arg = DECL_ARGUMENTS (orig); arg != NULL;
4236 arg = DECL_CHAIN (arg))
4237 {
4238 param_info *parm_i = param_uses->get (arg);
4239 gcc_checking_assert (parm_i);
4240 if (parm_i->this_ptr || parm_i->lambda_cobj)
4241 {
4242 /* We pass a reference to *this to the allocator lookup. */
4243 tree tt = TREE_TYPE (TREE_TYPE (arg));
4244 tree this_ref = build1 (INDIRECT_REF, tt, arg);
4245 tt = cp_build_reference_type (tt, false);
4246 this_ref = convert_to_reference (tt, this_ref, CONV_STATIC,
4247 LOOKUP_NORMAL , NULL_TREE,
4248 tf_warning_or_error);
4249 vec_safe_push (args, this_ref);
4250 }
4251 else
4252 vec_safe_push (args, arg);
4253 }
4254
4255 /* Note the function selected; we test to see if it's NOTHROW. */
4256 tree func;
4257 /* Failure is not an error for this attempt. */
4258 new_fn = build_new_method_call (dummy_promise, fns, &args, NULL,
4259 LOOKUP_NORMAL, &func, tf_none);
4260 release_tree_vector (args);
4261
4262 if (new_fn == error_mark_node)
4263 {
4264 /* [dcl.fct.def.coroutine] / 9 (part 3)
4265 If no viable function is found, overload resolution is performed
4266 again on a function call created by passing just the amount of
4267 space required as an argument of type std::size_t. */
4268 args = make_tree_vector_single (resizeable); /* Space needed. */
4269 new_fn = build_new_method_call (dummy_promise, fns, &args,
4270 NULL_TREE, LOOKUP_NORMAL, &func,
4271 tf_none);
4272 release_tree_vector (args);
4273 }
4274
4275 /* However, if the promise provides an operator new, then one of these
4276 two options must be available. */
4277 if (new_fn == error_mark_node)
4278 {
4279 error_at (fn_start, "%qE is provided by %qT but is not usable with"
4280 " the function signature %qD", nwname, promise_type, orig);
4281 new_fn = error_mark_node;
4282 }
4283 else if (grooaf && !TYPE_NOTHROW_P (TREE_TYPE (func)))
4284 error_at (fn_start, "%qE is provided by %qT but %qE is not marked"
4285 " %<throw()%> or %<noexcept%>", grooaf, promise_type, nwname);
4286 else if (!grooaf && TYPE_NOTHROW_P (TREE_TYPE (func)))
4287 warning_at (fn_start, 0, "%qE is marked %<throw()%> or %<noexcept%> but"
4288 " no usable %<get_return_object_on_allocation_failure%>"
4289 " is provided by %qT", nwname, promise_type);
4290 }
4291 else /* No operator new in the promise. */
4292 {
4293 /* [dcl.fct.def.coroutine] / 9 (part 4)
4294 If this lookup fails, the allocation function’s name is looked up in
4295 the global scope. */
4296
4297 vec<tree, va_gc> *args;
4298 /* build_operator_new_call () will insert size needed as element 0 of
4299 this, and we might need to append the std::nothrow constant. */
4300 vec_alloc (args, 2);
4301 if (grooaf)
4302 {
4303 /* [dcl.fct.def.coroutine] / 10 (part 2)
4304 If any declarations (of the get return on allocation fail) are
4305 found, then the result of a call to an allocation function used
4306 to obtain storage for the coroutine state is assumed to return
4307 nullptr if it fails to obtain storage and, if a global allocation
4308 function is selected, the ::operator new(size_t, nothrow_t) form
4309 is used. The allocation function used in this case shall have a
4310 non-throwing noexcept-specification. So we need std::nothrow. */
4311 tree std_nt = lookup_qualified_name (std_node,
4312 get_identifier ("nothrow"),
4313 LOOK_want::NORMAL,
4314 /*complain=*/true, false);
4315 if (!std_nt || std_nt == error_mark_node)
4316 error_at (fn_start, "%qE is provided by %qT but %<std::nothrow%> "
4317 "cannot be found", grooaf, promise_type);
4318 vec_safe_push (args, std_nt);
4319 }
4320
4321 /* If we get to this point, we must succeed in looking up the global
4322 operator new for the params provided. Extract a simplified version
4323 of the machinery from build_operator_new_call. This can update the
4324 frame size. */
4325 tree cookie = NULL;
4326 new_fn = build_operator_new_call (nwname, &args, &frame_size, &cookie,
4327 /*align_arg=*/NULL,
4328 /*size_check=*/NULL, /*fn=*/NULL,
4329 tf_warning_or_error);
4330 resizeable = build_call_expr_internal_loc
4331 (fn_start, IFN_CO_FRAME, size_type_node, 2, frame_size, coro_fp);
4332 /* If the operator call fails for some reason, then don't try to
4333 amend it. */
4334 if (new_fn != error_mark_node)
4335 CALL_EXPR_ARG (new_fn, 0) = resizeable;
4336
4337 release_tree_vector (args);
4338 }
4339
4340 tree allocated = build1 (CONVERT_EXPR, coro_frame_ptr, new_fn);
4341 tree r = build2 (INIT_EXPR, TREE_TYPE (coro_fp), coro_fp, allocated);
4342 r = coro_build_cvt_void_expr_stmt (r, fn_start);
4343 add_stmt (r);
4344
4345 /* If the user provided a method to return an object on alloc fail, then
4346 check the returned pointer and call the func if it's null.
4347 Otherwise, no check, and we fail for noexcept/fno-exceptions cases. */
4348
4349 if (grooaf)
4350 {
4351 /* [dcl.fct.def.coroutine] / 10 (part 3)
4352 If the allocation function returns nullptr,the coroutine returns
4353 control to the caller of the coroutine and the return value is
4354 obtained by a call to T::get_return_object_on_allocation_failure(),
4355 where T is the promise type. */
4356
4357 gcc_checking_assert (same_type_p (fn_return_type, TREE_TYPE (grooaf)));
4358 tree if_stmt = begin_if_stmt ();
4359 tree cond = build1 (CONVERT_EXPR, coro_frame_ptr, integer_zero_node);
4360 cond = build2 (EQ_EXPR, boolean_type_node, coro_fp, cond);
4361 finish_if_stmt_cond (cond, if_stmt);
4362 if (VOID_TYPE_P (fn_return_type))
4363 {
4364 /* Execute the get-return-object-on-alloc-fail call... */
4365 finish_expr_stmt (grooaf);
4366 /* ... but discard the result, since we return void. */
4367 finish_return_stmt (NULL_TREE);
4368 }
4369 else
4370 {
4371 /* Get the fallback return object. */
4372 r = build_cplus_new (fn_return_type, grooaf, tf_warning_or_error);
4373 finish_return_stmt (r);
4374 }
4375 finish_then_clause (if_stmt);
4376 finish_if_stmt (if_stmt);
4377 }
4378
4379 /* deref the frame pointer, to use in member access code. */
4380 tree deref_fp = build_x_arrow (fn_start, coro_fp, tf_warning_or_error);
4381
4382 /* For now, once allocation has succeeded we always assume that this needs
4383 destruction, there's no impl. for frame allocation elision. */
4384 tree fnf_m
4385 = lookup_member (coro_frame_type, fnf_name, 1, 0, tf_warning_or_error);
4386 tree fnf_x = build_class_member_access_expr (deref_fp, fnf_m, NULL_TREE,
4387 false, tf_warning_or_error);
4388 r = build2 (INIT_EXPR, boolean_type_node, fnf_x, boolean_true_node);
4389 r = coro_build_cvt_void_expr_stmt (r, fn_start);
4390 add_stmt (r);
4391
4392 /* Put the resumer and destroyer functions in. */
4393
4394 tree actor_addr = build1 (ADDR_EXPR, act_des_fn_ptr, actor);
4395 tree resume_m
4396 = lookup_member (coro_frame_type, resume_name,
4397 /*protect=*/1, /*want_type=*/0, tf_warning_or_error);
4398 tree resume_x = build_class_member_access_expr (deref_fp, resume_m, NULL_TREE,
4399 false, tf_warning_or_error);
4400 r = build2_loc (fn_start, INIT_EXPR, act_des_fn_ptr, resume_x, actor_addr);
4401 r = coro_build_cvt_void_expr_stmt (r, fn_start);
4402 add_stmt (r);
4403
4404 tree destroy_addr = build1 (ADDR_EXPR, act_des_fn_ptr, destroy);
4405 tree destroy_m
4406 = lookup_member (coro_frame_type, destroy_name,
4407 /*protect=*/1, /*want_type=*/0, tf_warning_or_error);
4408 tree destroy_x
4409 = build_class_member_access_expr (deref_fp, destroy_m, NULL_TREE, false,
4410 tf_warning_or_error);
4411 r = build2_loc (fn_start, INIT_EXPR, act_des_fn_ptr, destroy_x, destroy_addr);
4412 r = coro_build_cvt_void_expr_stmt (r, fn_start);
4413 add_stmt (r);
4414
4415 /* [dcl.fct.def.coroutine] /13
4416 When a coroutine is invoked, a copy is created for each coroutine
4417 parameter. Each such copy is an object with automatic storage duration
4418 that is direct-initialized from an lvalue referring to the corresponding
4419 parameter if the parameter is an lvalue reference, and from an xvalue
4420 referring to it otherwise. A reference to a parameter in the function-
4421 body of the coroutine and in the call to the coroutine promise
4422 constructor is replaced by a reference to its copy. */
4423
4424 vec<tree, va_gc> *promise_args = NULL; /* So that we can adjust refs. */
4425
4426 /* The initialization and destruction of each parameter copy occurs in the
4427 context of the called coroutine. Initializations of parameter copies are
4428 sequenced before the call to the coroutine promise constructor and
4429 indeterminately sequenced with respect to each other. The lifetime of
4430 parameter copies ends immediately after the lifetime of the coroutine
4431 promise object ends. */
4432
4433 vec<tree, va_gc> *param_dtor_list = NULL;
4434
4435 if (DECL_ARGUMENTS (orig))
4436 {
4437 promise_args = make_tree_vector ();
4438 for (tree arg = DECL_ARGUMENTS (orig); arg != NULL;
4439 arg = DECL_CHAIN (arg))
4440 {
4441 bool existed;
4442 param_info &parm = param_uses->get_or_insert (arg, &existed);
4443
4444 tree fld_ref = lookup_member (coro_frame_type, parm.field_id,
4445 /*protect=*/1, /*want_type=*/0,
4446 tf_warning_or_error);
4447 tree fld_idx
4448 = build_class_member_access_expr (deref_fp, fld_ref, NULL_TREE,
4449 false, tf_warning_or_error);
4450
4451 /* Add this to the promise CTOR arguments list, accounting for
4452 refs and special handling for method this ptr. */
4453 if (parm.this_ptr || parm.lambda_cobj)
4454 {
4455 /* We pass a reference to *this to the param preview. */
4456 tree tt = TREE_TYPE (arg);
4457 gcc_checking_assert (POINTER_TYPE_P (tt));
4458 tree ct = TREE_TYPE (tt);
4459 tree this_ref = build1 (INDIRECT_REF, ct, arg);
4460 tree rt = cp_build_reference_type (ct, false);
4461 this_ref = convert_to_reference (rt, this_ref, CONV_STATIC,
4462 LOOKUP_NORMAL , NULL_TREE,
4463 tf_warning_or_error);
4464 vec_safe_push (promise_args, this_ref);
4465 }
4466 else if (parm.by_ref)
4467 vec_safe_push (promise_args, fld_idx);
4468 else
4469 vec_safe_push (promise_args, arg);
4470
4471 if (TYPE_NEEDS_CONSTRUCTING (parm.frame_type))
4472 {
4473 vec<tree, va_gc> *p_in;
4474 if (CLASS_TYPE_P (parm.frame_type)
4475 && classtype_has_non_deleted_move_ctor (parm.frame_type))
4476 p_in = make_tree_vector_single (move (arg));
4477 else if (lvalue_p (arg))
4478 p_in = make_tree_vector_single (rvalue (arg));
4479 else
4480 p_in = make_tree_vector_single (arg);
4481 /* Construct in place or move as relevant. */
4482 r = build_special_member_call (fld_idx, complete_ctor_identifier,
4483 &p_in, parm.frame_type,
4484 LOOKUP_NORMAL,
4485 tf_warning_or_error);
4486 release_tree_vector (p_in);
4487 }
4488 else
4489 {
4490 if (!same_type_p (parm.frame_type, DECL_ARG_TYPE (arg)))
4491 r = build1_loc (DECL_SOURCE_LOCATION (arg), CONVERT_EXPR,
4492 parm.frame_type, arg);
4493 else
4494 r = arg;
4495 r = build_modify_expr (fn_start, fld_idx, parm.frame_type,
4496 INIT_EXPR, DECL_SOURCE_LOCATION (arg), r,
4497 TREE_TYPE (r));
4498 }
4499 r = coro_build_cvt_void_expr_stmt (r, fn_start);
4500 add_stmt (r);
4501 if (!parm.trivial_dtor)
4502 {
4503 if (param_dtor_list == NULL)
4504 param_dtor_list = make_tree_vector ();
4505 vec_safe_push (param_dtor_list, parm.field_id);
4506 }
4507 }
4508 }
4509
4510 /* Set up the promise. */
4511 tree promise_m
4512 = lookup_member (coro_frame_type, promise_name,
4513 /*protect=*/1, /*want_type=*/0, tf_warning_or_error);
4514
4515 tree p = build_class_member_access_expr (deref_fp, promise_m, NULL_TREE,
4516 false, tf_warning_or_error);
4517
4518 if (TYPE_NEEDS_CONSTRUCTING (promise_type))
4519 {
4520 /* Do a placement new constructor for the promise type (we never call
4521 the new operator, just the constructor on the object in place in the
4522 frame).
4523
4524 First try to find a constructor with the same parameter list as the
4525 original function (if it has params), failing that find a constructor
4526 with no parameter list. */
4527
4528 if (DECL_ARGUMENTS (orig))
4529 {
4530 r = build_special_member_call (p, complete_ctor_identifier,
4531 &promise_args, promise_type,
4532 LOOKUP_NORMAL, tf_none);
4533 release_tree_vector (promise_args);
4534 }
4535 else
4536 r = NULL_TREE;
4537
4538 if (r == NULL_TREE || r == error_mark_node)
4539 r = build_special_member_call (p, complete_ctor_identifier, NULL,
4540 promise_type, LOOKUP_NORMAL,
4541 tf_warning_or_error);
4542
4543 r = coro_build_cvt_void_expr_stmt (r, fn_start);
4544 add_stmt (r);
4545 }
4546
4547 /* Set up a new bind context for the GRO. */
4548 tree gro_context_bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
4549 /* Make and connect the scope blocks. */
4550 tree gro_block = make_node (BLOCK);
4551 BLOCK_SUPERCONTEXT (gro_block) = top_block;
4552 BLOCK_SUBBLOCKS (top_block) = gro_block;
4553 BIND_EXPR_BLOCK (gro_context_bind) = gro_block;
4554 add_stmt (gro_context_bind);
4555
4556 tree get_ro
4557 = coro_build_promise_expression (orig, p,
4558 coro_get_return_object_identifier,
4559 fn_start, NULL, /*musthave=*/true);
4560 /* Without a return object we haven't got much clue what's going on. */
4561 if (get_ro == error_mark_node)
4562 {
4563 BIND_EXPR_BODY (ramp_bind) = pop_stmt_list (ramp_body);
4564 DECL_SAVED_TREE (orig) = newbody;
4565 /* Suppress warnings about the missing return value. */
4566 TREE_NO_WARNING (orig) = true;
4567 return false;
4568 }
4569
4570 tree gro_context_body = push_stmt_list ();
4571 tree gro_type = TREE_TYPE (get_ro);
4572 bool gro_is_void_p = VOID_TYPE_P (gro_type);
4573
4574 tree gro = NULL_TREE;
4575 tree gro_bind_vars = NULL_TREE;
4576 tree gro_cleanup_stmt = NULL_TREE;
4577 /* We have to sequence the call to get_return_object before initial
4578 suspend. */
4579 if (gro_is_void_p)
4580 r = get_ro;
4581 else if (same_type_p (gro_type, fn_return_type))
4582 {
4583 /* [dcl.fct.def.coroutine] / 7
4584 The expression promise.get_return_object() is used to initialize the
4585 glvalue result or... (see below)
4586 Construct the return result directly. */
4587 if (TYPE_NEEDS_CONSTRUCTING (gro_type))
4588 {
4589 vec<tree, va_gc> *arg = make_tree_vector_single (get_ro);
4590 r = build_special_member_call (DECL_RESULT (orig),
4591 complete_ctor_identifier,
4592 &arg, gro_type, LOOKUP_NORMAL,
4593 tf_warning_or_error);
4594 release_tree_vector (arg);
4595 }
4596 else
4597 r = build2_loc (fn_start, INIT_EXPR, gro_type,
4598 DECL_RESULT (orig), get_ro);
4599 }
4600 else
4601 {
4602 /* ... or ... Construct an object that will be used as the single
4603 param to the CTOR for the return object. */
4604 gro = build_lang_decl (VAR_DECL, get_identifier ("coro.gro"), gro_type);
4605 DECL_CONTEXT (gro) = current_scope ();
4606 DECL_ARTIFICIAL (gro) = true;
4607 DECL_IGNORED_P (gro) = true;
4608 add_decl_expr (gro);
4609 gro_bind_vars = gro;
4610 if (TYPE_NEEDS_CONSTRUCTING (gro_type))
4611 {
4612 vec<tree, va_gc> *arg = make_tree_vector_single (get_ro);
4613 r = build_special_member_call (gro, complete_ctor_identifier,
4614 &arg, gro_type, LOOKUP_NORMAL,
4615 tf_warning_or_error);
4616 release_tree_vector (arg);
4617 }
4618 else
4619 r = build2_loc (fn_start, INIT_EXPR, gro_type, gro, get_ro);
4620 /* The constructed object might require a cleanup. */
4621 if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (gro_type))
4622 {
4623 tree cleanup
4624 = build_special_member_call (gro, complete_dtor_identifier,
4625 NULL, gro_type, LOOKUP_NORMAL,
4626 tf_warning_or_error);
4627 gro_cleanup_stmt = build_stmt (input_location, CLEANUP_STMT, NULL,
4628 cleanup, gro);
4629 }
4630 }
4631 finish_expr_stmt (r);
4632
4633 if (gro_cleanup_stmt)
4634 CLEANUP_BODY (gro_cleanup_stmt) = push_stmt_list ();
4635
4636 /* Initialize the resume_idx_name to 0, meaning "not started". */
4637 tree resume_idx_m
4638 = lookup_member (coro_frame_type, resume_idx_name,
4639 /*protect=*/1, /*want_type=*/0, tf_warning_or_error);
4640 tree resume_idx
4641 = build_class_member_access_expr (deref_fp, resume_idx_m, NULL_TREE, false,
4642 tf_warning_or_error);
4643 r = build_int_cst (short_unsigned_type_node, 0);
4644 r = build2_loc (fn_start, INIT_EXPR, short_unsigned_type_node, resume_idx, r);
4645 r = coro_build_cvt_void_expr_stmt (r, fn_start);
4646 add_stmt (r);
4647
4648 /* So .. call the actor .. */
4649 r = build_call_expr_loc (fn_start, actor, 1, coro_fp);
4650 r = maybe_cleanup_point_expr_void (r);
4651 add_stmt (r);
4652
4653 /* Switch to using 'input_location' as the loc, since we're now more
4654 logically doing things related to the end of the function. */
4655
4656 /* The ramp is done, we just need the return value.
4657 [dcl.fct.def.coroutine] / 7
4658 The expression promise.get_return_object() is used to initialize the
4659 glvalue result or prvalue result object of a call to a coroutine.
4660
4661 If the 'get return object' is non-void, then we built it before the
4662 promise was constructed. We now supply a reference to that var,
4663 either as the return value (if it's the same type) or to the CTOR
4664 for an object of the return type. */
4665
4666 if (same_type_p (gro_type, fn_return_type))
4667 r = gro_is_void_p ? NULL_TREE : DECL_RESULT (orig);
4668 else
4669 {
4670 if (CLASS_TYPE_P (fn_return_type))
4671 {
4672 /* For class type return objects, we can attempt to construct,
4673 even if the gro is void. */
4674 vec<tree, va_gc> *args = NULL;
4675 vec<tree, va_gc> **arglist = NULL;
4676 if (!gro_is_void_p)
4677 {
4678 args = make_tree_vector_single (rvalue (gro));
4679 arglist = &args;
4680 }
4681 r = build_special_member_call (NULL_TREE,
4682 complete_ctor_identifier, arglist,
4683 fn_return_type, LOOKUP_NORMAL,
4684 tf_warning_or_error);
4685 r = build_cplus_new (fn_return_type, r, tf_warning_or_error);
4686 if (args)
4687 release_tree_vector (args);
4688 }
4689 else if (gro_is_void_p)
4690 {
4691 /* We can't initialize a non-class return value from void. */
4692 error_at (input_location, "cannot initialize a return object of type"
4693 " %qT with an rvalue of type %<void%>", fn_return_type);
4694 r = error_mark_node;
4695 }
4696 else
4697 r = build1_loc (input_location, CONVERT_EXPR,
4698 fn_return_type, rvalue (gro));
4699 }
4700
4701 finish_return_stmt (r);
4702
4703 if (gro_cleanup_stmt)
4704 {
4705 CLEANUP_BODY (gro_cleanup_stmt)
4706 = pop_stmt_list (CLEANUP_BODY (gro_cleanup_stmt));
4707 add_stmt (gro_cleanup_stmt);
4708 }
4709
4710 /* Finish up the ramp function. */
4711 BIND_EXPR_VARS (gro_context_bind) = gro_bind_vars;
4712 BIND_EXPR_BODY (gro_context_bind) = pop_stmt_list (gro_context_body);
4713 TREE_SIDE_EFFECTS (gro_context_bind) = true;
4714 BIND_EXPR_BODY (ramp_bind) = pop_stmt_list (ramp_body);
4715 TREE_SIDE_EFFECTS (ramp_bind) = true;
4716
4717 /* Start to build the final functions.
4718
4719 We push_deferring_access_checks to avoid these routines being seen as
4720 nested by the middle end; we are doing the outlining here. */
4721
4722 push_deferring_access_checks (dk_no_check);
4723
4724 /* Build the actor... */
4725 build_actor_fn (fn_start, coro_frame_type, actor, fnbody, orig, param_uses,
4726 &local_var_uses, param_dtor_list, resume_fn_field,
4727 body_aw_points.await_number, frame_size);
4728
4729 /* Destroyer ... */
4730 build_destroy_fn (fn_start, coro_frame_type, destroy, actor);
4731
4732 pop_deferring_access_checks ();
4733
4734 DECL_SAVED_TREE (orig) = newbody;
4735 /* Link our new functions into the list. */
4736 TREE_CHAIN (destroy) = TREE_CHAIN (orig);
4737 TREE_CHAIN (actor) = destroy;
4738 TREE_CHAIN (orig) = actor;
4739
4740 *resumer = actor;
4741 *destroyer = destroy;
4742
4743 delete suspend_points;
4744 suspend_points = NULL;
4745 return true;
4746 }
4747
4748 #include "gt-cp-coroutines.h"
4749