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 : 22333197 : update_cloned_parm (tree parm, tree cloned_parm, bool first)
44 : : {
45 : 22333197 : DECL_ABSTRACT_ORIGIN (cloned_parm) = parm;
46 : :
47 : : /* We may have taken its address. */
48 : 22333197 : TREE_ADDRESSABLE (cloned_parm) = TREE_ADDRESSABLE (parm);
49 : :
50 : 22333197 : DECL_BY_REFERENCE (cloned_parm) = DECL_BY_REFERENCE (parm);
51 : :
52 : : /* The definition might have different constness. */
53 : 22333197 : TREE_READONLY (cloned_parm) = TREE_READONLY (parm);
54 : :
55 : 22333197 : TREE_USED (cloned_parm) = !first || TREE_USED (parm);
56 : :
57 : : /* The name may have changed from the declaration. */
58 : 22333197 : DECL_NAME (cloned_parm) = DECL_NAME (parm);
59 : 22333197 : DECL_SOURCE_LOCATION (cloned_parm) = DECL_SOURCE_LOCATION (parm);
60 : 22333197 : TREE_TYPE (cloned_parm) = TREE_TYPE (parm);
61 : :
62 : 22333197 : DECL_NOT_GIMPLE_REG_P (cloned_parm) = DECL_NOT_GIMPLE_REG_P (parm);
63 : 22333197 : }
64 : :
65 : : /* Like copy_decl_no_change, but handle DECL_OMP_PRIVATIZED_MEMBER
66 : : properly. */
67 : :
68 : : static tree
69 : 1209956 : cxx_copy_decl (tree decl, copy_body_data *id)
70 : : {
71 : 1209956 : tree copy = copy_decl_no_change (decl, id);
72 : 1209956 : if (VAR_P (decl)
73 : 1141989 : && DECL_HAS_VALUE_EXPR_P (decl)
74 : 36 : && DECL_ARTIFICIAL (decl)
75 : 36 : && DECL_LANG_SPECIFIC (decl)
76 : 1209982 : && DECL_OMP_PRIVATIZED_MEMBER (decl))
77 : : {
78 : 26 : tree expr = DECL_VALUE_EXPR (copy);
79 : 26 : walk_tree (&expr, copy_tree_body_r, id, NULL);
80 : 26 : SET_DECL_VALUE_EXPR (copy, expr);
81 : : }
82 : 1209956 : 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 : 6422523 : clone_body (tree clone, tree fn, void *arg_map)
91 : : {
92 : 6422523 : copy_body_data id;
93 : 6422523 : 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 : 6422523 : memset (&id, 0, sizeof (id));
98 : 6422523 : id.src_fn = fn;
99 : 6422523 : id.dst_fn = clone;
100 : 6422523 : id.src_cfun = DECL_STRUCT_FUNCTION (fn);
101 : 6422523 : id.decl_map = static_cast<hash_map<tree, tree> *> (arg_map);
102 : :
103 : 6422523 : id.copy_decl = cxx_copy_decl;
104 : 6422523 : id.transform_call_graph_edges = CB_CGE_DUPLICATE;
105 : 6422523 : id.transform_new_cfg = true;
106 : 6422523 : id.transform_return_to_modify = false;
107 : :
108 : : /* We're not inside any EH region. */
109 : 6422523 : id.eh_lp_nr = 0;
110 : :
111 : 6422523 : stmts = DECL_SAVED_TREE (fn);
112 : 6422523 : 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 : 6422523 : if (DECL_NAME (clone) == base_dtor_identifier
118 : 6422523 : || DECL_NAME (clone) == base_ctor_identifier)
119 : : {
120 : 6393605 : unsigned ix;
121 : 6393605 : tree decl;
122 : :
123 : 6393813 : FOR_EACH_LOCAL_DECL (DECL_STRUCT_FUNCTION (fn), ix, decl)
124 : 130 : walk_tree (&DECL_INITIAL (decl), copy_tree_body_r, &id, NULL);
125 : : }
126 : :
127 : 6422523 : append_to_statement_list_force (stmts, &DECL_SAVED_TREE (clone));
128 : 6422523 : }
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 : 251459 : build_delete_destructor_body (tree delete_dtor, tree complete_dtor)
135 : : {
136 : 251459 : tree parm = DECL_ARGUMENTS (delete_dtor);
137 : 251459 : tree virtual_size = cxx_sizeof (current_class_type);
138 : :
139 : : /* Call the delete function. */
140 : 251459 : 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 : 251459 : tree op = get_callee_fndecl (call_delete);
148 : 251459 : 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 : 251456 : gcc_assert (complete_dtor);
157 : 251456 : 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 : 251456 : 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 : 251459 : maybe_return_this ();
168 : 251459 : }
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 : 6118913 : cdtor_comdat_group (tree complete, tree base)
176 : : {
177 : 6118913 : tree complete_name = DECL_ASSEMBLER_NAME (complete);
178 : 6118913 : tree base_name = DECL_ASSEMBLER_NAME (base);
179 : 6118913 : char *grp_name;
180 : 6118913 : const char *p, *q;
181 : 6118913 : bool diff_seen = false;
182 : 6118913 : size_t idx;
183 : 6118913 : gcc_assert (IDENTIFIER_LENGTH (complete_name)
184 : : == IDENTIFIER_LENGTH (base_name));
185 : 6118913 : grp_name = XALLOCAVEC (char, IDENTIFIER_LENGTH (complete_name) + 1);
186 : 6118913 : p = IDENTIFIER_POINTER (complete_name);
187 : 6118913 : q = IDENTIFIER_POINTER (base_name);
188 : 358816907 : for (idx = 0; idx < IDENTIFIER_LENGTH (complete_name); idx++)
189 : 352697994 : if (p[idx] == q[idx])
190 : 346579081 : grp_name[idx] = p[idx];
191 : : else
192 : : {
193 : 6118913 : 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 : 6118913 : grp_name[idx] = '5';
200 : 6118913 : diff_seen = true;
201 : : }
202 : 6118913 : grp_name[idx] = '\0';
203 : 6118913 : gcc_assert (diff_seen);
204 : 6118913 : 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 : 6393932 : can_alias_cdtor (tree fn)
212 : : {
213 : : /* If aliases aren't supported by the assembler, fail. */
214 : 6393932 : if (!TARGET_SUPPORTS_ALIASES)
215 : : return false;
216 : :
217 : : /* We can't use an alias if there are virtual bases. */
218 : 6393932 : if (CLASSTYPE_VBASECLASSES (DECL_CONTEXT (fn)))
219 : : return false;
220 : 6374998 : 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 : 6374998 : return (DECL_WEAK (fn) ? (HAVE_COMDAT_GROUP && DECL_ONE_ONLY (fn))
224 : 248859 : : (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 : 6394244 : populate_clone_array (tree fn, tree *fns)
232 : : {
233 : 6394244 : tree clone;
234 : :
235 : 6394244 : fns[0] = NULL_TREE;
236 : 6394244 : fns[1] = NULL_TREE;
237 : 6394244 : fns[2] = NULL_TREE;
238 : :
239 : 19434206 : FOR_EACH_CLONE (clone, fn)
240 : 13039962 : if (DECL_NAME (clone) == complete_dtor_identifier
241 : 13039962 : || DECL_NAME (clone) == complete_ctor_identifier)
242 : 6394227 : fns[1] = clone;
243 : 6645735 : else if (DECL_NAME (clone) == base_dtor_identifier
244 : 6645735 : || DECL_NAME (clone) == base_ctor_identifier)
245 : 6394227 : fns[0] = clone;
246 : 251508 : else if (DECL_NAME (clone) == deleting_dtor_identifier)
247 : 251508 : fns[2] = clone;
248 : : else
249 : 0 : gcc_unreachable ();
250 : 6394244 : }
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 : 29239 : maybe_thunk_body (tree fn, bool force)
260 : : {
261 : 29239 : tree bind, block, call, clone, clone_result, fn_parm, fn_parm_typelist;
262 : 29239 : tree last_arg, modify, *args;
263 : 29239 : int parmno, vtt_parmno, max_parms;
264 : 29239 : tree fns[3];
265 : :
266 : 29239 : if (!force && !flag_declone_ctor_dtor)
267 : : return 0;
268 : :
269 : : /* If function accepts variable arguments, give up. */
270 : 312 : last_arg = tree_last (TYPE_ARG_TYPES (TREE_TYPE (fn)));
271 : 312 : 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 : 312 : populate_clone_array (fn, fns);
281 : :
282 : : /* Can happen during error recovery (c++/71464). */
283 : 312 : if (!fns[0] || !fns[1])
284 : : return 0;
285 : :
286 : : /* Don't use thunks if the base clone omits inherited parameters. */
287 : 311 : if (ctor_omit_inherited_parms (fns[0]))
288 : : return 0;
289 : :
290 : 311 : DECL_ABSTRACT_P (fn) = false;
291 : 311 : if (!DECL_WEAK (fn))
292 : : {
293 : 34 : TREE_PUBLIC (fn) = false;
294 : 34 : DECL_EXTERNAL (fn) = false;
295 : 34 : DECL_INTERFACE_KNOWN (fn) = true;
296 : : }
297 : 277 : else if (HAVE_COMDAT_GROUP)
298 : : {
299 : : /* At eof, defer creation of mangling aliases temporarily. */
300 : 277 : bool save_defer_mangling_aliases = defer_mangling_aliases;
301 : 277 : defer_mangling_aliases = true;
302 : 277 : tree comdat_group = cdtor_comdat_group (fns[1], fns[0]);
303 : 277 : defer_mangling_aliases = save_defer_mangling_aliases;
304 : 277 : cgraph_node::get_create (fns[0])->set_comdat_group (comdat_group);
305 : 277 : cgraph_node::get_create (fns[1])->add_to_same_comdat_group
306 : 277 : (cgraph_node::get_create (fns[0]));
307 : 277 : symtab_node::get (fn)->add_to_same_comdat_group
308 : 277 : (symtab_node::get (fns[0]));
309 : 277 : if (fns[2])
310 : : /* If *[CD][12]* dtors go into the *[CD]5* comdat group and dtor is
311 : : virtual, it goes into the same comdat group as well. */
312 : 36 : cgraph_node::get_create (fns[2])->add_to_same_comdat_group
313 : 36 : (symtab_node::get (fns[0]));
314 : : /* Emit them now that the thunks are same comdat group aliases. */
315 : 277 : if (!save_defer_mangling_aliases)
316 : 0 : generate_mangling_aliases ();
317 : 277 : TREE_PUBLIC (fn) = false;
318 : 277 : DECL_EXTERNAL (fn) = false;
319 : 277 : DECL_INTERFACE_KNOWN (fn) = true;
320 : : /* function_and_variable_visibility doesn't want !PUBLIC decls to
321 : : have these flags set. */
322 : 277 : DECL_WEAK (fn) = false;
323 : 277 : DECL_COMDAT (fn) = false;
324 : : }
325 : :
326 : : /* Find the vtt_parm, if present. */
327 : 311 : for (vtt_parmno = -1, parmno = 0, fn_parm = DECL_ARGUMENTS (fn);
328 : 933 : fn_parm;
329 : 622 : ++parmno, fn_parm = TREE_CHAIN (fn_parm))
330 : : {
331 : 933 : if (DECL_ARTIFICIAL (fn_parm)
332 : 933 : && DECL_NAME (fn_parm) == vtt_parm_identifier)
333 : : {
334 : : /* Compensate for removed in_charge parameter. */
335 : : vtt_parmno = parmno;
336 : : break;
337 : : }
338 : : }
339 : :
340 : : /* Allocate an argument buffer for build_cxx_call().
341 : : Make sure it is large enough for any of the clones. */
342 : 311 : max_parms = 0;
343 : 982 : FOR_EACH_CLONE (clone, fn)
344 : : {
345 : 671 : int length = list_length (DECL_ARGUMENTS (fn));
346 : 671 : if (length > max_parms)
347 : : max_parms = length;
348 : : }
349 : 311 : args = XALLOCAVEC (tree, max_parms);
350 : :
351 : : /* We know that any clones immediately follow FN in TYPE_FIELDS. */
352 : 982 : FOR_EACH_CLONE (clone, fn)
353 : : {
354 : 671 : tree clone_parm;
355 : :
356 : : /* If we've already generated a body for this clone, avoid
357 : : duplicating it. (Is it possible for a clone-list to grow after we
358 : : first see it?) */
359 : 671 : if (DECL_SAVED_TREE (clone) || TREE_ASM_WRITTEN (clone))
360 : 0 : continue;
361 : :
362 : : /* Start processing the function. */
363 : 671 : start_preparsed_function (clone, NULL_TREE, SF_PRE_PARSED);
364 : :
365 : 671 : if (clone == fns[2])
366 : : {
367 : 98 : for (clone_parm = DECL_ARGUMENTS (clone); clone_parm;
368 : 49 : clone_parm = TREE_CHAIN (clone_parm))
369 : 49 : DECL_ABSTRACT_ORIGIN (clone_parm) = NULL_TREE;
370 : : /* Build the delete destructor by calling complete destructor and
371 : : delete function. */
372 : 49 : build_delete_destructor_body (clone, fns[1]);
373 : : }
374 : : else
375 : : {
376 : : /* Walk parameter lists together, creating parameter list for
377 : : call to original function. */
378 : 622 : for (parmno = 0,
379 : 622 : fn_parm = DECL_ARGUMENTS (fn),
380 : 622 : fn_parm_typelist = TYPE_ARG_TYPES (TREE_TYPE (fn)),
381 : 622 : clone_parm = DECL_ARGUMENTS (clone);
382 : 2504 : fn_parm;
383 : 1882 : ++parmno,
384 : 1882 : fn_parm = TREE_CHAIN (fn_parm))
385 : : {
386 : 1882 : if (parmno == vtt_parmno && ! DECL_HAS_VTT_PARM_P (clone))
387 : : {
388 : 311 : gcc_assert (fn_parm_typelist);
389 : : /* Clobber argument with formal parameter type. */
390 : 622 : args[parmno]
391 : 311 : = convert (TREE_VALUE (fn_parm_typelist),
392 : : null_pointer_node);
393 : : }
394 : 1571 : else if (parmno == 1 && DECL_HAS_IN_CHARGE_PARM_P (fn))
395 : : {
396 : 622 : tree in_charge
397 : 622 : = copy_node (in_charge_arg_for_name (DECL_NAME (clone)));
398 : 622 : args[parmno] = in_charge;
399 : : }
400 : : /* Map other parameters to their equivalents in the cloned
401 : : function. */
402 : : else
403 : : {
404 : 949 : gcc_assert (clone_parm);
405 : 949 : DECL_ABSTRACT_ORIGIN (clone_parm) = NULL;
406 : 949 : args[parmno] = clone_parm;
407 : : /* Clear TREE_ADDRESSABLE on thunk arguments. */
408 : 949 : TREE_ADDRESSABLE (clone_parm) = 0;
409 : 949 : clone_parm = TREE_CHAIN (clone_parm);
410 : : }
411 : 1882 : if (fn_parm_typelist)
412 : 1882 : fn_parm_typelist = TREE_CHAIN (fn_parm_typelist);
413 : : }
414 : :
415 : : /* We built this list backwards; fix now. */
416 : 622 : mark_used (fn);
417 : 622 : call = build_cxx_call (fn, parmno, args, tf_warning_or_error);
418 : : /* Arguments passed to the thunk by invisible reference should
419 : : be transmitted to the callee unchanged. Do not create a
420 : : temporary and invoke the copy constructor. The thunking
421 : : transformation must not introduce any constructor calls. */
422 : 622 : CALL_FROM_THUNK_P (call) = 1;
423 : 622 : block = make_node (BLOCK);
424 : 622 : if (targetm.cxx.cdtor_returns_this ())
425 : : {
426 : 0 : clone_result = DECL_RESULT (clone);
427 : 0 : modify = build2 (MODIFY_EXPR, TREE_TYPE (clone_result),
428 : : clone_result, call);
429 : 0 : modify = build1 (RETURN_EXPR, void_type_node, modify);
430 : 0 : add_stmt (modify);
431 : : }
432 : : else
433 : : {
434 : 622 : add_stmt (call);
435 : : }
436 : 622 : bind = c_build_bind_expr (DECL_SOURCE_LOCATION (clone),
437 : 622 : block, cur_stmt_list);
438 : 622 : DECL_SAVED_TREE (clone) = push_stmt_list ();
439 : 622 : add_stmt (bind);
440 : : }
441 : :
442 : 671 : DECL_ABSTRACT_ORIGIN (clone) = NULL;
443 : 671 : expand_or_defer_fn (finish_function (/*inline_p=*/false));
444 : : }
445 : : return 1;
446 : : }
447 : :
448 : : /* Copy most attributes from ATTRS, omitting attributes that can really only
449 : : apply to a single decl. */
450 : :
451 : : tree
452 : 13276590 : clone_attrs (tree attrs)
453 : : {
454 : 13276590 : tree new_attrs = NULL_TREE;
455 : 13276590 : tree *p = &new_attrs;
456 : :
457 : 14221431 : for (tree a = attrs; a; a = TREE_CHAIN (a))
458 : : {
459 : 944841 : tree aname = get_attribute_name (a);
460 : 944841 : if (is_attribute_namespace_p ("", a)
461 : 944841 : && (is_attribute_p ("alias", aname)
462 : 944841 : || is_attribute_p ("ifunc", aname)))
463 : 0 : continue;
464 : 944841 : *p = copy_node (a);
465 : 944841 : p = &TREE_CHAIN (*p);
466 : : }
467 : 13276590 : *p = NULL_TREE;
468 : 13276590 : return new_attrs;
469 : : }
470 : :
471 : : /* FN is a function that has a complete body. Clone the body as
472 : : necessary. Returns nonzero if there's no longer any need to
473 : : process the main body. */
474 : :
475 : : bool
476 : 52351838 : maybe_clone_body (tree fn)
477 : : {
478 : 52351838 : tree comdat_group = NULL_TREE;
479 : 52351838 : tree clone;
480 : 52351838 : tree fns[3];
481 : 52351838 : bool first = true;
482 : 52351838 : int idx;
483 : 52351838 : bool need_alias = false;
484 : :
485 : : /* We only clone constructors and destructors. */
486 : 52351838 : if (!DECL_MAYBE_IN_CHARGE_CDTOR_P (fn))
487 : : return 0;
488 : :
489 : 6393932 : populate_clone_array (fn, fns);
490 : :
491 : : /* Remember if we can't have multiple clones for some reason. We need to
492 : : check this before we remap local static initializers in clone_body. */
493 : 6393932 : if (!tree_versionable_function_p (fn))
494 : 44 : need_alias = true;
495 : :
496 : : /* We know that any clones immediately follow FN in the TYPE_FIELDS
497 : : list. */
498 : 6393932 : push_to_top_level ();
499 : 25575728 : for (idx = 0; idx < 3; idx++)
500 : : {
501 : 19181796 : tree parm;
502 : 19181796 : tree clone_parm;
503 : :
504 : 19181796 : clone = fns[idx];
505 : 19181796 : if (!clone)
506 : 6142505 : continue;
507 : :
508 : : /* Update CLONE's source position information to match FN's. */
509 : 13039291 : DECL_SOURCE_LOCATION (clone) = DECL_SOURCE_LOCATION (fn);
510 : 13039291 : DECL_DECLARED_INLINE_P (clone) = DECL_DECLARED_INLINE_P (fn);
511 : 13039291 : DECL_DECLARED_CONSTEXPR_P (clone) = DECL_DECLARED_CONSTEXPR_P (fn);
512 : 13039291 : DECL_COMDAT (clone) = DECL_COMDAT (fn);
513 : 13039291 : DECL_WEAK (clone) = DECL_WEAK (fn);
514 : :
515 : : /* We don't copy the comdat group from fn to clone because the assembler
516 : : name of fn was corrupted by write_mangled_name by adding *INTERNAL*
517 : : to it. By doing so, it also corrupted the comdat group. */
518 : 13039291 : if (DECL_ONE_ONLY (fn))
519 : 12484552 : cgraph_node::get_create (clone)->set_comdat_group (cxx_comdat_group (clone));
520 : 13039291 : DECL_USE_TEMPLATE (clone) = DECL_USE_TEMPLATE (fn);
521 : 13039291 : DECL_EXTERNAL (clone) = DECL_EXTERNAL (fn);
522 : 13039291 : DECL_INTERFACE_KNOWN (clone) = DECL_INTERFACE_KNOWN (fn);
523 : 13039291 : DECL_NOT_REALLY_EXTERN (clone) = DECL_NOT_REALLY_EXTERN (fn);
524 : 13039291 : TREE_PUBLIC (clone) = TREE_PUBLIC (fn);
525 : 13039291 : DECL_VISIBILITY (clone) = DECL_VISIBILITY (fn);
526 : 13039291 : DECL_VISIBILITY_SPECIFIED (clone) = DECL_VISIBILITY_SPECIFIED (fn);
527 : 13039291 : DECL_DLLIMPORT_P (clone) = DECL_DLLIMPORT_P (fn);
528 : 13039291 : DECL_ATTRIBUTES (clone) = clone_attrs (DECL_ATTRIBUTES (fn));
529 : 13039291 : DECL_DISREGARD_INLINE_LIMITS (clone) = DECL_DISREGARD_INLINE_LIMITS (fn);
530 : 13039291 : set_decl_section_name (clone, fn);
531 : :
532 : : /* Adjust the parameter names and locations. */
533 : 13039291 : parm = DECL_ARGUMENTS (fn);
534 : 13039291 : clone_parm = DECL_ARGUMENTS (clone);
535 : : /* Update the `this' parameter, which is always first. */
536 : 13039291 : update_cloned_parm (parm, clone_parm, first);
537 : 13039291 : parm = DECL_CHAIN (parm);
538 : 13039291 : clone_parm = DECL_CHAIN (clone_parm);
539 : 13039291 : if (DECL_HAS_IN_CHARGE_PARM_P (fn))
540 : 45358 : parm = DECL_CHAIN (parm);
541 : 13039291 : if (DECL_HAS_VTT_PARM_P (fn))
542 : 45358 : parm = DECL_CHAIN (parm);
543 : 13039291 : if (DECL_HAS_VTT_PARM_P (clone))
544 : 18924 : clone_parm = DECL_CHAIN (clone_parm);
545 : 22333197 : for (; parm && clone_parm;
546 : 9293906 : parm = DECL_CHAIN (parm), clone_parm = DECL_CHAIN (clone_parm))
547 : : /* Update this parameter. */
548 : 9293906 : update_cloned_parm (parm, clone_parm, first);
549 : : }
550 : :
551 : 6393932 : bool can_alias = can_alias_cdtor (fn);
552 : :
553 : : /* If we decide to turn clones into thunks, they will branch to fn.
554 : : Must have original function available to call. */
555 : 6393932 : if (!can_alias && maybe_thunk_body (fn, need_alias))
556 : : {
557 : 311 : pop_from_top_level ();
558 : : /* We still need to emit the original function. */
559 : 311 : return 0;
560 : : }
561 : :
562 : : /* Emit the DWARF1 abstract instance. */
563 : 6393621 : (*debug_hooks->deferred_inline_function) (fn);
564 : :
565 : : /* We know that any clones immediately follow FN in the TYPE_FIELDS. */
566 : 25574484 : for (idx = 0; idx < 3; idx++)
567 : : {
568 : 19180863 : tree parm;
569 : 19180863 : tree clone_parm;
570 : 19180863 : int parmno;
571 : 19180863 : hash_map<tree, tree> *decl_map;
572 : 19180863 : bool alias = false;
573 : :
574 : 19180863 : clone = fns[idx];
575 : 19180863 : if (!clone)
576 : 6142243 : continue;
577 : :
578 : : /* Start processing the function. */
579 : 13038620 : start_preparsed_function (clone, NULL_TREE, SF_PRE_PARSED);
580 : :
581 : : /* Tell cgraph if both ctors or both dtors are known to have
582 : : the same body. */
583 : 13038620 : if (can_alias
584 : 12972972 : && fns[0]
585 : 12972972 : && idx == 1
586 : 25767994 : && cgraph_node::get_create (fns[0])->create_same_body_alias
587 : 6364687 : (clone, fns[0]))
588 : : {
589 : 6364687 : alias = true;
590 : 6364687 : if (DECL_ONE_ONLY (fns[0]))
591 : : {
592 : : /* For comdat base and complete cdtors put them
593 : : into the same, *[CD]5* comdat group instead of
594 : : *[CD][12]*. */
595 : 6118636 : comdat_group = cdtor_comdat_group (fns[1], fns[0]);
596 : 6118636 : cgraph_node::get_create (fns[0])->set_comdat_group (comdat_group);
597 : 6118636 : if (symtab_node::get (clone)->same_comdat_group)
598 : 3156612 : symtab_node::get (clone)->remove_from_same_comdat_group ();
599 : 6118636 : symtab_node::get (clone)->add_to_same_comdat_group
600 : 6118636 : (symtab_node::get (fns[0]));
601 : : }
602 : : }
603 : :
604 : : /* Build the delete destructor by calling complete destructor
605 : : and delete function. */
606 : 13038620 : if (idx == 2)
607 : : {
608 : 251410 : build_delete_destructor_body (clone, fns[1]);
609 : : /* If *[CD][12]* dtors go into the *[CD]5* comdat group and dtor is
610 : : virtual, it goes into the same comdat group as well. */
611 : 251410 : if (comdat_group)
612 : 235889 : cgraph_node::get_create (clone)->add_to_same_comdat_group
613 : 235889 : (symtab_node::get (fns[0]));
614 : : }
615 : 12787210 : else if (alias)
616 : : /* No need to populate body. */ ;
617 : : else
618 : : {
619 : : /* If we can't have multiple copies of FN (say, because there's a
620 : : static local initialized with the address of a label), we need
621 : : to use an alias for the complete variant. */
622 : 6422523 : if (idx == 1 && need_alias)
623 : : {
624 : 0 : if (DECL_STRUCT_FUNCTION (fn)->cannot_be_copied_set)
625 : 0 : sorry (DECL_STRUCT_FUNCTION (fn)->cannot_be_copied_reason, fn);
626 : : else
627 : 0 : sorry ("making multiple clones of %qD", fn);
628 : : }
629 : :
630 : : /* Remap the parameters. */
631 : 6422523 : decl_map = new hash_map<tree, tree>;
632 : 6422523 : for (parmno = 0,
633 : 6422523 : parm = DECL_ARGUMENTS (fn),
634 : 6422523 : clone_parm = DECL_ARGUMENTS (clone);
635 : 17577561 : parm;
636 : 11155038 : ++parmno,
637 : 11155038 : parm = DECL_CHAIN (parm))
638 : : {
639 : : /* Map the in-charge parameter to an appropriate constant. */
640 : 11155038 : if (DECL_HAS_IN_CHARGE_PARM_P (fn) && parmno == 1)
641 : : {
642 : 37226 : tree in_charge;
643 : 37226 : in_charge = in_charge_arg_for_name (DECL_NAME (clone));
644 : 37226 : decl_map->put (parm, in_charge);
645 : : }
646 : 11117812 : else if (DECL_ARTIFICIAL (parm)
647 : 11117812 : && DECL_NAME (parm) == vtt_parm_identifier)
648 : : {
649 : : /* For a subobject constructor or destructor, the next
650 : : argument is the VTT parameter. Remap the VTT_PARM
651 : : from the CLONE to this parameter. */
652 : 37226 : if (DECL_HAS_VTT_PARM_P (clone))
653 : : {
654 : 18613 : DECL_ABSTRACT_ORIGIN (clone_parm) = parm;
655 : 18613 : decl_map->put (parm, clone_parm);
656 : 18613 : clone_parm = DECL_CHAIN (clone_parm);
657 : : }
658 : : /* Otherwise, map the VTT parameter to `NULL'. */
659 : : else
660 : : {
661 : 18613 : tree t
662 : 18613 : = fold_convert (TREE_TYPE (parm), null_pointer_node);
663 : 18613 : decl_map->put (parm, t);
664 : : }
665 : : }
666 : : /* Map other parameters to their equivalents in the cloned
667 : : function. */
668 : : else
669 : : {
670 : 11080586 : tree replacement;
671 : 11080586 : if (clone_parm)
672 : : {
673 : 11080550 : replacement = clone_parm;
674 : 11080550 : clone_parm = DECL_CHAIN (clone_parm);
675 : : }
676 : : else
677 : : {
678 : : /* Inheriting ctors can omit parameters from the base
679 : : clone. Replace them with null lvalues. */
680 : 36 : tree reftype = build_reference_type (TREE_TYPE (parm));
681 : 36 : replacement = fold_convert (reftype, null_pointer_node);
682 : 36 : replacement = convert_from_reference (replacement);
683 : : }
684 : 11080586 : decl_map->put (parm, replacement);
685 : : }
686 : : }
687 : :
688 : 6422523 : if (targetm.cxx.cdtor_returns_this ())
689 : : {
690 : 0 : parm = DECL_RESULT (fn);
691 : 0 : clone_parm = DECL_RESULT (clone);
692 : 0 : decl_map->put (parm, clone_parm);
693 : : }
694 : :
695 : : /* Clone the body. */
696 : 6422523 : clone_body (clone, fn, decl_map);
697 : :
698 : : /* Clean up. */
699 : 6422523 : delete decl_map;
700 : : }
701 : :
702 : : /* The clone can throw iff the original function can throw. */
703 : 13038620 : cp_function_chain->can_throw = !TREE_NOTHROW (fn);
704 : :
705 : : /* Now, expand this function into RTL, if appropriate. */
706 : 13038620 : finish_function (/*inline_p=*/false);
707 : 13038620 : BLOCK_ABSTRACT_ORIGIN (DECL_INITIAL (clone)) = DECL_INITIAL (fn);
708 : 13038620 : if (alias)
709 : : {
710 : 6364687 : if (expand_or_defer_fn_1 (clone))
711 : 6363892 : emit_associated_thunks (clone);
712 : : /* We didn't generate a body, so remove the empty one. */
713 : 6364687 : DECL_SAVED_TREE (clone) = void_node;
714 : : }
715 : : else
716 : 6673933 : expand_or_defer_fn (clone);
717 : 13038620 : first = false;
718 : : }
719 : 6393621 : pop_from_top_level ();
720 : :
721 : : /* We don't need to process the original function any further. */
722 : 6393621 : return 1;
723 : : }
|