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

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.