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

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