118334Speter/* Handle the hair of processing (but not expanding) inline functions. 218334Speter Also manage function and variable name overloading. 3169689Skan Copyright (C) 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 4169689Skan 1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. 518334Speter Contributed by Michael Tiemann (tiemann@cygnus.com) 618334Speter 7132718SkanThis file is part of GCC. 8169689Skan 9132718SkanGCC is free software; you can redistribute it and/or modify 1018334Speterit under the terms of the GNU General Public License as published by 1118334Speterthe Free Software Foundation; either version 2, or (at your option) 1218334Speterany later version. 1318334Speter 14132718SkanGCC is distributed in the hope that it will be useful, 1518334Speterbut WITHOUT ANY WARRANTY; without even the implied warranty of 1618334SpeterMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1718334SpeterGNU General Public License for more details. 1818334Speter 1918334SpeterYou should have received a copy of the GNU General Public License 20132718Skanalong with GCC; see the file COPYING. If not, write to 21169689Skanthe Free Software Foundation, 51 Franklin Street, Fifth Floor, 22169689SkanBoston, MA 02110-1301, USA. */ 2318334Speter 2418334Speter 2518334Speter/* Handle method declarations. */ 2618334Speter#include "config.h" 2750397Sobrien#include "system.h" 28132718Skan#include "coretypes.h" 29132718Skan#include "tm.h" 3018334Speter#include "tree.h" 3118334Speter#include "cp-tree.h" 3218334Speter#include "rtl.h" 3318334Speter#include "expr.h" 3418334Speter#include "output.h" 3518334Speter#include "flags.h" 3650397Sobrien#include "toplev.h" 3790075Sobrien#include "tm_p.h" 38117395Skan#include "target.h" 39169689Skan#include "tree-pass.h" 40169689Skan#include "diagnostic.h" 4118334Speter 4290075Sobrien/* Various flags to control the mangling process. */ 4318334Speter 4490075Sobrienenum mangling_flags 4590075Sobrien{ 4690075Sobrien /* No flags. */ 4790075Sobrien mf_none = 0, 4890075Sobrien /* The thing we are presently mangling is part of a template type, 4990075Sobrien rather than a fully instantiated type. Therefore, we may see 5090075Sobrien complex expressions where we would normally expect to see a 5190075Sobrien simple integer constant. */ 5290075Sobrien mf_maybe_uninstantiated = 1, 5390075Sobrien /* When mangling a numeric value, use the form `_XX_' (instead of 5490075Sobrien just `XX') if the value has more than one digit. */ 55132718Skan mf_use_underscores_around_value = 2 5690075Sobrien}; 5750397Sobrien 5890075Sobrientypedef enum mangling_flags mangling_flags; 5990075Sobrien 60132718Skanstatic tree thunk_adjust (tree, bool, HOST_WIDE_INT, tree); 61132718Skanstatic void do_build_assign_ref (tree); 62132718Skanstatic void do_build_copy_constructor (tree); 63132718Skanstatic tree synthesize_exception_spec (tree, tree (*) (tree, void *), void *); 64132718Skanstatic tree locate_dtor (tree, void *); 65132718Skanstatic tree locate_ctor (tree, void *); 66132718Skanstatic tree locate_copy (tree, void *); 67132718Skanstatic tree make_alias_for_thunk (tree); 6818334Speter 6990075Sobrien/* Called once to initialize method.c. */ 7050397Sobrien 7118334Spetervoid 72132718Skaninit_method (void) 7318334Speter{ 7490075Sobrien init_mangle (); 7518334Speter} 7618334Speter 77132718Skan/* Return a this or result adjusting thunk to FUNCTION. THIS_ADJUSTING 78132718Skan indicates whether it is a this or result adjusting thunk. 79132718Skan FIXED_OFFSET and VIRTUAL_OFFSET indicate how to do the adjustment 80132718Skan (see thunk_adjust). VIRTUAL_OFFSET can be NULL, but FIXED_OFFSET 81132718Skan never is. VIRTUAL_OFFSET is the /index/ into the vtable for this 82132718Skan adjusting thunks, we scale it to a byte offset. For covariant 83132718Skan thunks VIRTUAL_OFFSET is the virtual binfo. You must post process 84132718Skan the returned thunk with finish_thunk. */ 8518334Speter 8618334Spetertree 87132718Skanmake_thunk (tree function, bool this_adjusting, 88132718Skan tree fixed_offset, tree virtual_offset) 8918334Speter{ 90132718Skan HOST_WIDE_INT d; 9118334Speter tree thunk; 92169689Skan 93169689Skan gcc_assert (TREE_CODE (function) == FUNCTION_DECL); 94132718Skan /* We can have this thunks to covariant thunks, but not vice versa. */ 95169689Skan gcc_assert (!DECL_THIS_THUNK_P (function)); 96169689Skan gcc_assert (!DECL_RESULT_THUNK_P (function) || this_adjusting); 97169689Skan 98132718Skan /* Scale the VIRTUAL_OFFSET to be in terms of bytes. */ 99132718Skan if (this_adjusting && virtual_offset) 100169689Skan virtual_offset 10190075Sobrien = size_binop (MULT_EXPR, 102169689Skan virtual_offset, 103169689Skan convert (ssizetype, 104169689Skan TYPE_SIZE_UNIT (vtable_entry_type))); 105169689Skan 106132718Skan d = tree_low_cst (fixed_offset, 0); 107169689Skan 108132718Skan /* See if we already have the thunk in question. For this_adjusting 109132718Skan thunks VIRTUAL_OFFSET will be an INTEGER_CST, for covariant thunks it 110132718Skan will be a BINFO. */ 111117395Skan for (thunk = DECL_THUNKS (function); thunk; thunk = TREE_CHAIN (thunk)) 112132718Skan if (DECL_THIS_THUNK_P (thunk) == this_adjusting 113132718Skan && THUNK_FIXED_OFFSET (thunk) == d 114132718Skan && !virtual_offset == !THUNK_VIRTUAL_OFFSET (thunk) 115132718Skan && (!virtual_offset 116132718Skan || (this_adjusting 117132718Skan ? tree_int_cst_equal (THUNK_VIRTUAL_OFFSET (thunk), 118132718Skan virtual_offset) 119132718Skan : THUNK_VIRTUAL_OFFSET (thunk) == virtual_offset))) 120117395Skan return thunk; 121169689Skan 122117395Skan /* All thunks must be created before FUNCTION is actually emitted; 123117395Skan the ABI requires that all thunks be emitted together with the 124117395Skan function to which they transfer control. */ 125169689Skan gcc_assert (!TREE_ASM_WRITTEN (function)); 126132718Skan /* Likewise, we can only be adding thunks to a function declared in 127132718Skan the class currently being laid out. */ 128169689Skan gcc_assert (TYPE_SIZE (DECL_CONTEXT (function)) 129169689Skan && TYPE_BEING_DEFINED (DECL_CONTEXT (function))); 130117395Skan 131132718Skan thunk = build_decl (FUNCTION_DECL, NULL_TREE, TREE_TYPE (function)); 132117395Skan DECL_LANG_SPECIFIC (thunk) = DECL_LANG_SPECIFIC (function); 133132718Skan cxx_dup_lang_specific_decl (thunk); 134132718Skan DECL_THUNKS (thunk) = NULL_TREE; 135169689Skan 136117395Skan DECL_CONTEXT (thunk) = DECL_CONTEXT (function); 137117395Skan TREE_READONLY (thunk) = TREE_READONLY (function); 138117395Skan TREE_THIS_VOLATILE (thunk) = TREE_THIS_VOLATILE (function); 139117395Skan TREE_PUBLIC (thunk) = TREE_PUBLIC (function); 140132718Skan SET_DECL_THUNK_P (thunk, this_adjusting); 141132718Skan THUNK_TARGET (thunk) = function; 142132718Skan THUNK_FIXED_OFFSET (thunk) = d; 143132718Skan THUNK_VIRTUAL_OFFSET (thunk) = virtual_offset; 144132718Skan THUNK_ALIAS (thunk) = NULL_TREE; 145169689Skan 146117395Skan /* The thunk itself is not a constructor or destructor, even if 147117395Skan the thing it is thunking to is. */ 148117395Skan DECL_INTERFACE_KNOWN (thunk) = 1; 149117395Skan DECL_NOT_REALLY_EXTERN (thunk) = 1; 150117395Skan DECL_SAVED_FUNCTION_DATA (thunk) = NULL; 151117395Skan DECL_DESTRUCTOR_P (thunk) = 0; 152117395Skan DECL_CONSTRUCTOR_P (thunk) = 0; 153117395Skan DECL_EXTERNAL (thunk) = 1; 154117395Skan DECL_ARTIFICIAL (thunk) = 1; 155117395Skan /* Even if this thunk is a member of a local class, we don't 156117395Skan need a static chain. */ 157117395Skan DECL_NO_STATIC_CHAIN (thunk) = 1; 158117395Skan /* The THUNK is not a pending inline, even if the FUNCTION is. */ 159117395Skan DECL_PENDING_INLINE_P (thunk) = 0; 160117395Skan DECL_INLINE (thunk) = 0; 161117395Skan DECL_DECLARED_INLINE_P (thunk) = 0; 162117395Skan /* Nor has it been deferred. */ 163117395Skan DECL_DEFERRED_FN (thunk) = 0; 164169689Skan /* Nor is it a template instantiation. */ 165169689Skan DECL_USE_TEMPLATE (thunk) = 0; 166169689Skan DECL_TEMPLATE_INFO (thunk) = NULL; 167169689Skan 168117395Skan /* Add it to the list of thunks associated with FUNCTION. */ 169117395Skan TREE_CHAIN (thunk) = DECL_THUNKS (function); 170117395Skan DECL_THUNKS (function) = thunk; 171117395Skan 17218334Speter return thunk; 17318334Speter} 17418334Speter 175132718Skan/* Finish THUNK, a thunk decl. */ 17650397Sobrien 17718334Spetervoid 178132718Skanfinish_thunk (tree thunk) 17918334Speter{ 180132718Skan tree function, name; 181132718Skan tree fixed_offset = ssize_int (THUNK_FIXED_OFFSET (thunk)); 182132718Skan tree virtual_offset = THUNK_VIRTUAL_OFFSET (thunk); 18318334Speter 184169689Skan gcc_assert (!DECL_NAME (thunk) && DECL_THUNK_P (thunk)); 185132718Skan if (virtual_offset && DECL_RESULT_THUNK_P (thunk)) 186132718Skan virtual_offset = BINFO_VPTR_FIELD (virtual_offset); 187132718Skan function = THUNK_TARGET (thunk); 188132718Skan name = mangle_thunk (function, DECL_THIS_THUNK_P (thunk), 189132718Skan fixed_offset, virtual_offset); 190132718Skan 191132718Skan /* We can end up with declarations of (logically) different 192132718Skan covariant thunks, that do identical adjustments. The two thunks 193132718Skan will be adjusting between within different hierarchies, which 194132718Skan happen to have the same layout. We must nullify one of them to 195132718Skan refer to the other. */ 196132718Skan if (DECL_RESULT_THUNK_P (thunk)) 197132718Skan { 198132718Skan tree cov_probe; 199132718Skan 200132718Skan for (cov_probe = DECL_THUNKS (function); 201132718Skan cov_probe; cov_probe = TREE_CHAIN (cov_probe)) 202132718Skan if (DECL_NAME (cov_probe) == name) 203132718Skan { 204169689Skan gcc_assert (!DECL_THUNKS (thunk)); 205132718Skan THUNK_ALIAS (thunk) = (THUNK_ALIAS (cov_probe) 206132718Skan ? THUNK_ALIAS (cov_probe) : cov_probe); 207132718Skan break; 208132718Skan } 209132718Skan } 210169689Skan 211132718Skan DECL_NAME (thunk) = name; 212132718Skan SET_DECL_ASSEMBLER_NAME (thunk, name); 213132718Skan} 214132718Skan 215132718Skan/* Adjust PTR by the constant FIXED_OFFSET, and by the vtable 216132718Skan offset indicated by VIRTUAL_OFFSET, if that is 217132718Skan non-null. THIS_ADJUSTING is nonzero for a this adjusting thunk and 218132718Skan zero for a result adjusting thunk. */ 219132718Skan 220132718Skanstatic tree 221132718Skanthunk_adjust (tree ptr, bool this_adjusting, 222132718Skan HOST_WIDE_INT fixed_offset, tree virtual_offset) 223132718Skan{ 224132718Skan if (this_adjusting) 225132718Skan /* Adjust the pointer by the constant. */ 226169689Skan ptr = fold_build2 (PLUS_EXPR, TREE_TYPE (ptr), ptr, 227169689Skan ssize_int (fixed_offset)); 228132718Skan 229132718Skan /* If there's a virtual offset, look up that value in the vtable and 230132718Skan adjust the pointer again. */ 231132718Skan if (virtual_offset) 232132718Skan { 233132718Skan tree vtable; 234132718Skan 235132718Skan ptr = save_expr (ptr); 236132718Skan /* The vptr is always at offset zero in the object. */ 237132718Skan vtable = build1 (NOP_EXPR, 238169689Skan build_pointer_type (build_pointer_type 239132718Skan (vtable_entry_type)), 240132718Skan ptr); 241132718Skan /* Form the vtable address. */ 242132718Skan vtable = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (vtable)), vtable); 243132718Skan /* Find the entry with the vcall offset. */ 244169689Skan vtable = build2 (PLUS_EXPR, TREE_TYPE (vtable), vtable, virtual_offset); 245132718Skan /* Get the offset itself. */ 246132718Skan vtable = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (vtable)), vtable); 247132718Skan /* Adjust the `this' pointer. */ 248169689Skan ptr = fold_build2 (PLUS_EXPR, TREE_TYPE (ptr), ptr, vtable); 249132718Skan } 250169689Skan 251132718Skan if (!this_adjusting) 252132718Skan /* Adjust the pointer by the constant. */ 253169689Skan ptr = fold_build2 (PLUS_EXPR, TREE_TYPE (ptr), ptr, 254169689Skan ssize_int (fixed_offset)); 255132718Skan 256132718Skan return ptr; 257132718Skan} 258132718Skan 259132718Skanstatic GTY (()) int thunk_labelno; 260132718Skan 261132718Skan/* Create a static alias to function. */ 262132718Skan 263169689Skantree 264169689Skanmake_alias_for (tree function, tree newid) 265132718Skan{ 266169689Skan tree alias = build_decl (FUNCTION_DECL, newid, TREE_TYPE (function)); 267132718Skan DECL_LANG_SPECIFIC (alias) = DECL_LANG_SPECIFIC (function); 268132718Skan cxx_dup_lang_specific_decl (alias); 269132718Skan DECL_CONTEXT (alias) = NULL; 270132718Skan TREE_READONLY (alias) = TREE_READONLY (function); 271132718Skan TREE_THIS_VOLATILE (alias) = TREE_THIS_VOLATILE (function); 272132718Skan TREE_PUBLIC (alias) = 0; 273132718Skan DECL_INTERFACE_KNOWN (alias) = 1; 274132718Skan DECL_NOT_REALLY_EXTERN (alias) = 1; 275132718Skan DECL_THIS_STATIC (alias) = 1; 276132718Skan DECL_SAVED_FUNCTION_DATA (alias) = NULL; 277132718Skan DECL_DESTRUCTOR_P (alias) = 0; 278132718Skan DECL_CONSTRUCTOR_P (alias) = 0; 279132718Skan DECL_CLONED_FUNCTION (alias) = NULL_TREE; 280132718Skan DECL_EXTERNAL (alias) = 0; 281132718Skan DECL_ARTIFICIAL (alias) = 1; 282132718Skan DECL_NO_STATIC_CHAIN (alias) = 1; 283132718Skan DECL_PENDING_INLINE_P (alias) = 0; 284132718Skan DECL_INLINE (alias) = 0; 285132718Skan DECL_DECLARED_INLINE_P (alias) = 0; 286132718Skan DECL_DEFERRED_FN (alias) = 0; 287132718Skan DECL_USE_TEMPLATE (alias) = 0; 288132718Skan DECL_TEMPLATE_INSTANTIATED (alias) = 0; 289132718Skan DECL_TEMPLATE_INFO (alias) = NULL; 290132718Skan DECL_INITIAL (alias) = error_mark_node; 291132718Skan TREE_ADDRESSABLE (alias) = 1; 292132718Skan TREE_USED (alias) = 1; 293132718Skan SET_DECL_ASSEMBLER_NAME (alias, DECL_NAME (alias)); 294132718Skan TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (alias)) = 1; 295169689Skan return alias; 296169689Skan} 297169689Skan 298169689Skanstatic tree 299169689Skanmake_alias_for_thunk (tree function) 300169689Skan{ 301169689Skan tree alias; 302169689Skan char buf[256]; 303169689Skan 304169689Skan ASM_GENERATE_INTERNAL_LABEL (buf, "LTHUNK", thunk_labelno); 305169689Skan thunk_labelno++; 306169689Skan 307169689Skan alias = make_alias_for (function, get_identifier (buf)); 308169689Skan 309132718Skan if (!flag_syntax_only) 310132718Skan assemble_alias (alias, DECL_ASSEMBLER_NAME (function)); 311169689Skan 312132718Skan return alias; 313132718Skan} 314132718Skan 315132718Skan/* Emit the definition of a C++ multiple inheritance or covariant 316132718Skan return vtable thunk. If EMIT_P is nonzero, the thunk is emitted 317132718Skan immediately. */ 318132718Skan 319132718Skanvoid 320132718Skanuse_thunk (tree thunk_fndecl, bool emit_p) 321132718Skan{ 322169689Skan tree a, t, function, alias; 323132718Skan tree virtual_offset; 324132718Skan HOST_WIDE_INT fixed_offset, virtual_value; 325132718Skan bool this_adjusting = DECL_THIS_THUNK_P (thunk_fndecl); 326132718Skan 327132718Skan /* We should have called finish_thunk to give it a name. */ 328169689Skan gcc_assert (DECL_NAME (thunk_fndecl)); 329132718Skan 330132718Skan /* We should never be using an alias, always refer to the 331132718Skan aliased thunk. */ 332169689Skan gcc_assert (!THUNK_ALIAS (thunk_fndecl)); 333132718Skan 33418334Speter if (TREE_ASM_WRITTEN (thunk_fndecl)) 33518334Speter return; 336169689Skan 337132718Skan function = THUNK_TARGET (thunk_fndecl); 338132718Skan if (DECL_RESULT (thunk_fndecl)) 33990075Sobrien /* We already turned this thunk into an ordinary function. 34090075Sobrien There's no need to process this thunk again. */ 34190075Sobrien return; 34218334Speter 343146895Skan if (DECL_THUNK_P (function)) 344146895Skan /* The target is itself a thunk, process it now. */ 345146895Skan use_thunk (function, emit_p); 346169689Skan 34790075Sobrien /* Thunks are always addressable; they only appear in vtables. */ 34890075Sobrien TREE_ADDRESSABLE (thunk_fndecl) = 1; 34918334Speter 35090075Sobrien /* Figure out what function is being thunked to. It's referenced in 35190075Sobrien this translation unit. */ 35250397Sobrien TREE_ADDRESSABLE (function) = 1; 35350397Sobrien mark_used (function); 35490075Sobrien if (!emit_p) 35590075Sobrien return; 35618334Speter 357169689Skan if (TARGET_USE_LOCAL_THUNK_ALIAS_P (function)) 358169689Skan alias = make_alias_for_thunk (function); 359169689Skan else 360169689Skan alias = function; 36118334Speter 362132718Skan fixed_offset = THUNK_FIXED_OFFSET (thunk_fndecl); 363132718Skan virtual_offset = THUNK_VIRTUAL_OFFSET (thunk_fndecl); 364132718Skan 365132718Skan if (virtual_offset) 366117395Skan { 367132718Skan if (!this_adjusting) 368132718Skan virtual_offset = BINFO_VPTR_FIELD (virtual_offset); 369132718Skan virtual_value = tree_low_cst (virtual_offset, /*pos=*/0); 370169689Skan gcc_assert (virtual_value); 371117395Skan } 372117395Skan else 373132718Skan virtual_value = 0; 374169689Skan 37590075Sobrien /* And, if we need to emit the thunk, it's used. */ 37690075Sobrien mark_used (thunk_fndecl); 37790075Sobrien /* This thunk is actually defined. */ 37890075Sobrien DECL_EXTERNAL (thunk_fndecl) = 0; 37990075Sobrien /* The linkage of the function may have changed. FIXME in linkage 38090075Sobrien rewrite. */ 38190075Sobrien TREE_PUBLIC (thunk_fndecl) = TREE_PUBLIC (function); 382132718Skan DECL_VISIBILITY (thunk_fndecl) = DECL_VISIBILITY (function); 383169689Skan DECL_VISIBILITY_SPECIFIED (thunk_fndecl) 384169689Skan = DECL_VISIBILITY_SPECIFIED (function); 385169689Skan if (DECL_ONE_ONLY (function)) 386169689Skan make_decl_one_only (thunk_fndecl); 38718334Speter 38890075Sobrien if (flag_syntax_only) 38990075Sobrien { 39090075Sobrien TREE_ASM_WRITTEN (thunk_fndecl) = 1; 39190075Sobrien return; 39290075Sobrien } 39390075Sobrien 39490075Sobrien push_to_top_level (); 39590075Sobrien 396169689Skan if (TARGET_USE_LOCAL_THUNK_ALIAS_P (function) 397169689Skan && targetm.have_named_sections) 398132718Skan { 399132718Skan resolve_unique_section (function, 0, flag_function_sections); 400132718Skan 401132718Skan if (DECL_SECTION_NAME (function) != NULL && DECL_ONE_ONLY (function)) 402132718Skan { 403132718Skan resolve_unique_section (thunk_fndecl, 0, flag_function_sections); 404132718Skan 405132718Skan /* Output the thunk into the same section as function. */ 406132718Skan DECL_SECTION_NAME (thunk_fndecl) = DECL_SECTION_NAME (function); 407132718Skan } 408132718Skan } 409132718Skan 41096263Sobrien /* The back-end expects DECL_INITIAL to contain a BLOCK, so we 41196263Sobrien create one. */ 41296263Sobrien DECL_INITIAL (thunk_fndecl) = make_node (BLOCK); 413169689Skan 414169689Skan /* Set up cloned argument trees for the thunk. */ 415169689Skan t = NULL_TREE; 416169689Skan for (a = DECL_ARGUMENTS (function); a; a = TREE_CHAIN (a)) 417169689Skan { 418169689Skan tree x = copy_node (a); 419169689Skan TREE_CHAIN (x) = t; 420169689Skan DECL_CONTEXT (x) = thunk_fndecl; 421169689Skan SET_DECL_RTL (x, NULL_RTX); 422169689Skan DECL_HAS_VALUE_EXPR_P (x) = 0; 423169689Skan t = x; 424169689Skan } 425169689Skan a = nreverse (t); 426169689Skan DECL_ARGUMENTS (thunk_fndecl) = a; 427169689Skan BLOCK_VARS (DECL_INITIAL (thunk_fndecl)) = a; 428169689Skan 429132718Skan if (this_adjusting 430132718Skan && targetm.asm_out.can_output_mi_thunk (thunk_fndecl, fixed_offset, 431132718Skan virtual_value, alias)) 43290075Sobrien { 43390075Sobrien const char *fnname; 43490075Sobrien current_function_decl = thunk_fndecl; 43590075Sobrien DECL_RESULT (thunk_fndecl) 43690075Sobrien = build_decl (RESULT_DECL, 0, integer_type_node); 43790075Sobrien fnname = XSTR (XEXP (DECL_RTL (thunk_fndecl), 0), 0); 438132718Skan init_function_start (thunk_fndecl); 43990075Sobrien current_function_is_thunk = 1; 44090075Sobrien assemble_start_function (thunk_fndecl, fnname); 441117395Skan 442132718Skan targetm.asm_out.output_mi_thunk (asm_out_file, thunk_fndecl, 443132718Skan fixed_offset, virtual_value, alias); 444117395Skan 44590075Sobrien assemble_end_function (thunk_fndecl, fnname); 446169689Skan init_insn_lengths (); 44790075Sobrien current_function_decl = 0; 44890075Sobrien cfun = 0; 44990075Sobrien TREE_ASM_WRITTEN (thunk_fndecl) = 1; 45090075Sobrien } 45190075Sobrien else 45296263Sobrien { 453132718Skan /* If this is a covariant thunk, or we don't have the necessary 454132718Skan code for efficient thunks, generate a thunk function that 455132718Skan just makes a call to the real function. Unfortunately, this 456132718Skan doesn't work for varargs. */ 45718334Speter 45896263Sobrien if (varargs_function_p (function)) 459169689Skan error ("generic thunk code fails for method %q#D which uses %<...%>", 46096263Sobrien function); 46118334Speter 46296263Sobrien DECL_RESULT (thunk_fndecl) = NULL_TREE; 46318334Speter 464169689Skan start_preparsed_function (thunk_fndecl, NULL_TREE, SF_PRE_PARSED); 46596263Sobrien /* We don't bother with a body block for thunks. */ 46618334Speter 467132718Skan /* There's no need to check accessibility inside the thunk body. */ 468132718Skan push_deferring_access_checks (dk_no_check); 46918334Speter 470132718Skan t = a; 471132718Skan if (this_adjusting) 472132718Skan t = thunk_adjust (t, /*this_adjusting=*/1, 473132718Skan fixed_offset, virtual_offset); 474169689Skan 47596263Sobrien /* Build up the call to the real function. */ 47696263Sobrien t = tree_cons (NULL_TREE, t, NULL_TREE); 47796263Sobrien for (a = TREE_CHAIN (a); a; a = TREE_CHAIN (a)) 47896263Sobrien t = tree_cons (NULL_TREE, a, t); 47996263Sobrien t = nreverse (t); 480132718Skan t = build_call (alias, t); 481132718Skan CALL_FROM_THUNK_P (t) = 1; 482169689Skan 48396263Sobrien if (VOID_TYPE_P (TREE_TYPE (t))) 48496263Sobrien finish_expr_stmt (t); 48596263Sobrien else 486169689Skan { 487169689Skan if (!this_adjusting) 488169689Skan { 489169689Skan tree cond = NULL_TREE; 49070635Sobrien 491169689Skan if (TREE_CODE (TREE_TYPE (t)) == POINTER_TYPE) 492169689Skan { 493169689Skan /* If the return type is a pointer, we need to 494169689Skan protect against NULL. We know there will be an 495169689Skan adjustment, because that's why we're emitting a 496169689Skan thunk. */ 497169689Skan t = save_expr (t); 498169689Skan cond = cp_convert (boolean_type_node, t); 499169689Skan } 500169689Skan 501169689Skan t = thunk_adjust (t, /*this_adjusting=*/0, 502169689Skan fixed_offset, virtual_offset); 503169689Skan if (cond) 504169689Skan t = build3 (COND_EXPR, TREE_TYPE (t), cond, t, 505169689Skan cp_convert (TREE_TYPE (t), integer_zero_node)); 506169689Skan } 507169689Skan if (IS_AGGR_TYPE (TREE_TYPE (t))) 508169689Skan t = build_cplus_new (TREE_TYPE (t), t); 509169689Skan finish_return_stmt (t); 510169689Skan } 511169689Skan 51296263Sobrien /* Since we want to emit the thunk, we explicitly mark its name as 51396263Sobrien referenced. */ 514169689Skan mark_decl_referenced (thunk_fndecl); 51560967Sobrien 51696263Sobrien /* But we don't want debugging information about it. */ 51796263Sobrien DECL_IGNORED_P (thunk_fndecl) = 1; 51860967Sobrien 519132718Skan /* Re-enable access control. */ 520132718Skan pop_deferring_access_checks (); 521132718Skan 522169689Skan thunk_fndecl = finish_function (0); 523169689Skan tree_lowering_passes (thunk_fndecl); 524169689Skan expand_body (thunk_fndecl); 52596263Sobrien } 52660967Sobrien 52790075Sobrien pop_from_top_level (); 52860967Sobrien} 52960967Sobrien 53018334Speter/* Code for synthesizing methods which have default semantics defined. */ 53118334Speter 53218334Speter/* Generate code for default X(X&) constructor. */ 53350397Sobrien 53450397Sobrienstatic void 535132718Skando_build_copy_constructor (tree fndecl) 53618334Speter{ 53790075Sobrien tree parm = FUNCTION_FIRST_USER_PARM (fndecl); 53818334Speter 53918334Speter parm = convert_from_reference (parm); 54018334Speter 54150397Sobrien if (TYPE_HAS_TRIVIAL_INIT_REF (current_class_type) 54250397Sobrien && is_empty_class (current_class_type)) 54350397Sobrien /* Don't copy the padding byte; it might not have been allocated 54450397Sobrien if *this is a base subobject. */; 54550397Sobrien else if (TYPE_HAS_TRIVIAL_INIT_REF (current_class_type)) 54618334Speter { 547169689Skan tree t = build2 (INIT_EXPR, void_type_node, current_class_ref, parm); 54890075Sobrien finish_expr_stmt (t); 54918334Speter } 55018334Speter else 55118334Speter { 55218334Speter tree fields = TYPE_FIELDS (current_class_type); 55390075Sobrien tree member_init_list = NULL_TREE; 55490075Sobrien int cvquals = cp_type_quals (TREE_TYPE (parm)); 55518334Speter int i; 556169689Skan tree binfo, base_binfo; 557169689Skan VEC(tree,gc) *vbases; 55818334Speter 55990075Sobrien /* Initialize all the base-classes with the parameter converted 56090075Sobrien to their type so that we get their copy constructor and not 56190075Sobrien another constructor that takes current_class_type. We must 56290075Sobrien deal with the binfo's directly as a direct base might be 56390075Sobrien inaccessible due to ambiguity. */ 564169689Skan for (vbases = CLASSTYPE_VBASECLASSES (current_class_type), i = 0; 565169689Skan VEC_iterate (tree, vbases, i, binfo); i++) 56690075Sobrien { 567169689Skan member_init_list 568117395Skan = tree_cons (binfo, 569117395Skan build_tree_list (NULL_TREE, 570117395Skan build_base_path (PLUS_EXPR, parm, 571117395Skan binfo, 1)), 572117395Skan member_init_list); 57390075Sobrien } 57490075Sobrien 575169689Skan for (binfo = TYPE_BINFO (current_class_type), i = 0; 576169689Skan BINFO_BASE_ITERATE (binfo, i, base_binfo); i++) 57718334Speter { 578169689Skan if (BINFO_VIRTUAL_P (base_binfo)) 579169689Skan continue; 58018334Speter 581169689Skan member_init_list 582169689Skan = tree_cons (base_binfo, 583117395Skan build_tree_list (NULL_TREE, 584117395Skan build_base_path (PLUS_EXPR, parm, 585169689Skan base_binfo, 1)), 586117395Skan member_init_list); 58752284Sobrien } 58850397Sobrien 58918334Speter for (; fields; fields = TREE_CHAIN (fields)) 59018334Speter { 591146895Skan tree init = parm; 59218334Speter tree field = fields; 59396263Sobrien tree expr_type; 59418334Speter 59518334Speter if (TREE_CODE (field) != FIELD_DECL) 59618334Speter continue; 59750397Sobrien 598146895Skan expr_type = TREE_TYPE (field); 59918334Speter if (DECL_NAME (field)) 60018334Speter { 60118334Speter if (VFIELD_NAME_P (DECL_NAME (field))) 60218334Speter continue; 60318334Speter } 604146895Skan else if (ANON_AGGR_TYPE_P (expr_type) && TYPE_FIELDS (expr_type)) 60590075Sobrien /* Just use the field; anonymous types can't have 60690075Sobrien nontrivial copy ctors or assignment ops. */; 60718334Speter else 60818334Speter continue; 60918334Speter 61096263Sobrien /* Compute the type of "init->field". If the copy-constructor 61196263Sobrien parameter is, for example, "const S&", and the type of 61296263Sobrien the field is "T", then the type will usually be "const 61396263Sobrien T". (There are no cv-qualified variants of reference 61496263Sobrien types.) */ 61596263Sobrien if (TREE_CODE (expr_type) != REFERENCE_TYPE) 616146895Skan { 617146895Skan int quals = cvquals; 618169689Skan 619146895Skan if (DECL_MUTABLE_P (field)) 620146895Skan quals &= ~TYPE_QUAL_CONST; 621146895Skan expr_type = cp_build_qualified_type (expr_type, quals); 622146895Skan } 623169689Skan 624169689Skan init = build3 (COMPONENT_REF, expr_type, init, field, NULL_TREE); 62518334Speter init = build_tree_list (NULL_TREE, init); 62618334Speter 627146895Skan member_init_list = tree_cons (field, init, member_init_list); 62818334Speter } 629117395Skan finish_mem_initializers (member_init_list); 63018334Speter } 63118334Speter} 63218334Speter 63350397Sobrienstatic void 634132718Skando_build_assign_ref (tree fndecl) 63518334Speter{ 63618334Speter tree parm = TREE_CHAIN (DECL_ARGUMENTS (fndecl)); 63790075Sobrien tree compound_stmt; 63818334Speter 639169689Skan compound_stmt = begin_compound_stmt (0); 64018334Speter parm = convert_from_reference (parm); 64118334Speter 64250397Sobrien if (TYPE_HAS_TRIVIAL_ASSIGN_REF (current_class_type) 64350397Sobrien && is_empty_class (current_class_type)) 64450397Sobrien /* Don't copy the padding byte; it might not have been allocated 64550397Sobrien if *this is a base subobject. */; 64650397Sobrien else if (TYPE_HAS_TRIVIAL_ASSIGN_REF (current_class_type)) 64718334Speter { 648169689Skan tree t = build2 (MODIFY_EXPR, void_type_node, current_class_ref, parm); 64990075Sobrien finish_expr_stmt (t); 65018334Speter } 65118334Speter else 65218334Speter { 653117395Skan tree fields; 65490075Sobrien int cvquals = cp_type_quals (TREE_TYPE (parm)); 65518334Speter int i; 656169689Skan tree binfo, base_binfo; 65718334Speter 658119256Skan /* Assign to each of the direct base classes. */ 659169689Skan for (binfo = TYPE_BINFO (current_class_type), i = 0; 660169689Skan BINFO_BASE_ITERATE (binfo, i, base_binfo); i++) 66118334Speter { 662117395Skan tree converted_parm; 66390075Sobrien 664117395Skan /* We must convert PARM directly to the base class 665117395Skan explicitly since the base class may be ambiguous. */ 666169689Skan converted_parm = build_base_path (PLUS_EXPR, parm, base_binfo, 1); 667117395Skan /* Call the base class assignment operator. */ 668169689Skan finish_expr_stmt 669169689Skan (build_special_member_call (current_class_ref, 670117395Skan ansi_assopname (NOP_EXPR), 671169689Skan build_tree_list (NULL_TREE, 672117395Skan converted_parm), 673169689Skan base_binfo, 674117395Skan LOOKUP_NORMAL | LOOKUP_NONVIRTUAL)); 67518334Speter } 676117395Skan 677117395Skan /* Assign to each of the non-static data members. */ 678169689Skan for (fields = TYPE_FIELDS (current_class_type); 679169689Skan fields; 680117395Skan fields = TREE_CHAIN (fields)) 68118334Speter { 682146895Skan tree comp = current_class_ref; 683146895Skan tree init = parm; 68418334Speter tree field = fields; 685146895Skan tree expr_type; 686146895Skan int quals; 68718334Speter 688117395Skan if (TREE_CODE (field) != FIELD_DECL || DECL_ARTIFICIAL (field)) 68918334Speter continue; 69050397Sobrien 691146895Skan expr_type = TREE_TYPE (field); 692169689Skan 693146895Skan if (CP_TYPE_CONST_P (expr_type)) 69450397Sobrien { 695169689Skan error ("non-static const member %q#D, can't use default " 696169689Skan "assignment operator", field); 69750397Sobrien continue; 69850397Sobrien } 699146895Skan else if (TREE_CODE (expr_type) == REFERENCE_TYPE) 70050397Sobrien { 701169689Skan error ("non-static reference member %q#D, can't use " 702169689Skan "default assignment operator", field); 70350397Sobrien continue; 70450397Sobrien } 70550397Sobrien 70618334Speter if (DECL_NAME (field)) 70718334Speter { 70818334Speter if (VFIELD_NAME_P (DECL_NAME (field))) 70918334Speter continue; 71018334Speter } 711169689Skan else if (ANON_AGGR_TYPE_P (expr_type) 712169689Skan && TYPE_FIELDS (expr_type) != NULL_TREE) 71390075Sobrien /* Just use the field; anonymous types can't have 71490075Sobrien nontrivial copy ctors or assignment ops. */; 71518334Speter else 71618334Speter continue; 71718334Speter 718169689Skan comp = build3 (COMPONENT_REF, expr_type, comp, field, NULL_TREE); 71918334Speter 720146895Skan /* Compute the type of init->field */ 721146895Skan quals = cvquals; 722146895Skan if (DECL_MUTABLE_P (field)) 723146895Skan quals &= ~TYPE_QUAL_CONST; 724146895Skan expr_type = cp_build_qualified_type (expr_type, quals); 725146895Skan 726169689Skan init = build3 (COMPONENT_REF, expr_type, init, field, NULL_TREE); 727169689Skan 72890075Sobrien if (DECL_NAME (field)) 729146895Skan init = build_modify_expr (comp, NOP_EXPR, init); 73090075Sobrien else 731169689Skan init = build2 (MODIFY_EXPR, TREE_TYPE (comp), comp, init); 732146895Skan finish_expr_stmt (init); 73318334Speter } 73418334Speter } 73590075Sobrien finish_return_stmt (current_class_ref); 736132718Skan finish_compound_stmt (compound_stmt); 73718334Speter} 73818334Speter 739169689Skan/* Synthesize FNDECL, a non-static member function. */ 740169689Skan 74118334Spetervoid 742132718Skansynthesize_method (tree fndecl) 74318334Speter{ 744132718Skan bool nested = (current_function_decl != NULL_TREE); 74590075Sobrien tree context = decl_function_context (fndecl); 746132718Skan bool need_body = true; 74790075Sobrien tree stmt; 748169689Skan location_t save_input_location = input_location; 749169689Skan int error_count = errorcount; 750169689Skan int warning_count = warningcount; 75118334Speter 752169689Skan /* Reset the source location, we might have been previously 753169689Skan deferred, and thus have saved where we were first needed. */ 754169689Skan DECL_SOURCE_LOCATION (fndecl) 755169689Skan = DECL_SOURCE_LOCATION (TYPE_NAME (DECL_CONTEXT (fndecl))); 75690075Sobrien 75790075Sobrien /* If we've been asked to synthesize a clone, just synthesize the 75890075Sobrien cloned function instead. Doing so will automatically fill in the 75990075Sobrien body for the clone. */ 76090075Sobrien if (DECL_CLONED_FUNCTION_P (fndecl)) 761169689Skan fndecl = DECL_CLONED_FUNCTION (fndecl); 76260967Sobrien 763132718Skan /* We may be in the middle of deferred access check. Disable 764132718Skan it now. */ 765132718Skan push_deferring_access_checks (dk_no_deferred); 766132718Skan 76750397Sobrien if (! context) 76850397Sobrien push_to_top_level (); 76950397Sobrien else if (nested) 77090075Sobrien push_function_context_to (context); 77118334Speter 772169689Skan input_location = DECL_SOURCE_LOCATION (fndecl); 77390075Sobrien 774169689Skan start_preparsed_function (fndecl, NULL_TREE, SF_DEFAULT | SF_PRE_PARSED); 77590075Sobrien stmt = begin_function_body (); 77618334Speter 77790075Sobrien if (DECL_OVERLOADED_OPERATOR_P (fndecl) == NOP_EXPR) 77818334Speter { 77990075Sobrien do_build_assign_ref (fndecl); 780132718Skan need_body = false; 78190075Sobrien } 78290075Sobrien else if (DECL_CONSTRUCTOR_P (fndecl)) 78390075Sobrien { 78490075Sobrien tree arg_chain = FUNCTION_FIRST_USER_PARMTYPE (fndecl); 78590075Sobrien if (arg_chain != void_list_node) 78618334Speter do_build_copy_constructor (fndecl); 787169689Skan else 78890075Sobrien finish_mem_initializers (NULL_TREE); 78918334Speter } 79018334Speter 79190075Sobrien /* If we haven't yet generated the body of the function, just 79290075Sobrien generate an empty compound statement. */ 79390075Sobrien if (need_body) 79490075Sobrien { 79590075Sobrien tree compound_stmt; 796169689Skan compound_stmt = begin_compound_stmt (BCS_FN_BODY); 797132718Skan finish_compound_stmt (compound_stmt); 79890075Sobrien } 79918334Speter 80090075Sobrien finish_function_body (stmt); 801132718Skan expand_or_defer_fn (finish_function (0)); 80290075Sobrien 803169689Skan input_location = save_input_location; 804169689Skan 80550397Sobrien if (! context) 80650397Sobrien pop_from_top_level (); 80750397Sobrien else if (nested) 80890075Sobrien pop_function_context_from (context); 809132718Skan 810132718Skan pop_deferring_access_checks (); 811169689Skan 812169689Skan if (error_count != errorcount || warning_count != warningcount) 813169689Skan inform ("%Hsynthesized method %qD first required here ", 814169689Skan &input_location, fndecl); 81518334Speter} 81690075Sobrien 81790075Sobrien/* Use EXTRACTOR to locate the relevant function called for each base & 81890075Sobrien class field of TYPE. CLIENT allows additional information to be passed 81996263Sobrien to EXTRACTOR. Generates the union of all exceptions generated by those 82096263Sobrien functions. Note that we haven't updated TYPE_FIELDS and such of any 82196263Sobrien variants yet, so we need to look at the main one. */ 82290075Sobrien 82390075Sobrienstatic tree 824132718Skansynthesize_exception_spec (tree type, tree (*extractor) (tree, void*), 825169689Skan void *client) 82690075Sobrien{ 82790075Sobrien tree raises = empty_except_spec; 82890075Sobrien tree fields = TYPE_FIELDS (type); 829169689Skan tree binfo, base_binfo; 830169689Skan int i; 83196263Sobrien 832169689Skan for (binfo = TYPE_BINFO (type), i = 0; 833169689Skan BINFO_BASE_ITERATE (binfo, i, base_binfo); i++) 83490075Sobrien { 835169689Skan tree fn = (*extractor) (BINFO_TYPE (base_binfo), client); 83690075Sobrien if (fn) 837169689Skan { 838169689Skan tree fn_raises = TYPE_RAISES_EXCEPTIONS (TREE_TYPE (fn)); 839169689Skan 840169689Skan raises = merge_exception_specifiers (raises, fn_raises); 841169689Skan } 84290075Sobrien } 84390075Sobrien for (; fields; fields = TREE_CHAIN (fields)) 84490075Sobrien { 84590075Sobrien tree type = TREE_TYPE (fields); 84690075Sobrien tree fn; 847169689Skan 848117395Skan if (TREE_CODE (fields) != FIELD_DECL || DECL_ARTIFICIAL (fields)) 849169689Skan continue; 85090075Sobrien while (TREE_CODE (type) == ARRAY_TYPE) 851169689Skan type = TREE_TYPE (type); 852161651Skan if (!CLASS_TYPE_P (type)) 853169689Skan continue; 854169689Skan 85590075Sobrien fn = (*extractor) (type, client); 85690075Sobrien if (fn) 857169689Skan { 858169689Skan tree fn_raises = TYPE_RAISES_EXCEPTIONS (TREE_TYPE (fn)); 859169689Skan 860169689Skan raises = merge_exception_specifiers (raises, fn_raises); 861169689Skan } 86290075Sobrien } 86390075Sobrien return raises; 86490075Sobrien} 86590075Sobrien 86690075Sobrien/* Locate the dtor of TYPE. */ 86790075Sobrien 86890075Sobrienstatic tree 869132718Skanlocate_dtor (tree type, void *client ATTRIBUTE_UNUSED) 87090075Sobrien{ 871169689Skan return CLASSTYPE_DESTRUCTORS (type); 87290075Sobrien} 87390075Sobrien 87490075Sobrien/* Locate the default ctor of TYPE. */ 87590075Sobrien 87690075Sobrienstatic tree 877132718Skanlocate_ctor (tree type, void *client ATTRIBUTE_UNUSED) 87890075Sobrien{ 87990075Sobrien tree fns; 880169689Skan 88190075Sobrien if (!TYPE_HAS_DEFAULT_CONSTRUCTOR (type)) 88290075Sobrien return NULL_TREE; 883169689Skan 884169689Skan /* Call lookup_fnfields_1 to create the constructor declarations, if 885169689Skan necessary. */ 886169689Skan if (CLASSTYPE_LAZY_DEFAULT_CTOR (type)) 887169689Skan return lazily_declare_fn (sfk_constructor, type); 888169689Skan 889169689Skan for (fns = CLASSTYPE_CONSTRUCTORS (type); fns; fns = OVL_NEXT (fns)) 89090075Sobrien { 89190075Sobrien tree fn = OVL_CURRENT (fns); 89290075Sobrien tree parms = TYPE_ARG_TYPES (TREE_TYPE (fn)); 893169689Skan 894161651Skan parms = skip_artificial_parms_for (fn, parms); 895161651Skan 896161651Skan if (sufficient_parms_p (parms)) 897169689Skan return fn; 89890075Sobrien } 899169689Skan gcc_unreachable (); 90090075Sobrien} 90190075Sobrien 90290075Sobrienstruct copy_data 90390075Sobrien{ 90490075Sobrien tree name; 90590075Sobrien int quals; 90690075Sobrien}; 90790075Sobrien 90890075Sobrien/* Locate the copy ctor or copy assignment of TYPE. CLIENT_ 90990075Sobrien points to a COPY_DATA holding the name (NULL for the ctor) 91090075Sobrien and desired qualifiers of the source operand. */ 91190075Sobrien 91290075Sobrienstatic tree 913132718Skanlocate_copy (tree type, void *client_) 91490075Sobrien{ 91590075Sobrien struct copy_data *client = (struct copy_data *)client_; 91690075Sobrien tree fns; 91790075Sobrien tree best = NULL_TREE; 918132718Skan bool excess_p = false; 919169689Skan 92090075Sobrien if (client->name) 92190075Sobrien { 922169689Skan int ix; 923169689Skan ix = lookup_fnfields_1 (type, client->name); 924169689Skan if (ix < 0) 925169689Skan return NULL_TREE; 926169689Skan fns = VEC_index (tree, CLASSTYPE_METHOD_VEC (type), ix); 92790075Sobrien } 92890075Sobrien else if (TYPE_HAS_INIT_REF (type)) 929169689Skan { 930169689Skan /* If construction of the copy constructor was postponed, create 931169689Skan it now. */ 932169689Skan if (CLASSTYPE_LAZY_COPY_CTOR (type)) 933169689Skan lazily_declare_fn (sfk_copy_constructor, type); 934169689Skan fns = CLASSTYPE_CONSTRUCTORS (type); 935169689Skan } 936169689Skan else 93790075Sobrien return NULL_TREE; 93890075Sobrien for (; fns; fns = OVL_NEXT (fns)) 93990075Sobrien { 94090075Sobrien tree fn = OVL_CURRENT (fns); 94190075Sobrien tree parms = TYPE_ARG_TYPES (TREE_TYPE (fn)); 94290075Sobrien tree src_type; 94390075Sobrien int excess; 94490075Sobrien int quals; 945169689Skan 946161651Skan parms = skip_artificial_parms_for (fn, parms); 94790075Sobrien if (!parms) 948169689Skan continue; 949132718Skan src_type = non_reference (TREE_VALUE (parms)); 950169689Skan 951169689Skan if (src_type == error_mark_node) 952169689Skan return NULL_TREE; 953169689Skan 95490075Sobrien if (!same_type_ignoring_top_level_qualifiers_p (src_type, type)) 955169689Skan continue; 95690075Sobrien if (!sufficient_parms_p (TREE_CHAIN (parms))) 957169689Skan continue; 95890075Sobrien quals = cp_type_quals (src_type); 95990075Sobrien if (client->quals & ~quals) 960169689Skan continue; 96190075Sobrien excess = quals & ~client->quals; 96290075Sobrien if (!best || (excess_p && !excess)) 963169689Skan { 964169689Skan best = fn; 965169689Skan excess_p = excess; 966169689Skan } 96790075Sobrien else 968169689Skan /* Ambiguous */ 969169689Skan return NULL_TREE; 97090075Sobrien } 97190075Sobrien return best; 97290075Sobrien} 97390075Sobrien 97490075Sobrien/* Implicitly declare the special function indicated by KIND, as a 97590075Sobrien member of TYPE. For copy constructors and assignment operators, 97690075Sobrien CONST_P indicates whether these functions should take a const 977169689Skan reference argument or a non-const reference. Returns the 978169689Skan FUNCTION_DECL for the implicitly declared function. */ 97990075Sobrien 980169689Skanstatic tree 981132718Skanimplicitly_declare_fn (special_function_kind kind, tree type, bool const_p) 98290075Sobrien{ 983169689Skan tree fn; 984169689Skan tree parameter_types = void_list_node; 985169689Skan tree return_type; 986169689Skan tree fn_type; 98790075Sobrien tree raises = empty_except_spec; 988169689Skan tree rhs_parm_type = NULL_TREE; 989169689Skan tree this_parm; 990169689Skan tree name; 991169689Skan HOST_WIDE_INT saved_processing_template_decl; 99290075Sobrien 993169689Skan /* Because we create declarations for implicitly declared functions 994169689Skan lazily, we may be creating the declaration for a member of TYPE 995169689Skan while in some completely different context. However, TYPE will 996169689Skan never be a dependent class (because we never want to do lookups 997169689Skan for implicitly defined functions in a dependent class). 998169689Skan Furthermore, we must set PROCESSING_TEMPLATE_DECL to zero here 999169689Skan because we only create clones for constructors and destructors 1000169689Skan when not in a template. */ 1001169689Skan gcc_assert (!dependent_type_p (type)); 1002169689Skan saved_processing_template_decl = processing_template_decl; 1003169689Skan processing_template_decl = 0; 1004169689Skan 1005169689Skan type = TYPE_MAIN_VARIANT (type); 1006169689Skan 1007169689Skan if (targetm.cxx.cdtor_returns_this () && !TYPE_FOR_JAVA (type)) 1008169689Skan { 1009169689Skan if (kind == sfk_destructor) 1010169689Skan /* See comment in check_special_function_return_type. */ 1011169689Skan return_type = build_pointer_type (void_type_node); 1012169689Skan else 1013169689Skan return_type = build_pointer_type (type); 1014169689Skan } 1015169689Skan else 1016169689Skan return_type = void_type_node; 1017169689Skan 101890075Sobrien switch (kind) 101990075Sobrien { 102090075Sobrien case sfk_destructor: 102190075Sobrien /* Destructor. */ 1022169689Skan name = constructor_name (type); 102390075Sobrien raises = synthesize_exception_spec (type, &locate_dtor, 0); 102490075Sobrien break; 102590075Sobrien 102690075Sobrien case sfk_constructor: 102790075Sobrien /* Default constructor. */ 1028169689Skan name = constructor_name (type); 102990075Sobrien raises = synthesize_exception_spec (type, &locate_ctor, 0); 103090075Sobrien break; 103190075Sobrien 103290075Sobrien case sfk_copy_constructor: 103390075Sobrien case sfk_assignment_operator: 103490075Sobrien { 103590075Sobrien struct copy_data data; 1036169689Skan 103790075Sobrien data.name = NULL; 103890075Sobrien data.quals = 0; 103990075Sobrien if (kind == sfk_assignment_operator) 1040169689Skan { 1041169689Skan return_type = build_reference_type (type); 1042169689Skan name = ansi_assopname (NOP_EXPR); 1043169689Skan data.name = name; 1044169689Skan } 1045169689Skan else 1046169689Skan name = constructor_name (type); 104790075Sobrien 104890075Sobrien if (const_p) 1049169689Skan { 1050169689Skan data.quals = TYPE_QUAL_CONST; 1051169689Skan rhs_parm_type = build_qualified_type (type, TYPE_QUAL_CONST); 1052169689Skan } 1053169689Skan else 1054169689Skan rhs_parm_type = type; 1055169689Skan rhs_parm_type = build_reference_type (rhs_parm_type); 1056169689Skan parameter_types = tree_cons (NULL_TREE, rhs_parm_type, parameter_types); 105790075Sobrien raises = synthesize_exception_spec (type, &locate_copy, &data); 105890075Sobrien break; 105990075Sobrien } 106090075Sobrien default: 1061169689Skan gcc_unreachable (); 106290075Sobrien } 106390075Sobrien 1064169689Skan /* Create the function. */ 1065169689Skan fn_type = build_method_type_directly (type, return_type, parameter_types); 1066169689Skan if (raises) 1067169689Skan fn_type = build_exception_variant (fn_type, raises); 1068169689Skan fn = build_lang_decl (FUNCTION_DECL, name, fn_type); 1069169689Skan DECL_SOURCE_LOCATION (fn) = DECL_SOURCE_LOCATION (TYPE_NAME (type)); 1070169689Skan if (kind == sfk_constructor || kind == sfk_copy_constructor) 1071169689Skan DECL_CONSTRUCTOR_P (fn) = 1; 1072169689Skan else if (kind == sfk_destructor) 1073169689Skan DECL_DESTRUCTOR_P (fn) = 1; 1074169689Skan else 1075169689Skan { 1076169689Skan DECL_ASSIGNMENT_OPERATOR_P (fn) = 1; 1077169689Skan SET_OVERLOADED_OPERATOR_CODE (fn, NOP_EXPR); 1078169689Skan } 1079169689Skan /* Create the explicit arguments. */ 1080169689Skan if (rhs_parm_type) 1081169689Skan { 1082169689Skan /* Note that this parameter is *not* marked DECL_ARTIFICIAL; we 1083169689Skan want its type to be included in the mangled function 1084169689Skan name. */ 1085169689Skan DECL_ARGUMENTS (fn) = cp_build_parm_decl (NULL_TREE, rhs_parm_type); 1086169689Skan TREE_READONLY (DECL_ARGUMENTS (fn)) = 1; 1087169689Skan } 1088169689Skan /* Add the "this" parameter. */ 1089169689Skan this_parm = build_this_parm (fn_type, TYPE_UNQUALIFIED); 1090169689Skan TREE_CHAIN (this_parm) = DECL_ARGUMENTS (fn); 1091169689Skan DECL_ARGUMENTS (fn) = this_parm; 109290075Sobrien 1093169689Skan grokclassfn (type, fn, kind == sfk_destructor ? DTOR_FLAG : NO_SPECIAL); 1094169689Skan set_linkage_according_to_type (type, fn); 1095169689Skan rest_of_decl_compilation (fn, toplevel_bindings_p (), at_eof); 1096169689Skan DECL_IN_AGGR_P (fn) = 1; 109790075Sobrien DECL_ARTIFICIAL (fn) = 1; 109890075Sobrien DECL_NOT_REALLY_EXTERN (fn) = 1; 109990075Sobrien DECL_DECLARED_INLINE_P (fn) = 1; 110090075Sobrien DECL_INLINE (fn) = 1; 1101169689Skan gcc_assert (!TREE_USED (fn)); 1102169689Skan 1103169689Skan /* Restore PROCESSING_TEMPLATE_DECL. */ 1104169689Skan processing_template_decl = saved_processing_template_decl; 1105169689Skan 110690075Sobrien return fn; 110790075Sobrien} 110890075Sobrien 1109169689Skan/* Add an implicit declaration to TYPE for the kind of function 1110169689Skan indicated by SFK. Return the FUNCTION_DECL for the new implicit 1111169689Skan declaration. */ 1112169689Skan 1113169689Skantree 1114169689Skanlazily_declare_fn (special_function_kind sfk, tree type) 1115169689Skan{ 1116169689Skan tree fn; 1117169689Skan bool const_p; 1118169689Skan 1119169689Skan /* Figure out whether or not the argument has a const reference 1120169689Skan type. */ 1121169689Skan if (sfk == sfk_copy_constructor) 1122169689Skan const_p = TYPE_HAS_CONST_INIT_REF (type); 1123169689Skan else if (sfk == sfk_assignment_operator) 1124169689Skan const_p = TYPE_HAS_CONST_ASSIGN_REF (type); 1125169689Skan else 1126169689Skan /* In this case, CONST_P will be ignored. */ 1127169689Skan const_p = false; 1128169689Skan /* Declare the function. */ 1129169689Skan fn = implicitly_declare_fn (sfk, type, const_p); 1130169689Skan /* A destructor may be virtual. */ 1131169689Skan if (sfk == sfk_destructor) 1132169689Skan check_for_override (fn, type); 1133169689Skan /* Add it to CLASSTYPE_METHOD_VEC. */ 1134169689Skan add_method (type, fn, NULL_TREE); 1135169689Skan /* Add it to TYPE_METHODS. */ 1136169689Skan if (sfk == sfk_destructor 1137169689Skan && DECL_VIRTUAL_P (fn) 1138169689Skan && abi_version_at_least (2)) 1139169689Skan /* The ABI requires that a virtual destructor go at the end of the 1140169689Skan vtable. */ 1141169689Skan TYPE_METHODS (type) = chainon (TYPE_METHODS (type), fn); 1142169689Skan else 1143169689Skan { 1144169689Skan /* G++ 3.2 put the implicit destructor at the *beginning* of the 1145169689Skan TYPE_METHODS list, which cause the destructor to be emitted 1146169689Skan in an incorrect location in the vtable. */ 1147169689Skan if (warn_abi && DECL_VIRTUAL_P (fn)) 1148169689Skan warning (OPT_Wabi, "vtable layout for class %qT may not be ABI-compliant" 1149169689Skan "and may change in a future version of GCC due to " 1150169689Skan "implicit virtual destructor", 1151169689Skan type); 1152169689Skan TREE_CHAIN (fn) = TYPE_METHODS (type); 1153169689Skan TYPE_METHODS (type) = fn; 1154169689Skan } 1155169689Skan maybe_add_class_template_decl_list (type, fn, /*friend_p=*/0); 1156169689Skan if (sfk == sfk_assignment_operator) 1157169689Skan CLASSTYPE_LAZY_ASSIGNMENT_OP (type) = 0; 1158169689Skan else 1159169689Skan { 1160169689Skan /* Remember that the function has been created. */ 1161169689Skan if (sfk == sfk_constructor) 1162169689Skan CLASSTYPE_LAZY_DEFAULT_CTOR (type) = 0; 1163169689Skan else if (sfk == sfk_copy_constructor) 1164169689Skan CLASSTYPE_LAZY_COPY_CTOR (type) = 0; 1165169689Skan else if (sfk == sfk_destructor) 1166169689Skan CLASSTYPE_LAZY_DESTRUCTOR (type) = 0; 1167169689Skan /* Create appropriate clones. */ 1168169689Skan clone_function_decl (fn, /*update_method_vec=*/true); 1169169689Skan } 1170169689Skan 1171169689Skan return fn; 1172169689Skan} 1173169689Skan 117490075Sobrien/* Given a FUNCTION_DECL FN and a chain LIST, skip as many elements of LIST 117590075Sobrien as there are artificial parms in FN. */ 117690075Sobrien 117790075Sobrientree 1178132718Skanskip_artificial_parms_for (tree fn, tree list) 117990075Sobrien{ 118090075Sobrien if (DECL_NONSTATIC_MEMBER_FUNCTION_P (fn)) 118190075Sobrien list = TREE_CHAIN (list); 118290075Sobrien else 118390075Sobrien return list; 118490075Sobrien 118590075Sobrien if (DECL_HAS_IN_CHARGE_PARM_P (fn)) 118690075Sobrien list = TREE_CHAIN (list); 118790075Sobrien if (DECL_HAS_VTT_PARM_P (fn)) 118890075Sobrien list = TREE_CHAIN (list); 118990075Sobrien return list; 119090075Sobrien} 1191132718Skan 1192132718Skan#include "gt-cp-method.h" 1193