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