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