annotate gcc/cp/optimize.c @ 158:494b0b89df80 default tip

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