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