1 /* coroutine-specific state, expansions and tests.
3 Copyright (C) 2018-2023 Free Software Foundation, Inc.
5 Contributed by Iain Sandoe <iain@sandoe.co.uk> under contract to Facebook.
7 This file is part of GCC.
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
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
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/>. */
25 #include "coretypes.h"
28 #include "stringpool.h"
30 #include "stor-layout.h"
31 #include "tree-iterator.h"
33 #include "gcc-rich-location.h"
36 static bool coro_promise_type_found_p (tree
, location_t
);
38 /* GCC C++ coroutines implementation.
40 The user authors a function that becomes a coroutine (lazily) by
41 making use of any of the co_await, co_yield or co_return keywords.
43 Unlike a regular function, where the activation record is placed on the
44 stack, and is destroyed on function exit, a coroutine has some state that
45 persists between calls - the coroutine frame (analogous to a stack frame).
47 We transform the user's function into three pieces:
48 1. A so-called ramp function, that establishes the coroutine frame and
49 begins execution of the coroutine.
50 2. An actor function that contains the state machine corresponding to the
51 user's suspend/resume structure.
52 3. A stub function that calls the actor function in 'destroy' mode.
54 The actor function is executed:
55 * from "resume point 0" by the ramp.
56 * from resume point N ( > 0 ) for handle.resume() calls.
57 * from the destroy stub for destroy point N for handle.destroy() calls.
59 The functions in this file carry out the necessary analysis of, and
60 transforms to, the AST to perform this.
62 The C++ coroutine design makes use of some helper functions that are
63 authored in a so-called "promise" class provided by the user.
65 At parse time (or post substitution) the type of the coroutine promise
66 will be determined. At that point, we can look up the required promise
67 class methods and issue diagnostics if they are missing or incorrect. To
68 avoid repeating these actions at code-gen time, we make use of temporary
69 'proxy' variables for the coroutine handle and the promise - which will
70 eventually be instantiated in the coroutine frame.
72 Each of the keywords will expand to a code sequence (although co_yield is
73 just syntactic sugar for a co_await).
75 We defer the analysis and transformation until template expansion is
76 complete so that we have complete types at that time. */
79 /* The state that we collect during parsing (and template expansion) for
82 struct GTY((for_user
)) coroutine_info
84 tree function_decl
; /* The original function decl. */
85 tree actor_decl
; /* The synthesized actor function. */
86 tree destroy_decl
; /* The synthesized destroy function. */
87 tree promise_type
; /* The cached promise type for this function. */
88 tree handle_type
; /* The cached coroutine handle for this function. */
89 tree self_h_proxy
; /* A handle instance that is used as the proxy for the
90 one that will eventually be allocated in the coroutine
92 tree promise_proxy
; /* Likewise, a proxy promise instance. */
93 tree return_void
; /* The expression for p.return_void() if it exists. */
94 location_t first_coro_keyword
; /* The location of the keyword that made this
95 function into a coroutine. */
96 /* Flags to avoid repeated errors for per-function issues. */
97 bool coro_ret_type_error_emitted
;
98 bool coro_promise_error_emitted
;
99 bool coro_co_return_error_emitted
;
102 struct coroutine_info_hasher
: ggc_ptr_hash
<coroutine_info
>
104 typedef tree compare_type
; /* We only compare the function decl. */
105 static inline hashval_t
hash (coroutine_info
*);
106 static inline hashval_t
hash (const compare_type
&);
107 static inline bool equal (coroutine_info
*, coroutine_info
*);
108 static inline bool equal (coroutine_info
*, const compare_type
&);
111 /* This table holds all the collected coroutine state for coroutines in
112 the current translation unit. */
114 static GTY (()) hash_table
<coroutine_info_hasher
> *coroutine_info_table
;
116 /* We will initialize state lazily. */
117 static bool coro_initialized
= false;
119 /* Return a hash value for the entry pointed to by INFO.
120 The compare type is a tree, but the only trees we are going use are
121 function decls. We use the DECL_UID as the hash value since that is
122 stable across PCH. */
125 coroutine_info_hasher::hash (coroutine_info
*info
)
127 return DECL_UID (info
->function_decl
);
130 /* Return a hash value for the compare value COMP. */
133 coroutine_info_hasher::hash (const compare_type
& comp
)
135 return DECL_UID (comp
);
138 /* Return true if the entries pointed to by LHS and RHS are for the
142 coroutine_info_hasher::equal (coroutine_info
*lhs
, coroutine_info
*rhs
)
144 return lhs
->function_decl
== rhs
->function_decl
;
148 coroutine_info_hasher::equal (coroutine_info
*lhs
, const compare_type
& rhs
)
150 return lhs
->function_decl
== rhs
;
153 /* Get the existing coroutine_info for FN_DECL, or insert a new one if the
154 entry does not yet exist. */
157 get_or_insert_coroutine_info (tree fn_decl
)
159 gcc_checking_assert (coroutine_info_table
!= NULL
);
161 coroutine_info
**slot
= coroutine_info_table
->find_slot_with_hash
162 (fn_decl
, coroutine_info_hasher::hash (fn_decl
), INSERT
);
166 *slot
= new (ggc_cleared_alloc
<coroutine_info
> ()) coroutine_info ();
167 (*slot
)->function_decl
= fn_decl
;
173 /* Get the existing coroutine_info for FN_DECL, fail if it doesn't exist. */
176 get_coroutine_info (tree fn_decl
)
178 if (coroutine_info_table
== NULL
)
181 coroutine_info
**slot
= coroutine_info_table
->find_slot_with_hash
182 (fn_decl
, coroutine_info_hasher::hash (fn_decl
), NO_INSERT
);
188 /* We will lazily create all the identifiers that are used by coroutines
189 on the first attempt to lookup the traits. */
191 /* Identifiers that are used by all coroutines. */
193 static GTY(()) tree coro_traits_identifier
;
194 static GTY(()) tree coro_handle_identifier
;
195 static GTY(()) tree coro_promise_type_identifier
;
197 /* Required promise method name identifiers. */
199 static GTY(()) tree coro_await_transform_identifier
;
200 static GTY(()) tree coro_initial_suspend_identifier
;
201 static GTY(()) tree coro_final_suspend_identifier
;
202 static GTY(()) tree coro_return_void_identifier
;
203 static GTY(()) tree coro_return_value_identifier
;
204 static GTY(()) tree coro_yield_value_identifier
;
205 static GTY(()) tree coro_resume_identifier
;
206 static GTY(()) tree coro_address_identifier
;
207 static GTY(()) tree coro_from_address_identifier
;
208 static GTY(()) tree coro_get_return_object_identifier
;
209 static GTY(()) tree coro_gro_on_allocation_fail_identifier
;
210 static GTY(()) tree coro_unhandled_exception_identifier
;
212 /* Awaitable methods. */
214 static GTY(()) tree coro_await_ready_identifier
;
215 static GTY(()) tree coro_await_suspend_identifier
;
216 static GTY(()) tree coro_await_resume_identifier
;
218 /* Accessors for the coroutine frame state used by the implementation. */
220 static GTY(()) tree coro_resume_fn_id
;
221 static GTY(()) tree coro_destroy_fn_id
;
222 static GTY(()) tree coro_promise_id
;
223 static GTY(()) tree coro_frame_needs_free_id
;
224 static GTY(()) tree coro_resume_index_id
;
225 static GTY(()) tree coro_self_handle_id
;
226 static GTY(()) tree coro_actor_continue_id
;
227 static GTY(()) tree coro_frame_i_a_r_c_id
;
229 /* Create the identifiers used by the coroutines library interfaces and
230 the implementation frame state. */
233 coro_init_identifiers ()
235 coro_traits_identifier
= get_identifier ("coroutine_traits");
236 coro_handle_identifier
= get_identifier ("coroutine_handle");
237 coro_promise_type_identifier
= get_identifier ("promise_type");
239 coro_await_transform_identifier
= get_identifier ("await_transform");
240 coro_initial_suspend_identifier
= get_identifier ("initial_suspend");
241 coro_final_suspend_identifier
= get_identifier ("final_suspend");
242 coro_return_void_identifier
= get_identifier ("return_void");
243 coro_return_value_identifier
= get_identifier ("return_value");
244 coro_yield_value_identifier
= get_identifier ("yield_value");
245 coro_resume_identifier
= get_identifier ("resume");
246 coro_address_identifier
= get_identifier ("address");
247 coro_from_address_identifier
= get_identifier ("from_address");
248 coro_get_return_object_identifier
= get_identifier ("get_return_object");
249 coro_gro_on_allocation_fail_identifier
=
250 get_identifier ("get_return_object_on_allocation_failure");
251 coro_unhandled_exception_identifier
= get_identifier ("unhandled_exception");
253 coro_await_ready_identifier
= get_identifier ("await_ready");
254 coro_await_suspend_identifier
= get_identifier ("await_suspend");
255 coro_await_resume_identifier
= get_identifier ("await_resume");
257 /* Coroutine state frame field accessors. */
258 coro_resume_fn_id
= get_identifier ("_Coro_resume_fn");
259 coro_destroy_fn_id
= get_identifier ("_Coro_destroy_fn");
260 coro_promise_id
= get_identifier ("_Coro_promise");
261 coro_frame_needs_free_id
= get_identifier ("_Coro_frame_needs_free");
262 coro_frame_i_a_r_c_id
= get_identifier ("_Coro_initial_await_resume_called");
263 coro_resume_index_id
= get_identifier ("_Coro_resume_index");
264 coro_self_handle_id
= get_identifier ("_Coro_self_handle");
265 coro_actor_continue_id
= get_identifier ("_Coro_actor_continue");
268 /* Trees we only need to set up once. */
270 static GTY(()) tree coro_traits_templ
;
271 static GTY(()) tree coro_handle_templ
;
272 static GTY(()) tree void_coro_handle_type
;
274 /* ================= Parse, Semantics and Type checking ================= */
276 /* This initial set of routines are helper for the parsing and template
279 At the completion of this, we will have completed trees for each of the
280 keywords, but making use of proxy variables for the self-handle and the
281 promise class instance. */
283 /* [coroutine.traits]
284 Lookup the coroutine_traits template decl. */
287 find_coro_traits_template_decl (location_t kw
)
289 /* If we are missing fundamental information, such as the traits, (or the
290 declaration found is not a type template), then don't emit an error for
291 every keyword in a TU, just do it once. */
292 static bool traits_error_emitted
= false;
294 tree traits_decl
= lookup_qualified_name (std_node
, coro_traits_identifier
,
296 /*complain=*/!traits_error_emitted
);
297 if (traits_decl
== error_mark_node
298 || !DECL_TYPE_TEMPLATE_P (traits_decl
))
300 if (!traits_error_emitted
)
302 gcc_rich_location
richloc (kw
);
303 error_at (&richloc
, "coroutines require a traits template; cannot"
304 " find %<%E::%E%>", std_node
, coro_traits_identifier
);
305 inform (&richloc
, "perhaps %<#include <coroutine>%> is missing");
306 traits_error_emitted
= true;
314 /* Instantiate Coroutine traits for the function signature. */
317 instantiate_coro_traits (tree fndecl
, location_t kw
)
319 /* [coroutine.traits.primary]
320 So now build up a type list for the template <typename _R, typename...>.
321 The types are the function's arg types and _R is the function return
324 tree functyp
= TREE_TYPE (fndecl
);
325 tree arg
= DECL_ARGUMENTS (fndecl
);
326 tree arg_node
= TYPE_ARG_TYPES (functyp
);
327 tree argtypes
= make_tree_vec (list_length (arg_node
)-1);
330 while (arg_node
!= NULL_TREE
&& !VOID_TYPE_P (TREE_VALUE (arg_node
)))
332 if (is_this_parameter (arg
)
333 || DECL_NAME (arg
) == closure_identifier
)
335 /* We pass a reference to *this to the param preview. */
336 tree ct
= TREE_TYPE (TREE_TYPE (arg
));
337 TREE_VEC_ELT (argtypes
, p
++) = cp_build_reference_type (ct
, false);
340 TREE_VEC_ELT (argtypes
, p
++) = TREE_VALUE (arg_node
);
342 arg_node
= TREE_CHAIN (arg_node
);
343 arg
= DECL_CHAIN (arg
);
346 tree argtypepack
= cxx_make_type (TYPE_ARGUMENT_PACK
);
347 ARGUMENT_PACK_ARGS (argtypepack
) = argtypes
;
349 tree targ
= make_tree_vec (2);
350 TREE_VEC_ELT (targ
, 0) = TREE_TYPE (functyp
);
351 TREE_VEC_ELT (targ
, 1) = argtypepack
;
354 = lookup_template_class (coro_traits_templ
, targ
,
355 /*in_decl=*/NULL_TREE
, /*context=*/NULL_TREE
,
356 /*entering scope=*/false, tf_warning_or_error
);
358 if (traits_class
== error_mark_node
)
360 error_at (kw
, "cannot instantiate %<coroutine traits%>");
367 /* [coroutine.handle] */
370 find_coro_handle_template_decl (location_t kw
)
372 /* As for the coroutine traits, this error is per TU, so only emit
374 static bool coro_handle_error_emitted
= false;
375 tree handle_decl
= lookup_qualified_name (std_node
, coro_handle_identifier
,
377 !coro_handle_error_emitted
);
378 if (handle_decl
== error_mark_node
379 || !DECL_CLASS_TEMPLATE_P (handle_decl
))
381 if (!coro_handle_error_emitted
)
382 error_at (kw
, "coroutines require a handle class template;"
383 " cannot find %<%E::%E%>", std_node
, coro_handle_identifier
);
384 coro_handle_error_emitted
= true;
391 /* Instantiate the handle template for a given promise type. */
394 instantiate_coro_handle_for_promise_type (location_t kw
, tree promise_type
)
396 /* So now build up a type list for the template, one entry, the promise. */
397 tree targ
= make_tree_vec (1);
398 TREE_VEC_ELT (targ
, 0) = promise_type
;
400 = lookup_template_class (coro_handle_identifier
, targ
,
401 /* in_decl=*/NULL_TREE
,
402 /* context=*/std_node
,
403 /* entering scope=*/false, tf_warning_or_error
);
405 if (handle_type
== error_mark_node
)
407 error_at (kw
, "cannot instantiate a %<coroutine handle%> for"
408 " promise type %qT", promise_type
);
415 /* Look for the promise_type in the instantiated traits. */
418 find_promise_type (tree traits_class
)
421 = lookup_member (traits_class
, coro_promise_type_identifier
,
422 /* protect=*/1, /*want_type=*/true, tf_warning_or_error
);
426 = complete_type_or_else (TREE_TYPE (promise_type
), promise_type
);
428 /* NULL_TREE on fail. */
433 coro_promise_type_found_p (tree fndecl
, location_t loc
)
435 gcc_assert (fndecl
!= NULL_TREE
);
437 if (!coro_initialized
)
439 /* Trees we only need to create once.
440 Set up the identifiers we will use. */
441 coro_init_identifiers ();
443 /* Coroutine traits template. */
444 coro_traits_templ
= find_coro_traits_template_decl (loc
);
445 if (coro_traits_templ
== NULL_TREE
)
448 /* coroutine_handle<> template. */
449 coro_handle_templ
= find_coro_handle_template_decl (loc
);
450 if (coro_handle_templ
== NULL_TREE
)
453 /* We can also instantiate the void coroutine_handle<> */
454 void_coro_handle_type
=
455 instantiate_coro_handle_for_promise_type (loc
, NULL_TREE
);
456 if (void_coro_handle_type
== NULL_TREE
)
459 /* A table to hold the state, per coroutine decl. */
460 gcc_checking_assert (coroutine_info_table
== NULL
);
461 coroutine_info_table
=
462 hash_table
<coroutine_info_hasher
>::create_ggc (11);
464 if (coroutine_info_table
== NULL
)
467 coro_initialized
= true;
470 /* Save the coroutine data on the side to avoid the overhead on every
471 function decl tree. */
473 coroutine_info
*coro_info
= get_or_insert_coroutine_info (fndecl
);
474 /* Without this, we cannot really proceed. */
475 gcc_checking_assert (coro_info
);
477 /* If we don't already have a current promise type, try to look it up. */
478 if (coro_info
->promise_type
== NULL_TREE
)
480 /* Get the coroutine traits template class instance for the function
481 signature we have - coroutine_traits <R, ...> */
483 tree templ_class
= instantiate_coro_traits (fndecl
, loc
);
485 /* Find the promise type for that. */
486 coro_info
->promise_type
= find_promise_type (templ_class
);
488 /* If we don't find it, punt on the rest. */
489 if (coro_info
->promise_type
== NULL_TREE
)
491 if (!coro_info
->coro_promise_error_emitted
)
492 error_at (loc
, "unable to find the promise type for"
494 coro_info
->coro_promise_error_emitted
= true;
498 /* Test for errors in the promise type that can be determined now. */
499 tree has_ret_void
= lookup_member (coro_info
->promise_type
,
500 coro_return_void_identifier
,
501 /*protect=*/1, /*want_type=*/0,
503 tree has_ret_val
= lookup_member (coro_info
->promise_type
,
504 coro_return_value_identifier
,
505 /*protect=*/1, /*want_type=*/0,
507 if (has_ret_void
&& has_ret_val
)
509 location_t ploc
= DECL_SOURCE_LOCATION (fndecl
);
510 if (!coro_info
->coro_co_return_error_emitted
)
511 error_at (ploc
, "the coroutine promise type %qT declares both"
512 " %<return_value%> and %<return_void%>",
513 coro_info
->promise_type
);
514 inform (DECL_SOURCE_LOCATION (BASELINK_FUNCTIONS (has_ret_void
)),
515 "%<return_void%> declared here");
516 has_ret_val
= BASELINK_FUNCTIONS (has_ret_val
);
517 const char *message
= "%<return_value%> declared here";
518 if (TREE_CODE (has_ret_val
) == OVERLOAD
)
520 has_ret_val
= OVL_FIRST (has_ret_val
);
521 message
= "%<return_value%> first declared here";
523 inform (DECL_SOURCE_LOCATION (has_ret_val
), message
);
524 coro_info
->coro_co_return_error_emitted
= true;
528 /* Try to find the handle type for the promise. */
530 instantiate_coro_handle_for_promise_type (loc
, coro_info
->promise_type
);
531 if (handle_type
== NULL_TREE
)
534 /* Complete this, we're going to use it. */
535 coro_info
->handle_type
= complete_type_or_else (handle_type
, fndecl
);
537 /* Diagnostic would be emitted by complete_type_or_else. */
538 if (!coro_info
->handle_type
)
541 /* Build a proxy for a handle to "self" as the param to
542 await_suspend() calls. */
543 coro_info
->self_h_proxy
544 = build_lang_decl (VAR_DECL
, coro_self_handle_id
,
545 coro_info
->handle_type
);
547 /* Build a proxy for the promise so that we can perform lookups. */
548 coro_info
->promise_proxy
549 = build_lang_decl (VAR_DECL
, coro_promise_id
,
550 coro_info
->promise_type
);
552 /* Note where we first saw a coroutine keyword. */
553 coro_info
->first_coro_keyword
= loc
;
559 /* Map from actor or destroyer to ramp. */
560 static GTY(()) hash_map
<tree
, tree
> *to_ramp
;
562 /* Given a tree that is an actor or destroy, find the ramp function. */
565 coro_get_ramp_function (tree decl
)
569 tree
*p
= to_ramp
->get (decl
);
575 /* Given the DECL for a ramp function (the user's original declaration) return
576 the actor function if it has been defined. */
579 coro_get_actor_function (tree decl
)
581 if (coroutine_info
*info
= get_coroutine_info (decl
))
582 return info
->actor_decl
;
587 /* Given the DECL for a ramp function (the user's original declaration) return
588 the destroy function if it has been defined. */
591 coro_get_destroy_function (tree decl
)
593 if (coroutine_info
*info
= get_coroutine_info (decl
))
594 return info
->destroy_decl
;
599 /* These functions assumes that the caller has verified that the state for
600 the decl has been initialized, we try to minimize work here. */
603 get_coroutine_promise_type (tree decl
)
605 if (coroutine_info
*info
= get_coroutine_info (decl
))
606 return info
->promise_type
;
612 get_coroutine_handle_type (tree decl
)
614 if (coroutine_info
*info
= get_coroutine_info (decl
))
615 return info
->handle_type
;
621 get_coroutine_self_handle_proxy (tree decl
)
623 if (coroutine_info
*info
= get_coroutine_info (decl
))
624 return info
->self_h_proxy
;
630 get_coroutine_promise_proxy (tree decl
)
632 if (coroutine_info
*info
= get_coroutine_info (decl
))
633 return info
->promise_proxy
;
639 lookup_promise_method (tree fndecl
, tree member_id
, location_t loc
,
642 tree promise
= get_coroutine_promise_type (fndecl
);
644 = lookup_member (promise
, member_id
,
645 /*protect=*/1, /*want_type=*/0, tf_warning_or_error
);
646 if (musthave
&& pm_memb
== NULL_TREE
)
648 error_at (loc
, "no member named %qE in %qT", member_id
, promise
);
649 return error_mark_node
;
654 /* Build an expression of the form p.method (args) where the p is a promise
655 object for the current coroutine.
656 OBJECT is the promise object instance to use, it may be NULL, in which case
657 we will use the promise_proxy instance for this coroutine.
658 ARGS may be NULL, for empty parm lists. */
661 coro_build_promise_expression (tree fn
, tree promise_obj
, tree member_id
,
662 location_t loc
, vec
<tree
, va_gc
> **args
,
665 tree meth
= lookup_promise_method (fn
, member_id
, loc
, musthave
);
666 if (meth
== error_mark_node
)
667 return error_mark_node
;
669 /* If we don't find it, and it isn't needed, an empty return is OK. */
674 = promise_obj
? promise_obj
675 : get_coroutine_promise_proxy (current_function_decl
);
677 if (BASELINK_P (meth
))
678 expr
= build_new_method_call (promise
, meth
, args
, NULL_TREE
,
679 LOOKUP_NORMAL
, NULL
, tf_warning_or_error
);
682 expr
= build_class_member_access_expr (promise
, meth
, NULL_TREE
,
683 true, tf_warning_or_error
);
684 vec
<tree
, va_gc
> *real_args
;
686 real_args
= make_tree_vector ();
689 expr
= build_op_call (expr
, &real_args
, tf_warning_or_error
);
694 /* Caching get for the expression p.return_void (). */
697 get_coroutine_return_void_expr (tree decl
, location_t loc
, bool musthave
)
699 if (coroutine_info
*info
= get_coroutine_info (decl
))
701 /* If we don't have it try to build it. */
702 if (!info
->return_void
)
704 = coro_build_promise_expression (current_function_decl
, NULL
,
705 coro_return_void_identifier
,
706 loc
, NULL
, musthave
);
707 /* Don't return an error if it's an optional call. */
708 if (!musthave
&& info
->return_void
== error_mark_node
)
710 return info
->return_void
;
712 return musthave
? error_mark_node
: NULL_TREE
;
715 /* Lookup an Awaitable member, which should be await_ready, await_suspend
719 lookup_awaitable_member (tree await_type
, tree member_id
, location_t loc
)
722 = lookup_member (await_type
, member_id
,
723 /*protect=*/1, /*want_type=*/0, tf_warning_or_error
);
724 if (aw_memb
== NULL_TREE
)
726 error_at (loc
, "no member named %qE in %qT", member_id
, await_type
);
727 return error_mark_node
;
732 /* Here we check the constraints that are common to all keywords (since the
733 presence of a coroutine keyword makes the function into a coroutine). */
736 coro_common_keyword_context_valid_p (tree fndecl
, location_t kw_loc
,
739 if (fndecl
== NULL_TREE
)
741 error_at (kw_loc
, "%qs cannot be used outside a function", kw_name
);
745 /* This is arranged in order of prohibitions in the std. */
746 if (DECL_MAIN_P (fndecl
))
748 /* [basic.start.main] 3. The function main shall not be a coroutine. */
749 error_at (kw_loc
, "%qs cannot be used in the %<main%> function",
754 if (DECL_DECLARED_CONSTEXPR_P (fndecl
))
756 cp_function_chain
->invalid_constexpr
= true;
757 if (!is_instantiation_of_constexpr (fndecl
))
759 /* [dcl.constexpr] 3.3 it shall not be a coroutine. */
760 error_at (kw_loc
, "%qs cannot be used in a %<constexpr%> function",
766 if (FNDECL_USED_AUTO (fndecl
))
768 /* [dcl.spec.auto] 15. A function declared with a return type that uses
769 a placeholder type shall not be a coroutine. */
771 "%qs cannot be used in a function with a deduced return type",
776 if (varargs_function_p (fndecl
))
778 /* [dcl.fct.def.coroutine] The parameter-declaration-clause of the
779 coroutine shall not terminate with an ellipsis that is not part
780 of a parameter-declaration. */
782 "%qs cannot be used in a varargs function", kw_name
);
786 if (DECL_CONSTRUCTOR_P (fndecl
))
788 /* [class.ctor] 7. a constructor shall not be a coroutine. */
789 error_at (kw_loc
, "%qs cannot be used in a constructor", kw_name
);
793 if (DECL_DESTRUCTOR_P (fndecl
))
795 /* [class.dtor] 21. a destructor shall not be a coroutine. */
796 error_at (kw_loc
, "%qs cannot be used in a destructor", kw_name
);
803 /* Here we check the constraints that are not per keyword. */
806 coro_function_valid_p (tree fndecl
)
808 location_t f_loc
= DECL_SOURCE_LOCATION (fndecl
);
810 /* For cases where fundamental information cannot be found, e.g. the
811 coroutine traits are missing, we need to punt early. */
812 if (!coro_promise_type_found_p (fndecl
, f_loc
))
815 /* Since we think the function is a coroutine, that implies we parsed
816 a keyword that triggered this. Keywords check promise validity for
817 their context and thus the promise type should be known at this point. */
818 if (get_coroutine_handle_type (fndecl
) == NULL_TREE
819 || get_coroutine_promise_type (fndecl
) == NULL_TREE
)
822 if (current_function_returns_value
|| current_function_returns_null
)
824 /* TODO: record or extract positions of returns (and the first coro
825 keyword) so that we can add notes to the diagnostic about where
826 the bad keyword is and what made the function into a coro. */
827 error_at (f_loc
, "a %<return%> statement is not allowed in coroutine;"
828 " did you mean %<co_return%>?");
835 enum suspend_point_kind
{
836 CO_AWAIT_SUSPEND_POINT
= 0,
837 CO_YIELD_SUSPEND_POINT
,
838 INITIAL_SUSPEND_POINT
,
842 /* Helper function to build a named variable for the temps we use for each
843 await point. The root of the name is determined by SUSPEND_KIND, and
844 the variable is of type V_TYPE. The awaitable number is reset each time
845 we encounter a final suspend. */
848 get_awaitable_var (suspend_point_kind suspend_kind
, tree v_type
)
852 switch (suspend_kind
)
854 default: buf
= xasprintf ("Aw%d", awn
++); break;
855 case CO_YIELD_SUSPEND_POINT
: buf
= xasprintf ("Yd%d", awn
++); break;
856 case INITIAL_SUSPEND_POINT
: buf
= xasprintf ("Is"); break;
857 case FINAL_SUSPEND_POINT
: buf
= xasprintf ("Fs"); awn
= 0; break;
859 tree ret
= get_identifier (buf
);
861 ret
= build_lang_decl (VAR_DECL
, ret
, v_type
);
862 DECL_ARTIFICIAL (ret
) = true;
866 /* Helpers to diagnose missing noexcept on final await expressions. */
869 coro_diagnose_throwing_fn (tree fndecl
)
871 if (!TYPE_NOTHROW_P (TREE_TYPE (fndecl
)))
873 location_t f_loc
= cp_expr_loc_or_loc (fndecl
,
874 DECL_SOURCE_LOCATION (fndecl
));
875 error_at (f_loc
, "the expression %qE is required to be non-throwing",
877 inform (f_loc
, "must be declared with %<noexcept(true)%>");
884 coro_diagnose_throwing_final_aw_expr (tree expr
)
886 if (TREE_CODE (expr
) == TARGET_EXPR
)
887 expr
= TARGET_EXPR_INITIAL (expr
);
889 if (TREE_CODE (expr
) == CALL_EXPR
)
890 fn
= CALL_EXPR_FN (expr
);
891 else if (TREE_CODE (expr
) == AGGR_INIT_EXPR
)
892 fn
= AGGR_INIT_EXPR_FN (expr
);
893 else if (TREE_CODE (expr
) == CONSTRUCTOR
)
897 gcc_checking_assert (0 && "unhandled expression type");
900 fn
= TREE_OPERAND (fn
, 0);
901 return coro_diagnose_throwing_fn (fn
);
904 /* This performs [expr.await] bullet 3.3 and validates the interface obtained.
905 It is also used to build the initial and final suspend points.
907 'a', 'o' and 'e' are used as per the description in the section noted.
909 A, the original yield/await expr, is found at source location LOC.
911 We will be constructing a CO_AWAIT_EXPR for a suspend point of one of
912 the four suspend_point_kind kinds. This is indicated by SUSPEND_KIND. */
915 build_co_await (location_t loc
, tree a
, suspend_point_kind suspend_kind
)
917 /* Try and overload of operator co_await, .... */
919 if (MAYBE_CLASS_TYPE_P (TREE_TYPE (a
)))
921 o
= build_new_op (loc
, CO_AWAIT_EXPR
, LOOKUP_NORMAL
, a
, NULL_TREE
,
922 NULL_TREE
, NULL_TREE
, NULL
, tf_warning_or_error
);
923 /* If no viable functions are found, o is a. */
924 if (!o
|| o
== error_mark_node
)
926 else if (flag_exceptions
&& suspend_kind
== FINAL_SUSPEND_POINT
)
928 /* We found an overload for co_await(), diagnose throwing cases. */
929 if (TREE_CODE (o
) == TARGET_EXPR
930 && coro_diagnose_throwing_final_aw_expr (o
))
931 return error_mark_node
;
933 /* We now know that the final suspend object is distinct from the
934 final awaiter, so check for a non-throwing DTOR where needed. */
935 tree a_type
= TREE_TYPE (a
);
936 if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (a_type
))
938 = build_special_member_call (a
, complete_dtor_identifier
,
939 NULL
, a_type
, LOOKUP_NORMAL
,
942 if (CONVERT_EXPR_P (dummy
))
943 dummy
= TREE_OPERAND (dummy
, 0);
944 dummy
= TREE_OPERAND (CALL_EXPR_FN (dummy
), 0);
945 if (coro_diagnose_throwing_fn (dummy
))
946 return error_mark_node
;
951 o
= a
; /* This is most likely about to fail anyway. */
953 tree o_type
= TREE_TYPE (o
);
954 if (o_type
&& !VOID_TYPE_P (o_type
))
955 o_type
= complete_type_or_else (o_type
, o
);
958 return error_mark_node
;
960 if (TREE_CODE (o_type
) != RECORD_TYPE
)
962 error_at (loc
, "awaitable type %qT is not a structure",
964 return error_mark_node
;
967 /* Check for required awaitable members and their types. */
969 = lookup_awaitable_member (o_type
, coro_await_ready_identifier
, loc
);
970 if (!awrd_meth
|| awrd_meth
== error_mark_node
)
971 return error_mark_node
;
973 = lookup_awaitable_member (o_type
, coro_await_suspend_identifier
, loc
);
974 if (!awsp_meth
|| awsp_meth
== error_mark_node
)
975 return error_mark_node
;
977 /* The type of the co_await is the return type of the awaitable's
978 await_resume, so we need to look that up. */
980 = lookup_awaitable_member (o_type
, coro_await_resume_identifier
, loc
);
981 if (!awrs_meth
|| awrs_meth
== error_mark_node
)
982 return error_mark_node
;
984 /* To complete the lookups, we need an instance of 'e' which is built from
985 'o' according to [expr.await] 3.4.
987 If we need to materialize this as a temporary, then that will have to be
988 'promoted' to a coroutine frame var. However, if the awaitable is a
989 user variable, parameter or comes from a scope outside this function,
990 then we must use it directly - or we will see unnecessary copies.
992 If o is a variable, find the underlying var. */
993 tree e_proxy
= STRIP_NOPS (o
);
994 if (INDIRECT_REF_P (e_proxy
))
995 e_proxy
= TREE_OPERAND (e_proxy
, 0);
996 while (TREE_CODE (e_proxy
) == COMPONENT_REF
)
998 e_proxy
= TREE_OPERAND (e_proxy
, 0);
999 if (INDIRECT_REF_P (e_proxy
))
1000 e_proxy
= TREE_OPERAND (e_proxy
, 0);
1001 if (TREE_CODE (e_proxy
) == CALL_EXPR
)
1003 /* We could have operator-> here too. */
1004 tree op
= TREE_OPERAND (CALL_EXPR_FN (e_proxy
), 0);
1005 if (DECL_OVERLOADED_OPERATOR_P (op
)
1006 && DECL_OVERLOADED_OPERATOR_IS (op
, COMPONENT_REF
))
1008 e_proxy
= CALL_EXPR_ARG (e_proxy
, 0);
1009 STRIP_NOPS (e_proxy
);
1010 gcc_checking_assert (TREE_CODE (e_proxy
) == ADDR_EXPR
);
1011 e_proxy
= TREE_OPERAND (e_proxy
, 0);
1014 STRIP_NOPS (e_proxy
);
1017 /* Only build a temporary if we need it. */
1018 STRIP_NOPS (e_proxy
);
1019 if (TREE_CODE (e_proxy
) == PARM_DECL
1020 || (VAR_P (e_proxy
) && !is_local_temp (e_proxy
)))
1023 o
= NULL_TREE
; /* The var is already present. */
1027 tree p_type
= o_type
;
1029 p_type
= cp_build_reference_type (p_type
, !lvalue_p (o
));
1030 e_proxy
= get_awaitable_var (suspend_kind
, p_type
);
1031 o
= cp_build_modify_expr (loc
, e_proxy
, INIT_EXPR
, o
,
1032 tf_warning_or_error
);
1033 e_proxy
= convert_from_reference (e_proxy
);
1036 /* I suppose we could check that this is contextually convertible to bool. */
1037 tree awrd_func
= NULL_TREE
;
1039 = build_new_method_call (e_proxy
, awrd_meth
, NULL
, NULL_TREE
, LOOKUP_NORMAL
,
1040 &awrd_func
, tf_warning_or_error
);
1042 if (!awrd_func
|| !awrd_call
|| awrd_call
== error_mark_node
)
1043 return error_mark_node
;
1045 /* The suspend method may return one of three types:
1046 1. void (no special action needed).
1047 2. bool (if true, we don't need to suspend).
1048 3. a coroutine handle, we execute the handle.resume() call. */
1049 tree awsp_func
= NULL_TREE
;
1050 tree h_proxy
= get_coroutine_self_handle_proxy (current_function_decl
);
1051 vec
<tree
, va_gc
> *args
= make_tree_vector_single (h_proxy
);
1053 = build_new_method_call (e_proxy
, awsp_meth
, &args
, NULL_TREE
,
1054 LOOKUP_NORMAL
, &awsp_func
, tf_warning_or_error
);
1056 release_tree_vector (args
);
1057 if (!awsp_func
|| !awsp_call
|| awsp_call
== error_mark_node
)
1058 return error_mark_node
;
1061 tree susp_return_type
= TREE_TYPE (TREE_TYPE (awsp_func
));
1062 if (same_type_p (susp_return_type
, void_type_node
))
1064 else if (same_type_p (susp_return_type
, boolean_type_node
))
1066 else if (TREE_CODE (susp_return_type
) == RECORD_TYPE
1067 && CLASS_TYPE_P (susp_return_type
)
1068 && CLASSTYPE_TEMPLATE_INFO (susp_return_type
))
1070 tree tt
= CLASSTYPE_TI_TEMPLATE (susp_return_type
);
1071 if (tt
== coro_handle_templ
)
1077 error_at (loc
, "%<await_suspend%> must return %<void%>, %<bool%> or"
1078 " a coroutine handle");
1079 return error_mark_node
;
1082 /* Finally, the type of e.await_resume() is the co_await's type. */
1083 tree awrs_func
= NULL_TREE
;
1085 = build_new_method_call (e_proxy
, awrs_meth
, NULL
, NULL_TREE
, LOOKUP_NORMAL
,
1086 &awrs_func
, tf_warning_or_error
);
1088 if (!awrs_func
|| !awrs_call
|| awrs_call
== error_mark_node
)
1089 return error_mark_node
;
1091 if (flag_exceptions
&& suspend_kind
== FINAL_SUSPEND_POINT
)
1093 if (coro_diagnose_throwing_fn (awrd_func
))
1094 return error_mark_node
;
1095 if (coro_diagnose_throwing_fn (awsp_func
))
1096 return error_mark_node
;
1097 if (coro_diagnose_throwing_fn (awrs_func
))
1098 return error_mark_node
;
1099 if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (o_type
))
1101 = build_special_member_call (e_proxy
, complete_dtor_identifier
,
1102 NULL
, o_type
, LOOKUP_NORMAL
,
1105 if (CONVERT_EXPR_P (dummy
))
1106 dummy
= TREE_OPERAND (dummy
, 0);
1107 dummy
= TREE_OPERAND (CALL_EXPR_FN (dummy
), 0);
1108 if (coro_diagnose_throwing_fn (dummy
))
1109 return error_mark_node
;
1113 /* We now have three call expressions, in terms of the promise, handle and
1114 'e' proxies. Save them in the await expression for later expansion. */
1116 tree awaiter_calls
= make_tree_vec (3);
1117 TREE_VEC_ELT (awaiter_calls
, 0) = awrd_call
; /* await_ready(). */
1118 TREE_VEC_ELT (awaiter_calls
, 1) = awsp_call
; /* await_suspend(). */
1119 tree te
= NULL_TREE
;
1120 if (TREE_CODE (awrs_call
) == TARGET_EXPR
)
1123 awrs_call
= TREE_OPERAND (awrs_call
, 1);
1125 TREE_VEC_ELT (awaiter_calls
, 2) = awrs_call
; /* await_resume(). */
1127 if (REFERENCE_REF_P (e_proxy
))
1128 e_proxy
= TREE_OPERAND (e_proxy
, 0);
1130 tree await_expr
= build5_loc (loc
, CO_AWAIT_EXPR
,
1131 TREE_TYPE (TREE_TYPE (awrs_func
)),
1132 a
, e_proxy
, o
, awaiter_calls
,
1133 build_int_cst (integer_type_node
,
1134 (int) suspend_kind
));
1135 TREE_SIDE_EFFECTS (await_expr
) = true;
1138 TREE_OPERAND (te
, 1) = await_expr
;
1139 TREE_SIDE_EFFECTS (te
) = true;
1142 SET_EXPR_LOCATION (await_expr
, loc
);
1143 return convert_from_reference (await_expr
);
1147 finish_co_await_expr (location_t kw
, tree expr
)
1149 if (!expr
|| error_operand_p (expr
))
1150 return error_mark_node
;
1152 if (!coro_common_keyword_context_valid_p (current_function_decl
, kw
,
1154 return error_mark_node
;
1156 /* The current function has now become a coroutine, if it wasn't already. */
1157 DECL_COROUTINE_P (current_function_decl
) = 1;
1159 /* This function will appear to have no return statement, even if it
1160 is declared to return non-void (most likely). This is correct - we
1161 synthesize the return for the ramp in the compiler. So suppress any
1162 extraneous warnings during substitution. */
1163 suppress_warning (current_function_decl
, OPT_Wreturn_type
);
1165 /* Defer expansion when we are processing a template.
1166 FIXME: If the coroutine function's type is not dependent, and the operand
1167 is not dependent, we should determine the type of the co_await expression
1168 using the DEPENDENT_EXPR wrapper machinery. That allows us to determine
1169 the subexpression type, but leave its operand unchanged and then
1170 instantiate it later. */
1171 if (processing_template_decl
)
1173 tree aw_expr
= build5_loc (kw
, CO_AWAIT_EXPR
, unknown_type_node
, expr
,
1174 NULL_TREE
, NULL_TREE
, NULL_TREE
,
1176 TREE_SIDE_EFFECTS (aw_expr
) = true;
1180 /* We must be able to look up the "await_transform" method in the scope of
1181 the promise type, and obtain its return type. */
1182 if (!coro_promise_type_found_p (current_function_decl
, kw
))
1183 return error_mark_node
;
1186 The incoming cast expression might be transformed by a promise
1187 'await_transform()'. */
1189 = lookup_promise_method (current_function_decl
,
1190 coro_await_transform_identifier
, kw
,
1191 /*musthave=*/false);
1192 if (at_meth
== error_mark_node
)
1193 return error_mark_node
;
1198 /* try to build a = p.await_transform (e). */
1199 vec
<tree
, va_gc
> *args
= make_tree_vector_single (expr
);
1200 a
= build_new_method_call (get_coroutine_promise_proxy (
1201 current_function_decl
),
1202 at_meth
, &args
, NULL_TREE
, LOOKUP_NORMAL
,
1203 NULL
, tf_warning_or_error
);
1205 /* As I read the section.
1206 We saw an await_transform method, so it's mandatory that we replace
1207 expr with p.await_transform (expr), therefore if the method call fails
1208 (presumably, we don't have suitable arguments) then this part of the
1210 if (a
== error_mark_node
)
1211 return error_mark_node
;
1214 /* Now we want to build co_await a. */
1215 return build_co_await (kw
, a
, CO_AWAIT_SUSPEND_POINT
);
1218 /* Take the EXPR given and attempt to build:
1219 co_await p.yield_value (expr);
1220 per [expr.yield] para 1. */
1223 finish_co_yield_expr (location_t kw
, tree expr
)
1225 if (!expr
|| error_operand_p (expr
))
1226 return error_mark_node
;
1228 /* Check the general requirements and simple syntax errors. */
1229 if (!coro_common_keyword_context_valid_p (current_function_decl
, kw
,
1231 return error_mark_node
;
1233 /* The current function has now become a coroutine, if it wasn't already. */
1234 DECL_COROUTINE_P (current_function_decl
) = 1;
1236 /* This function will appear to have no return statement, even if it
1237 is declared to return non-void (most likely). This is correct - we
1238 synthesize the return for the ramp in the compiler. So suppress any
1239 extraneous warnings during substitution. */
1240 suppress_warning (current_function_decl
, OPT_Wreturn_type
);
1242 /* Defer expansion when we are processing a template; see FIXME in the
1244 if (processing_template_decl
)
1245 return build2_loc (kw
, CO_YIELD_EXPR
, unknown_type_node
, expr
, NULL_TREE
);
1247 if (!coro_promise_type_found_p (current_function_decl
, kw
))
1248 /* We must be able to look up the "yield_value" method in the scope of
1249 the promise type, and obtain its return type. */
1250 return error_mark_node
;
1253 Let e be the operand of the yield-expression and p be an lvalue naming
1254 the promise object of the enclosing coroutine, then the yield-expression
1255 is equivalent to the expression co_await p.yield_value(e).
1256 build p.yield_value(e): */
1257 vec
<tree
, va_gc
> *args
= make_tree_vector_single (expr
);
1259 = coro_build_promise_expression (current_function_decl
, NULL
,
1260 coro_yield_value_identifier
, kw
,
1261 &args
, /*musthave=*/true);
1262 release_tree_vector (args
);
1264 /* Now build co_await p.yield_value (e).
1265 Noting that for co_yield, there is no evaluation of any potential
1266 promise transform_await(), so we call build_co_await directly. */
1268 tree op
= build_co_await (kw
, yield_call
, CO_YIELD_SUSPEND_POINT
);
1269 if (op
!= error_mark_node
)
1271 if (REFERENCE_REF_P (op
))
1272 op
= TREE_OPERAND (op
, 0);
1273 /* If the await expression is wrapped in a TARGET_EXPR, then transfer
1274 that wrapper to the CO_YIELD_EXPR, since this is just a proxy for
1275 its contained await. Otherwise, just build the CO_YIELD_EXPR. */
1276 if (TREE_CODE (op
) == TARGET_EXPR
)
1278 tree t
= TREE_OPERAND (op
, 1);
1279 t
= build2_loc (kw
, CO_YIELD_EXPR
, TREE_TYPE (t
), expr
, t
);
1280 TREE_OPERAND (op
, 1) = t
;
1283 op
= build2_loc (kw
, CO_YIELD_EXPR
, TREE_TYPE (op
), expr
, op
);
1284 TREE_SIDE_EFFECTS (op
) = 1;
1285 op
= convert_from_reference (op
);
1291 /* Check and build a co_return statement.
1292 First that it's valid to have a co_return keyword here.
1293 If it is, then check and build the p.return_{void(),value(expr)}.
1294 These are built against a proxy for the promise, which will be filled
1295 in with the actual frame version when the function is transformed. */
1298 finish_co_return_stmt (location_t kw
, tree expr
)
1301 STRIP_ANY_LOCATION_WRAPPER (expr
);
1303 if (error_operand_p (expr
))
1304 return error_mark_node
;
1306 /* If it fails the following test, the function is not permitted to be a
1307 coroutine, so the co_return statement is erroneous. */
1308 if (!coro_common_keyword_context_valid_p (current_function_decl
, kw
,
1310 return error_mark_node
;
1312 /* The current function has now become a coroutine, if it wasn't
1314 DECL_COROUTINE_P (current_function_decl
) = 1;
1316 /* This function will appear to have no return statement, even if it
1317 is declared to return non-void (most likely). This is correct - we
1318 synthesize the return for the ramp in the compiler. So suppress any
1319 extraneous warnings during substitution. */
1320 suppress_warning (current_function_decl
, OPT_Wreturn_type
);
1322 if (processing_template_decl
1323 && check_for_bare_parameter_packs (expr
))
1324 return error_mark_node
;
1326 /* Defer expansion when we are processing a template; see FIXME in the
1328 if (processing_template_decl
)
1330 /* co_return expressions are always void type, regardless of the
1332 expr
= build2_loc (kw
, CO_RETURN_EXPR
, void_type_node
,
1334 expr
= maybe_cleanup_point_expr_void (expr
);
1335 return add_stmt (expr
);
1338 if (!coro_promise_type_found_p (current_function_decl
, kw
))
1339 return error_mark_node
;
1341 /* Suppress -Wreturn-type for co_return, we need to check indirectly
1342 whether the promise type has a suitable return_void/return_value. */
1343 suppress_warning (current_function_decl
, OPT_Wreturn_type
);
1345 if (!processing_template_decl
&& warn_sequence_point
)
1346 verify_sequence_points (expr
);
1350 /* If we had an id-expression obfuscated by force_paren_expr, we need
1351 to undo it so we can try to treat it as an rvalue below. */
1352 expr
= maybe_undo_parenthesized_ref (expr
);
1354 if (error_operand_p (expr
))
1355 return error_mark_node
;
1358 /* If the promise object doesn't have the correct return call then
1359 there's a mis-match between the co_return <expr> and this. */
1360 tree co_ret_call
= error_mark_node
;
1361 if (expr
== NULL_TREE
|| VOID_TYPE_P (TREE_TYPE (expr
)))
1363 = get_coroutine_return_void_expr (current_function_decl
, kw
, true);
1366 /* [class.copy.elision] / 3.
1367 An implicitly movable entity is a variable of automatic storage
1368 duration that is either a non-volatile object or an rvalue reference
1369 to a non-volatile object type. For such objects in the context of
1370 the co_return, the overload resolution should be carried out first
1371 treating the object as an rvalue, if that fails, then we fall back
1372 to regular overload resolution. */
1375 if (tree moved
= treat_lvalue_as_rvalue_p (expr
, /*return*/true))
1378 releasing_vec args
= make_tree_vector_single (arg
);
1380 = coro_build_promise_expression (current_function_decl
, NULL
,
1381 coro_return_value_identifier
, kw
,
1382 &args
, /*musthave=*/true);
1385 /* Makes no sense for a co-routine really. */
1386 if (TREE_THIS_VOLATILE (current_function_decl
))
1388 "function declared %<noreturn%> has a"
1389 " %<co_return%> statement");
1391 expr
= build2_loc (kw
, CO_RETURN_EXPR
, void_type_node
, expr
, co_ret_call
);
1392 expr
= maybe_cleanup_point_expr_void (expr
);
1393 return add_stmt (expr
);
1396 /* We need to validate the arguments to __builtin_coro_promise, since the
1397 second two must be constant, and the builtins machinery doesn't seem to
1398 deal with that properly. */
1401 coro_validate_builtin_call (tree call
, tsubst_flags_t
)
1403 tree fn
= TREE_OPERAND (CALL_EXPR_FN (call
), 0);
1405 gcc_checking_assert (DECL_BUILT_IN_CLASS (fn
) == BUILT_IN_NORMAL
);
1406 switch (DECL_FUNCTION_CODE (fn
))
1411 case BUILT_IN_CORO_PROMISE
:
1413 /* Argument 0 is already checked by the normal built-in machinery
1414 Argument 1 must be a constant of size type. It probably makes
1415 little sense if it's not a power of 2, but that isn't specified
1417 tree arg
= CALL_EXPR_ARG (call
, 1);
1418 location_t loc
= EXPR_LOCATION (arg
);
1420 /* We expect alignof expressions in templates. */
1421 if (TREE_CODE (arg
) == ALIGNOF_EXPR
)
1423 else if (!TREE_CONSTANT (arg
))
1425 error_at (loc
, "the align argument to %<__builtin_coro_promise%>"
1426 " must be a constant");
1427 return error_mark_node
;
1429 /* Argument 2 is the direction - to / from handle address to promise
1431 arg
= CALL_EXPR_ARG (call
, 2);
1432 loc
= EXPR_LOCATION (arg
);
1433 if (!TREE_CONSTANT (arg
))
1435 error_at (loc
, "the direction argument to"
1436 " %<__builtin_coro_promise%> must be a constant");
1437 return error_mark_node
;
1445 /* ================= Morph and Expand. =================
1447 The entry point here is morph_fn_to_coro () which is called from
1448 finish_function () when we have completed any template expansion.
1450 This is preceded by helper functions that implement the phases below.
1452 The process proceeds in four phases.
1455 The user's function body is wrapped in the initial and final suspend
1456 points and we begin building the coroutine frame.
1457 We build empty decls for the actor and destroyer functions at this
1459 When exceptions are enabled, the user's function body will also be
1460 wrapped in a try-catch block with the catch invoking the promise
1461 class 'unhandled_exception' method.
1464 The user's function body is analyzed to determine the suspend points,
1465 if any, and to capture local variables that might persist across such
1466 suspensions. In most cases, it is not necessary to capture compiler
1467 temporaries, since the tree-lowering nests the suspensions correctly.
1468 However, in the case of a captured reference, there is a lifetime
1469 extension to the end of the full expression - which can mean across a
1470 suspend point in which case it must be promoted to a frame variable.
1472 At the conclusion of analysis, we have a conservative frame layout and
1473 maps of the local variables to their frame entry points.
1475 C Build the ramp function.
1476 Carry out the allocation for the coroutine frame (NOTE; the actual size
1477 computation is deferred until late in the middle end to allow for future
1478 optimizations that will be allowed to elide unused frame entries).
1479 We build the return object.
1481 D Build and expand the actor and destroyer function bodies.
1482 The destroyer is a trivial shim that sets a bit to indicate that the
1483 destroy dispatcher should be used and then calls into the actor.
1485 The actor function is the implementation of the user's state machine.
1486 The current suspend point is noted in an index.
1487 Each suspend point is encoded as a pair of internal functions, one in
1488 the relevant dispatcher, and one representing the suspend point.
1490 During this process, the user's local variables and the proxies for the
1491 self-handle and the promise class instance are re-written to their
1492 coroutine frame equivalents.
1494 The complete bodies for the ramp, actor and destroy function are passed
1495 back to finish_function for folding and gimplification. */
1497 /* Helpers to build EXPR_STMT and void-cast EXPR_STMT, common ops. */
1500 coro_build_expr_stmt (tree expr
, location_t loc
)
1502 return maybe_cleanup_point_expr_void (build_stmt (loc
, EXPR_STMT
, expr
));
1506 coro_build_cvt_void_expr_stmt (tree expr
, location_t loc
)
1508 tree t
= build1 (CONVERT_EXPR
, void_type_node
, expr
);
1509 return coro_build_expr_stmt (t
, loc
);
1512 /* Helpers to build an artificial var, with location LOC, NAME and TYPE, in
1513 CTX, and with initializer INIT. */
1516 coro_build_artificial_var (location_t loc
, tree name
, tree type
, tree ctx
,
1519 tree res
= build_lang_decl (VAR_DECL
, name
, type
);
1520 DECL_SOURCE_LOCATION (res
) = loc
;
1521 DECL_CONTEXT (res
) = ctx
;
1522 DECL_ARTIFICIAL (res
) = true;
1523 DECL_INITIAL (res
) = init
;
1528 coro_build_artificial_var (location_t loc
, const char *name
, tree type
,
1529 tree ctx
, tree init
)
1531 return coro_build_artificial_var (loc
, get_identifier (name
),
1535 /* Helpers for label creation:
1536 1. Create a named label in the specified context. */
1539 create_anon_label_with_ctx (location_t loc
, tree ctx
)
1541 tree lab
= build_decl (loc
, LABEL_DECL
, NULL_TREE
, void_type_node
);
1543 DECL_CONTEXT (lab
) = ctx
;
1544 DECL_ARTIFICIAL (lab
) = true;
1545 DECL_IGNORED_P (lab
) = true;
1546 TREE_USED (lab
) = true;
1550 /* 2. Create a named label in the specified context. */
1553 create_named_label_with_ctx (location_t loc
, const char *name
, tree ctx
)
1555 tree lab_id
= get_identifier (name
);
1556 tree lab
= define_label (loc
, lab_id
);
1557 DECL_CONTEXT (lab
) = ctx
;
1558 DECL_ARTIFICIAL (lab
) = true;
1559 TREE_USED (lab
) = true;
1563 struct proxy_replace
1569 replace_proxy (tree
*here
, int *do_subtree
, void *d
)
1571 proxy_replace
*data
= (proxy_replace
*) d
;
1573 if (*here
== data
->from
)
1583 /* Support for expansion of co_await statements. */
1587 tree actor_fn
; /* Decl for context. */
1588 tree coro_fp
; /* Frame pointer var. */
1589 tree resume_idx
; /* This is the index var in the frame. */
1590 tree i_a_r_c
; /* initial suspend await_resume() was called if true. */
1591 tree self_h
; /* This is a handle to the current coro (frame var). */
1592 tree cleanup
; /* This is where to go once we complete local destroy. */
1593 tree cororet
; /* This is where to go if we suspend. */
1594 tree corocont
; /* This is where to go if we continue. */
1595 tree conthand
; /* This is the handle for a continuation. */
1596 unsigned index
; /* This is our current resume index. */
1599 /* Lightweight search for the first await expression in tree-walk order.
1601 The first await expression found in STMT.
1602 NULL_TREE if there are none.
1603 So can be used to determine if the statement needs to be processed for
1607 co_await_find_in_subtree (tree
*stmt
, int *, void *d
)
1609 tree
**p
= (tree
**) d
;
1610 if (TREE_CODE (*stmt
) == CO_AWAIT_EXPR
)
1618 /* Starting with a statement:
1620 stmt => some tree containing one or more await expressions.
1622 We replace the statement with:
1624 initialize awaitable
1630 revised statement with one await expression rewritten to its
1631 await_resume() return value.
1634 We then recurse into the initializer and the revised statement
1635 repeating this replacement until there are no more await expressions
1639 expand_one_await_expression (tree
*stmt
, tree
*await_expr
, void *d
)
1641 coro_aw_data
*data
= (coro_aw_data
*) d
;
1643 tree saved_statement
= *stmt
;
1644 tree saved_co_await
= *await_expr
;
1646 tree actor
= data
->actor_fn
;
1647 location_t loc
= EXPR_LOCATION (*stmt
);
1648 tree var
= TREE_OPERAND (saved_co_await
, 1); /* frame slot. */
1649 tree expr
= TREE_OPERAND (saved_co_await
, 2); /* initializer. */
1650 tree awaiter_calls
= TREE_OPERAND (saved_co_await
, 3);
1652 tree source
= TREE_OPERAND (saved_co_await
, 4);
1653 bool is_final
= (source
1654 && TREE_INT_CST_LOW (source
) == (int) FINAL_SUSPEND_POINT
);
1655 bool needs_dtor
= TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (var
));
1656 int resume_point
= data
->index
;
1657 size_t bufsize
= sizeof ("destroy.") + 10;
1658 char *buf
= (char *) alloca (bufsize
);
1659 snprintf (buf
, bufsize
, "destroy.%d", resume_point
);
1660 tree destroy_label
= create_named_label_with_ctx (loc
, buf
, actor
);
1661 snprintf (buf
, bufsize
, "resume.%d", resume_point
);
1662 tree resume_label
= create_named_label_with_ctx (loc
, buf
, actor
);
1663 tree empty_list
= build_empty_stmt (loc
);
1665 tree await_type
= TREE_TYPE (var
);
1666 tree stmt_list
= NULL
;
1668 tree
*await_init
= NULL
;
1671 needs_dtor
= false; /* No need, the var's lifetime is managed elsewhere. */
1674 r
= coro_build_cvt_void_expr_stmt (expr
, loc
);
1675 append_to_statement_list_force (r
, &stmt_list
);
1676 /* We have an initializer, which might itself contain await exprs. */
1677 await_init
= tsi_stmt_ptr (tsi_last (stmt_list
));
1680 /* Use the await_ready() call to test if we need to suspend. */
1681 tree ready_cond
= TREE_VEC_ELT (awaiter_calls
, 0); /* await_ready(). */
1682 /* Convert to bool, if necessary. */
1683 if (TREE_CODE (TREE_TYPE (ready_cond
)) != BOOLEAN_TYPE
)
1684 ready_cond
= cp_convert (boolean_type_node
, ready_cond
,
1685 tf_warning_or_error
);
1686 /* Be aggressive in folding here, since there are a significant number of
1687 cases where the ready condition is constant. */
1688 ready_cond
= invert_truthvalue_loc (loc
, ready_cond
);
1690 = build1_loc (loc
, CLEANUP_POINT_EXPR
, boolean_type_node
, ready_cond
);
1692 tree body_list
= NULL
;
1693 tree susp_idx
= build_int_cst (short_unsigned_type_node
, data
->index
);
1694 r
= build2_loc (loc
, MODIFY_EXPR
, short_unsigned_type_node
, data
->resume_idx
,
1696 r
= coro_build_cvt_void_expr_stmt (r
, loc
);
1697 append_to_statement_list (r
, &body_list
);
1699 /* Find out what we have to do with the awaiter's suspend method.
1701 (5.1) If the result of await-ready is false, the coroutine is considered
1703 (5.1.1) If the type of await-suspend is std::coroutine_handle<Z>,
1704 await-suspend.resume() is evaluated.
1705 (5.1.2) if the type of await-suspend is bool, await-suspend is evaluated,
1706 and the coroutine is resumed if the result is false.
1707 (5.1.3) Otherwise, await-suspend is evaluated. */
1709 tree suspend
= TREE_VEC_ELT (awaiter_calls
, 1); /* await_suspend(). */
1710 tree susp_type
= TREE_TYPE (suspend
);
1712 bool is_cont
= false;
1713 /* NOTE: final suspend can't resume; the "resume" label in that case
1714 corresponds to implicit destruction. */
1715 if (VOID_TYPE_P (susp_type
))
1717 /* We just call await_suspend() and hit the yield. */
1718 suspend
= coro_build_cvt_void_expr_stmt (suspend
, loc
);
1719 append_to_statement_list (suspend
, &body_list
);
1721 else if (TREE_CODE (susp_type
) == BOOLEAN_TYPE
)
1723 /* Boolean return, continue if the call returns false. */
1724 suspend
= build1_loc (loc
, TRUTH_NOT_EXPR
, boolean_type_node
, suspend
);
1726 = build1_loc (loc
, CLEANUP_POINT_EXPR
, boolean_type_node
, suspend
);
1727 tree go_on
= build1_loc (loc
, GOTO_EXPR
, void_type_node
, resume_label
);
1728 r
= build3_loc (loc
, COND_EXPR
, void_type_node
, suspend
, go_on
,
1730 append_to_statement_list (r
, &body_list
);
1735 if (!same_type_ignoring_top_level_qualifiers_p (susp_type
,
1736 void_coro_handle_type
))
1737 r
= build1_loc (loc
, VIEW_CONVERT_EXPR
, void_coro_handle_type
, r
);
1738 r
= cp_build_init_expr (loc
, data
->conthand
, r
);
1739 r
= build1 (CONVERT_EXPR
, void_type_node
, r
);
1740 append_to_statement_list (r
, &body_list
);
1744 tree d_l
= build_address (destroy_label
);
1745 tree r_l
= build_address (resume_label
);
1746 tree susp
= build_address (data
->cororet
);
1747 tree cont
= build_address (data
->corocont
);
1748 tree final_susp
= build_int_cst (integer_type_node
, is_final
? 1 : 0);
1750 susp_idx
= build_int_cst (integer_type_node
, data
->index
);
1752 tree sw
= begin_switch_stmt ();
1753 tree cond
= build_decl (loc
, VAR_DECL
, NULL_TREE
, integer_type_node
);
1754 DECL_ARTIFICIAL (cond
) = 1;
1755 DECL_IGNORED_P (cond
) = 1;
1756 layout_decl (cond
, 0);
1758 r
= build_call_expr_internal_loc (loc
, IFN_CO_YIELD
, integer_type_node
, 5,
1759 susp_idx
, final_susp
, r_l
, d_l
,
1761 r
= cp_build_init_expr (cond
, r
);
1762 finish_switch_cond (r
, sw
);
1763 r
= build_case_label (build_int_cst (integer_type_node
, 0), NULL_TREE
,
1764 create_anon_label_with_ctx (loc
, actor
));
1765 add_stmt (r
); /* case 0: */
1766 /* Implement the suspend, a scope exit without clean ups. */
1767 r
= build_call_expr_internal_loc (loc
, IFN_CO_SUSPN
, void_type_node
, 1,
1768 is_cont
? cont
: susp
);
1769 r
= coro_build_cvt_void_expr_stmt (r
, loc
);
1770 add_stmt (r
); /* goto ret; */
1771 r
= build_case_label (build_int_cst (integer_type_node
, 1), NULL_TREE
,
1772 create_anon_label_with_ctx (loc
, actor
));
1773 add_stmt (r
); /* case 1: */
1774 r
= build1_loc (loc
, GOTO_EXPR
, void_type_node
, resume_label
);
1775 add_stmt (r
); /* goto resume; */
1776 r
= build_case_label (NULL_TREE
, NULL_TREE
,
1777 create_anon_label_with_ctx (loc
, actor
));
1778 add_stmt (r
); /* default:; */
1779 r
= build1_loc (loc
, GOTO_EXPR
, void_type_node
, destroy_label
);
1780 add_stmt (r
); /* goto destroy; */
1782 /* part of finish switch. */
1783 SWITCH_STMT_BODY (sw
) = pop_stmt_list (SWITCH_STMT_BODY (sw
));
1785 tree scope
= SWITCH_STMT_SCOPE (sw
);
1786 SWITCH_STMT_SCOPE (sw
) = NULL
;
1787 r
= do_poplevel (scope
);
1788 append_to_statement_list (r
, &body_list
);
1790 destroy_label
= build_stmt (loc
, LABEL_EXPR
, destroy_label
);
1791 append_to_statement_list (destroy_label
, &body_list
);
1794 tree dtor
= build_special_member_call (var
, complete_dtor_identifier
,
1795 NULL
, await_type
, LOOKUP_NORMAL
,
1796 tf_warning_or_error
);
1797 append_to_statement_list (dtor
, &body_list
);
1799 r
= build1_loc (loc
, GOTO_EXPR
, void_type_node
, data
->cleanup
);
1800 append_to_statement_list (r
, &body_list
);
1802 r
= build3_loc (loc
, COND_EXPR
, void_type_node
, ready_cond
, body_list
,
1805 append_to_statement_list (r
, &stmt_list
);
1808 resume_label
= build_stmt (loc
, LABEL_EXPR
, resume_label
);
1809 append_to_statement_list (resume_label
, &stmt_list
);
1811 /* This will produce the value (if one is provided) from the co_await
1813 tree resume_call
= TREE_VEC_ELT (awaiter_calls
, 2); /* await_resume(). */
1814 if (REFERENCE_REF_P (resume_call
))
1815 /* Sink to await_resume call_expr. */
1816 resume_call
= TREE_OPERAND (resume_call
, 0);
1818 *await_expr
= resume_call
; /* Replace the co_await expr with its result. */
1819 append_to_statement_list_force (saved_statement
, &stmt_list
);
1820 /* Get a pointer to the revised statement. */
1821 tree
*revised
= tsi_stmt_ptr (tsi_last (stmt_list
));
1824 tree dtor
= build_special_member_call (var
, complete_dtor_identifier
,
1825 NULL
, await_type
, LOOKUP_NORMAL
,
1826 tf_warning_or_error
);
1827 append_to_statement_list (dtor
, &stmt_list
);
1831 /* Replace the original statement with the expansion. */
1834 /* Now, if the awaitable had an initializer, expand any awaits that might
1835 be embedded in it. */
1838 cp_walk_tree (await_init
, co_await_find_in_subtree
, &aw_expr_ptr
, NULL
))
1839 expand_one_await_expression (await_init
, aw_expr_ptr
, d
);
1841 /* Expand any more await expressions in the original statement. */
1842 if (cp_walk_tree (revised
, co_await_find_in_subtree
, &aw_expr_ptr
, NULL
))
1843 expand_one_await_expression (revised
, aw_expr_ptr
, d
);
1848 /* Check to see if a statement contains at least one await expression, if
1849 so, then process that. */
1852 process_one_statement (tree
*stmt
, void *d
)
1855 if (cp_walk_tree (stmt
, co_await_find_in_subtree
, &aw_expr_ptr
, NULL
))
1856 expand_one_await_expression (stmt
, aw_expr_ptr
, d
);
1861 await_statement_expander (tree
*stmt
, int *do_subtree
, void *d
)
1863 tree res
= NULL_TREE
;
1865 /* Process a statement at a time. */
1866 if (STATEMENT_CLASS_P (*stmt
) || TREE_CODE (*stmt
) == BIND_EXPR
)
1867 return NULL_TREE
; /* Just process the sub-trees. */
1868 else if (TREE_CODE (*stmt
) == STATEMENT_LIST
)
1870 for (tree
&s
: tsi_range (*stmt
))
1872 res
= cp_walk_tree (&s
, await_statement_expander
,
1877 *do_subtree
= 0; /* Done subtrees. */
1879 else if (EXPR_P (*stmt
))
1881 process_one_statement (stmt
, d
);
1882 *do_subtree
= 0; /* Done subtrees. */
1885 /* Continue statement walk, where required. */
1889 /* Suspend point hash_map. */
1891 struct suspend_point_info
1893 /* coro frame field type. */
1894 tree awaitable_type
;
1895 /* coro frame field name. */
1896 tree await_field_id
;
1899 static hash_map
<tree
, suspend_point_info
> *suspend_points
;
1901 struct await_xform_data
1903 tree actor_fn
; /* Decl for context. */
1907 /* When we built the await expressions, we didn't know the coro frame
1908 layout, therefore no idea where to find the promise or where to put
1909 the awaitables. Now we know these things, fill them in. */
1912 transform_await_expr (tree await_expr
, await_xform_data
*xform
)
1914 suspend_point_info
*si
= suspend_points
->get (await_expr
);
1915 location_t loc
= EXPR_LOCATION (await_expr
);
1918 error_at (loc
, "no suspend point info for %qD", await_expr
);
1919 return error_mark_node
;
1922 /* So, on entry, we have:
1923 in : CO_AWAIT_EXPR (a, e_proxy, o, awr_call_vector, mode)
1924 We no longer need a [it had diagnostic value, maybe?]
1925 We need to replace the e_proxy in the awr_call. */
1927 tree coro_frame_type
= TREE_TYPE (xform
->actor_frame
);
1929 /* If we have a frame var for the awaitable, get a reference to it. */
1931 if (si
->await_field_id
)
1934 = lookup_member (coro_frame_type
, si
->await_field_id
,
1935 /*protect=*/1, /*want_type=*/0, tf_warning_or_error
);
1936 tree as
= build_class_member_access_expr (xform
->actor_frame
, as_m
,
1938 tf_warning_or_error
);
1940 /* Replace references to the instance proxy with the frame entry now
1942 data
.from
= TREE_OPERAND (await_expr
, 1);
1944 cp_walk_tree (&await_expr
, replace_proxy
, &data
, NULL
);
1946 /* .. and replace. */
1947 TREE_OPERAND (await_expr
, 1) = as
;
1953 /* A wrapper for the transform_await_expr function so that it can be a
1954 callback from cp_walk_tree. */
1957 transform_await_wrapper (tree
*stmt
, int *do_subtree
, void *d
)
1959 /* Set actor function as new DECL_CONTEXT of label_decl. */
1960 struct await_xform_data
*xform
= (struct await_xform_data
*) d
;
1961 if (TREE_CODE (*stmt
) == LABEL_DECL
1962 && DECL_CONTEXT (*stmt
) != xform
->actor_fn
)
1963 DECL_CONTEXT (*stmt
) = xform
->actor_fn
;
1965 /* We should have already lowered co_yields to their co_await. */
1966 gcc_checking_assert (TREE_CODE (*stmt
) != CO_YIELD_EXPR
);
1967 if (TREE_CODE (*stmt
) != CO_AWAIT_EXPR
)
1970 tree await_expr
= *stmt
;
1971 *stmt
= transform_await_expr (await_expr
, xform
);
1972 if (*stmt
== error_mark_node
)
1977 /* This caches information that we determine about function params,
1978 their uses and copies in the coroutine frame. */
1982 tree field_id
; /* The name of the copy in the coroutine frame. */
1983 tree copy_var
; /* The local var proxy for the frame copy. */
1984 vec
<tree
*> *body_uses
; /* Worklist of uses, void if there are none. */
1985 tree frame_type
; /* The type used to represent this parm in the frame. */
1986 tree orig_type
; /* The original type of the parm (not as passed). */
1987 tree guard_var
; /* If we need a DTOR on exception, this bool guards it. */
1988 tree fr_copy_dtor
; /* If we need a DTOR on exception, this is it. */
1989 bool by_ref
; /* Was passed by reference. */
1990 bool pt_ref
; /* Was a pointer to object. */
1991 bool rv_ref
; /* Was an rvalue ref. */
1992 bool trivial_dtor
; /* The frame type has a trivial DTOR. */
1993 bool this_ptr
; /* Is 'this' */
1994 bool lambda_cobj
; /* Lambda capture object */
1997 struct local_var_info
2002 bool is_lambda_capture
;
2004 bool has_value_expr_p
;
2008 /* For figuring out what local variable usage we have. */
2009 struct local_vars_transform
2013 tree coro_frame_type
;
2015 hash_map
<tree
, local_var_info
> *local_var_uses
;
2019 transform_local_var_uses (tree
*stmt
, int *do_subtree
, void *d
)
2021 local_vars_transform
*lvd
= (local_vars_transform
*) d
;
2023 /* For each var in this bind expr (that has a frame id, which means it was
2024 accessed), build a frame reference and add it as the DECL_VALUE_EXPR. */
2026 if (TREE_CODE (*stmt
) == BIND_EXPR
)
2029 for (lvar
= BIND_EXPR_VARS (*stmt
); lvar
!= NULL
;
2030 lvar
= DECL_CHAIN (lvar
))
2033 local_var_info
&local_var
2034 = lvd
->local_var_uses
->get_or_insert (lvar
, &existed
);
2035 gcc_checking_assert (existed
);
2037 /* Re-write the variable's context to be in the actor func. */
2038 DECL_CONTEXT (lvar
) = lvd
->context
;
2040 /* For capture proxies, this could include the decl value expr. */
2041 if (local_var
.is_lambda_capture
|| local_var
.has_value_expr_p
)
2042 continue; /* No frame entry for this. */
2044 /* TODO: implement selective generation of fields when vars are
2046 if (local_var
.field_id
== NULL_TREE
)
2047 continue; /* Wasn't used. */
2050 = lookup_member (lvd
->coro_frame_type
, local_var
.field_id
,
2051 /*protect=*/1, /*want_type=*/0,
2052 tf_warning_or_error
);
2053 tree fld_idx
= build3 (COMPONENT_REF
, TREE_TYPE (lvar
),
2054 lvd
->actor_frame
, fld_ref
, NULL_TREE
);
2055 local_var
.field_idx
= fld_idx
;
2056 SET_DECL_VALUE_EXPR (lvar
, fld_idx
);
2057 DECL_HAS_VALUE_EXPR_P (lvar
) = true;
2059 cp_walk_tree (&BIND_EXPR_BODY (*stmt
), transform_local_var_uses
, d
, NULL
);
2060 *do_subtree
= 0; /* We've done the body already. */
2066 /* A helper to build the frame DTOR.
2067 [dcl.fct.def.coroutine] / 12
2068 The deallocation function’s name is looked up in the scope of the promise
2069 type. If this lookup fails, the deallocation function’s name is looked up
2070 in the global scope. If deallocation function lookup finds both a usual
2071 deallocation function with only a pointer parameter and a usual
2072 deallocation function with both a pointer parameter and a size parameter,
2073 then the selected deallocation function shall be the one with two
2074 parameters. Otherwise, the selected deallocation function shall be the
2075 function with one parameter. If no usual deallocation function is found
2076 the program is ill-formed. The selected deallocation function shall be
2077 called with the address of the block of storage to be reclaimed as its
2078 first argument. If a deallocation function with a parameter of type
2079 std::size_t is used, the size of the block is passed as the corresponding
2083 coro_get_frame_dtor (tree coro_fp
, tree orig
, tree frame_size
,
2084 tree promise_type
, location_t loc
)
2086 tree del_coro_fr
= NULL_TREE
;
2087 tree frame_arg
= build1 (CONVERT_EXPR
, ptr_type_node
, coro_fp
);
2088 tree delname
= ovl_op_identifier (false, DELETE_EXPR
);
2089 tree fns
= lookup_promise_method (orig
, delname
, loc
,
2090 /*musthave=*/false);
2091 if (fns
&& BASELINK_P (fns
))
2093 /* Look for sized version first, since this takes precedence. */
2094 vec
<tree
, va_gc
> *args
= make_tree_vector ();
2095 vec_safe_push (args
, frame_arg
);
2096 vec_safe_push (args
, frame_size
);
2097 tree dummy_promise
= build_dummy_object (promise_type
);
2099 /* It's OK to fail for this one... */
2100 del_coro_fr
= build_new_method_call (dummy_promise
, fns
, &args
,
2101 NULL_TREE
, LOOKUP_NORMAL
, NULL
,
2104 if (!del_coro_fr
|| del_coro_fr
== error_mark_node
)
2106 release_tree_vector (args
);
2107 args
= make_tree_vector_single (frame_arg
);
2108 del_coro_fr
= build_new_method_call (dummy_promise
, fns
, &args
,
2109 NULL_TREE
, LOOKUP_NORMAL
, NULL
,
2113 /* But one of them must succeed, or the program is ill-formed. */
2114 if (!del_coro_fr
|| del_coro_fr
== error_mark_node
)
2116 error_at (loc
, "%qE is provided by %qT but is not usable with"
2117 " the function signature %qD", delname
, promise_type
, orig
);
2118 del_coro_fr
= error_mark_node
;
2123 del_coro_fr
= build_op_delete_call (DELETE_EXPR
, frame_arg
, frame_size
,
2124 /*global_p=*/true, /*placement=*/NULL
,
2126 tf_warning_or_error
);
2127 if (!del_coro_fr
|| del_coro_fr
== error_mark_node
)
2128 del_coro_fr
= error_mark_node
;
2133 /* The actor transform. */
2136 build_actor_fn (location_t loc
, tree coro_frame_type
, tree actor
, tree fnbody
,
2137 tree orig
, hash_map
<tree
, local_var_info
> *local_var_uses
,
2138 vec
<tree
, va_gc
> *param_dtor_list
,
2139 tree resume_idx_var
, unsigned body_count
, tree frame_size
)
2141 verify_stmt_tree (fnbody
);
2142 /* Some things we inherit from the original function. */
2143 tree handle_type
= get_coroutine_handle_type (orig
);
2144 tree promise_type
= get_coroutine_promise_type (orig
);
2145 tree promise_proxy
= get_coroutine_promise_proxy (orig
);
2147 /* One param, the coro frame pointer. */
2148 tree actor_fp
= DECL_ARGUMENTS (actor
);
2150 /* We have a definition here. */
2151 TREE_STATIC (actor
) = 1;
2153 tree actor_outer
= push_stmt_list ();
2154 current_stmt_tree ()->stmts_are_full_exprs_p
= 1;
2155 tree stmt
= begin_compound_stmt (BCS_FN_BODY
);
2157 tree actor_bind
= build3 (BIND_EXPR
, void_type_node
, NULL
, NULL
, NULL
);
2158 tree top_block
= make_node (BLOCK
);
2159 BIND_EXPR_BLOCK (actor_bind
) = top_block
;
2161 tree continuation
= coro_build_artificial_var (loc
, coro_actor_continue_id
,
2162 void_coro_handle_type
, actor
,
2165 BIND_EXPR_VARS (actor_bind
) = continuation
;
2166 BLOCK_VARS (top_block
) = BIND_EXPR_VARS (actor_bind
) ;
2168 /* Link in the block associated with the outer scope of the re-written
2170 tree first
= expr_first (fnbody
);
2171 gcc_checking_assert (first
&& TREE_CODE (first
) == BIND_EXPR
);
2172 tree block
= BIND_EXPR_BLOCK (first
);
2173 gcc_checking_assert (BLOCK_SUPERCONTEXT (block
) == NULL_TREE
);
2174 gcc_checking_assert (BLOCK_CHAIN (block
) == NULL_TREE
);
2175 BLOCK_SUPERCONTEXT (block
) = top_block
;
2176 BLOCK_SUBBLOCKS (top_block
) = block
;
2178 add_stmt (actor_bind
);
2179 tree actor_body
= push_stmt_list ();
2181 /* The entry point for the actor code from the ramp. */
2182 tree actor_begin_label
2183 = create_named_label_with_ctx (loc
, "actor.begin", actor
);
2184 tree actor_frame
= build1_loc (loc
, INDIRECT_REF
, coro_frame_type
, actor_fp
);
2186 /* Declare the continuation handle. */
2187 add_decl_expr (continuation
);
2189 /* Re-write local vars, similarly. */
2190 local_vars_transform xform_vars_data
2191 = {actor
, actor_frame
, coro_frame_type
, loc
, local_var_uses
};
2192 cp_walk_tree (&fnbody
, transform_local_var_uses
, &xform_vars_data
, NULL
);
2194 tree rat_field
= lookup_member (coro_frame_type
, coro_resume_index_id
,
2195 1, 0, tf_warning_or_error
);
2196 tree rat
= build3 (COMPONENT_REF
, short_unsigned_type_node
, actor_frame
,
2197 rat_field
, NULL_TREE
);
2200 = create_named_label_with_ctx (loc
, "actor.suspend.ret", actor
);
2203 = create_named_label_with_ctx (loc
, "actor.continue.ret", actor
);
2205 tree lsb_if
= begin_if_stmt ();
2206 tree chkb0
= build2 (BIT_AND_EXPR
, short_unsigned_type_node
, rat
,
2207 build_int_cst (short_unsigned_type_node
, 1));
2208 chkb0
= build2 (NE_EXPR
, short_unsigned_type_node
, chkb0
,
2209 build_int_cst (short_unsigned_type_node
, 0));
2210 finish_if_stmt_cond (chkb0
, lsb_if
);
2212 tree destroy_dispatcher
= begin_switch_stmt ();
2213 finish_switch_cond (rat
, destroy_dispatcher
);
2214 tree ddeflab
= build_case_label (NULL_TREE
, NULL_TREE
,
2215 create_anon_label_with_ctx (loc
, actor
));
2217 tree b
= build_call_expr_loc (loc
, builtin_decl_explicit (BUILT_IN_TRAP
), 0);
2218 b
= coro_build_cvt_void_expr_stmt (b
, loc
);
2221 /* The destroy point numbered #1 is special, in that it is reached from a
2222 coroutine that is suspended after re-throwing from unhandled_exception().
2223 This label just invokes the cleanup of promise, param copies and the
2225 tree del_promise_label
2226 = create_named_label_with_ctx (loc
, "coro.delete.promise", actor
);
2227 b
= build_case_label (build_int_cst (short_unsigned_type_node
, 1), NULL_TREE
,
2228 create_anon_label_with_ctx (loc
, actor
));
2230 add_stmt (build_stmt (loc
, GOTO_EXPR
, del_promise_label
));
2232 short unsigned lab_num
= 3;
2233 for (unsigned destr_pt
= 0; destr_pt
< body_count
; destr_pt
++)
2235 tree l_num
= build_int_cst (short_unsigned_type_node
, lab_num
);
2236 b
= build_case_label (l_num
, NULL_TREE
,
2237 create_anon_label_with_ctx (loc
, actor
));
2239 b
= build_call_expr_internal_loc (loc
, IFN_CO_ACTOR
, void_type_node
, 1,
2241 b
= coro_build_cvt_void_expr_stmt (b
, loc
);
2243 b
= build1 (GOTO_EXPR
, void_type_node
, CASE_LABEL (ddeflab
));
2248 /* Insert the prototype dispatcher. */
2249 finish_switch_stmt (destroy_dispatcher
);
2251 finish_then_clause (lsb_if
);
2252 begin_else_clause (lsb_if
);
2254 tree dispatcher
= begin_switch_stmt ();
2255 finish_switch_cond (rat
, dispatcher
);
2256 b
= build_case_label (build_int_cst (short_unsigned_type_node
, 0), NULL_TREE
,
2257 create_anon_label_with_ctx (loc
, actor
));
2259 b
= build1 (GOTO_EXPR
, void_type_node
, actor_begin_label
);
2262 tree rdeflab
= build_case_label (NULL_TREE
, NULL_TREE
,
2263 create_anon_label_with_ctx (loc
, actor
));
2265 b
= build_call_expr_loc (loc
, builtin_decl_explicit (BUILT_IN_TRAP
), 0);
2266 b
= coro_build_cvt_void_expr_stmt (b
, loc
);
2270 /* The final resume should be made to hit the default (trap, UB) entry
2271 although it will be unreachable via the normal entry point, since that
2272 is set to NULL on reaching final suspend. */
2273 for (unsigned resu_pt
= 0; resu_pt
< body_count
; resu_pt
++)
2275 tree l_num
= build_int_cst (short_unsigned_type_node
, lab_num
);
2276 b
= build_case_label (l_num
, NULL_TREE
,
2277 create_anon_label_with_ctx (loc
, actor
));
2279 b
= build_call_expr_internal_loc (loc
, IFN_CO_ACTOR
, void_type_node
, 1,
2281 b
= coro_build_cvt_void_expr_stmt (b
, loc
);
2283 b
= build1 (GOTO_EXPR
, void_type_node
, CASE_LABEL (rdeflab
));
2288 /* Insert the prototype dispatcher. */
2289 finish_switch_stmt (dispatcher
);
2290 finish_else_clause (lsb_if
);
2292 finish_if_stmt (lsb_if
);
2294 tree r
= build_stmt (loc
, LABEL_EXPR
, actor_begin_label
);
2297 /* actor's coroutine 'self handle'. */
2298 tree ash_m
= lookup_member (coro_frame_type
, coro_self_handle_id
, 1,
2299 0, tf_warning_or_error
);
2300 tree ash
= build_class_member_access_expr (actor_frame
, ash_m
, NULL_TREE
,
2301 false, tf_warning_or_error
);
2302 /* So construct the self-handle from the frame address. */
2303 tree hfa_m
= lookup_member (handle_type
, coro_from_address_identifier
, 1,
2304 0, tf_warning_or_error
);
2306 r
= build1 (CONVERT_EXPR
, build_pointer_type (void_type_node
), actor_fp
);
2307 vec
<tree
, va_gc
> *args
= make_tree_vector_single (r
);
2308 tree hfa
= build_new_method_call (ash
, hfa_m
, &args
, NULL_TREE
, LOOKUP_NORMAL
,
2309 NULL
, tf_warning_or_error
);
2310 r
= cp_build_init_expr (ash
, hfa
);
2311 r
= coro_build_cvt_void_expr_stmt (r
, loc
);
2313 release_tree_vector (args
);
2315 /* Now we know the real promise, and enough about the frame layout to
2316 decide where to put things. */
2318 await_xform_data xform
= {actor
, actor_frame
};
2320 /* Transform the await expressions in the function body. Only do each
2322 hash_set
<tree
> pset
;
2323 cp_walk_tree (&fnbody
, transform_await_wrapper
, &xform
, &pset
);
2325 /* Add in our function body with the co_returns rewritten to final form. */
2328 /* now do the tail of the function. */
2329 r
= build_stmt (loc
, LABEL_EXPR
, del_promise_label
);
2332 /* Destructors for the things we built explicitly. */
2333 r
= build_special_member_call (promise_proxy
, complete_dtor_identifier
, NULL
,
2334 promise_type
, LOOKUP_NORMAL
,
2335 tf_warning_or_error
);
2338 tree del_frame_label
2339 = create_named_label_with_ctx (loc
, "coro.delete.frame", actor
);
2340 r
= build_stmt (loc
, LABEL_EXPR
, del_frame_label
);
2343 /* Here deallocate the frame (if we allocated it), which we will have at
2346 = lookup_member (coro_frame_type
, coro_frame_needs_free_id
, 1,
2347 0, tf_warning_or_error
);
2348 tree fnf2_x
= build_class_member_access_expr (actor_frame
, fnf_m
, NULL_TREE
,
2349 false, tf_warning_or_error
);
2351 tree need_free_if
= begin_if_stmt ();
2352 fnf2_x
= build1 (CONVERT_EXPR
, integer_type_node
, fnf2_x
);
2353 tree cmp
= build2 (NE_EXPR
, integer_type_node
, fnf2_x
, integer_zero_node
);
2354 finish_if_stmt_cond (cmp
, need_free_if
);
2355 if (param_dtor_list
!= NULL
)
2359 FOR_EACH_VEC_ELT (*param_dtor_list
, i
, pid
)
2362 = lookup_member (coro_frame_type
, pid
, 1, 0, tf_warning_or_error
);
2363 tree a
= build_class_member_access_expr (actor_frame
, m
, NULL_TREE
,
2364 false, tf_warning_or_error
);
2365 tree t
= TREE_TYPE (a
);
2368 = build_special_member_call (a
, complete_dtor_identifier
, NULL
, t
,
2369 LOOKUP_NORMAL
, tf_warning_or_error
);
2374 /* Build the frame DTOR. */
2375 tree del_coro_fr
= coro_get_frame_dtor (actor_fp
, orig
, frame_size
,
2377 finish_expr_stmt (del_coro_fr
);
2378 finish_then_clause (need_free_if
);
2379 tree scope
= IF_SCOPE (need_free_if
);
2380 IF_SCOPE (need_free_if
) = NULL
;
2381 r
= do_poplevel (scope
);
2385 r
= build_stmt (loc
, RETURN_EXPR
, NULL
);
2386 suppress_warning (r
); /* We don't want a warning about this. */
2387 r
= maybe_cleanup_point_expr_void (r
);
2390 /* This is the suspend return point. */
2391 r
= build_stmt (loc
, LABEL_EXPR
, ret_label
);
2394 r
= build_stmt (loc
, RETURN_EXPR
, NULL
);
2395 suppress_warning (r
); /* We don't want a warning about this. */
2396 r
= maybe_cleanup_point_expr_void (r
);
2399 /* This is the 'continuation' return point. For such a case we have a coro
2400 handle (from the await_suspend() call) and we want handle.resume() to
2401 execute as a tailcall allowing arbitrary chaining of coroutines. */
2402 r
= build_stmt (loc
, LABEL_EXPR
, continue_label
);
2405 /* We want to force a tail-call even for O0/1, so this expands the resume
2406 call into its underlying implementation. */
2407 tree addr
= lookup_member (void_coro_handle_type
, coro_address_identifier
,
2408 1, 0, tf_warning_or_error
);
2409 addr
= build_new_method_call (continuation
, addr
, NULL
, NULL_TREE
,
2410 LOOKUP_NORMAL
, NULL
, tf_warning_or_error
);
2411 tree resume
= build_call_expr_loc
2412 (loc
, builtin_decl_explicit (BUILT_IN_CORO_RESUME
), 1, addr
);
2414 /* In order to support an arbitrary number of coroutine continuations,
2415 we must tail call them. However, some targets do not support indirect
2416 tail calls to arbitrary callees. See PR94359. */
2417 CALL_EXPR_TAILCALL (resume
) = true;
2418 resume
= coro_build_cvt_void_expr_stmt (resume
, loc
);
2421 r
= build_stmt (loc
, RETURN_EXPR
, NULL
);
2422 gcc_checking_assert (maybe_cleanup_point_expr_void (r
) == r
);
2425 /* We've now rewritten the tree and added the initial and final
2426 co_awaits. Now pass over the tree and expand the co_awaits. */
2428 coro_aw_data data
= {actor
, actor_fp
, resume_idx_var
, NULL_TREE
,
2429 ash
, del_promise_label
, ret_label
,
2430 continue_label
, continuation
, 2};
2431 cp_walk_tree (&actor_body
, await_statement_expander
, &data
, NULL
);
2433 BIND_EXPR_BODY (actor_bind
) = pop_stmt_list (actor_body
);
2434 TREE_SIDE_EFFECTS (actor_bind
) = true;
2436 finish_compound_stmt (stmt
);
2437 DECL_SAVED_TREE (actor
) = pop_stmt_list (actor_outer
);
2438 verify_stmt_tree (DECL_SAVED_TREE (actor
));
2441 /* The prototype 'destroy' function :
2442 frame->__Coro_resume_index |= 1;
2446 build_destroy_fn (location_t loc
, tree coro_frame_type
, tree destroy
,
2449 /* One param, the coro frame pointer. */
2450 tree destr_fp
= DECL_ARGUMENTS (destroy
);
2452 /* We have a definition here. */
2453 TREE_STATIC (destroy
) = 1;
2455 tree destr_outer
= push_stmt_list ();
2456 current_stmt_tree ()->stmts_are_full_exprs_p
= 1;
2457 tree dstr_stmt
= begin_compound_stmt (BCS_FN_BODY
);
2459 tree destr_frame
= build1 (INDIRECT_REF
, coro_frame_type
, destr_fp
);
2461 tree rat_field
= lookup_member (coro_frame_type
, coro_resume_index_id
,
2462 1, 0, tf_warning_or_error
);
2463 tree rat
= build3 (COMPONENT_REF
, short_unsigned_type_node
,
2464 destr_frame
, rat_field
, NULL_TREE
);
2466 /* _resume_at |= 1 */
2467 tree dstr_idx
= build2 (BIT_IOR_EXPR
, short_unsigned_type_node
, rat
,
2468 build_int_cst (short_unsigned_type_node
, 1));
2469 tree r
= build2 (MODIFY_EXPR
, short_unsigned_type_node
, rat
, dstr_idx
);
2470 r
= coro_build_cvt_void_expr_stmt (r
, loc
);
2473 /* So .. call the actor .. */
2474 r
= build_call_expr_loc (loc
, actor
, 1, destr_fp
);
2475 r
= coro_build_cvt_void_expr_stmt (r
, loc
);
2479 r
= build_stmt (loc
, RETURN_EXPR
, NULL
);
2480 r
= maybe_cleanup_point_expr_void (r
);
2483 finish_compound_stmt (dstr_stmt
);
2484 DECL_SAVED_TREE (destroy
) = pop_stmt_list (destr_outer
);
2487 /* Helper that returns an identifier for an appended extension to the
2488 current un-mangled function name. */
2491 get_fn_local_identifier (tree orig
, const char *append
)
2493 /* Figure out the bits we need to generate names for the outlined things
2494 For consistency, this needs to behave the same way as
2495 ASM_FORMAT_PRIVATE_NAME does. */
2496 tree nm
= DECL_NAME (orig
);
2497 const char *sep
, *pfx
= "";
2498 #ifndef NO_DOT_IN_LABEL
2501 #ifndef NO_DOLLAR_IN_LABEL
2510 if (DECL_ASSEMBLER_NAME (orig
))
2511 an
= ACONCAT ((IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (orig
)), sep
, append
,
2513 else if (DECL_USE_TEMPLATE (orig
) && DECL_TEMPLATE_INFO (orig
)
2514 && DECL_TI_ARGS (orig
))
2516 tree tpl_args
= DECL_TI_ARGS (orig
);
2517 an
= ACONCAT ((pfx
, IDENTIFIER_POINTER (nm
), (char *) 0));
2518 for (int i
= 0; i
< TREE_VEC_LENGTH (tpl_args
); ++i
)
2520 tree typ
= DECL_NAME (TYPE_NAME (TREE_VEC_ELT (tpl_args
, i
)));
2521 an
= ACONCAT ((an
, sep
, IDENTIFIER_POINTER (typ
), (char *) 0));
2523 an
= ACONCAT ((an
, sep
, append
, (char *) 0));
2526 an
= ACONCAT ((pfx
, IDENTIFIER_POINTER (nm
), sep
, append
, (char *) 0));
2528 return get_identifier (an
);
2531 /* Build an initial or final await initialized from the promise
2532 initial_suspend or final_suspend expression. */
2535 build_init_or_final_await (location_t loc
, bool is_final
)
2537 tree suspend_alt
= is_final
? coro_final_suspend_identifier
2538 : coro_initial_suspend_identifier
;
2541 = coro_build_promise_expression (current_function_decl
, NULL
, suspend_alt
,
2542 loc
, NULL
, /*musthave=*/true);
2544 /* Check for noexcept on the final_suspend call. */
2545 if (flag_exceptions
&& is_final
&& setup_call
!= error_mark_node
2546 && coro_diagnose_throwing_final_aw_expr (setup_call
))
2547 return error_mark_node
;
2549 /* So build the co_await for this */
2550 /* For initial/final suspends the call is "a" per [expr.await] 3.2. */
2551 return build_co_await (loc
, setup_call
, (is_final
? FINAL_SUSPEND_POINT
2552 : INITIAL_SUSPEND_POINT
));
2555 /* Callback to record the essential data for each await point found in the
2559 register_await_info (tree await_expr
, tree aw_type
, tree aw_nam
)
2562 suspend_point_info
&s
2563 = suspend_points
->get_or_insert (await_expr
, &seen
);
2566 warning_at (EXPR_LOCATION (await_expr
), 0, "duplicate info for %qE",
2570 s
.awaitable_type
= aw_type
;
2571 s
.await_field_id
= aw_nam
;
2575 /* This data set is used when analyzing statements for await expressions. */
2577 struct susp_frame_data
2579 /* Function-wide. */
2580 tree
*field_list
; /* The current coroutine frame field list. */
2581 tree handle_type
; /* The self-handle type for this coroutine. */
2582 tree fs_label
; /* The destination for co_returns. */
2583 vec
<tree
, va_gc
> *block_stack
; /* Track block scopes. */
2584 vec
<tree
, va_gc
> *bind_stack
; /* Track current bind expr. */
2585 unsigned await_number
; /* Which await in the function. */
2586 unsigned cond_number
; /* Which replaced condition in the fn. */
2587 /* Temporary values for one statement or expression being analyzed. */
2588 hash_set
<tree
> captured_temps
; /* The suspend captured these temps. */
2589 vec
<tree
, va_gc
> *to_replace
; /* The VAR decls to replace. */
2590 hash_set
<tree
> *truth_aoif_to_expand
; /* The set of TRUTH exprs to expand. */
2591 unsigned saw_awaits
; /* Count of awaits in this statement */
2592 bool captures_temporary
; /* This expr captures temps by ref. */
2593 bool needs_truth_if_exp
; /* We must expand a truth_if expression. */
2594 bool has_awaiter_init
; /* We must handle initializing an awaiter. */
2597 /* If this is an await expression, then count it (both uniquely within the
2598 function and locally within a single statement). */
2601 register_awaits (tree
*stmt
, int *, void *d
)
2603 tree aw_expr
= *stmt
;
2605 /* We should have already lowered co_yields to their co_await. */
2606 gcc_checking_assert (TREE_CODE (aw_expr
) != CO_YIELD_EXPR
);
2608 if (TREE_CODE (aw_expr
) != CO_AWAIT_EXPR
)
2611 /* Count how many awaits the current expression contains. */
2612 susp_frame_data
*data
= (susp_frame_data
*) d
;
2614 /* Each await suspend context is unique, this is a function-wide value. */
2615 data
->await_number
++;
2617 /* Awaitables should either be user-locals or promoted to coroutine frame
2618 entries at this point, and their initializers should have been broken
2620 tree aw
= TREE_OPERAND (aw_expr
, 1);
2621 gcc_checking_assert (!TREE_OPERAND (aw_expr
, 2));
2623 tree aw_field_type
= TREE_TYPE (aw
);
2624 tree aw_field_nam
= NULL_TREE
;
2625 register_await_info (aw_expr
, aw_field_type
, aw_field_nam
);
2627 /* Rewrite target expressions on the await_suspend () to remove extraneous
2628 cleanups for the awaitables, which are now promoted to frame vars and
2629 managed via that. */
2630 tree v
= TREE_OPERAND (aw_expr
, 3);
2631 tree o
= TREE_VEC_ELT (v
, 1);
2632 if (TREE_CODE (o
) == TARGET_EXPR
)
2633 TREE_VEC_ELT (v
, 1) = get_target_expr (TREE_OPERAND (o
, 1));
2637 /* There are cases where any await expression is relevant. */
2639 find_any_await (tree
*stmt
, int *dosub
, void *d
)
2641 if (TREE_CODE (*stmt
) == CO_AWAIT_EXPR
)
2643 *dosub
= 0; /* We don't need to consider this any further. */
2644 tree
**p
= (tree
**) d
;
2652 tmp_target_expr_p (tree t
)
2654 if (TREE_CODE (t
) != TARGET_EXPR
)
2656 tree v
= TREE_OPERAND (t
, 0);
2657 if (!DECL_ARTIFICIAL (v
))
2664 /* Structure to record sub-expressions that need to be handled by the
2665 statement flattener. */
2667 struct coro_interesting_subtree
2670 hash_set
<tree
> *temps_used
;
2673 /* tree-walk callback that returns the first encountered sub-expression of
2674 a kind that needs to be handled specifically by the statement flattener. */
2677 find_interesting_subtree (tree
*expr_p
, int *dosub
, void *d
)
2679 tree expr
= *expr_p
;
2680 coro_interesting_subtree
*p
= (coro_interesting_subtree
*)d
;
2681 if (TREE_CODE (expr
) == CO_AWAIT_EXPR
)
2683 *dosub
= 0; /* We don't need to consider this any further. */
2684 if (TREE_OPERAND (expr
, 2))
2690 else if (tmp_target_expr_p (expr
)
2691 && !TARGET_EXPR_ELIDING_P (expr
)
2692 && !p
->temps_used
->contains (expr
))
2701 /* Node for a doubly-linked list of promoted variables and their
2702 initializers. When the initializer is a conditional expression
2703 the 'then' and 'else' clauses are represented by a linked list
2704 attached to then_cl and else_cl respectively. */
2706 struct var_nest_node
2708 var_nest_node () = default;
2709 var_nest_node (tree v
, tree i
, var_nest_node
*p
, var_nest_node
*n
)
2710 : var(v
), init(i
), prev(p
), next(n
), then_cl (NULL
), else_cl (NULL
)
2719 var_nest_node
*prev
;
2720 var_nest_node
*next
;
2721 var_nest_node
*then_cl
;
2722 var_nest_node
*else_cl
;
2725 /* This is called for single statements from the co-await statement walker.
2726 It checks to see if the statement contains any initializers for awaitables
2727 and if any of these capture items by reference. */
2730 flatten_await_stmt (var_nest_node
*n
, hash_set
<tree
> *promoted
,
2731 hash_set
<tree
> *temps_used
, tree
*replace_in
)
2733 bool init_expr
= false;
2734 switch (TREE_CODE (n
->init
))
2737 /* Compound expressions must be flattened specifically. */
2740 tree first
= TREE_OPERAND (n
->init
, 0);
2741 n
->init
= TREE_OPERAND (n
->init
, 1);
2743 = new var_nest_node(NULL_TREE
, first
, n
->prev
, n
);
2744 /* The compiler (but not the user) can generate temporaries with
2745 uses in the second arm of a compound expr. */
2746 flatten_await_stmt (ins
, promoted
, temps_used
, &n
->init
);
2747 flatten_await_stmt (n
, promoted
, temps_used
, NULL
);
2748 /* The two arms have been processed separately. */
2752 /* Handle conditional expressions. */
2758 tree old_expr
= TREE_OPERAND (n
->init
, 1);
2759 if (TREE_CODE (old_expr
) == COMPOUND_EXPR
)
2761 tree first
= TREE_OPERAND (old_expr
, 0);
2762 TREE_OPERAND (n
->init
, 1) = TREE_OPERAND (old_expr
, 1);
2764 = new var_nest_node(NULL_TREE
, first
, n
->prev
, n
);
2765 flatten_await_stmt (ins
, promoted
, temps_used
,
2766 &TREE_OPERAND (n
->init
, 1));
2767 flatten_await_stmt (n
, promoted
, temps_used
, NULL
);
2770 if (TREE_CODE (old_expr
) != COND_EXPR
)
2772 /* Reconstruct x = t ? y : z;
2773 as (void) t ? x = y : x = z; */
2774 tree var
= TREE_OPERAND (n
->init
, 0);
2775 tree var_type
= TREE_TYPE (var
);
2776 tree cond
= COND_EXPR_COND (old_expr
);
2777 /* We are allowed a void type throw in one or both of the cond
2779 tree then_cl
= COND_EXPR_THEN (old_expr
);
2780 if (!VOID_TYPE_P (TREE_TYPE (then_cl
)))
2782 gcc_checking_assert (TREE_CODE (then_cl
) != STATEMENT_LIST
);
2784 then_cl
= cp_build_init_expr (var
, then_cl
);
2786 then_cl
= build2 (MODIFY_EXPR
, var_type
, var
, then_cl
);
2788 tree else_cl
= COND_EXPR_ELSE (old_expr
);
2789 if (!VOID_TYPE_P (TREE_TYPE (else_cl
)))
2791 gcc_checking_assert (TREE_CODE (else_cl
) != STATEMENT_LIST
);
2793 else_cl
= cp_build_init_expr (var
, else_cl
);
2795 else_cl
= build2 (MODIFY_EXPR
, var_type
, var
, else_cl
);
2797 n
->init
= build3 (COND_EXPR
, var_type
, cond
, then_cl
, else_cl
);
2803 tree cond
= COND_EXPR_COND (n
->init
);
2804 /* If the condition contains an await expression, then we need to
2805 set that first and use a separate var. */
2806 if (cp_walk_tree (&cond
, find_any_await
, &found
, NULL
))
2808 tree cond_type
= TREE_TYPE (cond
);
2809 tree cond_var
= build_lang_decl (VAR_DECL
, NULL_TREE
, cond_type
);
2810 DECL_ARTIFICIAL (cond_var
) = true;
2811 layout_decl (cond_var
, 0);
2812 gcc_checking_assert (!TYPE_NEEDS_CONSTRUCTING (cond_type
));
2813 cond
= cp_build_init_expr (cond_var
, cond
);
2815 = new var_nest_node (cond_var
, cond
, n
->prev
, n
);
2816 COND_EXPR_COND (n
->init
) = cond_var
;
2817 flatten_await_stmt (ins
, promoted
, temps_used
, NULL
);
2821 = new var_nest_node (n
->var
, COND_EXPR_THEN (n
->init
), NULL
, NULL
);
2823 = new var_nest_node (n
->var
, COND_EXPR_ELSE (n
->init
), NULL
, NULL
);
2824 flatten_await_stmt (n
->then_cl
, promoted
, temps_used
, NULL
);
2825 /* Point to the start of the flattened code. */
2826 while (n
->then_cl
->prev
)
2827 n
->then_cl
= n
->then_cl
->prev
;
2828 flatten_await_stmt (n
->else_cl
, promoted
, temps_used
, NULL
);
2829 while (n
->else_cl
->prev
)
2830 n
->else_cl
= n
->else_cl
->prev
;
2835 coro_interesting_subtree v
= { NULL
, temps_used
};
2836 tree t
= cp_walk_tree (&n
->init
, find_interesting_subtree
, (void *)&v
, NULL
);
2839 switch (TREE_CODE (t
))
2844 /* Await expressions with initializers have a compiler-temporary
2845 as the awaitable. 'promote' this. */
2846 tree var
= TREE_OPERAND (t
, 1);
2847 bool already_present
= promoted
->add (var
);
2848 gcc_checking_assert (!already_present
);
2849 tree init
= TREE_OPERAND (t
, 2);
2850 switch (TREE_CODE (init
))
2856 tree inner
= TREE_OPERAND (init
, 1);
2857 /* We can have non-lvalue-expressions here, but when we see
2858 a target expression, mark it as already used. */
2859 if (TREE_CODE (inner
) == TARGET_EXPR
)
2861 temps_used
->add (inner
);
2863 (TREE_CODE (TREE_OPERAND (inner
, 1)) != COND_EXPR
);
2868 /* If this is a call and not a CTOR, then we didn't expect it. */
2870 (DECL_CONSTRUCTOR_P (TREE_OPERAND (CALL_EXPR_FN (init
), 0)));
2873 var_nest_node
*ins
= new var_nest_node (var
, init
, n
->prev
, n
);
2874 TREE_OPERAND (t
, 2) = NULL_TREE
;
2875 flatten_await_stmt (ins
, promoted
, temps_used
, NULL
);
2876 flatten_await_stmt (n
, promoted
, temps_used
, NULL
);
2882 /* We have a temporary; promote it, but allow for the idiom in code
2883 generated by the compiler like
2884 a = (target_expr produces temp, op uses temp). */
2886 temps_used
->add (init
);
2887 tree var_type
= TREE_TYPE (init
);
2888 char *buf
= xasprintf ("T%03u", (unsigned) temps_used
->elements ());
2889 tree var
= build_lang_decl (VAR_DECL
, get_identifier (buf
), var_type
);
2890 DECL_ARTIFICIAL (var
) = true;
2892 bool already_present
= promoted
->add (var
);
2893 gcc_checking_assert (!already_present
);
2894 tree inner
= TREE_OPERAND (init
, 1);
2895 gcc_checking_assert (TREE_CODE (inner
) != COND_EXPR
);
2896 init
= cp_build_modify_expr (input_location
, var
, INIT_EXPR
, init
,
2897 tf_warning_or_error
);
2898 /* Simplify for the case that we have an init containing the temp
2900 if (t
== n
->init
&& n
->var
== NULL_TREE
)
2903 proxy_replace pr
= {TREE_OPERAND (t
, 0), var
};
2904 cp_walk_tree (&init
, replace_proxy
, &pr
, NULL
);
2907 cp_walk_tree (replace_in
, replace_proxy
, &pr
, NULL
);
2908 flatten_await_stmt (n
, promoted
, temps_used
, NULL
);
2913 = new var_nest_node (var
, init
, n
->prev
, n
);
2914 /* We have to replace the target expr... */
2916 /* ... and any uses of its var. */
2917 proxy_replace pr
= {TREE_OPERAND (t
, 0), var
};
2918 cp_walk_tree (&n
->init
, replace_proxy
, &pr
, NULL
);
2919 /* Compiler-generated temporaries can also have uses in
2920 following arms of compound expressions, which will be listed
2921 in 'replace_in' if present. */
2923 cp_walk_tree (replace_in
, replace_proxy
, &pr
, NULL
);
2924 flatten_await_stmt (ins
, promoted
, temps_used
, NULL
);
2925 flatten_await_stmt (n
, promoted
, temps_used
, NULL
);
2933 /* Helper for 'process_conditional' that handles recursion into nested
2937 handle_nested_conditionals (var_nest_node
*n
, vec
<tree
>& list
,
2938 hash_map
<tree
, tree
>& map
)
2942 if (n
->var
&& DECL_NAME (n
->var
))
2944 list
.safe_push (n
->var
);
2945 if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (n
->var
)))
2948 tree
& flag
= map
.get_or_insert (n
->var
, &existed
);
2951 /* We didn't see this var before and it needs a DTOR, so
2952 build a guard variable for it. */
2954 = xasprintf ("%s_guard",
2955 IDENTIFIER_POINTER (DECL_NAME (n
->var
)));
2956 flag
= build_lang_decl (VAR_DECL
, get_identifier (nam
),
2959 DECL_ARTIFICIAL (flag
) = true;
2962 /* The initializer for this variable is replaced by a compound
2963 expression that performs the init and then records that the
2964 variable is live (and the DTOR should be run at the scope
2966 tree set_flag
= cp_build_init_expr (flag
, boolean_true_node
);
2968 = build2 (COMPOUND_EXPR
, boolean_type_node
, n
->init
, set_flag
);
2971 if (TREE_CODE (n
->init
) == COND_EXPR
)
2973 tree new_then
= push_stmt_list ();
2974 handle_nested_conditionals (n
->then_cl
, list
, map
);
2975 new_then
= pop_stmt_list (new_then
);
2976 tree new_else
= push_stmt_list ();
2977 handle_nested_conditionals (n
->else_cl
, list
, map
);
2978 new_else
= pop_stmt_list (new_else
);
2980 = build4 (IF_STMT
, void_type_node
, COND_EXPR_COND (n
->init
),
2981 new_then
, new_else
, NULL_TREE
);
2985 finish_expr_stmt (n
->init
);
2990 /* helper for 'maybe_promote_temps'.
2992 When we have a conditional expression which might embed await expressions
2993 and/or promoted variables, we need to handle it appropriately.
2995 The linked lists for the 'then' and 'else' clauses in a conditional node
2996 identify the promoted variables (but these cannot be wrapped in a regular
2999 So recurse through the lists and build up a composite list of captured vars.
3000 Declare these and any guard variables needed to decide if a DTOR should be
3001 run. Then embed the conditional into a try-finally expression that handles
3002 running each DTOR conditionally on its guard variable. */
3005 process_conditional (var_nest_node
*n
, tree
& vlist
)
3007 tree init
= n
->init
;
3008 hash_map
<tree
, tree
> var_flags
;
3009 auto_vec
<tree
> var_list
;
3010 tree new_then
= push_stmt_list ();
3011 handle_nested_conditionals (n
->then_cl
, var_list
, var_flags
);
3012 new_then
= pop_stmt_list (new_then
);
3013 tree new_else
= push_stmt_list ();
3014 handle_nested_conditionals (n
->else_cl
, var_list
, var_flags
);
3015 new_else
= pop_stmt_list (new_else
);
3016 /* Declare the vars. There are two loops so that the boolean flags are
3017 grouped in the frame. */
3018 for (unsigned i
= 0; i
< var_list
.length(); i
++)
3020 tree var
= var_list
[i
];
3021 DECL_CHAIN (var
) = vlist
;
3023 add_decl_expr (var
);
3025 /* Define the guard flags for variables that need a DTOR. */
3026 for (unsigned i
= 0; i
< var_list
.length(); i
++)
3028 tree
*flag
= var_flags
.get (var_list
[i
]);
3031 DECL_INITIAL (*flag
) = boolean_false_node
;
3032 DECL_CHAIN (*flag
) = vlist
;
3034 add_decl_expr (*flag
);
3038 = build4 (IF_STMT
, void_type_node
, COND_EXPR_COND (init
),
3039 new_then
, new_else
, NULL_TREE
);
3040 /* Build a set of conditional DTORs. */
3041 tree final_actions
= push_stmt_list ();
3042 while (!var_list
.is_empty())
3044 tree var
= var_list
.pop ();
3045 tree
*flag
= var_flags
.get (var
);
3048 tree var_type
= TREE_TYPE (var
);
3050 = build_special_member_call (var
, complete_dtor_identifier
,
3051 NULL
, var_type
, LOOKUP_NORMAL
,
3052 tf_warning_or_error
);
3053 tree cond_cleanup
= begin_if_stmt ();
3054 finish_if_stmt_cond (*flag
, cond_cleanup
);
3055 finish_expr_stmt (cleanup
);
3056 finish_then_clause (cond_cleanup
);
3057 finish_if_stmt (cond_cleanup
);
3059 final_actions
= pop_stmt_list (final_actions
);
3061 = build2 (TRY_FINALLY_EXPR
, void_type_node
, new_if
, final_actions
);
3062 add_stmt (try_finally
);
3065 /* Given *STMT, that contains at least one await expression.
3067 The full expression represented in the original source code will contain
3068 suspension points, but it is still required that the lifetime of temporary
3069 values extends to the end of the expression.
3071 We already have a mechanism to 'promote' user-authored local variables
3072 to a coroutine frame counterpart (which allows explicit management of the
3073 lifetime across suspensions). The transform here re-writes STMT into
3074 a bind expression, promotes temporary values into local variables in that
3075 and flattens the statement into a series of cleanups.
3077 Conditional expressions are re-written to regular 'if' statements.
3078 The cleanups for variables initialized inside a conditional (including
3079 nested cases) are wrapped in a try-finally clause, with guard variables
3080 to determine which DTORs need to be run. */
3083 maybe_promote_temps (tree
*stmt
, void *d
)
3085 susp_frame_data
*awpts
= (susp_frame_data
*) d
;
3087 location_t sloc
= EXPR_LOCATION (*stmt
);
3089 /* Strip off uninteresting wrappers. */
3090 if (TREE_CODE (expr
) == CLEANUP_POINT_EXPR
)
3091 expr
= TREE_OPERAND (expr
, 0);
3092 if (TREE_CODE (expr
) == EXPR_STMT
)
3093 expr
= EXPR_STMT_EXPR (expr
);
3094 if (TREE_CODE (expr
) == CONVERT_EXPR
3095 && VOID_TYPE_P (TREE_TYPE (expr
)))
3096 expr
= TREE_OPERAND (expr
, 0);
3099 /* We walk the statement trees, flattening it into an ordered list of
3100 variables with initializers and fragments corresponding to compound
3101 expressions, truth or/and if and ternary conditionals. Conditional
3102 expressions carry a nested list of fragments for the then and else
3103 clauses. We anchor to the 'bottom' of the fragment list; we will write
3104 a cleanup nest with one shell for each variable initialized. */
3105 var_nest_node
*root
= new var_nest_node (NULL_TREE
, expr
, NULL
, NULL
);
3106 /* Check to see we didn't promote one twice. */
3107 hash_set
<tree
> promoted_vars
;
3108 hash_set
<tree
> used_temps
;
3109 flatten_await_stmt (root
, &promoted_vars
, &used_temps
, NULL
);
3111 gcc_checking_assert (root
->next
== NULL
);
3112 tree vlist
= NULL_TREE
;
3113 var_nest_node
*t
= root
;
3114 /* We build the bind scope expression from the bottom-up.
3115 EXPR_LIST holds the inner expression nest at the current cleanup
3116 level (becoming the final expression list when we've exhausted the
3117 number of sub-expression fragments). */
3118 tree expr_list
= NULL_TREE
;
3121 tree new_list
= push_stmt_list ();
3122 /* When we have a promoted variable, then add that to the bind scope
3123 and initialize it. When there's no promoted variable, we just need
3124 to run the initializer.
3125 If the initializer is a conditional expression, we need to collect
3126 and declare any promoted variables nested within it. DTORs for such
3127 variables must be run conditionally too. */
3131 DECL_CHAIN (var
) = vlist
;
3133 add_decl_expr (var
);
3134 if (TREE_CODE (t
->init
) == COND_EXPR
)
3135 process_conditional (t
, vlist
);
3137 finish_expr_stmt (t
->init
);
3138 tree var_type
= TREE_TYPE (var
);
3139 if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (var_type
))
3142 = build_special_member_call (var
, complete_dtor_identifier
,
3143 NULL
, var_type
, LOOKUP_NORMAL
,
3144 tf_warning_or_error
);
3145 tree cl
= build_stmt (sloc
, CLEANUP_STMT
, expr_list
, cleanup
, var
);
3146 add_stmt (cl
); /* push this onto the level above. */
3150 if (TREE_CODE (expr_list
) != STATEMENT_LIST
)
3151 add_stmt (expr_list
);
3152 else if (!tsi_end_p (tsi_start (expr_list
)))
3153 add_stmt (expr_list
);
3158 if (TREE_CODE (t
->init
) == COND_EXPR
)
3159 process_conditional (t
, vlist
);
3161 finish_expr_stmt (t
->init
);
3164 if (TREE_CODE (expr_list
) != STATEMENT_LIST
)
3165 add_stmt (expr_list
);
3166 else if (!tsi_end_p (tsi_start (expr_list
)))
3167 add_stmt (expr_list
);
3170 expr_list
= pop_stmt_list (new_list
);
3171 var_nest_node
*old
= t
;
3176 /* Now produce the bind expression containing the 'promoted' temporaries
3177 as its variable list, and the cleanup nest as the statement. */
3178 tree await_bind
= build3_loc (sloc
, BIND_EXPR
, void_type_node
,
3180 BIND_EXPR_BODY (await_bind
) = expr_list
;
3181 BIND_EXPR_VARS (await_bind
) = nreverse (vlist
);
3182 tree b_block
= make_node (BLOCK
);
3183 if (!awpts
->block_stack
->is_empty ())
3185 tree s_block
= awpts
->block_stack
->last ();
3188 BLOCK_SUPERCONTEXT (b_block
) = s_block
;
3189 BLOCK_CHAIN (b_block
) = BLOCK_SUBBLOCKS (s_block
);
3190 BLOCK_SUBBLOCKS (s_block
) = b_block
;
3193 BLOCK_VARS (b_block
) = BIND_EXPR_VARS (await_bind
) ;
3194 BIND_EXPR_BLOCK (await_bind
) = b_block
;
3195 TREE_SIDE_EFFECTS (await_bind
) = TREE_SIDE_EFFECTS (BIND_EXPR_BODY (await_bind
));
3197 hash_set
<tree
> visited
;
3198 return cp_walk_tree (stmt
, register_awaits
, d
, &visited
);
3201 /* Lightweight callback to determine two key factors:
3202 1) If the statement/expression contains any await expressions.
3203 2) If the statement/expression potentially requires a re-write to handle
3204 TRUTH_{AND,OR}IF_EXPRs since, in most cases, they will need expansion
3205 so that the await expressions are not processed in the case of the
3208 CO_YIELD expressions are re-written to their underlying co_await. */
3211 analyze_expression_awaits (tree
*stmt
, int *do_subtree
, void *d
)
3213 susp_frame_data
*awpts
= (susp_frame_data
*) d
;
3215 switch (TREE_CODE (*stmt
))
3217 default: return NULL_TREE
;
3219 /* co_yield is syntactic sugar, re-write it to co_await. */
3220 *stmt
= TREE_OPERAND (*stmt
, 1);
3223 awpts
->saw_awaits
++;
3224 /* A non-null initializer for the awaiter means we need to expand. */
3225 if (TREE_OPERAND (*stmt
, 2))
3226 awpts
->has_awaiter_init
= true;
3228 case TRUTH_ANDIF_EXPR
:
3229 case TRUTH_ORIF_EXPR
:
3231 /* We don't need special action for awaits in the always-executed
3232 arm of a TRUTH_IF. */
3233 if (tree res
= cp_walk_tree (&TREE_OPERAND (*stmt
, 0),
3234 analyze_expression_awaits
, d
, NULL
))
3236 /* However, if there are await expressions on the conditionally
3237 executed branch, we must expand the TRUTH_IF to ensure that the
3238 expanded await expression control-flow is fully contained in the
3239 conditionally executed code. */
3240 unsigned aw_count
= awpts
->saw_awaits
;
3241 if (tree res
= cp_walk_tree (&TREE_OPERAND (*stmt
, 1),
3242 analyze_expression_awaits
, d
, NULL
))
3244 if (awpts
->saw_awaits
> aw_count
)
3246 awpts
->truth_aoif_to_expand
->add (*stmt
);
3247 awpts
->needs_truth_if_exp
= true;
3249 /* We've done the sub-trees here. */
3255 return NULL_TREE
; /* Recurse until done. */
3259 If EXPR contains a TRUTH_{AND,OR}IF_EXPR, TAOIE with an await expr on
3260 the conditionally executed branch, change this in a ternary operator.
3262 bool not_expr = TAOIE == TRUTH_ORIF_EXPR ? NOT : NOP;
3263 not_expr (always-exec expr) ? conditionally-exec expr : not_expr;
3265 Apply this recursively to the condition and the conditionally-exec
3268 struct truth_if_transform
{
3271 hash_set
<tree
> *truth_aoif_to_expand
;
3275 expand_one_truth_if (tree
*expr
, int *do_subtree
, void *d
)
3277 truth_if_transform
*xform
= (truth_if_transform
*) d
;
3279 bool needs_not
= false;
3280 switch (TREE_CODE (*expr
))
3283 case TRUTH_ORIF_EXPR
:
3286 case TRUTH_ANDIF_EXPR
:
3288 if (!xform
->truth_aoif_to_expand
->contains (*expr
))
3291 location_t sloc
= EXPR_LOCATION (*expr
);
3292 /* Transform truth expression into a cond expression with
3293 * the always-executed arm as the condition.
3294 * the conditionally-executed arm as the then clause.
3295 * the 'else' clause is fixed: 'true' for ||,'false' for &&. */
3296 tree cond
= TREE_OPERAND (*expr
, 0);
3297 tree test1
= TREE_OPERAND (*expr
, 1);
3298 tree fixed
= needs_not
? boolean_true_node
: boolean_false_node
;
3300 cond
= build1 (TRUTH_NOT_EXPR
, boolean_type_node
, cond
);
3302 = build3_loc (sloc
, COND_EXPR
, boolean_type_node
,
3303 cond
, test1
, fixed
);
3305 if (tree res
= cp_walk_tree (&COND_EXPR_COND (*expr
),
3306 expand_one_truth_if
, d
, NULL
))
3308 if (tree res
= cp_walk_tree (&COND_EXPR_THEN (*expr
),
3309 expand_one_truth_if
, d
, NULL
))
3311 /* We've manually processed necessary sub-trees here. */
3319 /* Helper that adds a new variable of VAR_TYPE to a bind scope BIND, the
3320 name is made up from NAM_ROOT, NAM_VERS. */
3323 add_var_to_bind (tree
& bind
, tree var_type
,
3324 const char *nam_root
, unsigned nam_vers
)
3326 tree b_vars
= BIND_EXPR_VARS (bind
);
3327 /* Build a variable to hold the condition, this will be included in the
3328 frame as a local var. */
3329 char *nam
= xasprintf ("__%s_%d", nam_root
, nam_vers
);
3330 tree newvar
= build_lang_decl (VAR_DECL
, get_identifier (nam
), var_type
);
3332 DECL_CHAIN (newvar
) = b_vars
;
3333 BIND_EXPR_VARS (bind
) = newvar
;
3337 /* Helper to build and add if (!cond) break; */
3340 coro_build_add_if_not_cond_break (tree cond
)
3342 tree if_stmt
= begin_if_stmt ();
3343 tree invert
= build1 (TRUTH_NOT_EXPR
, boolean_type_node
, cond
);
3344 finish_if_stmt_cond (invert
, if_stmt
);
3345 finish_break_stmt ();
3346 finish_then_clause (if_stmt
);
3347 finish_if_stmt (if_stmt
);
3350 /* Tree walk callback to replace continue statements with goto label. */
3352 replace_continue (tree
*stmt
, int *do_subtree
, void *d
)
3355 if (TREE_CODE (expr
) == CLEANUP_POINT_EXPR
)
3356 expr
= TREE_OPERAND (expr
, 0);
3357 if (CONVERT_EXPR_P (expr
) && VOID_TYPE_P (expr
))
3358 expr
= TREE_OPERAND (expr
, 0);
3360 if (!STATEMENT_CLASS_P (expr
))
3363 switch (TREE_CODE (expr
))
3365 /* Unless it's a special case, just walk the subtrees as usual. */
3366 default: return NULL_TREE
;
3370 tree
*label
= (tree
*)d
;
3371 location_t loc
= EXPR_LOCATION (expr
);
3372 /* re-write a continue to goto label. */
3373 *stmt
= build_stmt (loc
, GOTO_EXPR
, *label
);
3378 /* Statements that do not require recursion. */
3383 case CASE_LABEL_EXPR
:
3385 /* These must break recursion. */
3394 /* Tree walk callback to analyze, register and pre-process statements that
3395 contain await expressions. */
3398 await_statement_walker (tree
*stmt
, int *do_subtree
, void *d
)
3400 tree res
= NULL_TREE
;
3401 susp_frame_data
*awpts
= (susp_frame_data
*) d
;
3403 /* Process a statement at a time. */
3404 if (TREE_CODE (*stmt
) == BIND_EXPR
)
3406 /* For conditional expressions, we might wish to add an artificial var
3407 to their containing bind expr. */
3408 vec_safe_push (awpts
->bind_stack
, *stmt
);
3409 /* We might need to insert a new bind expression, and want to link it
3410 into the correct scope, so keep a note of the current block scope. */
3411 tree blk
= BIND_EXPR_BLOCK (*stmt
);
3412 vec_safe_push (awpts
->block_stack
, blk
);
3413 res
= cp_walk_tree (&BIND_EXPR_BODY (*stmt
), await_statement_walker
,
3415 awpts
->block_stack
->pop ();
3416 awpts
->bind_stack
->pop ();
3417 *do_subtree
= 0; /* Done subtrees. */
3420 else if (TREE_CODE (*stmt
) == STATEMENT_LIST
)
3422 for (tree
&s
: tsi_range (*stmt
))
3424 res
= cp_walk_tree (&s
, await_statement_walker
,
3429 *do_subtree
= 0; /* Done subtrees. */
3433 /* We have something to be handled as a single statement. We have to handle
3434 a few statements specially where await statements have to be moved out of
3437 if (TREE_CODE (*stmt
) == CLEANUP_POINT_EXPR
)
3438 expr
= TREE_OPERAND (expr
, 0);
3441 if (STATEMENT_CLASS_P (expr
))
3442 switch (TREE_CODE (expr
))
3444 /* Unless it's a special case, just walk the subtrees as usual. */
3445 default: return NULL_TREE
;
3447 /* When we have a conditional expression, which contains one or more
3448 await expressions, we have to break the condition out into a
3449 regular statement so that the control flow introduced by the await
3450 transforms can be implemented. */
3454 hash_set
<tree
> visited
;
3455 /* Transform 'if (cond with awaits) then stmt1 else stmt2' into
3456 bool cond = cond with awaits.
3457 if (cond) then stmt1 else stmt2. */
3458 tree if_stmt
= *stmt
;
3459 /* We treat the condition as if it was a stand-alone statement,
3460 to see if there are any await expressions which will be analyzed
3462 if (!(cp_walk_tree (&IF_COND (if_stmt
),
3463 find_any_await
, &await_ptr
, &visited
)))
3464 return NULL_TREE
; /* Nothing special to do here. */
3466 gcc_checking_assert (!awpts
->bind_stack
->is_empty());
3467 tree
& bind_expr
= awpts
->bind_stack
->last ();
3468 tree newvar
= add_var_to_bind (bind_expr
, boolean_type_node
,
3469 "ifcd", awpts
->cond_number
++);
3470 tree insert_list
= push_stmt_list ();
3471 tree cond_inner
= IF_COND (if_stmt
);
3472 if (TREE_CODE (cond_inner
) == CLEANUP_POINT_EXPR
)
3473 cond_inner
= TREE_OPERAND (cond_inner
, 0);
3474 add_decl_expr (newvar
);
3475 location_t sloc
= EXPR_LOCATION (IF_COND (if_stmt
));
3476 /* We want to initialize the new variable with the expression
3477 that contains the await(s) and potentially also needs to
3478 have truth_if expressions expanded. */
3479 tree new_s
= cp_build_init_expr (sloc
, newvar
, cond_inner
);
3480 finish_expr_stmt (new_s
);
3481 IF_COND (if_stmt
) = newvar
;
3483 *stmt
= pop_stmt_list (insert_list
);
3484 /* So now walk the new statement list. */
3485 res
= cp_walk_tree (stmt
, await_statement_walker
, d
, NULL
);
3486 *do_subtree
= 0; /* Done subtrees. */
3493 hash_set
<tree
> visited
;
3494 /* for loops only need special treatment if the condition or the
3495 iteration expression contain a co_await. */
3496 tree for_stmt
= *stmt
;
3497 /* At present, the FE always generates a separate initializer for
3498 the FOR_INIT_STMT, when the expression has an await. Check that
3499 this assumption holds in the future. */
3501 (!(cp_walk_tree (&FOR_INIT_STMT (for_stmt
), find_any_await
,
3502 &await_ptr
, &visited
)));
3506 = cp_walk_tree (&FOR_COND (for_stmt
), find_any_await
,
3507 &await_ptr
, &visited
);
3511 = cp_walk_tree (&FOR_EXPR (for_stmt
), find_any_await
,
3512 &await_ptr
, &visited
);
3514 /* If the condition has an await, then we will need to rewrite the
3516 for (init expression;true;iteration expression) {
3517 condition = await expression;
3525 tree insert_list
= push_stmt_list ();
3526 /* This will be expanded when the revised body is handled. */
3527 coro_build_add_if_not_cond_break (FOR_COND (for_stmt
));
3528 /* .. add the original for body. */
3529 add_stmt (FOR_BODY (for_stmt
));
3530 /* To make the new for body. */
3531 FOR_BODY (for_stmt
) = pop_stmt_list (insert_list
);
3532 FOR_COND (for_stmt
) = boolean_true_node
;
3534 /* If the iteration expression has an await, it's a bit more
3536 for (init expression;condition;) {
3538 iteration_expr_label:
3539 iteration expression with await;
3541 but, then we will need to re-write any continue statements into
3542 'goto iteration_expr_label:'.
3546 location_t sloc
= EXPR_LOCATION (FOR_EXPR (for_stmt
));
3547 tree insert_list
= push_stmt_list ();
3548 /* The original for body. */
3549 add_stmt (FOR_BODY (for_stmt
));
3550 char *buf
= xasprintf ("for.iter.expr.%u", awpts
->cond_number
++);
3552 = create_named_label_with_ctx (sloc
, buf
, NULL_TREE
);
3554 add_stmt (build_stmt (sloc
, LABEL_EXPR
, it_expr_label
));
3555 tree for_expr
= FOR_EXPR (for_stmt
);
3556 /* Present the iteration expression as a statement. */
3557 if (TREE_CODE (for_expr
) == CLEANUP_POINT_EXPR
)
3558 for_expr
= TREE_OPERAND (for_expr
, 0);
3559 STRIP_NOPS (for_expr
);
3560 finish_expr_stmt (for_expr
);
3561 FOR_EXPR (for_stmt
) = NULL_TREE
;
3562 FOR_BODY (for_stmt
) = pop_stmt_list (insert_list
);
3563 /* rewrite continue statements to goto label. */
3564 hash_set
<tree
> visited_continue
;
3565 if ((res
= cp_walk_tree (&FOR_BODY (for_stmt
),
3566 replace_continue
, &it_expr_label
, &visited_continue
)))
3570 /* So now walk the body statement (list), if there were no await
3571 expressions, then this handles the original body - and either
3572 way we will have finished with this statement. */
3573 res
= cp_walk_tree (&FOR_BODY (for_stmt
),
3574 await_statement_walker
, d
, NULL
);
3575 *do_subtree
= 0; /* Done subtrees. */
3581 /* We turn 'while (cond with awaits) stmt' into
3583 if (!(cond with awaits))
3588 hash_set
<tree
> visited
;
3589 tree while_stmt
= *stmt
;
3590 if (!(cp_walk_tree (&WHILE_COND (while_stmt
),
3591 find_any_await
, &await_ptr
, &visited
)))
3592 return NULL_TREE
; /* Nothing special to do here. */
3594 tree insert_list
= push_stmt_list ();
3595 coro_build_add_if_not_cond_break (WHILE_COND (while_stmt
));
3596 /* The original while body. */
3597 add_stmt (WHILE_BODY (while_stmt
));
3598 /* The new while body. */
3599 WHILE_BODY (while_stmt
) = pop_stmt_list (insert_list
);
3600 WHILE_COND (while_stmt
) = boolean_true_node
;
3601 /* So now walk the new statement list. */
3602 res
= cp_walk_tree (&WHILE_BODY (while_stmt
),
3603 await_statement_walker
, d
, NULL
);
3604 *do_subtree
= 0; /* Done subtrees. */
3610 /* We turn do stmt while (cond with awaits) into:
3613 if (!(cond with awaits))
3616 tree do_stmt
= *stmt
;
3618 hash_set
<tree
> visited
;
3619 if (!(cp_walk_tree (&DO_COND (do_stmt
),
3620 find_any_await
, &await_ptr
, &visited
)))
3621 return NULL_TREE
; /* Nothing special to do here. */
3623 tree insert_list
= push_stmt_list ();
3624 /* The original do stmt body. */
3625 add_stmt (DO_BODY (do_stmt
));
3626 coro_build_add_if_not_cond_break (DO_COND (do_stmt
));
3627 /* The new while body. */
3628 DO_BODY (do_stmt
) = pop_stmt_list (insert_list
);
3629 DO_COND (do_stmt
) = boolean_true_node
;
3630 /* So now walk the new statement list. */
3631 res
= cp_walk_tree (&DO_BODY (do_stmt
), await_statement_walker
,
3633 *do_subtree
= 0; /* Done subtrees. */
3639 /* We turn 'switch (cond with awaits) stmt' into
3640 switch_type cond = cond with awaits
3641 switch (cond) stmt. */
3642 tree sw_stmt
= *stmt
;
3644 hash_set
<tree
> visited
;
3645 if (!(cp_walk_tree (&SWITCH_STMT_COND (sw_stmt
),
3646 find_any_await
, &await_ptr
, &visited
)))
3647 return NULL_TREE
; /* Nothing special to do here. */
3649 gcc_checking_assert (!awpts
->bind_stack
->is_empty());
3650 /* Build a variable to hold the condition, this will be
3651 included in the frame as a local var. */
3652 tree
& bind_expr
= awpts
->bind_stack
->last ();
3653 tree sw_type
= SWITCH_STMT_TYPE (sw_stmt
);
3654 tree newvar
= add_var_to_bind (bind_expr
, sw_type
, "swch",
3655 awpts
->cond_number
++);
3656 tree insert_list
= push_stmt_list ();
3657 add_decl_expr (newvar
);
3659 tree cond_inner
= SWITCH_STMT_COND (sw_stmt
);
3660 if (TREE_CODE (cond_inner
) == CLEANUP_POINT_EXPR
)
3661 cond_inner
= TREE_OPERAND (cond_inner
, 0);
3662 location_t sloc
= EXPR_LOCATION (SWITCH_STMT_COND (sw_stmt
));
3663 tree new_s
= cp_build_init_expr (sloc
, newvar
,
3665 finish_expr_stmt (new_s
);
3666 SWITCH_STMT_COND (sw_stmt
) = newvar
;
3667 /* Now add the switch statement with the condition re-
3668 written to use the local var. */
3670 *stmt
= pop_stmt_list (insert_list
);
3671 /* Process the expanded list. */
3672 res
= cp_walk_tree (stmt
, await_statement_walker
,
3674 *do_subtree
= 0; /* Done subtrees. */
3678 case CO_RETURN_EXPR
:
3680 /* Expand the co_return as per [stmt.return.coroutine]
3682 { p.return_void (); goto final_suspend; }
3683 - for co_return [void expr];
3684 { expr; p.return_void(); goto final_suspend;}
3685 - for co_return [non void expr];
3686 { p.return_value(expr); goto final_suspend; } */
3687 location_t loc
= EXPR_LOCATION (expr
);
3688 tree call
= TREE_OPERAND (expr
, 1);
3689 expr
= TREE_OPERAND (expr
, 0);
3690 tree ret_list
= push_stmt_list ();
3691 /* [stmt.return.coroutine], 2.2
3692 If expr is present and void, it is placed immediately before
3693 the call for return_void; */
3694 if (expr
&& VOID_TYPE_P (TREE_TYPE (expr
)))
3695 finish_expr_stmt (expr
);
3696 /* Insert p.return_{void,value(expr)}. */
3697 finish_expr_stmt (call
);
3698 TREE_USED (awpts
->fs_label
) = 1;
3699 add_stmt (build_stmt (loc
, GOTO_EXPR
, awpts
->fs_label
));
3700 *stmt
= pop_stmt_list (ret_list
);
3701 res
= cp_walk_tree (stmt
, await_statement_walker
, d
, NULL
);
3702 /* Once this is complete, we will have processed subtrees. */
3709 /* [expr.await] An await-expression shall appear only in a
3710 potentially-evaluated expression within the compound-statement
3711 of a function-body outside of a handler. */
3713 hash_set
<tree
> visited
;
3714 if (!(cp_walk_tree (&HANDLER_BODY (expr
), find_any_await
,
3715 &await_ptr
, &visited
)))
3716 return NULL_TREE
; /* All OK. */
3717 location_t loc
= EXPR_LOCATION (*await_ptr
);
3718 error_at (loc
, "await expressions are not permitted in handlers");
3719 return NULL_TREE
; /* This is going to fail later anyway. */
3723 else if (EXPR_P (expr
))
3725 hash_set
<tree
> visited
;
3727 if (!(cp_walk_tree (stmt
, find_any_await
, &await_ptr
, &visited
)))
3728 return NULL_TREE
; /* Nothing special to do here. */
3731 awpts
->saw_awaits
= 0;
3732 hash_set
<tree
> truth_aoif_to_expand
;
3733 awpts
->truth_aoif_to_expand
= &truth_aoif_to_expand
;
3734 awpts
->needs_truth_if_exp
= false;
3735 awpts
->has_awaiter_init
= false;
3736 if ((res
= cp_walk_tree (stmt
, analyze_expression_awaits
, d
, &visited
)))
3738 *do_subtree
= 0; /* Done subtrees. */
3739 if (!awpts
->saw_awaits
)
3740 return NULL_TREE
; /* Nothing special to do here. */
3742 if (awpts
->needs_truth_if_exp
)
3744 /* If a truth-and/or-if expression has an await expression in the
3745 conditionally-taken branch, then it must be rewritten into a
3746 regular conditional. */
3747 truth_if_transform xf
= {stmt
, NULL_TREE
, &truth_aoif_to_expand
};
3748 if ((res
= cp_walk_tree (stmt
, expand_one_truth_if
, &xf
, NULL
)))
3751 /* Process this statement, which contains at least one await expression
3752 to 'promote' temporary values to a coroutine frame slot. */
3753 return maybe_promote_temps (stmt
, d
);
3755 /* Continue recursion, if needed. */
3759 /* For figuring out what param usage we have. */
3761 struct param_frame_data
3764 hash_map
<tree
, param_info
> *param_uses
;
3765 hash_set
<tree
*> *visited
;
3770 /* A tree walk callback that rewrites each parm use to the local variable
3771 that represents its copy in the frame. */
3774 rewrite_param_uses (tree
*stmt
, int *do_subtree ATTRIBUTE_UNUSED
, void *d
)
3776 param_frame_data
*data
= (param_frame_data
*) d
;
3778 /* For lambda closure content, we have to look specifically. */
3779 if (VAR_P (*stmt
) && DECL_HAS_VALUE_EXPR_P (*stmt
))
3781 tree t
= DECL_VALUE_EXPR (*stmt
);
3782 return cp_walk_tree (&t
, rewrite_param_uses
, d
, NULL
);
3785 if (TREE_CODE (*stmt
) != PARM_DECL
)
3788 /* If we already saw the containing expression, then we're done. */
3789 if (data
->visited
->add (stmt
))
3793 param_info
&parm
= data
->param_uses
->get_or_insert (*stmt
, &existed
);
3794 gcc_checking_assert (existed
);
3796 *stmt
= parm
.copy_var
;
3800 /* Build up a set of info that determines how each param copy will be
3803 static hash_map
<tree
, param_info
> *
3804 analyze_fn_parms (tree orig
)
3806 if (!DECL_ARGUMENTS (orig
))
3809 hash_map
<tree
, param_info
> *param_uses
= new hash_map
<tree
, param_info
>;
3811 /* Build a hash map with an entry for each param.
3812 The key is the param tree.
3813 Then we have an entry for the frame field name.
3814 Then a cache for the field ref when we come to use it.
3815 Then a tree list of the uses.
3816 The second two entries start out empty - and only get populated
3817 when we see uses. */
3818 bool lambda_p
= LAMBDA_FUNCTION_P (orig
);
3820 unsigned no_name_parm
= 0;
3821 for (tree arg
= DECL_ARGUMENTS (orig
); arg
!= NULL
; arg
= DECL_CHAIN (arg
))
3824 param_info
&parm
= param_uses
->get_or_insert (arg
, &existed
);
3825 gcc_checking_assert (!existed
);
3826 parm
.body_uses
= NULL
;
3827 tree actual_type
= TREE_TYPE (arg
);
3828 actual_type
= complete_type_or_else (actual_type
, orig
);
3829 if (actual_type
== NULL_TREE
)
3830 actual_type
= error_mark_node
;
3831 parm
.orig_type
= actual_type
;
3832 parm
.by_ref
= parm
.pt_ref
= parm
.rv_ref
= false;
3833 if (TREE_CODE (actual_type
) == REFERENCE_TYPE
)
3835 /* If the user passes by reference, then we will save the
3836 pointer to the original. As noted in
3837 [dcl.fct.def.coroutine] / 13, if the lifetime of the
3838 referenced item ends and then the coroutine is resumed,
3839 we have UB; well, the user asked for it. */
3840 if (TYPE_REF_IS_RVALUE (actual_type
))
3845 else if (TYPE_REF_P (DECL_ARG_TYPE (arg
)))
3848 parm
.frame_type
= actual_type
;
3850 parm
.this_ptr
= is_this_parameter (arg
);
3851 parm
.lambda_cobj
= lambda_p
&& DECL_NAME (arg
) == closure_identifier
;
3853 tree name
= DECL_NAME (arg
);
3856 char *buf
= xasprintf ("_Coro_unnamed_parm_%d", no_name_parm
++);
3857 name
= get_identifier (buf
);
3860 parm
.field_id
= name
;
3862 if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (parm
.frame_type
))
3864 char *buf
= xasprintf ("%s%s_live", DECL_NAME (arg
) ? "_Coro_" : "",
3865 IDENTIFIER_POINTER (name
));
3867 = coro_build_artificial_var (UNKNOWN_LOCATION
, get_identifier (buf
),
3868 boolean_type_node
, orig
,
3869 boolean_false_node
);
3871 parm
.trivial_dtor
= false;
3874 parm
.trivial_dtor
= true;
3880 /* Small helper for the repetitive task of adding a new field to the coro
3884 coro_make_frame_entry (tree
*field_list
, const char *name
, tree fld_type
,
3887 tree id
= get_identifier (name
);
3888 tree decl
= build_decl (loc
, FIELD_DECL
, id
, fld_type
);
3889 DECL_CHAIN (decl
) = *field_list
;
3894 /* For recording local variable usage. */
3896 struct local_vars_frame_data
3899 hash_map
<tree
, local_var_info
> *local_var_uses
;
3900 unsigned int nest_depth
, bind_indx
;
3903 bool local_var_seen
;
3906 /* A tree-walk callback that processes one bind expression noting local
3907 variables, and making a coroutine frame slot available for those that
3908 need it, so that they can be 'promoted' across suspension points. */
3911 register_local_var_uses (tree
*stmt
, int *do_subtree
, void *d
)
3913 local_vars_frame_data
*lvd
= (local_vars_frame_data
*) d
;
3915 /* As we enter a bind expression - record the vars there and then recurse.
3916 As we exit drop the nest depth.
3917 The bind index is a growing count of how many bind indices we've seen.
3918 We build a space in the frame for each local var. */
3920 if (TREE_CODE (*stmt
) == BIND_EXPR
)
3923 unsigned serial
= 0;
3924 for (lvar
= BIND_EXPR_VARS (*stmt
); lvar
!= NULL
;
3925 lvar
= DECL_CHAIN (lvar
))
3928 local_var_info
&local_var
3929 = lvd
->local_var_uses
->get_or_insert (lvar
, &existed
);
3930 gcc_checking_assert (!existed
);
3931 local_var
.def_loc
= DECL_SOURCE_LOCATION (lvar
);
3932 tree lvtype
= TREE_TYPE (lvar
);
3933 local_var
.frame_type
= lvtype
;
3934 local_var
.field_idx
= local_var
.field_id
= NULL_TREE
;
3936 /* Make sure that we only present vars to the tests below. */
3937 if (TREE_CODE (lvar
) == TYPE_DECL
3938 || TREE_CODE (lvar
) == NAMESPACE_DECL
)
3941 /* We don't move static vars into the frame. */
3942 local_var
.is_static
= TREE_STATIC (lvar
);
3943 if (local_var
.is_static
)
3947 if (TREE_CODE (lvtype
) == ARRAY_TYPE
3948 && !poly_int_tree_p (DECL_SIZE_UNIT (lvar
), &size
))
3950 sorry_at (local_var
.def_loc
, "variable length arrays are not"
3951 " yet supported in coroutines");
3952 /* Ignore it, this is broken anyway. */
3956 lvd
->local_var_seen
= true;
3957 /* If this var is a lambda capture proxy, we want to leave it alone,
3958 and later rewrite the DECL_VALUE_EXPR to indirect through the
3959 frame copy of the pointer to the lambda closure object. */
3960 local_var
.is_lambda_capture
= is_capture_proxy (lvar
);
3961 if (local_var
.is_lambda_capture
)
3964 /* If a variable has a value expression, then that's what needs
3966 local_var
.has_value_expr_p
= DECL_HAS_VALUE_EXPR_P (lvar
);
3967 if (local_var
.has_value_expr_p
)
3970 /* Make names depth+index unique, so that we can support nested
3971 scopes with identically named locals and still be able to
3972 identify them in the coroutine frame. */
3973 tree lvname
= DECL_NAME (lvar
);
3976 /* The outermost bind scope contains the artificial variables that
3977 we inject to implement the coro state machine. We want to be able
3978 to inspect these in debugging. */
3979 if (lvname
!= NULL_TREE
&& lvd
->nest_depth
== 0)
3980 buf
= xasprintf ("%s", IDENTIFIER_POINTER (lvname
));
3981 else if (lvname
!= NULL_TREE
)
3982 buf
= xasprintf ("%s_%u_%u", IDENTIFIER_POINTER (lvname
),
3983 lvd
->nest_depth
, lvd
->bind_indx
);
3985 buf
= xasprintf ("_D%u_%u_%u", lvd
->nest_depth
, lvd
->bind_indx
,
3988 /* TODO: Figure out if we should build a local type that has any
3989 excess alignment or size from the original decl. */
3990 local_var
.field_id
= coro_make_frame_entry (lvd
->field_list
, buf
,
3993 /* We don't walk any of the local var sub-trees, they won't contain
3998 cp_walk_tree (&BIND_EXPR_BODY (*stmt
), register_local_var_uses
, d
, NULL
);
3999 *do_subtree
= 0; /* We've done this. */
4005 /* Build, return FUNCTION_DECL node based on ORIG with a type FN_TYPE which has
4006 a single argument of type CORO_FRAME_PTR. Build the actor function if
4007 ACTOR_P is true, otherwise the destroy. */
4010 coro_build_actor_or_destroy_function (tree orig
, tree fn_type
,
4011 tree coro_frame_ptr
, bool actor_p
)
4013 location_t loc
= DECL_SOURCE_LOCATION (orig
);
4015 = build_lang_decl (FUNCTION_DECL
, copy_node (DECL_NAME (orig
)), fn_type
);
4017 /* Allow for locating the ramp (original) function from this one. */
4019 to_ramp
= hash_map
<tree
, tree
>::create_ggc (10);
4020 to_ramp
->put (fn
, orig
);
4022 DECL_CONTEXT (fn
) = DECL_CONTEXT (orig
);
4023 DECL_SOURCE_LOCATION (fn
) = loc
;
4024 DECL_ARTIFICIAL (fn
) = true;
4025 DECL_INITIAL (fn
) = error_mark_node
;
4027 tree id
= get_identifier ("frame_ptr");
4028 tree fp
= build_lang_decl (PARM_DECL
, id
, coro_frame_ptr
);
4029 DECL_CONTEXT (fp
) = fn
;
4030 DECL_ARG_TYPE (fp
) = type_passed_as (coro_frame_ptr
);
4031 DECL_ARGUMENTS (fn
) = fp
;
4033 /* Copy selected attributes from the original function. */
4034 TREE_USED (fn
) = TREE_USED (orig
);
4035 if (DECL_SECTION_NAME (orig
))
4036 set_decl_section_name (fn
, orig
);
4037 /* Copy any alignment that the FE added. */
4038 if (DECL_ALIGN (orig
))
4039 SET_DECL_ALIGN (fn
, DECL_ALIGN (orig
));
4040 /* Copy any alignment the user added. */
4041 DECL_USER_ALIGN (fn
) = DECL_USER_ALIGN (orig
);
4042 /* Apply attributes from the original fn. */
4043 DECL_ATTRIBUTES (fn
) = copy_list (DECL_ATTRIBUTES (orig
));
4045 /* A void return. */
4046 tree resdecl
= build_decl (loc
, RESULT_DECL
, 0, void_type_node
);
4047 DECL_CONTEXT (resdecl
) = fn
;
4048 DECL_ARTIFICIAL (resdecl
) = 1;
4049 DECL_IGNORED_P (resdecl
) = 1;
4050 DECL_RESULT (fn
) = resdecl
;
4052 /* This is a coroutine component. */
4053 DECL_COROUTINE_P (fn
) = 1;
4055 /* Set up a means to find out if a decl is one of the helpers and, if so,
4057 if (coroutine_info
*info
= get_coroutine_info (orig
))
4059 gcc_checking_assert ((actor_p
&& info
->actor_decl
== NULL_TREE
)
4060 || info
->destroy_decl
== NULL_TREE
);
4062 info
->actor_decl
= fn
;
4064 info
->destroy_decl
= fn
;
4069 /* Re-write the body as per [dcl.fct.def.coroutine] / 5. */
4072 coro_rewrite_function_body (location_t fn_start
, tree fnbody
, tree orig
,
4073 hash_map
<tree
, param_info
> *param_uses
,
4074 tree resume_fn_ptr_type
,
4075 tree
& resume_idx_var
, tree
& fs_label
)
4077 /* This will be our new outer scope. */
4078 tree update_body
= build3 (BIND_EXPR
, void_type_node
, NULL
, NULL
, NULL
);
4079 tree top_block
= make_node (BLOCK
);
4080 BIND_EXPR_BLOCK (update_body
) = top_block
;
4081 BIND_EXPR_BODY (update_body
) = push_stmt_list ();
4083 /* If the function has a top level bind expression, then connect that
4084 after first making sure we give it a new block. */
4085 tree first
= expr_first (fnbody
);
4086 if (first
&& TREE_CODE (first
) == BIND_EXPR
)
4088 tree block
= BIND_EXPR_BLOCK (first
);
4089 gcc_checking_assert (block
);
4090 gcc_checking_assert (BLOCK_SUPERCONTEXT (block
) == NULL_TREE
);
4091 gcc_checking_assert (BLOCK_CHAIN (block
) == NULL_TREE
);
4092 /* Replace the top block to avoid issues with locations for args
4093 appearing to be in a non-existent place. */
4094 tree replace_blk
= make_node (BLOCK
);
4095 BLOCK_VARS (replace_blk
) = BLOCK_VARS (block
);
4096 BLOCK_SUBBLOCKS (replace_blk
) = BLOCK_SUBBLOCKS (block
);
4097 for (tree b
= BLOCK_SUBBLOCKS (replace_blk
); b
; b
= BLOCK_CHAIN (b
))
4098 BLOCK_SUPERCONTEXT (b
) = replace_blk
;
4099 BIND_EXPR_BLOCK (first
) = replace_blk
;
4100 /* The top block has one child, so far, and we have now got a
4102 BLOCK_SUPERCONTEXT (replace_blk
) = top_block
;
4103 BLOCK_SUBBLOCKS (top_block
) = replace_blk
;
4107 /* We are missing a top level BIND_EXPR. We need one to ensure that we
4108 don't shuffle around the coroutine frame and corrupt it. */
4109 tree bind_wrap
= build3_loc (fn_start
, BIND_EXPR
, void_type_node
,
4111 BIND_EXPR_BODY (bind_wrap
) = fnbody
;
4112 /* Ensure we have a block to connect up the scopes. */
4113 tree new_blk
= make_node (BLOCK
);
4114 BIND_EXPR_BLOCK (bind_wrap
) = new_blk
;
4115 BLOCK_SUBBLOCKS (top_block
) = new_blk
;
4119 /* Wrap the function body in a try {} catch (...) {} block, if exceptions
4121 tree var_list
= NULL_TREE
;
4122 tree initial_await
= build_init_or_final_await (fn_start
, false);
4124 /* [stmt.return.coroutine] / 3
4125 If p.return_void() is a valid expression, flowing off the end of a
4126 coroutine is equivalent to a co_return with no operand; otherwise
4127 flowing off the end of a coroutine results in undefined behavior. */
4129 = get_coroutine_return_void_expr (current_function_decl
, fn_start
, false);
4131 /* The pointer to the resume function. */
4133 = coro_build_artificial_var (fn_start
, coro_resume_fn_id
,
4134 resume_fn_ptr_type
, orig
, NULL_TREE
);
4135 DECL_CHAIN (resume_fn_ptr
) = var_list
;
4136 var_list
= resume_fn_ptr
;
4137 add_decl_expr (resume_fn_ptr
);
4139 /* We will need to be able to set the resume function pointer to nullptr
4140 to signal that the coroutine is 'done'. */
4142 = build1 (CONVERT_EXPR
, resume_fn_ptr_type
, nullptr_node
);
4144 /* The pointer to the destroy function. */
4145 tree var
= coro_build_artificial_var (fn_start
, coro_destroy_fn_id
,
4146 resume_fn_ptr_type
, orig
, NULL_TREE
);
4147 DECL_CHAIN (var
) = var_list
;
4149 add_decl_expr (var
);
4151 /* The promise was created on demand when parsing we now link it into
4153 tree promise
= get_coroutine_promise_proxy (orig
);
4154 DECL_CONTEXT (promise
) = orig
;
4155 DECL_SOURCE_LOCATION (promise
) = fn_start
;
4156 DECL_CHAIN (promise
) = var_list
;
4158 add_decl_expr (promise
);
4160 /* We need a handle to this coroutine, which is passed to every
4161 await_suspend(). This was created on demand when parsing we now link it
4163 var
= get_coroutine_self_handle_proxy (orig
);
4164 DECL_CONTEXT (var
) = orig
;
4165 DECL_SOURCE_LOCATION (var
) = fn_start
;
4166 DECL_CHAIN (var
) = var_list
;
4168 add_decl_expr (var
);
4170 /* If we have function parms, then these will be copied to the coroutine
4171 frame. Create a local (proxy) variable for each parm, since the original
4172 parms will be out of scope once the ramp has finished. The proxy vars will
4173 get DECL_VALUE_EXPRs pointing to the frame copies, so that we can interact
4174 with them in the debugger. */
4177 gcc_checking_assert (DECL_ARGUMENTS (orig
));
4178 /* Add a local var for each parm. */
4179 for (tree arg
= DECL_ARGUMENTS (orig
); arg
!= NULL
;
4180 arg
= DECL_CHAIN (arg
))
4182 param_info
*parm_i
= param_uses
->get (arg
);
4183 gcc_checking_assert (parm_i
);
4185 = build_lang_decl (VAR_DECL
, parm_i
->field_id
, TREE_TYPE (arg
));
4186 DECL_SOURCE_LOCATION (parm_i
->copy_var
) = DECL_SOURCE_LOCATION (arg
);
4187 DECL_CONTEXT (parm_i
->copy_var
) = orig
;
4188 DECL_ARTIFICIAL (parm_i
->copy_var
) = true;
4189 DECL_CHAIN (parm_i
->copy_var
) = var_list
;
4190 var_list
= parm_i
->copy_var
;
4191 add_decl_expr (parm_i
->copy_var
);
4194 /* Now replace all uses of the parms in the function body with the proxy
4195 vars. We want to this to apply to every instance of param's use, so
4196 don't include a 'visited' hash_set on the tree walk, however we will
4197 arrange to visit each containing expression only once. */
4198 hash_set
<tree
*> visited
;
4199 param_frame_data param_data
= {NULL
, param_uses
,
4200 &visited
, fn_start
, false};
4201 cp_walk_tree (&fnbody
, rewrite_param_uses
, ¶m_data
, NULL
);
4204 /* We create a resume index, this is initialized in the ramp. */
4206 = coro_build_artificial_var (fn_start
, coro_resume_index_id
,
4207 short_unsigned_type_node
, orig
, NULL_TREE
);
4208 DECL_CHAIN (resume_idx_var
) = var_list
;
4209 var_list
= resume_idx_var
;
4210 add_decl_expr (resume_idx_var
);
4212 /* If the coroutine has a frame that needs to be freed, this will be set by
4214 var
= coro_build_artificial_var (fn_start
, coro_frame_needs_free_id
,
4215 boolean_type_node
, orig
, NULL_TREE
);
4216 DECL_CHAIN (var
) = var_list
;
4218 add_decl_expr (var
);
4220 if (flag_exceptions
)
4222 /* Build promise.unhandled_exception(); */
4224 = coro_build_promise_expression (current_function_decl
, promise
,
4225 coro_unhandled_exception_identifier
,
4226 fn_start
, NULL
, /*musthave=*/true);
4227 /* Create and initialize the initial-await-resume-called variable per
4228 [dcl.fct.def.coroutine] / 5.3. */
4230 = coro_build_artificial_var (fn_start
, coro_frame_i_a_r_c_id
,
4231 boolean_type_node
, orig
,
4232 boolean_false_node
);
4233 DECL_CHAIN (i_a_r_c
) = var_list
;
4235 add_decl_expr (i_a_r_c
);
4236 /* Start the try-catch. */
4237 tree tcb
= build_stmt (fn_start
, TRY_BLOCK
, NULL_TREE
, NULL_TREE
);
4239 TRY_STMTS (tcb
) = push_stmt_list ();
4240 if (initial_await
!= error_mark_node
)
4242 /* Build a compound expression that sets the
4243 initial-await-resume-called variable true and then calls the
4244 initial suspend expression await resume.
4245 In the case that the user decides to make the initial await
4246 await_resume() return a value, we need to discard it and, it is
4247 a reference type, look past the indirection. */
4248 if (INDIRECT_REF_P (initial_await
))
4249 initial_await
= TREE_OPERAND (initial_await
, 0);
4250 tree vec
= TREE_OPERAND (initial_await
, 3);
4251 tree aw_r
= TREE_VEC_ELT (vec
, 2);
4252 aw_r
= convert_to_void (aw_r
, ICV_STATEMENT
, tf_warning_or_error
);
4253 tree update
= build2 (MODIFY_EXPR
, boolean_type_node
, i_a_r_c
,
4255 aw_r
= cp_build_compound_expr (update
, aw_r
, tf_warning_or_error
);
4256 TREE_VEC_ELT (vec
, 2) = aw_r
;
4258 /* Add the initial await to the start of the user-authored function. */
4259 finish_expr_stmt (initial_await
);
4260 /* Append the original function body. */
4263 add_stmt (return_void
);
4264 TRY_STMTS (tcb
) = pop_stmt_list (TRY_STMTS (tcb
));
4265 TRY_HANDLERS (tcb
) = push_stmt_list ();
4266 /* Mimic what the parser does for the catch. */
4267 tree handler
= begin_handler ();
4268 finish_handler_parms (NULL_TREE
, handler
); /* catch (...) */
4270 /* Get the initial await resume called value. */
4271 tree not_iarc_if
= begin_if_stmt ();
4272 tree not_iarc
= build1_loc (fn_start
, TRUTH_NOT_EXPR
,
4273 boolean_type_node
, i_a_r_c
);
4274 finish_if_stmt_cond (not_iarc
, not_iarc_if
);
4275 /* If the initial await resume called value is false, rethrow... */
4276 tree rethrow
= build_throw (fn_start
, NULL_TREE
);
4277 suppress_warning (rethrow
);
4278 finish_expr_stmt (rethrow
);
4279 finish_then_clause (not_iarc_if
);
4280 tree iarc_scope
= IF_SCOPE (not_iarc_if
);
4281 IF_SCOPE (not_iarc_if
) = NULL
;
4282 not_iarc_if
= do_poplevel (iarc_scope
);
4283 add_stmt (not_iarc_if
);
4284 /* ... else call the promise unhandled exception method
4285 but first we set done = true and the resume index to 0.
4286 If the unhandled exception method returns, then we continue
4287 to the final await expression (which duplicates the clearing of
4289 tree r
= build2 (MODIFY_EXPR
, resume_fn_ptr_type
, resume_fn_ptr
,
4291 finish_expr_stmt (r
);
4292 tree short_zero
= build_int_cst (short_unsigned_type_node
, 0);
4293 r
= build2 (MODIFY_EXPR
, short_unsigned_type_node
, resume_idx_var
,
4295 finish_expr_stmt (r
);
4296 finish_expr_stmt (ueh
);
4297 finish_handler (handler
);
4298 TRY_HANDLERS (tcb
) = pop_stmt_list (TRY_HANDLERS (tcb
));
4304 /* We still try to look for the promise method and warn if it's not
4307 = lookup_promise_method (orig
, coro_unhandled_exception_identifier
,
4308 fn_start
, /*musthave=*/false);
4309 if (!ueh_meth
|| ueh_meth
== error_mark_node
)
4310 warning_at (fn_start
, 0, "no member named %qE in %qT",
4311 coro_unhandled_exception_identifier
,
4312 get_coroutine_promise_type (orig
));
4314 /* Else we don't check and don't care if the method is missing..
4315 just add the initial suspend, function and return. */
4316 finish_expr_stmt (initial_await
);
4317 /* Append the original function body. */
4320 add_stmt (return_void
);
4323 /* co_return branches to the final_suspend label, so declare that now. */
4325 = create_named_label_with_ctx (fn_start
, "final.suspend", NULL_TREE
);
4326 add_stmt (build_stmt (fn_start
, LABEL_EXPR
, fs_label
));
4328 /* Before entering the final suspend point, we signal that this point has
4329 been reached by setting the resume function pointer to zero (this is
4330 what the 'done()' builtin tests) as per the current ABI. */
4331 zero_resume
= build2 (MODIFY_EXPR
, resume_fn_ptr_type
, resume_fn_ptr
,
4333 finish_expr_stmt (zero_resume
);
4334 finish_expr_stmt (build_init_or_final_await (fn_start
, true));
4335 BIND_EXPR_BODY (update_body
) = pop_stmt_list (BIND_EXPR_BODY (update_body
));
4336 BIND_EXPR_VARS (update_body
) = nreverse (var_list
);
4337 BLOCK_VARS (top_block
) = BIND_EXPR_VARS (update_body
);
4343 a) Check that the function and promise type are valid for a
4345 b) Carry out the initial morph to create the skeleton of the
4346 coroutine ramp function and the rewritten body.
4350 1. We only hit this code once all dependencies are resolved.
4351 2. The function body will be either a bind expr or a statement list
4352 3. That cfun and current_function_decl are valid for the case we're
4354 4. 'input_location' will be of the final brace for the function.
4356 We do something like this:
4357 declare a dummy coro frame.
4359 using handle_type = coro::coroutine_handle<coro1::promise_type>;
4360 void (*_Coro_resume_fn)(_R_frame *);
4361 void (*_Coro_destroy_fn)(_R_frame *);
4362 coro1::promise_type _Coro_promise;
4363 bool _Coro_frame_needs_free; free the coro frame mem if set.
4364 bool _Coro_i_a_r_c; [dcl.fct.def.coroutine] / 5.3
4365 short _Coro_resume_index;
4366 handle_type _Coro_self_handle;
4367 parameter copies (were required).
4368 local variables saved (including awaitables)
4369 (maybe) trailing space.
4373 morph_fn_to_coro (tree orig
, tree
*resumer
, tree
*destroyer
)
4375 gcc_checking_assert (orig
&& TREE_CODE (orig
) == FUNCTION_DECL
);
4377 *resumer
= error_mark_node
;
4378 *destroyer
= error_mark_node
;
4379 if (!coro_function_valid_p (orig
))
4381 /* For early errors, we do not want a diagnostic about the missing
4382 ramp return value, since the user cannot fix this - a 'return' is
4383 not allowed in a coroutine. */
4384 suppress_warning (orig
, OPT_Wreturn_type
);
4385 /* Discard the body, we can't process it further. */
4386 pop_stmt_list (DECL_SAVED_TREE (orig
));
4387 DECL_SAVED_TREE (orig
) = push_stmt_list ();
4391 /* We can't validly get here with an empty statement list, since there's no
4392 way for the FE to decide it's a coroutine in the absence of any code. */
4393 tree fnbody
= pop_stmt_list (DECL_SAVED_TREE (orig
));
4394 gcc_checking_assert (fnbody
!= NULL_TREE
);
4396 /* We don't have the locus of the opening brace - it's filled in later (and
4397 there doesn't really seem to be any easy way to get at it).
4398 The closing brace is assumed to be input_location. */
4399 location_t fn_start
= DECL_SOURCE_LOCATION (orig
);
4400 gcc_rich_location
fn_start_loc (fn_start
);
4402 /* Initial processing of the function-body.
4403 If we have no expressions or just an error then punt. */
4404 tree body_start
= expr_first (fnbody
);
4405 if (body_start
== NULL_TREE
|| body_start
== error_mark_node
)
4407 DECL_SAVED_TREE (orig
) = push_stmt_list ();
4408 append_to_statement_list (fnbody
, &DECL_SAVED_TREE (orig
));
4409 /* Suppress warnings about the missing return value. */
4410 suppress_warning (orig
, OPT_Wreturn_type
);
4414 /* So, we've tied off the original user-authored body in fn_body.
4416 Start the replacement synthesized ramp body as newbody.
4417 If we encounter a fatal error we might return a now-empty body.
4419 Note, the returned ramp body is not 'popped', to be compatible with
4420 the way that decl.cc handles regular functions, the scope pop is done
4423 tree newbody
= push_stmt_list ();
4424 DECL_SAVED_TREE (orig
) = newbody
;
4426 /* If our original body is noexcept, then that's what we apply to our
4427 generated ramp, transfer any MUST_NOT_THOW_EXPR to that. */
4428 bool is_noexcept
= TREE_CODE (body_start
) == MUST_NOT_THROW_EXPR
;
4431 /* The function body we will continue with is the single operand to
4432 the must-not-throw. */
4433 fnbody
= TREE_OPERAND (body_start
, 0);
4434 /* Transfer the must-not-throw to the ramp body. */
4435 add_stmt (body_start
);
4436 /* Re-start the ramp as must-not-throw. */
4437 TREE_OPERAND (body_start
, 0) = push_stmt_list ();
4440 /* If the original function has a return value with a non-trivial DTOR
4441 and the body contains a var with a DTOR that might throw, the decl is
4442 marked "throwing_cleanup".
4443 We do not [in the ramp, which is synthesised here], use any body var
4444 types with DTORs that might throw.
4445 The original body is transformed into the actor function which only
4446 contains void returns, and is also wrapped in a try-catch block.
4447 So (a) the 'throwing_cleanup' is not correct for the ramp and (b) we do
4448 not need to transfer it to the actor which only contains void returns. */
4449 cp_function_chain
->throwing_cleanup
= false;
4451 /* Create the coro frame type, as far as it can be known at this stage.
4452 1. Types we already know. */
4454 tree fn_return_type
= TREE_TYPE (TREE_TYPE (orig
));
4455 tree handle_type
= get_coroutine_handle_type (orig
);
4456 tree promise_type
= get_coroutine_promise_type (orig
);
4458 /* 2. Types we need to define or look up. */
4460 tree fr_name
= get_fn_local_identifier (orig
, "Frame");
4461 tree coro_frame_type
= xref_tag (record_type
, fr_name
);
4462 DECL_CONTEXT (TYPE_NAME (coro_frame_type
)) = current_scope ();
4463 tree coro_frame_ptr
= build_pointer_type (coro_frame_type
);
4464 tree act_des_fn_type
4465 = build_function_type_list (void_type_node
, coro_frame_ptr
, NULL_TREE
);
4466 tree act_des_fn_ptr
= build_pointer_type (act_des_fn_type
);
4468 /* Declare the actor and destroyer function. */
4469 tree actor
= coro_build_actor_or_destroy_function (orig
, act_des_fn_type
,
4470 coro_frame_ptr
, true);
4471 tree destroy
= coro_build_actor_or_destroy_function (orig
, act_des_fn_type
,
4472 coro_frame_ptr
, false);
4474 /* Construct the wrapped function body; we will analyze this to determine
4475 the requirements for the coroutine frame. */
4477 tree resume_idx_var
= NULL_TREE
;
4478 tree fs_label
= NULL_TREE
;
4479 hash_map
<tree
, param_info
> *param_uses
= analyze_fn_parms (orig
);
4481 fnbody
= coro_rewrite_function_body (fn_start
, fnbody
, orig
, param_uses
,
4483 resume_idx_var
, fs_label
);
4484 /* Build our dummy coro frame layout. */
4485 coro_frame_type
= begin_class_definition (coro_frame_type
);
4487 /* The fields for the coro frame. */
4488 tree field_list
= NULL_TREE
;
4490 /* We need to know, and inspect, each suspend point in the function
4491 in several places. It's convenient to place this map out of line
4492 since it's used from tree walk callbacks. */
4493 suspend_points
= new hash_map
<tree
, suspend_point_info
>;
4495 /* Now insert the data for any body await points, at this time we also need
4496 to promote any temporaries that are captured by reference (to regular
4497 vars) they will get added to the coro frame along with other locals. */
4498 susp_frame_data body_aw_points
4499 = {&field_list
, handle_type
, fs_label
, NULL
, NULL
, 0, 0,
4500 hash_set
<tree
> (), NULL
, NULL
, 0, false, false, false};
4501 body_aw_points
.block_stack
= make_tree_vector ();
4502 body_aw_points
.bind_stack
= make_tree_vector ();
4503 body_aw_points
.to_replace
= make_tree_vector ();
4504 cp_walk_tree (&fnbody
, await_statement_walker
, &body_aw_points
, NULL
);
4506 /* 4. Now make space for local vars, this is conservative again, and we
4507 would expect to delete unused entries later. */
4508 hash_map
<tree
, local_var_info
> local_var_uses
;
4509 local_vars_frame_data local_vars_data
4510 = {&field_list
, &local_var_uses
, 0, 0, fn_start
, false, false};
4511 cp_walk_tree (&fnbody
, register_local_var_uses
, &local_vars_data
, NULL
);
4513 /* Tie off the struct for now, so that we can build offsets to the
4515 TYPE_FIELDS (coro_frame_type
) = field_list
;
4516 TYPE_BINFO (coro_frame_type
) = make_tree_binfo (0);
4517 BINFO_OFFSET (TYPE_BINFO (coro_frame_type
)) = size_zero_node
;
4518 BINFO_TYPE (TYPE_BINFO (coro_frame_type
)) = coro_frame_type
;
4520 coro_frame_type
= finish_struct (coro_frame_type
, NULL_TREE
);
4523 /* Now build the ramp function pieces. */
4524 tree ramp_bind
= build3 (BIND_EXPR
, void_type_node
, NULL
, NULL
, NULL
);
4525 add_stmt (ramp_bind
);
4526 tree ramp_body
= push_stmt_list ();
4528 tree zeroinit
= build1_loc (fn_start
, CONVERT_EXPR
,
4529 coro_frame_ptr
, nullptr_node
);
4530 tree coro_fp
= coro_build_artificial_var (fn_start
, "_Coro_frameptr",
4531 coro_frame_ptr
, orig
, zeroinit
);
4532 tree varlist
= coro_fp
;
4534 /* To signal that we need to cleanup copied function args. */
4535 if (flag_exceptions
&& DECL_ARGUMENTS (orig
))
4536 for (tree arg
= DECL_ARGUMENTS (orig
); arg
!= NULL
;
4537 arg
= DECL_CHAIN (arg
))
4539 param_info
*parm_i
= param_uses
->get (arg
);
4540 gcc_checking_assert (parm_i
);
4541 if (parm_i
->trivial_dtor
)
4543 DECL_CHAIN (parm_i
->guard_var
) = varlist
;
4544 varlist
= parm_i
->guard_var
;
4547 /* Signal that we need to clean up the promise object on exception. */
4548 tree coro_promise_live
4549 = coro_build_artificial_var (fn_start
, "_Coro_promise_live",
4550 boolean_type_node
, orig
, boolean_false_node
);
4551 DECL_CHAIN (coro_promise_live
) = varlist
;
4552 varlist
= coro_promise_live
;
4554 /* When the get-return-object is in the RETURN slot, we need to arrange for
4555 cleanup on exception. */
4557 = coro_build_artificial_var (fn_start
, "_Coro_gro_live",
4558 boolean_type_node
, orig
, boolean_false_node
);
4560 DECL_CHAIN (coro_gro_live
) = varlist
;
4561 varlist
= coro_gro_live
;
4563 /* Collected the scope vars we need ... only one for now. */
4564 BIND_EXPR_VARS (ramp_bind
) = nreverse (varlist
);
4566 /* We're now going to create a new top level scope block for the ramp
4568 tree top_block
= make_node (BLOCK
);
4570 BIND_EXPR_BLOCK (ramp_bind
) = top_block
;
4571 BLOCK_VARS (top_block
) = BIND_EXPR_VARS (ramp_bind
);
4572 BLOCK_SUBBLOCKS (top_block
) = NULL_TREE
;
4573 current_binding_level
->blocks
= top_block
;
4575 /* The decl_expr for the coro frame pointer, initialize to zero so that we
4576 can pass it to the IFN_CO_FRAME (since there's no way to pass a type,
4577 directly apparently). This avoids a "used uninitialized" warning. */
4579 add_decl_expr (coro_fp
);
4580 if (flag_exceptions
&& DECL_ARGUMENTS (orig
))
4581 for (tree arg
= DECL_ARGUMENTS (orig
); arg
!= NULL
;
4582 arg
= DECL_CHAIN (arg
))
4584 param_info
*parm_i
= param_uses
->get (arg
);
4585 if (parm_i
->trivial_dtor
)
4587 add_decl_expr (parm_i
->guard_var
);;
4589 add_decl_expr (coro_promise_live
);
4590 add_decl_expr (coro_gro_live
);
4592 /* The CO_FRAME internal function is a mechanism to allow the middle end
4593 to adjust the allocation in response to optimizations. We provide the
4594 current conservative estimate of the frame size (as per the current)
4596 tree frame_size
= TYPE_SIZE_UNIT (coro_frame_type
);
4598 = build_call_expr_internal_loc (fn_start
, IFN_CO_FRAME
, size_type_node
, 2,
4599 frame_size
, coro_fp
);
4601 /* [dcl.fct.def.coroutine] / 10 (part1)
4602 The unqualified-id get_return_object_on_allocation_failure is looked up
4603 in the scope of the promise type by class member access lookup. */
4605 /* We don't require this, so coro_build_promise_expression can return NULL,
4606 but, if the lookup succeeds, then the function must be usable. */
4607 tree dummy_promise
= build_dummy_object (get_coroutine_promise_type (orig
));
4609 = coro_build_promise_expression (orig
, dummy_promise
,
4610 coro_gro_on_allocation_fail_identifier
,
4611 fn_start
, NULL
, /*musthave=*/false);
4613 /* however, should that fail, returning an error, the later stages can't
4614 handle the erroneous expression, so we reset the call as if it was
4616 if (grooaf
== error_mark_node
)
4619 /* Allocate the frame, this has several possibilities:
4620 [dcl.fct.def.coroutine] / 9 (part 1)
4621 The allocation function’s name is looked up in the scope of the promise
4622 type. It's not a failure for it to be absent see part 4, below. */
4624 tree nwname
= ovl_op_identifier (false, NEW_EXPR
);
4625 tree new_fn
= NULL_TREE
;
4627 if (TYPE_HAS_NEW_OPERATOR (promise_type
))
4629 tree fns
= lookup_promise_method (orig
, nwname
, fn_start
,
4631 /* [dcl.fct.def.coroutine] / 9 (part 2)
4632 If the lookup finds an allocation function in the scope of the promise
4633 type, overload resolution is performed on a function call created by
4634 assembling an argument list. The first argument is the amount of space
4635 requested, and has type std::size_t. The lvalues p1...pn are the
4636 succeeding arguments.. */
4637 vec
<tree
, va_gc
> *args
= make_tree_vector ();
4638 vec_safe_push (args
, resizeable
); /* Space needed. */
4640 for (tree arg
= DECL_ARGUMENTS (orig
); arg
!= NULL
;
4641 arg
= DECL_CHAIN (arg
))
4643 param_info
*parm_i
= param_uses
->get (arg
);
4644 gcc_checking_assert (parm_i
);
4645 if (parm_i
->this_ptr
|| parm_i
->lambda_cobj
)
4647 /* We pass a reference to *this to the allocator lookup. */
4648 tree tt
= TREE_TYPE (TREE_TYPE (arg
));
4649 tree this_ref
= build1 (INDIRECT_REF
, tt
, arg
);
4650 tt
= cp_build_reference_type (tt
, false);
4651 this_ref
= convert_to_reference (tt
, this_ref
, CONV_STATIC
,
4652 LOOKUP_NORMAL
, NULL_TREE
,
4653 tf_warning_or_error
);
4654 vec_safe_push (args
, convert_from_reference (this_ref
));
4657 vec_safe_push (args
, convert_from_reference (arg
));
4660 /* Note the function selected; we test to see if it's NOTHROW. */
4662 /* Failure is not an error for this attempt. */
4663 new_fn
= build_new_method_call (dummy_promise
, fns
, &args
, NULL
,
4664 LOOKUP_NORMAL
, &func
, tf_none
);
4665 release_tree_vector (args
);
4667 if (new_fn
== error_mark_node
)
4669 /* [dcl.fct.def.coroutine] / 9 (part 3)
4670 If no viable function is found, overload resolution is performed
4671 again on a function call created by passing just the amount of
4672 space required as an argument of type std::size_t. */
4673 args
= make_tree_vector_single (resizeable
); /* Space needed. */
4674 new_fn
= build_new_method_call (dummy_promise
, fns
, &args
,
4675 NULL_TREE
, LOOKUP_NORMAL
, &func
,
4677 release_tree_vector (args
);
4680 /* However, if the promise provides an operator new, then one of these
4681 two options must be available. */
4682 if (new_fn
== error_mark_node
)
4684 error_at (fn_start
, "%qE is provided by %qT but is not usable with"
4685 " the function signature %qD", nwname
, promise_type
, orig
);
4686 new_fn
= error_mark_node
;
4688 else if (grooaf
&& !TYPE_NOTHROW_P (TREE_TYPE (func
)))
4689 error_at (fn_start
, "%qE is provided by %qT but %qE is not marked"
4690 " %<throw()%> or %<noexcept%>", grooaf
, promise_type
, nwname
);
4691 else if (!grooaf
&& TYPE_NOTHROW_P (TREE_TYPE (func
)))
4692 warning_at (fn_start
, 0, "%qE is marked %<throw()%> or %<noexcept%> but"
4693 " no usable %<get_return_object_on_allocation_failure%>"
4694 " is provided by %qT", nwname
, promise_type
);
4696 else /* No operator new in the promise. */
4698 /* [dcl.fct.def.coroutine] / 9 (part 4)
4699 If this lookup fails, the allocation function’s name is looked up in
4700 the global scope. */
4702 vec
<tree
, va_gc
> *args
;
4703 /* build_operator_new_call () will insert size needed as element 0 of
4704 this, and we might need to append the std::nothrow constant. */
4705 vec_alloc (args
, 2);
4708 /* [dcl.fct.def.coroutine] / 10 (part 2)
4709 If any declarations (of the get return on allocation fail) are
4710 found, then the result of a call to an allocation function used
4711 to obtain storage for the coroutine state is assumed to return
4712 nullptr if it fails to obtain storage and, if a global allocation
4713 function is selected, the ::operator new(size_t, nothrow_t) form
4714 is used. The allocation function used in this case shall have a
4715 non-throwing noexcept-specification. So we need std::nothrow. */
4716 tree std_nt
= lookup_qualified_name (std_node
,
4717 get_identifier ("nothrow"),
4720 if (!std_nt
|| std_nt
== error_mark_node
)
4721 error_at (fn_start
, "%qE is provided by %qT but %<std::nothrow%> "
4722 "cannot be found", grooaf
, promise_type
);
4723 vec_safe_push (args
, std_nt
);
4726 /* If we get to this point, we must succeed in looking up the global
4727 operator new for the params provided. Extract a simplified version
4728 of the machinery from build_operator_new_call. This can update the
4731 new_fn
= build_operator_new_call (nwname
, &args
, &frame_size
, &cookie
,
4733 /*size_check=*/NULL
, /*fn=*/NULL
,
4734 tf_warning_or_error
);
4735 resizeable
= build_call_expr_internal_loc
4736 (fn_start
, IFN_CO_FRAME
, size_type_node
, 2, frame_size
, coro_fp
);
4737 /* If the operator call fails for some reason, then don't try to
4739 if (new_fn
!= error_mark_node
)
4740 CALL_EXPR_ARG (new_fn
, 0) = resizeable
;
4742 release_tree_vector (args
);
4745 tree allocated
= build1 (CONVERT_EXPR
, coro_frame_ptr
, new_fn
);
4746 tree r
= cp_build_init_expr (coro_fp
, allocated
);
4747 r
= coro_build_cvt_void_expr_stmt (r
, fn_start
);
4750 /* If the user provided a method to return an object on alloc fail, then
4751 check the returned pointer and call the func if it's null.
4752 Otherwise, no check, and we fail for noexcept/fno-exceptions cases. */
4756 /* [dcl.fct.def.coroutine] / 10 (part 3)
4757 If the allocation function returns nullptr,the coroutine returns
4758 control to the caller of the coroutine and the return value is
4759 obtained by a call to T::get_return_object_on_allocation_failure(),
4760 where T is the promise type. */
4762 gcc_checking_assert (same_type_p (fn_return_type
, TREE_TYPE (grooaf
)));
4763 tree if_stmt
= begin_if_stmt ();
4764 tree cond
= build1 (CONVERT_EXPR
, coro_frame_ptr
, nullptr_node
);
4765 cond
= build2 (EQ_EXPR
, boolean_type_node
, coro_fp
, cond
);
4766 finish_if_stmt_cond (cond
, if_stmt
);
4767 if (VOID_TYPE_P (fn_return_type
))
4769 /* Execute the get-return-object-on-alloc-fail call... */
4770 finish_expr_stmt (grooaf
);
4771 /* ... but discard the result, since we return void. */
4772 finish_return_stmt (NULL_TREE
);
4776 /* Get the fallback return object. */
4777 r
= build_cplus_new (fn_return_type
, grooaf
, tf_warning_or_error
);
4778 finish_return_stmt (r
);
4780 finish_then_clause (if_stmt
);
4781 finish_if_stmt (if_stmt
);
4784 /* Up to now any exception thrown will propagate directly to the caller.
4785 This is OK since the only source of such exceptions would be in allocation
4786 of the coroutine frame, and therefore the ramp will not have initialized
4787 any further state. From here, we will track state that needs explicit
4788 destruction in the case that promise or g.r.o setup fails or an exception
4789 is thrown from the initial suspend expression. */
4790 tree ramp_cleanup
= NULL_TREE
;
4791 if (flag_exceptions
)
4793 ramp_cleanup
= build_stmt (fn_start
, TRY_BLOCK
, NULL
, NULL
);
4794 add_stmt (ramp_cleanup
);
4795 TRY_STMTS (ramp_cleanup
) = push_stmt_list ();
4798 /* deref the frame pointer, to use in member access code. */
4799 tree deref_fp
= build_x_arrow (fn_start
, coro_fp
, tf_warning_or_error
);
4801 /* For now, once allocation has succeeded we always assume that this needs
4802 destruction, there's no impl. for frame allocation elision. */
4803 tree fnf_m
= lookup_member (coro_frame_type
, coro_frame_needs_free_id
,
4804 1, 0,tf_warning_or_error
);
4805 tree fnf_x
= build_class_member_access_expr (deref_fp
, fnf_m
, NULL_TREE
,
4806 false, tf_warning_or_error
);
4807 r
= cp_build_init_expr (fnf_x
, boolean_true_node
);
4808 r
= coro_build_cvt_void_expr_stmt (r
, fn_start
);
4811 /* Put the resumer and destroyer functions in. */
4813 tree actor_addr
= build1 (ADDR_EXPR
, act_des_fn_ptr
, actor
);
4815 = lookup_member (coro_frame_type
, coro_resume_fn_id
,
4816 /*protect=*/1, /*want_type=*/0, tf_warning_or_error
);
4817 tree resume_x
= build_class_member_access_expr (deref_fp
, resume_m
, NULL_TREE
,
4818 false, tf_warning_or_error
);
4819 r
= cp_build_init_expr (fn_start
, resume_x
, actor_addr
);
4820 finish_expr_stmt (r
);
4822 tree destroy_addr
= build1 (ADDR_EXPR
, act_des_fn_ptr
, destroy
);
4824 = lookup_member (coro_frame_type
, coro_destroy_fn_id
,
4825 /*protect=*/1, /*want_type=*/0, tf_warning_or_error
);
4827 = build_class_member_access_expr (deref_fp
, destroy_m
, NULL_TREE
, false,
4828 tf_warning_or_error
);
4829 r
= cp_build_init_expr (fn_start
, destroy_x
, destroy_addr
);
4830 finish_expr_stmt (r
);
4832 /* [dcl.fct.def.coroutine] /13
4833 When a coroutine is invoked, a copy is created for each coroutine
4834 parameter. Each such copy is an object with automatic storage duration
4835 that is direct-initialized from an lvalue referring to the corresponding
4836 parameter if the parameter is an lvalue reference, and from an xvalue
4837 referring to it otherwise. A reference to a parameter in the function-
4838 body of the coroutine and in the call to the coroutine promise
4839 constructor is replaced by a reference to its copy. */
4841 vec
<tree
, va_gc
> *promise_args
= NULL
; /* So that we can adjust refs. */
4843 /* The initialization and destruction of each parameter copy occurs in the
4844 context of the called coroutine. Initializations of parameter copies are
4845 sequenced before the call to the coroutine promise constructor and
4846 indeterminately sequenced with respect to each other. The lifetime of
4847 parameter copies ends immediately after the lifetime of the coroutine
4848 promise object ends. */
4850 vec
<tree
, va_gc
> *param_dtor_list
= NULL
;
4852 if (DECL_ARGUMENTS (orig
))
4854 promise_args
= make_tree_vector ();
4855 for (tree arg
= DECL_ARGUMENTS (orig
); arg
!= NULL
;
4856 arg
= DECL_CHAIN (arg
))
4859 param_info
&parm
= param_uses
->get_or_insert (arg
, &existed
);
4861 tree fld_ref
= lookup_member (coro_frame_type
, parm
.field_id
,
4862 /*protect=*/1, /*want_type=*/0,
4863 tf_warning_or_error
);
4865 = build_class_member_access_expr (deref_fp
, fld_ref
, NULL_TREE
,
4866 false, tf_warning_or_error
);
4868 /* Add this to the promise CTOR arguments list, accounting for
4869 refs and special handling for method this ptr. */
4870 if (parm
.this_ptr
|| parm
.lambda_cobj
)
4872 /* We pass a reference to *this to the param preview. */
4873 tree tt
= TREE_TYPE (arg
);
4874 gcc_checking_assert (POINTER_TYPE_P (tt
));
4875 tree ct
= TREE_TYPE (tt
);
4876 tree this_ref
= build1 (INDIRECT_REF
, ct
, arg
);
4877 tree rt
= cp_build_reference_type (ct
, false);
4878 this_ref
= convert_to_reference (rt
, this_ref
, CONV_STATIC
,
4879 LOOKUP_NORMAL
, NULL_TREE
,
4880 tf_warning_or_error
);
4881 vec_safe_push (promise_args
, this_ref
);
4883 else if (parm
.rv_ref
)
4884 vec_safe_push (promise_args
, move (fld_idx
));
4886 vec_safe_push (promise_args
, fld_idx
);
4888 if (parm
.rv_ref
|| parm
.pt_ref
)
4889 /* Initialise the frame reference field directly. */
4890 r
= cp_build_modify_expr (fn_start
, TREE_OPERAND (fld_idx
, 0),
4891 INIT_EXPR
, arg
, tf_warning_or_error
);
4894 r
= forward_parm (arg
);
4895 r
= cp_build_modify_expr (fn_start
, fld_idx
, INIT_EXPR
, r
,
4896 tf_warning_or_error
);
4898 finish_expr_stmt (r
);
4899 if (!parm
.trivial_dtor
)
4901 if (param_dtor_list
== NULL
)
4902 param_dtor_list
= make_tree_vector ();
4903 vec_safe_push (param_dtor_list
, parm
.field_id
);
4904 /* Cleanup this frame copy on exception. */
4906 = build_special_member_call (fld_idx
, complete_dtor_identifier
,
4907 NULL
, parm
.frame_type
,
4909 tf_warning_or_error
);
4910 if (flag_exceptions
)
4912 /* This var is now live. */
4913 r
= build_modify_expr (fn_start
, parm
.guard_var
,
4914 boolean_type_node
, INIT_EXPR
, fn_start
,
4915 boolean_true_node
, boolean_type_node
);
4916 finish_expr_stmt (r
);
4922 /* Set up the promise. */
4924 = lookup_member (coro_frame_type
, coro_promise_id
,
4925 /*protect=*/1, /*want_type=*/0, tf_warning_or_error
);
4927 tree p
= build_class_member_access_expr (deref_fp
, promise_m
, NULL_TREE
,
4928 false, tf_warning_or_error
);
4930 tree promise_dtor
= NULL_TREE
;
4931 if (type_build_ctor_call (promise_type
))
4933 /* Do a placement new constructor for the promise type (we never call
4934 the new operator, just the constructor on the object in place in the
4937 First try to find a constructor with the same parameter list as the
4938 original function (if it has params), failing that find a constructor
4939 with no parameter list. */
4941 if (DECL_ARGUMENTS (orig
))
4943 r
= build_special_member_call (p
, complete_ctor_identifier
,
4944 &promise_args
, promise_type
,
4945 LOOKUP_NORMAL
, tf_none
);
4946 release_tree_vector (promise_args
);
4951 if (r
== NULL_TREE
|| r
== error_mark_node
)
4952 r
= build_special_member_call (p
, complete_ctor_identifier
, NULL
,
4953 promise_type
, LOOKUP_NORMAL
,
4954 tf_warning_or_error
);
4956 r
= coro_build_cvt_void_expr_stmt (r
, fn_start
);
4957 finish_expr_stmt (r
);
4959 r
= build_modify_expr (fn_start
, coro_promise_live
, boolean_type_node
,
4960 INIT_EXPR
, fn_start
, boolean_true_node
,
4962 finish_expr_stmt (r
);
4965 = build_special_member_call (p
, complete_dtor_identifier
,
4966 NULL
, promise_type
, LOOKUP_NORMAL
,
4967 tf_warning_or_error
);
4970 /* Set up a new bind context for the GRO. */
4971 tree gro_context_bind
= build3 (BIND_EXPR
, void_type_node
, NULL
, NULL
, NULL
);
4972 /* Make and connect the scope blocks. */
4973 tree gro_block
= make_node (BLOCK
);
4974 BLOCK_SUPERCONTEXT (gro_block
) = top_block
;
4975 BLOCK_SUBBLOCKS (top_block
) = gro_block
;
4976 BIND_EXPR_BLOCK (gro_context_bind
) = gro_block
;
4977 add_stmt (gro_context_bind
);
4980 = coro_build_promise_expression (orig
, p
,
4981 coro_get_return_object_identifier
,
4982 fn_start
, NULL
, /*musthave=*/true);
4983 /* Without a return object we haven't got much clue what's going on. */
4984 if (get_ro
== error_mark_node
)
4986 BIND_EXPR_BODY (ramp_bind
) = pop_stmt_list (ramp_body
);
4987 DECL_SAVED_TREE (orig
) = newbody
;
4988 /* Suppress warnings about the missing return value. */
4989 suppress_warning (orig
, OPT_Wreturn_type
);
4993 tree gro_context_body
= push_stmt_list ();
4994 tree gro_type
= TREE_TYPE (get_ro
);
4995 bool gro_is_void_p
= VOID_TYPE_P (gro_type
);
4997 tree gro
= NULL_TREE
;
4998 tree gro_bind_vars
= NULL_TREE
;
4999 /* Used for return objects in the RESULT slot. */
5000 tree gro_ret_dtor
= NULL_TREE
;
5001 tree gro_cleanup_stmt
= NULL_TREE
;
5002 /* We have to sequence the call to get_return_object before initial
5006 else if (same_type_p (gro_type
, fn_return_type
))
5008 /* [dcl.fct.def.coroutine] / 7
5009 The expression promise.get_return_object() is used to initialize the
5010 glvalue result or... (see below)
5011 Construct the return result directly. */
5012 if (type_build_ctor_call (gro_type
))
5014 vec
<tree
, va_gc
> *arg
= make_tree_vector_single (get_ro
);
5015 r
= build_special_member_call (DECL_RESULT (orig
),
5016 complete_ctor_identifier
,
5017 &arg
, gro_type
, LOOKUP_NORMAL
,
5018 tf_warning_or_error
);
5019 release_tree_vector (arg
);
5022 r
= cp_build_init_expr (fn_start
, DECL_RESULT (orig
), get_ro
);
5024 if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (gro_type
))
5025 /* If some part of the initalization code (prior to the await_resume
5026 of the initial suspend expression), then we need to clean up the
5029 = build_special_member_call (DECL_RESULT (orig
),
5030 complete_dtor_identifier
, NULL
,
5031 gro_type
, LOOKUP_NORMAL
,
5032 tf_warning_or_error
);
5036 /* ... or ... Construct an object that will be used as the single
5037 param to the CTOR for the return object. */
5038 gro
= coro_build_artificial_var (fn_start
, "_Coro_gro", gro_type
, orig
,
5040 add_decl_expr (gro
);
5041 gro_bind_vars
= gro
;
5042 r
= cp_build_modify_expr (input_location
, gro
, INIT_EXPR
, get_ro
,
5043 tf_warning_or_error
);
5044 /* The constructed object might require a cleanup. */
5045 if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (gro_type
))
5048 = build_special_member_call (gro
, complete_dtor_identifier
,
5049 NULL
, gro_type
, LOOKUP_NORMAL
,
5050 tf_warning_or_error
);
5051 gro_cleanup_stmt
= build_stmt (input_location
, CLEANUP_STMT
, NULL
,
5052 gro_cleanup_stmt
, gro
);
5055 finish_expr_stmt (r
);
5057 if (gro_cleanup_stmt
&& gro_cleanup_stmt
!= error_mark_node
)
5058 CLEANUP_BODY (gro_cleanup_stmt
) = push_stmt_list ();
5060 /* If we have a live g.r.o in the return slot, then signal this for exception
5064 r
= build_modify_expr (fn_start
, coro_gro_live
, boolean_type_node
,
5065 INIT_EXPR
, fn_start
, boolean_true_node
,
5067 finish_expr_stmt (r
);
5069 /* Initialize the resume_idx_var to 0, meaning "not started". */
5071 = lookup_member (coro_frame_type
, coro_resume_index_id
,
5072 /*protect=*/1, /*want_type=*/0, tf_warning_or_error
);
5074 = build_class_member_access_expr (deref_fp
, resume_idx_m
, NULL_TREE
, false,
5075 tf_warning_or_error
);
5076 r
= build_int_cst (short_unsigned_type_node
, 0);
5077 r
= cp_build_init_expr (fn_start
, resume_idx
, r
);
5078 r
= coro_build_cvt_void_expr_stmt (r
, fn_start
);
5081 /* So .. call the actor .. */
5082 r
= build_call_expr_loc (fn_start
, actor
, 1, coro_fp
);
5083 r
= maybe_cleanup_point_expr_void (r
);
5086 /* Switch to using 'input_location' as the loc, since we're now more
5087 logically doing things related to the end of the function. */
5089 /* The ramp is done, we just need the return value.
5090 [dcl.fct.def.coroutine] / 7
5091 The expression promise.get_return_object() is used to initialize the
5092 glvalue result or prvalue result object of a call to a coroutine.
5094 If the 'get return object' is non-void, then we built it before the
5095 promise was constructed. We now supply a reference to that var,
5096 either as the return value (if it's the same type) or to the CTOR
5097 for an object of the return type. */
5099 if (same_type_p (gro_type
, fn_return_type
))
5100 r
= gro_is_void_p
? NULL_TREE
: DECL_RESULT (orig
);
5101 else if (!gro_is_void_p
)
5102 /* check_return_expr will automatically return gro as an rvalue via
5103 treat_lvalue_as_rvalue_p. */
5105 else if (CLASS_TYPE_P (fn_return_type
))
5107 /* For class type return objects, we can attempt to construct,
5108 even if the gro is void. ??? Citation ??? c++/100476 */
5109 r
= build_special_member_call (NULL_TREE
,
5110 complete_ctor_identifier
, NULL
,
5111 fn_return_type
, LOOKUP_NORMAL
,
5112 tf_warning_or_error
);
5113 r
= build_cplus_new (fn_return_type
, r
, tf_warning_or_error
);
5117 /* We can't initialize a non-class return value from void. */
5118 error_at (input_location
, "cannot initialize a return object of type"
5119 " %qT with an rvalue of type %<void%>", fn_return_type
);
5120 r
= error_mark_node
;
5123 finish_return_stmt (r
);
5125 if (gro_cleanup_stmt
)
5127 CLEANUP_BODY (gro_cleanup_stmt
)
5128 = pop_stmt_list (CLEANUP_BODY (gro_cleanup_stmt
));
5129 add_stmt (gro_cleanup_stmt
);
5132 /* Finish up the ramp function. */
5133 BIND_EXPR_VARS (gro_context_bind
) = gro_bind_vars
;
5134 BIND_EXPR_BODY (gro_context_bind
) = pop_stmt_list (gro_context_body
);
5135 TREE_SIDE_EFFECTS (gro_context_bind
) = true;
5137 if (flag_exceptions
)
5139 TRY_HANDLERS (ramp_cleanup
) = push_stmt_list ();
5140 tree handler
= begin_handler ();
5141 finish_handler_parms (NULL_TREE
, handler
); /* catch (...) */
5143 /* If we have a live G.R.O in the return slot, then run its DTOR.
5144 When the return object is constructed from a separate g.r.o, this is
5145 already handled by its regular cleanup. */
5146 if (gro_ret_dtor
&& gro_ret_dtor
!= error_mark_node
)
5148 tree gro_d_if
= begin_if_stmt ();
5149 finish_if_stmt_cond (coro_gro_live
, gro_d_if
);
5150 finish_expr_stmt (gro_ret_dtor
);
5151 finish_then_clause (gro_d_if
);
5152 tree gro_d_if_scope
= IF_SCOPE (gro_d_if
);
5153 IF_SCOPE (gro_d_if
) = NULL
;
5154 gro_d_if
= do_poplevel (gro_d_if_scope
);
5155 add_stmt (gro_d_if
);
5158 /* If the promise is live, then run its dtor if that's available. */
5159 if (promise_dtor
&& promise_dtor
!= error_mark_node
)
5161 tree promise_d_if
= begin_if_stmt ();
5162 finish_if_stmt_cond (coro_promise_live
, promise_d_if
);
5163 finish_expr_stmt (promise_dtor
);
5164 finish_then_clause (promise_d_if
);
5165 tree promise_d_if_scope
= IF_SCOPE (promise_d_if
);
5166 IF_SCOPE (promise_d_if
) = NULL
;
5167 promise_d_if
= do_poplevel (promise_d_if_scope
);
5168 add_stmt (promise_d_if
);
5171 /* Clean up any frame copies of parms with non-trivial dtors. */
5172 if (DECL_ARGUMENTS (orig
))
5173 for (tree arg
= DECL_ARGUMENTS (orig
); arg
!= NULL
;
5174 arg
= DECL_CHAIN (arg
))
5176 param_info
*parm_i
= param_uses
->get (arg
);
5177 if (parm_i
->trivial_dtor
)
5179 if (parm_i
->fr_copy_dtor
&& parm_i
->fr_copy_dtor
!= error_mark_node
)
5181 tree dtor_if
= begin_if_stmt ();
5182 finish_if_stmt_cond (parm_i
->guard_var
, dtor_if
);
5183 finish_expr_stmt (parm_i
->fr_copy_dtor
);
5184 finish_then_clause (dtor_if
);
5185 tree parm_d_if_scope
= IF_SCOPE (dtor_if
);
5186 IF_SCOPE (dtor_if
) = NULL
;
5187 dtor_if
= do_poplevel (parm_d_if_scope
);
5192 /* We always expect to delete the frame. */
5193 tree del_coro_fr
= coro_get_frame_dtor (coro_fp
, orig
, frame_size
,
5194 promise_type
, fn_start
);
5195 finish_expr_stmt (del_coro_fr
);
5196 tree rethrow
= build_throw (fn_start
, NULL_TREE
);
5197 suppress_warning (rethrow
);
5198 finish_expr_stmt (rethrow
);
5199 finish_handler (handler
);
5200 TRY_HANDLERS (ramp_cleanup
) = pop_stmt_list (TRY_HANDLERS (ramp_cleanup
));
5203 BIND_EXPR_BODY (ramp_bind
) = pop_stmt_list (ramp_body
);
5204 TREE_SIDE_EFFECTS (ramp_bind
) = true;
5206 /* Start to build the final functions.
5208 We push_deferring_access_checks to avoid these routines being seen as
5209 nested by the middle end; we are doing the outlining here. */
5211 push_deferring_access_checks (dk_no_check
);
5213 /* Build the actor... */
5214 build_actor_fn (fn_start
, coro_frame_type
, actor
, fnbody
, orig
,
5215 &local_var_uses
, param_dtor_list
,
5216 resume_idx_var
, body_aw_points
.await_number
, frame_size
);
5219 build_destroy_fn (fn_start
, coro_frame_type
, destroy
, actor
);
5221 pop_deferring_access_checks ();
5223 DECL_SAVED_TREE (orig
) = newbody
;
5224 /* Link our new functions into the list. */
5225 TREE_CHAIN (destroy
) = TREE_CHAIN (orig
);
5226 TREE_CHAIN (actor
) = destroy
;
5227 TREE_CHAIN (orig
) = actor
;
5230 *destroyer
= destroy
;
5232 delete suspend_points
;
5233 suspend_points
= NULL
;
5237 #include "gt-cp-coroutines.h"