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