LCOV - code coverage report
Current view: top level - gcc/cp - coroutines.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 95.0 % 2267 2154
Test Date: 2024-04-13 14:00:49 Functions: 94.5 % 73 69
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: - 0 0

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

Generated by: LCOV version 2.1-beta

LCOV profile is generated on x86_64 machine using following configure options: configure --disable-bootstrap --enable-coverage=opt --enable-languages=c,c++,fortran,go,jit,lto,rust,m2 --enable-host-shared. GCC test suite is run with the built compiler.