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

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.