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

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.