Home | History | Annotate | Line # | Download | only in cp
      1 /* Perform optimizations on tree structure.
      2    Copyright (C) 1998-2024 Free Software Foundation, Inc.
      3    Written by Mark Michell (mark (at) codesourcery.com).
      4 
      5 This file is part of GCC.
      6 
      7 GCC is free software; you can redistribute it and/or modify it
      8 under the terms of the GNU General Public License as published by
      9 the Free Software Foundation; either version 3, or (at your option)
     10 any later version.
     11 
     12 GCC is distributed in the hope that it will be useful, but
     13 WITHOUT ANY WARRANTY; without even the implied warranty of
     14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     15 General Public License for more details.
     16 
     17 You should have received a copy of the GNU General Public License
     18 along with GCC; see the file COPYING3.  If not see
     19 <http://www.gnu.org/licenses/>.  */
     20 
     21 #include "config.h"
     22 #include "system.h"
     23 #include "coretypes.h"
     24 #include "target.h"
     25 #include "cp-tree.h"
     26 #include "decl.h"
     27 #include "stringpool.h"
     28 #include "cgraph.h"
     29 #include "debug.h"
     30 #include "tree-inline.h"
     31 #include "tree-iterator.h"
     32 #include "attribs.h"
     33 
     34 /* Prototypes.  */
     35 
     36 static void update_cloned_parm (tree, tree, bool);
     37 
     38 /* CLONED_PARM is a copy of CLONE, generated for a cloned constructor
     39    or destructor.  Update it to ensure that the source-position for
     40    the cloned parameter matches that for the original, and that the
     41    debugging generation code will be able to find the original PARM.  */
     42 
     43 static void
     44 update_cloned_parm (tree parm, tree cloned_parm, bool first)
     45 {
     46   DECL_ABSTRACT_ORIGIN (cloned_parm) = parm;
     47 
     48   /* We may have taken its address.  */
     49   TREE_ADDRESSABLE (cloned_parm) = TREE_ADDRESSABLE (parm);
     50 
     51   DECL_BY_REFERENCE (cloned_parm) = DECL_BY_REFERENCE (parm);
     52 
     53   /* The definition might have different constness.  */
     54   TREE_READONLY (cloned_parm) = TREE_READONLY (parm);
     55 
     56   TREE_USED (cloned_parm) = !first || TREE_USED (parm);
     57 
     58   /* The name may have changed from the declaration.  */
     59   DECL_NAME (cloned_parm) = DECL_NAME (parm);
     60   DECL_SOURCE_LOCATION (cloned_parm) = DECL_SOURCE_LOCATION (parm);
     61   TREE_TYPE (cloned_parm) = TREE_TYPE (parm);
     62 
     63   DECL_NOT_GIMPLE_REG_P (cloned_parm) = DECL_NOT_GIMPLE_REG_P (parm);
     64 }
     65 
     66 /* Like copy_decl_no_change, but handle DECL_OMP_PRIVATIZED_MEMBER
     67    properly.  */
     68 
     69 static tree
     70 cxx_copy_decl (tree decl, copy_body_data *id)
     71 {
     72   tree copy = copy_decl_no_change (decl, id);
     73   if (VAR_P (decl)
     74       && DECL_HAS_VALUE_EXPR_P (decl)
     75       && DECL_ARTIFICIAL (decl)
     76       && DECL_LANG_SPECIFIC (decl)
     77       && DECL_OMP_PRIVATIZED_MEMBER (decl))
     78     {
     79       tree expr = DECL_VALUE_EXPR (copy);
     80       walk_tree (&expr, copy_tree_body_r, id, NULL);
     81       SET_DECL_VALUE_EXPR (copy, expr);
     82     }
     83   return copy;
     84 }
     85 
     86 /* FN is a function in High GIMPLE form that has a complete body and no
     87    CFG.  CLONE is a function whose body is to be set to a copy of FN,
     88    mapping argument declarations according to the ARG_MAP splay_tree.  */
     89 
     90 static void
     91 clone_body (tree clone, tree fn, void *arg_map)
     92 {
     93   copy_body_data id;
     94   tree stmts;
     95 
     96   /* Clone the body, as if we were making an inline call.  But, remap
     97      the parameters in the callee to the parameters of caller.  */
     98   memset (&id, 0, sizeof (id));
     99   id.src_fn = fn;
    100   id.dst_fn = clone;
    101   id.src_cfun = DECL_STRUCT_FUNCTION (fn);
    102   id.decl_map = static_cast<hash_map<tree, tree> *> (arg_map);
    103 
    104   id.copy_decl = cxx_copy_decl;
    105   id.transform_call_graph_edges = CB_CGE_DUPLICATE;
    106   id.transform_new_cfg = true;
    107   id.transform_return_to_modify = false;
    108 
    109   /* We're not inside any EH region.  */
    110   id.eh_lp_nr = 0;
    111 
    112   stmts = DECL_SAVED_TREE (fn);
    113   walk_tree (&stmts, copy_tree_body_r, &id, NULL);
    114 
    115   /* Also remap the initializer of any static variables so that they (in
    116      particular, any label addresses) correspond to the base variant rather
    117      than the abstract one.  */
    118   if (DECL_NAME (clone) == base_dtor_identifier
    119       || DECL_NAME (clone) == base_ctor_identifier)
    120     {
    121       unsigned ix;
    122       tree decl;
    123 
    124       FOR_EACH_LOCAL_DECL (DECL_STRUCT_FUNCTION (fn), ix, decl)
    125         walk_tree (&DECL_INITIAL (decl), copy_tree_body_r, &id, NULL);
    126     }
    127 
    128   append_to_statement_list_force (stmts, &DECL_SAVED_TREE (clone));
    129 }
    130 
    131 /* DELETE_DTOR is a delete destructor whose body will be built.
    132    COMPLETE_DTOR is the corresponding complete destructor.  */
    133 
    134 static void
    135 build_delete_destructor_body (tree delete_dtor, tree complete_dtor)
    136 {
    137   tree parm = DECL_ARGUMENTS (delete_dtor);
    138   tree virtual_size = cxx_sizeof (current_class_type);
    139 
    140   /* Call the delete function.  */
    141   tree call_delete = build_op_delete_call (DELETE_EXPR, current_class_ptr,
    142 					   virtual_size,
    143 					   /*global_p=*/false,
    144 					   /*placement=*/NULL_TREE,
    145 					   /*alloc_fn=*/NULL_TREE,
    146 					   tf_warning_or_error);
    147 
    148   tree op = get_callee_fndecl (call_delete);
    149   if (op && DECL_P (op) && destroying_delete_p (op))
    150     {
    151       /* The destroying delete will handle calling complete_dtor.  */
    152       add_stmt (call_delete);
    153     }
    154   else
    155     {
    156       /* Call the corresponding complete destructor.  */
    157       gcc_assert (complete_dtor);
    158       tree call_dtor = build_cxx_call (complete_dtor, 1, &parm,
    159 				       tf_warning_or_error);
    160 
    161       /* Operator delete must be called, whether or not the dtor throws.  */
    162       add_stmt (build2 (TRY_FINALLY_EXPR, void_type_node,
    163 			call_dtor, call_delete));
    164     }
    165 
    166   /* Return the address of the object.
    167      ??? How is it useful to return an invalid address?  */
    168   maybe_return_this ();
    169 }
    170 
    171 /* Return name of comdat group for complete and base ctor (or dtor)
    172    that have the same body.  If dtor is virtual, deleting dtor goes
    173    into this comdat group as well.  */
    174 
    175 static tree
    176 cdtor_comdat_group (tree complete, tree base)
    177 {
    178   tree complete_name = DECL_ASSEMBLER_NAME (complete);
    179   tree base_name = DECL_ASSEMBLER_NAME (base);
    180   char *grp_name;
    181   const char *p, *q;
    182   bool diff_seen = false;
    183   size_t idx;
    184   gcc_assert (IDENTIFIER_LENGTH (complete_name)
    185 	      == IDENTIFIER_LENGTH (base_name));
    186   grp_name = XALLOCAVEC (char, IDENTIFIER_LENGTH (complete_name) + 1);
    187   p = IDENTIFIER_POINTER (complete_name);
    188   q = IDENTIFIER_POINTER (base_name);
    189   for (idx = 0; idx < IDENTIFIER_LENGTH (complete_name); idx++)
    190     if (p[idx] == q[idx])
    191       grp_name[idx] = p[idx];
    192     else
    193       {
    194 	gcc_assert (!diff_seen
    195 		    && idx > 0
    196 		    && (p[idx - 1] == 'C' || p[idx - 1] == 'D'
    197 			|| p[idx - 1] == 'I')
    198 		    && p[idx] == '1'
    199 		    && q[idx] == '2');
    200 	grp_name[idx] = '5';
    201 	diff_seen = true;
    202       }
    203   grp_name[idx] = '\0';
    204   gcc_assert (diff_seen);
    205   return get_identifier (grp_name);
    206 }
    207 
    208 /* Returns true iff we can make the base and complete [cd]tor aliases of
    209    the same symbol rather than separate functions.  */
    210 
    211 static bool
    212 can_alias_cdtor (tree fn)
    213 {
    214   /* If aliases aren't supported by the assembler, fail.  */
    215   if (!TARGET_SUPPORTS_ALIASES)
    216     return false;
    217 
    218   /* We can't use an alias if there are virtual bases.  */
    219   if (CLASSTYPE_VBASECLASSES (DECL_CONTEXT (fn)))
    220     return false;
    221   gcc_assert (DECL_MAYBE_IN_CHARGE_CDTOR_P (fn));
    222   /* Don't use aliases for weak/linkonce definitions unless we can put both
    223      symbols in the same COMDAT group.  */
    224   return (DECL_WEAK (fn) ? (HAVE_COMDAT_GROUP && DECL_ONE_ONLY (fn))
    225 			 : (DECL_INTERFACE_KNOWN (fn) && !DECL_ONE_ONLY (fn)));
    226 }
    227 
    228 /* FN is a [cd]tor, fns is a pointer to an array of length 3.  Fill fns
    229    with pointers to the base, complete, and deleting variants.  */
    230 
    231 static void
    232 populate_clone_array (tree fn, tree *fns)
    233 {
    234   tree clone;
    235 
    236   fns[0] = NULL_TREE;
    237   fns[1] = NULL_TREE;
    238   fns[2] = NULL_TREE;
    239 
    240   FOR_EACH_CLONE (clone, fn)
    241     if (DECL_NAME (clone) == complete_dtor_identifier
    242 	|| DECL_NAME (clone) == complete_ctor_identifier)
    243       fns[1] = clone;
    244     else if (DECL_NAME (clone) == base_dtor_identifier
    245 	     || DECL_NAME (clone) == base_ctor_identifier)
    246       fns[0] = clone;
    247     else if (DECL_NAME (clone) == deleting_dtor_identifier)
    248       fns[2] = clone;
    249     else
    250       gcc_unreachable ();
    251 }
    252 
    253 /* FN is a constructor or destructor, and there are FUNCTION_DECLs
    254    cloned from it nearby.  Instead of cloning this body, leave it
    255    alone and create tiny one-call bodies for the cloned
    256    FUNCTION_DECLs.  These clones are sibcall candidates, and their
    257    resulting code will be very thunk-esque.  */
    258 
    259 static bool
    260 maybe_thunk_body (tree fn, bool force)
    261 {
    262   tree bind, block, call, clone, clone_result, fn_parm, fn_parm_typelist;
    263   tree last_arg, modify, *args;
    264   int parmno, vtt_parmno, max_parms;
    265   tree fns[3];
    266 
    267   if (!force && !flag_declone_ctor_dtor)
    268     return 0;
    269 
    270   /* If function accepts variable arguments, give up.  */
    271   last_arg = tree_last (TYPE_ARG_TYPES (TREE_TYPE (fn)));
    272   if (last_arg != void_list_node)
    273     return 0;
    274 
    275   /* If we got this far, we've decided to turn the clones into thunks.  */
    276 
    277   /* We're going to generate code for fn, so it is no longer "abstract."
    278      Also make the unified ctor/dtor private to either the translation unit
    279      (for non-vague linkage ctors) or the COMDAT group (otherwise).  */
    280 
    281   populate_clone_array (fn, fns);
    282 
    283   /* Can happen during error recovery (c++/71464).  */
    284   if (!fns[0] || !fns[1])
    285     return 0;
    286 
    287   /* Don't use thunks if the base clone omits inherited parameters.  */
    288   if (ctor_omit_inherited_parms (fns[0]))
    289     return 0;
    290 
    291   /* Don't diagnose deprecated or unavailable cdtors just because they
    292      have thunks emitted for them.  */
    293   auto du = make_temp_override (deprecated_state,
    294 				UNAVAILABLE_DEPRECATED_SUPPRESS);
    295 
    296   DECL_ABSTRACT_P (fn) = false;
    297   if (!DECL_WEAK (fn))
    298     {
    299       TREE_PUBLIC (fn) = false;
    300       DECL_EXTERNAL (fn) = false;
    301       DECL_INTERFACE_KNOWN (fn) = true;
    302     }
    303   else if (HAVE_COMDAT_GROUP)
    304     {
    305       /* At eof, defer creation of mangling aliases temporarily.  */
    306       bool save_defer_mangling_aliases = defer_mangling_aliases;
    307       defer_mangling_aliases = true;
    308       tree comdat_group = cdtor_comdat_group (fns[1], fns[0]);
    309       defer_mangling_aliases = save_defer_mangling_aliases;
    310       cgraph_node::get_create (fns[0])->set_comdat_group (comdat_group);
    311       cgraph_node::get_create (fns[1])->add_to_same_comdat_group
    312 	(cgraph_node::get (fns[0]));
    313       symtab_node::get_create (fn)->add_to_same_comdat_group
    314 	(symtab_node::get (fns[0]));
    315       if (fns[2])
    316 	/* If *[CD][12]* dtors go into the *[CD]5* comdat group and dtor is
    317 	   virtual, it goes into the same comdat group as well.  */
    318 	cgraph_node::get_create (fns[2])->add_to_same_comdat_group
    319 	  (symtab_node::get (fns[0]));
    320       /* Emit them now that the thunks are same comdat group aliases.  */
    321       if (!save_defer_mangling_aliases)
    322 	generate_mangling_aliases ();
    323       TREE_PUBLIC (fn) = false;
    324       DECL_EXTERNAL (fn) = false;
    325       DECL_INTERFACE_KNOWN (fn) = true;
    326       /* function_and_variable_visibility doesn't want !PUBLIC decls to
    327 	 have these flags set.  */
    328       DECL_WEAK (fn) = false;
    329       DECL_COMDAT (fn) = false;
    330     }
    331 
    332   /* Find the vtt_parm, if present.  */
    333   for (vtt_parmno = -1, parmno = 0, fn_parm = DECL_ARGUMENTS (fn);
    334        fn_parm;
    335        ++parmno, fn_parm = TREE_CHAIN (fn_parm))
    336     {
    337       if (DECL_ARTIFICIAL (fn_parm)
    338 	  && DECL_NAME (fn_parm) == vtt_parm_identifier)
    339 	{
    340 	  /* Compensate for removed in_charge parameter.  */
    341 	  vtt_parmno = parmno;
    342 	  break;
    343 	}
    344     }
    345 
    346   /* Allocate an argument buffer for build_cxx_call().
    347      Make sure it is large enough for any of the clones.  */
    348   max_parms = 0;
    349   FOR_EACH_CLONE (clone, fn)
    350     {
    351       int length = list_length (DECL_ARGUMENTS (fn));
    352       if (length > max_parms)
    353         max_parms = length;
    354     }
    355   args = XALLOCAVEC (tree, max_parms);
    356 
    357   /* We know that any clones immediately follow FN in TYPE_FIELDS.  */
    358   FOR_EACH_CLONE (clone, fn)
    359     {
    360       tree clone_parm;
    361 
    362       /* If we've already generated a body for this clone, avoid
    363 	 duplicating it.  (Is it possible for a clone-list to grow after we
    364 	 first see it?)  */
    365       if (DECL_SAVED_TREE (clone) || TREE_ASM_WRITTEN (clone))
    366 	continue;
    367 
    368       /* Start processing the function.  */
    369       start_preparsed_function (clone, NULL_TREE, SF_PRE_PARSED);
    370 
    371       if (clone == fns[2])
    372 	{
    373 	  for (clone_parm = DECL_ARGUMENTS (clone); clone_parm;
    374 	       clone_parm = TREE_CHAIN (clone_parm))
    375 	    DECL_ABSTRACT_ORIGIN (clone_parm) = NULL_TREE;
    376 	  /* Build the delete destructor by calling complete destructor and
    377 	     delete function.  */
    378 	  build_delete_destructor_body (clone, fns[1]);
    379 	}
    380       else
    381 	{
    382 	  /* Walk parameter lists together, creating parameter list for
    383 	     call to original function.  */
    384 	  for (parmno = 0,
    385 		 fn_parm = DECL_ARGUMENTS (fn),
    386 		 fn_parm_typelist = TYPE_ARG_TYPES (TREE_TYPE (fn)),
    387 		 clone_parm = DECL_ARGUMENTS (clone);
    388 	       fn_parm;
    389 	       ++parmno,
    390 		 fn_parm = TREE_CHAIN (fn_parm))
    391 	    {
    392 	      if (parmno == vtt_parmno && ! DECL_HAS_VTT_PARM_P (clone))
    393 		{
    394 		  gcc_assert (fn_parm_typelist);
    395 		  /* Clobber argument with formal parameter type.  */
    396 		  args[parmno]
    397 		    = convert (TREE_VALUE (fn_parm_typelist),
    398 			       null_pointer_node);
    399 		}
    400 	      else if (parmno == 1 && DECL_HAS_IN_CHARGE_PARM_P (fn))
    401 		{
    402 		  tree in_charge
    403 		    = copy_node (in_charge_arg_for_name (DECL_NAME (clone)));
    404 		  args[parmno] = in_charge;
    405 		}
    406 	      /* Map other parameters to their equivalents in the cloned
    407 		 function.  */
    408 	      else
    409 		{
    410 		  gcc_assert (clone_parm);
    411 		  DECL_ABSTRACT_ORIGIN (clone_parm) = NULL;
    412 		  args[parmno] = clone_parm;
    413 		  /* Clear TREE_ADDRESSABLE on thunk arguments.  */
    414 		  TREE_ADDRESSABLE (clone_parm) = 0;
    415 		  clone_parm = TREE_CHAIN (clone_parm);
    416 		}
    417 	      if (fn_parm_typelist)
    418 		fn_parm_typelist = TREE_CHAIN (fn_parm_typelist);
    419 	    }
    420 
    421 	  /* We built this list backwards; fix now.  */
    422 	  mark_used (fn);
    423 	  call = build_cxx_call (fn, parmno, args, tf_warning_or_error);
    424 	  /* Arguments passed to the thunk by invisible reference should
    425 	     be transmitted to the callee unchanged.  Do not create a
    426 	     temporary and invoke the copy constructor.  The thunking
    427 	     transformation must not introduce any constructor calls.  */
    428 	  CALL_FROM_THUNK_P (call) = 1;
    429 	  block = make_node (BLOCK);
    430 	  if (targetm.cxx.cdtor_returns_this ())
    431 	    {
    432 	      clone_result = DECL_RESULT (clone);
    433 	      modify = build2 (MODIFY_EXPR, TREE_TYPE (clone_result),
    434 			       clone_result, call);
    435 	      modify = build1 (RETURN_EXPR, void_type_node, modify);
    436 	      add_stmt (modify);
    437 	    }
    438 	  else
    439 	    {
    440 	      add_stmt (call);
    441 	    }
    442 	  bind = c_build_bind_expr (DECL_SOURCE_LOCATION (clone),
    443 				    block, cur_stmt_list);
    444 	  DECL_SAVED_TREE (clone) = push_stmt_list ();
    445 	  add_stmt (bind);
    446 	}
    447 
    448       DECL_ABSTRACT_ORIGIN (clone) = NULL;
    449       expand_or_defer_fn (finish_function (/*inline_p=*/false));
    450     }
    451   return 1;
    452 }
    453 
    454 /* Copy most attributes from ATTRS, omitting attributes that can really only
    455    apply to a single decl.  */
    456 
    457 tree
    458 clone_attrs (tree attrs)
    459 {
    460   tree new_attrs = NULL_TREE;
    461   tree *p = &new_attrs;
    462 
    463   for (tree a = attrs; a; a = TREE_CHAIN (a))
    464     {
    465       tree aname = get_attribute_name (a);
    466       if (is_attribute_namespace_p ("", a)
    467 	  && (is_attribute_p ("alias", aname)
    468 	      || is_attribute_p ("ifunc", aname)))
    469 	continue;
    470       *p = copy_node (a);
    471       p = &TREE_CHAIN (*p);
    472     }
    473   *p = NULL_TREE;
    474   return new_attrs;
    475 }
    476 
    477 /* FN is a function that has a complete body.  Clone the body as
    478    necessary.  Returns nonzero if there's no longer any need to
    479    process the main body.  */
    480 
    481 bool
    482 maybe_clone_body (tree fn)
    483 {
    484   tree comdat_group = NULL_TREE;
    485   tree clone;
    486   tree fns[3];
    487   bool first = true;
    488   int idx;
    489   bool need_alias = false;
    490 
    491   /* We only clone constructors and destructors.  */
    492   if (!DECL_MAYBE_IN_CHARGE_CDTOR_P (fn))
    493     return 0;
    494 
    495   populate_clone_array (fn, fns);
    496 
    497   /* Remember if we can't have multiple clones for some reason.  We need to
    498      check this before we remap local static initializers in clone_body.  */
    499   if (!tree_versionable_function_p (fn))
    500     need_alias = true;
    501 
    502   /* We know that any clones immediately follow FN in the TYPE_FIELDS
    503      list.  */
    504   push_to_top_level ();
    505   for (idx = 0; idx < 3; idx++)
    506     {
    507       tree parm;
    508       tree clone_parm;
    509 
    510       clone = fns[idx];
    511       if (!clone)
    512 	continue;
    513 
    514       /* Update CLONE's source position information to match FN's.  */
    515       DECL_SOURCE_LOCATION (clone) = DECL_SOURCE_LOCATION (fn);
    516       DECL_DECLARED_INLINE_P (clone) = DECL_DECLARED_INLINE_P (fn);
    517       DECL_DECLARED_CONSTEXPR_P (clone) = DECL_DECLARED_CONSTEXPR_P (fn);
    518       DECL_COMDAT (clone) = DECL_COMDAT (fn);
    519       DECL_WEAK (clone) = DECL_WEAK (fn);
    520 
    521       /* We don't copy the comdat group from fn to clone because the assembler
    522 	 name of fn was corrupted by write_mangled_name by adding *INTERNAL*
    523 	 to it. By doing so, it also corrupted the comdat group. */
    524       if (DECL_ONE_ONLY (fn))
    525 	cgraph_node::get_create (clone)->set_comdat_group (cxx_comdat_group (clone));
    526       DECL_USE_TEMPLATE (clone) = DECL_USE_TEMPLATE (fn);
    527       DECL_EXTERNAL (clone) = DECL_EXTERNAL (fn);
    528       DECL_INTERFACE_KNOWN (clone) = DECL_INTERFACE_KNOWN (fn);
    529       DECL_NOT_REALLY_EXTERN (clone) = DECL_NOT_REALLY_EXTERN (fn);
    530       TREE_PUBLIC (clone) = TREE_PUBLIC (fn);
    531       DECL_VISIBILITY (clone) = DECL_VISIBILITY (fn);
    532       DECL_VISIBILITY_SPECIFIED (clone) = DECL_VISIBILITY_SPECIFIED (fn);
    533       DECL_DLLIMPORT_P (clone) = DECL_DLLIMPORT_P (fn);
    534       DECL_ATTRIBUTES (clone) = clone_attrs (DECL_ATTRIBUTES (fn));
    535       DECL_DISREGARD_INLINE_LIMITS (clone) = DECL_DISREGARD_INLINE_LIMITS (fn);
    536       set_decl_section_name (clone, fn);
    537 
    538       /* Adjust the parameter names and locations.  */
    539       parm = DECL_ARGUMENTS (fn);
    540       clone_parm = DECL_ARGUMENTS (clone);
    541       /* Update the `this' parameter, which is always first.  */
    542       update_cloned_parm (parm, clone_parm, first);
    543       parm = DECL_CHAIN (parm);
    544       clone_parm = DECL_CHAIN (clone_parm);
    545       if (DECL_HAS_IN_CHARGE_PARM_P (fn))
    546 	parm = DECL_CHAIN (parm);
    547       if (DECL_HAS_VTT_PARM_P (fn))
    548 	parm = DECL_CHAIN (parm);
    549       if (DECL_HAS_VTT_PARM_P (clone))
    550 	clone_parm = DECL_CHAIN (clone_parm);
    551       for (; parm && clone_parm;
    552 	   parm = DECL_CHAIN (parm), clone_parm = DECL_CHAIN (clone_parm))
    553 	/* Update this parameter.  */
    554 	update_cloned_parm (parm, clone_parm, first);
    555     }
    556 
    557   bool can_alias = can_alias_cdtor (fn);
    558 
    559   /* If we decide to turn clones into thunks, they will branch to fn.
    560      Must have original function available to call.  */
    561   if (!can_alias && maybe_thunk_body (fn, need_alias))
    562     {
    563       pop_from_top_level ();
    564       /* We still need to emit the original function.  */
    565       return 0;
    566     }
    567 
    568   /* Emit the DWARF1 abstract instance.  */
    569   (*debug_hooks->deferred_inline_function) (fn);
    570 
    571   /* We know that any clones immediately follow FN in the TYPE_FIELDS. */
    572   for (idx = 0; idx < 3; idx++)
    573     {
    574       tree parm;
    575       tree clone_parm;
    576       int parmno;
    577       hash_map<tree, tree> *decl_map;
    578       bool alias = false;
    579 
    580       clone = fns[idx];
    581       if (!clone)
    582 	continue;
    583 
    584       /* Start processing the function.  */
    585       start_preparsed_function (clone, NULL_TREE, SF_PRE_PARSED);
    586 
    587       /* Tell cgraph if both ctors or both dtors are known to have
    588 	 the same body.  */
    589       if (can_alias
    590 	  && fns[0]
    591 	  && idx == 1
    592 	  && cgraph_node::get_create (fns[0])->create_same_body_alias
    593 	       (clone, fns[0]))
    594 	{
    595 	  alias = true;
    596 	  if (DECL_ONE_ONLY (fns[0]))
    597 	    {
    598 	      /* For comdat base and complete cdtors put them
    599 		 into the same, *[CD]5* comdat group instead of
    600 		 *[CD][12]*.  */
    601 	      comdat_group = cdtor_comdat_group (fns[1], fns[0]);
    602 	      cgraph_node::get_create (fns[0])->set_comdat_group (comdat_group);
    603 	      if (symtab_node::get (clone)->same_comdat_group)
    604 		symtab_node::get (clone)->remove_from_same_comdat_group ();
    605 	      symtab_node::get (clone)->add_to_same_comdat_group
    606 		(symtab_node::get (fns[0]));
    607 	    }
    608 	}
    609 
    610       /* Build the delete destructor by calling complete destructor
    611          and delete function.  */
    612       if (idx == 2)
    613 	{
    614 	  build_delete_destructor_body (clone, fns[1]);
    615 	  /* If *[CD][12]* dtors go into the *[CD]5* comdat group and dtor is
    616 	     virtual, it goes into the same comdat group as well.  */
    617 	  if (comdat_group)
    618 	    cgraph_node::get_create (clone)->add_to_same_comdat_group
    619 	      (symtab_node::get (fns[0]));
    620 	}
    621       else if (alias)
    622 	/* No need to populate body.  */ ;
    623       else
    624 	{
    625 	  /* If we can't have multiple copies of FN (say, because there's a
    626 	     static local initialized with the address of a label), we need
    627 	     to use an alias for the complete variant.  */
    628 	  if (idx == 1 && need_alias)
    629 	    {
    630 	      if (DECL_STRUCT_FUNCTION (fn)->cannot_be_copied_set)
    631 		sorry (DECL_STRUCT_FUNCTION (fn)->cannot_be_copied_reason, fn);
    632 	      else
    633 		sorry ("making multiple clones of %qD", fn);
    634 	    }
    635 
    636           /* Remap the parameters.  */
    637           decl_map = new hash_map<tree, tree>;
    638           for (parmno = 0,
    639                 parm = DECL_ARGUMENTS (fn),
    640                 clone_parm = DECL_ARGUMENTS (clone);
    641               parm;
    642               ++parmno,
    643                 parm = DECL_CHAIN (parm))
    644             {
    645               /* Map the in-charge parameter to an appropriate constant.  */
    646               if (DECL_HAS_IN_CHARGE_PARM_P (fn) && parmno == 1)
    647                 {
    648                   tree in_charge;
    649                   in_charge = in_charge_arg_for_name (DECL_NAME (clone));
    650                   decl_map->put (parm, in_charge);
    651                 }
    652               else if (DECL_ARTIFICIAL (parm)
    653                        && DECL_NAME (parm) == vtt_parm_identifier)
    654                 {
    655                   /* For a subobject constructor or destructor, the next
    656                      argument is the VTT parameter.  Remap the VTT_PARM
    657                      from the CLONE to this parameter.  */
    658                   if (DECL_HAS_VTT_PARM_P (clone))
    659                     {
    660                       DECL_ABSTRACT_ORIGIN (clone_parm) = parm;
    661                       decl_map->put (parm, clone_parm);
    662                       clone_parm = DECL_CHAIN (clone_parm);
    663                     }
    664                   /* Otherwise, map the VTT parameter to `NULL'.  */
    665                   else
    666 		    {
    667 		      tree t
    668 			= fold_convert (TREE_TYPE (parm), null_pointer_node);
    669 		      decl_map->put (parm, t);
    670 		    }
    671                 }
    672               /* Map other parameters to their equivalents in the cloned
    673                  function.  */
    674               else
    675                 {
    676 		  tree replacement;
    677 		  if (clone_parm)
    678 		    {
    679 		      replacement = clone_parm;
    680 		      clone_parm = DECL_CHAIN (clone_parm);
    681 		    }
    682 		  else
    683 		    {
    684 		      /* Inheriting ctors can omit parameters from the base
    685 			 clone.  Replace them with null lvalues.  */
    686 		      tree reftype = build_reference_type (TREE_TYPE (parm));
    687 		      replacement = fold_convert (reftype, null_pointer_node);
    688 		      replacement = convert_from_reference (replacement);
    689 		    }
    690                   decl_map->put (parm, replacement);
    691                 }
    692             }
    693 
    694           if (targetm.cxx.cdtor_returns_this ())
    695             {
    696               parm = DECL_RESULT (fn);
    697               clone_parm = DECL_RESULT (clone);
    698               decl_map->put (parm, clone_parm);
    699             }
    700 
    701           /* Clone the body.  */
    702           clone_body (clone, fn, decl_map);
    703 
    704           /* Clean up.  */
    705           delete decl_map;
    706         }
    707 
    708       /* The clone can throw iff the original function can throw.  */
    709       cp_function_chain->can_throw = !TREE_NOTHROW (fn);
    710 
    711       /* Now, expand this function into RTL, if appropriate.  */
    712       finish_function (/*inline_p=*/false);
    713       BLOCK_ABSTRACT_ORIGIN (DECL_INITIAL (clone)) = DECL_INITIAL (fn);
    714       if (alias)
    715 	{
    716 	  if (expand_or_defer_fn_1 (clone))
    717 	    emit_associated_thunks (clone);
    718 	  /* We didn't generate a body, so remove the empty one.  */
    719 	  DECL_SAVED_TREE (clone) = void_node;
    720 	}
    721       else
    722 	expand_or_defer_fn (clone);
    723       first = false;
    724     }
    725   pop_from_top_level ();
    726 
    727   /* We don't need to process the original function any further.  */
    728   return 1;
    729 }
    730