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