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