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