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

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.