1 /* Perform optimizations on tree structure.
2    Copyright (C) 1998-2019 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   /* ??? Why not use aliases with -frepo?  */
227   if (flag_use_repository)
228     return false;
229   gcc_assert (DECL_MAYBE_IN_CHARGE_CDTOR_P (fn));
230   /* Don't use aliases for weak/linkonce definitions unless we can put both
231      symbols in the same COMDAT group.  */
232   return (DECL_INTERFACE_KNOWN (fn)
233 	  && (SUPPORTS_ONE_ONLY || !DECL_WEAK (fn))
234 	  && (!DECL_ONE_ONLY (fn)
235 	      || (HAVE_COMDAT_GROUP && DECL_WEAK (fn))));
236 }
237 
238 /* FN is a [cd]tor, fns is a pointer to an array of length 3.  Fill fns
239    with pointers to the base, complete, and deleting variants.  */
240 
241 static void
populate_clone_array(tree fn,tree * fns)242 populate_clone_array (tree fn, tree *fns)
243 {
244   tree clone;
245 
246   fns[0] = NULL_TREE;
247   fns[1] = NULL_TREE;
248   fns[2] = NULL_TREE;
249 
250   /* Look for the complete destructor which may be used to build the
251      delete destructor.  */
252   FOR_EACH_CLONE (clone, fn)
253     if (DECL_NAME (clone) == complete_dtor_identifier
254 	|| DECL_NAME (clone) == complete_ctor_identifier)
255       fns[1] = clone;
256     else if (DECL_NAME (clone) == base_dtor_identifier
257 	     || DECL_NAME (clone) == base_ctor_identifier)
258       fns[0] = clone;
259     else if (DECL_NAME (clone) == deleting_dtor_identifier)
260       fns[2] = clone;
261     else
262       gcc_unreachable ();
263 }
264 
265 /* FN is a constructor or destructor, and there are FUNCTION_DECLs
266    cloned from it nearby.  Instead of cloning this body, leave it
267    alone and create tiny one-call bodies for the cloned
268    FUNCTION_DECLs.  These clones are sibcall candidates, and their
269    resulting code will be very thunk-esque.  */
270 
271 static bool
maybe_thunk_body(tree fn,bool force)272 maybe_thunk_body (tree fn, bool force)
273 {
274   tree bind, block, call, clone, clone_result, fn_parm, fn_parm_typelist;
275   tree last_arg, modify, *args;
276   int parmno, vtt_parmno, max_parms;
277   tree fns[3];
278 
279   if (!force && !flag_declone_ctor_dtor)
280     return 0;
281 
282   /* If function accepts variable arguments, give up.  */
283   last_arg = tree_last (TYPE_ARG_TYPES (TREE_TYPE (fn)));
284   if (last_arg != void_list_node)
285     return 0;
286 
287   /* If we got this far, we've decided to turn the clones into thunks.  */
288 
289   /* We're going to generate code for fn, so it is no longer "abstract."
290      Also make the unified ctor/dtor private to either the translation unit
291      (for non-vague linkage ctors) or the COMDAT group (otherwise).  */
292 
293   populate_clone_array (fn, fns);
294 
295   /* Can happen during error recovery (c++/71464).  */
296   if (!fns[0] || !fns[1])
297     return 0;
298 
299   /* Don't use thunks if the base clone omits inherited parameters.  */
300   if (ctor_omit_inherited_parms (fns[0]))
301     return 0;
302 
303   DECL_ABSTRACT_P (fn) = false;
304   if (!DECL_WEAK (fn))
305     {
306       TREE_PUBLIC (fn) = false;
307       DECL_EXTERNAL (fn) = false;
308       DECL_INTERFACE_KNOWN (fn) = true;
309     }
310   else if (HAVE_COMDAT_GROUP)
311     {
312       /* At eof, defer creation of mangling aliases temporarily.  */
313       bool save_defer_mangling_aliases = defer_mangling_aliases;
314       defer_mangling_aliases = true;
315       tree comdat_group = cdtor_comdat_group (fns[1], fns[0]);
316       defer_mangling_aliases = save_defer_mangling_aliases;
317       cgraph_node::get_create (fns[0])->set_comdat_group (comdat_group);
318       cgraph_node::get_create (fns[1])->add_to_same_comdat_group
319 	(cgraph_node::get_create (fns[0]));
320       symtab_node::get (fn)->add_to_same_comdat_group
321 	(symtab_node::get (fns[0]));
322       if (fns[2])
323 	/* If *[CD][12]* dtors go into the *[CD]5* comdat group and dtor is
324 	   virtual, it goes into the same comdat group as well.  */
325 	cgraph_node::get_create (fns[2])->add_to_same_comdat_group
326 	  (symtab_node::get (fns[0]));
327       /* Emit them now that the thunks are same comdat group aliases.  */
328       if (!save_defer_mangling_aliases)
329 	generate_mangling_aliases ();
330       TREE_PUBLIC (fn) = false;
331       DECL_EXTERNAL (fn) = false;
332       DECL_INTERFACE_KNOWN (fn) = true;
333       /* function_and_variable_visibility doesn't want !PUBLIC decls to
334 	 have these flags set.  */
335       DECL_WEAK (fn) = false;
336       DECL_COMDAT (fn) = false;
337     }
338 
339   /* Find the vtt_parm, if present.  */
340   for (vtt_parmno = -1, parmno = 0, fn_parm = DECL_ARGUMENTS (fn);
341        fn_parm;
342        ++parmno, fn_parm = TREE_CHAIN (fn_parm))
343     {
344       if (DECL_ARTIFICIAL (fn_parm)
345 	  && DECL_NAME (fn_parm) == vtt_parm_identifier)
346 	{
347 	  /* Compensate for removed in_charge parameter.  */
348 	  vtt_parmno = parmno;
349 	  break;
350 	}
351     }
352 
353   /* Allocate an argument buffer for build_cxx_call().
354      Make sure it is large enough for any of the clones.  */
355   max_parms = 0;
356   FOR_EACH_CLONE (clone, fn)
357     {
358       int length = list_length (DECL_ARGUMENTS (fn));
359       if (length > max_parms)
360         max_parms = length;
361     }
362   args = XALLOCAVEC (tree, max_parms);
363 
364   /* We know that any clones immediately follow FN in TYPE_FIELDS.  */
365   FOR_EACH_CLONE (clone, fn)
366     {
367       tree clone_parm;
368 
369       /* If we've already generated a body for this clone, avoid
370 	 duplicating it.  (Is it possible for a clone-list to grow after we
371 	 first see it?)  */
372       if (DECL_SAVED_TREE (clone) || TREE_ASM_WRITTEN (clone))
373 	continue;
374 
375       /* Start processing the function.  */
376       start_preparsed_function (clone, NULL_TREE, SF_PRE_PARSED);
377 
378       if (clone == fns[2])
379 	{
380 	  for (clone_parm = DECL_ARGUMENTS (clone); clone_parm;
381 	       clone_parm = TREE_CHAIN (clone_parm))
382 	    DECL_ABSTRACT_ORIGIN (clone_parm) = NULL_TREE;
383 	  /* Build the delete destructor by calling complete destructor and
384 	     delete function.  */
385 	  build_delete_destructor_body (clone, fns[1]);
386 	}
387       else
388 	{
389 	  /* Walk parameter lists together, creating parameter list for
390 	     call to original function.  */
391 	  for (parmno = 0,
392 		 fn_parm = DECL_ARGUMENTS (fn),
393 		 fn_parm_typelist = TYPE_ARG_TYPES (TREE_TYPE (fn)),
394 		 clone_parm = DECL_ARGUMENTS (clone);
395 	       fn_parm;
396 	       ++parmno,
397 		 fn_parm = TREE_CHAIN (fn_parm))
398 	    {
399 	      if (parmno == vtt_parmno && ! DECL_HAS_VTT_PARM_P (clone))
400 		{
401 		  gcc_assert (fn_parm_typelist);
402 		  /* Clobber argument with formal parameter type.  */
403 		  args[parmno]
404 		    = convert (TREE_VALUE (fn_parm_typelist),
405 			       null_pointer_node);
406 		}
407 	      else if (parmno == 1 && DECL_HAS_IN_CHARGE_PARM_P (fn))
408 		{
409 		  tree in_charge
410 		    = copy_node (in_charge_arg_for_name (DECL_NAME (clone)));
411 		  args[parmno] = in_charge;
412 		}
413 	      /* Map other parameters to their equivalents in the cloned
414 		 function.  */
415 	      else
416 		{
417 		  gcc_assert (clone_parm);
418 		  DECL_ABSTRACT_ORIGIN (clone_parm) = NULL;
419 		  args[parmno] = clone_parm;
420 		  /* Clear TREE_ADDRESSABLE on thunk arguments.  */
421 		  TREE_ADDRESSABLE (clone_parm) = 0;
422 		  clone_parm = TREE_CHAIN (clone_parm);
423 		}
424 	      if (fn_parm_typelist)
425 		fn_parm_typelist = TREE_CHAIN (fn_parm_typelist);
426 	    }
427 
428 	  /* We built this list backwards; fix now.  */
429 	  mark_used (fn);
430 	  call = build_cxx_call (fn, parmno, args, tf_warning_or_error);
431 	  /* Arguments passed to the thunk by invisible reference should
432 	     be transmitted to the callee unchanged.  Do not create a
433 	     temporary and invoke the copy constructor.  The thunking
434 	     transformation must not introduce any constructor calls.  */
435 	  CALL_FROM_THUNK_P (call) = 1;
436 	  block = make_node (BLOCK);
437 	  if (targetm.cxx.cdtor_returns_this ())
438 	    {
439 	      clone_result = DECL_RESULT (clone);
440 	      modify = build2 (MODIFY_EXPR, TREE_TYPE (clone_result),
441 			       clone_result, call);
442 	      modify = build1 (RETURN_EXPR, void_type_node, modify);
443 	      add_stmt (modify);
444 	    }
445 	  else
446 	    {
447 	      add_stmt (call);
448 	    }
449 	  bind = c_build_bind_expr (DECL_SOURCE_LOCATION (clone),
450 				    block, cur_stmt_list);
451 	  DECL_SAVED_TREE (clone) = push_stmt_list ();
452 	  add_stmt (bind);
453 	}
454 
455       DECL_ABSTRACT_ORIGIN (clone) = NULL;
456       expand_or_defer_fn (finish_function (/*inline_p=*/false));
457     }
458   return 1;
459 }
460 
461 /* FN is a function that has a complete body.  Clone the body as
462    necessary.  Returns nonzero if there's no longer any need to
463    process the main body.  */
464 
465 bool
maybe_clone_body(tree fn)466 maybe_clone_body (tree fn)
467 {
468   tree comdat_group = NULL_TREE;
469   tree clone;
470   tree fns[3];
471   bool first = true;
472   int idx;
473   bool need_alias = false;
474 
475   /* We only clone constructors and destructors.  */
476   if (!DECL_MAYBE_IN_CHARGE_CDTOR_P (fn))
477     return 0;
478 
479   populate_clone_array (fn, fns);
480 
481   /* Remember if we can't have multiple clones for some reason.  We need to
482      check this before we remap local static initializers in clone_body.  */
483   if (!tree_versionable_function_p (fn))
484     need_alias = true;
485 
486   /* We know that any clones immediately follow FN in the TYPE_FIELDS
487      list.  */
488   push_to_top_level ();
489   for (idx = 0; idx < 3; idx++)
490     {
491       tree parm;
492       tree clone_parm;
493 
494       clone = fns[idx];
495       if (!clone)
496 	continue;
497 
498       /* Update CLONE's source position information to match FN's.  */
499       DECL_SOURCE_LOCATION (clone) = DECL_SOURCE_LOCATION (fn);
500       DECL_DECLARED_INLINE_P (clone) = DECL_DECLARED_INLINE_P (fn);
501       DECL_DECLARED_CONSTEXPR_P (clone) = DECL_DECLARED_CONSTEXPR_P (fn);
502       DECL_COMDAT (clone) = DECL_COMDAT (fn);
503       DECL_WEAK (clone) = DECL_WEAK (fn);
504 
505       /* We don't copy the comdat group from fn to clone because the assembler
506 	 name of fn was corrupted by write_mangled_name by adding *INTERNAL*
507 	 to it. By doing so, it also corrupted the comdat group. */
508       if (DECL_ONE_ONLY (fn))
509 	cgraph_node::get_create (clone)->set_comdat_group (cxx_comdat_group (clone));
510       DECL_USE_TEMPLATE (clone) = DECL_USE_TEMPLATE (fn);
511       DECL_EXTERNAL (clone) = DECL_EXTERNAL (fn);
512       DECL_INTERFACE_KNOWN (clone) = DECL_INTERFACE_KNOWN (fn);
513       DECL_NOT_REALLY_EXTERN (clone) = DECL_NOT_REALLY_EXTERN (fn);
514       TREE_PUBLIC (clone) = TREE_PUBLIC (fn);
515       DECL_VISIBILITY (clone) = DECL_VISIBILITY (fn);
516       DECL_VISIBILITY_SPECIFIED (clone) = DECL_VISIBILITY_SPECIFIED (fn);
517       DECL_DLLIMPORT_P (clone) = DECL_DLLIMPORT_P (fn);
518       DECL_ATTRIBUTES (clone) = copy_list (DECL_ATTRIBUTES (fn));
519       DECL_DISREGARD_INLINE_LIMITS (clone) = DECL_DISREGARD_INLINE_LIMITS (fn);
520       set_decl_section_name (clone, DECL_SECTION_NAME (fn));
521 
522       /* Adjust the parameter names and locations.  */
523       parm = DECL_ARGUMENTS (fn);
524       clone_parm = DECL_ARGUMENTS (clone);
525       /* Update the `this' parameter, which is always first.  */
526       update_cloned_parm (parm, clone_parm, first);
527       parm = DECL_CHAIN (parm);
528       clone_parm = DECL_CHAIN (clone_parm);
529       if (DECL_HAS_IN_CHARGE_PARM_P (fn))
530 	parm = DECL_CHAIN (parm);
531       if (DECL_HAS_VTT_PARM_P (fn))
532 	parm = DECL_CHAIN (parm);
533       if (DECL_HAS_VTT_PARM_P (clone))
534 	clone_parm = DECL_CHAIN (clone_parm);
535       for (; parm && clone_parm;
536 	   parm = DECL_CHAIN (parm), clone_parm = DECL_CHAIN (clone_parm))
537 	/* Update this parameter.  */
538 	update_cloned_parm (parm, clone_parm, first);
539     }
540 
541   bool can_alias = can_alias_cdtor (fn);
542 
543   /* If we decide to turn clones into thunks, they will branch to fn.
544      Must have original function available to call.  */
545   if (!can_alias && maybe_thunk_body (fn, need_alias))
546     {
547       pop_from_top_level ();
548       /* We still need to emit the original function.  */
549       return 0;
550     }
551 
552   /* Emit the DWARF1 abstract instance.  */
553   (*debug_hooks->deferred_inline_function) (fn);
554 
555   /* We know that any clones immediately follow FN in the TYPE_FIELDS. */
556   for (idx = 0; idx < 3; idx++)
557     {
558       tree parm;
559       tree clone_parm;
560       int parmno;
561       hash_map<tree, tree> *decl_map;
562       bool alias = false;
563 
564       clone = fns[idx];
565       if (!clone)
566 	continue;
567 
568       /* Start processing the function.  */
569       start_preparsed_function (clone, NULL_TREE, SF_PRE_PARSED);
570 
571       /* Tell cgraph if both ctors or both dtors are known to have
572 	 the same body.  */
573       if (can_alias
574 	  && fns[0]
575 	  && idx == 1
576 	  && cgraph_node::get_create (fns[0])->create_same_body_alias
577 	       (clone, fns[0]))
578 	{
579 	  alias = true;
580 	  if (DECL_ONE_ONLY (fns[0]))
581 	    {
582 	      /* For comdat base and complete cdtors put them
583 		 into the same, *[CD]5* comdat group instead of
584 		 *[CD][12]*.  */
585 	      comdat_group = cdtor_comdat_group (fns[1], fns[0]);
586 	      cgraph_node::get_create (fns[0])->set_comdat_group (comdat_group);
587 	      if (symtab_node::get (clone)->same_comdat_group)
588 		symtab_node::get (clone)->remove_from_same_comdat_group ();
589 	      symtab_node::get (clone)->add_to_same_comdat_group
590 		(symtab_node::get (fns[0]));
591 	    }
592 	}
593 
594       /* Build the delete destructor by calling complete destructor
595          and delete function.  */
596       if (idx == 2)
597 	{
598 	  build_delete_destructor_body (clone, fns[1]);
599 	  /* If *[CD][12]* dtors go into the *[CD]5* comdat group and dtor is
600 	     virtual, it goes into the same comdat group as well.  */
601 	  if (comdat_group)
602 	    cgraph_node::get_create (clone)->add_to_same_comdat_group
603 	      (symtab_node::get (fns[0]));
604 	}
605       else if (alias)
606 	/* No need to populate body.  */ ;
607       else
608 	{
609 	  /* If we can't have multiple copies of FN (say, because there's a
610 	     static local initialized with the address of a label), we need
611 	     to use an alias for the complete variant.  */
612 	  if (idx == 1 && need_alias)
613 	    {
614 	      if (DECL_STRUCT_FUNCTION (fn)->cannot_be_copied_set)
615 		sorry (DECL_STRUCT_FUNCTION (fn)->cannot_be_copied_reason, fn);
616 	      else
617 		sorry ("making multiple clones of %qD", fn);
618 	    }
619 
620           /* Remap the parameters.  */
621           decl_map = new hash_map<tree, tree>;
622           for (parmno = 0,
623                 parm = DECL_ARGUMENTS (fn),
624                 clone_parm = DECL_ARGUMENTS (clone);
625               parm;
626               ++parmno,
627                 parm = DECL_CHAIN (parm))
628             {
629               /* Map the in-charge parameter to an appropriate constant.  */
630               if (DECL_HAS_IN_CHARGE_PARM_P (fn) && parmno == 1)
631                 {
632                   tree in_charge;
633                   in_charge = in_charge_arg_for_name (DECL_NAME (clone));
634                   decl_map->put (parm, in_charge);
635                 }
636               else if (DECL_ARTIFICIAL (parm)
637                        && DECL_NAME (parm) == vtt_parm_identifier)
638                 {
639                   /* For a subobject constructor or destructor, the next
640                      argument is the VTT parameter.  Remap the VTT_PARM
641                      from the CLONE to this parameter.  */
642                   if (DECL_HAS_VTT_PARM_P (clone))
643                     {
644                       DECL_ABSTRACT_ORIGIN (clone_parm) = parm;
645                       decl_map->put (parm, clone_parm);
646                       clone_parm = DECL_CHAIN (clone_parm);
647                     }
648                   /* Otherwise, map the VTT parameter to `NULL'.  */
649                   else
650 		    {
651 		      tree t
652 			= fold_convert (TREE_TYPE (parm), null_pointer_node);
653 		      decl_map->put (parm, t);
654 		    }
655                 }
656               /* Map other parameters to their equivalents in the cloned
657                  function.  */
658               else
659                 {
660 		  tree replacement;
661 		  if (clone_parm)
662 		    {
663 		      replacement = clone_parm;
664 		      clone_parm = DECL_CHAIN (clone_parm);
665 		    }
666 		  else
667 		    {
668 		      /* Inheriting ctors can omit parameters from the base
669 			 clone.  Replace them with null lvalues.  */
670 		      tree reftype = build_reference_type (TREE_TYPE (parm));
671 		      replacement = fold_convert (reftype, null_pointer_node);
672 		      replacement = convert_from_reference (replacement);
673 		    }
674                   decl_map->put (parm, replacement);
675                 }
676             }
677 
678           if (targetm.cxx.cdtor_returns_this ())
679             {
680               parm = DECL_RESULT (fn);
681               clone_parm = DECL_RESULT (clone);
682               decl_map->put (parm, clone_parm);
683             }
684 
685           /* Clone the body.  */
686           clone_body (clone, fn, decl_map);
687 
688           /* Clean up.  */
689           delete decl_map;
690         }
691 
692       /* The clone can throw iff the original function can throw.  */
693       cp_function_chain->can_throw = !TREE_NOTHROW (fn);
694 
695       /* Now, expand this function into RTL, if appropriate.  */
696       finish_function (/*inline_p=*/false);
697       BLOCK_ABSTRACT_ORIGIN (DECL_INITIAL (clone)) = DECL_INITIAL (fn);
698       if (alias)
699 	{
700 	  if (expand_or_defer_fn_1 (clone))
701 	    emit_associated_thunks (clone);
702 	  /* We didn't generate a body, so remove the empty one.  */
703 	  DECL_SAVED_TREE (clone) = NULL_TREE;
704 	}
705       else
706 	expand_or_defer_fn (clone);
707       first = false;
708     }
709   pop_from_top_level ();
710 
711   /* We don't need to process the original function any further.  */
712   return 1;
713 }
714