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