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