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