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