--- gcc/cp/method.c 2018/04/24 18:20:21 1.1.1.1 +++ gcc/cp/method.c 2018/04/24 18:27:06 1.1.1.2 @@ -1,6 +1,6 @@ /* Handle the hair of processing (but not expanding) inline functions. Also manage function and variable name overloading. - Copyright (C) 1987, 1989, 1992, 1993 Free Software Foundation, Inc. + Copyright (C) 1987, 89, 92, 93, 94, 1995 Free Software Foundation, Inc. Contributed by Michael Tiemann (tiemann@cygnus.com) This file is part of GNU CC. @@ -17,7 +17,8 @@ GNU General Public License for more deta You should have received a copy of the GNU General Public License along with GNU CC; see the file COPYING. If not, write to -the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ #ifndef PARM_CAN_BE_ARRAY_TYPE @@ -59,6 +60,7 @@ static char *scratch_firstobj; IDENTIFIER_LENGTH (ID))) # define OB_PUTCP(S) (obstack_grow (&scratch_obstack, (S), strlen (S))) # define OB_FINISH() (obstack_1grow (&scratch_obstack, '\0')) +# define OB_LAST() (obstack_next_free (&scratch_obstack)[-1]) #ifdef NO_AUTO_OVERLOAD int is_overloaded (); @@ -163,14 +165,6 @@ report_type_mismatch (cp, parmtypes, nam cp->function); return; - case -3: - if (TYPE_READONLY (TREE_TYPE (TREE_VALUE (parmtypes)))) - cp_error ("call to const %s `%#D' with non-const object", name_kind, - cp->function); - else - cp_error ("call to non-const %s `%#D' with const object", name_kind, - cp->function); - return; case -2: cp_error ("too few arguments for %s `%#D'", name_kind, cp->function); return; @@ -178,14 +172,15 @@ report_type_mismatch (cp, parmtypes, nam cp_error ("too many arguments for %s `%#D'", name_kind, cp->function); return; case 0: - if (TREE_CODE (TREE_TYPE (cp->function)) == METHOD_TYPE) - { - /* Happens when we have an ambiguous base class. */ - my_friendly_assert (get_binfo (DECL_CLASS_CONTEXT (cp->function), - TREE_TYPE (TREE_TYPE (TREE_VALUE (parmtypes))), 1) == error_mark_node, - 241); - return; - } + if (TREE_CODE (TREE_TYPE (cp->function)) != METHOD_TYPE) + break; + case -3: + /* Happens when the implicit object parameter is rejected. */ + my_friendly_assert (! TYPE_READONLY (TREE_TYPE (TREE_VALUE (parmtypes))), + 241); + cp_error ("call to non-const %s `%#D' with const object", + name_kind, cp->function); + return; } ttf = TYPE_ARG_TYPES (TREE_TYPE (cp->function)); @@ -313,23 +308,69 @@ flush_repeats (type) OB_PUTC ('_'); } -static int numeric_outputed_need_bar; +static int numeric_output_need_bar; static void build_overload_identifier (); static void -build_overload_nested_name (context) - tree context; +build_overload_nested_name (decl) + tree decl; { - /* We use DECL_NAME here, because pushtag now sets the DECL_ASSEMBLER_NAME. */ - tree name = DECL_NAME (context); - if (DECL_CONTEXT (context)) + if (DECL_CONTEXT (decl)) { - context = DECL_CONTEXT (context); + tree context = DECL_CONTEXT (decl); if (TREE_CODE_CLASS (TREE_CODE (context)) == 't') - context = TYPE_NAME (context); + context = TYPE_MAIN_DECL (context); build_overload_nested_name (context); } - build_overload_identifier (name); + + if (TREE_CODE (decl) == FUNCTION_DECL) + { + tree name = DECL_ASSEMBLER_NAME (decl); + char *label; + extern int var_labelno; + + ASM_FORMAT_PRIVATE_NAME (label, IDENTIFIER_POINTER (name), var_labelno); + var_labelno++; + + if (numeric_output_need_bar) + { + OB_PUTC ('_'); + numeric_output_need_bar = 0; + } + icat (strlen (label)); + OB_PUTCP (label); + } + else /* TYPE_DECL */ + { + tree name = DECL_NAME (decl); + build_overload_identifier (name); + } +} + +/* Encoding for an INTEGER_CST value. */ +static void +build_overload_int (value) + tree value; +{ + my_friendly_assert (TREE_CODE (value) == INTEGER_CST, 243); + if (TYPE_PRECISION (value) == 2 * HOST_BITS_PER_WIDE_INT) + { + if (tree_int_cst_lt (value, integer_zero_node)) + { + OB_PUTC ('m'); + value = build_int_2 (~ TREE_INT_CST_LOW (value), + - TREE_INT_CST_HIGH (value)); + } + if (TREE_INT_CST_HIGH (value) + != (TREE_INT_CST_LOW (value) >> (HOST_BITS_PER_WIDE_INT - 1))) + { + /* need to print a DImode value in decimal */ + sorry ("conversion of long long as PT parameter"); + } + /* else fall through to print in smaller mode */ + } + /* Wordsize or smaller */ + icat (TREE_INT_CST_LOW (value)); } static void @@ -341,35 +382,37 @@ build_overload_value (type, value) value = TREE_OPERAND (value, 0); my_friendly_assert (TREE_CODE (type) == PARM_DECL, 242); type = TREE_TYPE (type); + + if (numeric_output_need_bar) + { + OB_PUTC ('_'); + numeric_output_need_bar = 0; + } + + if (TREE_CODE (type) == POINTER_TYPE + && TREE_CODE (TREE_TYPE (type)) == OFFSET_TYPE) + { + /* Handle a pointer to data member as a template instantiation + parameter, boy, what fun! */ + type = integer_type_node; + if (TREE_CODE (value) != INTEGER_CST) + { + sorry ("unknown pointer to member constant"); + return; + } + } + + if (TYPE_PTRMEMFUNC_P (type)) + type = TYPE_PTRMEMFUNC_FN_TYPE (type); + switch (TREE_CODE (type)) { case INTEGER_TYPE: case ENUMERAL_TYPE: - { - my_friendly_assert (TREE_CODE (value) == INTEGER_CST, 243); - if (TYPE_PRECISION (value) == 2 * HOST_BITS_PER_WIDE_INT) - { - if (tree_int_cst_lt (value, integer_zero_node)) - { - OB_PUTC ('m'); - value = build_int_2 (~ TREE_INT_CST_LOW (value), - - TREE_INT_CST_HIGH (value)); - } - if (TREE_INT_CST_HIGH (value) - != (TREE_INT_CST_LOW (value) >> (HOST_BITS_PER_WIDE_INT - 1))) - { - /* need to print a DImode value in decimal */ - sorry ("conversion of long long as PT parameter"); - } - /* else fall through to print in smaller mode */ - } - /* Wordsize or smaller */ - icat (TREE_INT_CST_LOW (value)); - return; - } case BOOLEAN_TYPE: { - icat (TREE_INT_CST_LOW (value)); + build_overload_int (value); + numeric_output_need_bar = 1; return; } #ifndef REAL_IS_NOT_DOUBLE @@ -416,10 +459,58 @@ build_overload_value (type, value) } } OB_PUTCP (digit_buffer); + numeric_output_need_bar = 1; return; } #endif case POINTER_TYPE: + if (TREE_CODE (TREE_TYPE (type)) == METHOD_TYPE + && TREE_CODE (value) != ADDR_EXPR) + { + if (TREE_CODE (value) == CONSTRUCTOR) + { + /* This is dangerous code, crack built up pointer to members. */ + tree args = CONSTRUCTOR_ELTS (value); + tree a1 = TREE_VALUE (args); + tree a2 = TREE_VALUE (TREE_CHAIN (args)); + tree a3 = CONSTRUCTOR_ELTS (TREE_VALUE (TREE_CHAIN (TREE_CHAIN (args)))); + a3 = TREE_VALUE (a3); + STRIP_NOPS (a3); + if (TREE_CODE (a1) == INTEGER_CST + && TREE_CODE (a2) == INTEGER_CST) + { + build_overload_int (a1); + OB_PUTC ('_'); + build_overload_int (a2); + OB_PUTC ('_'); + if (TREE_CODE (a3) == ADDR_EXPR) + { + a3 = TREE_OPERAND (a3, 0); + if (TREE_CODE (a3) == FUNCTION_DECL) + { + numeric_output_need_bar = 0; + build_overload_identifier (DECL_ASSEMBLER_NAME (a3)); + return; + } + } + else if (TREE_CODE (a3) == INTEGER_CST) + { + OB_PUTC ('i'); + build_overload_int (a3); + numeric_output_need_bar = 1; + return; + } + } + } + sorry ("template instantiation with pointer to method that is too complex"); + return; + } + if (TREE_CODE (value) == INTEGER_CST) + { + build_overload_int (value); + numeric_output_need_bar = 1; + return; + } value = TREE_OPERAND (value, 0); if (TREE_CODE (value) == VAR_DECL) { @@ -474,19 +565,20 @@ build_overload_identifier (name) } else { + parm = tsubst (parm, &TREE_VEC_ELT (arglist, 0), + TREE_VEC_LENGTH (arglist), NULL_TREE); /* It's a PARM_DECL. */ build_overload_name (TREE_TYPE (parm), 0, 0); build_overload_value (parm, arg); - numeric_outputed_need_bar = 1; } } } else { - if (numeric_outputed_need_bar) + if (numeric_output_need_bar) { OB_PUTC ('_'); - numeric_outputed_need_bar = 0; + numeric_output_need_bar = 0; } icat (IDENTIFIER_LENGTH (name)); OB_PUTID (name); @@ -514,7 +606,7 @@ build_overload_name (parmtypes, begin, e tree parmtype; if (begin) OB_INIT (); - numeric_outputed_need_bar = 0; + numeric_output_need_bar = 0; if ((just_one = (TREE_CODE (parmtypes) != TREE_LIST))) { @@ -528,44 +620,30 @@ build_overload_name (parmtypes, begin, e only_one: - if (! nofold) + if (! nofold && ! just_one) { - if (! just_one) - /* Every argument gets counted. */ - typevec[maxtype++] = parmtype; + /* Every argument gets counted. */ + typevec[maxtype++] = parmtype; - if (TREE_USED (parmtype)) + if (TREE_USED (parmtype) && parmtype == typevec[maxtype-2]) { - if (! just_one && parmtype == typevec[maxtype-2]) - nrepeats++; - else - { - if (nrepeats) - flush_repeats (parmtype); - if (! just_one && TREE_CHAIN (parmtypes) - && parmtype == TREE_VALUE (TREE_CHAIN (parmtypes))) - nrepeats++; - else - { - int tindex = 0; - - while (typevec[tindex] != parmtype) - tindex++; - OB_PUTC ('T'); - icat (tindex); - if (tindex > 9) - OB_PUTC ('_'); - } - } + nrepeats++; goto next; } + if (nrepeats) flush_repeats (typevec[maxtype-2]); - if (! just_one - /* Only cache types which take more than one character. */ - && (parmtype != TYPE_MAIN_VARIANT (parmtype) - || (TREE_CODE (parmtype) != INTEGER_TYPE - && TREE_CODE (parmtype) != REAL_TYPE))) + + if (TREE_USED (parmtype)) + { + flush_repeats (parmtype); + goto next; + } + + /* Only cache types which take more than one character. */ + if (parmtype != TYPE_MAIN_VARIANT (parmtype) + || (TREE_CODE (parmtype) != INTEGER_TYPE + && TREE_CODE (parmtype) != REAL_TYPE)) TREE_USED (parmtype) = 1; } @@ -762,6 +840,13 @@ build_overload_name (parmtypes, begin, e if (TREE_CODE (name) == TYPE_DECL) { tree context = name; + + /* If DECL_ASSEMBLER_NAME has been set properly, use it. */ + if (DECL_ASSEMBLER_NAME (context) != DECL_NAME (context)) + { + OB_PUTID (DECL_ASSEMBLER_NAME (context)); + break; + } while (DECL_CONTEXT (context)) { i += 1; @@ -780,8 +865,8 @@ build_overload_name (parmtypes, begin, e icat (i); if (i > 9) OB_PUTC ('_'); - numeric_outputed_need_bar = 0; - build_overload_nested_name (TYPE_NAME (parmtype)); + numeric_output_need_bar = 0; + build_overload_nested_name (TYPE_MAIN_DECL (parmtype)); } else build_overload_identifier (name); @@ -1179,10 +1264,11 @@ build_opfncall (code, flags, xarg1, xarg fnname, tree_cons (NULL_TREE, xarg1, build_tree_list (NULL_TREE, xarg2)), NULL_TREE, flags); - /* This happens when the user mis-declares `operator delete'. - Should now be impossible. */ +#if 0 + /* This can happen when operator delete is protected. */ my_friendly_assert (rval != error_mark_node, 250); TREE_TYPE (rval) = void_type_node; +#endif return rval; } break; @@ -1294,7 +1380,7 @@ build_opfncall (code, flags, xarg1, xarg /* Look for an `operator++ (int)'. If they didn't have one, then we fall back to the old way of doing things. */ - for (t = TREE_VALUE (fields1); t ; t = TREE_CHAIN (t)) + for (t = TREE_VALUE (fields1); t ; t = DECL_CHAIN (t)) { t2 = TYPE_ARG_TYPES (TREE_TYPE (t)); if (TREE_CHAIN (t2) != NULL_TREE @@ -1310,12 +1396,9 @@ build_opfncall (code, flags, xarg1, xarg char *op = POSTINCREMENT_EXPR ? "++" : "--"; /* There's probably a LOT of code in the world that - relies upon this old behavior. So we'll only give this - warning when we've been given -pedantic. A few - releases after 2.4, we'll convert this to be a pedwarn - or something else more appropriate. */ - if (pedantic) - warning ("no `operator%s (int)' declared for postfix `%s'", + relies upon this old behavior. */ + if (! flag_traditional) + pedwarn ("no `operator%s (int)' declared for postfix `%s', using prefix operator instead", op, op); xarg2 = NULL_TREE; binary_is_unary = 1; @@ -1454,23 +1537,7 @@ hack_identifier (value, name, yychar) return error_mark_node; } TREE_USED (current_class_decl) = 1; - if (yychar == '(') - if (! ((TYPE_LANG_SPECIFIC (type) - && TYPE_OVERLOADS_CALL_EXPR (type)) - || (TREE_CODE (type) == REFERENCE_TYPE - && TYPE_LANG_SPECIFIC (TREE_TYPE (type)) - && TYPE_OVERLOADS_CALL_EXPR (TREE_TYPE (type)))) - && TREE_CODE (type) != FUNCTION_TYPE - && TREE_CODE (type) != METHOD_TYPE - && !TYPE_PTRMEMFUNC_P (type) - && (TREE_CODE (type) != POINTER_TYPE - || (TREE_CODE (TREE_TYPE (type)) != FUNCTION_TYPE - && TREE_CODE (TREE_TYPE (type)) != METHOD_TYPE))) - { - error ("component `%s' is not a method", - IDENTIFIER_POINTER (name)); - return error_mark_node; - } + /* Mark so that if we are in a constructor, and then find that this field was initialized by a base initializer, we can emit an error message. */ @@ -1555,8 +1622,7 @@ hack_identifier (value, name, yychar) my_friendly_assert (TREE_CODE (value) == VAR_DECL || TREE_CODE (value) == PARM_DECL || TREE_CODE (value) == RESULT_DECL, 252); - if (DECL_REFERENCE_SLOT (value)) - return DECL_REFERENCE_SLOT (value); + return convert_from_reference (value); } return value; } @@ -1721,7 +1787,10 @@ make_thunk (function, delta) if (TREE_CODE (func_decl) != FUNCTION_DECL) abort (); func_name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (func_decl)); - sprintf (buffer, "__thunk_%d_%s", -delta, func_name); + if (delta<=0) + sprintf (buffer, "__thunk_%d_%s", -delta, func_name); + else + sprintf (buffer, "__thunk_n%d_%s", delta, func_name); thunk_id = get_identifier (buffer); thunk = IDENTIFIER_GLOBAL_VALUE (thunk_id); if (thunk && TREE_CODE (thunk) != THUNK_DECL) @@ -1733,7 +1802,9 @@ make_thunk (function, delta) { thunk = build_decl (THUNK_DECL, thunk_id, TREE_TYPE (func_decl)); DECL_RESULT (thunk) - = build_decl (RESULT_DECL, NULL_TREE, TREE_TYPE (vtable_entry_type)); + = build_decl (RESULT_DECL, 0, TYPE_MAIN_VARIANT (TREE_TYPE (vtable_entry_type))); + TREE_READONLY (thunk) = TYPE_READONLY (TREE_TYPE (vtable_entry_type)); + TREE_THIS_VOLATILE (thunk) = TYPE_VOLATILE (TREE_TYPE (vtable_entry_type)); make_function_rtl (thunk); DECL_INITIAL (thunk) = function; THUNK_DELTA (thunk) = delta; @@ -1891,7 +1962,7 @@ emit_thunk (thunk_fndecl) emit_insn (gen_rtx (USE, VOIDmode, need_use[--need_use_count])); expand_end_bindings (NULL, 1, 0); - poplevel (0, 0, 0); + poplevel (0, 0, 1); /* From now on, allocate rtl in current_obstack, not in saveable_obstack. Note that that may have been done above, in save_for_inline_copying. @@ -1906,6 +1977,10 @@ emit_thunk (thunk_fndecl) unshare_all_rtl (insns); + /* Instantiate all virtual registers. */ + + instantiate_virtual_regs (current_function_decl, get_insns ()); + /* We are no longer anticipating cse in this function, at least. */ cse_not_expected = 1; @@ -1971,16 +2046,6 @@ emit_thunk (thunk_fndecl) /* Code for synthesizing methods which have default semantics defined. */ -void -build_default_constructor (fndecl) - tree fndecl; -{ - start_function (NULL_TREE, fndecl, NULL_TREE, 1); - store_parm_decls (); - setup_vtbl_ptr (); - finish_function (lineno, 0); -} - /* For the anonymous union in TYPE, return the member that is at least as large as the rest of the members, so we can copy it. */ static tree @@ -1990,7 +2055,7 @@ largest_union_member (type) tree f, type_size = TYPE_SIZE (type); for (f = TYPE_FIELDS (type); f; f = TREE_CHAIN (f)) - if (simple_cst_equal (DECL_SIZE (f), type_size)) + if (simple_cst_equal (DECL_SIZE (f), type_size) == 1) return f; /* We should always find one. */ @@ -2000,14 +2065,12 @@ largest_union_member (type) /* Generate code for default X(X&) constructor. */ void -build_copy_constructor (fndecl) +do_build_copy_constructor (fndecl) tree fndecl; { tree parm = TREE_CHAIN (DECL_ARGUMENTS (fndecl)); tree t; - start_function (NULL_TREE, fndecl, NULL_TREE, 1); - store_parm_decls (); clear_last_expr (); push_momentary (); @@ -2015,7 +2078,7 @@ build_copy_constructor (fndecl) parm = TREE_CHAIN (parm); parm = convert_from_reference (parm); - if (! TYPE_HAS_COMPLEX_INIT_REF (current_class_type)) + if (TYPE_HAS_TRIVIAL_INIT_REF (current_class_type)) { t = build (INIT_EXPR, void_type_node, C_C_D, parm); TREE_SIDE_EFFECTS (t) = 1; @@ -2032,7 +2095,9 @@ build_copy_constructor (fndecl) t = TREE_CHAIN (t)) { tree basetype = BINFO_TYPE (t); - tree p = convert (build_reference_type (basetype), parm); + tree p = convert_to_reference + (build_reference_type (basetype), parm, + CONV_IMPLICIT|CONV_CONST, LOOKUP_COMPLAIN, NULL_TREE); p = convert_from_reference (p); current_base_init_list = tree_cons (TYPE_NESTED_NAME (basetype), p, current_base_init_list); @@ -2042,10 +2107,12 @@ build_copy_constructor (fndecl) { tree p, basetype = TREE_VEC_ELT (binfos, i); if (TREE_VIA_VIRTUAL (basetype)) - continue; + continue; basetype = BINFO_TYPE (basetype); - p = convert (build_reference_type (basetype), parm); + p = convert_to_reference + (build_reference_type (basetype), parm, + CONV_IMPLICIT|CONV_CONST, LOOKUP_COMPLAIN, NULL_TREE); p = convert_from_reference (p); current_base_init_list = tree_cons (TYPE_NESTED_NAME (basetype), p, current_base_init_list); @@ -2053,54 +2120,55 @@ build_copy_constructor (fndecl) for (; fields; fields = TREE_CHAIN (fields)) { tree name, init, t; - if (TREE_CODE (fields) != FIELD_DECL) + tree field = fields; + + if (TREE_CODE (field) != FIELD_DECL) continue; - if (DECL_NAME (fields)) + if (DECL_NAME (field)) { - if (VFIELD_NAME_P (DECL_NAME (fields))) + if (VFIELD_NAME_P (DECL_NAME (field))) continue; - if (VBASE_NAME_P (DECL_NAME (fields))) + if (VBASE_NAME_P (DECL_NAME (field))) continue; /* True for duplicate members. */ - if (IDENTIFIER_CLASS_VALUE (DECL_NAME (fields)) != fields) + if (IDENTIFIER_CLASS_VALUE (DECL_NAME (field)) != field) continue; } - else if ((t = TREE_TYPE (fields)) != NULL_TREE + else if ((t = TREE_TYPE (field)) != NULL_TREE && TREE_CODE (t) == UNION_TYPE && ANON_AGGRNAME_P (TYPE_IDENTIFIER (t)) && TYPE_FIELDS (t) != NULL_TREE) - fields = largest_union_member (t); + field = largest_union_member (t); else continue; - init = build (COMPONENT_REF, TREE_TYPE (fields), parm, fields); + init = build (COMPONENT_REF, TREE_TYPE (field), parm, field); init = build_tree_list (NULL_TREE, init); current_member_init_list - = tree_cons (DECL_NAME (fields), init, current_member_init_list); + = tree_cons (DECL_NAME (field), init, current_member_init_list); } current_member_init_list = nreverse (current_member_init_list); + current_base_init_list = nreverse (current_base_init_list); setup_vtbl_ptr (); } pop_momentary (); - finish_function (lineno, 0); } void -build_assign_ref (fndecl) +do_build_assign_ref (fndecl) tree fndecl; { tree parm = TREE_CHAIN (DECL_ARGUMENTS (fndecl)); - start_function (NULL_TREE, fndecl, NULL_TREE, 1); - store_parm_decls (); + clear_last_expr (); push_momentary (); parm = convert_from_reference (parm); - if (! TYPE_HAS_COMPLEX_ASSIGN_REF (current_class_type)) + if (TYPE_HAS_TRIVIAL_ASSIGN_REF (current_class_type)) { tree t = build (MODIFY_EXPR, void_type_node, C_C_D, parm); TREE_SIDE_EFFECTS (t) = 1; @@ -2118,7 +2186,9 @@ build_assign_ref (fndecl) tree basetype = BINFO_TYPE (TREE_VEC_ELT (binfos, i)); if (TYPE_HAS_ASSIGN_REF (basetype)) { - tree p = convert (build_reference_type (basetype), parm); + tree p = convert_to_reference + (build_reference_type (basetype), parm, + CONV_IMPLICIT|CONV_CONST, LOOKUP_COMPLAIN, NULL_TREE); p = convert_from_reference (p); p = build_member_call (TYPE_NESTED_NAME (basetype), ansi_opname [MODIFY_EXPR], @@ -2129,43 +2199,89 @@ build_assign_ref (fndecl) for (; fields; fields = TREE_CHAIN (fields)) { tree comp, init, t; - if (TREE_CODE (fields) != FIELD_DECL) + tree field = fields; + + if (TREE_CODE (field) != FIELD_DECL) continue; - if (DECL_NAME (fields)) + if (DECL_NAME (field)) { - if (VFIELD_NAME_P (DECL_NAME (fields))) + if (VFIELD_NAME_P (DECL_NAME (field))) continue; - if (VBASE_NAME_P (DECL_NAME (fields))) + if (VBASE_NAME_P (DECL_NAME (field))) continue; /* True for duplicate members. */ - if (IDENTIFIER_CLASS_VALUE (DECL_NAME (fields)) != fields) + if (IDENTIFIER_CLASS_VALUE (DECL_NAME (field)) != field) continue; } - else if ((t = TREE_TYPE (fields)) != NULL_TREE + else if ((t = TREE_TYPE (field)) != NULL_TREE && TREE_CODE (t) == UNION_TYPE && ANON_AGGRNAME_P (TYPE_IDENTIFIER (t)) && TYPE_FIELDS (t) != NULL_TREE) - fields = largest_union_member (t); + field = largest_union_member (t); else continue; - comp = build (COMPONENT_REF, TREE_TYPE (fields), C_C_D, fields); - init = build (COMPONENT_REF, TREE_TYPE (fields), parm, fields); + comp = build (COMPONENT_REF, TREE_TYPE (field), C_C_D, field); + init = build (COMPONENT_REF, TREE_TYPE (field), parm, field); expand_expr_stmt (build_modify_expr (comp, NOP_EXPR, init)); } } c_expand_return (C_C_D); pop_momentary (); - finish_function (lineno, 0); } +void push_cp_function_context (); +void pop_cp_function_context (); + void -build_dtor (fndecl) +synthesize_method (fndecl) tree fndecl; { - start_function (NULL_TREE, fndecl, NULL_TREE, 1); + int nested = (current_function_decl != NULL_TREE); + tree context = decl_function_context (fndecl); + char *f = input_filename; + tree base = DECL_CLASS_CONTEXT (fndecl); + + if (nested) + push_cp_function_context (context); + + input_filename = DECL_SOURCE_FILE (fndecl); + interface_unknown = CLASSTYPE_INTERFACE_UNKNOWN (base); + interface_only = CLASSTYPE_INTERFACE_ONLY (base); + start_function (NULL_TREE, fndecl, NULL_TREE, NULL_TREE, 1); store_parm_decls (); - finish_function (lineno, 0); + + if (DECL_NAME (fndecl) == ansi_opname[MODIFY_EXPR]) + do_build_assign_ref (fndecl); + else if (DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (fndecl))) + ; + else + { + tree arg_chain = FUNCTION_ARG_CHAIN (fndecl); + if (DECL_CONSTRUCTOR_FOR_VBASE_P (fndecl)) + arg_chain = TREE_CHAIN (arg_chain); + if (arg_chain != void_list_node) + do_build_copy_constructor (fndecl); + else if (TYPE_NEEDS_CONSTRUCTING (current_class_type)) + setup_vtbl_ptr (); + } + + finish_function (lineno, 0, nested); + + /* Do we really *want* to inline this function? */ + if (DECL_INLINE (fndecl)) + { + /* Turn off DECL_INLINE for the moment so function_cannot_inline_p + will check our size. */ + DECL_INLINE (fndecl) = 0; + if (function_cannot_inline_p (fndecl) == 0) + DECL_INLINE (fndecl) = 1; + } + + input_filename = f; + extract_interface_info (); + if (nested) + pop_cp_function_context (context); }