Branch data Line data Source code
1 : : /* Perform optimizations on tree structure.
2 : : Copyright (C) 1998-2024 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 : 21601974 : update_cloned_parm (tree parm, tree cloned_parm, bool first)
44 : : {
45 : 21601974 : DECL_ABSTRACT_ORIGIN (cloned_parm) = parm;
46 : :
47 : : /* We may have taken its address. */
48 : 21601974 : TREE_ADDRESSABLE (cloned_parm) = TREE_ADDRESSABLE (parm);
49 : :
50 : 21601974 : DECL_BY_REFERENCE (cloned_parm) = DECL_BY_REFERENCE (parm);
51 : :
52 : : /* The definition might have different constness. */
53 : 21601974 : TREE_READONLY (cloned_parm) = TREE_READONLY (parm);
54 : :
55 : 21601974 : TREE_USED (cloned_parm) = !first || TREE_USED (parm);
56 : :
57 : : /* The name may have changed from the declaration. */
58 : 21601974 : DECL_NAME (cloned_parm) = DECL_NAME (parm);
59 : 21601974 : DECL_SOURCE_LOCATION (cloned_parm) = DECL_SOURCE_LOCATION (parm);
60 : 21601974 : TREE_TYPE (cloned_parm) = TREE_TYPE (parm);
61 : :
62 : 21601974 : DECL_NOT_GIMPLE_REG_P (cloned_parm) = DECL_NOT_GIMPLE_REG_P (parm);
63 : 21601974 : }
64 : :
65 : : /* Like copy_decl_no_change, but handle DECL_OMP_PRIVATIZED_MEMBER
66 : : properly. */
67 : :
68 : : static tree
69 : 1220031 : cxx_copy_decl (tree decl, copy_body_data *id)
70 : : {
71 : 1220031 : tree copy = copy_decl_no_change (decl, id);
72 : 1220031 : if (VAR_P (decl)
73 : 1152873 : && DECL_HAS_VALUE_EXPR_P (decl)
74 : 45 : && DECL_ARTIFICIAL (decl)
75 : 45 : && DECL_LANG_SPECIFIC (decl)
76 : 1220065 : && 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 : 1220031 : 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 : 6378927 : clone_body (tree clone, tree fn, void *arg_map)
91 : : {
92 : 6378927 : copy_body_data id;
93 : 6378927 : 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 : 6378927 : memset (&id, 0, sizeof (id));
98 : 6378927 : id.src_fn = fn;
99 : 6378927 : id.dst_fn = clone;
100 : 6378927 : id.src_cfun = DECL_STRUCT_FUNCTION (fn);
101 : 6378927 : id.decl_map = static_cast<hash_map<tree, tree> *> (arg_map);
102 : :
103 : 6378927 : id.copy_decl = cxx_copy_decl;
104 : 6378927 : id.transform_call_graph_edges = CB_CGE_DUPLICATE;
105 : 6378927 : id.transform_new_cfg = true;
106 : 6378927 : id.transform_return_to_modify = false;
107 : :
108 : : /* We're not inside any EH region. */
109 : 6378927 : id.eh_lp_nr = 0;
110 : :
111 : 6378927 : stmts = DECL_SAVED_TREE (fn);
112 : 6378927 : 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 : 6378927 : if (DECL_NAME (clone) == base_dtor_identifier
118 : 6378927 : || DECL_NAME (clone) == base_ctor_identifier)
119 : : {
120 : 6186526 : unsigned ix;
121 : 6186526 : tree decl;
122 : :
123 : 6186722 : FOR_EACH_LOCAL_DECL (DECL_STRUCT_FUNCTION (fn), ix, decl)
124 : 120 : walk_tree (&DECL_INITIAL (decl), copy_tree_body_r, &id, NULL);
125 : : }
126 : :
127 : 6378927 : append_to_statement_list_force (stmts, &DECL_SAVED_TREE (clone));
128 : 6378927 : }
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 : 244090 : build_delete_destructor_body (tree delete_dtor, tree complete_dtor)
135 : : {
136 : 244090 : tree parm = DECL_ARGUMENTS (delete_dtor);
137 : 244090 : tree virtual_size = cxx_sizeof (current_class_type);
138 : :
139 : : /* Call the delete function. */
140 : 244090 : 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 : 244090 : tree op = get_callee_fndecl (call_delete);
148 : 244090 : 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 : 244089 : gcc_assert (complete_dtor);
157 : 244089 : 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 : 244089 : 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 : 244090 : maybe_return_this ();
168 : 244090 : }
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 : 5752610 : cdtor_comdat_group (tree complete, tree base)
176 : : {
177 : 5752610 : tree complete_name = DECL_ASSEMBLER_NAME (complete);
178 : 5752610 : tree base_name = DECL_ASSEMBLER_NAME (base);
179 : 5752610 : char *grp_name;
180 : 5752610 : const char *p, *q;
181 : 5752610 : bool diff_seen = false;
182 : 5752610 : size_t idx;
183 : 5752610 : gcc_assert (IDENTIFIER_LENGTH (complete_name)
184 : : == IDENTIFIER_LENGTH (base_name));
185 : 5752610 : grp_name = XALLOCAVEC (char, IDENTIFIER_LENGTH (complete_name) + 1);
186 : 5752610 : p = IDENTIFIER_POINTER (complete_name);
187 : 5752610 : q = IDENTIFIER_POINTER (base_name);
188 : 335358895 : for (idx = 0; idx < IDENTIFIER_LENGTH (complete_name); idx++)
189 : 329606285 : if (p[idx] == q[idx])
190 : 323853675 : grp_name[idx] = p[idx];
191 : : else
192 : : {
193 : 5752610 : 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 : 5752610 : grp_name[idx] = '5';
200 : 5752610 : diff_seen = true;
201 : : }
202 : 5752610 : grp_name[idx] = '\0';
203 : 5752610 : gcc_assert (diff_seen);
204 : 5752610 : 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 : 6186882 : can_alias_cdtor (tree fn)
212 : : {
213 : : /* If aliases aren't supported by the assembler, fail. */
214 : 6186882 : if (!TARGET_SUPPORTS_ALIASES)
215 : : return false;
216 : :
217 : : /* We can't use an alias if there are virtual bases. */
218 : 6186882 : if (CLASSTYPE_VBASECLASSES (DECL_CONTEXT (fn)))
219 : : return false;
220 : 6168197 : 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 : 6168197 : return (DECL_INTERFACE_KNOWN (fn)
224 : 6168197 : && (SUPPORTS_ONE_ONLY || !DECL_WEAK (fn))
225 : 6168197 : && (!DECL_ONE_ONLY (fn)
226 : 5750215 : || (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 : 6187220 : populate_clone_array (tree fn, tree *fns)
234 : : {
235 : 6187220 : tree clone;
236 : :
237 : 6187220 : fns[0] = NULL_TREE;
238 : 6187220 : fns[1] = NULL_TREE;
239 : 6187220 : fns[2] = NULL_TREE;
240 : :
241 : 18805760 : FOR_EACH_CLONE (clone, fn)
242 : 12618540 : if (DECL_NAME (clone) == complete_dtor_identifier
243 : 12618540 : || DECL_NAME (clone) == complete_ctor_identifier)
244 : 6187200 : fns[1] = clone;
245 : 6431340 : else if (DECL_NAME (clone) == base_dtor_identifier
246 : 6431340 : || DECL_NAME (clone) == base_ctor_identifier)
247 : 6187200 : fns[0] = clone;
248 : 244140 : else if (DECL_NAME (clone) == deleting_dtor_identifier)
249 : 244140 : fns[2] = clone;
250 : : else
251 : 0 : gcc_unreachable ();
252 : 6187220 : }
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 : 192749 : maybe_thunk_body (tree fn, bool force)
262 : : {
263 : 192749 : tree bind, block, call, clone, clone_result, fn_parm, fn_parm_typelist;
264 : 192749 : tree last_arg, modify, *args;
265 : 192749 : int parmno, vtt_parmno, max_parms;
266 : 192749 : tree fns[3];
267 : :
268 : 192749 : 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 : 1001 : fn_parm;
331 : 664 : ++parmno, fn_parm = TREE_CHAIN (fn_parm))
332 : : {
333 : 983 : if (DECL_ARTIFICIAL (fn_parm)
334 : 983 : && 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 : 2658 : fn_parm;
385 : 1984 : ++parmno,
386 : 1984 : fn_parm = TREE_CHAIN (fn_parm))
387 : : {
388 : 1984 : 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 : 1665 : 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 : 1027 : gcc_assert (clone_parm);
407 : 1027 : DECL_ABSTRACT_ORIGIN (clone_parm) = NULL;
408 : 1027 : args[parmno] = clone_parm;
409 : : /* Clear TREE_ADDRESSABLE on thunk arguments. */
410 : 1027 : TREE_ADDRESSABLE (clone_parm) = 0;
411 : 1027 : clone_parm = TREE_CHAIN (clone_parm);
412 : : }
413 : 1984 : if (fn_parm_typelist)
414 : 1984 : 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 : 12834419 : clone_attrs (tree attrs)
455 : : {
456 : 12834419 : tree new_attrs = NULL_TREE;
457 : 12834419 : tree *p = &new_attrs;
458 : :
459 : 13739070 : for (tree a = attrs; a; a = TREE_CHAIN (a))
460 : : {
461 : 904651 : tree aname = get_attribute_name (a);
462 : 904651 : if (is_attribute_namespace_p ("", a)
463 : 904651 : && (is_attribute_p ("alias", aname)
464 : 904651 : || is_attribute_p ("ifunc", aname)))
465 : 0 : continue;
466 : 904651 : *p = copy_node (a);
467 : 904651 : p = &TREE_CHAIN (*p);
468 : : }
469 : 12834419 : *p = NULL_TREE;
470 : 12834419 : 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 : 50560670 : maybe_clone_body (tree fn)
479 : : {
480 : 50560670 : tree comdat_group = NULL_TREE;
481 : 50560670 : tree clone;
482 : 50560670 : tree fns[3];
483 : 50560670 : bool first = true;
484 : 50560670 : int idx;
485 : 50560670 : bool need_alias = false;
486 : :
487 : : /* We only clone constructors and destructors. */
488 : 50560670 : if (!DECL_MAYBE_IN_CHARGE_CDTOR_P (fn))
489 : : return 0;
490 : :
491 : 6186882 : 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 : 6186882 : if (!tree_versionable_function_p (fn))
496 : 45 : need_alias = true;
497 : :
498 : : /* We know that any clones immediately follow FN in the TYPE_FIELDS
499 : : list. */
500 : 6186882 : push_to_top_level ();
501 : 24747528 : for (idx = 0; idx < 3; idx++)
502 : : {
503 : 18560646 : tree parm;
504 : 18560646 : tree clone_parm;
505 : :
506 : 18560646 : clone = fns[idx];
507 : 18560646 : if (!clone)
508 : 5942830 : continue;
509 : :
510 : : /* Update CLONE's source position information to match FN's. */
511 : 12617816 : DECL_SOURCE_LOCATION (clone) = DECL_SOURCE_LOCATION (fn);
512 : 12617816 : DECL_DECLARED_INLINE_P (clone) = DECL_DECLARED_INLINE_P (fn);
513 : 12617816 : DECL_DECLARED_CONSTEXPR_P (clone) = DECL_DECLARED_CONSTEXPR_P (fn);
514 : 12617816 : DECL_COMDAT (clone) = DECL_COMDAT (fn);
515 : 12617816 : 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 : 12617816 : if (DECL_ONE_ONLY (fn))
521 : 11742999 : cgraph_node::get_create (clone)->set_comdat_group (cxx_comdat_group (clone));
522 : 12617816 : DECL_USE_TEMPLATE (clone) = DECL_USE_TEMPLATE (fn);
523 : 12617816 : DECL_EXTERNAL (clone) = DECL_EXTERNAL (fn);
524 : 12617816 : DECL_INTERFACE_KNOWN (clone) = DECL_INTERFACE_KNOWN (fn);
525 : 12617816 : DECL_NOT_REALLY_EXTERN (clone) = DECL_NOT_REALLY_EXTERN (fn);
526 : 12617816 : TREE_PUBLIC (clone) = TREE_PUBLIC (fn);
527 : 12617816 : DECL_VISIBILITY (clone) = DECL_VISIBILITY (fn);
528 : 12617816 : DECL_VISIBILITY_SPECIFIED (clone) = DECL_VISIBILITY_SPECIFIED (fn);
529 : 12617816 : DECL_DLLIMPORT_P (clone) = DECL_DLLIMPORT_P (fn);
530 : 12617816 : DECL_ATTRIBUTES (clone) = clone_attrs (DECL_ATTRIBUTES (fn));
531 : 12617816 : DECL_DISREGARD_INLINE_LIMITS (clone) = DECL_DISREGARD_INLINE_LIMITS (fn);
532 : 12617816 : set_decl_section_name (clone, fn);
533 : :
534 : : /* Adjust the parameter names and locations. */
535 : 12617816 : parm = DECL_ARGUMENTS (fn);
536 : 12617816 : clone_parm = DECL_ARGUMENTS (clone);
537 : : /* Update the `this' parameter, which is always first. */
538 : 12617816 : update_cloned_parm (parm, clone_parm, first);
539 : 12617816 : parm = DECL_CHAIN (parm);
540 : 12617816 : clone_parm = DECL_CHAIN (clone_parm);
541 : 12617816 : if (DECL_HAS_IN_CHARGE_PARM_P (fn))
542 : 3018862 : parm = DECL_CHAIN (parm);
543 : 12617816 : if (DECL_HAS_VTT_PARM_P (fn))
544 : 44466 : parm = DECL_CHAIN (parm);
545 : 12617816 : if (DECL_HAS_VTT_PARM_P (clone))
546 : 18674 : clone_parm = DECL_CHAIN (clone_parm);
547 : 21601974 : for (; parm && clone_parm;
548 : 8984158 : parm = DECL_CHAIN (parm), clone_parm = DECL_CHAIN (clone_parm))
549 : : /* Update this parameter. */
550 : 8984158 : update_cloned_parm (parm, clone_parm, first);
551 : : }
552 : :
553 : 6186882 : 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 : 6186882 : 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 : 6186545 : (*debug_hooks->deferred_inline_function) (fn);
566 : :
567 : : /* We know that any clones immediately follow FN in the TYPE_FIELDS. */
568 : 24746180 : for (idx = 0; idx < 3; idx++)
569 : : {
570 : 18559635 : tree parm;
571 : 18559635 : tree clone_parm;
572 : 18559635 : int parmno;
573 : 18559635 : hash_map<tree, tree> *decl_map;
574 : 18559635 : bool alias = false;
575 : :
576 : 18559635 : clone = fns[idx];
577 : 18559635 : if (!clone)
578 : 5942543 : continue;
579 : :
580 : : /* Start processing the function. */
581 : 12617092 : 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 : 12617092 : if (can_alias
586 : 12225086 : && fns[0]
587 : 12225086 : && idx == 1
588 : 24605342 : && cgraph_node::get_create (fns[0])->create_same_body_alias
589 : 5994125 : (clone, fns[0]))
590 : : {
591 : 5994125 : alias = true;
592 : 5994125 : 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 : 5752330 : comdat_group = cdtor_comdat_group (fns[1], fns[0]);
598 : 5752330 : cgraph_node::get_create (fns[0])->set_comdat_group (comdat_group);
599 : 5752330 : if (symtab_node::get (clone)->same_comdat_group)
600 : 3043314 : symtab_node::get (clone)->remove_from_same_comdat_group ();
601 : 5752330 : symtab_node::get (clone)->add_to_same_comdat_group
602 : 5752330 : (symtab_node::get (fns[0]));
603 : : }
604 : : }
605 : :
606 : : /* Build the delete destructor by calling complete destructor
607 : : and delete function. */
608 : 12617092 : if (idx == 2)
609 : : {
610 : 244040 : 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 : 244040 : if (comdat_group)
614 : 229432 : cgraph_node::get_create (clone)->add_to_same_comdat_group
615 : 229432 : (symtab_node::get (fns[0]));
616 : : }
617 : 12373052 : 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 : 6378927 : 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 : 6378927 : decl_map = new hash_map<tree, tree>;
634 : 6378927 : for (parmno = 0,
635 : 6378927 : parm = DECL_ARGUMENTS (fn),
636 : 6378927 : clone_parm = DECL_ARGUMENTS (clone);
637 : 18823995 : parm;
638 : 12445068 : ++parmno,
639 : 12445068 : parm = DECL_CHAIN (parm))
640 : : {
641 : : /* Map the in-charge parameter to an appropriate constant. */
642 : 12445068 : if (DECL_HAS_IN_CHARGE_PARM_P (fn) && parmno == 1)
643 : : {
644 : 1406474 : tree in_charge;
645 : 1406474 : in_charge = in_charge_arg_for_name (DECL_NAME (clone));
646 : 1406474 : decl_map->put (parm, in_charge);
647 : : }
648 : 11038594 : else if (DECL_ARTIFICIAL (parm)
649 : 11038594 : && 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 : 36710 : if (DECL_HAS_VTT_PARM_P (clone))
655 : : {
656 : 18355 : DECL_ABSTRACT_ORIGIN (clone_parm) = parm;
657 : 18355 : decl_map->put (parm, clone_parm);
658 : 18355 : clone_parm = DECL_CHAIN (clone_parm);
659 : : }
660 : : /* Otherwise, map the VTT parameter to `NULL'. */
661 : : else
662 : : {
663 : 18355 : tree t
664 : 18355 : = fold_convert (TREE_TYPE (parm), null_pointer_node);
665 : 18355 : decl_map->put (parm, t);
666 : : }
667 : : }
668 : : /* Map other parameters to their equivalents in the cloned
669 : : function. */
670 : : else
671 : : {
672 : 11001884 : tree replacement;
673 : 11001884 : if (clone_parm)
674 : : {
675 : 11001848 : replacement = clone_parm;
676 : 11001848 : 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 : 11001884 : decl_map->put (parm, replacement);
687 : : }
688 : : }
689 : :
690 : 6378927 : 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 : 6378927 : clone_body (clone, fn, decl_map);
699 : :
700 : : /* Clean up. */
701 : 6378927 : delete decl_map;
702 : : }
703 : :
704 : : /* The clone can throw iff the original function can throw. */
705 : 12617092 : cp_function_chain->can_throw = !TREE_NOTHROW (fn);
706 : :
707 : : /* Now, expand this function into RTL, if appropriate. */
708 : 12617092 : finish_function (/*inline_p=*/false);
709 : 12617092 : BLOCK_ABSTRACT_ORIGIN (DECL_INITIAL (clone)) = DECL_INITIAL (fn);
710 : 12617092 : if (alias)
711 : : {
712 : 5994125 : if (expand_or_defer_fn_1 (clone))
713 : 5993337 : emit_associated_thunks (clone);
714 : : /* We didn't generate a body, so remove the empty one. */
715 : 5994125 : DECL_SAVED_TREE (clone) = NULL_TREE;
716 : : }
717 : : else
718 : 6622967 : expand_or_defer_fn (clone);
719 : 12617092 : first = false;
720 : : }
721 : 6186545 : pop_from_top_level ();
722 : :
723 : : /* We don't need to process the original function any further. */
724 : 6186545 : return 1;
725 : : }
|