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

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.