xref: /dflybsd-src/contrib/gcc-8.0/gcc/cp/optimize.c (revision 95059079af47f9a66a175f374f2da1a5020e3255)
138fd1498Szrj /* Perform optimizations on tree structure.
238fd1498Szrj    Copyright (C) 1998-2018 Free Software Foundation, Inc.
338fd1498Szrj    Written by Mark Michell (mark@codesourcery.com).
438fd1498Szrj 
538fd1498Szrj This file is part of GCC.
638fd1498Szrj 
738fd1498Szrj GCC is free software; you can redistribute it and/or modify it
838fd1498Szrj under the terms of the GNU General Public License as published by
938fd1498Szrj the Free Software Foundation; either version 3, or (at your option)
1038fd1498Szrj any later version.
1138fd1498Szrj 
1238fd1498Szrj GCC is distributed in the hope that it will be useful, but
1338fd1498Szrj WITHOUT ANY WARRANTY; without even the implied warranty of
1438fd1498Szrj MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
1538fd1498Szrj General Public License for more details.
1638fd1498Szrj 
1738fd1498Szrj You should have received a copy of the GNU General Public License
1838fd1498Szrj along with GCC; see the file COPYING3.  If not see
1938fd1498Szrj <http://www.gnu.org/licenses/>.  */
2038fd1498Szrj 
2138fd1498Szrj #include "config.h"
2238fd1498Szrj #include "system.h"
2338fd1498Szrj #include "coretypes.h"
2438fd1498Szrj #include "target.h"
2538fd1498Szrj #include "cp-tree.h"
2638fd1498Szrj #include "stringpool.h"
2738fd1498Szrj #include "cgraph.h"
2838fd1498Szrj #include "debug.h"
2938fd1498Szrj #include "tree-inline.h"
3038fd1498Szrj #include "tree-iterator.h"
3138fd1498Szrj 
3238fd1498Szrj /* Prototypes.  */
3338fd1498Szrj 
3438fd1498Szrj static void update_cloned_parm (tree, tree, bool);
3538fd1498Szrj 
3638fd1498Szrj /* CLONED_PARM is a copy of CLONE, generated for a cloned constructor
3738fd1498Szrj    or destructor.  Update it to ensure that the source-position for
3838fd1498Szrj    the cloned parameter matches that for the original, and that the
3938fd1498Szrj    debugging generation code will be able to find the original PARM.  */
4038fd1498Szrj 
4138fd1498Szrj static void
update_cloned_parm(tree parm,tree cloned_parm,bool first)4238fd1498Szrj update_cloned_parm (tree parm, tree cloned_parm, bool first)
4338fd1498Szrj {
4438fd1498Szrj   DECL_ABSTRACT_ORIGIN (cloned_parm) = parm;
4538fd1498Szrj 
4638fd1498Szrj   /* We may have taken its address.  */
4738fd1498Szrj   TREE_ADDRESSABLE (cloned_parm) = TREE_ADDRESSABLE (parm);
4838fd1498Szrj 
49*58e805e6Szrj   DECL_BY_REFERENCE (cloned_parm) = DECL_BY_REFERENCE (parm);
50*58e805e6Szrj 
5138fd1498Szrj   /* The definition might have different constness.  */
5238fd1498Szrj   TREE_READONLY (cloned_parm) = TREE_READONLY (parm);
5338fd1498Szrj 
5438fd1498Szrj   TREE_USED (cloned_parm) = !first || TREE_USED (parm);
5538fd1498Szrj 
5638fd1498Szrj   /* The name may have changed from the declaration.  */
5738fd1498Szrj   DECL_NAME (cloned_parm) = DECL_NAME (parm);
5838fd1498Szrj   DECL_SOURCE_LOCATION (cloned_parm) = DECL_SOURCE_LOCATION (parm);
5938fd1498Szrj   TREE_TYPE (cloned_parm) = TREE_TYPE (parm);
6038fd1498Szrj 
6138fd1498Szrj   DECL_GIMPLE_REG_P (cloned_parm) = DECL_GIMPLE_REG_P (parm);
6238fd1498Szrj }
6338fd1498Szrj 
64*58e805e6Szrj /* Like copy_decl_no_change, but handle DECL_OMP_PRIVATIZED_MEMBER
65*58e805e6Szrj    properly.  */
66*58e805e6Szrj 
67*58e805e6Szrj static tree
cxx_copy_decl(tree decl,copy_body_data * id)68*58e805e6Szrj cxx_copy_decl (tree decl, copy_body_data *id)
69*58e805e6Szrj {
70*58e805e6Szrj   tree copy = copy_decl_no_change (decl, id);
71*58e805e6Szrj   if (VAR_P (decl)
72*58e805e6Szrj       && DECL_HAS_VALUE_EXPR_P (decl)
73*58e805e6Szrj       && DECL_ARTIFICIAL (decl)
74*58e805e6Szrj       && DECL_LANG_SPECIFIC (decl)
75*58e805e6Szrj       && DECL_OMP_PRIVATIZED_MEMBER (decl))
76*58e805e6Szrj     {
77*58e805e6Szrj       tree expr = DECL_VALUE_EXPR (copy);
78*58e805e6Szrj       walk_tree (&expr, copy_tree_body_r, id, NULL);
79*58e805e6Szrj       SET_DECL_VALUE_EXPR (copy, expr);
80*58e805e6Szrj     }
81*58e805e6Szrj   return copy;
82*58e805e6Szrj }
8338fd1498Szrj 
8438fd1498Szrj /* FN is a function in High GIMPLE form that has a complete body and no
8538fd1498Szrj    CFG.  CLONE is a function whose body is to be set to a copy of FN,
8638fd1498Szrj    mapping argument declarations according to the ARG_MAP splay_tree.  */
8738fd1498Szrj 
8838fd1498Szrj static void
clone_body(tree clone,tree fn,void * arg_map)8938fd1498Szrj clone_body (tree clone, tree fn, void *arg_map)
9038fd1498Szrj {
9138fd1498Szrj   copy_body_data id;
9238fd1498Szrj   tree stmts;
9338fd1498Szrj 
9438fd1498Szrj   /* Clone the body, as if we were making an inline call.  But, remap
9538fd1498Szrj      the parameters in the callee to the parameters of caller.  */
9638fd1498Szrj   memset (&id, 0, sizeof (id));
9738fd1498Szrj   id.src_fn = fn;
9838fd1498Szrj   id.dst_fn = clone;
9938fd1498Szrj   id.src_cfun = DECL_STRUCT_FUNCTION (fn);
10038fd1498Szrj   id.decl_map = static_cast<hash_map<tree, tree> *> (arg_map);
10138fd1498Szrj 
102*58e805e6Szrj   id.copy_decl = cxx_copy_decl;
10338fd1498Szrj   id.transform_call_graph_edges = CB_CGE_DUPLICATE;
10438fd1498Szrj   id.transform_new_cfg = true;
10538fd1498Szrj   id.transform_return_to_modify = false;
10638fd1498Szrj   id.transform_lang_insert_block = NULL;
10738fd1498Szrj 
10838fd1498Szrj   /* We're not inside any EH region.  */
10938fd1498Szrj   id.eh_lp_nr = 0;
11038fd1498Szrj 
11138fd1498Szrj   stmts = DECL_SAVED_TREE (fn);
11238fd1498Szrj   walk_tree (&stmts, copy_tree_body_r, &id, NULL);
11338fd1498Szrj 
11438fd1498Szrj   /* Also remap the initializer of any static variables so that they (in
11538fd1498Szrj      particular, any label addresses) correspond to the base variant rather
11638fd1498Szrj      than the abstract one.  */
11738fd1498Szrj   if (DECL_NAME (clone) == base_dtor_identifier
11838fd1498Szrj       || DECL_NAME (clone) == base_ctor_identifier)
11938fd1498Szrj     {
12038fd1498Szrj       unsigned ix;
12138fd1498Szrj       tree decl;
12238fd1498Szrj 
12338fd1498Szrj       FOR_EACH_LOCAL_DECL (DECL_STRUCT_FUNCTION (fn), ix, decl)
12438fd1498Szrj         walk_tree (&DECL_INITIAL (decl), copy_tree_body_r, &id, NULL);
12538fd1498Szrj     }
12638fd1498Szrj 
12738fd1498Szrj   append_to_statement_list_force (stmts, &DECL_SAVED_TREE (clone));
12838fd1498Szrj }
12938fd1498Szrj 
13038fd1498Szrj /* DELETE_DTOR is a delete destructor whose body will be built.
13138fd1498Szrj    COMPLETE_DTOR is the corresponding complete destructor.  */
13238fd1498Szrj 
13338fd1498Szrj static void
build_delete_destructor_body(tree delete_dtor,tree complete_dtor)13438fd1498Szrj build_delete_destructor_body (tree delete_dtor, tree complete_dtor)
13538fd1498Szrj {
13638fd1498Szrj   tree parm = DECL_ARGUMENTS (delete_dtor);
13738fd1498Szrj   tree virtual_size = cxx_sizeof (current_class_type);
13838fd1498Szrj 
13938fd1498Szrj   /* Call the corresponding complete destructor.  */
14038fd1498Szrj   gcc_assert (complete_dtor);
14138fd1498Szrj   tree call_dtor = build_cxx_call (complete_dtor, 1, &parm,
14238fd1498Szrj 				   tf_warning_or_error);
14338fd1498Szrj 
14438fd1498Szrj   /* Call the delete function.  */
14538fd1498Szrj   tree call_delete = build_op_delete_call (DELETE_EXPR, current_class_ptr,
14638fd1498Szrj 					   virtual_size,
14738fd1498Szrj 					   /*global_p=*/false,
14838fd1498Szrj 					   /*placement=*/NULL_TREE,
14938fd1498Szrj 					   /*alloc_fn=*/NULL_TREE,
15038fd1498Szrj 					   tf_warning_or_error);
15138fd1498Szrj 
15238fd1498Szrj   /* Operator delete must be called, whether or not the dtor throws.  */
15338fd1498Szrj   add_stmt (build2 (TRY_FINALLY_EXPR, void_type_node, call_dtor, call_delete));
15438fd1498Szrj 
15538fd1498Szrj   /* Return the address of the object.  */
15638fd1498Szrj   if (targetm.cxx.cdtor_returns_this ())
15738fd1498Szrj     {
15838fd1498Szrj       tree val = DECL_ARGUMENTS (delete_dtor);
15938fd1498Szrj       val = build2 (MODIFY_EXPR, TREE_TYPE (val),
16038fd1498Szrj                     DECL_RESULT (delete_dtor), val);
16138fd1498Szrj       add_stmt (build_stmt (0, RETURN_EXPR, val));
16238fd1498Szrj     }
16338fd1498Szrj }
16438fd1498Szrj 
16538fd1498Szrj /* Return name of comdat group for complete and base ctor (or dtor)
16638fd1498Szrj    that have the same body.  If dtor is virtual, deleting dtor goes
16738fd1498Szrj    into this comdat group as well.  */
16838fd1498Szrj 
16938fd1498Szrj static tree
cdtor_comdat_group(tree complete,tree base)17038fd1498Szrj cdtor_comdat_group (tree complete, tree base)
17138fd1498Szrj {
17238fd1498Szrj   tree complete_name = DECL_ASSEMBLER_NAME (complete);
17338fd1498Szrj   tree base_name = DECL_ASSEMBLER_NAME (base);
17438fd1498Szrj   char *grp_name;
17538fd1498Szrj   const char *p, *q;
17638fd1498Szrj   bool diff_seen = false;
17738fd1498Szrj   size_t idx;
17838fd1498Szrj   gcc_assert (IDENTIFIER_LENGTH (complete_name)
17938fd1498Szrj 	      == IDENTIFIER_LENGTH (base_name));
18038fd1498Szrj   grp_name = XALLOCAVEC (char, IDENTIFIER_LENGTH (complete_name) + 1);
18138fd1498Szrj   p = IDENTIFIER_POINTER (complete_name);
18238fd1498Szrj   q = IDENTIFIER_POINTER (base_name);
18338fd1498Szrj   for (idx = 0; idx < IDENTIFIER_LENGTH (complete_name); idx++)
18438fd1498Szrj     if (p[idx] == q[idx])
18538fd1498Szrj       grp_name[idx] = p[idx];
18638fd1498Szrj     else
18738fd1498Szrj       {
18838fd1498Szrj 	gcc_assert (!diff_seen
18938fd1498Szrj 		    && idx > 0
19038fd1498Szrj 		    && (p[idx - 1] == 'C' || p[idx - 1] == 'D'
19138fd1498Szrj 			|| p[idx - 1] == 'I')
19238fd1498Szrj 		    && p[idx] == '1'
19338fd1498Szrj 		    && q[idx] == '2');
19438fd1498Szrj 	grp_name[idx] = '5';
19538fd1498Szrj 	diff_seen = true;
19638fd1498Szrj       }
19738fd1498Szrj   grp_name[idx] = '\0';
19838fd1498Szrj   gcc_assert (diff_seen);
19938fd1498Szrj   return get_identifier (grp_name);
20038fd1498Szrj }
20138fd1498Szrj 
20238fd1498Szrj /* Returns true iff we can make the base and complete [cd]tor aliases of
20338fd1498Szrj    the same symbol rather than separate functions.  */
20438fd1498Szrj 
20538fd1498Szrj static bool
can_alias_cdtor(tree fn)20638fd1498Szrj can_alias_cdtor (tree fn)
20738fd1498Szrj {
20838fd1498Szrj   /* If aliases aren't supported by the assembler, fail.  */
20938fd1498Szrj   if (!TARGET_SUPPORTS_ALIASES)
21038fd1498Szrj     return false;
21138fd1498Szrj 
21238fd1498Szrj   /* We can't use an alias if there are virtual bases.  */
21338fd1498Szrj   if (CLASSTYPE_VBASECLASSES (DECL_CONTEXT (fn)))
21438fd1498Szrj     return false;
21538fd1498Szrj   /* ??? Why not use aliases with -frepo?  */
21638fd1498Szrj   if (flag_use_repository)
21738fd1498Szrj     return false;
21838fd1498Szrj   gcc_assert (DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (fn)
21938fd1498Szrj 	      || DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (fn));
22038fd1498Szrj   /* Don't use aliases for weak/linkonce definitions unless we can put both
22138fd1498Szrj      symbols in the same COMDAT group.  */
22238fd1498Szrj   return (DECL_INTERFACE_KNOWN (fn)
22338fd1498Szrj 	  && (SUPPORTS_ONE_ONLY || !DECL_WEAK (fn))
22438fd1498Szrj 	  && (!DECL_ONE_ONLY (fn)
22538fd1498Szrj 	      || (HAVE_COMDAT_GROUP && DECL_WEAK (fn))));
22638fd1498Szrj }
22738fd1498Szrj 
22838fd1498Szrj /* FN is a [cd]tor, fns is a pointer to an array of length 3.  Fill fns
22938fd1498Szrj    with pointers to the base, complete, and deleting variants.  */
23038fd1498Szrj 
23138fd1498Szrj static void
populate_clone_array(tree fn,tree * fns)23238fd1498Szrj populate_clone_array (tree fn, tree *fns)
23338fd1498Szrj {
23438fd1498Szrj   tree clone;
23538fd1498Szrj 
23638fd1498Szrj   fns[0] = NULL_TREE;
23738fd1498Szrj   fns[1] = NULL_TREE;
23838fd1498Szrj   fns[2] = NULL_TREE;
23938fd1498Szrj 
24038fd1498Szrj   /* Look for the complete destructor which may be used to build the
24138fd1498Szrj      delete destructor.  */
24238fd1498Szrj   FOR_EACH_CLONE (clone, fn)
24338fd1498Szrj     if (DECL_NAME (clone) == complete_dtor_identifier
24438fd1498Szrj 	|| DECL_NAME (clone) == complete_ctor_identifier)
24538fd1498Szrj       fns[1] = clone;
24638fd1498Szrj     else if (DECL_NAME (clone) == base_dtor_identifier
24738fd1498Szrj 	     || DECL_NAME (clone) == base_ctor_identifier)
24838fd1498Szrj       fns[0] = clone;
24938fd1498Szrj     else if (DECL_NAME (clone) == deleting_dtor_identifier)
25038fd1498Szrj       fns[2] = clone;
25138fd1498Szrj     else
25238fd1498Szrj       gcc_unreachable ();
25338fd1498Szrj }
25438fd1498Szrj 
25538fd1498Szrj /* FN is a constructor or destructor, and there are FUNCTION_DECLs
25638fd1498Szrj    cloned from it nearby.  Instead of cloning this body, leave it
25738fd1498Szrj    alone and create tiny one-call bodies for the cloned
25838fd1498Szrj    FUNCTION_DECLs.  These clones are sibcall candidates, and their
25938fd1498Szrj    resulting code will be very thunk-esque.  */
26038fd1498Szrj 
26138fd1498Szrj static bool
maybe_thunk_body(tree fn,bool force)26238fd1498Szrj maybe_thunk_body (tree fn, bool force)
26338fd1498Szrj {
26438fd1498Szrj   tree bind, block, call, clone, clone_result, fn_parm, fn_parm_typelist;
26538fd1498Szrj   tree last_arg, modify, *args;
26638fd1498Szrj   int parmno, vtt_parmno, max_parms;
26738fd1498Szrj   tree fns[3];
26838fd1498Szrj 
26938fd1498Szrj   if (!force && !flag_declone_ctor_dtor)
27038fd1498Szrj     return 0;
27138fd1498Szrj 
27238fd1498Szrj   /* If function accepts variable arguments, give up.  */
27338fd1498Szrj   last_arg = tree_last (TYPE_ARG_TYPES (TREE_TYPE (fn)));
27438fd1498Szrj   if (last_arg != void_list_node)
27538fd1498Szrj     return 0;
27638fd1498Szrj 
27738fd1498Szrj   /* If we got this far, we've decided to turn the clones into thunks.  */
27838fd1498Szrj 
27938fd1498Szrj   /* We're going to generate code for fn, so it is no longer "abstract."
28038fd1498Szrj      Also make the unified ctor/dtor private to either the translation unit
28138fd1498Szrj      (for non-vague linkage ctors) or the COMDAT group (otherwise).  */
28238fd1498Szrj 
28338fd1498Szrj   populate_clone_array (fn, fns);
28438fd1498Szrj 
28538fd1498Szrj   /* Can happen during error recovery (c++/71464).  */
28638fd1498Szrj   if (!fns[0] || !fns[1])
28738fd1498Szrj     return 0;
28838fd1498Szrj 
28938fd1498Szrj   /* Don't use thunks if the base clone omits inherited parameters.  */
29038fd1498Szrj   if (ctor_omit_inherited_parms (fns[0]))
29138fd1498Szrj     return 0;
29238fd1498Szrj 
29338fd1498Szrj   DECL_ABSTRACT_P (fn) = false;
29438fd1498Szrj   if (!DECL_WEAK (fn))
29538fd1498Szrj     {
29638fd1498Szrj       TREE_PUBLIC (fn) = false;
29738fd1498Szrj       DECL_EXTERNAL (fn) = false;
29838fd1498Szrj       DECL_INTERFACE_KNOWN (fn) = true;
29938fd1498Szrj     }
30038fd1498Szrj   else if (HAVE_COMDAT_GROUP)
30138fd1498Szrj     {
30238fd1498Szrj       /* At eof, defer creation of mangling aliases temporarily.  */
30338fd1498Szrj       bool save_defer_mangling_aliases = defer_mangling_aliases;
30438fd1498Szrj       defer_mangling_aliases = true;
30538fd1498Szrj       tree comdat_group = cdtor_comdat_group (fns[1], fns[0]);
30638fd1498Szrj       defer_mangling_aliases = save_defer_mangling_aliases;
30738fd1498Szrj       cgraph_node::get_create (fns[0])->set_comdat_group (comdat_group);
30838fd1498Szrj       cgraph_node::get_create (fns[1])->add_to_same_comdat_group
30938fd1498Szrj 	(cgraph_node::get_create (fns[0]));
31038fd1498Szrj       symtab_node::get (fn)->add_to_same_comdat_group
31138fd1498Szrj 	(symtab_node::get (fns[0]));
31238fd1498Szrj       if (fns[2])
31338fd1498Szrj 	/* If *[CD][12]* dtors go into the *[CD]5* comdat group and dtor is
31438fd1498Szrj 	   virtual, it goes into the same comdat group as well.  */
31538fd1498Szrj 	cgraph_node::get_create (fns[2])->add_to_same_comdat_group
31638fd1498Szrj 	  (symtab_node::get (fns[0]));
31738fd1498Szrj       /* Emit them now that the thunks are same comdat group aliases.  */
31838fd1498Szrj       if (!save_defer_mangling_aliases)
31938fd1498Szrj 	generate_mangling_aliases ();
32038fd1498Szrj       TREE_PUBLIC (fn) = false;
32138fd1498Szrj       DECL_EXTERNAL (fn) = false;
32238fd1498Szrj       DECL_INTERFACE_KNOWN (fn) = true;
32338fd1498Szrj       /* function_and_variable_visibility doesn't want !PUBLIC decls to
32438fd1498Szrj 	 have these flags set.  */
32538fd1498Szrj       DECL_WEAK (fn) = false;
32638fd1498Szrj       DECL_COMDAT (fn) = false;
32738fd1498Szrj     }
32838fd1498Szrj 
32938fd1498Szrj   /* Find the vtt_parm, if present.  */
33038fd1498Szrj   for (vtt_parmno = -1, parmno = 0, fn_parm = DECL_ARGUMENTS (fn);
33138fd1498Szrj        fn_parm;
33238fd1498Szrj        ++parmno, fn_parm = TREE_CHAIN (fn_parm))
33338fd1498Szrj     {
33438fd1498Szrj       if (DECL_ARTIFICIAL (fn_parm)
33538fd1498Szrj 	  && DECL_NAME (fn_parm) == vtt_parm_identifier)
33638fd1498Szrj 	{
33738fd1498Szrj 	  /* Compensate for removed in_charge parameter.  */
33838fd1498Szrj 	  vtt_parmno = parmno;
33938fd1498Szrj 	  break;
34038fd1498Szrj 	}
34138fd1498Szrj     }
34238fd1498Szrj 
34338fd1498Szrj   /* Allocate an argument buffer for build_cxx_call().
34438fd1498Szrj      Make sure it is large enough for any of the clones.  */
34538fd1498Szrj   max_parms = 0;
34638fd1498Szrj   FOR_EACH_CLONE (clone, fn)
34738fd1498Szrj     {
34838fd1498Szrj       int length = list_length (DECL_ARGUMENTS (fn));
34938fd1498Szrj       if (length > max_parms)
35038fd1498Szrj         max_parms = length;
35138fd1498Szrj     }
35238fd1498Szrj   args = XALLOCAVEC (tree, max_parms);
35338fd1498Szrj 
35438fd1498Szrj   /* We know that any clones immediately follow FN in TYPE_FIELDS.  */
35538fd1498Szrj   FOR_EACH_CLONE (clone, fn)
35638fd1498Szrj     {
35738fd1498Szrj       tree clone_parm;
35838fd1498Szrj 
35938fd1498Szrj       /* If we've already generated a body for this clone, avoid
36038fd1498Szrj 	 duplicating it.  (Is it possible for a clone-list to grow after we
36138fd1498Szrj 	 first see it?)  */
36238fd1498Szrj       if (DECL_SAVED_TREE (clone) || TREE_ASM_WRITTEN (clone))
36338fd1498Szrj 	continue;
36438fd1498Szrj 
36538fd1498Szrj       /* Start processing the function.  */
36638fd1498Szrj       start_preparsed_function (clone, NULL_TREE, SF_PRE_PARSED);
36738fd1498Szrj 
36838fd1498Szrj       if (clone == fns[2])
36938fd1498Szrj 	{
37038fd1498Szrj 	  for (clone_parm = DECL_ARGUMENTS (clone); clone_parm;
37138fd1498Szrj 	       clone_parm = TREE_CHAIN (clone_parm))
37238fd1498Szrj 	    DECL_ABSTRACT_ORIGIN (clone_parm) = NULL_TREE;
37338fd1498Szrj 	  /* Build the delete destructor by calling complete destructor and
37438fd1498Szrj 	     delete function.  */
37538fd1498Szrj 	  build_delete_destructor_body (clone, fns[1]);
37638fd1498Szrj 	}
37738fd1498Szrj       else
37838fd1498Szrj 	{
37938fd1498Szrj 	  /* Walk parameter lists together, creating parameter list for
38038fd1498Szrj 	     call to original function.  */
38138fd1498Szrj 	  for (parmno = 0,
38238fd1498Szrj 		 fn_parm = DECL_ARGUMENTS (fn),
38338fd1498Szrj 		 fn_parm_typelist = TYPE_ARG_TYPES (TREE_TYPE (fn)),
38438fd1498Szrj 		 clone_parm = DECL_ARGUMENTS (clone);
38538fd1498Szrj 	       fn_parm;
38638fd1498Szrj 	       ++parmno,
38738fd1498Szrj 		 fn_parm = TREE_CHAIN (fn_parm))
38838fd1498Szrj 	    {
38938fd1498Szrj 	      if (parmno == vtt_parmno && ! DECL_HAS_VTT_PARM_P (clone))
39038fd1498Szrj 		{
39138fd1498Szrj 		  gcc_assert (fn_parm_typelist);
39238fd1498Szrj 		  /* Clobber argument with formal parameter type.  */
39338fd1498Szrj 		  args[parmno]
39438fd1498Szrj 		    = convert (TREE_VALUE (fn_parm_typelist),
39538fd1498Szrj 			       null_pointer_node);
39638fd1498Szrj 		}
39738fd1498Szrj 	      else if (parmno == 1 && DECL_HAS_IN_CHARGE_PARM_P (fn))
39838fd1498Szrj 		{
39938fd1498Szrj 		  tree in_charge
40038fd1498Szrj 		    = copy_node (in_charge_arg_for_name (DECL_NAME (clone)));
40138fd1498Szrj 		  args[parmno] = in_charge;
40238fd1498Szrj 		}
40338fd1498Szrj 	      /* Map other parameters to their equivalents in the cloned
40438fd1498Szrj 		 function.  */
40538fd1498Szrj 	      else
40638fd1498Szrj 		{
40738fd1498Szrj 		  gcc_assert (clone_parm);
40838fd1498Szrj 		  DECL_ABSTRACT_ORIGIN (clone_parm) = NULL;
40938fd1498Szrj 		  args[parmno] = clone_parm;
410*58e805e6Szrj 		  /* Clear TREE_ADDRESSABLE on thunk arguments.  */
411*58e805e6Szrj 		  TREE_ADDRESSABLE (clone_parm) = 0;
41238fd1498Szrj 		  clone_parm = TREE_CHAIN (clone_parm);
41338fd1498Szrj 		}
41438fd1498Szrj 	      if (fn_parm_typelist)
41538fd1498Szrj 		fn_parm_typelist = TREE_CHAIN (fn_parm_typelist);
41638fd1498Szrj 	    }
41738fd1498Szrj 
41838fd1498Szrj 	  /* We built this list backwards; fix now.  */
41938fd1498Szrj 	  mark_used (fn);
42038fd1498Szrj 	  call = build_cxx_call (fn, parmno, args, tf_warning_or_error);
42138fd1498Szrj 	  /* Arguments passed to the thunk by invisible reference should
42238fd1498Szrj 	     be transmitted to the callee unchanged.  Do not create a
42338fd1498Szrj 	     temporary and invoke the copy constructor.  The thunking
42438fd1498Szrj 	     transformation must not introduce any constructor calls.  */
42538fd1498Szrj 	  CALL_FROM_THUNK_P (call) = 1;
42638fd1498Szrj 	  block = make_node (BLOCK);
42738fd1498Szrj 	  if (targetm.cxx.cdtor_returns_this ())
42838fd1498Szrj 	    {
42938fd1498Szrj 	      clone_result = DECL_RESULT (clone);
43038fd1498Szrj 	      modify = build2 (MODIFY_EXPR, TREE_TYPE (clone_result),
43138fd1498Szrj 			       clone_result, call);
43238fd1498Szrj 	      modify = build1 (RETURN_EXPR, void_type_node, modify);
43338fd1498Szrj 	      add_stmt (modify);
43438fd1498Szrj 	    }
43538fd1498Szrj 	  else
43638fd1498Szrj 	    {
43738fd1498Szrj 	      add_stmt (call);
43838fd1498Szrj 	    }
43938fd1498Szrj 	  bind = c_build_bind_expr (DECL_SOURCE_LOCATION (clone),
44038fd1498Szrj 				    block, cur_stmt_list);
44138fd1498Szrj 	  DECL_SAVED_TREE (clone) = push_stmt_list ();
44238fd1498Szrj 	  add_stmt (bind);
44338fd1498Szrj 	}
44438fd1498Szrj 
44538fd1498Szrj       DECL_ABSTRACT_ORIGIN (clone) = NULL;
44638fd1498Szrj       expand_or_defer_fn (finish_function (/*inline_p=*/false));
44738fd1498Szrj     }
44838fd1498Szrj   return 1;
44938fd1498Szrj }
45038fd1498Szrj 
45138fd1498Szrj /* FN is a function that has a complete body.  Clone the body as
45238fd1498Szrj    necessary.  Returns nonzero if there's no longer any need to
45338fd1498Szrj    process the main body.  */
45438fd1498Szrj 
45538fd1498Szrj bool
maybe_clone_body(tree fn)45638fd1498Szrj maybe_clone_body (tree fn)
45738fd1498Szrj {
45838fd1498Szrj   tree comdat_group = NULL_TREE;
45938fd1498Szrj   tree clone;
46038fd1498Szrj   tree fns[3];
46138fd1498Szrj   bool first = true;
46238fd1498Szrj   int idx;
46338fd1498Szrj   bool need_alias = false;
46438fd1498Szrj 
46538fd1498Szrj   /* We only clone constructors and destructors.  */
46638fd1498Szrj   if (!DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (fn)
46738fd1498Szrj       && !DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (fn))
46838fd1498Szrj     return 0;
46938fd1498Szrj 
47038fd1498Szrj   populate_clone_array (fn, fns);
47138fd1498Szrj 
47238fd1498Szrj   /* Remember if we can't have multiple clones for some reason.  We need to
47338fd1498Szrj      check this before we remap local static initializers in clone_body.  */
47438fd1498Szrj   if (!tree_versionable_function_p (fn))
47538fd1498Szrj     need_alias = true;
47638fd1498Szrj 
47738fd1498Szrj   /* We know that any clones immediately follow FN in the TYPE_FIELDS
47838fd1498Szrj      list.  */
47938fd1498Szrj   push_to_top_level ();
48038fd1498Szrj   for (idx = 0; idx < 3; idx++)
48138fd1498Szrj     {
48238fd1498Szrj       tree parm;
48338fd1498Szrj       tree clone_parm;
48438fd1498Szrj 
48538fd1498Szrj       clone = fns[idx];
48638fd1498Szrj       if (!clone)
48738fd1498Szrj 	continue;
48838fd1498Szrj 
48938fd1498Szrj       /* Update CLONE's source position information to match FN's.  */
49038fd1498Szrj       DECL_SOURCE_LOCATION (clone) = DECL_SOURCE_LOCATION (fn);
49138fd1498Szrj       DECL_DECLARED_INLINE_P (clone) = DECL_DECLARED_INLINE_P (fn);
49238fd1498Szrj       DECL_DECLARED_CONSTEXPR_P (clone) = DECL_DECLARED_CONSTEXPR_P (fn);
49338fd1498Szrj       DECL_COMDAT (clone) = DECL_COMDAT (fn);
49438fd1498Szrj       DECL_WEAK (clone) = DECL_WEAK (fn);
49538fd1498Szrj 
49638fd1498Szrj       /* We don't copy the comdat group from fn to clone because the assembler
49738fd1498Szrj 	 name of fn was corrupted by write_mangled_name by adding *INTERNAL*
49838fd1498Szrj 	 to it. By doing so, it also corrupted the comdat group. */
49938fd1498Szrj       if (DECL_ONE_ONLY (fn))
50038fd1498Szrj 	cgraph_node::get_create (clone)->set_comdat_group (cxx_comdat_group (clone));
50138fd1498Szrj       DECL_USE_TEMPLATE (clone) = DECL_USE_TEMPLATE (fn);
50238fd1498Szrj       DECL_EXTERNAL (clone) = DECL_EXTERNAL (fn);
50338fd1498Szrj       DECL_INTERFACE_KNOWN (clone) = DECL_INTERFACE_KNOWN (fn);
50438fd1498Szrj       DECL_NOT_REALLY_EXTERN (clone) = DECL_NOT_REALLY_EXTERN (fn);
50538fd1498Szrj       TREE_PUBLIC (clone) = TREE_PUBLIC (fn);
50638fd1498Szrj       DECL_VISIBILITY (clone) = DECL_VISIBILITY (fn);
50738fd1498Szrj       DECL_VISIBILITY_SPECIFIED (clone) = DECL_VISIBILITY_SPECIFIED (fn);
50838fd1498Szrj       DECL_DLLIMPORT_P (clone) = DECL_DLLIMPORT_P (fn);
50938fd1498Szrj       DECL_ATTRIBUTES (clone) = copy_list (DECL_ATTRIBUTES (fn));
51038fd1498Szrj       DECL_DISREGARD_INLINE_LIMITS (clone) = DECL_DISREGARD_INLINE_LIMITS (fn);
51138fd1498Szrj       set_decl_section_name (clone, DECL_SECTION_NAME (fn));
51238fd1498Szrj 
51338fd1498Szrj       /* Adjust the parameter names and locations.  */
51438fd1498Szrj       parm = DECL_ARGUMENTS (fn);
51538fd1498Szrj       clone_parm = DECL_ARGUMENTS (clone);
51638fd1498Szrj       /* Update the `this' parameter, which is always first.  */
51738fd1498Szrj       update_cloned_parm (parm, clone_parm, first);
51838fd1498Szrj       parm = DECL_CHAIN (parm);
51938fd1498Szrj       clone_parm = DECL_CHAIN (clone_parm);
52038fd1498Szrj       if (DECL_HAS_IN_CHARGE_PARM_P (fn))
52138fd1498Szrj 	parm = DECL_CHAIN (parm);
52238fd1498Szrj       if (DECL_HAS_VTT_PARM_P (fn))
52338fd1498Szrj 	parm = DECL_CHAIN (parm);
52438fd1498Szrj       if (DECL_HAS_VTT_PARM_P (clone))
52538fd1498Szrj 	clone_parm = DECL_CHAIN (clone_parm);
52638fd1498Szrj       for (; parm && clone_parm;
52738fd1498Szrj 	   parm = DECL_CHAIN (parm), clone_parm = DECL_CHAIN (clone_parm))
52838fd1498Szrj 	/* Update this parameter.  */
52938fd1498Szrj 	update_cloned_parm (parm, clone_parm, first);
53038fd1498Szrj     }
53138fd1498Szrj 
53238fd1498Szrj   bool can_alias = can_alias_cdtor (fn);
53338fd1498Szrj 
53438fd1498Szrj   /* If we decide to turn clones into thunks, they will branch to fn.
53538fd1498Szrj      Must have original function available to call.  */
53638fd1498Szrj   if (!can_alias && maybe_thunk_body (fn, need_alias))
53738fd1498Szrj     {
53838fd1498Szrj       pop_from_top_level ();
53938fd1498Szrj       /* We still need to emit the original function.  */
54038fd1498Szrj       return 0;
54138fd1498Szrj     }
54238fd1498Szrj 
54338fd1498Szrj   /* Emit the DWARF1 abstract instance.  */
54438fd1498Szrj   (*debug_hooks->deferred_inline_function) (fn);
54538fd1498Szrj 
54638fd1498Szrj   /* We know that any clones immediately follow FN in the TYPE_FIELDS. */
54738fd1498Szrj   for (idx = 0; idx < 3; idx++)
54838fd1498Szrj     {
54938fd1498Szrj       tree parm;
55038fd1498Szrj       tree clone_parm;
55138fd1498Szrj       int parmno;
55238fd1498Szrj       hash_map<tree, tree> *decl_map;
55338fd1498Szrj       bool alias = false;
55438fd1498Szrj 
55538fd1498Szrj       clone = fns[idx];
55638fd1498Szrj       if (!clone)
55738fd1498Szrj 	continue;
55838fd1498Szrj 
55938fd1498Szrj       /* Start processing the function.  */
56038fd1498Szrj       start_preparsed_function (clone, NULL_TREE, SF_PRE_PARSED);
56138fd1498Szrj 
56238fd1498Szrj       /* Tell cgraph if both ctors or both dtors are known to have
56338fd1498Szrj 	 the same body.  */
56438fd1498Szrj       if (can_alias
56538fd1498Szrj 	  && fns[0]
56638fd1498Szrj 	  && idx == 1
56738fd1498Szrj 	  && cgraph_node::get_create (fns[0])->create_same_body_alias
56838fd1498Szrj 	       (clone, fns[0]))
56938fd1498Szrj 	{
57038fd1498Szrj 	  alias = true;
57138fd1498Szrj 	  if (DECL_ONE_ONLY (fns[0]))
57238fd1498Szrj 	    {
57338fd1498Szrj 	      /* For comdat base and complete cdtors put them
57438fd1498Szrj 		 into the same, *[CD]5* comdat group instead of
57538fd1498Szrj 		 *[CD][12]*.  */
57638fd1498Szrj 	      comdat_group = cdtor_comdat_group (fns[1], fns[0]);
57738fd1498Szrj 	      cgraph_node::get_create (fns[0])->set_comdat_group (comdat_group);
57838fd1498Szrj 	      if (symtab_node::get (clone)->same_comdat_group)
57938fd1498Szrj 		symtab_node::get (clone)->remove_from_same_comdat_group ();
58038fd1498Szrj 	      symtab_node::get (clone)->add_to_same_comdat_group
58138fd1498Szrj 		(symtab_node::get (fns[0]));
58238fd1498Szrj 	    }
58338fd1498Szrj 	}
58438fd1498Szrj 
58538fd1498Szrj       /* Build the delete destructor by calling complete destructor
58638fd1498Szrj          and delete function.  */
58738fd1498Szrj       if (idx == 2)
58838fd1498Szrj 	{
58938fd1498Szrj 	  build_delete_destructor_body (clone, fns[1]);
59038fd1498Szrj 	  /* If *[CD][12]* dtors go into the *[CD]5* comdat group and dtor is
59138fd1498Szrj 	     virtual, it goes into the same comdat group as well.  */
59238fd1498Szrj 	  if (comdat_group)
59338fd1498Szrj 	    cgraph_node::get_create (clone)->add_to_same_comdat_group
59438fd1498Szrj 	      (symtab_node::get (fns[0]));
59538fd1498Szrj 	}
59638fd1498Szrj       else if (alias)
59738fd1498Szrj 	/* No need to populate body.  */ ;
59838fd1498Szrj       else
59938fd1498Szrj 	{
60038fd1498Szrj 	  /* If we can't have multiple copies of FN (say, because there's a
60138fd1498Szrj 	     static local initialized with the address of a label), we need
60238fd1498Szrj 	     to use an alias for the complete variant.  */
60338fd1498Szrj 	  if (idx == 1 && need_alias)
60438fd1498Szrj 	    {
60538fd1498Szrj 	      if (DECL_STRUCT_FUNCTION (fn)->cannot_be_copied_set)
60638fd1498Szrj 		sorry (DECL_STRUCT_FUNCTION (fn)->cannot_be_copied_reason, fn);
60738fd1498Szrj 	      else
60838fd1498Szrj 		sorry ("making multiple clones of %qD", fn);
60938fd1498Szrj 	    }
61038fd1498Szrj 
61138fd1498Szrj           /* Remap the parameters.  */
61238fd1498Szrj           decl_map = new hash_map<tree, tree>;
61338fd1498Szrj           for (parmno = 0,
61438fd1498Szrj                 parm = DECL_ARGUMENTS (fn),
61538fd1498Szrj                 clone_parm = DECL_ARGUMENTS (clone);
61638fd1498Szrj               parm;
61738fd1498Szrj               ++parmno,
61838fd1498Szrj                 parm = DECL_CHAIN (parm))
61938fd1498Szrj             {
62038fd1498Szrj               /* Map the in-charge parameter to an appropriate constant.  */
62138fd1498Szrj               if (DECL_HAS_IN_CHARGE_PARM_P (fn) && parmno == 1)
62238fd1498Szrj                 {
62338fd1498Szrj                   tree in_charge;
62438fd1498Szrj                   in_charge = in_charge_arg_for_name (DECL_NAME (clone));
62538fd1498Szrj                   decl_map->put (parm, in_charge);
62638fd1498Szrj                 }
62738fd1498Szrj               else if (DECL_ARTIFICIAL (parm)
62838fd1498Szrj                        && DECL_NAME (parm) == vtt_parm_identifier)
62938fd1498Szrj                 {
63038fd1498Szrj                   /* For a subobject constructor or destructor, the next
63138fd1498Szrj                      argument is the VTT parameter.  Remap the VTT_PARM
63238fd1498Szrj                      from the CLONE to this parameter.  */
63338fd1498Szrj                   if (DECL_HAS_VTT_PARM_P (clone))
63438fd1498Szrj                     {
63538fd1498Szrj                       DECL_ABSTRACT_ORIGIN (clone_parm) = parm;
63638fd1498Szrj                       decl_map->put (parm, clone_parm);
63738fd1498Szrj                       clone_parm = DECL_CHAIN (clone_parm);
63838fd1498Szrj                     }
63938fd1498Szrj                   /* Otherwise, map the VTT parameter to `NULL'.  */
64038fd1498Szrj                   else
64138fd1498Szrj 		    {
64238fd1498Szrj 		      tree t
64338fd1498Szrj 			= fold_convert (TREE_TYPE (parm), null_pointer_node);
64438fd1498Szrj 		      decl_map->put (parm, t);
64538fd1498Szrj 		    }
64638fd1498Szrj                 }
64738fd1498Szrj               /* Map other parameters to their equivalents in the cloned
64838fd1498Szrj                  function.  */
64938fd1498Szrj               else
65038fd1498Szrj                 {
65138fd1498Szrj 		  tree replacement;
65238fd1498Szrj 		  if (clone_parm)
65338fd1498Szrj 		    {
65438fd1498Szrj 		      replacement = clone_parm;
65538fd1498Szrj 		      clone_parm = DECL_CHAIN (clone_parm);
65638fd1498Szrj 		    }
65738fd1498Szrj 		  else
65838fd1498Szrj 		    {
65938fd1498Szrj 		      /* Inheriting ctors can omit parameters from the base
66038fd1498Szrj 			 clone.  Replace them with null lvalues.  */
66138fd1498Szrj 		      tree reftype = build_reference_type (TREE_TYPE (parm));
66238fd1498Szrj 		      replacement = fold_convert (reftype, null_pointer_node);
66338fd1498Szrj 		      replacement = convert_from_reference (replacement);
66438fd1498Szrj 		    }
66538fd1498Szrj                   decl_map->put (parm, replacement);
66638fd1498Szrj                 }
66738fd1498Szrj             }
66838fd1498Szrj 
66938fd1498Szrj           if (targetm.cxx.cdtor_returns_this ())
67038fd1498Szrj             {
67138fd1498Szrj               parm = DECL_RESULT (fn);
67238fd1498Szrj               clone_parm = DECL_RESULT (clone);
67338fd1498Szrj               decl_map->put (parm, clone_parm);
67438fd1498Szrj             }
67538fd1498Szrj 
67638fd1498Szrj           /* Clone the body.  */
67738fd1498Szrj           clone_body (clone, fn, decl_map);
67838fd1498Szrj 
67938fd1498Szrj           /* Clean up.  */
68038fd1498Szrj           delete decl_map;
68138fd1498Szrj         }
68238fd1498Szrj 
68338fd1498Szrj       /* The clone can throw iff the original function can throw.  */
68438fd1498Szrj       cp_function_chain->can_throw = !TREE_NOTHROW (fn);
68538fd1498Szrj 
68638fd1498Szrj       /* Now, expand this function into RTL, if appropriate.  */
68738fd1498Szrj       finish_function (/*inline_p=*/false);
68838fd1498Szrj       BLOCK_ABSTRACT_ORIGIN (DECL_INITIAL (clone)) = DECL_INITIAL (fn);
68938fd1498Szrj       if (alias)
69038fd1498Szrj 	{
69138fd1498Szrj 	  if (expand_or_defer_fn_1 (clone))
69238fd1498Szrj 	    emit_associated_thunks (clone);
69338fd1498Szrj 	  /* We didn't generate a body, so remove the empty one.  */
69438fd1498Szrj 	  DECL_SAVED_TREE (clone) = NULL_TREE;
69538fd1498Szrj 	}
69638fd1498Szrj       else
69738fd1498Szrj 	expand_or_defer_fn (clone);
69838fd1498Szrj       first = false;
69938fd1498Szrj     }
70038fd1498Szrj   pop_from_top_level ();
70138fd1498Szrj 
70238fd1498Szrj   /* We don't need to process the original function any further.  */
70338fd1498Szrj   return 1;
70438fd1498Szrj }
705