LCOV - code coverage report
Current view: top level - gcc/cp - coroutines.cc (source / functions) Hit Total Coverage
Test: gcc.info Lines: 2166 2288 94.7 %
Date: 2023-07-19 08:18:47 Functions: 69 73 94.5 %

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

Generated by: LCOV version 1.16