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 410169689Skan /* Set up cloned argument trees for the thunk. */ 411169689Skan t = NULL_TREE; 412169689Skan for (a = DECL_ARGUMENTS (function); a; a = TREE_CHAIN (a)) 413169689Skan { 414169689Skan tree x = copy_node (a); 415169689Skan TREE_CHAIN (x) = t; 416169689Skan DECL_CONTEXT (x) = thunk_fndecl; 417169689Skan SET_DECL_RTL (x, NULL_RTX); 418169689Skan DECL_HAS_VALUE_EXPR_P (x) = 0; 419169689Skan t = x; 420169689Skan } 421169689Skan a = nreverse (t); 422169689Skan DECL_ARGUMENTS (thunk_fndecl) = a; 423169689Skan 424132718Skan if (this_adjusting 425132718Skan && targetm.asm_out.can_output_mi_thunk (thunk_fndecl, fixed_offset, 426132718Skan virtual_value, alias)) 42790075Sobrien { 42890075Sobrien const char *fnname; 429260139Spfg tree fn_block; 430260139Spfg 43190075Sobrien current_function_decl = thunk_fndecl; 43290075Sobrien DECL_RESULT (thunk_fndecl) 43390075Sobrien = build_decl (RESULT_DECL, 0, integer_type_node); 43490075Sobrien fnname = XSTR (XEXP (DECL_RTL (thunk_fndecl), 0), 0); 435260139Spfg /* The back-end expects DECL_INITIAL to contain a BLOCK, so we 436260139Spfg create one. */ 437260139Spfg fn_block = make_node (BLOCK); 438260139Spfg BLOCK_VARS (fn_block) = a; 439260139Spfg DECL_INITIAL (thunk_fndecl) = fn_block; 440132718Skan init_function_start (thunk_fndecl); 44190075Sobrien current_function_is_thunk = 1; 44290075Sobrien assemble_start_function (thunk_fndecl, fnname); 443117395Skan 444132718Skan targetm.asm_out.output_mi_thunk (asm_out_file, thunk_fndecl, 445132718Skan fixed_offset, virtual_value, alias); 446117395Skan 44790075Sobrien assemble_end_function (thunk_fndecl, fnname); 448169689Skan init_insn_lengths (); 44990075Sobrien current_function_decl = 0; 45090075Sobrien cfun = 0; 45190075Sobrien TREE_ASM_WRITTEN (thunk_fndecl) = 1; 45290075Sobrien } 45390075Sobrien else 45496263Sobrien { 455132718Skan /* If this is a covariant thunk, or we don't have the necessary 456132718Skan code for efficient thunks, generate a thunk function that 457132718Skan just makes a call to the real function. Unfortunately, this 458132718Skan doesn't work for varargs. */ 45918334Speter 46096263Sobrien if (varargs_function_p (function)) 461169689Skan error ("generic thunk code fails for method %q#D which uses %<...%>", 46296263Sobrien function); 46318334Speter 46496263Sobrien DECL_RESULT (thunk_fndecl) = NULL_TREE; 46518334Speter 466169689Skan start_preparsed_function (thunk_fndecl, NULL_TREE, SF_PRE_PARSED); 46796263Sobrien /* We don't bother with a body block for thunks. */ 46818334Speter 469132718Skan /* There's no need to check accessibility inside the thunk body. */ 470132718Skan push_deferring_access_checks (dk_no_check); 47118334Speter 472132718Skan t = a; 473132718Skan if (this_adjusting) 474132718Skan t = thunk_adjust (t, /*this_adjusting=*/1, 475132718Skan fixed_offset, virtual_offset); 476169689Skan 47796263Sobrien /* Build up the call to the real function. */ 47896263Sobrien t = tree_cons (NULL_TREE, t, NULL_TREE); 47996263Sobrien for (a = TREE_CHAIN (a); a; a = TREE_CHAIN (a)) 48096263Sobrien t = tree_cons (NULL_TREE, a, t); 48196263Sobrien t = nreverse (t); 482132718Skan t = build_call (alias, t); 483132718Skan CALL_FROM_THUNK_P (t) = 1; 484169689Skan 48596263Sobrien if (VOID_TYPE_P (TREE_TYPE (t))) 48696263Sobrien finish_expr_stmt (t); 48796263Sobrien else 488169689Skan { 489169689Skan if (!this_adjusting) 490169689Skan { 491169689Skan tree cond = NULL_TREE; 49270635Sobrien 493169689Skan if (TREE_CODE (TREE_TYPE (t)) == POINTER_TYPE) 494169689Skan { 495169689Skan /* If the return type is a pointer, we need to 496169689Skan protect against NULL. We know there will be an 497169689Skan adjustment, because that's why we're emitting a 498169689Skan thunk. */ 499169689Skan t = save_expr (t); 500169689Skan cond = cp_convert (boolean_type_node, t); 501169689Skan } 502169689Skan 503169689Skan t = thunk_adjust (t, /*this_adjusting=*/0, 504169689Skan fixed_offset, virtual_offset); 505169689Skan if (cond) 506169689Skan t = build3 (COND_EXPR, TREE_TYPE (t), cond, t, 507169689Skan cp_convert (TREE_TYPE (t), integer_zero_node)); 508169689Skan } 509169689Skan if (IS_AGGR_TYPE (TREE_TYPE (t))) 510169689Skan t = build_cplus_new (TREE_TYPE (t), t); 511169689Skan finish_return_stmt (t); 512169689Skan } 513169689Skan 51496263Sobrien /* Since we want to emit the thunk, we explicitly mark its name as 51596263Sobrien referenced. */ 516169689Skan mark_decl_referenced (thunk_fndecl); 51760967Sobrien 51896263Sobrien /* But we don't want debugging information about it. */ 51996263Sobrien DECL_IGNORED_P (thunk_fndecl) = 1; 52060967Sobrien 521132718Skan /* Re-enable access control. */ 522132718Skan pop_deferring_access_checks (); 523132718Skan 524169689Skan thunk_fndecl = finish_function (0); 525169689Skan tree_lowering_passes (thunk_fndecl); 526169689Skan expand_body (thunk_fndecl); 52796263Sobrien } 52860967Sobrien 52990075Sobrien pop_from_top_level (); 53060967Sobrien} 53160967Sobrien 53218334Speter/* Code for synthesizing methods which have default semantics defined. */ 53318334Speter 53418334Speter/* Generate code for default X(X&) constructor. */ 53550397Sobrien 53650397Sobrienstatic void 537132718Skando_build_copy_constructor (tree fndecl) 53818334Speter{ 53990075Sobrien tree parm = FUNCTION_FIRST_USER_PARM (fndecl); 54018334Speter 54118334Speter parm = convert_from_reference (parm); 54218334Speter 54350397Sobrien if (TYPE_HAS_TRIVIAL_INIT_REF (current_class_type) 54450397Sobrien && is_empty_class (current_class_type)) 54550397Sobrien /* Don't copy the padding byte; it might not have been allocated 54650397Sobrien if *this is a base subobject. */; 54750397Sobrien else if (TYPE_HAS_TRIVIAL_INIT_REF (current_class_type)) 54818334Speter { 549169689Skan tree t = build2 (INIT_EXPR, void_type_node, current_class_ref, parm); 55090075Sobrien finish_expr_stmt (t); 55118334Speter } 55218334Speter else 55318334Speter { 55418334Speter tree fields = TYPE_FIELDS (current_class_type); 55590075Sobrien tree member_init_list = NULL_TREE; 55690075Sobrien int cvquals = cp_type_quals (TREE_TYPE (parm)); 55718334Speter int i; 558169689Skan tree binfo, base_binfo; 559169689Skan VEC(tree,gc) *vbases; 56018334Speter 56190075Sobrien /* Initialize all the base-classes with the parameter converted 56290075Sobrien to their type so that we get their copy constructor and not 56390075Sobrien another constructor that takes current_class_type. We must 56490075Sobrien deal with the binfo's directly as a direct base might be 56590075Sobrien inaccessible due to ambiguity. */ 566169689Skan for (vbases = CLASSTYPE_VBASECLASSES (current_class_type), i = 0; 567169689Skan VEC_iterate (tree, vbases, i, binfo); i++) 56890075Sobrien { 569169689Skan member_init_list 570117395Skan = tree_cons (binfo, 571117395Skan build_tree_list (NULL_TREE, 572117395Skan build_base_path (PLUS_EXPR, parm, 573117395Skan binfo, 1)), 574117395Skan member_init_list); 57590075Sobrien } 57690075Sobrien 577169689Skan for (binfo = TYPE_BINFO (current_class_type), i = 0; 578169689Skan BINFO_BASE_ITERATE (binfo, i, base_binfo); i++) 57918334Speter { 580169689Skan if (BINFO_VIRTUAL_P (base_binfo)) 581169689Skan continue; 58218334Speter 583169689Skan member_init_list 584169689Skan = tree_cons (base_binfo, 585117395Skan build_tree_list (NULL_TREE, 586117395Skan build_base_path (PLUS_EXPR, parm, 587169689Skan base_binfo, 1)), 588117395Skan member_init_list); 58952284Sobrien } 59050397Sobrien 59118334Speter for (; fields; fields = TREE_CHAIN (fields)) 59218334Speter { 593146895Skan tree init = parm; 59418334Speter tree field = fields; 59596263Sobrien tree expr_type; 59618334Speter 59718334Speter if (TREE_CODE (field) != FIELD_DECL) 59818334Speter continue; 59950397Sobrien 600146895Skan expr_type = TREE_TYPE (field); 60118334Speter if (DECL_NAME (field)) 60218334Speter { 60318334Speter if (VFIELD_NAME_P (DECL_NAME (field))) 60418334Speter continue; 60518334Speter } 606146895Skan else if (ANON_AGGR_TYPE_P (expr_type) && TYPE_FIELDS (expr_type)) 60790075Sobrien /* Just use the field; anonymous types can't have 60890075Sobrien nontrivial copy ctors or assignment ops. */; 60918334Speter else 61018334Speter continue; 61118334Speter 61296263Sobrien /* Compute the type of "init->field". If the copy-constructor 61396263Sobrien parameter is, for example, "const S&", and the type of 61496263Sobrien the field is "T", then the type will usually be "const 61596263Sobrien T". (There are no cv-qualified variants of reference 61696263Sobrien types.) */ 61796263Sobrien if (TREE_CODE (expr_type) != REFERENCE_TYPE) 618146895Skan { 619146895Skan int quals = cvquals; 620169689Skan 621146895Skan if (DECL_MUTABLE_P (field)) 622146895Skan quals &= ~TYPE_QUAL_CONST; 623146895Skan expr_type = cp_build_qualified_type (expr_type, quals); 624146895Skan } 625169689Skan 626169689Skan init = build3 (COMPONENT_REF, expr_type, init, field, NULL_TREE); 62718334Speter init = build_tree_list (NULL_TREE, init); 62818334Speter 629146895Skan member_init_list = tree_cons (field, init, member_init_list); 63018334Speter } 631117395Skan finish_mem_initializers (member_init_list); 63218334Speter } 63318334Speter} 63418334Speter 63550397Sobrienstatic void 636132718Skando_build_assign_ref (tree fndecl) 63718334Speter{ 63818334Speter tree parm = TREE_CHAIN (DECL_ARGUMENTS (fndecl)); 63990075Sobrien tree compound_stmt; 64018334Speter 641169689Skan compound_stmt = begin_compound_stmt (0); 64218334Speter parm = convert_from_reference (parm); 64318334Speter 64450397Sobrien if (TYPE_HAS_TRIVIAL_ASSIGN_REF (current_class_type) 64550397Sobrien && is_empty_class (current_class_type)) 64650397Sobrien /* Don't copy the padding byte; it might not have been allocated 64750397Sobrien if *this is a base subobject. */; 64850397Sobrien else if (TYPE_HAS_TRIVIAL_ASSIGN_REF (current_class_type)) 64918334Speter { 650169689Skan tree t = build2 (MODIFY_EXPR, void_type_node, current_class_ref, parm); 65190075Sobrien finish_expr_stmt (t); 65218334Speter } 65318334Speter else 65418334Speter { 655117395Skan tree fields; 65690075Sobrien int cvquals = cp_type_quals (TREE_TYPE (parm)); 65718334Speter int i; 658169689Skan tree binfo, base_binfo; 65918334Speter 660119256Skan /* Assign to each of the direct base classes. */ 661169689Skan for (binfo = TYPE_BINFO (current_class_type), i = 0; 662169689Skan BINFO_BASE_ITERATE (binfo, i, base_binfo); i++) 66318334Speter { 664117395Skan tree converted_parm; 66590075Sobrien 666117395Skan /* We must convert PARM directly to the base class 667117395Skan explicitly since the base class may be ambiguous. */ 668169689Skan converted_parm = build_base_path (PLUS_EXPR, parm, base_binfo, 1); 669117395Skan /* Call the base class assignment operator. */ 670169689Skan finish_expr_stmt 671169689Skan (build_special_member_call (current_class_ref, 672117395Skan ansi_assopname (NOP_EXPR), 673169689Skan build_tree_list (NULL_TREE, 674117395Skan converted_parm), 675169689Skan base_binfo, 676117395Skan LOOKUP_NORMAL | LOOKUP_NONVIRTUAL)); 67718334Speter } 678117395Skan 679117395Skan /* Assign to each of the non-static data members. */ 680169689Skan for (fields = TYPE_FIELDS (current_class_type); 681169689Skan fields; 682117395Skan fields = TREE_CHAIN (fields)) 68318334Speter { 684146895Skan tree comp = current_class_ref; 685146895Skan tree init = parm; 68618334Speter tree field = fields; 687146895Skan tree expr_type; 688146895Skan int quals; 68918334Speter 690117395Skan if (TREE_CODE (field) != FIELD_DECL || DECL_ARTIFICIAL (field)) 69118334Speter continue; 69250397Sobrien 693146895Skan expr_type = TREE_TYPE (field); 694169689Skan 695146895Skan if (CP_TYPE_CONST_P (expr_type)) 69650397Sobrien { 697169689Skan error ("non-static const member %q#D, can't use default " 698169689Skan "assignment operator", field); 69950397Sobrien continue; 70050397Sobrien } 701146895Skan else if (TREE_CODE (expr_type) == REFERENCE_TYPE) 70250397Sobrien { 703169689Skan error ("non-static reference member %q#D, can't use " 704169689Skan "default assignment operator", field); 70550397Sobrien continue; 70650397Sobrien } 70750397Sobrien 70818334Speter if (DECL_NAME (field)) 70918334Speter { 71018334Speter if (VFIELD_NAME_P (DECL_NAME (field))) 71118334Speter continue; 71218334Speter } 713169689Skan else if (ANON_AGGR_TYPE_P (expr_type) 714169689Skan && TYPE_FIELDS (expr_type) != NULL_TREE) 71590075Sobrien /* Just use the field; anonymous types can't have 71690075Sobrien nontrivial copy ctors or assignment ops. */; 71718334Speter else 71818334Speter continue; 71918334Speter 720169689Skan comp = build3 (COMPONENT_REF, expr_type, comp, field, NULL_TREE); 72118334Speter 722146895Skan /* Compute the type of init->field */ 723146895Skan quals = cvquals; 724146895Skan if (DECL_MUTABLE_P (field)) 725146895Skan quals &= ~TYPE_QUAL_CONST; 726146895Skan expr_type = cp_build_qualified_type (expr_type, quals); 727146895Skan 728169689Skan init = build3 (COMPONENT_REF, expr_type, init, field, NULL_TREE); 729169689Skan 73090075Sobrien if (DECL_NAME (field)) 731146895Skan init = build_modify_expr (comp, NOP_EXPR, init); 73290075Sobrien else 733169689Skan init = build2 (MODIFY_EXPR, TREE_TYPE (comp), comp, init); 734146895Skan finish_expr_stmt (init); 73518334Speter } 73618334Speter } 73790075Sobrien finish_return_stmt (current_class_ref); 738132718Skan finish_compound_stmt (compound_stmt); 73918334Speter} 74018334Speter 741169689Skan/* Synthesize FNDECL, a non-static member function. */ 742169689Skan 74318334Spetervoid 744132718Skansynthesize_method (tree fndecl) 74518334Speter{ 746132718Skan bool nested = (current_function_decl != NULL_TREE); 74790075Sobrien tree context = decl_function_context (fndecl); 748132718Skan bool need_body = true; 74990075Sobrien tree stmt; 750169689Skan location_t save_input_location = input_location; 751169689Skan int error_count = errorcount; 752169689Skan int warning_count = warningcount; 75318334Speter 754169689Skan /* Reset the source location, we might have been previously 755169689Skan deferred, and thus have saved where we were first needed. */ 756169689Skan DECL_SOURCE_LOCATION (fndecl) 757169689Skan = DECL_SOURCE_LOCATION (TYPE_NAME (DECL_CONTEXT (fndecl))); 75890075Sobrien 75990075Sobrien /* If we've been asked to synthesize a clone, just synthesize the 76090075Sobrien cloned function instead. Doing so will automatically fill in the 76190075Sobrien body for the clone. */ 76290075Sobrien if (DECL_CLONED_FUNCTION_P (fndecl)) 763169689Skan fndecl = DECL_CLONED_FUNCTION (fndecl); 76460967Sobrien 765132718Skan /* We may be in the middle of deferred access check. Disable 766132718Skan it now. */ 767132718Skan push_deferring_access_checks (dk_no_deferred); 768132718Skan 76950397Sobrien if (! context) 77050397Sobrien push_to_top_level (); 77150397Sobrien else if (nested) 77290075Sobrien push_function_context_to (context); 77318334Speter 774169689Skan input_location = DECL_SOURCE_LOCATION (fndecl); 77590075Sobrien 776169689Skan start_preparsed_function (fndecl, NULL_TREE, SF_DEFAULT | SF_PRE_PARSED); 77790075Sobrien stmt = begin_function_body (); 77818334Speter 77990075Sobrien if (DECL_OVERLOADED_OPERATOR_P (fndecl) == NOP_EXPR) 78018334Speter { 78190075Sobrien do_build_assign_ref (fndecl); 782132718Skan need_body = false; 78390075Sobrien } 78490075Sobrien else if (DECL_CONSTRUCTOR_P (fndecl)) 78590075Sobrien { 78690075Sobrien tree arg_chain = FUNCTION_FIRST_USER_PARMTYPE (fndecl); 78790075Sobrien if (arg_chain != void_list_node) 78818334Speter do_build_copy_constructor (fndecl); 789169689Skan else 79090075Sobrien finish_mem_initializers (NULL_TREE); 79118334Speter } 79218334Speter 79390075Sobrien /* If we haven't yet generated the body of the function, just 79490075Sobrien generate an empty compound statement. */ 79590075Sobrien if (need_body) 79690075Sobrien { 79790075Sobrien tree compound_stmt; 798169689Skan compound_stmt = begin_compound_stmt (BCS_FN_BODY); 799132718Skan finish_compound_stmt (compound_stmt); 80090075Sobrien } 80118334Speter 80290075Sobrien finish_function_body (stmt); 803132718Skan expand_or_defer_fn (finish_function (0)); 80490075Sobrien 805169689Skan input_location = save_input_location; 806169689Skan 80750397Sobrien if (! context) 80850397Sobrien pop_from_top_level (); 80950397Sobrien else if (nested) 81090075Sobrien pop_function_context_from (context); 811132718Skan 812132718Skan pop_deferring_access_checks (); 813169689Skan 814169689Skan if (error_count != errorcount || warning_count != warningcount) 815169689Skan inform ("%Hsynthesized method %qD first required here ", 816169689Skan &input_location, fndecl); 81718334Speter} 81890075Sobrien 81990075Sobrien/* Use EXTRACTOR to locate the relevant function called for each base & 82090075Sobrien class field of TYPE. CLIENT allows additional information to be passed 82196263Sobrien to EXTRACTOR. Generates the union of all exceptions generated by those 82296263Sobrien functions. Note that we haven't updated TYPE_FIELDS and such of any 82396263Sobrien variants yet, so we need to look at the main one. */ 82490075Sobrien 82590075Sobrienstatic tree 826132718Skansynthesize_exception_spec (tree type, tree (*extractor) (tree, void*), 827169689Skan void *client) 82890075Sobrien{ 82990075Sobrien tree raises = empty_except_spec; 83090075Sobrien tree fields = TYPE_FIELDS (type); 831169689Skan tree binfo, base_binfo; 832169689Skan int i; 83396263Sobrien 834169689Skan for (binfo = TYPE_BINFO (type), i = 0; 835169689Skan BINFO_BASE_ITERATE (binfo, i, base_binfo); i++) 83690075Sobrien { 837169689Skan tree fn = (*extractor) (BINFO_TYPE (base_binfo), client); 83890075Sobrien if (fn) 839169689Skan { 840169689Skan tree fn_raises = TYPE_RAISES_EXCEPTIONS (TREE_TYPE (fn)); 841169689Skan 842169689Skan raises = merge_exception_specifiers (raises, fn_raises); 843169689Skan } 84490075Sobrien } 84590075Sobrien for (; fields; fields = TREE_CHAIN (fields)) 84690075Sobrien { 84790075Sobrien tree type = TREE_TYPE (fields); 84890075Sobrien tree fn; 849169689Skan 850117395Skan if (TREE_CODE (fields) != FIELD_DECL || DECL_ARTIFICIAL (fields)) 851169689Skan continue; 85290075Sobrien while (TREE_CODE (type) == ARRAY_TYPE) 853169689Skan type = TREE_TYPE (type); 854161651Skan if (!CLASS_TYPE_P (type)) 855169689Skan continue; 856169689Skan 85790075Sobrien fn = (*extractor) (type, client); 85890075Sobrien if (fn) 859169689Skan { 860169689Skan tree fn_raises = TYPE_RAISES_EXCEPTIONS (TREE_TYPE (fn)); 861169689Skan 862169689Skan raises = merge_exception_specifiers (raises, fn_raises); 863169689Skan } 86490075Sobrien } 86590075Sobrien return raises; 86690075Sobrien} 86790075Sobrien 86890075Sobrien/* Locate the dtor of TYPE. */ 86990075Sobrien 87090075Sobrienstatic tree 871132718Skanlocate_dtor (tree type, void *client ATTRIBUTE_UNUSED) 87290075Sobrien{ 873169689Skan return CLASSTYPE_DESTRUCTORS (type); 87490075Sobrien} 87590075Sobrien 87690075Sobrien/* Locate the default ctor of TYPE. */ 87790075Sobrien 87890075Sobrienstatic tree 879132718Skanlocate_ctor (tree type, void *client ATTRIBUTE_UNUSED) 88090075Sobrien{ 88190075Sobrien tree fns; 882169689Skan 88390075Sobrien if (!TYPE_HAS_DEFAULT_CONSTRUCTOR (type)) 88490075Sobrien return NULL_TREE; 885169689Skan 886169689Skan /* Call lookup_fnfields_1 to create the constructor declarations, if 887169689Skan necessary. */ 888169689Skan if (CLASSTYPE_LAZY_DEFAULT_CTOR (type)) 889169689Skan return lazily_declare_fn (sfk_constructor, type); 890169689Skan 891169689Skan for (fns = CLASSTYPE_CONSTRUCTORS (type); fns; fns = OVL_NEXT (fns)) 89290075Sobrien { 89390075Sobrien tree fn = OVL_CURRENT (fns); 89490075Sobrien tree parms = TYPE_ARG_TYPES (TREE_TYPE (fn)); 895169689Skan 896161651Skan parms = skip_artificial_parms_for (fn, parms); 897161651Skan 898161651Skan if (sufficient_parms_p (parms)) 899169689Skan return fn; 90090075Sobrien } 901169689Skan gcc_unreachable (); 90290075Sobrien} 90390075Sobrien 90490075Sobrienstruct copy_data 90590075Sobrien{ 90690075Sobrien tree name; 90790075Sobrien int quals; 90890075Sobrien}; 90990075Sobrien 91090075Sobrien/* Locate the copy ctor or copy assignment of TYPE. CLIENT_ 91190075Sobrien points to a COPY_DATA holding the name (NULL for the ctor) 91290075Sobrien and desired qualifiers of the source operand. */ 91390075Sobrien 91490075Sobrienstatic tree 915132718Skanlocate_copy (tree type, void *client_) 91690075Sobrien{ 91790075Sobrien struct copy_data *client = (struct copy_data *)client_; 91890075Sobrien tree fns; 91990075Sobrien tree best = NULL_TREE; 920132718Skan bool excess_p = false; 921169689Skan 92290075Sobrien if (client->name) 92390075Sobrien { 924169689Skan int ix; 925169689Skan ix = lookup_fnfields_1 (type, client->name); 926169689Skan if (ix < 0) 927169689Skan return NULL_TREE; 928169689Skan fns = VEC_index (tree, CLASSTYPE_METHOD_VEC (type), ix); 92990075Sobrien } 93090075Sobrien else if (TYPE_HAS_INIT_REF (type)) 931169689Skan { 932169689Skan /* If construction of the copy constructor was postponed, create 933169689Skan it now. */ 934169689Skan if (CLASSTYPE_LAZY_COPY_CTOR (type)) 935169689Skan lazily_declare_fn (sfk_copy_constructor, type); 936169689Skan fns = CLASSTYPE_CONSTRUCTORS (type); 937169689Skan } 938169689Skan else 93990075Sobrien return NULL_TREE; 94090075Sobrien for (; fns; fns = OVL_NEXT (fns)) 94190075Sobrien { 94290075Sobrien tree fn = OVL_CURRENT (fns); 94390075Sobrien tree parms = TYPE_ARG_TYPES (TREE_TYPE (fn)); 94490075Sobrien tree src_type; 94590075Sobrien int excess; 94690075Sobrien int quals; 947169689Skan 948161651Skan parms = skip_artificial_parms_for (fn, parms); 94990075Sobrien if (!parms) 950169689Skan continue; 951132718Skan src_type = non_reference (TREE_VALUE (parms)); 952169689Skan 953169689Skan if (src_type == error_mark_node) 954169689Skan return NULL_TREE; 955169689Skan 95690075Sobrien if (!same_type_ignoring_top_level_qualifiers_p (src_type, type)) 957169689Skan continue; 95890075Sobrien if (!sufficient_parms_p (TREE_CHAIN (parms))) 959169689Skan continue; 96090075Sobrien quals = cp_type_quals (src_type); 96190075Sobrien if (client->quals & ~quals) 962169689Skan continue; 96390075Sobrien excess = quals & ~client->quals; 96490075Sobrien if (!best || (excess_p && !excess)) 965169689Skan { 966169689Skan best = fn; 967169689Skan excess_p = excess; 968169689Skan } 96990075Sobrien else 970169689Skan /* Ambiguous */ 971169689Skan return NULL_TREE; 97290075Sobrien } 97390075Sobrien return best; 97490075Sobrien} 97590075Sobrien 97690075Sobrien/* Implicitly declare the special function indicated by KIND, as a 97790075Sobrien member of TYPE. For copy constructors and assignment operators, 97890075Sobrien CONST_P indicates whether these functions should take a const 979169689Skan reference argument or a non-const reference. Returns the 980169689Skan FUNCTION_DECL for the implicitly declared function. */ 98190075Sobrien 982169689Skanstatic tree 983132718Skanimplicitly_declare_fn (special_function_kind kind, tree type, bool const_p) 98490075Sobrien{ 985169689Skan tree fn; 986169689Skan tree parameter_types = void_list_node; 987169689Skan tree return_type; 988169689Skan tree fn_type; 98990075Sobrien tree raises = empty_except_spec; 990169689Skan tree rhs_parm_type = NULL_TREE; 991169689Skan tree this_parm; 992169689Skan tree name; 993169689Skan HOST_WIDE_INT saved_processing_template_decl; 99490075Sobrien 995169689Skan /* Because we create declarations for implicitly declared functions 996169689Skan lazily, we may be creating the declaration for a member of TYPE 997169689Skan while in some completely different context. However, TYPE will 998169689Skan never be a dependent class (because we never want to do lookups 999169689Skan for implicitly defined functions in a dependent class). 1000169689Skan Furthermore, we must set PROCESSING_TEMPLATE_DECL to zero here 1001169689Skan because we only create clones for constructors and destructors 1002169689Skan when not in a template. */ 1003169689Skan gcc_assert (!dependent_type_p (type)); 1004169689Skan saved_processing_template_decl = processing_template_decl; 1005169689Skan processing_template_decl = 0; 1006169689Skan 1007169689Skan type = TYPE_MAIN_VARIANT (type); 1008169689Skan 1009169689Skan if (targetm.cxx.cdtor_returns_this () && !TYPE_FOR_JAVA (type)) 1010169689Skan { 1011169689Skan if (kind == sfk_destructor) 1012169689Skan /* See comment in check_special_function_return_type. */ 1013169689Skan return_type = build_pointer_type (void_type_node); 1014169689Skan else 1015169689Skan return_type = build_pointer_type (type); 1016169689Skan } 1017169689Skan else 1018169689Skan return_type = void_type_node; 1019169689Skan 102090075Sobrien switch (kind) 102190075Sobrien { 102290075Sobrien case sfk_destructor: 102390075Sobrien /* Destructor. */ 1024169689Skan name = constructor_name (type); 102590075Sobrien raises = synthesize_exception_spec (type, &locate_dtor, 0); 102690075Sobrien break; 102790075Sobrien 102890075Sobrien case sfk_constructor: 102990075Sobrien /* Default constructor. */ 1030169689Skan name = constructor_name (type); 103190075Sobrien raises = synthesize_exception_spec (type, &locate_ctor, 0); 103290075Sobrien break; 103390075Sobrien 103490075Sobrien case sfk_copy_constructor: 103590075Sobrien case sfk_assignment_operator: 103690075Sobrien { 103790075Sobrien struct copy_data data; 1038169689Skan 103990075Sobrien data.name = NULL; 104090075Sobrien data.quals = 0; 104190075Sobrien if (kind == sfk_assignment_operator) 1042169689Skan { 1043169689Skan return_type = build_reference_type (type); 1044169689Skan name = ansi_assopname (NOP_EXPR); 1045169689Skan data.name = name; 1046169689Skan } 1047169689Skan else 1048169689Skan name = constructor_name (type); 104990075Sobrien 105090075Sobrien if (const_p) 1051169689Skan { 1052169689Skan data.quals = TYPE_QUAL_CONST; 1053169689Skan rhs_parm_type = build_qualified_type (type, TYPE_QUAL_CONST); 1054169689Skan } 1055169689Skan else 1056169689Skan rhs_parm_type = type; 1057169689Skan rhs_parm_type = build_reference_type (rhs_parm_type); 1058169689Skan parameter_types = tree_cons (NULL_TREE, rhs_parm_type, parameter_types); 105990075Sobrien raises = synthesize_exception_spec (type, &locate_copy, &data); 106090075Sobrien break; 106190075Sobrien } 106290075Sobrien default: 1063169689Skan gcc_unreachable (); 106490075Sobrien } 106590075Sobrien 1066169689Skan /* Create the function. */ 1067169689Skan fn_type = build_method_type_directly (type, return_type, parameter_types); 1068169689Skan if (raises) 1069169689Skan fn_type = build_exception_variant (fn_type, raises); 1070169689Skan fn = build_lang_decl (FUNCTION_DECL, name, fn_type); 1071169689Skan DECL_SOURCE_LOCATION (fn) = DECL_SOURCE_LOCATION (TYPE_NAME (type)); 1072169689Skan if (kind == sfk_constructor || kind == sfk_copy_constructor) 1073169689Skan DECL_CONSTRUCTOR_P (fn) = 1; 1074169689Skan else if (kind == sfk_destructor) 1075169689Skan DECL_DESTRUCTOR_P (fn) = 1; 1076169689Skan else 1077169689Skan { 1078169689Skan DECL_ASSIGNMENT_OPERATOR_P (fn) = 1; 1079169689Skan SET_OVERLOADED_OPERATOR_CODE (fn, NOP_EXPR); 1080169689Skan } 1081169689Skan /* Create the explicit arguments. */ 1082169689Skan if (rhs_parm_type) 1083169689Skan { 1084169689Skan /* Note that this parameter is *not* marked DECL_ARTIFICIAL; we 1085169689Skan want its type to be included in the mangled function 1086169689Skan name. */ 1087169689Skan DECL_ARGUMENTS (fn) = cp_build_parm_decl (NULL_TREE, rhs_parm_type); 1088169689Skan TREE_READONLY (DECL_ARGUMENTS (fn)) = 1; 1089169689Skan } 1090169689Skan /* Add the "this" parameter. */ 1091169689Skan this_parm = build_this_parm (fn_type, TYPE_UNQUALIFIED); 1092169689Skan TREE_CHAIN (this_parm) = DECL_ARGUMENTS (fn); 1093169689Skan DECL_ARGUMENTS (fn) = this_parm; 109490075Sobrien 1095169689Skan grokclassfn (type, fn, kind == sfk_destructor ? DTOR_FLAG : NO_SPECIAL); 1096169689Skan set_linkage_according_to_type (type, fn); 1097169689Skan rest_of_decl_compilation (fn, toplevel_bindings_p (), at_eof); 1098169689Skan DECL_IN_AGGR_P (fn) = 1; 109990075Sobrien DECL_ARTIFICIAL (fn) = 1; 110090075Sobrien DECL_NOT_REALLY_EXTERN (fn) = 1; 110190075Sobrien DECL_DECLARED_INLINE_P (fn) = 1; 110290075Sobrien DECL_INLINE (fn) = 1; 1103169689Skan gcc_assert (!TREE_USED (fn)); 1104169689Skan 1105169689Skan /* Restore PROCESSING_TEMPLATE_DECL. */ 1106169689Skan processing_template_decl = saved_processing_template_decl; 1107169689Skan 110890075Sobrien return fn; 110990075Sobrien} 111090075Sobrien 1111169689Skan/* Add an implicit declaration to TYPE for the kind of function 1112169689Skan indicated by SFK. Return the FUNCTION_DECL for the new implicit 1113169689Skan declaration. */ 1114169689Skan 1115169689Skantree 1116169689Skanlazily_declare_fn (special_function_kind sfk, tree type) 1117169689Skan{ 1118169689Skan tree fn; 1119169689Skan bool const_p; 1120169689Skan 1121169689Skan /* Figure out whether or not the argument has a const reference 1122169689Skan type. */ 1123169689Skan if (sfk == sfk_copy_constructor) 1124169689Skan const_p = TYPE_HAS_CONST_INIT_REF (type); 1125169689Skan else if (sfk == sfk_assignment_operator) 1126169689Skan const_p = TYPE_HAS_CONST_ASSIGN_REF (type); 1127169689Skan else 1128169689Skan /* In this case, CONST_P will be ignored. */ 1129169689Skan const_p = false; 1130169689Skan /* Declare the function. */ 1131169689Skan fn = implicitly_declare_fn (sfk, type, const_p); 1132169689Skan /* A destructor may be virtual. */ 1133169689Skan if (sfk == sfk_destructor) 1134169689Skan check_for_override (fn, type); 1135169689Skan /* Add it to CLASSTYPE_METHOD_VEC. */ 1136169689Skan add_method (type, fn, NULL_TREE); 1137169689Skan /* Add it to TYPE_METHODS. */ 1138169689Skan if (sfk == sfk_destructor 1139169689Skan && DECL_VIRTUAL_P (fn) 1140169689Skan && abi_version_at_least (2)) 1141169689Skan /* The ABI requires that a virtual destructor go at the end of the 1142169689Skan vtable. */ 1143169689Skan TYPE_METHODS (type) = chainon (TYPE_METHODS (type), fn); 1144169689Skan else 1145169689Skan { 1146169689Skan /* G++ 3.2 put the implicit destructor at the *beginning* of the 1147169689Skan TYPE_METHODS list, which cause the destructor to be emitted 1148169689Skan in an incorrect location in the vtable. */ 1149169689Skan if (warn_abi && DECL_VIRTUAL_P (fn)) 1150169689Skan warning (OPT_Wabi, "vtable layout for class %qT may not be ABI-compliant" 1151169689Skan "and may change in a future version of GCC due to " 1152169689Skan "implicit virtual destructor", 1153169689Skan type); 1154169689Skan TREE_CHAIN (fn) = TYPE_METHODS (type); 1155169689Skan TYPE_METHODS (type) = fn; 1156169689Skan } 1157169689Skan maybe_add_class_template_decl_list (type, fn, /*friend_p=*/0); 1158169689Skan if (sfk == sfk_assignment_operator) 1159169689Skan CLASSTYPE_LAZY_ASSIGNMENT_OP (type) = 0; 1160169689Skan else 1161169689Skan { 1162169689Skan /* Remember that the function has been created. */ 1163169689Skan if (sfk == sfk_constructor) 1164169689Skan CLASSTYPE_LAZY_DEFAULT_CTOR (type) = 0; 1165169689Skan else if (sfk == sfk_copy_constructor) 1166169689Skan CLASSTYPE_LAZY_COPY_CTOR (type) = 0; 1167169689Skan else if (sfk == sfk_destructor) 1168169689Skan CLASSTYPE_LAZY_DESTRUCTOR (type) = 0; 1169169689Skan /* Create appropriate clones. */ 1170169689Skan clone_function_decl (fn, /*update_method_vec=*/true); 1171169689Skan } 1172169689Skan 1173169689Skan return fn; 1174169689Skan} 1175169689Skan 117690075Sobrien/* Given a FUNCTION_DECL FN and a chain LIST, skip as many elements of LIST 117790075Sobrien as there are artificial parms in FN. */ 117890075Sobrien 117990075Sobrientree 1180132718Skanskip_artificial_parms_for (tree fn, tree list) 118190075Sobrien{ 118290075Sobrien if (DECL_NONSTATIC_MEMBER_FUNCTION_P (fn)) 118390075Sobrien list = TREE_CHAIN (list); 118490075Sobrien else 118590075Sobrien return list; 118690075Sobrien 118790075Sobrien if (DECL_HAS_IN_CHARGE_PARM_P (fn)) 118890075Sobrien list = TREE_CHAIN (list); 118990075Sobrien if (DECL_HAS_VTT_PARM_P (fn)) 119090075Sobrien list = TREE_CHAIN (list); 119190075Sobrien return list; 119290075Sobrien} 1193132718Skan 1194132718Skan#include "gt-cp-method.h" 1195