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