1/* Perform optimizations on tree structure. 2 Copyright (C) 1998-2022 Free Software Foundation, Inc. 3 Written by Mark Michell (mark@codesourcery.com). 4 5This file is part of GCC. 6 7GCC is free software; you can redistribute it and/or modify it 8under the terms of the GNU General Public License as published by 9the Free Software Foundation; either version 3, or (at your option) 10any later version. 11 12GCC is distributed in the hope that it will be useful, but 13WITHOUT ANY WARRANTY; without even the implied warranty of 14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15General Public License for more details. 16 17You should have received a copy of the GNU General Public License 18along 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 32/* Prototypes. */ 33 34static void update_cloned_parm (tree, tree, bool); 35 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. */ 40 41static void 42update_cloned_parm (tree parm, tree cloned_parm, bool first) 43{ 44 DECL_ABSTRACT_ORIGIN (cloned_parm) = parm; 45 46 /* We may have taken its address. */ 47 TREE_ADDRESSABLE (cloned_parm) = TREE_ADDRESSABLE (parm); 48 49 DECL_BY_REFERENCE (cloned_parm) = DECL_BY_REFERENCE (parm); 50 51 /* The definition might have different constness. */ 52 TREE_READONLY (cloned_parm) = TREE_READONLY (parm); 53 54 TREE_USED (cloned_parm) = !first || TREE_USED (parm); 55 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); 60 61 DECL_NOT_GIMPLE_REG_P (cloned_parm) = DECL_NOT_GIMPLE_REG_P (parm); 62} 63 64/* Like copy_decl_no_change, but handle DECL_OMP_PRIVATIZED_MEMBER 65 properly. */ 66 67static tree 68cxx_copy_decl (tree decl, copy_body_data *id) 69{ 70 tree copy = copy_decl_no_change (decl, id); 71 if (VAR_P (decl) 72 && DECL_HAS_VALUE_EXPR_P (decl) 73 && DECL_ARTIFICIAL (decl) 74 && DECL_LANG_SPECIFIC (decl) 75 && DECL_OMP_PRIVATIZED_MEMBER (decl)) 76 { 77 tree expr = DECL_VALUE_EXPR (copy); 78 walk_tree (&expr, copy_tree_body_r, id, NULL); 79 SET_DECL_VALUE_EXPR (copy, expr); 80 } 81 return copy; 82} 83 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. */ 87 88static void 89clone_body (tree clone, tree fn, void *arg_map) 90{ 91 copy_body_data id; 92 tree stmts; 93 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)); 97 id.src_fn = fn; 98 id.dst_fn = clone; 99 id.src_cfun = DECL_STRUCT_FUNCTION (fn); 100 id.decl_map = static_cast<hash_map<tree, tree> *> (arg_map); 101 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 107 /* We're not inside any EH region. */ 108 id.eh_lp_nr = 0; 109 110 stmts = DECL_SAVED_TREE (fn); 111 walk_tree (&stmts, copy_tree_body_r, &id, NULL); 112 113 /* Also remap the initializer of any static variables so that they (in 114 particular, any label addresses) correspond to the base variant rather 115 than the abstract one. */ 116 if (DECL_NAME (clone) == base_dtor_identifier 117 || DECL_NAME (clone) == base_ctor_identifier) 118 { 119 unsigned ix; 120 tree decl; 121 122 FOR_EACH_LOCAL_DECL (DECL_STRUCT_FUNCTION (fn), ix, decl) 123 walk_tree (&DECL_INITIAL (decl), copy_tree_body_r, &id, NULL); 124 } 125 126 append_to_statement_list_force (stmts, &DECL_SAVED_TREE (clone)); 127} 128 129/* DELETE_DTOR is a delete destructor whose body will be built. 130 COMPLETE_DTOR is the corresponding complete destructor. */ 131 132static void 133build_delete_destructor_body (tree delete_dtor, tree complete_dtor) 134{ 135 tree parm = DECL_ARGUMENTS (delete_dtor); 136 tree virtual_size = cxx_sizeof (current_class_type); 137 138 /* Call the delete function. */ 139 tree call_delete = build_op_delete_call (DELETE_EXPR, current_class_ptr, 140 virtual_size, 141 /*global_p=*/false, 142 /*placement=*/NULL_TREE, 143 /*alloc_fn=*/NULL_TREE, 144 tf_warning_or_error); 145 146 tree op = get_callee_fndecl (call_delete); 147 if (op && DECL_P (op) && destroying_delete_p (op)) 148 { 149 /* The destroying delete will handle calling complete_dtor. */ 150 add_stmt (call_delete); 151 } 152 else 153 { 154 /* Call the corresponding complete destructor. */ 155 gcc_assert (complete_dtor); 156 tree call_dtor = build_cxx_call (complete_dtor, 1, &parm, 157 tf_warning_or_error); 158 159 /* Operator delete must be called, whether or not the dtor throws. */ 160 add_stmt (build2 (TRY_FINALLY_EXPR, void_type_node, 161 call_dtor, call_delete)); 162 } 163 164 /* Return the address of the object. 165 ??? How is it useful to return an invalid address? */ 166 if (targetm.cxx.cdtor_returns_this ()) 167 { 168 tree val = DECL_ARGUMENTS (delete_dtor); 169 suppress_warning (val, OPT_Wuse_after_free); 170 val = build2 (MODIFY_EXPR, TREE_TYPE (val), 171 DECL_RESULT (delete_dtor), val); 172 add_stmt (build_stmt (0, RETURN_EXPR, val)); 173 } 174} 175 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. */ 179 180static tree 181cdtor_comdat_group (tree complete, tree base) 182{ 183 tree complete_name = DECL_ASSEMBLER_NAME (complete); 184 tree base_name = DECL_ASSEMBLER_NAME (base); 185 char *grp_name; 186 const char *p, *q; 187 bool diff_seen = false; 188 size_t idx; 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]; 197 else 198 { 199 gcc_assert (!diff_seen 200 && idx > 0 201 && (p[idx - 1] == 'C' || p[idx - 1] == 'D' 202 || p[idx - 1] == 'I') 203 && p[idx] == '1' 204 && q[idx] == '2'); 205 grp_name[idx] = '5'; 206 diff_seen = true; 207 } 208 grp_name[idx] = '\0'; 209 gcc_assert (diff_seen); 210 return get_identifier (grp_name); 211} 212 213/* Returns true iff we can make the base and complete [cd]tor aliases of 214 the same symbol rather than separate functions. */ 215 216static bool 217can_alias_cdtor (tree fn) 218{ 219 /* If aliases aren't supported by the assembler, fail. */ 220 if (!TARGET_SUPPORTS_ALIASES) 221 return false; 222 223 /* We can't use an alias if there are virtual bases. */ 224 if (CLASSTYPE_VBASECLASSES (DECL_CONTEXT (fn))) 225 return false; 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)))); 233} 234 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. */ 237 238static void 239populate_clone_array (tree fn, tree *fns) 240{ 241 tree clone; 242 243 fns[0] = NULL_TREE; 244 fns[1] = NULL_TREE; 245 fns[2] = NULL_TREE; 246 247 FOR_EACH_CLONE (clone, fn) 248 if (DECL_NAME (clone) == complete_dtor_identifier 249 || DECL_NAME (clone) == complete_ctor_identifier) 250 fns[1] = clone; 251 else if (DECL_NAME (clone) == base_dtor_identifier 252 || DECL_NAME (clone) == base_ctor_identifier) 253 fns[0] = clone; 254 else if (DECL_NAME (clone) == deleting_dtor_identifier) 255 fns[2] = clone; 256 else 257 gcc_unreachable (); 258} 259 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. */ 265 266static bool 267maybe_thunk_body (tree fn, bool force) 268{ 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; 272 tree fns[3]; 273 274 if (!force && !flag_declone_ctor_dtor) 275 return 0; 276 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) 280 return 0; 281 282 /* If we got this far, we've decided to turn the clones into thunks. */ 283 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). */ 287 288 populate_clone_array (fn, fns); 289 290 /* Can happen during error recovery (c++/71464). */ 291 if (!fns[0] || !fns[1]) 292 return 0; 293 294 /* Don't use thunks if the base clone omits inherited parameters. */ 295 if (ctor_omit_inherited_parms (fns[0])) 296 return 0; 297 298 DECL_ABSTRACT_P (fn) = false; 299 if (!DECL_WEAK (fn)) 300 { 301 TREE_PUBLIC (fn) = false; 302 DECL_EXTERNAL (fn) = false; 303 DECL_INTERFACE_KNOWN (fn) = true; 304 } 305 else if (HAVE_COMDAT_GROUP) 306 { 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])); 317 if (fns[2]) 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; 332 } 333 334 /* Find the vtt_parm, if present. */ 335 for (vtt_parmno = -1, parmno = 0, fn_parm = DECL_ARGUMENTS (fn); 336 fn_parm; 337 ++parmno, fn_parm = TREE_CHAIN (fn_parm)) 338 { 339 if (DECL_ARTIFICIAL (fn_parm) 340 && DECL_NAME (fn_parm) == vtt_parm_identifier) 341 { 342 /* Compensate for removed in_charge parameter. */ 343 vtt_parmno = parmno; 344 break; 345 } 346 } 347 348 /* Allocate an argument buffer for build_cxx_call(). 349 Make sure it is large enough for any of the clones. */ 350 max_parms = 0; 351 FOR_EACH_CLONE (clone, fn) 352 { 353 int length = list_length (DECL_ARGUMENTS (fn)); 354 if (length > max_parms) 355 max_parms = length; 356 } 357 args = XALLOCAVEC (tree, max_parms); 358 359 /* We know that any clones immediately follow FN in TYPE_FIELDS. */ 360 FOR_EACH_CLONE (clone, fn) 361 { 362 tree clone_parm; 363 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 366 first see it?) */ 367 if (DECL_SAVED_TREE (clone) || TREE_ASM_WRITTEN (clone)) 368 continue; 369 370 /* Start processing the function. */ 371 start_preparsed_function (clone, NULL_TREE, SF_PRE_PARSED); 372 373 if (clone == fns[2]) 374 { 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 379 delete function. */ 380 build_delete_destructor_body (clone, fns[1]); 381 } 382 else 383 { 384 /* Walk parameter lists together, creating parameter list for 385 call to original function. */ 386 for (parmno = 0, 387 fn_parm = DECL_ARGUMENTS (fn), 388 fn_parm_typelist = TYPE_ARG_TYPES (TREE_TYPE (fn)), 389 clone_parm = DECL_ARGUMENTS (clone); 390 fn_parm; 391 ++parmno, 392 fn_parm = TREE_CHAIN (fn_parm)) 393 { 394 if (parmno == vtt_parmno && ! DECL_HAS_VTT_PARM_P (clone)) 395 { 396 gcc_assert (fn_parm_typelist); 397 /* Clobber argument with formal parameter type. */ 398 args[parmno] 399 = convert (TREE_VALUE (fn_parm_typelist), 400 null_pointer_node); 401 } 402 else if (parmno == 1 && DECL_HAS_IN_CHARGE_PARM_P (fn)) 403 { 404 tree in_charge 405 = copy_node (in_charge_arg_for_name (DECL_NAME (clone))); 406 args[parmno] = in_charge; 407 } 408 /* Map other parameters to their equivalents in the cloned 409 function. */ 410 else 411 { 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); 418 } 419 if (fn_parm_typelist) 420 fn_parm_typelist = TREE_CHAIN (fn_parm_typelist); 421 } 422 423 /* We built this list backwards; fix now. */ 424 mark_used (fn); 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 ()) 433 { 434 clone_result = DECL_RESULT (clone); 435 modify = build2 (MODIFY_EXPR, TREE_TYPE (clone_result), 436 clone_result, call); 437 modify = build1 (RETURN_EXPR, void_type_node, modify); 438 add_stmt (modify); 439 } 440 else 441 { 442 add_stmt (call); 443 } 444 bind = c_build_bind_expr (DECL_SOURCE_LOCATION (clone), 445 block, cur_stmt_list); 446 DECL_SAVED_TREE (clone) = push_stmt_list (); 447 add_stmt (bind); 448 } 449 450 DECL_ABSTRACT_ORIGIN (clone) = NULL; 451 expand_or_defer_fn (finish_function (/*inline_p=*/false)); 452 } 453 return 1; 454} 455 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. */ 459 460bool 461maybe_clone_body (tree fn) 462{ 463 tree comdat_group = NULL_TREE; 464 tree clone; 465 tree fns[3]; 466 bool first = true; 467 int idx; 468 bool need_alias = false; 469 470 /* We only clone constructors and destructors. */ 471 if (!DECL_MAYBE_IN_CHARGE_CDTOR_P (fn)) 472 return 0; 473 474 populate_clone_array (fn, fns); 475 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)) 479 need_alias = true; 480 481 /* We know that any clones immediately follow FN in the TYPE_FIELDS 482 list. */ 483 push_to_top_level (); 484 for (idx = 0; idx < 3; idx++) 485 { 486 tree parm; 487 tree clone_parm; 488 489 clone = fns[idx]; 490 if (!clone) 491 continue; 492 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); 499 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, fn); 516 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); 534 } 535 536 bool can_alias = can_alias_cdtor (fn); 537 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)) 541 { 542 pop_from_top_level (); 543 /* We still need to emit the original function. */ 544 return 0; 545 } 546 547 /* Emit the DWARF1 abstract instance. */ 548 (*debug_hooks->deferred_inline_function) (fn); 549 550 /* We know that any clones immediately follow FN in the TYPE_FIELDS. */ 551 for (idx = 0; idx < 3; idx++) 552 { 553 tree parm; 554 tree clone_parm; 555 int parmno; 556 hash_map<tree, tree> *decl_map; 557 bool alias = false; 558 559 clone = fns[idx]; 560 if (!clone) 561 continue; 562 563 /* Start processing the function. */ 564 start_preparsed_function (clone, NULL_TREE, SF_PRE_PARSED); 565 566 /* Tell cgraph if both ctors or both dtors are known to have 567 the same body. */ 568 if (can_alias 569 && fns[0] 570 && idx == 1 571 && cgraph_node::get_create (fns[0])->create_same_body_alias 572 (clone, fns[0])) 573 { 574 alias = true; 575 if (DECL_ONE_ONLY (fns[0])) 576 { 577 /* For comdat base and complete cdtors put them 578 into the same, *[CD]5* comdat group instead of 579 *[CD][12]*. */ 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])); 586 } 587 } 588 589 /* Build the delete destructor by calling complete destructor 590 and delete function. */ 591 if (idx == 2) 592 { 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. */ 596 if (comdat_group) 597 cgraph_node::get_create (clone)->add_to_same_comdat_group 598 (symtab_node::get (fns[0])); 599 } 600 else if (alias) 601 /* No need to populate body. */ ; 602 else 603 { 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) 608 { 609 if (DECL_STRUCT_FUNCTION (fn)->cannot_be_copied_set) 610 sorry (DECL_STRUCT_FUNCTION (fn)->cannot_be_copied_reason, fn); 611 else 612 sorry ("making multiple clones of %qD", fn); 613 } 614 615 /* Remap the parameters. */ 616 decl_map = new hash_map<tree, tree>; 617 for (parmno = 0, 618 parm = DECL_ARGUMENTS (fn), 619 clone_parm = DECL_ARGUMENTS (clone); 620 parm; 621 ++parmno, 622 parm = DECL_CHAIN (parm)) 623 { 624 /* Map the in-charge parameter to an appropriate constant. */ 625 if (DECL_HAS_IN_CHARGE_PARM_P (fn) && parmno == 1) 626 { 627 tree in_charge; 628 in_charge = in_charge_arg_for_name (DECL_NAME (clone)); 629 decl_map->put (parm, in_charge); 630 } 631 else if (DECL_ARTIFICIAL (parm) 632 && DECL_NAME (parm) == vtt_parm_identifier) 633 { 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)) 638 { 639 DECL_ABSTRACT_ORIGIN (clone_parm) = parm; 640 decl_map->put (parm, clone_parm); 641 clone_parm = DECL_CHAIN (clone_parm); 642 } 643 /* Otherwise, map the VTT parameter to `NULL'. */ 644 else 645 { 646 tree t 647 = fold_convert (TREE_TYPE (parm), null_pointer_node); 648 decl_map->put (parm, t); 649 } 650 } 651 /* Map other parameters to their equivalents in the cloned 652 function. */ 653 else 654 { 655 tree replacement; 656 if (clone_parm) 657 { 658 replacement = clone_parm; 659 clone_parm = DECL_CHAIN (clone_parm); 660 } 661 else 662 { 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); 668 } 669 decl_map->put (parm, replacement); 670 } 671 } 672 673 if (targetm.cxx.cdtor_returns_this ()) 674 { 675 parm = DECL_RESULT (fn); 676 clone_parm = DECL_RESULT (clone); 677 decl_map->put (parm, clone_parm); 678 } 679 680 /* Clone the body. */ 681 clone_body (clone, fn, decl_map); 682 683 /* Clean up. */ 684 delete decl_map; 685 } 686 687 /* The clone can throw iff the original function can throw. */ 688 cp_function_chain->can_throw = !TREE_NOTHROW (fn); 689 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); 693 if (alias) 694 { 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; 699 } 700 else 701 expand_or_defer_fn (clone); 702 first = false; 703 } 704 pop_from_top_level (); 705 706 /* We don't need to process the original function any further. */ 707 return 1; 708} 709