1 /* Perform optimizations on tree structure.
2 Copyright (C) 1998-2024 Free Software Foundation, Inc.
3 Written by Mark Michell (mark@codesourcery.com).
5 This file is part of GCC.
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)
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.
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/>. */
23 #include "coretypes.h"
26 #include "stringpool.h"
29 #include "tree-inline.h"
30 #include "tree-iterator.h"
35 static void update_cloned_parm (tree
, tree
, bool);
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. */
43 update_cloned_parm (tree parm
, tree cloned_parm
, bool first
)
45 DECL_ABSTRACT_ORIGIN (cloned_parm
) = parm
;
47 /* We may have taken its address. */
48 TREE_ADDRESSABLE (cloned_parm
) = TREE_ADDRESSABLE (parm
);
50 DECL_BY_REFERENCE (cloned_parm
) = DECL_BY_REFERENCE (parm
);
52 /* The definition might have different constness. */
53 TREE_READONLY (cloned_parm
) = TREE_READONLY (parm
);
55 TREE_USED (cloned_parm
) = !first
|| TREE_USED (parm
);
57 /* The name may have changed from the declaration. */
58 DECL_NAME (cloned_parm
) = DECL_NAME (parm
);
59 DECL_SOURCE_LOCATION (cloned_parm
) = DECL_SOURCE_LOCATION (parm
);
60 TREE_TYPE (cloned_parm
) = TREE_TYPE (parm
);
62 DECL_NOT_GIMPLE_REG_P (cloned_parm
) = DECL_NOT_GIMPLE_REG_P (parm
);
65 /* Like copy_decl_no_change, but handle DECL_OMP_PRIVATIZED_MEMBER
69 cxx_copy_decl (tree decl
, copy_body_data
*id
)
71 tree copy
= copy_decl_no_change (decl
, id
);
73 && DECL_HAS_VALUE_EXPR_P (decl
)
74 && DECL_ARTIFICIAL (decl
)
75 && DECL_LANG_SPECIFIC (decl
)
76 && DECL_OMP_PRIVATIZED_MEMBER (decl
))
78 tree expr
= DECL_VALUE_EXPR (copy
);
79 walk_tree (&expr
, copy_tree_body_r
, id
, NULL
);
80 SET_DECL_VALUE_EXPR (copy
, expr
);
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. */
90 clone_body (tree clone
, tree fn
, void *arg_map
)
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 memset (&id
, 0, sizeof (id
));
100 id
.src_cfun
= DECL_STRUCT_FUNCTION (fn
);
101 id
.decl_map
= static_cast<hash_map
<tree
, tree
> *> (arg_map
);
103 id
.copy_decl
= cxx_copy_decl
;
104 id
.transform_call_graph_edges
= CB_CGE_DUPLICATE
;
105 id
.transform_new_cfg
= true;
106 id
.transform_return_to_modify
= false;
108 /* We're not inside any EH region. */
111 stmts
= DECL_SAVED_TREE (fn
);
112 walk_tree (&stmts
, copy_tree_body_r
, &id
, NULL
);
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 if (DECL_NAME (clone
) == base_dtor_identifier
118 || DECL_NAME (clone
) == base_ctor_identifier
)
123 FOR_EACH_LOCAL_DECL (DECL_STRUCT_FUNCTION (fn
), ix
, decl
)
124 walk_tree (&DECL_INITIAL (decl
), copy_tree_body_r
, &id
, NULL
);
127 append_to_statement_list_force (stmts
, &DECL_SAVED_TREE (clone
));
130 /* DELETE_DTOR is a delete destructor whose body will be built.
131 COMPLETE_DTOR is the corresponding complete destructor. */
134 build_delete_destructor_body (tree delete_dtor
, tree complete_dtor
)
136 tree parm
= DECL_ARGUMENTS (delete_dtor
);
137 tree virtual_size
= cxx_sizeof (current_class_type
);
139 /* Call the delete function. */
140 tree call_delete
= build_op_delete_call (DELETE_EXPR
, current_class_ptr
,
143 /*placement=*/NULL_TREE
,
144 /*alloc_fn=*/NULL_TREE
,
145 tf_warning_or_error
);
147 tree op
= get_callee_fndecl (call_delete
);
148 if (op
&& DECL_P (op
) && destroying_delete_p (op
))
150 /* The destroying delete will handle calling complete_dtor. */
151 add_stmt (call_delete
);
155 /* Call the corresponding complete destructor. */
156 gcc_assert (complete_dtor
);
157 tree call_dtor
= build_cxx_call (complete_dtor
, 1, &parm
,
158 tf_warning_or_error
);
160 /* Operator delete must be called, whether or not the dtor throws. */
161 add_stmt (build2 (TRY_FINALLY_EXPR
, void_type_node
,
162 call_dtor
, call_delete
));
165 /* Return the address of the object.
166 ??? How is it useful to return an invalid address? */
167 maybe_return_this ();
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. */
175 cdtor_comdat_group (tree complete
, tree base
)
177 tree complete_name
= DECL_ASSEMBLER_NAME (complete
);
178 tree base_name
= DECL_ASSEMBLER_NAME (base
);
181 bool diff_seen
= false;
183 gcc_assert (IDENTIFIER_LENGTH (complete_name
)
184 == IDENTIFIER_LENGTH (base_name
));
185 grp_name
= XALLOCAVEC (char, IDENTIFIER_LENGTH (complete_name
) + 1);
186 p
= IDENTIFIER_POINTER (complete_name
);
187 q
= IDENTIFIER_POINTER (base_name
);
188 for (idx
= 0; idx
< IDENTIFIER_LENGTH (complete_name
); idx
++)
189 if (p
[idx
] == q
[idx
])
190 grp_name
[idx
] = p
[idx
];
193 gcc_assert (!diff_seen
195 && (p
[idx
- 1] == 'C' || p
[idx
- 1] == 'D'
196 || p
[idx
- 1] == 'I')
202 grp_name
[idx
] = '\0';
203 gcc_assert (diff_seen
);
204 return get_identifier (grp_name
);
207 /* Returns true iff we can make the base and complete [cd]tor aliases of
208 the same symbol rather than separate functions. */
211 can_alias_cdtor (tree fn
)
213 /* If aliases aren't supported by the assembler, fail. */
214 if (!TARGET_SUPPORTS_ALIASES
)
217 /* We can't use an alias if there are virtual bases. */
218 if (CLASSTYPE_VBASECLASSES (DECL_CONTEXT (fn
)))
220 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 return (DECL_INTERFACE_KNOWN (fn
)
224 && (SUPPORTS_ONE_ONLY
|| !DECL_WEAK (fn
))
225 && (!DECL_ONE_ONLY (fn
)
226 || (HAVE_COMDAT_GROUP
&& DECL_WEAK (fn
))));
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. */
233 populate_clone_array (tree fn
, tree
*fns
)
241 FOR_EACH_CLONE (clone
, fn
)
242 if (DECL_NAME (clone
) == complete_dtor_identifier
243 || DECL_NAME (clone
) == complete_ctor_identifier
)
245 else if (DECL_NAME (clone
) == base_dtor_identifier
246 || DECL_NAME (clone
) == base_ctor_identifier
)
248 else if (DECL_NAME (clone
) == deleting_dtor_identifier
)
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. */
261 maybe_thunk_body (tree fn
, bool force
)
263 tree bind
, block
, call
, clone
, clone_result
, fn_parm
, fn_parm_typelist
;
264 tree last_arg
, modify
, *args
;
265 int parmno
, vtt_parmno
, max_parms
;
268 if (!force
&& !flag_declone_ctor_dtor
)
271 /* If function accepts variable arguments, give up. */
272 last_arg
= tree_last (TYPE_ARG_TYPES (TREE_TYPE (fn
)));
273 if (last_arg
!= void_list_node
)
276 /* If we got this far, we've decided to turn the clones into thunks. */
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). */
282 populate_clone_array (fn
, fns
);
284 /* Can happen during error recovery (c++/71464). */
285 if (!fns
[0] || !fns
[1])
288 /* Don't use thunks if the base clone omits inherited parameters. */
289 if (ctor_omit_inherited_parms (fns
[0]))
292 DECL_ABSTRACT_P (fn
) = false;
295 TREE_PUBLIC (fn
) = false;
296 DECL_EXTERNAL (fn
) = false;
297 DECL_INTERFACE_KNOWN (fn
) = true;
299 else if (HAVE_COMDAT_GROUP
)
301 /* At eof, defer creation of mangling aliases temporarily. */
302 bool save_defer_mangling_aliases
= defer_mangling_aliases
;
303 defer_mangling_aliases
= true;
304 tree comdat_group
= cdtor_comdat_group (fns
[1], fns
[0]);
305 defer_mangling_aliases
= save_defer_mangling_aliases
;
306 cgraph_node::get_create (fns
[0])->set_comdat_group (comdat_group
);
307 cgraph_node::get_create (fns
[1])->add_to_same_comdat_group
308 (cgraph_node::get_create (fns
[0]));
309 symtab_node::get (fn
)->add_to_same_comdat_group
310 (symtab_node::get (fns
[0]));
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 cgraph_node::get_create (fns
[2])->add_to_same_comdat_group
315 (symtab_node::get (fns
[0]));
316 /* Emit them now that the thunks are same comdat group aliases. */
317 if (!save_defer_mangling_aliases
)
318 generate_mangling_aliases ();
319 TREE_PUBLIC (fn
) = false;
320 DECL_EXTERNAL (fn
) = false;
321 DECL_INTERFACE_KNOWN (fn
) = true;
322 /* function_and_variable_visibility doesn't want !PUBLIC decls to
323 have these flags set. */
324 DECL_WEAK (fn
) = false;
325 DECL_COMDAT (fn
) = false;
328 /* Find the vtt_parm, if present. */
329 for (vtt_parmno
= -1, parmno
= 0, fn_parm
= DECL_ARGUMENTS (fn
);
331 ++parmno
, fn_parm
= TREE_CHAIN (fn_parm
))
333 if (DECL_ARTIFICIAL (fn_parm
)
334 && DECL_NAME (fn_parm
) == vtt_parm_identifier
)
336 /* Compensate for removed in_charge parameter. */
342 /* Allocate an argument buffer for build_cxx_call().
343 Make sure it is large enough for any of the clones. */
345 FOR_EACH_CLONE (clone
, fn
)
347 int length
= list_length (DECL_ARGUMENTS (fn
));
348 if (length
> max_parms
)
351 args
= XALLOCAVEC (tree
, max_parms
);
353 /* We know that any clones immediately follow FN in TYPE_FIELDS. */
354 FOR_EACH_CLONE (clone
, fn
)
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
361 if (DECL_SAVED_TREE (clone
) || TREE_ASM_WRITTEN (clone
))
364 /* Start processing the function. */
365 start_preparsed_function (clone
, NULL_TREE
, SF_PRE_PARSED
);
369 for (clone_parm
= DECL_ARGUMENTS (clone
); clone_parm
;
370 clone_parm
= TREE_CHAIN (clone_parm
))
371 DECL_ABSTRACT_ORIGIN (clone_parm
) = NULL_TREE
;
372 /* Build the delete destructor by calling complete destructor and
374 build_delete_destructor_body (clone
, fns
[1]);
378 /* Walk parameter lists together, creating parameter list for
379 call to original function. */
381 fn_parm
= DECL_ARGUMENTS (fn
),
382 fn_parm_typelist
= TYPE_ARG_TYPES (TREE_TYPE (fn
)),
383 clone_parm
= DECL_ARGUMENTS (clone
);
386 fn_parm
= TREE_CHAIN (fn_parm
))
388 if (parmno
== vtt_parmno
&& ! DECL_HAS_VTT_PARM_P (clone
))
390 gcc_assert (fn_parm_typelist
);
391 /* Clobber argument with formal parameter type. */
393 = convert (TREE_VALUE (fn_parm_typelist
),
396 else if (parmno
== 1 && DECL_HAS_IN_CHARGE_PARM_P (fn
))
399 = copy_node (in_charge_arg_for_name (DECL_NAME (clone
)));
400 args
[parmno
] = in_charge
;
402 /* Map other parameters to their equivalents in the cloned
406 gcc_assert (clone_parm
);
407 DECL_ABSTRACT_ORIGIN (clone_parm
) = NULL
;
408 args
[parmno
] = clone_parm
;
409 /* Clear TREE_ADDRESSABLE on thunk arguments. */
410 TREE_ADDRESSABLE (clone_parm
) = 0;
411 clone_parm
= TREE_CHAIN (clone_parm
);
413 if (fn_parm_typelist
)
414 fn_parm_typelist
= TREE_CHAIN (fn_parm_typelist
);
417 /* We built this list backwards; fix now. */
419 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 CALL_FROM_THUNK_P (call
) = 1;
425 block
= make_node (BLOCK
);
426 if (targetm
.cxx
.cdtor_returns_this ())
428 clone_result
= DECL_RESULT (clone
);
429 modify
= build2 (MODIFY_EXPR
, TREE_TYPE (clone_result
),
431 modify
= build1 (RETURN_EXPR
, void_type_node
, modify
);
438 bind
= c_build_bind_expr (DECL_SOURCE_LOCATION (clone
),
439 block
, cur_stmt_list
);
440 DECL_SAVED_TREE (clone
) = push_stmt_list ();
444 DECL_ABSTRACT_ORIGIN (clone
) = NULL
;
445 expand_or_defer_fn (finish_function (/*inline_p=*/false));
450 /* Copy most attributes from ATTRS, omitting attributes that can really only
451 apply to a single decl. */
454 clone_attrs (tree attrs
)
456 tree new_attrs
= NULL_TREE
;
457 tree
*p
= &new_attrs
;
459 for (tree a
= attrs
; a
; a
= TREE_CHAIN (a
))
461 tree aname
= get_attribute_name (a
);
462 if (is_attribute_namespace_p ("", a
)
463 && (is_attribute_p ("alias", aname
)
464 || is_attribute_p ("ifunc", aname
)))
467 p
= &TREE_CHAIN (*p
);
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. */
478 maybe_clone_body (tree fn
)
480 tree comdat_group
= NULL_TREE
;
485 bool need_alias
= false;
487 /* We only clone constructors and destructors. */
488 if (!DECL_MAYBE_IN_CHARGE_CDTOR_P (fn
))
491 populate_clone_array (fn
, fns
);
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 if (!tree_versionable_function_p (fn
))
498 /* We know that any clones immediately follow FN in the TYPE_FIELDS
500 push_to_top_level ();
501 for (idx
= 0; idx
< 3; idx
++)
510 /* Update CLONE's source position information to match FN's. */
511 DECL_SOURCE_LOCATION (clone
) = DECL_SOURCE_LOCATION (fn
);
512 DECL_DECLARED_INLINE_P (clone
) = DECL_DECLARED_INLINE_P (fn
);
513 DECL_DECLARED_CONSTEXPR_P (clone
) = DECL_DECLARED_CONSTEXPR_P (fn
);
514 DECL_COMDAT (clone
) = DECL_COMDAT (fn
);
515 DECL_WEAK (clone
) = DECL_WEAK (fn
);
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 if (DECL_ONE_ONLY (fn
))
521 cgraph_node::get_create (clone
)->set_comdat_group (cxx_comdat_group (clone
));
522 DECL_USE_TEMPLATE (clone
) = DECL_USE_TEMPLATE (fn
);
523 DECL_EXTERNAL (clone
) = DECL_EXTERNAL (fn
);
524 DECL_INTERFACE_KNOWN (clone
) = DECL_INTERFACE_KNOWN (fn
);
525 DECL_NOT_REALLY_EXTERN (clone
) = DECL_NOT_REALLY_EXTERN (fn
);
526 TREE_PUBLIC (clone
) = TREE_PUBLIC (fn
);
527 DECL_VISIBILITY (clone
) = DECL_VISIBILITY (fn
);
528 DECL_VISIBILITY_SPECIFIED (clone
) = DECL_VISIBILITY_SPECIFIED (fn
);
529 DECL_DLLIMPORT_P (clone
) = DECL_DLLIMPORT_P (fn
);
530 DECL_ATTRIBUTES (clone
) = clone_attrs (DECL_ATTRIBUTES (fn
));
531 DECL_DISREGARD_INLINE_LIMITS (clone
) = DECL_DISREGARD_INLINE_LIMITS (fn
);
532 set_decl_section_name (clone
, fn
);
534 /* Adjust the parameter names and locations. */
535 parm
= DECL_ARGUMENTS (fn
);
536 clone_parm
= DECL_ARGUMENTS (clone
);
537 /* Update the `this' parameter, which is always first. */
538 update_cloned_parm (parm
, clone_parm
, first
);
539 parm
= DECL_CHAIN (parm
);
540 clone_parm
= DECL_CHAIN (clone_parm
);
541 if (DECL_HAS_IN_CHARGE_PARM_P (fn
))
542 parm
= DECL_CHAIN (parm
);
543 if (DECL_HAS_VTT_PARM_P (fn
))
544 parm
= DECL_CHAIN (parm
);
545 if (DECL_HAS_VTT_PARM_P (clone
))
546 clone_parm
= DECL_CHAIN (clone_parm
);
547 for (; parm
&& clone_parm
;
548 parm
= DECL_CHAIN (parm
), clone_parm
= DECL_CHAIN (clone_parm
))
549 /* Update this parameter. */
550 update_cloned_parm (parm
, clone_parm
, first
);
553 bool can_alias
= can_alias_cdtor (fn
);
555 /* If we decide to turn clones into thunks, they will branch to fn.
556 Must have original function available to call. */
557 if (!can_alias
&& maybe_thunk_body (fn
, need_alias
))
559 pop_from_top_level ();
560 /* We still need to emit the original function. */
564 /* Emit the DWARF1 abstract instance. */
565 (*debug_hooks
->deferred_inline_function
) (fn
);
567 /* We know that any clones immediately follow FN in the TYPE_FIELDS. */
568 for (idx
= 0; idx
< 3; idx
++)
573 hash_map
<tree
, tree
> *decl_map
;
580 /* Start processing the function. */
581 start_preparsed_function (clone
, NULL_TREE
, SF_PRE_PARSED
);
583 /* Tell cgraph if both ctors or both dtors are known to have
588 && cgraph_node::get_create (fns
[0])->create_same_body_alias
592 if (DECL_ONE_ONLY (fns
[0]))
594 /* For comdat base and complete cdtors put them
595 into the same, *[CD]5* comdat group instead of
597 comdat_group
= cdtor_comdat_group (fns
[1], fns
[0]);
598 cgraph_node::get_create (fns
[0])->set_comdat_group (comdat_group
);
599 if (symtab_node::get (clone
)->same_comdat_group
)
600 symtab_node::get (clone
)->remove_from_same_comdat_group ();
601 symtab_node::get (clone
)->add_to_same_comdat_group
602 (symtab_node::get (fns
[0]));
606 /* Build the delete destructor by calling complete destructor
607 and delete function. */
610 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. */
614 cgraph_node::get_create (clone
)->add_to_same_comdat_group
615 (symtab_node::get (fns
[0]));
618 /* No need to populate body. */ ;
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 if (idx
== 1 && need_alias
)
626 if (DECL_STRUCT_FUNCTION (fn
)->cannot_be_copied_set
)
627 sorry (DECL_STRUCT_FUNCTION (fn
)->cannot_be_copied_reason
, fn
);
629 sorry ("making multiple clones of %qD", fn
);
632 /* Remap the parameters. */
633 decl_map
= new hash_map
<tree
, tree
>;
635 parm
= DECL_ARGUMENTS (fn
),
636 clone_parm
= DECL_ARGUMENTS (clone
);
639 parm
= DECL_CHAIN (parm
))
641 /* Map the in-charge parameter to an appropriate constant. */
642 if (DECL_HAS_IN_CHARGE_PARM_P (fn
) && parmno
== 1)
645 in_charge
= in_charge_arg_for_name (DECL_NAME (clone
));
646 decl_map
->put (parm
, in_charge
);
648 else if (DECL_ARTIFICIAL (parm
)
649 && DECL_NAME (parm
) == vtt_parm_identifier
)
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 if (DECL_HAS_VTT_PARM_P (clone
))
656 DECL_ABSTRACT_ORIGIN (clone_parm
) = parm
;
657 decl_map
->put (parm
, clone_parm
);
658 clone_parm
= DECL_CHAIN (clone_parm
);
660 /* Otherwise, map the VTT parameter to `NULL'. */
664 = fold_convert (TREE_TYPE (parm
), null_pointer_node
);
665 decl_map
->put (parm
, t
);
668 /* Map other parameters to their equivalents in the cloned
675 replacement
= clone_parm
;
676 clone_parm
= DECL_CHAIN (clone_parm
);
680 /* Inheriting ctors can omit parameters from the base
681 clone. Replace them with null lvalues. */
682 tree reftype
= build_reference_type (TREE_TYPE (parm
));
683 replacement
= fold_convert (reftype
, null_pointer_node
);
684 replacement
= convert_from_reference (replacement
);
686 decl_map
->put (parm
, replacement
);
690 if (targetm
.cxx
.cdtor_returns_this ())
692 parm
= DECL_RESULT (fn
);
693 clone_parm
= DECL_RESULT (clone
);
694 decl_map
->put (parm
, clone_parm
);
697 /* Clone the body. */
698 clone_body (clone
, fn
, decl_map
);
704 /* The clone can throw iff the original function can throw. */
705 cp_function_chain
->can_throw
= !TREE_NOTHROW (fn
);
707 /* Now, expand this function into RTL, if appropriate. */
708 finish_function (/*inline_p=*/false);
709 BLOCK_ABSTRACT_ORIGIN (DECL_INITIAL (clone
)) = DECL_INITIAL (fn
);
712 if (expand_or_defer_fn_1 (clone
))
713 emit_associated_thunks (clone
);
714 /* We didn't generate a body, so remove the empty one. */
715 DECL_SAVED_TREE (clone
) = NULL_TREE
;
718 expand_or_defer_fn (clone
);
721 pop_from_top_level ();
723 /* We don't need to process the original function any further. */