1 /* Perform optimizations on tree structure.
2 Copyright (C) 1998-2020 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"
34 static void update_cloned_parm (tree
, tree
, bool);
36 /* CLONED_PARM is a copy of CLONE, generated for a cloned constructor
37 or destructor. Update it to ensure that the source-position for
38 the cloned parameter matches that for the original, and that the
39 debugging generation code will be able to find the original PARM. */
42 update_cloned_parm (tree parm
, tree cloned_parm
, bool first
)
44 DECL_ABSTRACT_ORIGIN (cloned_parm
) = parm
;
46 /* We may have taken its address. */
47 TREE_ADDRESSABLE (cloned_parm
) = TREE_ADDRESSABLE (parm
);
49 DECL_BY_REFERENCE (cloned_parm
) = DECL_BY_REFERENCE (parm
);
51 /* The definition might have different constness. */
52 TREE_READONLY (cloned_parm
) = TREE_READONLY (parm
);
54 TREE_USED (cloned_parm
) = !first
|| TREE_USED (parm
);
56 /* The name may have changed from the declaration. */
57 DECL_NAME (cloned_parm
) = DECL_NAME (parm
);
58 DECL_SOURCE_LOCATION (cloned_parm
) = DECL_SOURCE_LOCATION (parm
);
59 TREE_TYPE (cloned_parm
) = TREE_TYPE (parm
);
61 DECL_NOT_GIMPLE_REG_P (cloned_parm
) = DECL_NOT_GIMPLE_REG_P (parm
);
64 /* Like copy_decl_no_change, but handle DECL_OMP_PRIVATIZED_MEMBER
68 cxx_copy_decl (tree decl
, copy_body_data
*id
)
70 tree copy
= copy_decl_no_change (decl
, id
);
72 && DECL_HAS_VALUE_EXPR_P (decl
)
73 && DECL_ARTIFICIAL (decl
)
74 && DECL_LANG_SPECIFIC (decl
)
75 && DECL_OMP_PRIVATIZED_MEMBER (decl
))
77 tree expr
= DECL_VALUE_EXPR (copy
);
78 walk_tree (&expr
, copy_tree_body_r
, id
, NULL
);
79 SET_DECL_VALUE_EXPR (copy
, expr
);
84 /* FN is a function in High GIMPLE form that has a complete body and no
85 CFG. CLONE is a function whose body is to be set to a copy of FN,
86 mapping argument declarations according to the ARG_MAP splay_tree. */
89 clone_body (tree clone
, tree fn
, void *arg_map
)
94 /* Clone the body, as if we were making an inline call. But, remap
95 the parameters in the callee to the parameters of caller. */
96 memset (&id
, 0, sizeof (id
));
99 id
.src_cfun
= DECL_STRUCT_FUNCTION (fn
);
100 id
.decl_map
= static_cast<hash_map
<tree
, tree
> *> (arg_map
);
102 id
.copy_decl
= cxx_copy_decl
;
103 id
.transform_call_graph_edges
= CB_CGE_DUPLICATE
;
104 id
.transform_new_cfg
= true;
105 id
.transform_return_to_modify
= false;
106 id
.transform_lang_insert_block
= NULL
;
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 if (targetm
.cxx
.cdtor_returns_this ())
169 tree val
= DECL_ARGUMENTS (delete_dtor
);
170 val
= build2 (MODIFY_EXPR
, TREE_TYPE (val
),
171 DECL_RESULT (delete_dtor
), val
);
172 add_stmt (build_stmt (0, RETURN_EXPR
, val
));
176 /* Return name of comdat group for complete and base ctor (or dtor)
177 that have the same body. If dtor is virtual, deleting dtor goes
178 into this comdat group as well. */
181 cdtor_comdat_group (tree complete
, tree base
)
183 tree complete_name
= DECL_ASSEMBLER_NAME (complete
);
184 tree base_name
= DECL_ASSEMBLER_NAME (base
);
187 bool diff_seen
= false;
189 gcc_assert (IDENTIFIER_LENGTH (complete_name
)
190 == IDENTIFIER_LENGTH (base_name
));
191 grp_name
= XALLOCAVEC (char, IDENTIFIER_LENGTH (complete_name
) + 1);
192 p
= IDENTIFIER_POINTER (complete_name
);
193 q
= IDENTIFIER_POINTER (base_name
);
194 for (idx
= 0; idx
< IDENTIFIER_LENGTH (complete_name
); idx
++)
195 if (p
[idx
] == q
[idx
])
196 grp_name
[idx
] = p
[idx
];
199 gcc_assert (!diff_seen
201 && (p
[idx
- 1] == 'C' || p
[idx
- 1] == 'D'
202 || p
[idx
- 1] == 'I')
208 grp_name
[idx
] = '\0';
209 gcc_assert (diff_seen
);
210 return get_identifier (grp_name
);
213 /* Returns true iff we can make the base and complete [cd]tor aliases of
214 the same symbol rather than separate functions. */
217 can_alias_cdtor (tree fn
)
219 /* If aliases aren't supported by the assembler, fail. */
220 if (!TARGET_SUPPORTS_ALIASES
)
223 /* We can't use an alias if there are virtual bases. */
224 if (CLASSTYPE_VBASECLASSES (DECL_CONTEXT (fn
)))
226 gcc_assert (DECL_MAYBE_IN_CHARGE_CDTOR_P (fn
));
227 /* Don't use aliases for weak/linkonce definitions unless we can put both
228 symbols in the same COMDAT group. */
229 return (DECL_INTERFACE_KNOWN (fn
)
230 && (SUPPORTS_ONE_ONLY
|| !DECL_WEAK (fn
))
231 && (!DECL_ONE_ONLY (fn
)
232 || (HAVE_COMDAT_GROUP
&& DECL_WEAK (fn
))));
235 /* FN is a [cd]tor, fns is a pointer to an array of length 3. Fill fns
236 with pointers to the base, complete, and deleting variants. */
239 populate_clone_array (tree fn
, tree
*fns
)
247 FOR_EACH_CLONE (clone
, fn
)
248 if (DECL_NAME (clone
) == complete_dtor_identifier
249 || DECL_NAME (clone
) == complete_ctor_identifier
)
251 else if (DECL_NAME (clone
) == base_dtor_identifier
252 || DECL_NAME (clone
) == base_ctor_identifier
)
254 else if (DECL_NAME (clone
) == deleting_dtor_identifier
)
260 /* FN is a constructor or destructor, and there are FUNCTION_DECLs
261 cloned from it nearby. Instead of cloning this body, leave it
262 alone and create tiny one-call bodies for the cloned
263 FUNCTION_DECLs. These clones are sibcall candidates, and their
264 resulting code will be very thunk-esque. */
267 maybe_thunk_body (tree fn
, bool force
)
269 tree bind
, block
, call
, clone
, clone_result
, fn_parm
, fn_parm_typelist
;
270 tree last_arg
, modify
, *args
;
271 int parmno
, vtt_parmno
, max_parms
;
274 if (!force
&& !flag_declone_ctor_dtor
)
277 /* If function accepts variable arguments, give up. */
278 last_arg
= tree_last (TYPE_ARG_TYPES (TREE_TYPE (fn
)));
279 if (last_arg
!= void_list_node
)
282 /* If we got this far, we've decided to turn the clones into thunks. */
284 /* We're going to generate code for fn, so it is no longer "abstract."
285 Also make the unified ctor/dtor private to either the translation unit
286 (for non-vague linkage ctors) or the COMDAT group (otherwise). */
288 populate_clone_array (fn
, fns
);
290 /* Can happen during error recovery (c++/71464). */
291 if (!fns
[0] || !fns
[1])
294 /* Don't use thunks if the base clone omits inherited parameters. */
295 if (ctor_omit_inherited_parms (fns
[0]))
298 DECL_ABSTRACT_P (fn
) = false;
301 TREE_PUBLIC (fn
) = false;
302 DECL_EXTERNAL (fn
) = false;
303 DECL_INTERFACE_KNOWN (fn
) = true;
305 else if (HAVE_COMDAT_GROUP
)
307 /* At eof, defer creation of mangling aliases temporarily. */
308 bool save_defer_mangling_aliases
= defer_mangling_aliases
;
309 defer_mangling_aliases
= true;
310 tree comdat_group
= cdtor_comdat_group (fns
[1], fns
[0]);
311 defer_mangling_aliases
= save_defer_mangling_aliases
;
312 cgraph_node::get_create (fns
[0])->set_comdat_group (comdat_group
);
313 cgraph_node::get_create (fns
[1])->add_to_same_comdat_group
314 (cgraph_node::get_create (fns
[0]));
315 symtab_node::get (fn
)->add_to_same_comdat_group
316 (symtab_node::get (fns
[0]));
318 /* If *[CD][12]* dtors go into the *[CD]5* comdat group and dtor is
319 virtual, it goes into the same comdat group as well. */
320 cgraph_node::get_create (fns
[2])->add_to_same_comdat_group
321 (symtab_node::get (fns
[0]));
322 /* Emit them now that the thunks are same comdat group aliases. */
323 if (!save_defer_mangling_aliases
)
324 generate_mangling_aliases ();
325 TREE_PUBLIC (fn
) = false;
326 DECL_EXTERNAL (fn
) = false;
327 DECL_INTERFACE_KNOWN (fn
) = true;
328 /* function_and_variable_visibility doesn't want !PUBLIC decls to
329 have these flags set. */
330 DECL_WEAK (fn
) = false;
331 DECL_COMDAT (fn
) = false;
334 /* Find the vtt_parm, if present. */
335 for (vtt_parmno
= -1, parmno
= 0, fn_parm
= DECL_ARGUMENTS (fn
);
337 ++parmno
, fn_parm
= TREE_CHAIN (fn_parm
))
339 if (DECL_ARTIFICIAL (fn_parm
)
340 && DECL_NAME (fn_parm
) == vtt_parm_identifier
)
342 /* Compensate for removed in_charge parameter. */
348 /* Allocate an argument buffer for build_cxx_call().
349 Make sure it is large enough for any of the clones. */
351 FOR_EACH_CLONE (clone
, fn
)
353 int length
= list_length (DECL_ARGUMENTS (fn
));
354 if (length
> max_parms
)
357 args
= XALLOCAVEC (tree
, max_parms
);
359 /* We know that any clones immediately follow FN in TYPE_FIELDS. */
360 FOR_EACH_CLONE (clone
, fn
)
364 /* If we've already generated a body for this clone, avoid
365 duplicating it. (Is it possible for a clone-list to grow after we
367 if (DECL_SAVED_TREE (clone
) || TREE_ASM_WRITTEN (clone
))
370 /* Start processing the function. */
371 start_preparsed_function (clone
, NULL_TREE
, SF_PRE_PARSED
);
375 for (clone_parm
= DECL_ARGUMENTS (clone
); clone_parm
;
376 clone_parm
= TREE_CHAIN (clone_parm
))
377 DECL_ABSTRACT_ORIGIN (clone_parm
) = NULL_TREE
;
378 /* Build the delete destructor by calling complete destructor and
380 build_delete_destructor_body (clone
, fns
[1]);
384 /* Walk parameter lists together, creating parameter list for
385 call to original function. */
387 fn_parm
= DECL_ARGUMENTS (fn
),
388 fn_parm_typelist
= TYPE_ARG_TYPES (TREE_TYPE (fn
)),
389 clone_parm
= DECL_ARGUMENTS (clone
);
392 fn_parm
= TREE_CHAIN (fn_parm
))
394 if (parmno
== vtt_parmno
&& ! DECL_HAS_VTT_PARM_P (clone
))
396 gcc_assert (fn_parm_typelist
);
397 /* Clobber argument with formal parameter type. */
399 = convert (TREE_VALUE (fn_parm_typelist
),
402 else if (parmno
== 1 && DECL_HAS_IN_CHARGE_PARM_P (fn
))
405 = copy_node (in_charge_arg_for_name (DECL_NAME (clone
)));
406 args
[parmno
] = in_charge
;
408 /* Map other parameters to their equivalents in the cloned
412 gcc_assert (clone_parm
);
413 DECL_ABSTRACT_ORIGIN (clone_parm
) = NULL
;
414 args
[parmno
] = clone_parm
;
415 /* Clear TREE_ADDRESSABLE on thunk arguments. */
416 TREE_ADDRESSABLE (clone_parm
) = 0;
417 clone_parm
= TREE_CHAIN (clone_parm
);
419 if (fn_parm_typelist
)
420 fn_parm_typelist
= TREE_CHAIN (fn_parm_typelist
);
423 /* We built this list backwards; fix now. */
425 call
= build_cxx_call (fn
, parmno
, args
, tf_warning_or_error
);
426 /* Arguments passed to the thunk by invisible reference should
427 be transmitted to the callee unchanged. Do not create a
428 temporary and invoke the copy constructor. The thunking
429 transformation must not introduce any constructor calls. */
430 CALL_FROM_THUNK_P (call
) = 1;
431 block
= make_node (BLOCK
);
432 if (targetm
.cxx
.cdtor_returns_this ())
434 clone_result
= DECL_RESULT (clone
);
435 modify
= build2 (MODIFY_EXPR
, TREE_TYPE (clone_result
),
437 modify
= build1 (RETURN_EXPR
, void_type_node
, modify
);
444 bind
= c_build_bind_expr (DECL_SOURCE_LOCATION (clone
),
445 block
, cur_stmt_list
);
446 DECL_SAVED_TREE (clone
) = push_stmt_list ();
450 DECL_ABSTRACT_ORIGIN (clone
) = NULL
;
451 expand_or_defer_fn (finish_function (/*inline_p=*/false));
456 /* FN is a function that has a complete body. Clone the body as
457 necessary. Returns nonzero if there's no longer any need to
458 process the main body. */
461 maybe_clone_body (tree fn
)
463 tree comdat_group
= NULL_TREE
;
468 bool need_alias
= false;
470 /* We only clone constructors and destructors. */
471 if (!DECL_MAYBE_IN_CHARGE_CDTOR_P (fn
))
474 populate_clone_array (fn
, fns
);
476 /* Remember if we can't have multiple clones for some reason. We need to
477 check this before we remap local static initializers in clone_body. */
478 if (!tree_versionable_function_p (fn
))
481 /* We know that any clones immediately follow FN in the TYPE_FIELDS
483 push_to_top_level ();
484 for (idx
= 0; idx
< 3; idx
++)
493 /* Update CLONE's source position information to match FN's. */
494 DECL_SOURCE_LOCATION (clone
) = DECL_SOURCE_LOCATION (fn
);
495 DECL_DECLARED_INLINE_P (clone
) = DECL_DECLARED_INLINE_P (fn
);
496 DECL_DECLARED_CONSTEXPR_P (clone
) = DECL_DECLARED_CONSTEXPR_P (fn
);
497 DECL_COMDAT (clone
) = DECL_COMDAT (fn
);
498 DECL_WEAK (clone
) = DECL_WEAK (fn
);
500 /* We don't copy the comdat group from fn to clone because the assembler
501 name of fn was corrupted by write_mangled_name by adding *INTERNAL*
502 to it. By doing so, it also corrupted the comdat group. */
503 if (DECL_ONE_ONLY (fn
))
504 cgraph_node::get_create (clone
)->set_comdat_group (cxx_comdat_group (clone
));
505 DECL_USE_TEMPLATE (clone
) = DECL_USE_TEMPLATE (fn
);
506 DECL_EXTERNAL (clone
) = DECL_EXTERNAL (fn
);
507 DECL_INTERFACE_KNOWN (clone
) = DECL_INTERFACE_KNOWN (fn
);
508 DECL_NOT_REALLY_EXTERN (clone
) = DECL_NOT_REALLY_EXTERN (fn
);
509 TREE_PUBLIC (clone
) = TREE_PUBLIC (fn
);
510 DECL_VISIBILITY (clone
) = DECL_VISIBILITY (fn
);
511 DECL_VISIBILITY_SPECIFIED (clone
) = DECL_VISIBILITY_SPECIFIED (fn
);
512 DECL_DLLIMPORT_P (clone
) = DECL_DLLIMPORT_P (fn
);
513 DECL_ATTRIBUTES (clone
) = copy_list (DECL_ATTRIBUTES (fn
));
514 DECL_DISREGARD_INLINE_LIMITS (clone
) = DECL_DISREGARD_INLINE_LIMITS (fn
);
515 set_decl_section_name (clone
, DECL_SECTION_NAME (fn
));
517 /* Adjust the parameter names and locations. */
518 parm
= DECL_ARGUMENTS (fn
);
519 clone_parm
= DECL_ARGUMENTS (clone
);
520 /* Update the `this' parameter, which is always first. */
521 update_cloned_parm (parm
, clone_parm
, first
);
522 parm
= DECL_CHAIN (parm
);
523 clone_parm
= DECL_CHAIN (clone_parm
);
524 if (DECL_HAS_IN_CHARGE_PARM_P (fn
))
525 parm
= DECL_CHAIN (parm
);
526 if (DECL_HAS_VTT_PARM_P (fn
))
527 parm
= DECL_CHAIN (parm
);
528 if (DECL_HAS_VTT_PARM_P (clone
))
529 clone_parm
= DECL_CHAIN (clone_parm
);
530 for (; parm
&& clone_parm
;
531 parm
= DECL_CHAIN (parm
), clone_parm
= DECL_CHAIN (clone_parm
))
532 /* Update this parameter. */
533 update_cloned_parm (parm
, clone_parm
, first
);
536 bool can_alias
= can_alias_cdtor (fn
);
538 /* If we decide to turn clones into thunks, they will branch to fn.
539 Must have original function available to call. */
540 if (!can_alias
&& maybe_thunk_body (fn
, need_alias
))
542 pop_from_top_level ();
543 /* We still need to emit the original function. */
547 /* Emit the DWARF1 abstract instance. */
548 (*debug_hooks
->deferred_inline_function
) (fn
);
550 /* We know that any clones immediately follow FN in the TYPE_FIELDS. */
551 for (idx
= 0; idx
< 3; idx
++)
556 hash_map
<tree
, tree
> *decl_map
;
563 /* Start processing the function. */
564 start_preparsed_function (clone
, NULL_TREE
, SF_PRE_PARSED
);
566 /* Tell cgraph if both ctors or both dtors are known to have
571 && cgraph_node::get_create (fns
[0])->create_same_body_alias
575 if (DECL_ONE_ONLY (fns
[0]))
577 /* For comdat base and complete cdtors put them
578 into the same, *[CD]5* comdat group instead of
580 comdat_group
= cdtor_comdat_group (fns
[1], fns
[0]);
581 cgraph_node::get_create (fns
[0])->set_comdat_group (comdat_group
);
582 if (symtab_node::get (clone
)->same_comdat_group
)
583 symtab_node::get (clone
)->remove_from_same_comdat_group ();
584 symtab_node::get (clone
)->add_to_same_comdat_group
585 (symtab_node::get (fns
[0]));
589 /* Build the delete destructor by calling complete destructor
590 and delete function. */
593 build_delete_destructor_body (clone
, fns
[1]);
594 /* If *[CD][12]* dtors go into the *[CD]5* comdat group and dtor is
595 virtual, it goes into the same comdat group as well. */
597 cgraph_node::get_create (clone
)->add_to_same_comdat_group
598 (symtab_node::get (fns
[0]));
601 /* No need to populate body. */ ;
604 /* If we can't have multiple copies of FN (say, because there's a
605 static local initialized with the address of a label), we need
606 to use an alias for the complete variant. */
607 if (idx
== 1 && need_alias
)
609 if (DECL_STRUCT_FUNCTION (fn
)->cannot_be_copied_set
)
610 sorry (DECL_STRUCT_FUNCTION (fn
)->cannot_be_copied_reason
, fn
);
612 sorry ("making multiple clones of %qD", fn
);
615 /* Remap the parameters. */
616 decl_map
= new hash_map
<tree
, tree
>;
618 parm
= DECL_ARGUMENTS (fn
),
619 clone_parm
= DECL_ARGUMENTS (clone
);
622 parm
= DECL_CHAIN (parm
))
624 /* Map the in-charge parameter to an appropriate constant. */
625 if (DECL_HAS_IN_CHARGE_PARM_P (fn
) && parmno
== 1)
628 in_charge
= in_charge_arg_for_name (DECL_NAME (clone
));
629 decl_map
->put (parm
, in_charge
);
631 else if (DECL_ARTIFICIAL (parm
)
632 && DECL_NAME (parm
) == vtt_parm_identifier
)
634 /* For a subobject constructor or destructor, the next
635 argument is the VTT parameter. Remap the VTT_PARM
636 from the CLONE to this parameter. */
637 if (DECL_HAS_VTT_PARM_P (clone
))
639 DECL_ABSTRACT_ORIGIN (clone_parm
) = parm
;
640 decl_map
->put (parm
, clone_parm
);
641 clone_parm
= DECL_CHAIN (clone_parm
);
643 /* Otherwise, map the VTT parameter to `NULL'. */
647 = fold_convert (TREE_TYPE (parm
), null_pointer_node
);
648 decl_map
->put (parm
, t
);
651 /* Map other parameters to their equivalents in the cloned
658 replacement
= clone_parm
;
659 clone_parm
= DECL_CHAIN (clone_parm
);
663 /* Inheriting ctors can omit parameters from the base
664 clone. Replace them with null lvalues. */
665 tree reftype
= build_reference_type (TREE_TYPE (parm
));
666 replacement
= fold_convert (reftype
, null_pointer_node
);
667 replacement
= convert_from_reference (replacement
);
669 decl_map
->put (parm
, replacement
);
673 if (targetm
.cxx
.cdtor_returns_this ())
675 parm
= DECL_RESULT (fn
);
676 clone_parm
= DECL_RESULT (clone
);
677 decl_map
->put (parm
, clone_parm
);
680 /* Clone the body. */
681 clone_body (clone
, fn
, decl_map
);
687 /* The clone can throw iff the original function can throw. */
688 cp_function_chain
->can_throw
= !TREE_NOTHROW (fn
);
690 /* Now, expand this function into RTL, if appropriate. */
691 finish_function (/*inline_p=*/false);
692 BLOCK_ABSTRACT_ORIGIN (DECL_INITIAL (clone
)) = DECL_INITIAL (fn
);
695 if (expand_or_defer_fn_1 (clone
))
696 emit_associated_thunks (clone
);
697 /* We didn't generate a body, so remove the empty one. */
698 DECL_SAVED_TREE (clone
) = NULL_TREE
;
701 expand_or_defer_fn (clone
);
704 pop_from_top_level ();
706 /* We don't need to process the original function any further. */