LCOV - code coverage report
Current view: top level - gcc/cp - coroutines.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 93.2 % 2313 2155
Test Date: 2026-10-24 16:24:59 Functions: 99.0 % 96 95
Legend: Lines:     hit not hit

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

Generated by: LCOV version 2.5.0-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.