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