LCOV - code coverage report
Current view: top level - gcc/cp - coroutines.cc (source / functions) Hit Total Coverage
Test: gcc.info Lines: 1618 1687 95.9 %
Date: 2020-03-28 11:57:23 Functions: 43 49 87.8 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 0 -

           Branch data     Line data    Source code
       1                 :            : /* coroutine-specific state, expansions and tests.
       2                 :            : 
       3                 :            :    Copyright (C) 2018-2020 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                 :            : 
      36                 :            : static bool coro_promise_type_found_p (tree, location_t);
      37                 :            : 
      38                 :            : /* GCC C++ coroutines implementation.
      39                 :            : 
      40                 :            :   The user authors a function that becomes a coroutine (lazily) by
      41                 :            :   making use of any of the co_await, co_yield or co_return keywords.
      42                 :            : 
      43                 :            :   Unlike a regular function, where the activation record is placed on the
      44                 :            :   stack, and is destroyed on function exit, a coroutine has some state that
      45                 :            :   persists between calls - the coroutine frame (analogous to a stack frame).
      46                 :            : 
      47                 :            :   We transform the user's function into three pieces:
      48                 :            :   1. A so-called ramp function, that establishes the coroutine frame and
      49                 :            :      begins execution of the coroutine.
      50                 :            :   2. An actor function that contains the state machine corresponding to the
      51                 :            :      user's suspend/resume structure.
      52                 :            :   3. A stub function that calls the actor function in 'destroy' mode.
      53                 :            : 
      54                 :            :   The actor function is executed:
      55                 :            :    * from "resume point 0" by the ramp.
      56                 :            :    * from resume point N ( > 0 ) for handle.resume() calls.
      57                 :            :    * from the destroy stub for destroy point N for handle.destroy() calls.
      58                 :            : 
      59                 :            :   The functions in this file carry out the necessary analysis of, and
      60                 :            :   transforms to, the AST to perform this.
      61                 :            : 
      62                 :            :   The C++ coroutine design makes use of some helper functions that are
      63                 :            :   authored in a so-called "promise" class provided by the user.
      64                 :            : 
      65                 :            :   At parse time (or post substitution) the type of the coroutine promise
      66                 :            :   will be determined.  At that point, we can look up the required promise
      67                 :            :   class methods and issue diagnostics if they are missing or incorrect.  To
      68                 :            :   avoid repeating these actions at code-gen time, we make use of temporary
      69                 :            :   'proxy' variables for the coroutine handle and the promise - which will
      70                 :            :   eventually be instantiated in the coroutine frame.
      71                 :            : 
      72                 :            :   Each of the keywords will expand to a code sequence (although co_yield is
      73                 :            :   just syntactic sugar for a co_await).
      74                 :            : 
      75                 :            :   We defer the analysis and transformation until template expansion is
      76                 :            :   complete so that we have complete types at that time.  */
      77                 :            : 
      78                 :            : 
      79                 :            : /* The state that we collect during parsing (and template expansion) for
      80                 :            :    a coroutine.  */
      81                 :            : 
      82                 :            : struct GTY((for_user)) coroutine_info
      83                 :            : {
      84                 :            :   tree function_decl; /* The original function decl.  */
      85                 :            :   tree promise_type; /* The cached promise type for this function.  */
      86                 :            :   tree handle_type;  /* The cached coroutine handle for this function.  */
      87                 :            :   tree self_h_proxy; /* A handle instance that is used as the proxy for the
      88                 :            :                         one that will eventually be allocated in the coroutine
      89                 :            :                         frame.  */
      90                 :            :   tree promise_proxy; /* Likewise, a proxy promise instance.  */
      91                 :            :   location_t first_coro_keyword; /* The location of the keyword that made this
      92                 :            :                                     function into a coroutine.  */
      93                 :            :   /* Flags to avoid repeated errors for per-function issues.  */
      94                 :            :   bool coro_ret_type_error_emitted;
      95                 :            :   bool coro_promise_error_emitted;
      96                 :            : };
      97                 :            : 
      98                 :            : struct coroutine_info_hasher : ggc_ptr_hash<coroutine_info>
      99                 :            : {
     100                 :            :   typedef tree compare_type; /* We only compare the function decl.  */
     101                 :            :   static inline hashval_t hash (coroutine_info *);
     102                 :            :   static inline hashval_t hash (const compare_type &);
     103                 :            :   static inline bool equal (coroutine_info *, coroutine_info *);
     104                 :            :   static inline bool equal (coroutine_info *, const compare_type &);
     105                 :            : };
     106                 :            : 
     107                 :            : /* This table holds all the collected coroutine state for coroutines in
     108                 :            :    the current translation unit.  */
     109                 :            : 
     110                 :            : static GTY (()) hash_table<coroutine_info_hasher> *coroutine_info_table;
     111                 :            : 
     112                 :            : /* We will initialise state lazily.  */
     113                 :            : static bool coro_initialized = false;
     114                 :            : 
     115                 :            : /* Return a hash value for the entry pointed to by INFO.
     116                 :            :    The compare type is a tree, but the only trees we are going use are
     117                 :            :    function decls.  We use the DECL_UID as the hash value since that is
     118                 :            :    stable across PCH.  */
     119                 :            : 
     120                 :            : hashval_t
     121                 :      18986 : coroutine_info_hasher::hash (coroutine_info *info)
     122                 :            : {
     123                 :      18986 :   return DECL_UID (info->function_decl);
     124                 :            : }
     125                 :            : 
     126                 :            : /* Return a hash value for the compare value COMP.  */
     127                 :            : 
     128                 :            : hashval_t
     129                 :      22400 : coroutine_info_hasher::hash (const compare_type& comp)
     130                 :            : {
     131                 :      44800 :   return DECL_UID (comp);
     132                 :            : }
     133                 :            : 
     134                 :            : /* Return true if the entries pointed to by LHS and RHS are for the
     135                 :            :    same coroutine.  */
     136                 :            : 
     137                 :            : bool
     138                 :            : coroutine_info_hasher::equal (coroutine_info *lhs, coroutine_info *rhs)
     139                 :            : {
     140                 :            :   return lhs->function_decl == rhs->function_decl;
     141                 :            : }
     142                 :            : 
     143                 :            : bool
     144                 :      22815 : coroutine_info_hasher::equal (coroutine_info *lhs, const compare_type& rhs)
     145                 :            : {
     146                 :      22815 :   return lhs->function_decl == rhs;
     147                 :            : }
     148                 :            : 
     149                 :            : /* Get the existing coroutine_info for FN_DECL, or insert a new one if the
     150                 :            :    entry does not yet exist.  */
     151                 :            : 
     152                 :            : coroutine_info *
     153                 :       2378 : get_or_insert_coroutine_info (tree fn_decl)
     154                 :            : {
     155                 :       2378 :   gcc_checking_assert (coroutine_info_table != NULL);
     156                 :            : 
     157                 :       2378 :   coroutine_info **slot = coroutine_info_table->find_slot_with_hash
     158                 :       2378 :     (fn_decl, coroutine_info_hasher::hash (fn_decl), INSERT);
     159                 :            : 
     160                 :       2378 :   if (*slot == NULL)
     161                 :            :     {
     162                 :        789 :       *slot = new (ggc_cleared_alloc<coroutine_info> ()) coroutine_info ();
     163                 :        789 :       (*slot)->function_decl = fn_decl;
     164                 :            :     }
     165                 :            : 
     166                 :       2378 :   return *slot;
     167                 :            : }
     168                 :            : 
     169                 :            : /* Get the existing coroutine_info for FN_DECL, fail if it doesn't exist.  */
     170                 :            : 
     171                 :            : coroutine_info *
     172                 :      20022 : get_coroutine_info (tree fn_decl)
     173                 :            : {
     174                 :      20022 :   if (coroutine_info_table == NULL)
     175                 :            :     return NULL;
     176                 :            : 
     177                 :      20022 :   coroutine_info **slot = coroutine_info_table->find_slot_with_hash
     178                 :      20022 :     (fn_decl, coroutine_info_hasher::hash (fn_decl), NO_INSERT);
     179                 :      20022 :   if (slot)
     180                 :      20022 :     return *slot;
     181                 :            :   return NULL;
     182                 :            : }
     183                 :            : 
     184                 :            : /* We will lazily create all the identifiers that are used by coroutines
     185                 :            :    on the first attempt to lookup the traits.  */
     186                 :            : 
     187                 :            : /* Identifiers that are used by all coroutines.  */
     188                 :            : 
     189                 :            : static GTY(()) tree coro_traits_identifier;
     190                 :            : static GTY(()) tree coro_handle_identifier;
     191                 :            : static GTY(()) tree coro_promise_type_identifier;
     192                 :            : 
     193                 :            : /* Required promise method name identifiers.  */
     194                 :            : 
     195                 :            : static GTY(()) tree coro_await_transform_identifier;
     196                 :            : static GTY(()) tree coro_initial_suspend_identifier;
     197                 :            : static GTY(()) tree coro_final_suspend_identifier;
     198                 :            : static GTY(()) tree coro_return_void_identifier;
     199                 :            : static GTY(()) tree coro_return_value_identifier;
     200                 :            : static GTY(()) tree coro_yield_value_identifier;
     201                 :            : static GTY(()) tree coro_resume_identifier;
     202                 :            : static GTY(()) tree coro_address_identifier;
     203                 :            : static GTY(()) tree coro_from_address_identifier;
     204                 :            : static GTY(()) tree coro_get_return_object_identifier;
     205                 :            : static GTY(()) tree coro_gro_on_allocation_fail_identifier;
     206                 :            : static GTY(()) tree coro_unhandled_exception_identifier;
     207                 :            : 
     208                 :            : /* Awaitable methods.  */
     209                 :            : 
     210                 :            : static GTY(()) tree coro_await_ready_identifier;
     211                 :            : static GTY(()) tree coro_await_suspend_identifier;
     212                 :            : static GTY(()) tree coro_await_resume_identifier;
     213                 :            : 
     214                 :            : /* Create the identifiers used by the coroutines library interfaces.  */
     215                 :            : 
     216                 :            : static void
     217                 :        774 : coro_init_identifiers ()
     218                 :            : {
     219                 :        774 :   coro_traits_identifier = get_identifier ("coroutine_traits");
     220                 :        774 :   coro_handle_identifier = get_identifier ("coroutine_handle");
     221                 :        774 :   coro_promise_type_identifier = get_identifier ("promise_type");
     222                 :            : 
     223                 :        774 :   coro_await_transform_identifier = get_identifier ("await_transform");
     224                 :        774 :   coro_initial_suspend_identifier = get_identifier ("initial_suspend");
     225                 :        774 :   coro_final_suspend_identifier = get_identifier ("final_suspend");
     226                 :        774 :   coro_return_void_identifier = get_identifier ("return_void");
     227                 :        774 :   coro_return_value_identifier = get_identifier ("return_value");
     228                 :        774 :   coro_yield_value_identifier = get_identifier ("yield_value");
     229                 :        774 :   coro_resume_identifier = get_identifier ("resume");
     230                 :        774 :   coro_address_identifier = get_identifier ("address");
     231                 :        774 :   coro_from_address_identifier = get_identifier ("from_address");
     232                 :        774 :   coro_get_return_object_identifier = get_identifier ("get_return_object");
     233                 :       1548 :   coro_gro_on_allocation_fail_identifier =
     234                 :        774 :     get_identifier ("get_return_object_on_allocation_failure");
     235                 :        774 :   coro_unhandled_exception_identifier = get_identifier ("unhandled_exception");
     236                 :            : 
     237                 :        774 :   coro_await_ready_identifier = get_identifier ("await_ready");
     238                 :        774 :   coro_await_suspend_identifier = get_identifier ("await_suspend");
     239                 :        774 :   coro_await_resume_identifier = get_identifier ("await_resume");
     240                 :        774 : }
     241                 :            : 
     242                 :            : /* Trees we only need to set up once.  */
     243                 :            : 
     244                 :            : static GTY(()) tree coro_traits_templ;
     245                 :            : static GTY(()) tree coro_handle_templ;
     246                 :            : static GTY(()) tree void_coro_handle_type;
     247                 :            : 
     248                 :            : /* ================= Parse, Semantics and Type checking ================= */
     249                 :            : 
     250                 :            : /* This initial set of routines are helper for the parsing and template
     251                 :            :    expansion phases.
     252                 :            : 
     253                 :            :    At the completion of this, we will have completed trees for each of the
     254                 :            :    keywords, but making use of proxy variables for the self-handle and the
     255                 :            :    promise class instance.  */
     256                 :            : 
     257                 :            : /* [coroutine.traits]
     258                 :            :    Lookup the coroutine_traits template decl.  */
     259                 :            : 
     260                 :            : static tree
     261                 :        774 : find_coro_traits_template_decl (location_t kw)
     262                 :            : {
     263                 :            :   /* If we are missing fundmental information, such as the traits, (or the
     264                 :            :      declaration found is not a type template), then don't emit an error for
     265                 :            :      every keyword in a TU, just do it once.  */
     266                 :        774 :   static bool traits_error_emitted = false;
     267                 :            : 
     268                 :       1548 :   tree traits_decl = lookup_qualified_name (std_node, coro_traits_identifier,
     269                 :            :                                             0,
     270                 :        774 :                                             /*complain=*/!traits_error_emitted);
     271                 :        774 :   if (traits_decl == error_mark_node
     272                 :        774 :       || !DECL_TYPE_TEMPLATE_P (traits_decl))
     273                 :            :     {
     274                 :          6 :       if (!traits_error_emitted)
     275                 :            :         {
     276                 :          4 :           gcc_rich_location richloc (kw);
     277                 :          2 :           error_at (&richloc, "coroutines require a traits template; cannot"
     278                 :            :                     " find %<%E::%E%>", std_node, coro_traits_identifier);
     279                 :          2 :           inform (&richloc, "perhaps %<#include <coroutine>%> is missing");
     280                 :          2 :           traits_error_emitted = true;
     281                 :            :         }
     282                 :          6 :       return NULL_TREE;
     283                 :            :     }
     284                 :            :   else
     285                 :            :     return traits_decl;
     286                 :            : }
     287                 :            : 
     288                 :            : /*  Instantiate Coroutine traits for the function signature.  */
     289                 :            : 
     290                 :            : static tree
     291                 :        790 : instantiate_coro_traits (tree fndecl, location_t kw)
     292                 :            : {
     293                 :            :   /* [coroutine.traits.primary]
     294                 :            :      So now build up a type list for the template <typename _R, typename...>.
     295                 :            :      The types are the function's arg types and _R is the function return
     296                 :            :      type.  */
     297                 :            : 
     298                 :        790 :   tree functyp = TREE_TYPE (fndecl);
     299                 :        790 :   tree arg_node = TYPE_ARG_TYPES (functyp);
     300                 :        790 :   tree argtypes = make_tree_vec (list_length (arg_node)-1);
     301                 :        790 :   unsigned p = 0;
     302                 :            : 
     303                 :       2716 :   while (arg_node != NULL_TREE && !VOID_TYPE_P (TREE_VALUE (arg_node)))
     304                 :            :     {
     305                 :        568 :       TREE_VEC_ELT (argtypes, p++) = TREE_VALUE (arg_node);
     306                 :        568 :       arg_node = TREE_CHAIN (arg_node);
     307                 :            :     }
     308                 :            : 
     309                 :        790 :   tree argtypepack = cxx_make_type (TYPE_ARGUMENT_PACK);
     310                 :        790 :   SET_ARGUMENT_PACK_ARGS (argtypepack, argtypes);
     311                 :            : 
     312                 :        790 :   tree targ = make_tree_vec (2);
     313                 :        790 :   TREE_VEC_ELT (targ, 0) = TREE_TYPE (functyp);
     314                 :        790 :   TREE_VEC_ELT (targ, 1) = argtypepack;
     315                 :            : 
     316                 :        790 :   tree traits_class
     317                 :        790 :     = lookup_template_class (coro_traits_templ, targ,
     318                 :            :                              /*in_decl=*/NULL_TREE, /*context=*/NULL_TREE,
     319                 :            :                              /*entering scope=*/false, tf_warning_or_error);
     320                 :            : 
     321                 :        790 :   if (traits_class == error_mark_node)
     322                 :            :     {
     323                 :          0 :       error_at (kw, "cannot instantiate %<coroutine traits%>");
     324                 :          0 :       return NULL_TREE;
     325                 :            :     }
     326                 :            : 
     327                 :            :   return traits_class;
     328                 :            : }
     329                 :            : 
     330                 :            : /* [coroutine.handle] */
     331                 :            : 
     332                 :            : static tree
     333                 :        768 : find_coro_handle_template_decl (location_t kw)
     334                 :            : {
     335                 :            :   /* As for the coroutine traits, this error is per TU, so only emit
     336                 :            :     it once.  */
     337                 :        768 :   static bool coro_handle_error_emitted = false;
     338                 :       1536 :   tree handle_decl = lookup_qualified_name (std_node, coro_handle_identifier,
     339                 :        768 :                                             0, !coro_handle_error_emitted);
     340                 :        768 :   if (handle_decl == error_mark_node
     341                 :        768 :       || !DECL_CLASS_TEMPLATE_P (handle_decl))
     342                 :            :     {
     343                 :          6 :       if (!coro_handle_error_emitted)
     344                 :          2 :         error_at (kw, "coroutines require a handle class template;"
     345                 :            :                   " cannot find %<%E::%E%>", std_node, coro_handle_identifier);
     346                 :          6 :       coro_handle_error_emitted = true;
     347                 :          6 :       return NULL_TREE;
     348                 :            :     }
     349                 :            :   else
     350                 :            :     return handle_decl;
     351                 :            : }
     352                 :            : 
     353                 :            : /* Instantiate the handle template for a given promise type.  */
     354                 :            : 
     355                 :            : static tree
     356                 :       1549 : instantiate_coro_handle_for_promise_type (location_t kw, tree promise_type)
     357                 :            : {
     358                 :            :   /* So now build up a type list for the template, one entry, the promise.  */
     359                 :       1549 :   tree targ = make_tree_vec (1);
     360                 :       1549 :   TREE_VEC_ELT (targ, 0) = promise_type;
     361                 :       1549 :   tree handle_type
     362                 :       1549 :     = lookup_template_class (coro_handle_identifier, targ,
     363                 :            :                              /* in_decl=*/NULL_TREE,
     364                 :            :                              /* context=*/std_node,
     365                 :            :                              /* entering scope=*/false, tf_warning_or_error);
     366                 :            : 
     367                 :       1549 :   if (handle_type == error_mark_node)
     368                 :            :     {
     369                 :          0 :       error_at (kw, "cannot instantiate a %<coroutine handle%> for"
     370                 :            :                 " promise type %qT", promise_type);
     371                 :          0 :       return NULL_TREE;
     372                 :            :     }
     373                 :            : 
     374                 :            :   return handle_type;
     375                 :            : }
     376                 :            : 
     377                 :            : /* Look for the promise_type in the instantiated traits.  */
     378                 :            : 
     379                 :            : static tree
     380                 :        790 : find_promise_type (tree traits_class)
     381                 :            : {
     382                 :        790 :   tree promise_type
     383                 :        790 :     = lookup_member (traits_class, coro_promise_type_identifier,
     384                 :            :                      /* protect=*/1, /*want_type=*/true, tf_warning_or_error);
     385                 :            : 
     386                 :        790 :   if (promise_type)
     387                 :        790 :     promise_type
     388                 :        790 :       = complete_type_or_else (TREE_TYPE (promise_type), promise_type);
     389                 :            : 
     390                 :            :   /* NULL_TREE on fail.  */
     391                 :        790 :   return promise_type;
     392                 :            : }
     393                 :            : 
     394                 :            : static bool
     395                 :       2390 : coro_promise_type_found_p (tree fndecl, location_t loc)
     396                 :            : {
     397                 :       2390 :   gcc_assert (fndecl != NULL_TREE);
     398                 :            : 
     399                 :       2390 :   if (!coro_initialized)
     400                 :            :     {
     401                 :            :       /* Trees we only need to create once.
     402                 :            :          Set up the identifiers we will use.  */
     403                 :        774 :       coro_init_identifiers ();
     404                 :            : 
     405                 :            :       /* Coroutine traits template.  */
     406                 :        774 :       coro_traits_templ = find_coro_traits_template_decl (loc);
     407                 :        774 :       if (coro_traits_templ == NULL_TREE)
     408                 :            :         return false;
     409                 :            : 
     410                 :            :       /*  coroutine_handle<> template.  */
     411                 :        768 :       coro_handle_templ = find_coro_handle_template_decl (loc);
     412                 :        768 :       if (coro_handle_templ == NULL_TREE)
     413                 :            :         return false;
     414                 :            : 
     415                 :            :       /*  We can also instantiate the void coroutine_handle<>  */
     416                 :       1524 :       void_coro_handle_type =
     417                 :        762 :         instantiate_coro_handle_for_promise_type (loc, NULL_TREE);
     418                 :        762 :       if (void_coro_handle_type == NULL_TREE)
     419                 :            :         return false;
     420                 :            : 
     421                 :            :       /* A table to hold the state, per coroutine decl.  */
     422                 :        762 :       gcc_checking_assert (coroutine_info_table == NULL);
     423                 :       1524 :       coroutine_info_table =
     424                 :        762 :         hash_table<coroutine_info_hasher>::create_ggc (11);
     425                 :            : 
     426                 :        762 :       if (coroutine_info_table == NULL)
     427                 :            :         return false;
     428                 :            : 
     429                 :        762 :       coro_initialized = true;
     430                 :            :     }
     431                 :            : 
     432                 :            :   /* Save the coroutine data on the side to avoid the overhead on every
     433                 :            :      function decl tree.  */
     434                 :            : 
     435                 :       2378 :   coroutine_info *coro_info = get_or_insert_coroutine_info (fndecl);
     436                 :            :   /* Without this, we cannot really proceed.  */
     437                 :       2378 :   gcc_checking_assert (coro_info);
     438                 :            : 
     439                 :            :   /* If we don't already have a current promise type, try to look it up.  */
     440                 :       2378 :   if (coro_info->promise_type == NULL_TREE)
     441                 :            :     {
     442                 :            :       /* Get the coroutine traits template class instance for the function
     443                 :            :          signature we have - coroutine_traits <R, ...>  */
     444                 :        793 :       tree return_type = TREE_TYPE (TREE_TYPE (fndecl));
     445                 :       1583 :       if (!CLASS_TYPE_P (return_type))
     446                 :            :         {
     447                 :            :           /* It makes more sense to show the function header for this, even
     448                 :            :              though we will have encountered it when processing a keyword.
     449                 :            :              Only emit the error once, not for every keyword we encounter.  */
     450                 :          3 :           if (!coro_info->coro_ret_type_error_emitted)
     451                 :          1 :             error_at (DECL_SOURCE_LOCATION (fndecl), "coroutine return type"
     452                 :            :                       " %qT is not a class", return_type);
     453                 :          3 :           coro_info->coro_ret_type_error_emitted = true;
     454                 :          3 :           return false;
     455                 :            :         }
     456                 :            : 
     457                 :        790 :       tree templ_class = instantiate_coro_traits (fndecl, loc);
     458                 :            : 
     459                 :            :       /* Find the promise type for that.  */
     460                 :        790 :       coro_info->promise_type = find_promise_type (templ_class);
     461                 :            : 
     462                 :            :       /* If we don't find it, punt on the rest.  */
     463                 :        790 :       if (coro_info->promise_type == NULL_TREE)
     464                 :            :         {
     465                 :          3 :           if (!coro_info->coro_promise_error_emitted)
     466                 :          1 :             error_at (loc, "unable to find the promise type for"
     467                 :            :                       " this coroutine");
     468                 :          3 :           coro_info->coro_promise_error_emitted = true;
     469                 :          3 :           return false;
     470                 :            :         }
     471                 :            : 
     472                 :            :       /* Try to find the handle type for the promise.  */
     473                 :        787 :       tree handle_type =
     474                 :        787 :         instantiate_coro_handle_for_promise_type (loc, coro_info->promise_type);
     475                 :        787 :       if (handle_type == NULL_TREE)
     476                 :            :         return false;
     477                 :            : 
     478                 :            :       /* Complete this, we're going to use it.  */
     479                 :        787 :       coro_info->handle_type = complete_type_or_else (handle_type, fndecl);
     480                 :            : 
     481                 :            :       /* Diagnostic would be emitted by complete_type_or_else.  */
     482                 :        787 :       if (!coro_info->handle_type)
     483                 :            :         return false;
     484                 :            : 
     485                 :            :       /* Build a proxy for a handle to "self" as the param to
     486                 :            :          await_suspend() calls.  */
     487                 :        787 :       coro_info->self_h_proxy
     488                 :        787 :         = build_lang_decl (VAR_DECL, get_identifier ("self_h.proxy"),
     489                 :            :                            coro_info->handle_type);
     490                 :            : 
     491                 :            :       /* Build a proxy for the promise so that we can perform lookups.  */
     492                 :        787 :       coro_info->promise_proxy
     493                 :        787 :         = build_lang_decl (VAR_DECL, get_identifier ("promise.proxy"),
     494                 :            :                            coro_info->promise_type);
     495                 :            : 
     496                 :            :       /* Note where we first saw a coroutine keyword.  */
     497                 :        787 :       coro_info->first_coro_keyword = loc;
     498                 :            :     }
     499                 :            : 
     500                 :            :   return true;
     501                 :            : }
     502                 :            : 
     503                 :            : /* These functions assumes that the caller has verified that the state for
     504                 :            :    the decl has been initialized, we try to minimize work here.  */
     505                 :            : 
     506                 :            : static tree
     507                 :      10983 : get_coroutine_promise_type (tree decl)
     508                 :            : {
     509                 :      10983 :   if (coroutine_info *info = get_coroutine_info (decl))
     510                 :      10196 :     return info->promise_type;
     511                 :            : 
     512                 :            :   return NULL_TREE;
     513                 :            : }
     514                 :            : 
     515                 :            : static tree
     516                 :       2353 : get_coroutine_handle_type (tree decl)
     517                 :            : {
     518                 :       2353 :   if (coroutine_info *info = get_coroutine_info (decl))
     519                 :       1566 :     return info->handle_type;
     520                 :            : 
     521                 :            :   return NULL_TREE;
     522                 :            : }
     523                 :            : 
     524                 :            : static tree
     525                 :       3010 : get_coroutine_self_handle_proxy (tree decl)
     526                 :            : {
     527                 :       3010 :   if (coroutine_info *info = get_coroutine_info (decl))
     528                 :       3010 :     return info->self_h_proxy;
     529                 :            : 
     530                 :            :   return NULL_TREE;
     531                 :            : }
     532                 :            : 
     533                 :            : static tree
     534                 :       3676 : get_coroutine_promise_proxy (tree decl)
     535                 :            : {
     536                 :       3676 :   if (coroutine_info *info = get_coroutine_info (decl))
     537                 :       3676 :     return info->promise_proxy;
     538                 :            : 
     539                 :            :   return NULL_TREE;
     540                 :            : }
     541                 :            : 
     542                 :            : static tree
     543                 :       7846 : lookup_promise_method (tree fndecl, tree member_id, location_t loc,
     544                 :            :                        bool musthave)
     545                 :            : {
     546                 :       7846 :   tree promise = get_coroutine_promise_type (fndecl);
     547                 :       7846 :   tree pm_memb
     548                 :       7846 :     = lookup_member (promise, member_id,
     549                 :            :                      /*protect=*/1, /*want_type=*/0, tf_warning_or_error);
     550                 :       7846 :   if (musthave && pm_memb == NULL_TREE)
     551                 :            :     {
     552                 :          5 :       error_at (loc, "no member named %qE in %qT", member_id, promise);
     553                 :          5 :       return error_mark_node;
     554                 :            :     }
     555                 :            :   return pm_memb;
     556                 :            : }
     557                 :            : 
     558                 :            : /* Lookup an Awaitable member, which should be await_ready, await_suspend
     559                 :            :    or await_resume.  */
     560                 :            : 
     561                 :            : static tree
     562                 :       6692 : lookup_awaitable_member (tree await_type, tree member_id, location_t loc)
     563                 :            : {
     564                 :       6692 :   tree aw_memb
     565                 :       6692 :     = lookup_member (await_type, member_id,
     566                 :            :                      /*protect=*/1, /*want_type=*/0, tf_warning_or_error);
     567                 :       6692 :   if (aw_memb == NULL_TREE)
     568                 :            :     {
     569                 :          4 :       error_at (loc, "no member named %qE in %qT", member_id, await_type);
     570                 :          4 :       return error_mark_node;
     571                 :            :     }
     572                 :            :   return aw_memb;
     573                 :            : }
     574                 :            : 
     575                 :            : /* Here we check the constraints that are common to all keywords (since the
     576                 :            :    presence of a coroutine keyword makes the function into a coroutine).  */
     577                 :            : 
     578                 :            : static bool
     579                 :       1902 : coro_common_keyword_context_valid_p (tree fndecl, location_t kw_loc,
     580                 :            :                                      const char *kw_name)
     581                 :            : {
     582                 :       1902 :   if (fndecl == NULL_TREE)
     583                 :            :     {
     584                 :          4 :       error_at (kw_loc, "%qs cannot be used outside a function", kw_name);
     585                 :          4 :       return false;
     586                 :            :     }
     587                 :            : 
     588                 :            :   /* This is arranged in order of prohibitions in the std.  */
     589                 :       5697 :   if (DECL_MAIN_P (fndecl))
     590                 :            :     {
     591                 :            :       /* [basic.start.main] 3. The function main shall not be a coroutine.  */
     592                 :          3 :       error_at (kw_loc, "%qs cannot be used in the %<main%> function",
     593                 :            :                 kw_name);
     594                 :          3 :       return false;
     595                 :            :     }
     596                 :            : 
     597                 :       3790 :   if (DECL_DECLARED_CONSTEXPR_P (fndecl))
     598                 :            :     {
     599                 :            :       /* [dcl.constexpr] 3.3 it shall not be a coroutine.  */
     600                 :          3 :       error_at (kw_loc, "%qs cannot be used in a %<constexpr%> function",
     601                 :            :                 kw_name);
     602                 :          3 :       cp_function_chain->invalid_constexpr = true;
     603                 :          3 :       return false;
     604                 :            :     }
     605                 :            : 
     606                 :       1892 :   if (FNDECL_USED_AUTO (fndecl))
     607                 :            :     {
     608                 :            :       /* [dcl.spec.auto] 15. A function declared with a return type that uses
     609                 :            :          a placeholder type shall not be a coroutine.  */
     610                 :          6 :       error_at (kw_loc,
     611                 :            :                 "%qs cannot be used in a function with a deduced return type",
     612                 :            :                 kw_name);
     613                 :          6 :       return false;
     614                 :            :     }
     615                 :            : 
     616                 :       1886 :   if (varargs_function_p (fndecl))
     617                 :            :     {
     618                 :            :       /* [dcl.fct.def.coroutine] The parameter-declaration-clause of the
     619                 :            :          coroutine shall not terminate with an ellipsis that is not part
     620                 :            :          of a parameter-declaration.  */
     621                 :          3 :       error_at (kw_loc,
     622                 :            :                 "%qs cannot be used in a varargs function", kw_name);
     623                 :          3 :       return false;
     624                 :            :     }
     625                 :            : 
     626                 :       3766 :   if (DECL_CONSTRUCTOR_P (fndecl))
     627                 :            :     {
     628                 :            :       /* [class.ctor] 7. a constructor shall not be a coroutine.  */
     629                 :          3 :       error_at (kw_loc, "%qs cannot be used in a constructor", kw_name);
     630                 :          3 :       return false;
     631                 :            :     }
     632                 :            : 
     633                 :       1880 :   if (DECL_DESTRUCTOR_P (fndecl))
     634                 :            :     {
     635                 :            :       /* [class.dtor] 21. a destructor shall not be a coroutine.  */
     636                 :          3 :       error_at (kw_loc, "%qs cannot be used in a destructor", kw_name);
     637                 :          3 :       return false;
     638                 :            :     }
     639                 :            : 
     640                 :            :   return true;
     641                 :            : }
     642                 :            : 
     643                 :            : /* Here we check the constraints that are not per keyword.  */
     644                 :            : 
     645                 :            : static bool
     646                 :        793 : coro_function_valid_p (tree fndecl)
     647                 :            : {
     648                 :        793 :   location_t f_loc = DECL_SOURCE_LOCATION (fndecl);
     649                 :            : 
     650                 :            :   /* For cases where fundamental information cannot be found, e.g. the
     651                 :            :      coroutine traits are missing, we need to punt early.  */
     652                 :        793 :   if (!coro_promise_type_found_p (fndecl, f_loc))
     653                 :            :     return false;
     654                 :            : 
     655                 :            :   /* Since we think the function is a coroutine, that implies we parsed
     656                 :            :      a keyword that triggered this.  Keywords check promise validity for
     657                 :            :      their context and thus the promise type should be known at this point.  */
     658                 :        787 :   if (get_coroutine_handle_type (fndecl) == NULL_TREE
     659                 :       1574 :       || get_coroutine_promise_type (fndecl) == NULL_TREE)
     660                 :          0 :     return false;
     661                 :            : 
     662                 :        787 :   if (current_function_returns_value || current_function_returns_null)
     663                 :            :     {
     664                 :            :        /* TODO: record or extract positions of returns (and the first coro
     665                 :            :           keyword) so that we can add notes to the diagnostic about where
     666                 :            :           the bad keyword is and what made the function into a coro.  */
     667                 :          1 :       error_at (f_loc, "a %<return%> statement is not allowed in coroutine;"
     668                 :            :                         " did you mean %<co_return%>?");
     669                 :          1 :       return false;
     670                 :            :     }
     671                 :            : 
     672                 :            :   return true;
     673                 :            : }
     674                 :            : 
     675                 :            : enum suspend_point_kind {
     676                 :            :   CO_AWAIT_SUSPEND_POINT = 0,
     677                 :            :   CO_YIELD_SUSPEND_POINT,
     678                 :            :   INITIAL_SUSPEND_POINT,
     679                 :            :   FINAL_SUSPEND_POINT
     680                 :            : };
     681                 :            : 
     682                 :            : /*  This performs [expr.await] bullet 3.3 and validates the interface obtained.
     683                 :            :     It is also used to build the initial and final suspend points.
     684                 :            : 
     685                 :            :     'a', 'o' and 'e' are used as per the description in the section noted.
     686                 :            : 
     687                 :            :     A, the original yield/await expr, is found at source location LOC.
     688                 :            : 
     689                 :            :     We will be constructing a CO_AWAIT_EXPR for a suspend point of one of
     690                 :            :     the four suspend_point_kind kinds.  This is indicated by SUSPEND_KIND.  */
     691                 :            : 
     692                 :            : static tree
     693                 :       2233 : build_co_await (location_t loc, tree a, suspend_point_kind suspend_kind)
     694                 :            : {
     695                 :            :   /* Try and overload of operator co_await, .... */
     696                 :       2233 :   tree o;
     697                 :       2233 :   if (MAYBE_CLASS_TYPE_P (TREE_TYPE (a)))
     698                 :            :     {
     699                 :       2232 :       tree overload = NULL_TREE;
     700                 :       2232 :       o = build_new_op (loc, CO_AWAIT_EXPR, LOOKUP_NORMAL, a, NULL_TREE,
     701                 :            :                         NULL_TREE, &overload, tf_warning_or_error);
     702                 :            :       /* If no viable functions are found, o is a.  */
     703                 :       2232 :       if (!o || o == error_mark_node)
     704                 :       2129 :         o = a;
     705                 :            :     }
     706                 :            :   else
     707                 :            :     o = a; /* This is most likely about to fail anyway.  */
     708                 :            : 
     709                 :       2233 :   tree o_type = TREE_TYPE (o);
     710                 :       2233 :   if (o_type && !VOID_TYPE_P (o_type))
     711                 :       2232 :     o_type = complete_type_or_else (o_type, o);
     712                 :            : 
     713                 :       2233 :   if (!o_type)
     714                 :          0 :     return error_mark_node;
     715                 :            : 
     716                 :       2233 :   if (TREE_CODE (o_type) != RECORD_TYPE)
     717                 :            :     {
     718                 :          1 :       error_at (loc, "awaitable type %qT is not a structure",
     719                 :            :                 o_type);
     720                 :          1 :       return error_mark_node;
     721                 :            :     }
     722                 :            : 
     723                 :            :   /* Check for required awaitable members and their types.  */
     724                 :       2232 :   tree awrd_meth
     725                 :       2232 :     = lookup_awaitable_member (o_type, coro_await_ready_identifier, loc);
     726                 :       2232 :   if (!awrd_meth || awrd_meth == error_mark_node)
     727                 :          1 :     return error_mark_node;
     728                 :       2231 :   tree awsp_meth
     729                 :       2231 :     = lookup_awaitable_member (o_type, coro_await_suspend_identifier, loc);
     730                 :       2231 :   if (!awsp_meth || awsp_meth == error_mark_node)
     731                 :          2 :     return error_mark_node;
     732                 :            : 
     733                 :            :   /* The type of the co_await is the return type of the awaitable's
     734                 :            :      await_resume, so we need to look that up.  */
     735                 :       2229 :   tree awrs_meth
     736                 :       2229 :     = lookup_awaitable_member (o_type, coro_await_resume_identifier, loc);
     737                 :       2229 :   if (!awrs_meth || awrs_meth == error_mark_node)
     738                 :          1 :     return error_mark_node;
     739                 :            : 
     740                 :            :   /* To complete the lookups, we need an instance of 'e' which is built from
     741                 :            :      'o' according to [expr.await] 3.4.  However, we don't want to materialize
     742                 :            :      'e' here (it might need to be placed in the coroutine frame) so we will
     743                 :            :      make a temp placeholder instead.  If 'o' is a parameter or a local var,
     744                 :            :      then we do not need an additional var (parms and local vars are already
     745                 :            :      copied into the frame and will have lifetimes according to their original
     746                 :            :      scope).  */
     747                 :       2228 :   tree e_proxy = STRIP_NOPS (o);
     748                 :       2228 :   if (INDIRECT_REF_P (e_proxy))
     749                 :         27 :     e_proxy = TREE_OPERAND (e_proxy, 0);
     750                 :       2228 :   if (TREE_CODE (e_proxy) == PARM_DECL
     751                 :       2264 :       || (TREE_CODE (e_proxy) == VAR_DECL && !DECL_ARTIFICIAL (e_proxy)))
     752                 :            :     e_proxy = o;
     753                 :            :   else
     754                 :            :     {
     755                 :       2165 :       e_proxy = build_lang_decl (VAR_DECL, NULL_TREE, o_type);
     756                 :       2165 :       DECL_ARTIFICIAL (e_proxy) = true;
     757                 :            :     }
     758                 :            : 
     759                 :            :   /* I suppose we could check that this is contextually convertible to bool.  */
     760                 :       2228 :   tree awrd_func = NULL_TREE;
     761                 :       2228 :   tree awrd_call
     762                 :       2228 :     = build_new_method_call (e_proxy, awrd_meth, NULL, NULL_TREE, LOOKUP_NORMAL,
     763                 :            :                              &awrd_func, tf_warning_or_error);
     764                 :            : 
     765                 :       2228 :   if (!awrd_func || !awrd_call || awrd_call == error_mark_node)
     766                 :          0 :     return error_mark_node;
     767                 :            : 
     768                 :            :   /* The suspend method may return one of three types:
     769                 :            :       1. void (no special action needed).
     770                 :            :       2. bool (if true, we don't need to suspend).
     771                 :            :       3. a coroutine handle, we execute the handle.resume() call.  */
     772                 :       2228 :   tree awsp_func = NULL_TREE;
     773                 :       2228 :   tree h_proxy = get_coroutine_self_handle_proxy (current_function_decl);
     774                 :       2228 :   vec<tree, va_gc> *args = make_tree_vector_single (h_proxy);
     775                 :       2228 :   tree awsp_call
     776                 :       2228 :     = build_new_method_call (e_proxy, awsp_meth, &args, NULL_TREE,
     777                 :            :                              LOOKUP_NORMAL, &awsp_func, tf_warning_or_error);
     778                 :            : 
     779                 :       2228 :   release_tree_vector (args);
     780                 :       2228 :   if (!awsp_func || !awsp_call || awsp_call == error_mark_node)
     781                 :          0 :     return error_mark_node;
     782                 :            : 
     783                 :       2228 :   bool ok = false;
     784                 :       2228 :   tree susp_return_type = TREE_TYPE (TREE_TYPE (awsp_func));
     785                 :       2228 :   if (same_type_p (susp_return_type, void_type_node))
     786                 :            :     ok = true;
     787                 :         26 :   else if (same_type_p (susp_return_type, boolean_type_node))
     788                 :            :     ok = true;
     789                 :          9 :   else if (TREE_CODE (susp_return_type) == RECORD_TYPE
     790                 :         18 :            && CLASS_TYPE_P (susp_return_type))
     791                 :            :     {
     792                 :          9 :       tree tt = CLASSTYPE_TI_TEMPLATE (susp_return_type);
     793                 :          9 :       if (tt == coro_handle_templ)
     794                 :            :         ok = true;
     795                 :            :     }
     796                 :            : 
     797                 :            :   if (!ok)
     798                 :            :     {
     799                 :          0 :       error_at (loc, "%<await_suspend%> must return %<void%>, %<bool%> or"
     800                 :            :                      " a coroutine handle");
     801                 :          0 :       return error_mark_node;
     802                 :            :     }
     803                 :            : 
     804                 :            :   /* Finally, the type of e.await_resume() is the co_await's type.  */
     805                 :       2228 :   tree awrs_func = NULL_TREE;
     806                 :       2228 :   tree awrs_call
     807                 :       2228 :     = build_new_method_call (e_proxy, awrs_meth, NULL, NULL_TREE, LOOKUP_NORMAL,
     808                 :            :                              &awrs_func, tf_warning_or_error);
     809                 :            : 
     810                 :       2228 :   if (!awrs_func || !awrs_call || awrs_call == error_mark_node)
     811                 :          0 :     return error_mark_node;
     812                 :            : 
     813                 :            :   /* We now have three call expressions, in terms of the promise, handle and
     814                 :            :      'e' proxies.  Save them in the await expression for later expansion.  */
     815                 :            : 
     816                 :       2228 :   tree awaiter_calls = make_tree_vec (3);
     817                 :       2228 :   TREE_VEC_ELT (awaiter_calls, 0) = awrd_call; /* await_ready().  */
     818                 :       2228 :   TREE_VEC_ELT (awaiter_calls, 1) = awsp_call; /* await_suspend().  */
     819                 :       2228 :   TREE_VEC_ELT (awaiter_calls, 2) = awrs_call; /* await_resume().  */
     820                 :            : 
     821                 :       6684 :   tree await_expr = build5_loc (loc, CO_AWAIT_EXPR,
     822                 :       2228 :                                 TREE_TYPE (TREE_TYPE (awrs_func)),
     823                 :            :                                 a, e_proxy, o, awaiter_calls,
     824                 :            :                                 build_int_cst (integer_type_node,
     825                 :       2228 :                                                (int) suspend_kind));
     826                 :       2228 :   return convert_from_reference (await_expr);
     827                 :            : }
     828                 :            : 
     829                 :            : tree
     830                 :        550 : finish_co_await_expr (location_t kw, tree expr)
     831                 :            : {
     832                 :       1100 :   if (!expr || error_operand_p (expr))
     833                 :          0 :     return error_mark_node;
     834                 :            : 
     835                 :        550 :   if (!coro_common_keyword_context_valid_p (current_function_decl, kw,
     836                 :            :                                             "co_await"))
     837                 :          9 :     return error_mark_node;
     838                 :            : 
     839                 :            :   /* The current function has now become a coroutine, if it wasn't already.  */
     840                 :        541 :   DECL_COROUTINE_P (current_function_decl) = 1;
     841                 :            : 
     842                 :        541 :   if (processing_template_decl)
     843                 :            :     {
     844                 :         90 :       current_function_returns_value = 1;
     845                 :            : 
     846                 :         90 :       if (check_for_bare_parameter_packs (expr))
     847                 :          0 :         return error_mark_node;
     848                 :            : 
     849                 :            :       /* If we don't know the promise type, we can't proceed.  */
     850                 :         90 :       tree functype = TREE_TYPE (current_function_decl);
     851                 :         90 :       if (dependent_type_p (functype) || type_dependent_expression_p (expr))
     852                 :         90 :         return build5_loc (kw, CO_AWAIT_EXPR, unknown_type_node, expr,
     853                 :            :                            NULL_TREE, NULL_TREE, NULL_TREE, integer_zero_node);
     854                 :            :     }
     855                 :            : 
     856                 :            :   /* We must be able to look up the "await_transform" method in the scope of
     857                 :            :      the promise type, and obtain its return type.  */
     858                 :        451 :   if (!coro_promise_type_found_p (current_function_decl, kw))
     859                 :          0 :     return error_mark_node;
     860                 :            : 
     861                 :            :   /* [expr.await] 3.2
     862                 :            :      The incoming cast expression might be transformed by a promise
     863                 :            :      'await_transform()'.  */
     864                 :        451 :   tree at_meth
     865                 :        451 :     = lookup_promise_method (current_function_decl,
     866                 :            :                              coro_await_transform_identifier, kw,
     867                 :            :                              /*musthave=*/false);
     868                 :        451 :   if (at_meth == error_mark_node)
     869                 :            :     return error_mark_node;
     870                 :            : 
     871                 :        451 :   tree a = expr;
     872                 :        451 :   if (at_meth)
     873                 :            :     {
     874                 :            :       /* try to build a = p.await_transform (e). */
     875                 :        196 :       tree at_fn = NULL_TREE;
     876                 :        196 :       vec<tree, va_gc> *args = make_tree_vector_single (expr);
     877                 :        392 :       a = build_new_method_call (get_coroutine_promise_proxy (
     878                 :            :                                    current_function_decl),
     879                 :            :                                  at_meth, &args, NULL_TREE, LOOKUP_NORMAL,
     880                 :            :                                  &at_fn, tf_warning_or_error);
     881                 :            : 
     882                 :            :       /* As I read the section.
     883                 :            :          We saw an await_transform method, so it's mandatory that we replace
     884                 :            :          expr with p.await_transform (expr), therefore if the method call fails
     885                 :            :          (presumably, we don't have suitable arguments) then this part of the
     886                 :            :          process fails.  */
     887                 :        196 :       if (!at_fn || a == error_mark_node)
     888                 :          0 :         return error_mark_node;
     889                 :            :     }
     890                 :            : 
     891                 :            :   /* Now we want to build co_await a.  */
     892                 :        451 :   tree op = build_co_await (kw, a, CO_AWAIT_SUSPEND_POINT);
     893                 :        451 :   if (op != error_mark_node)
     894                 :            :     {
     895                 :        449 :       TREE_SIDE_EFFECTS (op) = 1;
     896                 :        449 :       SET_EXPR_LOCATION (op, kw);
     897                 :            :     }
     898                 :            : 
     899                 :            :   return op;
     900                 :            : }
     901                 :            : 
     902                 :            : /* Take the EXPR given and attempt to build:
     903                 :            :      co_await p.yield_value (expr);
     904                 :            :    per [expr.yield] para 1. */
     905                 :            : 
     906                 :            : tree
     907                 :        273 : finish_co_yield_expr (location_t kw, tree expr)
     908                 :            : {
     909                 :        546 :   if (!expr || error_operand_p (expr))
     910                 :          0 :     return error_mark_node;
     911                 :            : 
     912                 :            :   /* Check the general requirements and simple syntax errors.  */
     913                 :        273 :   if (!coro_common_keyword_context_valid_p (current_function_decl, kw,
     914                 :            :                                             "co_yield"))
     915                 :          9 :     return error_mark_node;
     916                 :            : 
     917                 :            :   /* The current function has now become a coroutine, if it wasn't already.  */
     918                 :        264 :   DECL_COROUTINE_P (current_function_decl) = 1;
     919                 :            : 
     920                 :        264 :   if (processing_template_decl)
     921                 :            :     {
     922                 :         42 :       current_function_returns_value = 1;
     923                 :            : 
     924                 :         42 :       if (check_for_bare_parameter_packs (expr))
     925                 :          0 :         return error_mark_node;
     926                 :            : 
     927                 :         42 :       tree functype = TREE_TYPE (current_function_decl);
     928                 :            :       /* If we don't know the promise type, we can't proceed.  */
     929                 :         42 :       if (dependent_type_p (functype) || type_dependent_expression_p (expr))
     930                 :         42 :         return build2_loc (kw, CO_YIELD_EXPR, unknown_type_node, expr,
     931                 :            :                            NULL_TREE);
     932                 :            :     }
     933                 :            : 
     934                 :        222 :   if (!coro_promise_type_found_p (current_function_decl, kw))
     935                 :            :     /* We must be able to look up the "yield_value" method in the scope of
     936                 :            :        the promise type, and obtain its return type.  */
     937                 :          6 :     return error_mark_node;
     938                 :            : 
     939                 :            :   /* The incoming expr is "e" per [expr.yield] para 1, lookup and build a
     940                 :            :      call for p.yield_value(e).  */
     941                 :        216 :   tree y_meth = lookup_promise_method (current_function_decl,
     942                 :            :                                        coro_yield_value_identifier, kw,
     943                 :            :                                        /*musthave=*/true);
     944                 :        216 :   if (!y_meth || y_meth == error_mark_node)
     945                 :          1 :     return error_mark_node;
     946                 :            : 
     947                 :        215 :   tree yield_fn = NULL_TREE;
     948                 :        215 :   vec<tree, va_gc> *args = make_tree_vector_single (expr);
     949                 :        430 :   tree yield_call = build_new_method_call (
     950                 :            :     get_coroutine_promise_proxy (current_function_decl), y_meth, &args,
     951                 :            :     NULL_TREE, LOOKUP_NORMAL, &yield_fn, tf_warning_or_error);
     952                 :            : 
     953                 :        215 :   if (!yield_fn || yield_call == error_mark_node)
     954                 :          0 :     return error_mark_node;
     955                 :            : 
     956                 :            :   /* So now we have the type of p.yield_value (e).
     957                 :            :      Now we want to build co_await p.yield_value (e).
     958                 :            :      Noting that for co_yield, there is no evaluation of any potential
     959                 :            :      promise transform_await().  */
     960                 :            : 
     961                 :        215 :   tree op = build_co_await (kw, yield_call, CO_YIELD_SUSPEND_POINT);
     962                 :        215 :   if (op != error_mark_node)
     963                 :            :     {
     964                 :        213 :       op = build2_loc (kw, CO_YIELD_EXPR, TREE_TYPE (op), expr, op);
     965                 :        213 :       TREE_SIDE_EFFECTS (op) = 1;
     966                 :            :     }
     967                 :            : 
     968                 :            :   return op;
     969                 :            : }
     970                 :            : 
     971                 :            : /* Check that it's valid to have a co_return keyword here.
     972                 :            :    If it is, then check and build the p.return_{void(),value(expr)}.
     973                 :            :    These are built against the promise proxy, but saved for expand time.  */
     974                 :            : 
     975                 :            : tree
     976                 :       1079 : finish_co_return_stmt (location_t kw, tree expr)
     977                 :            : {
     978                 :       1079 :   if (expr == error_mark_node)
     979                 :            :     return error_mark_node;
     980                 :            : 
     981                 :       1079 :   if (!coro_common_keyword_context_valid_p (current_function_decl, kw,
     982                 :            :                                             "co_return"))
     983                 :          7 :     return error_mark_node;
     984                 :            : 
     985                 :            :   /* The current function has now become a coroutine, if it wasn't
     986                 :            :      already.  */
     987                 :       1072 :   DECL_COROUTINE_P (current_function_decl) = 1;
     988                 :            : 
     989                 :       1072 :   if (processing_template_decl)
     990                 :            :     {
     991                 :        148 :       current_function_returns_value = 1;
     992                 :            : 
     993                 :        148 :       if (check_for_bare_parameter_packs (expr))
     994                 :          0 :         return error_mark_node;
     995                 :            : 
     996                 :        148 :       tree functype = TREE_TYPE (current_function_decl);
     997                 :            :       /* If we don't know the promise type, we can't proceed, return the
     998                 :            :          expression as it is.  */
     999                 :        148 :       if (dependent_type_p (functype) || type_dependent_expression_p (expr))
    1000                 :            :         {
    1001                 :        148 :           expr
    1002                 :        148 :             = build2_loc (kw, CO_RETURN_EXPR, void_type_node, expr, NULL_TREE);
    1003                 :        148 :           expr = maybe_cleanup_point_expr_void (expr);
    1004                 :        148 :           expr = add_stmt (expr);
    1005                 :        148 :           return expr;
    1006                 :            :         }
    1007                 :            :     }
    1008                 :            : 
    1009                 :        924 :   if (!coro_promise_type_found_p (current_function_decl, kw))
    1010                 :          6 :     return error_mark_node;
    1011                 :            : 
    1012                 :       1731 :   if (error_operand_p (expr))
    1013                 :            :     return error_mark_node;
    1014                 :            : 
    1015                 :            :   /* Suppress -Wreturn-type for co_return, we need to check indirectly
    1016                 :            :      whether the promise type has a suitable return_void/return_value.  */
    1017                 :        918 :   TREE_NO_WARNING (current_function_decl) = true;
    1018                 :            : 
    1019                 :        918 :   if (!processing_template_decl && warn_sequence_point)
    1020                 :          0 :     verify_sequence_points (expr);
    1021                 :            : 
    1022                 :            :   /* If the promise object doesn't have the correct return call then
    1023                 :            :      there's a mis-match between the co_return <expr> and this.  */
    1024                 :        918 :   tree co_ret_call = NULL_TREE;
    1025                 :       1731 :   if (expr == NULL_TREE || VOID_TYPE_P (TREE_TYPE (expr)))
    1026                 :            :     {
    1027                 :        114 :       tree crv_meth
    1028                 :        114 :         = lookup_promise_method (current_function_decl,
    1029                 :            :                                  coro_return_void_identifier, kw,
    1030                 :            :                                  /*musthave=*/true);
    1031                 :        114 :       if (!crv_meth || crv_meth == error_mark_node)
    1032                 :          1 :         return error_mark_node;
    1033                 :            : 
    1034                 :        226 :       co_ret_call = build_new_method_call (
    1035                 :            :         get_coroutine_promise_proxy (current_function_decl), crv_meth, NULL,
    1036                 :            :         NULL_TREE, LOOKUP_NORMAL, NULL, tf_warning_or_error);
    1037                 :            :     }
    1038                 :            :   else
    1039                 :            :     {
    1040                 :        804 :       tree crv_meth
    1041                 :        804 :         = lookup_promise_method (current_function_decl,
    1042                 :            :                                  coro_return_value_identifier, kw,
    1043                 :            :                                  /*musthave=*/true);
    1044                 :        804 :       if (!crv_meth || crv_meth == error_mark_node)
    1045                 :          1 :         return error_mark_node;
    1046                 :            : 
    1047                 :        803 :       vec<tree, va_gc> *args = make_tree_vector_single (expr);
    1048                 :       1606 :       co_ret_call = build_new_method_call (
    1049                 :            :         get_coroutine_promise_proxy (current_function_decl), crv_meth, &args,
    1050                 :            :         NULL_TREE, LOOKUP_NORMAL, NULL, tf_warning_or_error);
    1051                 :            :     }
    1052                 :            : 
    1053                 :            :   /* Makes no sense for a co-routine really. */
    1054                 :        916 :   if (TREE_THIS_VOLATILE (current_function_decl))
    1055                 :          0 :     warning_at (kw, 0,
    1056                 :            :                 "function declared %<noreturn%> has a"
    1057                 :            :                 " %<co_return%> statement");
    1058                 :            : 
    1059                 :        916 :   if (!co_ret_call || co_ret_call == error_mark_node)
    1060                 :          0 :     return error_mark_node;
    1061                 :            : 
    1062                 :        916 :   expr = build2_loc (kw, CO_RETURN_EXPR, void_type_node, expr, co_ret_call);
    1063                 :        916 :   expr = maybe_cleanup_point_expr_void (expr);
    1064                 :        916 :   expr = add_stmt (expr);
    1065                 :        916 :   return expr;
    1066                 :            : }
    1067                 :            : 
    1068                 :            : /* We need to validate the arguments to __builtin_coro_promise, since the
    1069                 :            :    second two must be constant, and the builtins machinery doesn't seem to
    1070                 :            :    deal with that properly.  */
    1071                 :            : 
    1072                 :            : tree
    1073                 :      16766 : coro_validate_builtin_call (tree call, tsubst_flags_t)
    1074                 :            : {
    1075                 :      16766 :   tree fn = TREE_OPERAND (CALL_EXPR_FN (call), 0);
    1076                 :            : 
    1077                 :      16766 :   gcc_checking_assert (DECL_BUILT_IN_CLASS (fn) == BUILT_IN_NORMAL);
    1078                 :      16766 :   switch (DECL_FUNCTION_CODE (fn))
    1079                 :            :     {
    1080                 :            :     default:
    1081                 :            :       return call;
    1082                 :            : 
    1083                 :       3781 :     case BUILT_IN_CORO_PROMISE:
    1084                 :       3781 :       {
    1085                 :            :         /* Argument 0 is already checked by the normal built-in machinery
    1086                 :            :            Argument 1 must be a constant of size type.  It probably makes
    1087                 :            :            little sense if it's not a power of 2, but that isn't specified
    1088                 :            :            formally.  */
    1089                 :       3781 :         tree arg = CALL_EXPR_ARG (call, 1);
    1090                 :       3781 :         location_t loc = EXPR_LOCATION (arg);
    1091                 :            : 
    1092                 :            :         /* We expect alignof expressions in templates.  */
    1093                 :       3781 :         if (TREE_CODE (arg) == NON_DEPENDENT_EXPR
    1094                 :       3781 :             && TREE_CODE (TREE_OPERAND (arg, 0)) == ALIGNOF_EXPR)
    1095                 :            :           ;
    1096                 :       2189 :         else if (!TREE_CONSTANT (arg))
    1097                 :            :           {
    1098                 :          0 :             error_at (loc, "the align argument to %<__builtin_coro_promise%>"
    1099                 :            :                            " must be a constant");
    1100                 :          0 :             return error_mark_node;
    1101                 :            :           }
    1102                 :            :         /* Argument 2 is the direction - to / from handle address to promise
    1103                 :            :            address.  */
    1104                 :       3781 :         arg = CALL_EXPR_ARG (call, 2);
    1105                 :       3781 :         loc = EXPR_LOCATION (arg);
    1106                 :       3781 :         if (!TREE_CONSTANT (arg))
    1107                 :            :           {
    1108                 :          0 :             error_at (loc, "the direction argument to"
    1109                 :            :                            " %<__builtin_coro_promise%> must be a constant");
    1110                 :          0 :             return error_mark_node;
    1111                 :            :           }
    1112                 :            :         return call;
    1113                 :            :         break;
    1114                 :            :       }
    1115                 :            :     }
    1116                 :            : }
    1117                 :            : 
    1118                 :            : /* ================= Morph and Expand. =================
    1119                 :            : 
    1120                 :            :    The entry point here is morph_fn_to_coro () which is called from
    1121                 :            :    finish_function () when we have completed any template expansion.
    1122                 :            : 
    1123                 :            :    This is preceded by helper functions that implement the phases below.
    1124                 :            : 
    1125                 :            :    The process proceeds in four phases.
    1126                 :            : 
    1127                 :            :    A Initial framing.
    1128                 :            :      The user's function body is wrapped in the initial and final suspend
    1129                 :            :      points and we begin building the coroutine frame.
    1130                 :            :      We build empty decls for the actor and destroyer functions at this
    1131                 :            :      time too.
    1132                 :            :      When exceptions are enabled, the user's function body will also be
    1133                 :            :      wrapped in a try-catch block with the catch invoking the promise
    1134                 :            :      class 'unhandled_exception' method.
    1135                 :            : 
    1136                 :            :    B Analysis.
    1137                 :            :      The user's function body is analyzed to determine the suspend points,
    1138                 :            :      if any, and to capture local variables that might persist across such
    1139                 :            :      suspensions.  In most cases, it is not necessary to capture compiler
    1140                 :            :      temporaries, since the tree-lowering nests the suspensions correctly.
    1141                 :            :      However, in the case of a captured reference, there is a lifetime
    1142                 :            :      extension to the end of the full expression - which can mean across a
    1143                 :            :      suspend point in which case it must be promoted to a frame variable.
    1144                 :            : 
    1145                 :            :      At the conclusion of analysis, we have a conservative frame layout and
    1146                 :            :      maps of the local variables to their frame entry points.
    1147                 :            : 
    1148                 :            :    C Build the ramp function.
    1149                 :            :      Carry out the allocation for the coroutine frame (NOTE; the actual size
    1150                 :            :      computation is deferred until late in the middle end to allow for future
    1151                 :            :      optimizations that will be allowed to elide unused frame entries).
    1152                 :            :      We build the return object.
    1153                 :            : 
    1154                 :            :    D Build and expand the actor and destroyer function bodies.
    1155                 :            :      The destroyer is a trivial shim that sets a bit to indicate that the
    1156                 :            :      destroy dispatcher should be used and then calls into the actor.
    1157                 :            : 
    1158                 :            :      The actor function is the implementation of the user's state machine.
    1159                 :            :      The current suspend point is noted in an index.
    1160                 :            :      Each suspend point is encoded as a pair of internal functions, one in
    1161                 :            :      the relevant dispatcher, and one representing the suspend point.
    1162                 :            : 
    1163                 :            :      During this process, the user's local variables and the proxies for the
    1164                 :            :      self-handle and the promise class instance are re-written to their
    1165                 :            :      coroutine frame equivalents.
    1166                 :            : 
    1167                 :            :      The complete bodies for the ramp, actor and destroy function are passed
    1168                 :            :      back to finish_function for folding and gimplification.  */
    1169                 :            : 
    1170                 :            : /* Helpers to build EXPR_STMT and void-cast EXPR_STMT, common ops.  */
    1171                 :            : 
    1172                 :            : static tree
    1173                 :      29547 : coro_build_expr_stmt (tree expr, location_t loc)
    1174                 :            : {
    1175                 :      29547 :   return maybe_cleanup_point_expr_void (build_stmt (loc, EXPR_STMT, expr));
    1176                 :            : }
    1177                 :            : 
    1178                 :            : static tree
    1179                 :      27983 : coro_build_cvt_void_expr_stmt (tree expr, location_t loc)
    1180                 :            : {
    1181                 :      27983 :   tree t = build1 (CONVERT_EXPR, void_type_node, expr);
    1182                 :      27983 :   return coro_build_expr_stmt (t, loc);
    1183                 :            : }
    1184                 :            : 
    1185                 :            : /* Helpers for label creation:
    1186                 :            :    1. Create a named label in the specified context.  */
    1187                 :            : 
    1188                 :            : static tree
    1189                 :      12694 : create_anon_label_with_ctx (location_t loc, tree ctx)
    1190                 :            : {
    1191                 :      12694 :   tree lab = build_decl (loc, LABEL_DECL, NULL_TREE, void_type_node);
    1192                 :            : 
    1193                 :      12694 :   DECL_CONTEXT (lab) = ctx;
    1194                 :      12694 :   DECL_ARTIFICIAL (lab) = true;
    1195                 :      12694 :   DECL_IGNORED_P (lab) = true;
    1196                 :      12694 :   TREE_USED (lab) = true;
    1197                 :      12694 :   return lab;
    1198                 :            : }
    1199                 :            : 
    1200                 :            : /*  2. Create a named label in the specified context.  */
    1201                 :            : 
    1202                 :            : static tree
    1203                 :       9161 : create_named_label_with_ctx (location_t loc, const char *name, tree ctx)
    1204                 :            : {
    1205                 :       9161 :   tree lab_id = get_identifier (name);
    1206                 :       9161 :   tree lab = define_label (loc, lab_id);
    1207                 :       9161 :   DECL_CONTEXT (lab) = ctx;
    1208                 :       9161 :   DECL_ARTIFICIAL (lab) = true;
    1209                 :       9161 :   TREE_USED (lab) = true;
    1210                 :       9161 :   return lab;
    1211                 :            : }
    1212                 :            : 
    1213                 :            : struct proxy_replace
    1214                 :            : {
    1215                 :            :   tree from, to;
    1216                 :            : };
    1217                 :            : 
    1218                 :            : static tree
    1219                 :     842236 : replace_proxy (tree *here, int *do_subtree, void *d)
    1220                 :            : {
    1221                 :     842236 :   proxy_replace *data = (proxy_replace *) d;
    1222                 :            : 
    1223                 :     842236 :   if (*here == data->from)
    1224                 :            :     {
    1225                 :      16911 :       *here = data->to;
    1226                 :      16911 :       *do_subtree = 0;
    1227                 :            :     }
    1228                 :            :   else
    1229                 :     825325 :     *do_subtree = 1;
    1230                 :     842236 :   return NULL_TREE;
    1231                 :            : }
    1232                 :            : 
    1233                 :            : /* Support for expansion of co_return statements.  */
    1234                 :            : 
    1235                 :            : struct coro_ret_data
    1236                 :            : {
    1237                 :            :   tree promise_proxy;
    1238                 :            :   tree real_promise;
    1239                 :            :   tree fs_label;
    1240                 :            : };
    1241                 :            : 
    1242                 :            : /* If this is a coreturn statement (or one wrapped in a cleanup) then
    1243                 :            :    return the list of statements to replace it.  */
    1244                 :            : 
    1245                 :            : static tree
    1246                 :     109853 : coro_maybe_expand_co_return (tree co_ret_expr, coro_ret_data *data)
    1247                 :            : {
    1248                 :            :   /* Look inside <(void) (expr)> cleanup */
    1249                 :     109853 :   if (TREE_CODE (co_ret_expr) == CLEANUP_POINT_EXPR)
    1250                 :       6638 :     co_ret_expr = TREE_OPERAND (co_ret_expr, 0);
    1251                 :            : 
    1252                 :     109853 :   if (TREE_CODE (co_ret_expr) != CO_RETURN_EXPR)
    1253                 :            :     return NULL_TREE;
    1254                 :            : 
    1255                 :        913 :   location_t loc = EXPR_LOCATION (co_ret_expr);
    1256                 :        913 :   tree expr = TREE_OPERAND (co_ret_expr, 0);
    1257                 :        913 :   tree call = TREE_OPERAND (co_ret_expr, 1);
    1258                 :        913 :   tree stmt_list = NULL;
    1259                 :       1724 :   if (expr && VOID_TYPE_P (TREE_TYPE (expr)))
    1260                 :            :     {
    1261                 :            :        /* [stmt.return.coroutine], 2.2 
    1262                 :            :           If expr is present and void, it is placed immediately before
    1263                 :            :           the call for return_void;  */
    1264                 :          9 :       expr = maybe_cleanup_point_expr_void (expr);
    1265                 :          9 :       append_to_statement_list (expr, &stmt_list);
    1266                 :            :     }
    1267                 :            : 
    1268                 :            :   /* Now replace the promise proxy with its real value.  */
    1269                 :        913 :   proxy_replace p_data;
    1270                 :        913 :   p_data.from = data->promise_proxy;
    1271                 :        913 :   p_data.to = data->real_promise;
    1272                 :        913 :   cp_walk_tree (&call, replace_proxy, &p_data, NULL);
    1273                 :            : 
    1274                 :            :   /* The types of p.return_void and p.return_value are not explicitly stated
    1275                 :            :      at least in n4835, it is expected that they will return void.  */
    1276                 :        913 :   call = maybe_cleanup_point_expr_void (call);
    1277                 :        913 :   append_to_statement_list (call, &stmt_list);
    1278                 :        913 :   tree r = build1_loc (loc, GOTO_EXPR, void_type_node, data->fs_label);
    1279                 :        913 :   append_to_statement_list (r, &stmt_list);
    1280                 :        913 :   return stmt_list;
    1281                 :            : }
    1282                 :            : 
    1283                 :            : /* Callback that rewrites co_return as per [stmt.return.coroutine]
    1284                 :            :    - for co_return;
    1285                 :            :    { p.return_void (); goto final_suspend; }
    1286                 :            :    - for co_return [void expr];
    1287                 :            :    { expr; p.return_void(); goto final_suspend;}
    1288                 :            :    - for co_return [non void expr];
    1289                 :            :    { p.return_value(expr); goto final_suspend; }  */
    1290                 :            : 
    1291                 :            : static tree
    1292                 :     106419 : co_return_expander (tree *stmt, int *do_subtree, void *d)
    1293                 :            : {
    1294                 :     106419 :   coro_ret_data *data = (coro_ret_data *) d;
    1295                 :            : 
    1296                 :            :   /* To avoid nesting statement lists, walk them and insert as needed.  */
    1297                 :     106419 :   if (TREE_CODE (*stmt) == STATEMENT_LIST)
    1298                 :            :     {
    1299                 :       1970 :       tree_stmt_iterator i;
    1300                 :       6720 :       for (i = tsi_start (*stmt); !tsi_end_p (i); tsi_next (&i))
    1301                 :            :         {
    1302                 :       5404 :           tree *new_stmt = tsi_stmt_ptr (i);
    1303                 :       5404 :           tree replace = coro_maybe_expand_co_return (*new_stmt, data);
    1304                 :            :           /* If we got something, it will be list and we want to splice
    1305                 :            :              it in.  */
    1306                 :       5404 :           if (replace != NULL_TREE)
    1307                 :            :             {
    1308                 :            :               /* Splice it in ... */
    1309                 :        757 :               tsi_link_before (&i, replace, TSI_SAME_STMT);
    1310                 :            :               /* ... and delete what we expanded.  */
    1311                 :        757 :               tsi_delink (&i);
    1312                 :            :               /* Maybe, even likely, we replaced the last in the list.  */
    1313                 :        757 :               if (tsi_end_p (i))
    1314                 :            :                 break;
    1315                 :            :             }
    1316                 :            :           else /* Continue the walk.  */
    1317                 :       4647 :             cp_walk_tree (new_stmt, co_return_expander, d, NULL);
    1318                 :            :         }
    1319                 :       1970 :       *do_subtree = 0; /* Done subtrees.  */
    1320                 :            :     }
    1321                 :            :   else
    1322                 :            :     {
    1323                 :            :       /* We might have a single co_return statement, in which case, we do
    1324                 :            :          have to replace it with a list.  */
    1325                 :     104449 :       tree replace = coro_maybe_expand_co_return (*stmt, data);
    1326                 :     104449 :       if (replace != NULL_TREE)
    1327                 :            :         {
    1328                 :        156 :           *stmt = replace;
    1329                 :        156 :           *do_subtree = 0; /* Done here.  */
    1330                 :            :         }
    1331                 :            :     }
    1332                 :     106419 :   return NULL_TREE;
    1333                 :            : }
    1334                 :            : 
    1335                 :            : /* Walk the original function body, rewriting co_returns.  */
    1336                 :            : 
    1337                 :            : static tree
    1338                 :        782 : expand_co_returns (tree *fnbody, tree promise_proxy, tree promise,
    1339                 :            :                    tree fs_label)
    1340                 :            : {
    1341                 :        782 :   coro_ret_data data = {promise_proxy, promise, fs_label};
    1342                 :          0 :   cp_walk_tree (fnbody, co_return_expander, &data, NULL);
    1343                 :        782 :   return *fnbody;
    1344                 :            : }
    1345                 :            : 
    1346                 :            : /* Support for expansion of co_await statements.  */
    1347                 :            : 
    1348                 :            : struct coro_aw_data
    1349                 :            : {
    1350                 :            :   tree actor_fn;   /* Decl for context.  */
    1351                 :            :   tree coro_fp;    /* Frame pointer var.  */
    1352                 :            :   tree resume_idx; /* This is the index var in the frame.  */
    1353                 :            :   tree i_a_r_c;    /* initial suspend await_resume() was called if true.  */
    1354                 :            :   tree self_h;     /* This is a handle to the current coro (frame var).  */
    1355                 :            :   tree cleanup;    /* This is where to go once we complete local destroy.  */
    1356                 :            :   tree cororet;    /* This is where to go if we suspend.  */
    1357                 :            :   tree corocont;   /* This is where to go if we continue.  */
    1358                 :            :   tree conthand;   /* This is the handle for a continuation.  */
    1359                 :            :   unsigned index;  /* This is our current resume index.  */
    1360                 :            : };
    1361                 :            : 
    1362                 :            : static tree
    1363                 :     476768 : co_await_find_in_subtree (tree *stmt, int *do_subtree ATTRIBUTE_UNUSED, void *d)
    1364                 :            : {
    1365                 :     476768 :   tree **p = (tree **) d;
    1366                 :     476768 :   if (TREE_CODE (*stmt) == CO_AWAIT_EXPR)
    1367                 :            :     {
    1368                 :        299 :       *p = stmt;
    1369                 :        299 :       return *stmt;
    1370                 :            :     }
    1371                 :            :   return NULL_TREE;
    1372                 :            : }
    1373                 :            : 
    1374                 :            : /* When we come here:
    1375                 :            :     the first operand is the [currently unused] handle for suspend.
    1376                 :            :     the second operand is the var to be copy-initialized
    1377                 :            :     the third operand is 'o' (the initializer for the second)
    1378                 :            :                               as defined in [await.expr] (3.3)
    1379                 :            :     the fourth operand is the mode as per the comment on build_co_await ().
    1380                 :            : 
    1381                 :            :    When we leave:
    1382                 :            :    the IFN_CO_YIELD carries the labels of the resume and destroy
    1383                 :            :    branch targets for this await.  */
    1384                 :            : 
    1385                 :            : static tree
    1386                 :     509437 : co_await_expander (tree *stmt, int * /*do_subtree*/, void *d)
    1387                 :            : {
    1388                 :     509437 :   if (STATEMENT_CLASS_P (*stmt) || !EXPR_P (*stmt))
    1389                 :            :     return NULL_TREE;
    1390                 :            : 
    1391                 :     243099 :   coro_aw_data *data = (coro_aw_data *) d;
    1392                 :            : 
    1393                 :     243099 :   enum tree_code stmt_code = TREE_CODE (*stmt);
    1394                 :     243099 :   tree stripped_stmt = *stmt;
    1395                 :            : 
    1396                 :            :   /* Look inside <(void) (expr)> cleanup */
    1397                 :     243099 :   if (stmt_code == CLEANUP_POINT_EXPR)
    1398                 :            :     {
    1399                 :      22724 :       stripped_stmt = TREE_OPERAND (*stmt, 0);
    1400                 :      22724 :       stmt_code = TREE_CODE (stripped_stmt);
    1401                 :      22724 :       if (stmt_code == EXPR_STMT
    1402                 :      16421 :           && (TREE_CODE (EXPR_STMT_EXPR (stripped_stmt)) == CONVERT_EXPR
    1403                 :       2673 :               || TREE_CODE (EXPR_STMT_EXPR (stripped_stmt)) == CAST_EXPR)
    1404                 :      36472 :           && VOID_TYPE_P (TREE_TYPE (EXPR_STMT_EXPR (stripped_stmt))))
    1405                 :            :         {
    1406                 :      13748 :           stripped_stmt = TREE_OPERAND (EXPR_STMT_EXPR (stripped_stmt), 0);
    1407                 :      13748 :           stmt_code = TREE_CODE (stripped_stmt);
    1408                 :            :         }
    1409                 :            :     }
    1410                 :            : 
    1411                 :     243099 :   tree *buried_stmt = NULL;
    1412                 :     243099 :   tree saved_co_await = NULL_TREE;
    1413                 :     243099 :   enum tree_code sub_code = NOP_EXPR;
    1414                 :            : 
    1415                 :     243099 :   if (stmt_code == EXPR_STMT
    1416                 :     243099 :       && TREE_CODE (EXPR_STMT_EXPR (stripped_stmt)) == CO_AWAIT_EXPR)
    1417                 :       1796 :     saved_co_await
    1418                 :       1796 :       = EXPR_STMT_EXPR (stripped_stmt); /* hopefully, a void exp.  */
    1419                 :     241303 :   else if (stmt_code == MODIFY_EXPR || stmt_code == INIT_EXPR)
    1420                 :            :     {
    1421                 :      19717 :       sub_code = TREE_CODE (TREE_OPERAND (stripped_stmt, 1));
    1422                 :      19717 :       if (sub_code == CO_AWAIT_EXPR)
    1423                 :        130 :         saved_co_await = TREE_OPERAND (stripped_stmt, 1); /* Get the RHS.  */
    1424                 :      39174 :       else if (tree r
    1425                 :      19587 :                = cp_walk_tree (&TREE_OPERAND (stripped_stmt, 1),
    1426                 :            :                                co_await_find_in_subtree, &buried_stmt, NULL))
    1427                 :            :         saved_co_await = r;
    1428                 :            :     }
    1429                 :     221586 :   else if (stmt_code == CALL_EXPR)
    1430                 :            :     {
    1431                 :      39218 :       if (tree r = cp_walk_tree (&stripped_stmt, co_await_find_in_subtree,
    1432                 :            :                                  &buried_stmt, NULL))
    1433                 :            :         saved_co_await = r;
    1434                 :            :     }
    1435                 :     182368 :   else if ((stmt_code == CONVERT_EXPR || stmt_code == NOP_EXPR)
    1436                 :     182368 :            && TREE_CODE (TREE_OPERAND (stripped_stmt, 0)) == CO_AWAIT_EXPR)
    1437                 :          1 :     saved_co_await = TREE_OPERAND (stripped_stmt, 0);
    1438                 :            : 
    1439                 :       2226 :   if (!saved_co_await)
    1440                 :     240873 :     return NULL_TREE;
    1441                 :            : 
    1442                 :            :   /* We want to splice in the await_resume() value in some cases.  */
    1443                 :       2226 :   tree saved_statement = *stmt;
    1444                 :            : 
    1445                 :       2226 :   tree actor = data->actor_fn;
    1446                 :       2226 :   location_t loc = EXPR_LOCATION (*stmt);
    1447                 :       2226 :   tree var = TREE_OPERAND (saved_co_await, 1);  /* frame slot. */
    1448                 :       2226 :   tree expr = TREE_OPERAND (saved_co_await, 2); /* initializer.  */
    1449                 :       2226 :   tree awaiter_calls = TREE_OPERAND (saved_co_await, 3);
    1450                 :            : 
    1451                 :       2226 :   tree source = TREE_OPERAND (saved_co_await, 4);
    1452                 :       2226 :   bool is_initial =
    1453                 :       2226 :     (source && TREE_INT_CST_LOW (source) == (int) INITIAL_SUSPEND_POINT);
    1454                 :       2226 :   bool is_final = (source
    1455                 :       2226 :                    && TREE_INT_CST_LOW (source) == (int) FINAL_SUSPEND_POINT);
    1456                 :       2226 :   bool needs_dtor = TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (var));
    1457                 :       2226 :   int resume_point = data->index;
    1458                 :       2226 :   size_t bufsize = sizeof ("destroy.") + 10;
    1459                 :       2226 :   char *buf = (char *) alloca (bufsize);
    1460                 :       2226 :   snprintf (buf, bufsize, "destroy.%d", resume_point);
    1461                 :       2226 :   tree destroy_label = create_named_label_with_ctx (loc, buf, actor);
    1462                 :       2226 :   snprintf (buf, bufsize, "resume.%d", resume_point);
    1463                 :       2226 :   tree resume_label = create_named_label_with_ctx (loc, buf, actor);
    1464                 :       2226 :   tree empty_list = build_empty_stmt (loc);
    1465                 :            : 
    1466                 :       2226 :   tree dtor = NULL_TREE;
    1467                 :       2226 :   tree await_type = TREE_TYPE (var);
    1468                 :       2226 :   if (needs_dtor)
    1469                 :       1841 :     dtor = build_special_member_call (var, complete_dtor_identifier, NULL,
    1470                 :            :                                       await_type, LOOKUP_NORMAL,
    1471                 :            :                                       tf_warning_or_error);
    1472                 :            : 
    1473                 :       2226 :   tree stmt_list = NULL;
    1474                 :       2226 :   tree t_expr = STRIP_NOPS (expr);
    1475                 :       2226 :   tree r;
    1476                 :       2226 :   if (t_expr == var)
    1477                 :            :     dtor = NULL_TREE;
    1478                 :            :   else
    1479                 :            :     {
    1480                 :            :       /* Initialize the var from the provided 'o' expression.  */
    1481                 :       2163 :       r = build2 (INIT_EXPR, await_type, var, expr);
    1482                 :       2163 :       r = coro_build_cvt_void_expr_stmt (r, loc);
    1483                 :       2163 :       append_to_statement_list (r, &stmt_list);
    1484                 :            :     }
    1485                 :            : 
    1486                 :            :   /* Use the await_ready() call to test if we need to suspend.  */
    1487                 :       2226 :   tree ready_cond = TREE_VEC_ELT (awaiter_calls, 0); /* await_ready().  */
    1488                 :       2226 :   ready_cond = build1_loc (loc, TRUTH_NOT_EXPR, boolean_type_node, ready_cond);
    1489                 :       2226 :   ready_cond
    1490                 :       2226 :     = build1_loc (loc, CLEANUP_POINT_EXPR, boolean_type_node, ready_cond);
    1491                 :            : 
    1492                 :       2226 :   tree body_list = NULL;
    1493                 :       2226 :   tree susp_idx = build_int_cst (short_unsigned_type_node, data->index);
    1494                 :       2226 :   r = build2_loc (loc, MODIFY_EXPR, short_unsigned_type_node, data->resume_idx,
    1495                 :            :                   susp_idx);
    1496                 :       2226 :   r = coro_build_cvt_void_expr_stmt (r, loc);
    1497                 :       2226 :   append_to_statement_list (r, &body_list);
    1498                 :            : 
    1499                 :            :   /* Find out what we have to do with the awaiter's suspend method.
    1500                 :            :      [expr.await]
    1501                 :            :      (5.1) If the result of await-ready is false, the coroutine is considered
    1502                 :            :            suspended. Then:
    1503                 :            :      (5.1.1) If the type of await-suspend is std::coroutine_handle<Z>,
    1504                 :            :              await-suspend.resume() is evaluated.
    1505                 :            :      (5.1.2) if the type of await-suspend is bool, await-suspend is evaluated,
    1506                 :            :              and the coroutine is resumed if the result is false.
    1507                 :            :      (5.1.3) Otherwise, await-suspend is evaluated.  */
    1508                 :            : 
    1509                 :       2226 :   tree suspend = TREE_VEC_ELT (awaiter_calls, 1); /* await_suspend().  */
    1510                 :       2226 :   tree susp_type = TREE_TYPE (suspend);
    1511                 :            : 
    1512                 :       2226 :   bool is_cont = false;
    1513                 :            :   /* NOTE: final suspend can't resume; the "resume" label in that case
    1514                 :            :      corresponds to implicit destruction.  */
    1515                 :       2226 :   if (VOID_TYPE_P (susp_type))
    1516                 :            :     {
    1517                 :            :       /* We just call await_suspend() and hit the yield.  */
    1518                 :       2200 :       suspend = coro_build_cvt_void_expr_stmt (suspend, loc);
    1519                 :       2200 :       append_to_statement_list (suspend, &body_list);
    1520                 :            :     }
    1521                 :         26 :   else if (TREE_CODE (susp_type) == BOOLEAN_TYPE)
    1522                 :            :     {
    1523                 :            :       /* Boolean return, continue if the call returns false.  */
    1524                 :         17 :       suspend = build1_loc (loc, TRUTH_NOT_EXPR, boolean_type_node, suspend);
    1525                 :         17 :       suspend
    1526                 :         17 :         = build1_loc (loc, CLEANUP_POINT_EXPR, boolean_type_node, suspend);
    1527                 :         17 :       tree go_on = build1_loc (loc, GOTO_EXPR, void_type_node, resume_label);
    1528                 :         17 :       r = build3_loc (loc, COND_EXPR, void_type_node, suspend, go_on,
    1529                 :            :                       empty_list);
    1530                 :         17 :       append_to_statement_list (r, &body_list);
    1531                 :            :     }
    1532                 :            :   else
    1533                 :            :     {
    1534                 :          9 :       r = build1_loc (loc, CONVERT_EXPR, void_coro_handle_type, suspend);
    1535                 :          9 :       r = build2_loc (loc, INIT_EXPR, void_coro_handle_type, data->conthand, r);
    1536                 :          9 :       r = build1 (CONVERT_EXPR, void_type_node, r);
    1537                 :          9 :       append_to_statement_list (r, &body_list);
    1538                 :          9 :       is_cont = true;
    1539                 :            :     }
    1540                 :            : 
    1541                 :       2226 :   tree d_l = build_address (destroy_label);
    1542                 :       2226 :   tree r_l = build_address (resume_label);
    1543                 :       2226 :   tree susp = build_address (data->cororet);
    1544                 :       2226 :   tree cont = build_address (data->corocont);
    1545                 :       3670 :   tree final_susp = build_int_cst (integer_type_node, is_final ? 1 : 0);
    1546                 :            : 
    1547                 :       2226 :   susp_idx = build_int_cst (integer_type_node, data->index);
    1548                 :            : 
    1549                 :       2226 :   tree sw = begin_switch_stmt ();
    1550                 :       2226 :   tree cond = build_decl (loc, VAR_DECL, NULL_TREE, integer_type_node);
    1551                 :       2226 :   DECL_ARTIFICIAL (cond) = 1;
    1552                 :       2226 :   DECL_IGNORED_P (cond) = 1;
    1553                 :       2226 :   layout_decl (cond, 0);
    1554                 :            : 
    1555                 :       2226 :   r = build_call_expr_internal_loc (loc, IFN_CO_YIELD, integer_type_node, 5,
    1556                 :            :                                     susp_idx, final_susp, r_l, d_l,
    1557                 :            :                                     data->coro_fp);
    1558                 :       2226 :   r = build2 (INIT_EXPR, integer_type_node, cond, r);
    1559                 :       2226 :   finish_switch_cond (r, sw);
    1560                 :       2226 :   r = build_case_label (build_int_cst (integer_type_node, 0), NULL_TREE,
    1561                 :            :                         create_anon_label_with_ctx (loc, actor));
    1562                 :       2226 :   add_stmt (r); /* case 0: */
    1563                 :            :   /* Implement the suspend, a scope exit without clean ups.  */
    1564                 :       4443 :   r = build_call_expr_internal_loc (loc, IFN_CO_SUSPN, void_type_node, 1,
    1565                 :            :                                     is_cont ? cont : susp);
    1566                 :       2226 :   r = coro_build_cvt_void_expr_stmt (r, loc);
    1567                 :       2226 :   add_stmt (r); /*   goto ret;  */
    1568                 :       2226 :   r = build_case_label (build_int_cst (integer_type_node, 1), NULL_TREE,
    1569                 :            :                         create_anon_label_with_ctx (loc, actor));
    1570                 :       2226 :   add_stmt (r); /* case 1:  */
    1571                 :       2226 :   r = build1_loc (loc, GOTO_EXPR, void_type_node, resume_label);
    1572                 :       2226 :   add_stmt (r); /*  goto resume;  */
    1573                 :       2226 :   r = build_case_label (NULL_TREE, NULL_TREE,
    1574                 :            :                         create_anon_label_with_ctx (loc, actor));
    1575                 :       2226 :   add_stmt (r); /* default:;  */
    1576                 :       2226 :   r = build1_loc (loc, GOTO_EXPR, void_type_node, destroy_label);
    1577                 :       2226 :   add_stmt (r); /* goto destroy;  */
    1578                 :            : 
    1579                 :            :   /* part of finish switch.  */
    1580                 :       2226 :   SWITCH_STMT_BODY (sw) = pop_stmt_list (SWITCH_STMT_BODY (sw));
    1581                 :       2226 :   pop_switch ();
    1582                 :       2226 :   tree scope = SWITCH_STMT_SCOPE (sw);
    1583                 :       2226 :   SWITCH_STMT_SCOPE (sw) = NULL;
    1584                 :       2226 :   r = do_poplevel (scope);
    1585                 :       2226 :   append_to_statement_list (r, &body_list);
    1586                 :            : 
    1587                 :       2226 :   destroy_label = build_stmt (loc, LABEL_EXPR, destroy_label);
    1588                 :       2226 :   append_to_statement_list (destroy_label, &body_list);
    1589                 :       2226 :   if (needs_dtor)
    1590                 :       1841 :     append_to_statement_list (dtor, &body_list);
    1591                 :       2226 :   r = build1_loc (loc, GOTO_EXPR, void_type_node, data->cleanup);
    1592                 :       2226 :   append_to_statement_list (r, &body_list);
    1593                 :            : 
    1594                 :       2226 :   r = build3_loc (loc, COND_EXPR, void_type_node, ready_cond, body_list,
    1595                 :            :                   empty_list);
    1596                 :            : 
    1597                 :       2226 :   append_to_statement_list (r, &stmt_list);
    1598                 :            : 
    1599                 :            :   /* Resume point.  */
    1600                 :       2226 :   resume_label = build_stmt (loc, LABEL_EXPR, resume_label);
    1601                 :       2226 :   append_to_statement_list (resume_label, &stmt_list);
    1602                 :            : 
    1603                 :       2226 :   if (is_initial)
    1604                 :            :     {
    1605                 :            :       /* Note that we are about to execute the await_resume() for the initial
    1606                 :            :          await expression.  */
    1607                 :        782 :       r = build2_loc (loc, MODIFY_EXPR, boolean_type_node, data->i_a_r_c,
    1608                 :            :                       boolean_true_node);
    1609                 :        782 :       r = coro_build_cvt_void_expr_stmt (r, loc);
    1610                 :        782 :       append_to_statement_list (r, &stmt_list);
    1611                 :            :     }
    1612                 :            : 
    1613                 :            :   /* This will produce the value (if one is provided) from the co_await
    1614                 :            :      expression.  */
    1615                 :       2226 :   tree resume_call = TREE_VEC_ELT (awaiter_calls, 2); /* await_resume().  */
    1616                 :       2226 :   if (REFERENCE_REF_P (resume_call))
    1617                 :            :     /* Sink to await_resume call_expr.  */
    1618                 :         26 :     resume_call = TREE_OPERAND (resume_call, 0);
    1619                 :       2226 :   switch (stmt_code)
    1620                 :            :     {
    1621                 :       1796 :     default: /* not likely to work .. but... */
    1622                 :       1796 :       append_to_statement_list (resume_call, &stmt_list);
    1623                 :       1796 :       break;
    1624                 :          1 :     case CONVERT_EXPR:
    1625                 :          1 :     case NOP_EXPR:
    1626                 :          1 :       TREE_OPERAND (stripped_stmt, 0) = resume_call;
    1627                 :          1 :       append_to_statement_list (saved_statement, &stmt_list);
    1628                 :          1 :       break;
    1629                 :        429 :     case INIT_EXPR:
    1630                 :        429 :     case MODIFY_EXPR:
    1631                 :        429 :     case CALL_EXPR:
    1632                 :            :       /* Replace the use of co_await by the resume expr.  */
    1633                 :        429 :       if (sub_code == CO_AWAIT_EXPR)
    1634                 :            :         {
    1635                 :            :           /* We're updating the interior of a possibly <(void) expr>cleanup.  */
    1636                 :        130 :           TREE_OPERAND (stripped_stmt, 1) = resume_call;
    1637                 :        130 :           append_to_statement_list (saved_statement, &stmt_list);
    1638                 :            :         }
    1639                 :        299 :       else if (buried_stmt != NULL)
    1640                 :            :         {
    1641                 :        299 :           *buried_stmt = resume_call;
    1642                 :        299 :           append_to_statement_list (saved_statement, &stmt_list);
    1643                 :            :         }
    1644                 :            :       else
    1645                 :            :         {
    1646                 :          0 :           error_at (loc, "failed to substitute the resume method in %qE",
    1647                 :            :                     saved_statement);
    1648                 :          0 :           append_to_statement_list (saved_statement, &stmt_list);
    1649                 :            :         }
    1650                 :            :       break;
    1651                 :            :     }
    1652                 :       2226 :   if (needs_dtor)
    1653                 :       1841 :     append_to_statement_list (dtor, &stmt_list);
    1654                 :       2226 :   data->index += 2;
    1655                 :       2226 :   *stmt = stmt_list;
    1656                 :       2226 :   return NULL_TREE;
    1657                 :            : }
    1658                 :            : 
    1659                 :            : /* Suspend point hash_map.  */
    1660                 :            : 
    1661                 :            : struct suspend_point_info
    1662                 :            : {
    1663                 :            :   /* coro frame field type.  */
    1664                 :            :   tree awaitable_type;
    1665                 :            :   /* coro frame field name.  */
    1666                 :            :   tree await_field_id;
    1667                 :            : };
    1668                 :            : 
    1669                 :            : static hash_map<tree, suspend_point_info> *suspend_points;
    1670                 :            : 
    1671                 :            : struct await_xform_data
    1672                 :            : {
    1673                 :            :   tree actor_fn;   /* Decl for context.  */
    1674                 :            :   tree actor_frame;
    1675                 :            :   tree promise_proxy;
    1676                 :            :   tree real_promise;
    1677                 :            :   tree self_h_proxy;
    1678                 :            :   tree real_self_h;
    1679                 :            : };
    1680                 :            : 
    1681                 :            : /* When we built the await expressions, we didn't know the coro frame
    1682                 :            :    layout, therefore no idea where to find the promise or where to put
    1683                 :            :    the awaitables.  Now we know these things, fill them in.  */
    1684                 :            : 
    1685                 :            : static tree
    1686                 :       3006 : transform_await_expr (tree await_expr, await_xform_data *xform)
    1687                 :            : {
    1688                 :       3006 :   suspend_point_info *si = suspend_points->get (await_expr);
    1689                 :       3006 :   location_t loc = EXPR_LOCATION (await_expr);
    1690                 :       3006 :   if (!si)
    1691                 :            :     {
    1692                 :          0 :       error_at (loc, "no suspend point info for %qD", await_expr);
    1693                 :          0 :       return error_mark_node;
    1694                 :            :     }
    1695                 :            : 
    1696                 :            :   /* So, on entry, we have:
    1697                 :            :      in : CO_AWAIT_EXPR (a, e_proxy, o, awr_call_vector, mode)
    1698                 :            :           We no longer need a [it had diagnostic value, maybe?]
    1699                 :            :           We need to replace the promise proxy in all elements
    1700                 :            :           We need to replace the e_proxy in the awr_call.  */
    1701                 :            : 
    1702                 :       3006 :   tree coro_frame_type = TREE_TYPE (xform->actor_frame);
    1703                 :            : 
    1704                 :            :   /* If we have a frame var for the awaitable, get a reference to it.  */
    1705                 :       3006 :   proxy_replace data;
    1706                 :       3006 :   if (si->await_field_id)
    1707                 :            :     {
    1708                 :       2943 :       tree as_m
    1709                 :       2943 :          = lookup_member (coro_frame_type, si->await_field_id,
    1710                 :            :                           /*protect=*/1, /*want_type=*/0, tf_warning_or_error);
    1711                 :       2943 :       tree as = build_class_member_access_expr (xform->actor_frame, as_m,
    1712                 :            :                                                 NULL_TREE, true,
    1713                 :            :                                                 tf_warning_or_error);
    1714                 :            : 
    1715                 :            :       /* Replace references to the instance proxy with the frame entry now
    1716                 :            :          computed.  */
    1717                 :       2943 :       data.from = TREE_OPERAND (await_expr, 1);
    1718                 :       2943 :       data.to = as;
    1719                 :       2943 :       cp_walk_tree (&await_expr, replace_proxy, &data, NULL);
    1720                 :            : 
    1721                 :            :       /* .. and replace.  */
    1722                 :       2943 :       TREE_OPERAND (await_expr, 1) = as;
    1723                 :            :     }
    1724                 :            : 
    1725                 :            :   /* Now do the self_handle.  */
    1726                 :       3006 :   data.from = xform->self_h_proxy;
    1727                 :       3006 :   data.to = xform->real_self_h;
    1728                 :       3006 :   cp_walk_tree (&await_expr, replace_proxy, &data, NULL);
    1729                 :            : 
    1730                 :            :   /* Now do the promise.  */
    1731                 :       3006 :   data.from = xform->promise_proxy;
    1732                 :       3006 :   data.to = xform->real_promise;
    1733                 :       3006 :   cp_walk_tree (&await_expr, replace_proxy, &data, NULL);
    1734                 :            : 
    1735                 :       3006 :   return await_expr;
    1736                 :            : }
    1737                 :            : 
    1738                 :            : /* A wrapper for the transform_await_expr function so that it can be a
    1739                 :            :    callback from cp_walk_tree.  */
    1740                 :            : 
    1741                 :            : static tree
    1742                 :      98199 : transform_await_wrapper (tree *stmt, int *do_subtree, void *d)
    1743                 :            : {
    1744                 :            :   /* Set actor function as new DECL_CONTEXT of label_decl.  */
    1745                 :      98199 :   struct await_xform_data *xform = (struct await_xform_data *) d;
    1746                 :      98199 :   if (TREE_CODE (*stmt) == LABEL_DECL
    1747                 :      98199 :       && DECL_CONTEXT (*stmt) != xform->actor_fn)
    1748                 :         18 :     DECL_CONTEXT (*stmt) = xform->actor_fn;
    1749                 :            : 
    1750                 :      98199 :   if (TREE_CODE (*stmt) != CO_AWAIT_EXPR && TREE_CODE (*stmt) != CO_YIELD_EXPR)
    1751                 :            :     return NULL_TREE;
    1752                 :            : 
    1753                 :       1442 :   tree await_expr = *stmt;
    1754                 :       1442 :   *stmt = transform_await_expr (await_expr, xform);
    1755                 :       1442 :   if (*stmt == error_mark_node)
    1756                 :          0 :     *do_subtree = 0;
    1757                 :            :   return NULL_TREE;
    1758                 :            : }
    1759                 :            : 
    1760                 :            : /* This caches information that we determine about function params,
    1761                 :            :    their uses and copies in the coroutine frame.  */
    1762                 :            : 
    1763                 :            : struct param_info
    1764                 :            : {
    1765                 :            :   tree field_id;  /* The name of the copy in the coroutine frame.  */
    1766                 :            :   vec<tree *> *body_uses; /* Worklist of uses, void if there are none.  */
    1767                 :            :   tree frame_type; /* The type used to represent this parm in the frame.  */
    1768                 :            :   tree orig_type;  /* The original type of the parm (not as passed).  */
    1769                 :            :   bool by_ref;  /* Was passed by reference.  */
    1770                 :            :   bool rv_ref;  /* Was an rvalue reference.  */
    1771                 :            :   bool pt_ref;  /* Was a pointer to object.  */
    1772                 :            :   bool trivial_dtor; /* The frame type has a trivial DTOR.  */
    1773                 :            : };
    1774                 :            : 
    1775                 :            : struct local_var_info
    1776                 :            : {
    1777                 :            :   tree field_id;
    1778                 :            :   tree field_idx;
    1779                 :            :   tree frame_type;
    1780                 :            :   bool is_lambda_capture;
    1781                 :            :   location_t def_loc;
    1782                 :            : };
    1783                 :            : 
    1784                 :            : /* For figuring out what local variable usage we have.  */
    1785                 :            : struct local_vars_transform
    1786                 :            : {
    1787                 :            :   tree context;
    1788                 :            :   tree actor_frame;
    1789                 :            :   tree coro_frame_type;
    1790                 :            :   location_t loc;
    1791                 :            :   hash_map<tree, local_var_info> *local_var_uses;
    1792                 :            : };
    1793                 :            : 
    1794                 :            : static tree
    1795                 :     148946 : transform_local_var_uses (tree *stmt, int *do_subtree, void *d)
    1796                 :            : {
    1797                 :     148946 :   local_vars_transform *lvd = (local_vars_transform *) d;
    1798                 :            : 
    1799                 :            :   /* For each var in this bind expr (that has a frame id, which means it was
    1800                 :            :      accessed), build a frame reference for each and then walk the bind expr
    1801                 :            :      statements, substituting the frame ref for the original var.  */
    1802                 :            : 
    1803                 :     148946 :   if (TREE_CODE (*stmt) == BIND_EXPR)
    1804                 :            :     {
    1805                 :        923 :       tree lvar;
    1806                 :       1537 :       for (lvar = BIND_EXPR_VARS (*stmt); lvar != NULL;
    1807                 :        614 :            lvar = DECL_CHAIN (lvar))
    1808                 :            :         {
    1809                 :        614 :           bool existed;
    1810                 :        614 :           local_var_info &local_var
    1811                 :        614 :             = lvd->local_var_uses->get_or_insert (lvar, &existed);
    1812                 :        614 :           gcc_checking_assert (existed);
    1813                 :            : 
    1814                 :            :           /* Re-write the variable's context to be in the actor func.  */
    1815                 :        614 :           DECL_CONTEXT (lvar) = lvd->context;
    1816                 :            : 
    1817                 :            :           /* we need to walk some of the decl trees, which might contain
    1818                 :            :              references to vars replaced at a higher level.  */
    1819                 :        614 :           cp_walk_tree (&DECL_INITIAL (lvar), transform_local_var_uses, d,
    1820                 :            :                         NULL);
    1821                 :        614 :           cp_walk_tree (&DECL_SIZE (lvar), transform_local_var_uses, d, NULL);
    1822                 :        614 :           cp_walk_tree (&DECL_SIZE_UNIT (lvar), transform_local_var_uses, d,
    1823                 :            :                         NULL);
    1824                 :            : 
    1825                 :            :         /* For capture proxies, this could include the decl value expr.  */
    1826                 :        614 :         if (local_var.is_lambda_capture)
    1827                 :            :           {
    1828                 :         96 :             tree ve = DECL_VALUE_EXPR (lvar);
    1829                 :         96 :             cp_walk_tree (&ve, transform_local_var_uses, d, NULL);
    1830                 :         96 :             continue; /* No frame entry for this.  */
    1831                 :            :           }
    1832                 :            : 
    1833                 :            :           /* TODO: implement selective generation of fields when vars are
    1834                 :            :              known not-used.  */
    1835                 :        518 :           if (local_var.field_id == NULL_TREE)
    1836                 :          0 :             continue; /* Wasn't used.  */
    1837                 :            : 
    1838                 :        518 :           tree fld_ref
    1839                 :        518 :             = lookup_member (lvd->coro_frame_type, local_var.field_id,
    1840                 :            :                              /*protect=*/1, /*want_type=*/0,
    1841                 :            :                              tf_warning_or_error);
    1842                 :        518 :           tree fld_idx = build3_loc (lvd->loc, COMPONENT_REF, TREE_TYPE (lvar),
    1843                 :            :                                      lvd->actor_frame, fld_ref, NULL_TREE);
    1844                 :        518 :           local_var.field_idx = fld_idx;
    1845                 :            :         }
    1846                 :        923 :       cp_walk_tree (&BIND_EXPR_BODY (*stmt), transform_local_var_uses, d, NULL);
    1847                 :            : 
    1848                 :            :       /* Now we have processed and removed references to the original vars,
    1849                 :            :          we can drop those from the bind - leaving capture proxies alone.  */
    1850                 :       1537 :       for (tree *pvar = &BIND_EXPR_VARS (*stmt); *pvar != NULL;)
    1851                 :            :         {
    1852                 :        614 :           bool existed;
    1853                 :        614 :           local_var_info &local_var
    1854                 :        614 :             = lvd->local_var_uses->get_or_insert (*pvar, &existed);
    1855                 :        614 :           gcc_checking_assert (existed);
    1856                 :            : 
    1857                 :            :           /* Leave lambda closure captures alone, we replace the *this
    1858                 :            :              pointer with the frame version and let the normal process
    1859                 :            :              deal with the rest.  */
    1860                 :        614 :           if (local_var.is_lambda_capture)
    1861                 :            :             {
    1862                 :         96 :               pvar = &DECL_CHAIN (*pvar);
    1863                 :         96 :               continue;
    1864                 :            :             }
    1865                 :            : 
    1866                 :            :           /* It's not used, but we can let the optimizer deal with that.  */
    1867                 :        518 :           if (local_var.field_id == NULL_TREE)
    1868                 :            :             {
    1869                 :          0 :               pvar = &DECL_CHAIN (*pvar);
    1870                 :          0 :               continue;
    1871                 :            :             }
    1872                 :            : 
    1873                 :            :           /* Discard this one, we replaced it.  */
    1874                 :        518 :           *pvar = DECL_CHAIN (*pvar);
    1875                 :            :         }
    1876                 :            : 
    1877                 :        923 :       *do_subtree = 0; /* We've done the body already.  */
    1878                 :        923 :       return NULL_TREE;
    1879                 :            :     }
    1880                 :            : 
    1881                 :     148023 :   tree var_decl = *stmt;
    1882                 :            :   /* Look inside cleanups, we don't want to wrap a statement list in a
    1883                 :            :      cleanup.  */
    1884                 :     148023 :   bool needs_cleanup = true;
    1885                 :     148023 :   if (TREE_CODE (var_decl) == CLEANUP_POINT_EXPR)
    1886                 :       4209 :     var_decl = TREE_OPERAND (var_decl, 0);
    1887                 :            :   else
    1888                 :            :     needs_cleanup = false;
    1889                 :            : 
    1890                 :            :   /* Look inside the decl_expr for the actual var.  */
    1891                 :     148023 :   bool decl_expr_p = TREE_CODE (var_decl) == DECL_EXPR;
    1892                 :     148023 :   if (decl_expr_p && TREE_CODE (DECL_EXPR_DECL (var_decl)) == VAR_DECL)
    1893                 :        604 :     var_decl = DECL_EXPR_DECL (var_decl);
    1894                 :     147419 :   else if (TREE_CODE (var_decl) != VAR_DECL)
    1895                 :            :     return NULL_TREE;
    1896                 :            : 
    1897                 :            :   /* VAR_DECLs that are not recorded can belong to the proxies we've placed
    1898                 :            :      for the promise and coroutine handle(s), to global vars or to compiler
    1899                 :            :      temporaries.  Skip past these, we will handle them later.  */
    1900                 :      19723 :   local_var_info *local_var_i = lvd->local_var_uses->get (var_decl);
    1901                 :       2542 :   if (local_var_i == NULL)
    1902                 :            :     return NULL_TREE;
    1903                 :            : 
    1904                 :       2542 :   if (local_var_i->is_lambda_capture)
    1905                 :            :     return NULL_TREE;
    1906                 :            : 
    1907                 :            :   /* This is our revised 'local' i.e. a frame slot.  */
    1908                 :       1918 :   tree revised = local_var_i->field_idx;
    1909                 :       1918 :   gcc_checking_assert (DECL_CONTEXT (var_decl) == lvd->context);
    1910                 :            : 
    1911                 :       1918 :   if (decl_expr_p && DECL_INITIAL (var_decl))
    1912                 :            :     {
    1913                 :        307 :       location_t loc = DECL_SOURCE_LOCATION (var_decl);
    1914                 :        307 :       tree r
    1915                 :        614 :         = cp_build_modify_expr (loc, revised, INIT_EXPR,
    1916                 :        307 :                                 DECL_INITIAL (var_decl), tf_warning_or_error);
    1917                 :        307 :       if (needs_cleanup)
    1918                 :        115 :         r = coro_build_cvt_void_expr_stmt (r, EXPR_LOCATION (*stmt));
    1919                 :        307 :       *stmt = r;
    1920                 :            :     }
    1921                 :            :   else
    1922                 :       1611 :     *stmt = revised;
    1923                 :            : 
    1924                 :       1918 :   if (decl_expr_p)
    1925                 :        492 :     *do_subtree = 0; /* We've accounted for the nested use.  */
    1926                 :            :   return NULL_TREE;
    1927                 :            : }
    1928                 :            : 
    1929                 :            : /* The actor transform.  */
    1930                 :            : 
    1931                 :            : static void
    1932                 :        782 : build_actor_fn (location_t loc, tree coro_frame_type, tree actor, tree fnbody,
    1933                 :            :                 tree orig, hash_map<tree, param_info> *param_uses,
    1934                 :            :                 hash_map<tree, local_var_info> *local_var_uses,
    1935                 :            :                 vec<tree, va_gc> *param_dtor_list, tree initial_await,
    1936                 :            :                 tree final_await, unsigned body_count, tree frame_size)
    1937                 :            : {
    1938                 :        782 :   verify_stmt_tree (fnbody);
    1939                 :            :   /* Some things we inherit from the original function.  */
    1940                 :        782 :   tree coro_frame_ptr = build_pointer_type (coro_frame_type);
    1941                 :        782 :   tree handle_type = get_coroutine_handle_type (orig);
    1942                 :        782 :   tree self_h_proxy = get_coroutine_self_handle_proxy (orig);
    1943                 :        782 :   tree promise_type = get_coroutine_promise_type (orig);
    1944                 :        782 :   tree promise_proxy = get_coroutine_promise_proxy (orig);
    1945                 :        782 :   tree act_des_fn_type
    1946                 :        782 :     = build_function_type_list (void_type_node, coro_frame_ptr, NULL_TREE);
    1947                 :        782 :   tree act_des_fn_ptr = build_pointer_type (act_des_fn_type);
    1948                 :            : 
    1949                 :            :   /* One param, the coro frame pointer.  */
    1950                 :        782 :   tree actor_fp = DECL_ARGUMENTS (actor);
    1951                 :            : 
    1952                 :            :   /* A void return.  */
    1953                 :        782 :   tree resdecl = build_decl (loc, RESULT_DECL, 0, void_type_node);
    1954                 :        782 :   DECL_ARTIFICIAL (resdecl) = 1;
    1955                 :        782 :   DECL_IGNORED_P (resdecl) = 1;
    1956                 :        782 :   DECL_RESULT (actor) = resdecl;
    1957                 :        782 :   DECL_COROUTINE_P (actor) = 1;
    1958                 :            : 
    1959                 :            :   /* We have a definition here.  */
    1960                 :        782 :   TREE_STATIC (actor) = 1;
    1961                 :            : 
    1962                 :        782 :   tree actor_outer = push_stmt_list ();
    1963                 :        782 :   current_stmt_tree ()->stmts_are_full_exprs_p = 1;
    1964                 :        782 :   tree stmt = begin_compound_stmt (BCS_FN_BODY);
    1965                 :            : 
    1966                 :            :   /* ??? Can we dispense with the enclosing bind if the function body does
    1967                 :            :      not start with a bind_expr? (i.e. there's no contained scopes).  */
    1968                 :        782 :   tree actor_bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
    1969                 :        782 :   tree top_block = make_node (BLOCK);
    1970                 :        782 :   BIND_EXPR_BLOCK (actor_bind) = top_block;
    1971                 :            : 
    1972                 :        782 :   tree continuation = build_lang_decl (VAR_DECL,
    1973                 :            :                                        get_identifier ("actor.continue"),
    1974                 :            :                                        void_coro_handle_type);
    1975                 :        782 :   DECL_ARTIFICIAL (continuation) = 1;
    1976                 :        782 :   DECL_IGNORED_P (continuation) = 1;
    1977                 :        782 :   DECL_CONTEXT (continuation) = actor;
    1978                 :        782 :   BIND_EXPR_VARS (actor_bind) = continuation;
    1979                 :            : 
    1980                 :            :   /* Update the block associated with the outer scope of the orig fn.  */
    1981                 :        782 :   tree first = expr_first (fnbody);
    1982                 :        782 :   if (first && TREE_CODE (first) == BIND_EXPR)
    1983                 :            :     {
    1984                 :            :       /* We will discard this, since it's connected to the original scope
    1985                 :            :          nest.  */
    1986                 :        375 :       tree block = BIND_EXPR_BLOCK (first);
    1987                 :        375 :       if (block) /* For this to be missing is probably a bug.  */
    1988                 :            :         {
    1989                 :        375 :           gcc_assert (BLOCK_SUPERCONTEXT (block) == NULL_TREE);
    1990                 :        375 :           gcc_assert (BLOCK_CHAIN (block) == NULL_TREE);
    1991                 :        375 :           BLOCK_SUPERCONTEXT (block) = top_block;
    1992                 :        375 :           BLOCK_SUBBLOCKS (top_block) = block;
    1993                 :            :         }
    1994                 :            :     }
    1995                 :            : 
    1996                 :        782 :   add_stmt (actor_bind);
    1997                 :        782 :   tree actor_body = push_stmt_list ();
    1998                 :            : 
    1999                 :            :   /* The entry point for the actor code from the ramp.  */
    2000                 :        782 :   tree actor_begin_label
    2001                 :        782 :     = create_named_label_with_ctx (loc, "actor.begin", actor);
    2002                 :        782 :   tree actor_frame = build1_loc (loc, INDIRECT_REF, coro_frame_type, actor_fp);
    2003                 :            : 
    2004                 :            :   /* Declare the continuation handle.  */
    2005                 :        782 :   add_decl_expr (continuation);
    2006                 :            : 
    2007                 :            :   /* Re-write param references in the body, no code should be generated
    2008                 :            :      here.  */
    2009                 :        782 :   if (DECL_ARGUMENTS (orig))
    2010                 :            :     {
    2011                 :        404 :       tree arg;
    2012                 :        972 :       for (arg = DECL_ARGUMENTS (orig); arg != NULL; arg = DECL_CHAIN (arg))
    2013                 :            :         {
    2014                 :        568 :           bool existed;
    2015                 :        568 :           param_info &parm = param_uses->get_or_insert (arg, &existed);
    2016                 :        568 :           if (!parm.body_uses)
    2017                 :        132 :             continue; /* Wasn't used in the orignal function body.  */
    2018                 :            : 
    2019                 :        436 :           tree fld_ref = lookup_member (coro_frame_type, parm.field_id,
    2020                 :            :                                         /*protect=*/1, /*want_type=*/0,
    2021                 :            :                                         tf_warning_or_error);
    2022                 :        436 :           tree fld_idx = build3_loc (loc, COMPONENT_REF, parm.frame_type,
    2023                 :            :                                      actor_frame, fld_ref, NULL_TREE);
    2024                 :            : 
    2025                 :            :           /* We keep these in the frame as a regular pointer, so convert that
    2026                 :            :            back to the type expected.  */
    2027                 :        436 :           if (parm.pt_ref)
    2028                 :         51 :             fld_idx = build1_loc (loc, CONVERT_EXPR, TREE_TYPE (arg), fld_idx);
    2029                 :            : 
    2030                 :            :           /* We expect an rvalue ref. here.  */
    2031                 :        436 :           if (parm.rv_ref)
    2032                 :         26 :             fld_idx = convert_to_reference (DECL_ARG_TYPE (arg), fld_idx,
    2033                 :            :                                             CONV_STATIC, LOOKUP_NORMAL,
    2034                 :            :                                             NULL_TREE, tf_warning_or_error);
    2035                 :            : 
    2036                 :        436 :           int i;
    2037                 :        436 :           tree *puse;
    2038                 :       1700 :           FOR_EACH_VEC_ELT (*parm.body_uses, i, puse)
    2039                 :        828 :             *puse = fld_idx;
    2040                 :            :         }
    2041                 :            :     }
    2042                 :            : 
    2043                 :            :   /* Re-write local vars, similarly.  */
    2044                 :        782 :   local_vars_transform xform_vars_data
    2045                 :        782 :     = {actor, actor_frame, coro_frame_type, loc, local_var_uses};
    2046                 :        782 :   cp_walk_tree (&fnbody, transform_local_var_uses, &xform_vars_data, NULL);
    2047                 :            : 
    2048                 :        782 :   tree resume_idx_name = get_identifier ("__resume_at");
    2049                 :        782 :   tree rat_field = lookup_member (coro_frame_type, resume_idx_name, 1, 0,
    2050                 :            :                                   tf_warning_or_error);
    2051                 :        782 :   tree rat = build3 (COMPONENT_REF, short_unsigned_type_node, actor_frame,
    2052                 :            :                      rat_field, NULL_TREE);
    2053                 :            : 
    2054                 :        782 :   tree ret_label
    2055                 :        782 :     = create_named_label_with_ctx (loc, "actor.suspend.ret", actor);
    2056                 :            : 
    2057                 :        782 :   tree continue_label
    2058                 :        782 :     = create_named_label_with_ctx (loc, "actor.continue.ret", actor);
    2059                 :            : 
    2060                 :        782 :   tree lsb_if = begin_if_stmt ();
    2061                 :        782 :   tree chkb0 = build2 (BIT_AND_EXPR, short_unsigned_type_node, rat,
    2062                 :        782 :                        build_int_cst (short_unsigned_type_node, 1));
    2063                 :        782 :   chkb0 = build2 (NE_EXPR, short_unsigned_type_node, chkb0,
    2064                 :        782 :                   build_int_cst (short_unsigned_type_node, 0));
    2065                 :        782 :   finish_if_stmt_cond (chkb0, lsb_if);
    2066                 :            : 
    2067                 :        782 :   tree destroy_dispatcher = begin_switch_stmt ();
    2068                 :        782 :   finish_switch_cond (rat, destroy_dispatcher);
    2069                 :        782 :   tree ddeflab = build_case_label (NULL_TREE, NULL_TREE,
    2070                 :            :                                    create_anon_label_with_ctx (loc, actor));
    2071                 :        782 :   add_stmt (ddeflab);
    2072                 :        782 :   tree b = build_call_expr_loc (loc, builtin_decl_explicit (BUILT_IN_TRAP), 0);
    2073                 :        782 :   b = coro_build_cvt_void_expr_stmt (b, loc);
    2074                 :        782 :   add_stmt (b);
    2075                 :            : 
    2076                 :        782 :   short unsigned lab_num = 3;
    2077                 :       3008 :   for (unsigned destr_pt = 0; destr_pt < body_count + 2; destr_pt++)
    2078                 :            :     {
    2079                 :       2226 :       tree l_num = build_int_cst (short_unsigned_type_node, lab_num);
    2080                 :       2226 :       b = build_case_label (l_num, NULL_TREE,
    2081                 :            :                             create_anon_label_with_ctx (loc, actor));
    2082                 :       2226 :       add_stmt (b);
    2083                 :       2226 :       b = build_call_expr_internal_loc (loc, IFN_CO_ACTOR, void_type_node, 1,
    2084                 :            :                                         l_num);
    2085                 :       2226 :       b = coro_build_cvt_void_expr_stmt (b, loc);
    2086                 :       2226 :       add_stmt (b);
    2087                 :       2226 :       b = build1 (GOTO_EXPR, void_type_node, CASE_LABEL (ddeflab));
    2088                 :       2226 :       add_stmt (b);
    2089                 :       2226 :       lab_num += 2;
    2090                 :            :     }
    2091                 :            : 
    2092                 :            :   /* Insert the prototype dispatcher.  */
    2093                 :        782 :   finish_switch_stmt (destroy_dispatcher);
    2094                 :            : 
    2095                 :        782 :   finish_then_clause (lsb_if);
    2096                 :            : 
    2097                 :        782 :   tree dispatcher = begin_switch_stmt ();
    2098                 :        782 :   finish_switch_cond (rat, dispatcher);
    2099                 :        782 :   b = build_case_label (build_int_cst (short_unsigned_type_node, 0), NULL_TREE,
    2100                 :            :                         create_anon_label_with_ctx (loc, actor));
    2101                 :        782 :   add_stmt (b);
    2102                 :        782 :   b = build1 (GOTO_EXPR, void_type_node, actor_begin_label);
    2103                 :        782 :   add_stmt (b);
    2104                 :            : 
    2105                 :        782 :   tree rdeflab = build_case_label (NULL_TREE, NULL_TREE,
    2106                 :            :                                    create_anon_label_with_ctx (loc, actor));
    2107                 :        782 :   add_stmt (rdeflab);
    2108                 :        782 :   b = build_call_expr_loc (loc, builtin_decl_explicit (BUILT_IN_TRAP), 0);
    2109                 :        782 :   b = coro_build_cvt_void_expr_stmt (b, loc);
    2110                 :        782 :   add_stmt (b);
    2111                 :            : 
    2112                 :        782 :   lab_num = 2;
    2113                 :            :   /* The final resume should be made to hit the default (trap, UB) entry.  */
    2114                 :       2226 :   for (unsigned resu_pt = 0; resu_pt < body_count + 1; resu_pt++)
    2115                 :            :     {
    2116                 :       1444 :       tree l_num = build_int_cst (short_unsigned_type_node, lab_num);
    2117                 :       1444 :       b = build_case_label (l_num, NULL_TREE,
    2118                 :            :                             create_anon_label_with_ctx (loc, actor));
    2119                 :       1444 :       add_stmt (b);
    2120                 :       1444 :       b = build_call_expr_internal_loc (loc, IFN_CO_ACTOR, void_type_node, 1,
    2121                 :            :                                         l_num);
    2122                 :       1444 :       b = coro_build_cvt_void_expr_stmt (b, loc);
    2123                 :       1444 :       add_stmt (b);
    2124                 :       1444 :       b = build1 (GOTO_EXPR, void_type_node, CASE_LABEL (rdeflab));
    2125                 :       1444 :       add_stmt (b);
    2126                 :       1444 :       lab_num += 2;
    2127                 :            :     }
    2128                 :            : 
    2129                 :            :   /* Insert the prototype dispatcher.  */
    2130                 :        782 :   finish_switch_stmt (dispatcher);
    2131                 :            : 
    2132                 :        782 :   finish_if_stmt (lsb_if);
    2133                 :            : 
    2134                 :        782 :   tree r = build_stmt (loc, LABEL_EXPR, actor_begin_label);
    2135                 :        782 :   add_stmt (r);
    2136                 :            : 
    2137                 :            :   /* actor's version of the promise.  */
    2138                 :        782 :   tree ap_m = lookup_member (coro_frame_type, get_identifier ("__p"), 1, 0,
    2139                 :            :                              tf_warning_or_error);
    2140                 :        782 :   tree ap = build_class_member_access_expr (actor_frame, ap_m, NULL_TREE, false,
    2141                 :            :                                             tf_warning_or_error);
    2142                 :            : 
    2143                 :            :   /* actor's coroutine 'self handle'.  */
    2144                 :        782 :   tree ash_m = lookup_member (coro_frame_type, get_identifier ("__self_h"), 1,
    2145                 :            :                               0, tf_warning_or_error);
    2146                 :        782 :   tree ash = build_class_member_access_expr (actor_frame, ash_m, NULL_TREE,
    2147                 :            :                                              false, tf_warning_or_error);
    2148                 :            :   /* So construct the self-handle from the frame address.  */
    2149                 :        782 :   tree hfa_m = lookup_member (handle_type, coro_from_address_identifier, 1,
    2150                 :            :                               0, tf_warning_or_error);
    2151                 :            : 
    2152                 :        782 :   r = build1 (CONVERT_EXPR, build_pointer_type (void_type_node), actor_fp);
    2153                 :        782 :   vec<tree, va_gc> *args = make_tree_vector_single (r);
    2154                 :        782 :   tree hfa = build_new_method_call (ash, hfa_m, &args, NULL_TREE, LOOKUP_NORMAL,
    2155                 :            :                                     NULL, tf_warning_or_error);
    2156                 :        782 :   r = build2 (INIT_EXPR, handle_type, ash, hfa);
    2157                 :        782 :   r = coro_build_cvt_void_expr_stmt (r, loc);
    2158                 :        782 :   add_stmt (r);
    2159                 :        782 :   release_tree_vector (args);
    2160                 :            : 
    2161                 :            :   /* Now we know the real promise, and enough about the frame layout to
    2162                 :            :      decide where to put things.  */
    2163                 :            : 
    2164                 :        782 :   await_xform_data xform
    2165                 :        782 :     = {actor, actor_frame, promise_proxy, ap, self_h_proxy, ash};
    2166                 :            : 
    2167                 :            :   /* Get a reference to the initial suspend var in the frame.  */
    2168                 :        782 :   transform_await_expr (initial_await, &xform);
    2169                 :        782 :   tree initial_await_stmt = coro_build_expr_stmt (initial_await, loc);
    2170                 :            : 
    2171                 :            :   /* co_return branches to the final_suspend label, so declare that now.  */
    2172                 :        782 :   tree fs_label = create_named_label_with_ctx (loc, "final.suspend", actor);
    2173                 :            : 
    2174                 :            :   /* Expand co_returns in the saved function body  */
    2175                 :        782 :   fnbody = expand_co_returns (&fnbody, promise_proxy, ap, fs_label);
    2176                 :            : 
    2177                 :            :   /* n4849 adds specific behaviour to treat exceptions thrown by the
    2178                 :            :      await_resume () of the initial suspend expression.  In order to
    2179                 :            :      implement this, we need to treat the initial_suspend expression
    2180                 :            :      as if it were part of the user-authored function body.  This
    2181                 :            :      only applies if exceptions are enabled.  */
    2182                 :        782 :   if (flag_exceptions)
    2183                 :            :     {
    2184                 :        780 :       tree outer = fnbody;
    2185                 :        780 :       if (TREE_CODE (outer) == BIND_EXPR)
    2186                 :        375 :         outer = BIND_EXPR_BODY (outer);
    2187                 :        780 :       gcc_checking_assert (TREE_CODE (outer) == TRY_BLOCK);
    2188                 :        780 :       tree sl = TRY_STMTS (outer);
    2189                 :        780 :       if (TREE_CODE (sl) == STATEMENT_LIST)
    2190                 :            :         {
    2191                 :        521 :           tree_stmt_iterator si = tsi_start (sl);
    2192                 :        521 :           tsi_link_before (&si, initial_await_stmt, TSI_NEW_STMT);
    2193                 :            :         }
    2194                 :            :       else
    2195                 :            :         {
    2196                 :        259 :           tree new_try = NULL_TREE;
    2197                 :        259 :           append_to_statement_list (initial_await_stmt, &new_try);
    2198                 :        259 :           append_to_statement_list (sl, &new_try);
    2199                 :        259 :           TRY_STMTS (outer) = new_try;
    2200                 :            :         }
    2201                 :            :     }
    2202                 :            :   else
    2203                 :          2 :     add_stmt (initial_await_stmt);
    2204                 :            : 
    2205                 :            :   /* Transform the await expressions in the function body.  Only do each
    2206                 :            :      await tree once!  */
    2207                 :        782 :   hash_set<tree> pset;
    2208                 :        782 :   cp_walk_tree (&fnbody, transform_await_wrapper, &xform, &pset);
    2209                 :            : 
    2210                 :            :   /* Add in our function body with the co_returns rewritten to final form.  */
    2211                 :        782 :   add_stmt (fnbody);
    2212                 :            : 
    2213                 :            :   /* Final suspend starts here.  */
    2214                 :        782 :   r = build_stmt (loc, LABEL_EXPR, fs_label);
    2215                 :        782 :   add_stmt (r);
    2216                 :            : 
    2217                 :            :   /* Set the actor pointer to null, so that 'done' will work.
    2218                 :            :      Resume from here is UB anyway - although a 'ready' await will
    2219                 :            :      branch to the final resume, and fall through to the destroy.  */
    2220                 :        782 :   tree resume_m
    2221                 :        782 :     = lookup_member (coro_frame_type, get_identifier ("__resume"),
    2222                 :            :                      /*protect=*/1, /*want_type=*/0, tf_warning_or_error);
    2223                 :        782 :   tree res_x = build_class_member_access_expr (actor_frame, resume_m, NULL_TREE,
    2224                 :            :                                                false, tf_warning_or_error);
    2225                 :        782 :   r = build1 (CONVERT_EXPR, act_des_fn_ptr, integer_zero_node);
    2226                 :        782 :   r = build2 (INIT_EXPR, act_des_fn_ptr, res_x, r);
    2227                 :        782 :   r = coro_build_cvt_void_expr_stmt (r, loc);
    2228                 :        782 :   add_stmt (r);
    2229                 :            : 
    2230                 :            :   /* Get a reference to the final suspend var in the frame.  */
    2231                 :        782 :   transform_await_expr (final_await, &xform);
    2232                 :        782 :   r = coro_build_expr_stmt (final_await, loc);
    2233                 :        782 :   add_stmt (r);
    2234                 :            : 
    2235                 :            :   /* now do the tail of the function.  */
    2236                 :        782 :   tree del_promise_label
    2237                 :        782 :     = create_named_label_with_ctx (loc, "coro.delete.promise", actor);
    2238                 :        782 :   r = build_stmt (loc, LABEL_EXPR, del_promise_label);
    2239                 :        782 :   add_stmt (r);
    2240                 :            : 
    2241                 :            :   /* Destructors for the things we built explicitly.  */
    2242                 :        782 :   r = build_special_member_call (ap, complete_dtor_identifier, NULL,
    2243                 :            :                                  promise_type, LOOKUP_NORMAL,
    2244                 :            :                                  tf_warning_or_error);
    2245                 :        782 :   add_stmt (r);
    2246                 :            : 
    2247                 :        782 :   tree del_frame_label
    2248                 :        782 :     = create_named_label_with_ctx (loc, "coro.delete.frame", actor);
    2249                 :        782 :   r = build_stmt (loc, LABEL_EXPR, del_frame_label);
    2250                 :        782 :   add_stmt (r);
    2251                 :            : 
    2252                 :            :   /* Here deallocate the frame (if we allocated it), which we will have at
    2253                 :            :      present.  */
    2254                 :        782 :   tree fnf_m
    2255                 :        782 :     = lookup_member (coro_frame_type, get_identifier ("__frame_needs_free"), 1,
    2256                 :            :                      0, tf_warning_or_error);
    2257                 :        782 :   tree fnf2_x = build_class_member_access_expr (actor_frame, fnf_m, NULL_TREE,
    2258                 :            :                                                 false, tf_warning_or_error);
    2259                 :            : 
    2260                 :        782 :   tree need_free_if = begin_if_stmt ();
    2261                 :        782 :   fnf2_x = build1 (CONVERT_EXPR, integer_type_node, fnf2_x);
    2262                 :        782 :   tree cmp = build2 (NE_EXPR, integer_type_node, fnf2_x, integer_zero_node);
    2263                 :        782 :   finish_if_stmt_cond (cmp, need_free_if);
    2264                 :        782 :   if (param_dtor_list != NULL)
    2265                 :            :     {
    2266                 :            :       int i;
    2267                 :            :       tree pid;
    2268                 :         72 :       FOR_EACH_VEC_ELT (*param_dtor_list, i, pid)
    2269                 :            :         {
    2270                 :         45 :           tree m
    2271                 :         45 :             = lookup_member (coro_frame_type, pid, 1, 0, tf_warning_or_error);
    2272                 :         45 :           tree a = build_class_member_access_expr (actor_frame, m, NULL_TREE,
    2273                 :            :                                                    false, tf_warning_or_error);
    2274                 :         45 :           tree t = TREE_TYPE (a);
    2275                 :         45 :           tree dtor;
    2276                 :         45 :           dtor
    2277                 :         45 :             = build_special_member_call (a, complete_dtor_identifier, NULL, t,
    2278                 :            :                                          LOOKUP_NORMAL, tf_warning_or_error);
    2279                 :         45 :           add_stmt (dtor);
    2280                 :            :         }
    2281                 :            :     }
    2282                 :            : 
    2283                 :            :   /* n4849 [dcl.fct.def.coroutine] / 12
    2284                 :            :      The deallocation function’s name is looked up in the scope of the promise
    2285                 :            :      type.  If this lookup fails, the deallocation function’s name is looked up
    2286                 :            :      in the global scope.  If deallocation function lookup finds both a usual
    2287                 :            :      deallocation function with only a pointer parameter and a usual
    2288                 :            :      deallocation function with both a pointer parameter and a size parameter,
    2289                 :            :      then the selected deallocation function shall be the one with two
    2290                 :            :      parameters.  Otherwise, the selected deallocation function shall be the
    2291                 :            :      function with one parameter.  If no usual deallocation function is found
    2292                 :            :      the program is ill-formed.  The selected deallocation function shall be
    2293                 :            :      called with the address of the block of storage to be reclaimed as its
    2294                 :            :      first argument.  If a deallocation function with a parameter of type
    2295                 :            :      std::size_t is used, the size of the block is passed as the corresponding
    2296                 :            :      argument.  */
    2297                 :            : 
    2298                 :        782 :   tree del_coro_fr = NULL_TREE;
    2299                 :        782 :   tree frame_arg = build1 (CONVERT_EXPR, ptr_type_node, actor_fp);
    2300                 :            : 
    2301                 :        782 :   tree delname = ovl_op_identifier (false, DELETE_EXPR);
    2302                 :        782 :   tree fns = lookup_promise_method (orig, delname, loc, /*musthave=*/false);
    2303                 :        782 :   if (fns && BASELINK_P (fns))
    2304                 :            :     {
    2305                 :            :       /* Look for sized version first, since this takes precedence.  */
    2306                 :         26 :       vec<tree, va_gc> *args = make_tree_vector ();
    2307                 :         26 :       vec_safe_push (args, frame_arg);
    2308                 :         26 :       vec_safe_push (args, frame_size);
    2309                 :         26 :       tree dummy_promise = build_dummy_object (promise_type);
    2310                 :            : 
    2311                 :            :       /* It's OK to fail for this one... */
    2312                 :         26 :       del_coro_fr = build_new_method_call (dummy_promise, fns, &args,
    2313                 :            :                                            NULL_TREE, LOOKUP_NORMAL, NULL,
    2314                 :            :                                            tf_none);
    2315                 :            : 
    2316                 :         26 :       if (!del_coro_fr || del_coro_fr == error_mark_node)
    2317                 :            :         {
    2318                 :         18 :           release_tree_vector (args);
    2319                 :         18 :           args = make_tree_vector_single (frame_arg);
    2320                 :         18 :           del_coro_fr = build_new_method_call (dummy_promise, fns, &args,
    2321                 :            :                                                NULL_TREE, LOOKUP_NORMAL, NULL,
    2322                 :            :                                                tf_none);
    2323                 :            :         }
    2324                 :            : 
    2325                 :            :       /* But one of them must succeed, or the program is ill-formed.  */
    2326                 :         26 :       if (!del_coro_fr || del_coro_fr == error_mark_node)
    2327                 :            :         {
    2328                 :          1 :           error_at (loc, "%qE is provided by %qT but is not usable with"
    2329                 :            :                   " the function signature %qD", delname, promise_type, orig);
    2330                 :          1 :           del_coro_fr = error_mark_node;
    2331                 :         26 :         }
    2332                 :            :     }
    2333                 :            :   else
    2334                 :            :     {
    2335                 :        756 :       del_coro_fr = build_op_delete_call (DELETE_EXPR, frame_arg, frame_size,
    2336                 :            :                                           /*global_p=*/true, /*placement=*/NULL,
    2337                 :            :                                           /*alloc_fn=*/NULL,
    2338                 :            :                                           tf_warning_or_error);
    2339                 :        756 :       if (!del_coro_fr || del_coro_fr == error_mark_node)
    2340                 :          0 :         del_coro_fr = error_mark_node;
    2341                 :            :     }
    2342                 :            : 
    2343                 :        782 :   del_coro_fr = coro_build_cvt_void_expr_stmt (del_coro_fr, loc);
    2344                 :        782 :   add_stmt (del_coro_fr);
    2345                 :        782 :   finish_then_clause (need_free_if);
    2346                 :        782 :   tree scope = IF_SCOPE (need_free_if);
    2347                 :        782 :   IF_SCOPE (need_free_if) = NULL;
    2348                 :        782 :   r = do_poplevel (scope);
    2349                 :        782 :   add_stmt (r);
    2350                 :            : 
    2351                 :            :   /* done.  */
    2352                 :        782 :   r = build_stmt (loc, RETURN_EXPR, NULL);
    2353                 :        782 :   TREE_NO_WARNING (r) |= 1; /* We don't want a warning about this.  */
    2354                 :        782 :   r = maybe_cleanup_point_expr_void (r);
    2355                 :        782 :   add_stmt (r);
    2356                 :            : 
    2357                 :            :   /* This is the suspend return point.  */
    2358                 :        782 :   r = build_stmt (loc, LABEL_EXPR, ret_label);
    2359                 :        782 :   add_stmt (r);
    2360                 :            : 
    2361                 :        782 :   r = build_stmt (loc, RETURN_EXPR, NULL);
    2362                 :        782 :   TREE_NO_WARNING (r) |= 1; /* We don't want a warning about this.  */
    2363                 :        782 :   r = maybe_cleanup_point_expr_void (r);
    2364                 :        782 :   add_stmt (r);
    2365                 :            : 
    2366                 :            :   /* This is the 'continuation' return point.  For such a case we have a coro
    2367                 :            :      handle (from the await_suspend() call) and we want handle.resume() to
    2368                 :            :      execute as a tailcall allowing arbitrary chaining of coroutines.  */
    2369                 :        782 :   r = build_stmt (loc, LABEL_EXPR, continue_label);
    2370                 :        782 :   add_stmt (r);
    2371                 :            : 
    2372                 :            :   /* We want to force a tail-call even for O0/1, so this expands the resume
    2373                 :            :      call into its underlying implementation.  */
    2374                 :        782 :   tree addr = lookup_member (void_coro_handle_type, coro_address_identifier,
    2375                 :            :                                1, 0, tf_warning_or_error);
    2376                 :        782 :   addr = build_new_method_call (continuation, addr, NULL, NULL_TREE,
    2377                 :            :                                   LOOKUP_NORMAL, NULL, tf_warning_or_error);
    2378                 :        782 :   tree resume = build_call_expr_loc
    2379                 :        782 :     (loc, builtin_decl_explicit (BUILT_IN_CORO_RESUME), 1, addr);
    2380                 :            : 
    2381                 :            :   /* Now we have the actual call, and we can mark it as a tail.  */
    2382                 :        782 :   CALL_EXPR_TAILCALL (resume) = true;
    2383                 :            :   /* ... and for optimisation levels 0..1, mark it as requiring a tail-call
    2384                 :            :      for correctness.  It seems that doing this for optimisation levels that
    2385                 :            :      normally perform tail-calling, confuses the ME (or it would be logical
    2386                 :            :      to put this on unilaterally).  */
    2387                 :        782 :   if (optimize < 2)
    2388                 :        293 :     CALL_EXPR_MUST_TAIL_CALL (resume) = true;
    2389                 :        782 :   resume = coro_build_cvt_void_expr_stmt (resume, loc);
    2390                 :        782 :   add_stmt (resume);
    2391                 :            : 
    2392                 :        782 :   r = build_stmt (loc, RETURN_EXPR, NULL);
    2393                 :        782 :   gcc_checking_assert (maybe_cleanup_point_expr_void (r) == r);
    2394                 :        782 :   add_stmt (r);
    2395                 :            : 
    2396                 :            :   /* We will need to know which resume point number should be encoded.  */
    2397                 :        782 :   tree res_idx_m
    2398                 :        782 :     = lookup_member (coro_frame_type, resume_idx_name,
    2399                 :            :                      /*protect=*/1, /*want_type=*/0, tf_warning_or_error);
    2400                 :        782 :   tree resume_pt_number
    2401                 :        782 :     = build_class_member_access_expr (actor_frame, res_idx_m, NULL_TREE, false,
    2402                 :            :                                       tf_warning_or_error);
    2403                 :            : 
    2404                 :            :   /* Boolean value to flag that the initial suspend expression's
    2405                 :            :      await_resume () has been called, and therefore we are in the user's
    2406                 :            :      function body for the purposes of handing exceptions.  */
    2407                 :        782 :   tree i_a_r_c_m
    2408                 :        782 :     = lookup_member (coro_frame_type, get_identifier ("__i_a_r_c"),
    2409                 :            :                      /*protect=*/1, /*want_type=*/0, tf_warning_or_error);
    2410                 :        782 :   tree i_a_r_c
    2411                 :        782 :     = build_class_member_access_expr (actor_frame, i_a_r_c_m, NULL_TREE,
    2412                 :            :                                       false, tf_warning_or_error);
    2413                 :            : 
    2414                 :            :   /* We've now rewritten the tree and added the initial and final
    2415                 :            :      co_awaits.  Now pass over the tree and expand the co_awaits.  */
    2416                 :            : 
    2417                 :        782 :   coro_aw_data data = {actor, actor_fp, resume_pt_number, i_a_r_c,
    2418                 :            :                        ash, del_promise_label, ret_label,
    2419                 :        782 :                        continue_label, continuation, 2};
    2420                 :        782 :   cp_walk_tree (&actor_body, co_await_expander, &data, NULL);
    2421                 :            : 
    2422                 :        782 :   actor_body = pop_stmt_list (actor_body);
    2423                 :        782 :   BIND_EXPR_BODY (actor_bind) = actor_body;
    2424                 :            : 
    2425                 :        782 :   finish_compound_stmt (stmt);
    2426                 :        782 :   DECL_SAVED_TREE (actor) = pop_stmt_list (actor_outer);
    2427                 :        782 :   verify_stmt_tree (DECL_SAVED_TREE (actor));
    2428                 :        782 : }
    2429                 :            : 
    2430                 :            : /* The prototype 'destroy' function :
    2431                 :            :    frame->__resume_at |= 1;
    2432                 :            :    actor (frame);  */
    2433                 :            : 
    2434                 :            : static void
    2435                 :        782 : build_destroy_fn (location_t loc, tree coro_frame_type, tree destroy,
    2436                 :            :                   tree actor)
    2437                 :            : {
    2438                 :            :   /* One param, the coro frame pointer.  */
    2439                 :        782 :   tree destr_fp = DECL_ARGUMENTS (destroy);
    2440                 :            : 
    2441                 :            :   /* A void return.  */
    2442                 :        782 :   tree resdecl = build_decl (loc, RESULT_DECL, 0, void_type_node);
    2443                 :        782 :   DECL_ARTIFICIAL (resdecl) = 1;
    2444                 :        782 :   DECL_IGNORED_P (resdecl) = 1;
    2445                 :        782 :   DECL_RESULT (destroy) = resdecl;
    2446                 :            : 
    2447                 :            :   /* We have a definition here.  */
    2448                 :        782 :   TREE_STATIC (destroy) = 1;
    2449                 :        782 :   DECL_COROUTINE_P (destroy) = 1;
    2450                 :            : 
    2451                 :        782 :   tree destr_outer = push_stmt_list ();
    2452                 :        782 :   current_stmt_tree ()->stmts_are_full_exprs_p = 1;
    2453                 :        782 :   tree dstr_stmt = begin_compound_stmt (BCS_FN_BODY);
    2454                 :            : 
    2455                 :        782 :   tree destr_frame = build1 (INDIRECT_REF, coro_frame_type, destr_fp);
    2456                 :            : 
    2457                 :        782 :   tree resume_idx_name = get_identifier ("__resume_at");
    2458                 :        782 :   tree rat_field = lookup_member (coro_frame_type, resume_idx_name, 1, 0,
    2459                 :            :                                   tf_warning_or_error);
    2460                 :        782 :   tree rat = build3 (COMPONENT_REF, short_unsigned_type_node, destr_frame,
    2461                 :            :                      rat_field, NULL_TREE);
    2462                 :            : 
    2463                 :            :   /* _resume_at |= 1 */
    2464                 :        782 :   tree dstr_idx = build2 (BIT_IOR_EXPR, short_unsigned_type_node, rat,
    2465                 :        782 :                           build_int_cst (short_unsigned_type_node, 1));
    2466                 :        782 :   tree r = build2 (MODIFY_EXPR, short_unsigned_type_node, rat, dstr_idx);
    2467                 :        782 :   r = coro_build_cvt_void_expr_stmt (r, loc);
    2468                 :        782 :   add_stmt (r);
    2469                 :            : 
    2470                 :            :   /* So .. call the actor ..  */
    2471                 :        782 :   r = build_call_expr_loc (loc, actor, 1, destr_fp);
    2472                 :        782 :   r = coro_build_cvt_void_expr_stmt (r, loc);
    2473                 :        782 :   add_stmt (r);
    2474                 :            : 
    2475                 :            :   /* done. */
    2476                 :        782 :   r = build_stmt (loc, RETURN_EXPR, NULL);
    2477                 :        782 :   r = maybe_cleanup_point_expr_void (r);
    2478                 :        782 :   add_stmt (r);
    2479                 :            : 
    2480                 :        782 :   finish_compound_stmt (dstr_stmt);
    2481                 :        782 :   DECL_SAVED_TREE (destroy) = pop_stmt_list (destr_outer);
    2482                 :        782 : }
    2483                 :            : 
    2484                 :            : /* Helper that returns an identifier for an appended extension to the
    2485                 :            :    current un-mangled function name.  */
    2486                 :            : 
    2487                 :            : static tree
    2488                 :       2349 : get_fn_local_identifier (tree orig, const char *append)
    2489                 :            : {
    2490                 :            :   /* Figure out the bits we need to generate names for the outlined things
    2491                 :            :      For consistency, this needs to behave the same way as
    2492                 :            :      ASM_FORMAT_PRIVATE_NAME does. */
    2493                 :       2349 :   tree nm = DECL_NAME (orig);
    2494                 :       2349 :   const char *sep, *pfx = "";
    2495                 :            : #ifndef NO_DOT_IN_LABEL
    2496                 :       2349 :   sep = ".";
    2497                 :            : #else
    2498                 :            : #ifndef NO_DOLLAR_IN_LABEL
    2499                 :            :   sep = "$";
    2500                 :            : #else
    2501                 :            :   sep = "_";
    2502                 :            :   pfx = "__";
    2503                 :            : #endif
    2504                 :            : #endif
    2505                 :            : 
    2506                 :       2349 :   char *an;
    2507                 :       2349 :   if (DECL_ASSEMBLER_NAME (orig))
    2508                 :       2349 :     an = ACONCAT ((IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (orig)), sep, append,
    2509                 :            :                    (char *) 0));
    2510                 :          0 :   else if (DECL_USE_TEMPLATE (orig) && DECL_TEMPLATE_INFO (orig)
    2511                 :          0 :            && DECL_TI_ARGS (orig))
    2512                 :            :     {
    2513                 :          0 :       tree tpl_args = DECL_TI_ARGS (orig);
    2514                 :          0 :       an = ACONCAT ((pfx, IDENTIFIER_POINTER (nm), (char *) 0));
    2515                 :          0 :       for (int i = 0; i < TREE_VEC_LENGTH (tpl_args); ++i)
    2516                 :            :         {
    2517                 :          0 :           tree typ = DECL_NAME (TYPE_NAME (TREE_VEC_ELT (tpl_args, i)));
    2518                 :          0 :           an = ACONCAT ((an, sep, IDENTIFIER_POINTER (typ), (char *) 0));
    2519                 :            :         }
    2520                 :          0 :       an = ACONCAT ((an, sep, append, (char *) 0));
    2521                 :            :     }
    2522                 :            :   else
    2523                 :          0 :     an = ACONCAT ((pfx, IDENTIFIER_POINTER (nm), sep, append, (char *) 0));
    2524                 :            : 
    2525                 :       2349 :   return get_identifier (an);
    2526                 :            : }
    2527                 :            : 
    2528                 :            : static tree
    2529                 :       1567 : build_init_or_final_await (location_t loc, bool is_final)
    2530                 :            : {
    2531                 :       1567 :   tree suspend_alt = is_final ? coro_final_suspend_identifier
    2532                 :            :                               : coro_initial_suspend_identifier;
    2533                 :       1567 :   tree setup_meth = lookup_promise_method (current_function_decl, suspend_alt,
    2534                 :            :                                            loc, /*musthave=*/true);
    2535                 :       1567 :   if (!setup_meth || setup_meth == error_mark_node)
    2536                 :          0 :     return error_mark_node;
    2537                 :            : 
    2538                 :       1567 :   tree s_fn = NULL_TREE;
    2539                 :       3134 :   tree setup_call = build_new_method_call (
    2540                 :            :     get_coroutine_promise_proxy (current_function_decl), setup_meth, NULL,
    2541                 :            :     NULL_TREE, LOOKUP_NORMAL, &s_fn, tf_warning_or_error);
    2542                 :            : 
    2543                 :       1567 :   if (!s_fn || setup_call == error_mark_node)
    2544                 :          0 :     return error_mark_node;
    2545                 :            : 
    2546                 :            :   /* So build the co_await for this */
    2547                 :            :   /* For initial/final suspends the call is "a" per [expr.await] 3.2.  */
    2548                 :       2351 :   return build_co_await (loc, setup_call, (is_final ? FINAL_SUSPEND_POINT
    2549                 :       1567 :                                                     : INITIAL_SUSPEND_POINT));
    2550                 :            : }
    2551                 :            : 
    2552                 :            : /* Callback to record the essential data for each await point found in the
    2553                 :            :    function.  */
    2554                 :            : 
    2555                 :            : static bool
    2556                 :       2228 : register_await_info (tree await_expr, tree aw_type, tree aw_nam)
    2557                 :            : {
    2558                 :       2228 :   bool seen;
    2559                 :       2228 :   suspend_point_info &s
    2560                 :       2228 :     = suspend_points->get_or_insert (await_expr, &seen);
    2561                 :       2228 :   if (seen)
    2562                 :            :     {
    2563                 :          0 :       error_at (EXPR_LOCATION (await_expr), "duplicate info for %qE",
    2564                 :            :                 await_expr);
    2565                 :          0 :       return false;
    2566                 :            :     }
    2567                 :       2228 :   s.awaitable_type = aw_type;
    2568                 :       2228 :   s.await_field_id = aw_nam;
    2569                 :       2228 :   return true;
    2570                 :            : }
    2571                 :            : 
    2572                 :            : /* Small helper for the repetitive task of adding a new field to the coro
    2573                 :            :    frame type.  */
    2574                 :            : 
    2575                 :            : static tree
    2576                 :       8732 : coro_make_frame_entry (tree *field_list, const char *name, tree fld_type,
    2577                 :            :                        location_t loc)
    2578                 :            : {
    2579                 :       8732 :   tree id = get_identifier (name);
    2580                 :       8732 :   tree decl = build_decl (loc, FIELD_DECL, id, fld_type);
    2581                 :       8732 :   DECL_CHAIN (decl) = *field_list;
    2582                 :       8732 :   *field_list = decl;
    2583                 :       8732 :   return id;
    2584                 :            : }
    2585                 :            : 
    2586                 :        783 : struct susp_frame_data
    2587                 :            : {
    2588                 :            :   tree *field_list;
    2589                 :            :   tree handle_type;
    2590                 :            :   hash_set<tree> captured_temps;
    2591                 :            :   vec<tree, va_gc> *to_replace;
    2592                 :            :   vec<tree, va_gc> *block_stack;
    2593                 :            :   unsigned count;
    2594                 :            :   unsigned saw_awaits;
    2595                 :            :   bool captures_temporary;
    2596                 :            : };
    2597                 :            : 
    2598                 :            : /* Walk the sub-tree looking for call expressions that both capture
    2599                 :            :    references and have compiler-temporaries as parms.  */
    2600                 :            : 
    2601                 :            : static tree
    2602                 :       6303 : captures_temporary (tree *stmt, int *do_subtree, void *d)
    2603                 :            : {
    2604                 :            :   /* Stop recursing if we see an await expression, the subtrees
    2605                 :            :      of that will be handled when it is processed.  */
    2606                 :       6303 :   if (TREE_CODE (*stmt) == CO_AWAIT_EXPR || TREE_CODE (*stmt) == CO_YIELD_EXPR)
    2607                 :            :     {
    2608                 :         32 :       *do_subtree = 0;
    2609                 :         32 :       return NULL_TREE;
    2610                 :            :     }
    2611                 :            : 
    2612                 :            :   /* We're only interested in calls.  */
    2613                 :       6271 :   if (TREE_CODE (*stmt) != CALL_EXPR)
    2614                 :            :     return NULL_TREE;
    2615                 :            : 
    2616                 :            :   /* Does this call capture references?
    2617                 :            :      Strip the ADDRESS_EXPR to get the fn decl and inspect it.  */
    2618                 :        629 :   tree fn = TREE_OPERAND (CALL_EXPR_FN (*stmt), 0);
    2619                 :        629 :   bool is_meth = TREE_CODE (TREE_TYPE (fn)) == METHOD_TYPE;
    2620                 :        629 :   tree arg = TYPE_ARG_TYPES (TREE_TYPE (fn));
    2621                 :        629 :   unsigned offset = 3;
    2622                 :       1906 :   for (unsigned anum = 0; arg != NULL; arg = TREE_CHAIN (arg), anum++)
    2623                 :            :     {
    2624                 :       1277 :       tree parm_type = TREE_VALUE (arg);
    2625                 :       1277 :       if (anum == 0 && is_meth && INDIRECT_TYPE_P (parm_type))
    2626                 :            :         {
    2627                 :            :           /* Account for 'this' when the fn is a method.  Unless it
    2628                 :            :              belongs to a CTOR or DTOR.  */
    2629                 :       1224 :           if (DECL_CONSTRUCTOR_P (fn) || DECL_DESTRUCTOR_P (fn))
    2630                 :       1259 :             continue;
    2631                 :            :         }
    2632                 :        665 :       else if (!TYPE_REF_P (parm_type))
    2633                 :            :         /* If it's not a reference, we don't care.  */
    2634                 :        656 :         continue;
    2635                 :            : 
    2636                 :            :       /* Fetch the value presented to the fn.  */
    2637                 :         91 :       tree parm = TREE_OPERAND (*stmt, anum + offset);
    2638                 :            : 
    2639                 :        100 :       while (TREE_CODE (parm) == NOP_EXPR)
    2640                 :          9 :         parm = TREE_OPERAND (parm, 0);
    2641                 :            : 
    2642                 :            :       /* We only care if we're taking the addr of a temporary.  */
    2643                 :         91 :       if (TREE_CODE (parm) != ADDR_EXPR)
    2644                 :         27 :         continue;
    2645                 :            : 
    2646                 :         64 :       parm = TREE_OPERAND (parm, 0);
    2647                 :            : 
    2648                 :            :       /* In case of component_ref, we need to capture the object of base
    2649                 :            :          class as if it is temporary object.  There are two possibilities:
    2650                 :            :          (*base).field and base->field.  */
    2651                 :        145 :       while (TREE_CODE (parm) == COMPONENT_REF)
    2652                 :            :         {
    2653                 :         81 :           parm = TREE_OPERAND (parm, 0);
    2654                 :         81 :           if (TREE_CODE (parm) == INDIRECT_REF)
    2655                 :          9 :             parm = TREE_OPERAND (parm, 0);
    2656                 :         81 :           parm = STRIP_NOPS (parm);
    2657                 :            :         }
    2658                 :            : 
    2659                 :            :       /* This isn't a temporary.  */
    2660                 :         28 :       if ((TREE_CODE (parm) == VAR_DECL && !DECL_ARTIFICIAL (parm))
    2661                 :         36 :           || TREE_CODE (parm) == PARM_DECL
    2662                 :         82 :           || TREE_CODE (parm) == NON_LVALUE_EXPR)
    2663                 :         46 :         continue;
    2664                 :            : 
    2665                 :         18 :       if (TREE_CODE (parm) == TARGET_EXPR)
    2666                 :            :         {
    2667                 :            :           /* We're taking the address of a temporary and using it as a ref.  */
    2668                 :         18 :           tree tvar = TREE_OPERAND (parm, 0);
    2669                 :         18 :           gcc_checking_assert (DECL_ARTIFICIAL (tvar));
    2670                 :            : 
    2671                 :         18 :           susp_frame_data *data = (susp_frame_data *) d;
    2672                 :         18 :           data->captures_temporary = true;
    2673                 :            :           /* Record this one so we don't duplicate, and on the first
    2674                 :            :              occurrence note the target expr to be replaced.  */
    2675                 :         18 :           if (!data->captured_temps.add (tvar))
    2676                 :         18 :             vec_safe_push (data->to_replace, parm);
    2677                 :            :           /* Now see if the initializer contains any more cases.  */
    2678                 :         36 :           hash_set<tree> visited;
    2679                 :         18 :           tree res = cp_walk_tree (&TREE_OPERAND (parm, 1),
    2680                 :            :                                    captures_temporary, d, &visited);
    2681                 :         18 :           if (res)
    2682                 :          0 :             return res;
    2683                 :            :           /* Otherwise, we're done with sub-trees for this.  */
    2684                 :            :         }
    2685                 :          0 :       else if (TREE_CODE (parm) == CO_AWAIT_EXPR)
    2686                 :            :         {
    2687                 :            :           /* CO_AWAIT expressions behave in a similar manner to target
    2688                 :            :              expressions when the await_resume call is contained in one.  */
    2689                 :          0 :           tree awr = TREE_OPERAND (parm, 3); /* call vector.  */
    2690                 :          0 :           awr = TREE_VEC_ELT (awr, 2); /* resume call.  */
    2691                 :          0 :           if (TREE_CODE (awr) == TARGET_EXPR)
    2692                 :            :             {
    2693                 :          0 :               tree tvar = TREE_OPERAND (awr, 0);
    2694                 :          0 :               gcc_checking_assert (DECL_ARTIFICIAL (tvar));
    2695                 :            : 
    2696                 :          0 :               susp_frame_data *data = (susp_frame_data *) d;
    2697                 :          0 :               data->captures_temporary = true;
    2698                 :            :               /* Use this as a place-holder.  */
    2699                 :          0 :               if (!data->captured_temps.add (tvar))
    2700                 :          0 :                 vec_safe_push (data->to_replace, parm);
    2701                 :            :             }
    2702                 :            :         /* We will walk the sub-trees of this co_await separately.  */
    2703                 :            :         }
    2704                 :            :       else
    2705                 :          0 :         gcc_unreachable ();
    2706                 :            :     }
    2707                 :            :   /* As far as it's necessary, we've walked the subtrees of the call
    2708                 :            :      expr.  */
    2709                 :        629 :   *do_subtree = 0;
    2710                 :        629 :   return NULL_TREE;
    2711                 :            : }
    2712                 :            : 
    2713                 :            : /* If this is an await, then register it and decide on what coro
    2714                 :            :    frame storage is needed.
    2715                 :            :    If this is a co_yield (which embeds an await), drop the yield
    2716                 :            :    and record the await (the yield was kept for diagnostics only).  */
    2717                 :            : 
    2718                 :            : static tree
    2719                 :      40694 : register_awaits (tree *stmt, int *do_subtree ATTRIBUTE_UNUSED, void *d)
    2720                 :            : {
    2721                 :      40694 :   susp_frame_data *data = (susp_frame_data *) d;
    2722                 :            : 
    2723                 :      40694 :   if (TREE_CODE (*stmt) != CO_AWAIT_EXPR && TREE_CODE (*stmt) != CO_YIELD_EXPR)
    2724                 :            :     return NULL_TREE;
    2725                 :            : 
    2726                 :            :   /* co_yield is syntactic sugar, re-write it to co_await.  */
    2727                 :        662 :   tree aw_expr = *stmt;
    2728                 :        662 :   location_t aw_loc = EXPR_LOCATION (aw_expr); /* location of the co_xxxx.  */
    2729                 :        662 :   if (TREE_CODE (aw_expr) == CO_YIELD_EXPR)
    2730                 :            :     {
    2731                 :        213 :       aw_expr = TREE_OPERAND (aw_expr, 1);
    2732                 :        213 :       *stmt = aw_expr;
    2733                 :            :     }
    2734                 :            : 
    2735                 :            :   /* Count how many awaits full expression contains.  This is not the same
    2736                 :            :      as the counter used for the function-wide await point number.  */
    2737                 :        662 :   data->saw_awaits++;
    2738                 :            : 
    2739                 :            :   /* If the awaitable is a parm or a local variable, then we already have
    2740                 :            :      a frame copy, so don't make a new one.  */
    2741                 :        662 :   tree aw = TREE_OPERAND (aw_expr, 1);
    2742                 :        662 :   tree aw_field_type = TREE_TYPE (aw);
    2743                 :        662 :   tree aw_field_nam = NULL_TREE;
    2744                 :        662 :   if (INDIRECT_REF_P (aw))
    2745                 :         18 :     aw = TREE_OPERAND (aw, 0);
    2746                 :        662 :   if (TREE_CODE (aw) == PARM_DECL
    2747                 :       1297 :       || (TREE_CODE (aw) == VAR_DECL && !DECL_ARTIFICIAL (aw)))
    2748                 :            :     ; /* Don't make an additional copy.  */
    2749                 :            :   else
    2750                 :            :     {
    2751                 :            :       /* The required field has the same type as the proxy stored in the
    2752                 :            :          await expr.  */
    2753                 :        599 :       char *nam = xasprintf ("__aw_s.%d", data->count);
    2754                 :        599 :       aw_field_nam = coro_make_frame_entry (data->field_list, nam,
    2755                 :            :                                             aw_field_type, aw_loc);
    2756                 :        599 :       free (nam);
    2757                 :            :     }
    2758                 :            : 
    2759                 :        662 :   register_await_info (aw_expr, aw_field_type, aw_field_nam);
    2760                 :            : 
    2761                 :        662 :   data->count++; /* Each await suspend context is unique.  */
    2762                 :            : 
    2763                 :            :   /* We now need to know if to take special action on lifetime extension
    2764                 :            :      of temporaries captured by reference.  This can only happen if such
    2765                 :            :      a case appears in the initializer for the awaitable.  The callback
    2766                 :            :      records captured temporaries including subtrees of initializers.  */
    2767                 :        662 :   hash_set<tree> visited;
    2768                 :        662 :   tree res = cp_walk_tree (&TREE_OPERAND (aw_expr, 2), captures_temporary, d,
    2769                 :            :                            &visited);
    2770                 :        662 :   return res;
    2771                 :            : }
    2772                 :            : 
    2773                 :            : /* The gimplifier correctly extends the lifetime of temporaries captured
    2774                 :            :    by reference (per. [class.temporary] (6.9) "A temporary object bound
    2775                 :            :    to a reference parameter in a function call persists until the completion
    2776                 :            :    of the full-expression containing the call").  However, that is not
    2777                 :            :    sufficient to work across a suspension - and we need to promote such
    2778                 :            :    temporaries to be regular vars that will then get a coro frame slot.
    2779                 :            :    We don't want to incur the effort of checking for this unless we have
    2780                 :            :    an await expression in the current full expression.  */
    2781                 :            : 
    2782                 :            : static tree
    2783                 :       2286 : maybe_promote_captured_temps (tree *stmt, void *d)
    2784                 :            : {
    2785                 :       2286 :   susp_frame_data *awpts = (susp_frame_data *) d;
    2786                 :       2286 :   hash_set<tree> visited;
    2787                 :       2286 :   awpts->saw_awaits = 0;
    2788                 :            : 
    2789                 :            :   /* When register_awaits sees an await, it walks the initializer for
    2790                 :            :      that await looking for temporaries captured by reference and notes
    2791                 :            :      them in awpts->captured_temps.  We only need to take any action here
    2792                 :            :      if the statement contained any awaits, and any of those had temporaries
    2793                 :            :      captured by reference in the initializers for their class.  */
    2794                 :            : 
    2795                 :       2286 :   tree res = cp_walk_tree (stmt, register_awaits, d, &visited);
    2796                 :       2286 :   if (!res && awpts->saw_awaits > 0 && !awpts->captured_temps.is_empty ())
    2797                 :            :     {
    2798                 :         18 :       location_t sloc = EXPR_LOCATION (*stmt);
    2799                 :         18 :       tree aw_bind
    2800                 :         18 :         = build3_loc (sloc, BIND_EXPR, void_type_node, NULL, NULL, NULL);
    2801                 :         18 :       tree aw_statement_current;
    2802                 :         18 :       if (TREE_CODE (*stmt) == CLEANUP_POINT_EXPR)
    2803                 :         18 :         aw_statement_current = TREE_OPERAND (*stmt, 0);
    2804                 :            :       else
    2805                 :          0 :         aw_statement_current = *stmt;
    2806                 :            :       /* Collected the scope vars we need move the temps to regular. */
    2807                 :         18 :       tree aw_bind_body = push_stmt_list ();
    2808                 :         18 :       tree varlist = NULL_TREE;
    2809                 :         18 :       int vnum = -1;
    2810                 :         36 :       while (!awpts->to_replace->is_empty ())
    2811                 :            :         {
    2812                 :         18 :           size_t bufsize = sizeof ("__aw_.tmp.") + 20;
    2813                 :         18 :           char *buf = (char *) alloca (bufsize);
    2814                 :         18 :           snprintf (buf, bufsize, "__aw_%d.tmp.%d", awpts->count, ++vnum);
    2815                 :         18 :           tree to_replace = awpts->to_replace->pop ();
    2816                 :         18 :           tree orig_temp;
    2817                 :         18 :           if (TREE_CODE (to_replace) == CO_AWAIT_EXPR)
    2818                 :            :             {
    2819                 :          0 :               orig_temp = TREE_OPERAND (to_replace, 3);
    2820                 :          0 :               orig_temp = TREE_VEC_ELT (orig_temp, 2);
    2821                 :          0 :               orig_temp = TREE_OPERAND (orig_temp, 0);
    2822                 :            :             }
    2823                 :            :           else
    2824                 :         18 :             orig_temp = TREE_OPERAND (to_replace, 0);
    2825                 :            : 
    2826                 :         18 :           tree var_type = TREE_TYPE (orig_temp);
    2827                 :         18 :           gcc_assert (same_type_p (TREE_TYPE (to_replace), var_type));
    2828                 :         18 :           tree newvar
    2829                 :         18 :             = build_lang_decl (VAR_DECL, get_identifier (buf), var_type);
    2830                 :         18 :           DECL_CONTEXT (newvar) = DECL_CONTEXT (orig_temp);
    2831                 :         18 :           if (DECL_SOURCE_LOCATION (orig_temp))
    2832                 :         18 :             sloc = DECL_SOURCE_LOCATION (orig_temp);
    2833                 :         18 :           DECL_SOURCE_LOCATION (newvar) = sloc;
    2834                 :         18 :           DECL_CHAIN (newvar) = varlist;
    2835                 :         18 :           varlist = newvar;
    2836                 :         18 :           tree stmt
    2837                 :         18 :             = build2_loc (sloc, INIT_EXPR, var_type, newvar, to_replace);
    2838                 :         18 :           stmt = coro_build_cvt_void_expr_stmt (stmt, sloc);
    2839                 :         18 :           add_stmt (stmt);
    2840                 :         18 :           proxy_replace pr = {to_replace, newvar};
    2841                 :            :           /* Replace all instances of that temp in the original expr.  */
    2842                 :         18 :           cp_walk_tree (&aw_statement_current, replace_proxy, &pr, NULL);
    2843                 :            :         }
    2844                 :            :       /* What's left should be the original statement with any temporaries
    2845                 :            :          broken out.  */
    2846                 :         18 :       add_stmt (aw_statement_current);
    2847                 :         18 :       BIND_EXPR_BODY (aw_bind) = pop_stmt_list (aw_bind_body);
    2848                 :         18 :       awpts->captured_temps.empty ();
    2849                 :            : 
    2850                 :         18 :       BIND_EXPR_VARS (aw_bind) = nreverse (varlist);
    2851                 :         18 :       tree b_block = make_node (BLOCK);
    2852                 :         18 :       if (!awpts->block_stack->is_empty ())
    2853                 :            :         {
    2854                 :         18 :           tree s_block = awpts->block_stack->last ();
    2855                 :         18 :           if (s_block)
    2856                 :            :             {
    2857                 :         18 :               BLOCK_SUPERCONTEXT (b_block) = s_block;
    2858                 :         18 :               BLOCK_CHAIN (b_block) = BLOCK_SUBBLOCKS (s_block);
    2859                 :         18 :               BLOCK_SUBBLOCKS (s_block) = b_block;
    2860                 :            :             }
    2861                 :            :         }
    2862                 :         18 :       BIND_EXPR_BLOCK (aw_bind) = b_block;
    2863                 :            : 
    2864                 :         18 :       *stmt = aw_bind;
    2865                 :            :     }
    2866                 :       2286 :   return res;
    2867                 :            : }
    2868                 :            : 
    2869                 :            : static tree
    2870                 :       4734 : await_statement_walker (tree *stmt, int *do_subtree, void *d)
    2871                 :            : {
    2872                 :       4734 :   tree res = NULL_TREE;
    2873                 :       4734 :   susp_frame_data *awpts = (susp_frame_data *) d;
    2874                 :            : 
    2875                 :            :   /* We might need to insert a new bind expression, and want to link it
    2876                 :            :      into the correct scope, so keep a note of the current block scope.  */
    2877                 :       4734 :   if (TREE_CODE (*stmt) == BIND_EXPR)
    2878                 :            :     {
    2879                 :        530 :       tree *body = &BIND_EXPR_BODY (*stmt);
    2880                 :        530 :       tree blk = BIND_EXPR_BLOCK (*stmt);
    2881                 :        530 :       vec_safe_push (awpts->block_stack, blk);
    2882                 :            : 
    2883                 :        530 :       if (TREE_CODE (*body) == STATEMENT_LIST)
    2884                 :            :         {
    2885                 :        430 :           tree_stmt_iterator i;
    2886                 :       1939 :           for (i = tsi_start (*body); !tsi_end_p (i); tsi_next (&i))
    2887                 :            :             {
    2888                 :       1509 :               tree *new_stmt = tsi_stmt_ptr (i);
    2889                 :       1509 :               if (STATEMENT_CLASS_P (*new_stmt) || !EXPR_P (*new_stmt)
    2890                 :        891 :                   || TREE_CODE (*new_stmt) == BIND_EXPR)
    2891                 :        692 :                 res = cp_walk_tree (new_stmt, await_statement_walker, d, NULL);
    2892                 :            :               else
    2893                 :        817 :                 res = maybe_promote_captured_temps (new_stmt, d);
    2894                 :       1509 :               if (res)
    2895                 :          0 :                 return res;
    2896                 :            :             }
    2897                 :        430 :           *do_subtree = 0; /* Done subtrees.  */
    2898                 :            :         }
    2899                 :        100 :       else if (!STATEMENT_CLASS_P (*body) && EXPR_P (*body)
    2900                 :         55 :                && TREE_CODE (*body) != BIND_EXPR)
    2901                 :            :         {
    2902                 :          7 :           res = maybe_promote_captured_temps (body, d);
    2903                 :          7 :           *do_subtree = 0; /* Done subtrees.  */
    2904                 :            :         }
    2905                 :        530 :       awpts->block_stack->pop ();
    2906                 :            :     }
    2907                 :       4204 :   else if (!STATEMENT_CLASS_P (*stmt) && EXPR_P (*stmt)
    2908                 :            :            && TREE_CODE (*stmt) != BIND_EXPR)
    2909                 :            :     {
    2910                 :       1462 :       res = maybe_promote_captured_temps (stmt, d);
    2911                 :       1462 :       *do_subtree = 0; /* Done subtrees.  */
    2912                 :            :     }
    2913                 :            :   /* If it wasn't a statement list, or a single statement, continue.  */
    2914                 :            :   return res;
    2915                 :            : }
    2916                 :            : 
    2917                 :            : /* For figuring out what param usage we have.  */
    2918                 :            : 
    2919                 :            : struct param_frame_data
    2920                 :            : {
    2921                 :            :   tree *field_list;
    2922                 :            :   hash_map<tree, param_info> *param_uses;
    2923                 :            :   hash_set<tree *> *visited;
    2924                 :            :   location_t loc;
    2925                 :            :   bool param_seen;
    2926                 :            : };
    2927                 :            : 
    2928                 :            : static tree
    2929                 :      75120 : register_param_uses (tree *stmt, int *do_subtree ATTRIBUTE_UNUSED, void *d)
    2930                 :            : {
    2931                 :      75120 :   param_frame_data *data = (param_frame_data *) d;
    2932                 :            : 
    2933                 :            :   /* For lambda closure content, we have to look specifically.  */
    2934                 :      75120 :   if (TREE_CODE (*stmt) == VAR_DECL && DECL_HAS_VALUE_EXPR_P (*stmt))
    2935                 :            :     {
    2936                 :        656 :       tree t = DECL_VALUE_EXPR (*stmt);
    2937                 :        656 :       return cp_walk_tree (&t, register_param_uses, d, NULL);
    2938                 :            :     }
    2939                 :            : 
    2940                 :      74464 :   if (TREE_CODE (*stmt) != PARM_DECL)
    2941                 :            :     return NULL_TREE;
    2942                 :            : 
    2943                 :            :   /* If we already saw the containing expression, then we're done.  */
    2944                 :       2493 :   if (data->visited->add (stmt))
    2945                 :            :     return NULL_TREE;
    2946                 :            : 
    2947                 :        828 :   bool existed;
    2948                 :        828 :   param_info &parm = data->param_uses->get_or_insert (*stmt, &existed);
    2949                 :        828 :   gcc_checking_assert (existed);
    2950                 :            : 
    2951                 :        828 :   if (!parm.body_uses)
    2952                 :            :     {
    2953                 :        436 :       vec_alloc (parm.body_uses, 4);
    2954                 :        436 :       parm.body_uses->quick_push (stmt);
    2955                 :        436 :       data->param_seen = true;
    2956                 :            :     }
    2957                 :            :   else
    2958                 :        392 :     parm.body_uses->safe_push (stmt);
    2959                 :            : 
    2960                 :            :   return NULL_TREE;
    2961                 :            : }
    2962                 :            : 
    2963                 :            : /* For figuring out what local variable usage we have.  */
    2964                 :            : 
    2965                 :            : struct local_vars_frame_data
    2966                 :            : {
    2967                 :            :   tree *field_list;
    2968                 :            :   hash_map<tree, local_var_info> *local_var_uses;
    2969                 :            :   unsigned int nest_depth, bind_indx;
    2970                 :            :   location_t loc;
    2971                 :            :   bool saw_capture;
    2972                 :            :   bool local_var_seen;
    2973                 :            : };
    2974                 :            : 
    2975                 :            : static tree
    2976                 :      98994 : register_local_var_uses (tree *stmt, int *do_subtree, void *d)
    2977                 :            : {
    2978                 :      98994 :   local_vars_frame_data *lvd = (local_vars_frame_data *) d;
    2979                 :            : 
    2980                 :            :   /* As we enter a bind expression - record the vars there and then recurse.
    2981                 :            :      As we exit drop the nest depth.
    2982                 :            :      The bind index is a growing count of how many bind indices we've seen.
    2983                 :            :      We build a space in the frame for each local var.  */
    2984                 :            : 
    2985                 :      98994 :   if (TREE_CODE (*stmt) == BIND_EXPR)
    2986                 :            :     {
    2987                 :        548 :       lvd->bind_indx++;
    2988                 :        548 :       lvd->nest_depth++;
    2989                 :        548 :       tree lvar;
    2990                 :       1162 :       for (lvar = BIND_EXPR_VARS (*stmt); lvar != NULL;
    2991                 :        614 :            lvar = DECL_CHAIN (lvar))
    2992                 :            :         {
    2993                 :        614 :           bool existed;
    2994                 :        614 :           local_var_info &local_var
    2995                 :        614 :             = lvd->local_var_uses->get_or_insert (lvar, &existed);
    2996                 :        614 :           gcc_checking_assert (!existed);
    2997                 :        614 :           local_var.def_loc = DECL_SOURCE_LOCATION (lvar);
    2998                 :        614 :           tree lvtype = TREE_TYPE (lvar);
    2999                 :        614 :           local_var.frame_type = lvtype;
    3000                 :        614 :           local_var.field_idx = local_var.field_id = NULL_TREE;
    3001                 :        614 :           lvd->local_var_seen = true;
    3002                 :            :           /* If this var is a lambda capture proxy, we want to leave it alone,
    3003                 :            :              and later rewrite the DECL_VALUE_EXPR to indirect through the
    3004                 :            :              frame copy of the pointer to the lambda closure object.  */
    3005                 :        614 :           local_var.is_lambda_capture = is_capture_proxy (lvar);
    3006                 :        614 :           if (local_var.is_lambda_capture)
    3007                 :         96 :             continue;
    3008                 :            : 
    3009                 :            :           /* Make names depth+index unique, so that we can support nested
    3010                 :            :              scopes with identically named locals.  */
    3011                 :        518 :           tree lvname = DECL_NAME (lvar);
    3012                 :        518 :           char *buf;
    3013                 :        518 :           if (lvname != NULL_TREE)
    3014                 :        510 :             buf = xasprintf ("__lv.%u.%u.%s", lvd->bind_indx, lvd->nest_depth,
    3015                 :        510 :                              IDENTIFIER_POINTER (lvname));
    3016                 :            :           else
    3017                 :          8 :             buf = xasprintf ("__lv.%u.%u.D%u", lvd->bind_indx, lvd->nest_depth,
    3018                 :          8 :                              DECL_UID (lvar));
    3019                 :            :           /* TODO: Figure out if we should build a local type that has any
    3020                 :            :              excess alignment or size from the original decl.  */
    3021                 :        518 :           local_var.field_id
    3022                 :        518 :             = coro_make_frame_entry (lvd->field_list, buf, lvtype, lvd->loc);
    3023                 :        518 :           free (buf);
    3024                 :            :           /* We don't walk any of the local var sub-trees, they won't contain
    3025                 :            :              any bind exprs.  */
    3026                 :            :         }
    3027                 :        548 :       cp_walk_tree (&BIND_EXPR_BODY (*stmt), register_local_var_uses, d, NULL);
    3028                 :        548 :       *do_subtree = 0; /* We've done this.  */
    3029                 :        548 :       lvd->nest_depth--;
    3030                 :            :     }
    3031                 :      98994 :   return NULL_TREE;
    3032                 :            : }
    3033                 :            : 
    3034                 :            : /* Build, return FUNCTION_DECL node with its coroutine frame pointer argument
    3035                 :            :    for either actor or destroy functions.  */
    3036                 :            : 
    3037                 :            : static tree
    3038                 :       1566 : act_des_fn (tree orig, tree fn_type, tree coro_frame_ptr, const char* name)
    3039                 :            : {
    3040                 :       1566 :   tree fn_name = get_fn_local_identifier (orig, name);
    3041                 :       1566 :   tree fn = build_lang_decl (FUNCTION_DECL, fn_name, fn_type);
    3042                 :       1566 :   DECL_CONTEXT (fn) = DECL_CONTEXT (orig);
    3043                 :       1566 :   DECL_INITIAL (fn) = error_mark_node;
    3044                 :       1566 :   tree id = get_identifier ("frame_ptr");
    3045                 :       1566 :   tree fp = build_lang_decl (PARM_DECL, id, coro_frame_ptr);
    3046                 :       1566 :   DECL_CONTEXT (fp) = fn;
    3047                 :       1566 :   DECL_ARG_TYPE (fp) = type_passed_as (coro_frame_ptr);
    3048                 :       1566 :   DECL_ARGUMENTS (fn) = fp;
    3049                 :       1566 :   return fn;
    3050                 :            : }
    3051                 :            : 
    3052                 :            : /* Here we:
    3053                 :            :    a) Check that the function and promise type are valid for a
    3054                 :            :       coroutine.
    3055                 :            :    b) Carry out the initial morph to create the skeleton of the
    3056                 :            :       coroutine ramp function and the rewritten body.
    3057                 :            : 
    3058                 :            :   Assumptions.
    3059                 :            : 
    3060                 :            :   1. We only hit this code once all dependencies are resolved.
    3061                 :            :   2. The function body will be either a bind expr or a statement list
    3062                 :            :   3. That cfun and current_function_decl are valid for the case we're
    3063                 :            :      expanding.
    3064                 :            :   4. 'input_location' will be of the final brace for the function.
    3065                 :            : 
    3066                 :            :  We do something like this:
    3067                 :            :  declare a dummy coro frame.
    3068                 :            :  struct _R_frame {
    3069                 :            :   using handle_type = coro::coroutine_handle<coro1::promise_type>;
    3070                 :            :   void (*__resume)(_R_frame *);
    3071                 :            :   void (*__destroy)(_R_frame *);
    3072                 :            :   coro1::promise_type __p;
    3073                 :            :   bool frame_needs_free; free the coro frame mem if set.
    3074                 :            :   bool i_a_r_c; [dcl.fct.def.coroutine] / 5.3
    3075                 :            :   short __resume_at;
    3076                 :            :   handle_type self_handle;
    3077                 :            :   (maybe) parameter copies.
    3078                 :            :   coro1::suspend_never_prt __is;
    3079                 :            :   coro1::suspend_always_prt __fs;
    3080                 :            :   (maybe) local variables saved
    3081                 :            :   (maybe) trailing space.
    3082                 :            :  };  */
    3083                 :            : 
    3084                 :            : bool
    3085                 :        793 : morph_fn_to_coro (tree orig, tree *resumer, tree *destroyer)
    3086                 :            : {
    3087                 :        793 :   gcc_checking_assert (orig && TREE_CODE (orig) == FUNCTION_DECL);
    3088                 :            : 
    3089                 :        793 :   if (!coro_function_valid_p (orig))
    3090                 :            :     return false;
    3091                 :            : 
    3092                 :            :   /* The ramp function does return a value.  */
    3093                 :        786 :   current_function_returns_value = 1;
    3094                 :            : 
    3095                 :            :   /* We can't validly get here with an empty statement list, since there's no
    3096                 :            :      way for the FE to decide it's a coroutine in the absence of any code.  */
    3097                 :        786 :   tree fnbody = pop_stmt_list (DECL_SAVED_TREE (orig));
    3098                 :        786 :   if (fnbody == NULL_TREE)
    3099                 :            :     return false;
    3100                 :            : 
    3101                 :            :   /* We don't have the locus of the opening brace - it's filled in later (and
    3102                 :            :      there doesn't really seem to be any easy way to get at it).
    3103                 :            :      The closing brace is assumed to be input_location.  */
    3104                 :        786 :   location_t fn_start = DECL_SOURCE_LOCATION (orig);
    3105                 :        786 :   gcc_rich_location fn_start_loc (fn_start);
    3106                 :            : 
    3107                 :            :   /* Initial processing of the function-body.
    3108                 :            :      If we have no expressions or just an error then punt.  */
    3109                 :        786 :   tree body_start = expr_first (fnbody);
    3110                 :        786 :   if (body_start == NULL_TREE || body_start == error_mark_node)
    3111                 :            :     {
    3112                 :          2 :       DECL_SAVED_TREE (orig) = push_stmt_list ();
    3113                 :          2 :       append_to_statement_list (DECL_SAVED_TREE (orig), &fnbody);
    3114                 :          2 :       return false;
    3115                 :            :     }
    3116                 :            : 
    3117                 :            :   /* So, we've tied off the original body.  Now start the replacement.
    3118                 :            :      If we encounter a fatal error we might return a now-empty body.
    3119                 :            :      TODO: determine if it would help to restore the original.
    3120                 :            :            determine if looking for more errors in coro_function_valid_p()
    3121                 :            :            and stashing types is a better solution.  */
    3122                 :            : 
    3123                 :        784 :   tree newbody = push_stmt_list ();
    3124                 :        784 :   DECL_SAVED_TREE (orig) = newbody;
    3125                 :            : 
    3126                 :            :   /* If our original body is noexcept, then that's what we apply to our
    3127                 :            :      generated functions.  Remember that we're NOEXCEPT and fish out the
    3128                 :            :      contained list (we tied off to the top level already).  */
    3129                 :        784 :   bool is_noexcept = TREE_CODE (body_start) == MUST_NOT_THROW_EXPR;
    3130                 :        784 :   if (is_noexcept)
    3131                 :            :     {
    3132                 :            :       /* Simplified abstract from begin_eh_spec_block, since we already
    3133                 :            :          know the outcome.  */
    3134                 :        358 :       fnbody = TREE_OPERAND (body_start, 0); /* Stash the original...  */
    3135                 :        358 :       add_stmt (body_start);                 /* ... and start the new.  */
    3136                 :        358 :       TREE_OPERAND (body_start, 0) = push_stmt_list ();
    3137                 :            :     }
    3138                 :            : 
    3139                 :            :   /* Create the coro frame type, as far as it can be known at this stage.
    3140                 :            :      1. Types we already know.  */
    3141                 :            : 
    3142                 :        784 :   tree fn_return_type = TREE_TYPE (TREE_TYPE (orig));
    3143                 :        784 :   gcc_assert (!VOID_TYPE_P (fn_return_type));
    3144                 :        784 :   tree handle_type = get_coroutine_handle_type (orig);
    3145                 :        784 :   tree promise_type = get_coroutine_promise_type (orig);
    3146                 :            : 
    3147                 :            :   /* 2. Types we need to define or look up.  */
    3148                 :            : 
    3149                 :            :   /* We need to know, and inspect, each suspend point in the function
    3150                 :            :      in several places.  It's convenient to place this map out of line
    3151                 :            :      since it's used from tree walk callbacks.  */
    3152                 :        784 :   suspend_points = new hash_map<tree, suspend_point_info>;
    3153                 :            : 
    3154                 :            :   /* Initial and final suspend types are special in that the co_awaits for
    3155                 :            :      them are synthetic.  We need to find the type for each awaiter from
    3156                 :            :      the coroutine promise.  */
    3157                 :        784 :   tree initial_await = build_init_or_final_await (fn_start, false);
    3158                 :        784 :   if (initial_await == error_mark_node)
    3159                 :            :     return false;
    3160                 :            :   /* The type of the frame var for this is the type of its temp proxy.  */
    3161                 :        783 :   tree initial_suspend_type = TREE_TYPE (TREE_OPERAND (initial_await, 1));
    3162                 :            : 
    3163                 :        783 :   tree final_await = build_init_or_final_await (fn_start, true);
    3164                 :        783 :   if (final_await == error_mark_node)
    3165                 :            :     return false;
    3166                 :            : 
    3167                 :            :   /* The type of the frame var for this is the type of its temp proxy.  */
    3168                 :        783 :   tree final_suspend_type = TREE_TYPE (TREE_OPERAND (final_await, 1));
    3169                 :            : 
    3170                 :        783 :   tree fr_name = get_fn_local_identifier (orig, "frame");
    3171                 :        783 :   tree coro_frame_type = xref_tag (record_type, fr_name, ts_current, false);
    3172                 :        783 :   DECL_CONTEXT (TYPE_NAME (coro_frame_type)) = current_scope ();
    3173                 :        783 :   tree coro_frame_ptr = build_pointer_type (coro_frame_type);
    3174                 :        783 :   tree act_des_fn_type
    3175                 :        783 :     = build_function_type_list (void_type_node, coro_frame_ptr, NULL_TREE);
    3176                 :        783 :   tree act_des_fn_ptr = build_pointer_type (act_des_fn_type);
    3177                 :            : 
    3178                 :            :   /* Declare the actor and destroyer function.  */
    3179                 :        783 :   tree actor = act_des_fn (orig, act_des_fn_type, coro_frame_ptr, "actor");
    3180                 :        783 :   tree destroy = act_des_fn (orig, act_des_fn_type, coro_frame_ptr, "destroy");
    3181                 :            : 
    3182                 :            :   /* Build our dummy coro frame layout.  */
    3183                 :        783 :   coro_frame_type = begin_class_definition (coro_frame_type);
    3184                 :            : 
    3185                 :        783 :   tree field_list = NULL_TREE;
    3186                 :        783 :   tree resume_name
    3187                 :        783 :     = coro_make_frame_entry (&field_list, "__resume", act_des_fn_ptr, fn_start);
    3188                 :        783 :   tree destroy_name = coro_make_frame_entry (&field_list, "__destroy",
    3189                 :            :                                              act_des_fn_ptr, fn_start);
    3190                 :        783 :   tree promise_name
    3191                 :        783 :     = coro_make_frame_entry (&field_list, "__p", promise_type, fn_start);
    3192                 :        783 :   tree fnf_name = coro_make_frame_entry (&field_list, "__frame_needs_free",
    3193                 :            :                                          boolean_type_node, fn_start);
    3194                 :        783 :   tree iarc_name = coro_make_frame_entry (&field_list, "__i_a_r_c",
    3195                 :            :                                          boolean_type_node, fn_start);
    3196                 :        783 :   tree resume_idx_name
    3197                 :        783 :     = coro_make_frame_entry (&field_list, "__resume_at",
    3198                 :            :                              short_unsigned_type_node, fn_start);
    3199                 :            : 
    3200                 :            :   /* We need a handle to this coroutine, which is passed to every
    3201                 :            :      await_suspend().  There's no point in creating it over and over.  */
    3202                 :        783 :   (void) coro_make_frame_entry (&field_list, "__self_h", handle_type, fn_start);
    3203                 :            : 
    3204                 :            :   /* Now add in fields for function params (if there are any).
    3205                 :            :      We do not attempt elision of copies at this stage, we do analyse the
    3206                 :            :      uses and build worklists to replace those when the state machine is
    3207                 :            :      lowered.  */
    3208                 :            : 
    3209                 :        783 :   hash_map<tree, param_info> *param_uses = NULL;
    3210                 :        783 :   if (DECL_ARGUMENTS (orig))
    3211                 :            :     {
    3212                 :            :       /* Build a hash map with an entry for each param.
    3213                 :            :           The key is the param tree.
    3214                 :            :           Then we have an entry for the frame field name.
    3215                 :            :           Then a cache for the field ref when we come to use it.
    3216                 :            :           Then a tree list of the uses.
    3217                 :            :           The second two entries start out empty - and only get populated
    3218                 :            :           when we see uses.  */
    3219                 :        404 :       param_uses = new hash_map<tree, param_info>;
    3220                 :            : 
    3221                 :        972 :       for (tree arg = DECL_ARGUMENTS (orig); arg != NULL;
    3222                 :        568 :            arg = DECL_CHAIN (arg))
    3223                 :            :         {
    3224                 :        568 :           bool existed;
    3225                 :        568 :           param_info &parm = param_uses->get_or_insert (arg, &existed);
    3226                 :        568 :           gcc_checking_assert (!existed);
    3227                 :        568 :           parm.body_uses = NULL;
    3228                 :        568 :           tree actual_type = TREE_TYPE (arg);
    3229                 :        568 :           actual_type = complete_type_or_else (actual_type, orig);
    3230                 :        568 :           if (actual_type == NULL_TREE)
    3231                 :          0 :             actual_type = error_mark_node;
    3232                 :        568 :           parm.orig_type = actual_type;
    3233                 :        568 :           parm.by_ref = parm.rv_ref = parm.pt_ref = false;
    3234                 :        568 :           if (TREE_CODE (actual_type) == REFERENCE_TYPE
    3235                 :        568 :               && TYPE_REF_IS_RVALUE (DECL_ARG_TYPE (arg)))
    3236                 :            :             {
    3237                 :         26 :               parm.rv_ref = true;
    3238                 :         26 :               actual_type = TREE_TYPE (actual_type);
    3239                 :         26 :               parm.frame_type = actual_type;
    3240                 :            :             }
    3241                 :        542 :           else if (TREE_CODE (actual_type) == REFERENCE_TYPE)
    3242                 :            :             {
    3243                 :            :               /* If the user passes by reference, then we will save the
    3244                 :            :                  pointer to the original.  As noted in
    3245                 :            :                  [dcl.fct.def.coroutine] / 13, if the lifetime of the
    3246                 :            :                  referenced item ends and then the coroutine is resumed,
    3247                 :            :                  we have UB; well, the user asked for it.  */
    3248                 :         51 :               actual_type = build_pointer_type (TREE_TYPE (actual_type));
    3249                 :         51 :               parm.frame_type = actual_type;
    3250                 :         51 :               parm.pt_ref = true;
    3251                 :            :             }
    3252                 :        491 :           else if (TYPE_REF_P (DECL_ARG_TYPE (arg)))
    3253                 :            :             {
    3254                 :         35 :               parm.by_ref = true;
    3255                 :         35 :               parm.frame_type = actual_type;
    3256                 :            :             }
    3257                 :            :           else
    3258                 :        456 :             parm.frame_type = actual_type;
    3259                 :            : 
    3260                 :        568 :           parm.trivial_dtor = TYPE_HAS_TRIVIAL_DESTRUCTOR (parm.frame_type);
    3261                 :        568 :           tree pname = DECL_NAME (arg);
    3262                 :        568 :           char *buf = xasprintf ("__parm.%s", IDENTIFIER_POINTER (pname));
    3263                 :       1136 :           parm.field_id = coro_make_frame_entry
    3264                 :        568 :             (&field_list, buf, actual_type, DECL_SOURCE_LOCATION (arg));
    3265                 :        568 :           free (buf);
    3266                 :            :         }
    3267                 :            : 
    3268                 :            :       /* We want to record every instance of param's use, so don't include
    3269                 :            :          a 'visited' hash_set on the tree walk, but only record a containing
    3270                 :            :          expression once.  */
    3271                 :        808 :       hash_set<tree *> visited;
    3272                 :        404 :       param_frame_data param_data
    3273                 :        404 :         = {&field_list, param_uses, &visited, fn_start, false};
    3274                 :        404 :       cp_walk_tree (&fnbody, register_param_uses, &param_data, NULL);
    3275                 :            :     }
    3276                 :            : 
    3277                 :            :   /* Initial suspend is mandated.  */
    3278                 :        783 :   tree init_susp_name = coro_make_frame_entry (&field_list, "__aw_s.is",
    3279                 :            :                                                initial_suspend_type, fn_start);
    3280                 :            : 
    3281                 :        783 :   register_await_info (initial_await, initial_suspend_type, init_susp_name);
    3282                 :            : 
    3283                 :            :   /* Now insert the data for any body await points, at this time we also need
    3284                 :            :      to promote any temporaries that are captured by reference (to regular
    3285                 :            :      vars) they will get added to the coro frame along with other locals.  */
    3286                 :        783 :   susp_frame_data body_aw_points
    3287                 :       1569 :     = {&field_list, handle_type, hash_set<tree> (), NULL, NULL, 0, 0, false};
    3288                 :        783 :   body_aw_points.to_replace = make_tree_vector ();
    3289                 :        783 :   body_aw_points.block_stack = make_tree_vector ();
    3290                 :        783 :   cp_walk_tree (&fnbody, await_statement_walker, &body_aw_points, NULL);
    3291                 :            : 
    3292                 :            :   /* Final suspend is mandated.  */
    3293                 :        783 :   tree fin_susp_name = coro_make_frame_entry (&field_list, "__aw_s.fs",
    3294                 :            :                                               final_suspend_type, fn_start);
    3295                 :            : 
    3296                 :        783 :   register_await_info (final_await, final_suspend_type, fin_susp_name);
    3297                 :            : 
    3298                 :            :   /* 4. Now make space for local vars, this is conservative again, and we
    3299                 :            :      would expect to delete unused entries later.  */
    3300                 :       1566 :   hash_map<tree, local_var_info> local_var_uses;
    3301                 :        783 :   local_vars_frame_data local_vars_data
    3302                 :        783 :     = {&field_list, &local_var_uses, 0, 0, fn_start, false, false};
    3303                 :        783 :   cp_walk_tree (&fnbody, register_local_var_uses, &local_vars_data, NULL);
    3304                 :            : 
    3305                 :            :   /* Tie off the struct for now, so that we can build offsets to the
    3306                 :            :      known entries.  */
    3307                 :        783 :   TYPE_FIELDS (coro_frame_type) = field_list;
    3308                 :        783 :   TYPE_BINFO (coro_frame_type) = make_tree_binfo (0);
    3309                 :        783 :   BINFO_OFFSET (TYPE_BINFO (coro_frame_type)) = size_zero_node;
    3310                 :        783 :   BINFO_TYPE (TYPE_BINFO (coro_frame_type)) = coro_frame_type;
    3311                 :            : 
    3312                 :        783 :   coro_frame_type = finish_struct (coro_frame_type, NULL_TREE);
    3313                 :            : 
    3314                 :            :   /* Ramp: */
    3315                 :            :   /* Now build the ramp function pieces.  */
    3316                 :        783 :   tree ramp_bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
    3317                 :        783 :   add_stmt (ramp_bind);
    3318                 :        783 :   tree ramp_body = push_stmt_list ();
    3319                 :        783 :   tree empty_list = build_empty_stmt (fn_start);
    3320                 :            : 
    3321                 :        783 :   tree coro_fp = build_lang_decl (VAR_DECL, get_identifier ("coro.frameptr"),
    3322                 :            :                                   coro_frame_ptr);
    3323                 :        783 :   tree varlist = coro_fp;
    3324                 :            : 
    3325                 :            :   /* Collected the scope vars we need ... only one for now. */
    3326                 :        783 :   BIND_EXPR_VARS (ramp_bind) = nreverse (varlist);
    3327                 :            : 
    3328                 :            :   /* We're now going to create a new top level scope block for the ramp
    3329                 :            :      function.  */
    3330                 :        783 :   tree top_block = make_node (BLOCK);
    3331                 :            : 
    3332                 :        783 :   BIND_EXPR_BLOCK (ramp_bind) = top_block;
    3333                 :        783 :   BLOCK_VARS (top_block) = BIND_EXPR_VARS (ramp_bind);
    3334                 :        783 :   BLOCK_SUBBLOCKS (top_block) = NULL_TREE;
    3335                 :            : 
    3336                 :            :   /* The decl_expr for the coro frame pointer, initialize to zero so that we
    3337                 :            :      can pass it to the IFN_CO_FRAME (since there's no way to pass a type,
    3338                 :            :      directly apparently).  This avoids a "used uninitialized" warning.  */
    3339                 :        783 :   tree r = build_stmt (fn_start, DECL_EXPR, coro_fp);
    3340                 :        783 :   tree zeroinit = build1 (CONVERT_EXPR, coro_frame_ptr, integer_zero_node);
    3341                 :        783 :   r = build2 (INIT_EXPR, TREE_TYPE (coro_fp), coro_fp, zeroinit);
    3342                 :        783 :   r = coro_build_cvt_void_expr_stmt (r, fn_start);
    3343                 :        783 :   add_stmt (r);
    3344                 :            : 
    3345                 :            :   /* The CO_FRAME internal function is a mechanism to allow the middle end
    3346                 :            :      to adjust the allocation in response to optimisations.  We provide the
    3347                 :            :      current conservative estimate of the frame size (as per the current)
    3348                 :            :      computed layout.  */
    3349                 :        783 :   tree frame_size = TYPE_SIZE_UNIT (coro_frame_type);
    3350                 :        783 :   tree resizeable
    3351                 :        783 :     = build_call_expr_internal_loc (fn_start, IFN_CO_FRAME, size_type_node, 2,
    3352                 :        783 :                                     frame_size, coro_fp);
    3353                 :            : 
    3354                 :            :   /* n4849 [dcl.fct.def.coroutine] / 10 (part1)
    3355                 :            :     The unqualified-id get_return_object_on_allocation_failure is looked up
    3356                 :            :     in the scope of the promise type by class member access lookup.  */
    3357                 :            : 
    3358                 :        783 :   tree grooaf_meth
    3359                 :        783 :     = lookup_promise_method (orig, coro_gro_on_allocation_fail_identifier,
    3360                 :            :                              fn_start, /*musthave=*/false);
    3361                 :            : 
    3362                 :        783 :   tree grooaf = NULL_TREE;
    3363                 :       1566 :   tree dummy_promise = build_dummy_object (get_coroutine_promise_type (orig));
    3364                 :            : 
    3365                 :            :   /* We don't require this, so lookup_promise_method can return NULL...  */
    3366                 :        783 :   if (grooaf_meth && BASELINK_P (grooaf_meth))
    3367                 :            :     {
    3368                 :            :       /* ... but, if the lookup succeeds, then the function must be
    3369                 :            :          usable.
    3370                 :            :          build_new_method_call () wants a valid pointer to (an empty)  args
    3371                 :            :          list in this case.  */
    3372                 :         17 :       vec<tree, va_gc> *args = make_tree_vector ();
    3373                 :         17 :       grooaf = build_new_method_call (dummy_promise, grooaf_meth, &args,
    3374                 :            :                                       NULL_TREE, LOOKUP_NORMAL, NULL,
    3375                 :            :                                       tf_warning_or_error);
    3376                 :         17 :       release_tree_vector (args);
    3377                 :            :     }
    3378                 :            : 
    3379                 :            :   /* Allocate the frame, this has several possibilities:
    3380                 :            :      n4849 [dcl.fct.def.coroutine] / 9 (part 1)
    3381                 :            :      The allocation function’s name is looked up in the scope of the promise
    3382                 :            :      type.  It's not a failure for it to be absent see part 4, below.  */
    3383                 :        783 :   tree nwname = ovl_op_identifier (false, NEW_EXPR);
    3384                 :        783 :   tree fns = lookup_promise_method (orig, nwname, fn_start,
    3385                 :            :                                     /*musthave=*/false);
    3386                 :        783 :   tree new_fn = NULL_TREE;
    3387                 :        783 :   if (fns && BASELINK_P (fns))
    3388                 :            :     {
    3389                 :            :       /* n4849 [dcl.fct.def.coroutine] / 9 (part 2)
    3390                 :            :         If the lookup finds an allocation function in the scope of the promise
    3391                 :            :         type, overload resolution is performed on a function call created by
    3392                 :            :         assembling an argument list.  The first argument is the amount of space
    3393                 :            :         requested, and has type std::size_t.  The succeeding arguments are
    3394                 :            :         those of the original function.  */
    3395                 :         34 :       vec<tree, va_gc> *args = make_tree_vector ();
    3396                 :         34 :       vec_safe_push (args, resizeable); /* Space needed.  */
    3397                 :         50 :       for (tree arg = DECL_ARGUMENTS (orig); arg != NULL;
    3398                 :         16 :            arg = DECL_CHAIN (arg))
    3399                 :         16 :         vec_safe_push (args, arg);
    3400                 :            : 
    3401                 :            :       /* We might need to check that the provided function is nothrow.  */
    3402                 :         34 :       tree func;
    3403                 :            :       /* Failure is OK for the first attempt.  */
    3404                 :         34 :       new_fn = build_new_method_call (dummy_promise, fns, &args, NULL,
    3405                 :            :                                       LOOKUP_NORMAL, &func, tf_none);
    3406                 :         34 :       release_tree_vector (args);
    3407                 :            : 
    3408                 :         34 :       if (!new_fn || new_fn == error_mark_node)
    3409                 :            :         {
    3410                 :            :           /* n4849 [dcl.fct.def.coroutine] / 9 (part 3)
    3411                 :            :             If no viable function is found, overload resolution is performed
    3412                 :            :             again on a function call created by passing just the amount of
    3413                 :            :             space required as an argument of type std::size_t.  */
    3414                 :          9 :           args = make_tree_vector ();
    3415                 :          9 :           vec_safe_push (args, resizeable); /* Space needed.  */
    3416                 :          9 :           new_fn = build_new_method_call (dummy_promise, fns, &args,
    3417                 :            :                                           NULL_TREE, LOOKUP_NORMAL, &func,
    3418                 :            :                                           tf_none);
    3419                 :          9 :           release_tree_vector (args);
    3420                 :            :         }
    3421                 :            : 
    3422                 :            :      /* However, if the initial lookup succeeded, then one of these two
    3423                 :            :         options must be available.  */
    3424                 :         34 :     if (!new_fn || new_fn == error_mark_node)
    3425                 :            :       {
    3426                 :          1 :         error_at (fn_start, "%qE is provided by %qT but is not usable with"
    3427                 :            :                   " the function signature %qD", nwname, promise_type, orig);
    3428                 :          1 :         new_fn = error_mark_node;
    3429                 :            :       }
    3430                 :         33 :     else if (grooaf && !TYPE_NOTHROW_P (TREE_TYPE (func)))
    3431                 :          1 :       error_at (fn_start, "%qE is provided by %qT but %qE is not marked"
    3432                 :         34 :                 " %<throw()%> or %<noexcept%>", grooaf, promise_type, nwname);
    3433                 :            :     }
    3434                 :            :   else
    3435                 :            :     {
    3436                 :            :       /* n4849 [dcl.fct.def.coroutine] / 9 (part 4)
    3437                 :            :          If this lookup fails, the allocation function’s name is looked up in
    3438                 :            :          the global scope.  */
    3439                 :            : 
    3440                 :        749 :       vec<tree, va_gc> *args;
    3441                 :            :       /* build_operator_new_call () will insert size needed as element 0 of
    3442                 :            :          this, and we might need to append the std::nothrow constant.  */
    3443                 :        749 :       vec_alloc (args, 2);
    3444                 :            : 
    3445                 :        749 :       if (grooaf)
    3446                 :            :         {
    3447                 :            :           /* n4849 [dcl.fct.def.coroutine] / 10 (part 2)
    3448                 :            :            If any declarations (of the get return on allocation fail) are
    3449                 :            :            found, then the result of a call to an allocation function used
    3450                 :            :            to obtain storage for the coroutine state is assumed to return
    3451                 :            :            nullptr if it fails to obtain storage and, if a global allocation
    3452                 :            :            function is selected, the ::operator new(size_t, nothrow_t) form
    3453                 :            :            is used.  The allocation function used in this case shall have a
    3454                 :            :            non-throwing noexcept-specification.  So we need std::nothrow.  */
    3455                 :          8 :           tree std_nt = lookup_qualified_name (std_node,
    3456                 :            :                                                get_identifier ("nothrow"),
    3457                 :          8 :                                                0, /*complain=*/true, false);
    3458                 :          8 :           vec_safe_push (args, std_nt);
    3459                 :            :         }
    3460                 :            : 
    3461                 :            :       /* If we get to this point, we must succeed in looking up the global
    3462                 :            :          operator new for the params provided.  Extract a simplified version
    3463                 :            :          of the machinery from build_operator_new_call.  This can update the
    3464                 :            :          frame size.  */
    3465                 :        749 :       tree cookie = NULL;
    3466                 :        749 :       new_fn = build_operator_new_call (nwname, &args, &frame_size, &cookie,
    3467                 :            :                                         /*align_arg=*/NULL,
    3468                 :            :                                         /*size_check=*/NULL, /*fn=*/NULL,
    3469                 :            :                                         tf_warning_or_error);
    3470                 :       1498 :       resizeable = build_call_expr_internal_loc
    3471                 :        749 :         (fn_start, IFN_CO_FRAME, size_type_node, 2, frame_size, coro_fp);
    3472                 :        749 :       CALL_EXPR_ARG (new_fn, 0) = resizeable;
    3473                 :            : 
    3474                 :        749 :       release_tree_vector (args);
    3475                 :            :     }
    3476                 :            : 
    3477                 :        783 :   tree allocated = build1 (CONVERT_EXPR, coro_frame_ptr, new_fn);
    3478                 :        783 :   r = build2 (INIT_EXPR, TREE_TYPE (coro_fp), coro_fp, allocated);
    3479                 :        783 :   r = coro_build_cvt_void_expr_stmt (r, fn_start);
    3480                 :        783 :   add_stmt (r);
    3481                 :            : 
    3482                 :            :   /* If the user provided a method to return an object on alloc fail, then
    3483                 :            :      check the returned pointer and call the func if it's null.
    3484                 :            :      Otherwise, no check, and we fail for noexcept/fno-exceptions cases.  */
    3485                 :            : 
    3486                 :        783 :   if (grooaf)
    3487                 :            :     {
    3488                 :            :       /* n4849 [dcl.fct.def.coroutine] / 10 (part 3)
    3489                 :            :          If the allocation function returns nullptr,the coroutine returns
    3490                 :            :          control to the caller of the coroutine and the return value is
    3491                 :            :          obtained by a call to T::get_return_object_on_allocation_failure(),
    3492                 :            :          where T is the promise type.  */
    3493                 :         17 :        tree cfra_label
    3494                 :         17 :         = create_named_label_with_ctx (fn_start, "coro.frame.active",
    3495                 :            :                                        current_scope ());
    3496                 :         17 :       tree early_ret_list = NULL;
    3497                 :            :       /* init the retval using the user's func.  */
    3498                 :         17 :       r = build2 (INIT_EXPR, TREE_TYPE (DECL_RESULT (orig)), DECL_RESULT (orig),
    3499                 :            :                   grooaf);
    3500                 :         17 :       r = coro_build_cvt_void_expr_stmt (r, fn_start);
    3501                 :         17 :       append_to_statement_list (r, &early_ret_list);
    3502                 :            :       /* We know it's the correct type.  */
    3503                 :         17 :       r = DECL_RESULT (orig);
    3504                 :         17 :       r = build_stmt (fn_start, RETURN_EXPR, r);
    3505                 :         17 :       TREE_NO_WARNING (r) |= 1;
    3506                 :         17 :       r = maybe_cleanup_point_expr_void (r);
    3507                 :         17 :       append_to_statement_list (r, &early_ret_list);
    3508                 :            : 
    3509                 :         17 :       tree goto_st = NULL;
    3510                 :         17 :       r = build1 (GOTO_EXPR, void_type_node, cfra_label);
    3511                 :         17 :       append_to_statement_list (r, &goto_st);
    3512                 :            : 
    3513                 :         17 :       tree ckk = build1 (CONVERT_EXPR, coro_frame_ptr, integer_zero_node);
    3514                 :         17 :       tree ckz = build2 (EQ_EXPR, boolean_type_node, coro_fp, ckk);
    3515                 :         17 :       r = build3 (COND_EXPR, void_type_node, ckz, early_ret_list, empty_list);
    3516                 :         17 :       add_stmt (r);
    3517                 :            : 
    3518                 :         17 :       cfra_label = build_stmt (fn_start, LABEL_EXPR, cfra_label);
    3519                 :         17 :       add_stmt (cfra_label);
    3520                 :            :     }
    3521                 :            : 
    3522                 :            :   /* deref the frame pointer, to use in member access code.  */
    3523                 :        783 :   tree deref_fp = build_x_arrow (fn_start, coro_fp, tf_warning_or_error);
    3524                 :            : 
    3525                 :            :   /* For now, once allocation has succeeded we always assume that this needs
    3526                 :            :      destruction, there's no impl. for frame allocation elision.  */
    3527                 :        783 :   tree fnf_m
    3528                 :        783 :     = lookup_member (coro_frame_type, fnf_name, 1, 0, tf_warning_or_error);
    3529                 :        783 :   tree fnf_x = build_class_member_access_expr (deref_fp, fnf_m, NULL_TREE,
    3530                 :            :                                                false, tf_warning_or_error);
    3531                 :        783 :   r = build2 (INIT_EXPR, boolean_type_node, fnf_x, boolean_true_node);
    3532                 :        783 :   r = coro_build_cvt_void_expr_stmt (r, fn_start);
    3533                 :        783 :   add_stmt (r);
    3534                 :            : 
    3535                 :            :   /* Put the resumer and destroyer functions in.  */
    3536                 :            : 
    3537                 :        783 :   tree actor_addr = build1 (ADDR_EXPR, act_des_fn_ptr, actor);
    3538                 :        783 :   tree resume_m
    3539                 :        783 :     = lookup_member (coro_frame_type, resume_name,
    3540                 :            :                      /*protect=*/1, /*want_type=*/0, tf_warning_or_error);
    3541                 :        783 :   tree resume_x = build_class_member_access_expr (deref_fp, resume_m, NULL_TREE,
    3542                 :            :                                                   false, tf_warning_or_error);
    3543                 :        783 :   r = build2_loc (fn_start, INIT_EXPR, act_des_fn_ptr, resume_x, actor_addr);
    3544                 :        783 :   r = coro_build_cvt_void_expr_stmt (r, fn_start);
    3545                 :        783 :   add_stmt (r);
    3546                 :            : 
    3547                 :        783 :   tree destroy_addr = build1 (ADDR_EXPR, act_des_fn_ptr, destroy);
    3548                 :        783 :   tree destroy_m
    3549                 :        783 :     = lookup_member (coro_frame_type, destroy_name,
    3550                 :            :                      /*protect=*/1, /*want_type=*/0, tf_warning_or_error);
    3551                 :        783 :   tree destroy_x
    3552                 :        783 :     = build_class_member_access_expr (deref_fp, destroy_m, NULL_TREE, false,
    3553                 :            :                                       tf_warning_or_error);
    3554                 :        783 :   r = build2_loc (fn_start, INIT_EXPR, act_des_fn_ptr, destroy_x, destroy_addr);
    3555                 :        783 :   r = coro_build_cvt_void_expr_stmt (r, fn_start);
    3556                 :        783 :   add_stmt (r);
    3557                 :            : 
    3558                 :            :   /* n4849 [dcl.fct.def.coroutine] /13
    3559                 :            :      When a coroutine is invoked, a copy is created for each coroutine
    3560                 :            :      parameter.  Each such copy is an object with automatic storage duration
    3561                 :            :      that is direct-initialized from an lvalue referring to the corresponding
    3562                 :            :      parameter if the parameter is an lvalue reference, and from an xvalue
    3563                 :            :      referring to it otherwise.  A reference to a parameter in the function-
    3564                 :            :      body of the coroutine and in the call to the coroutine promise
    3565                 :            :      constructor is replaced by a reference to its copy.  */
    3566                 :            : 
    3567                 :        783 :   vec<tree, va_gc> *promise_args = NULL; /* So that we can adjust refs.  */
    3568                 :            : 
    3569                 :            :   /* The initialization and destruction of each parameter copy occurs in the
    3570                 :            :      context of the called coroutine.  Initializations of parameter copies are
    3571                 :            :      sequenced before the call to the coroutine promise constructor and
    3572                 :            :      indeterminately sequenced with respect to each other.  The lifetime of
    3573                 :            :      parameter copies ends immediately after the lifetime of the coroutine
    3574                 :            :      promise object ends.  */
    3575                 :            : 
    3576                 :        783 :   vec<tree, va_gc> *param_dtor_list = NULL;
    3577                 :            : 
    3578                 :        783 :   if (DECL_ARGUMENTS (orig))
    3579                 :            :     {
    3580                 :        404 :       promise_args = make_tree_vector ();
    3581                 :        972 :       for (tree arg = DECL_ARGUMENTS (orig); arg != NULL;
    3582                 :        568 :            arg = DECL_CHAIN (arg))
    3583                 :            :         {
    3584                 :        568 :           bool existed;
    3585                 :        568 :           param_info &parm = param_uses->get_or_insert (arg, &existed);
    3586                 :            : 
    3587                 :        568 :           tree fld_ref = lookup_member (coro_frame_type, parm.field_id,
    3588                 :            :                                         /*protect=*/1, /*want_type=*/0,
    3589                 :            :                                         tf_warning_or_error);
    3590                 :        568 :           tree fld_idx
    3591                 :        568 :             = build_class_member_access_expr (deref_fp, fld_ref, NULL_TREE,
    3592                 :        568 :                                               false, tf_warning_or_error);
    3593                 :            : 
    3594                 :            :           /* Add this to the promise CTOR arguments list, accounting for
    3595                 :            :              refs.  */
    3596                 :        568 :           if (parm.by_ref)
    3597                 :         35 :             vec_safe_push (promise_args, fld_idx);
    3598                 :        533 :           else if (parm.rv_ref)
    3599                 :         26 :             vec_safe_push (promise_args, rvalue (fld_idx));
    3600                 :            :           else
    3601                 :        507 :             vec_safe_push (promise_args, arg);
    3602                 :            : 
    3603                 :        568 :           if (TYPE_NEEDS_CONSTRUCTING (parm.frame_type))
    3604                 :            :             {
    3605                 :         53 :               vec<tree, va_gc> *p_in;
    3606                 :         53 :               if (parm.by_ref
    3607                 :         35 :                   && classtype_has_non_deleted_move_ctor (parm.frame_type)
    3608                 :         88 :                   && !classtype_has_non_deleted_copy_ctor (parm.frame_type))
    3609                 :          0 :                 p_in = make_tree_vector_single (rvalue (arg));
    3610                 :            :               else
    3611                 :         53 :                 p_in = make_tree_vector_single (arg);
    3612                 :            :               /* Construct in place or move as relevant.  */
    3613                 :         53 :               r = build_special_member_call (fld_idx, complete_ctor_identifier,
    3614                 :            :                                              &p_in, parm.frame_type,
    3615                 :            :                                              LOOKUP_NORMAL,
    3616                 :            :                                              tf_warning_or_error);
    3617                 :         53 :               release_tree_vector (p_in);
    3618                 :            :             }
    3619                 :            :           else
    3620                 :            :             {
    3621                 :        515 :               if (parm.rv_ref)
    3622                 :          8 :                 r = convert_from_reference (arg);
    3623                 :        507 :               else if (!same_type_p (parm.frame_type, DECL_ARG_TYPE (arg)))
    3624                 :         51 :                 r = build1_loc (DECL_SOURCE_LOCATION (arg), CONVERT_EXPR,
    3625                 :            :                                 parm.frame_type, arg);
    3626                 :            :               else
    3627                 :        456 :                 r = arg;
    3628                 :        515 :               r = build_modify_expr (fn_start, fld_idx, parm.frame_type,
    3629                 :        515 :                                      INIT_EXPR, DECL_SOURCE_LOCATION (arg), r,
    3630                 :        515 :                                      TREE_TYPE (r));
    3631                 :            :             }
    3632                 :        568 :           r = coro_build_cvt_void_expr_stmt (r, fn_start);
    3633                 :        568 :           add_stmt (r);
    3634                 :        568 :           if (!parm.trivial_dtor)
    3635                 :            :             {
    3636                 :         45 :               if (param_dtor_list == NULL)
    3637                 :         27 :                 param_dtor_list = make_tree_vector ();
    3638                 :         45 :               vec_safe_push (param_dtor_list, parm.field_id);
    3639                 :            :             }
    3640                 :            :         }
    3641                 :            :     }
    3642                 :            : 
    3643                 :            :   /* Set up the promise.  */
    3644                 :        783 :   tree promise_m
    3645                 :        783 :     = lookup_member (coro_frame_type, promise_name,
    3646                 :            :                      /*protect=*/1, /*want_type=*/0, tf_warning_or_error);
    3647                 :            : 
    3648                 :        783 :   tree p = build_class_member_access_expr (deref_fp, promise_m, NULL_TREE,
    3649                 :            :                                            false, tf_warning_or_error);
    3650                 :            : 
    3651                 :        783 :   if (TYPE_NEEDS_CONSTRUCTING (promise_type))
    3652                 :            :     {
    3653                 :            :       /* Do a placement new constructor for the promise type (we never call
    3654                 :            :          the new operator, just the constructor on the object in place in the
    3655                 :            :          frame).
    3656                 :            : 
    3657                 :            :          First try to find a constructor with the same parameter list as the
    3658                 :            :          original function (if it has params), failing that find a constructor
    3659                 :            :          with no parameter list.  */
    3660                 :            : 
    3661                 :        738 :       if (DECL_ARGUMENTS (orig))
    3662                 :            :         {
    3663                 :        383 :           r = build_special_member_call (p, complete_ctor_identifier,
    3664                 :            :                                          &promise_args, promise_type,
    3665                 :            :                                          LOOKUP_NORMAL, tf_none);
    3666                 :        383 :           release_tree_vector (promise_args);
    3667                 :            :         }
    3668                 :            :       else
    3669                 :            :         r = NULL_TREE;
    3670                 :            : 
    3671                 :        383 :       if (r == NULL_TREE || r == error_mark_node)
    3672                 :        625 :         r = build_special_member_call (p, complete_ctor_identifier, NULL,
    3673                 :            :                                        promise_type, LOOKUP_NORMAL,
    3674                 :            :                                        tf_warning_or_error);
    3675                 :            : 
    3676                 :        738 :       r = coro_build_cvt_void_expr_stmt (r, fn_start);
    3677                 :        738 :       add_stmt (r);
    3678                 :            :     }
    3679                 :            : 
    3680                 :            :   /* Set up a new bind context for the GRO.  */
    3681                 :        783 :   tree gro_context_bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
    3682                 :            :   /* Make and connect the scope blocks.  */
    3683                 :        783 :   tree gro_block = make_node (BLOCK);
    3684                 :        783 :   BLOCK_SUPERCONTEXT (gro_block) = top_block;
    3685                 :        783 :   BLOCK_SUBBLOCKS (top_block) = gro_block;
    3686                 :        783 :   BIND_EXPR_BLOCK (gro_context_bind) = gro_block;
    3687                 :        783 :   add_stmt (gro_context_bind);
    3688                 :            : 
    3689                 :        783 :   tree gro_meth = lookup_promise_method (orig,
    3690                 :            :                                          coro_get_return_object_identifier,
    3691                 :            :                                          fn_start, /*musthave=*/true );
    3692                 :        783 :   tree get_ro
    3693                 :        783 :     = build_new_method_call (p, gro_meth, NULL, NULL_TREE, LOOKUP_NORMAL, NULL,
    3694                 :            :                              tf_warning_or_error);
    3695                 :            :   /* Without a return object we haven't got much clue what's going on.  */
    3696                 :        783 :   if (get_ro == error_mark_node)
    3697                 :            :     {
    3698                 :          1 :       BIND_EXPR_BODY (ramp_bind) = pop_stmt_list (ramp_body);
    3699                 :          1 :       DECL_SAVED_TREE (orig) = newbody;
    3700                 :          1 :       return false;
    3701                 :            :     }
    3702                 :            : 
    3703                 :        782 :   tree gro_context_body = push_stmt_list ();
    3704                 :        782 :   tree gro, gro_bind_vars;
    3705                 :        782 :   if (same_type_p (TREE_TYPE (get_ro), fn_return_type))
    3706                 :            :     {
    3707                 :         39 :       gro = DECL_RESULT (orig);
    3708                 :         39 :       gro_bind_vars = NULL_TREE; /* We don't need a separate var.  */
    3709                 :            :     }
    3710                 :            :   else
    3711                 :            :     {
    3712                 :        743 :       gro = build_lang_decl (VAR_DECL, get_identifier ("coro.gro"),
    3713                 :        743 :                              TREE_TYPE (TREE_OPERAND (get_ro, 0)));
    3714                 :        743 :       DECL_CONTEXT (gro) = current_scope ();
    3715                 :        743 :       r = build_stmt (fn_start, DECL_EXPR, gro);
    3716                 :        743 :       add_stmt (r);
    3717                 :        743 :       gro_bind_vars = gro; /* We need a temporary var.  */
    3718                 :            :     }
    3719                 :            : 
    3720                 :            :   /* Initialize our actual var.  */
    3721                 :        782 :   r = build2_loc (fn_start, INIT_EXPR, TREE_TYPE (gro), gro, get_ro);
    3722                 :        782 :   r = coro_build_cvt_void_expr_stmt (r, fn_start);
    3723                 :        782 :   add_stmt (r);
    3724                 :            : 
    3725                 :            :   /* Initialize the resume_idx_name to 0, meaning "not started".  */
    3726                 :        782 :   tree resume_idx_m
    3727                 :        782 :     = lookup_member (coro_frame_type, resume_idx_name,
    3728                 :            :                      /*protect=*/1, /*want_type=*/0, tf_warning_or_error);
    3729                 :        782 :   tree resume_idx
    3730                 :        782 :     = build_class_member_access_expr (deref_fp, resume_idx_m, NULL_TREE, false,
    3731                 :            :                                       tf_warning_or_error);
    3732                 :        782 :   r = build_int_cst (short_unsigned_type_node, 0);
    3733                 :        782 :   r = build2_loc (fn_start, INIT_EXPR, short_unsigned_type_node, resume_idx, r);
    3734                 :        782 :   r = coro_build_cvt_void_expr_stmt (r, fn_start);
    3735                 :        782 :   add_stmt (r);
    3736                 :            : 
    3737                 :            :   /* Initialize 'initial-await-resume-called' as per
    3738                 :            :      [dcl.fct.def.coroutine] / 5.3 */
    3739                 :        782 :   tree i_a_r_c_m
    3740                 :        782 :     = lookup_member (coro_frame_type, iarc_name, 1, 0, tf_warning_or_error);
    3741                 :        782 :   tree i_a_r_c = build_class_member_access_expr (deref_fp, i_a_r_c_m,
    3742                 :            :                                                  NULL_TREE, false,
    3743                 :            :                                                  tf_warning_or_error);
    3744                 :        782 :   r = build2 (INIT_EXPR, boolean_type_node, i_a_r_c, boolean_false_node);
    3745                 :        782 :   r = coro_build_cvt_void_expr_stmt (r, fn_start);
    3746                 :        782 :   add_stmt (r);
    3747                 :            : 
    3748                 :            :   /* So .. call the actor ..  */
    3749                 :        782 :   r = build_call_expr_loc (fn_start, actor, 1, coro_fp);
    3750                 :        782 :   r = maybe_cleanup_point_expr_void (r);
    3751                 :        782 :   add_stmt (r);
    3752                 :            : 
    3753                 :            :   /* Switch to using 'input_location' as the loc, since we're now more
    3754                 :            :      logically doing things related to the end of the function.  */
    3755                 :            : 
    3756                 :            :   /* The ramp is done, we just need the return value.  */
    3757                 :        782 :   if (!same_type_p (TREE_TYPE (gro), fn_return_type))
    3758                 :            :     {
    3759                 :            :       /* construct the return value with a single GRO param.  */
    3760                 :        743 :       vec<tree, va_gc> *args = make_tree_vector_single (gro);
    3761                 :        743 :       r = build_special_member_call (DECL_RESULT (orig),
    3762                 :            :                                      complete_ctor_identifier, &args,
    3763                 :            :                                      fn_return_type, LOOKUP_NORMAL,
    3764                 :            :                                      tf_warning_or_error);
    3765                 :        743 :       r = coro_build_cvt_void_expr_stmt (r, input_location);
    3766                 :        743 :       add_stmt (r);
    3767                 :        743 :       release_tree_vector (args);
    3768                 :            :     }
    3769                 :            :   /* Else the GRO is the return and we already built it in place.  */
    3770                 :            : 
    3771                 :        782 :   bool no_warning;
    3772                 :        782 :   r = check_return_expr (DECL_RESULT (orig), &no_warning);
    3773                 :       1564 :   if (error_operand_p (r) && warn_return_type)
    3774                 :            :     /* Suppress -Wreturn-type for the ramp.  */
    3775                 :          0 :     TREE_NO_WARNING (orig) = true;
    3776                 :            : 
    3777                 :        782 :   r = build_stmt (input_location, RETURN_EXPR, DECL_RESULT (orig));
    3778                 :        782 :   TREE_NO_WARNING (r) |= no_warning;
    3779                 :        782 :   r = maybe_cleanup_point_expr_void (r);
    3780                 :        782 :   add_stmt (r);
    3781                 :        782 :   BIND_EXPR_VARS (gro_context_bind) = gro_bind_vars;
    3782                 :        782 :   BIND_EXPR_BODY (gro_context_bind) = pop_stmt_list (gro_context_body);
    3783                 :        782 :   BIND_EXPR_BODY (ramp_bind) = pop_stmt_list (ramp_body);
    3784                 :            : 
    3785                 :            :   /* We know the "real" promise and have a frame layout with a slot for each
    3786                 :            :      suspend point, so we can build an actor function (which contains the
    3787                 :            :      functionality for both 'resume' and 'destroy').
    3788                 :            : 
    3789                 :            :      wrap the function body in a try {} catch (...) {} block, if exceptions
    3790                 :            :      are enabled.  */
    3791                 :            : 
    3792                 :            :   /* First make a new block for the body - that will be embedded in the
    3793                 :            :      re-written function.  */
    3794                 :        782 :   tree first = expr_first (fnbody);
    3795                 :        782 :   bool orig_fn_has_outer_bind = false;
    3796                 :        782 :   tree replace_blk = NULL_TREE;
    3797                 :        782 :   if (first && TREE_CODE (first) == BIND_EXPR)
    3798                 :            :     {
    3799                 :        375 :       orig_fn_has_outer_bind = true;
    3800                 :        375 :       tree block = BIND_EXPR_BLOCK (first);
    3801                 :        375 :       replace_blk = make_node (BLOCK);
    3802                 :        375 :       if (block) /* missing block is probably an error.  */
    3803                 :            :         {
    3804                 :        375 :           gcc_assert (BLOCK_SUPERCONTEXT (block) == NULL_TREE);
    3805                 :        375 :           gcc_assert (BLOCK_CHAIN (block) == NULL_TREE);
    3806                 :        375 :           BLOCK_VARS (replace_blk) = BLOCK_VARS (block);
    3807                 :        375 :           BLOCK_SUBBLOCKS (replace_blk) = BLOCK_SUBBLOCKS (block);
    3808                 :        508 :           for (tree b = BLOCK_SUBBLOCKS (replace_blk); b; b = BLOCK_CHAIN (b))
    3809                 :        133 :             BLOCK_SUPERCONTEXT (b) = replace_blk;
    3810                 :            :         }
    3811                 :        375 :       BIND_EXPR_BLOCK (first) = replace_blk;
    3812                 :            :     }
    3813                 :            : 
    3814                 :            :   /* actor's version of the promise.  */
    3815                 :        782 :   tree actor_frame = build1_loc (fn_start, INDIRECT_REF, coro_frame_type,
    3816                 :        782 :                                  DECL_ARGUMENTS (actor));
    3817                 :        782 :   tree ap_m = lookup_member (coro_frame_type, get_identifier ("__p"), 1, 0,
    3818                 :            :                              tf_warning_or_error);
    3819                 :        782 :   tree ap = build_class_member_access_expr (actor_frame, ap_m, NULL_TREE,
    3820                 :            :                                             false, tf_warning_or_error);
    3821                 :            : 
    3822                 :            :   /* Now we've built the promise etc, process fnbody for co_returns.
    3823                 :            :      We want the call to return_void () below and it has no params so
    3824                 :            :      we can create it once here.
    3825                 :            :      Calls to return_value () will have to be checked and created as
    3826                 :            :      required.  */
    3827                 :            : 
    3828                 :        782 :   tree return_void = NULL_TREE;
    3829                 :        782 :   tree rvm
    3830                 :        782 :     = lookup_promise_method (orig, coro_return_void_identifier, fn_start,
    3831                 :            :                              /*musthave=*/false);
    3832                 :        782 :   if (rvm && rvm != error_mark_node)
    3833                 :        129 :     return_void
    3834                 :        129 :       = build_new_method_call (ap, rvm, NULL, NULL_TREE, LOOKUP_NORMAL, NULL,
    3835                 :            :                                tf_warning_or_error);
    3836                 :            : 
    3837                 :            :   /* [stmt.return.coroutine] (2.2 : 3) if p.return_void() is a valid
    3838                 :            :      expression, flowing off the end of a coroutine is equivalent to
    3839                 :            :      co_return; otherwise UB.
    3840                 :            :      We just inject the call to p.return_void() here, and fall through to
    3841                 :            :      the final_suspend: label (eliding the goto).  If the function body has
    3842                 :            :      a co_return, then this statement will be unreachable and DCEd.  */
    3843                 :        129 :   if (return_void != NULL_TREE)
    3844                 :            :     {
    3845                 :        129 :       tree append = push_stmt_list ();
    3846                 :        129 :       add_stmt (fnbody);
    3847                 :        129 :       add_stmt (return_void);
    3848                 :        129 :       fnbody = pop_stmt_list(append);
    3849                 :            :     }
    3850                 :            : 
    3851                 :        782 :   if (flag_exceptions)
    3852                 :            :     {
    3853                 :        780 :       tree ueh_meth
    3854                 :        780 :         = lookup_promise_method (orig, coro_unhandled_exception_identifier,
    3855                 :            :                                  fn_start, /*musthave=*/true);
    3856                 :            :       /* Build promise.unhandled_exception();  */
    3857                 :        780 :       tree ueh
    3858                 :        780 :         = build_new_method_call (ap, ueh_meth, NULL, NULL_TREE, LOOKUP_NORMAL,
    3859                 :            :                                  NULL, tf_warning_or_error);
    3860                 :            : 
    3861                 :            :       /* The try block is just the original function, there's no real
    3862                 :            :          need to call any function to do this.  */
    3863                 :        780 :       fnbody = build_stmt (fn_start, TRY_BLOCK, fnbody, NULL_TREE);
    3864                 :        780 :       TRY_HANDLERS (fnbody) = push_stmt_list ();
    3865                 :            :       /* Mimic what the parser does for the catch.  */
    3866                 :        780 :       tree handler = begin_handler ();
    3867                 :        780 :       finish_handler_parms (NULL_TREE, handler); /* catch (...) */
    3868                 :            : 
    3869                 :            :       /* Get the initial await resume called value.  */
    3870                 :        780 :       tree i_a_r_c = build_class_member_access_expr (actor_frame, i_a_r_c_m,
    3871                 :            :                                                      NULL_TREE, false,
    3872                 :            :                                                      tf_warning_or_error);
    3873                 :        780 :       tree not_iarc_if = begin_if_stmt ();
    3874                 :        780 :       tree not_iarc = build1_loc (fn_start, TRUTH_NOT_EXPR,
    3875                 :            :                                   boolean_type_node, i_a_r_c);
    3876                 :        780 :       finish_if_stmt_cond (not_iarc, not_iarc_if);
    3877                 :            :       /* If the initial await resume called value is false, rethrow...  */
    3878                 :        780 :       tree rethrow = build_throw (fn_start, NULL_TREE);
    3879                 :        780 :       TREE_NO_WARNING (rethrow) = true;
    3880                 :        780 :       finish_expr_stmt (rethrow);
    3881                 :        780 :       finish_then_clause (not_iarc_if);
    3882                 :        780 :       tree iarc_scope = IF_SCOPE (not_iarc_if);
    3883                 :        780 :       IF_SCOPE (not_iarc_if) = NULL;
    3884                 :        780 :       not_iarc_if = do_poplevel (iarc_scope);
    3885                 :        780 :       add_stmt (not_iarc_if);
    3886                 :            :       /* ... else call the promise unhandled exception method.  */
    3887                 :        780 :       ueh = maybe_cleanup_point_expr_void (ueh);
    3888                 :        780 :       add_stmt (ueh);
    3889                 :        780 :       finish_handler (handler);
    3890                 :        780 :       TRY_HANDLERS (fnbody) = pop_stmt_list (TRY_HANDLERS (fnbody));
    3891                 :            :       /* If the function starts with a BIND_EXPR, then we need to create
    3892                 :            :          one here to contain the try-catch and to link up the scopes.  */
    3893                 :        780 :       if (orig_fn_has_outer_bind)
    3894                 :            :         {
    3895                 :        375 :           fnbody = build3 (BIND_EXPR, void_type_node, NULL, fnbody, NULL);
    3896                 :            :           /* Make and connect the scope blocks.  */
    3897                 :        375 :           tree tcb_block = make_node (BLOCK);
    3898                 :            :           /* .. and connect it here.  */
    3899                 :        375 :           BLOCK_SUPERCONTEXT (replace_blk) = tcb_block;
    3900                 :        375 :           BLOCK_SUBBLOCKS (tcb_block) = replace_blk;
    3901                 :        375 :           BIND_EXPR_BLOCK (fnbody) = tcb_block;
    3902                 :            :         }
    3903                 :            :     }
    3904                 :          2 :   else if (pedantic)
    3905                 :            :     {
    3906                 :            :       /* We still try to look for the promise method and warn if it's not
    3907                 :            :          present.  */
    3908                 :          1 :       tree ueh_meth
    3909                 :          1 :         = lookup_promise_method (orig, coro_unhandled_exception_identifier,
    3910                 :            :                                  fn_start, /*musthave=*/false);
    3911                 :          1 :       if (!ueh_meth || ueh_meth == error_mark_node)
    3912                 :          2 :         warning_at (fn_start, 0, "no member named %qE in %qT",
    3913                 :            :                     coro_unhandled_exception_identifier,
    3914                 :            :                     get_coroutine_promise_type (orig));
    3915                 :            :     }
    3916                 :            :   /* Else we don't check and don't care if the method is missing.  */
    3917                 :            : 
    3918                 :            :   /* Start to build the final functions.
    3919                 :            : 
    3920                 :            :      We push_deferring_access_checks to avoid these routines being seen as
    3921                 :            :      nested by the middle end; we are doing the outlining here.  */
    3922                 :            : 
    3923                 :        782 :   push_deferring_access_checks (dk_no_check);
    3924                 :            : 
    3925                 :            :   /* Actor ...  */
    3926                 :        782 :   build_actor_fn (fn_start, coro_frame_type, actor, fnbody, orig, param_uses,
    3927                 :            :                   &local_var_uses, param_dtor_list, initial_await, final_await,
    3928                 :            :                   body_aw_points.count, frame_size);
    3929                 :            : 
    3930                 :            :   /* Destroyer ... */
    3931                 :        782 :   build_destroy_fn (fn_start, coro_frame_type, destroy, actor);
    3932                 :            : 
    3933                 :        782 :   pop_deferring_access_checks ();
    3934                 :            : 
    3935                 :        782 :   DECL_SAVED_TREE (orig) = newbody;
    3936                 :            :   /* Link our new functions into the list.  */
    3937                 :        782 :   TREE_CHAIN (destroy) = TREE_CHAIN (orig);
    3938                 :        782 :   TREE_CHAIN (actor) = destroy;
    3939                 :        782 :   TREE_CHAIN (orig) = actor;
    3940                 :            : 
    3941                 :        782 :   *resumer = actor;
    3942                 :        782 :   *destroyer = destroy;
    3943                 :            : 
    3944                 :       1564 :   delete suspend_points;
    3945                 :        782 :   suspend_points = NULL;
    3946                 :        782 :   return true;
    3947                 :            : }
    3948                 :            : 
    3949                 :            : #include "gt-cp-coroutines.h"
    3950                 :            : 

Generated by: LCOV version 1.0

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 --enable-host-shared. GCC test suite is run with the built compiler.