--- gcc/cp/class.c 2018/04/24 18:20:21 1.1 +++ gcc/cp/class.c 2018/04/24 18:27:08 1.1.1.2 @@ -1,5 +1,5 @@ /* Functions related to building classes and their related objects. - Copyright (C) 1987, 1992, 1993, 1994 Free Software Foundation, Inc. + Copyright (C) 1987, 1992, 1993, 1994, 1995 Free Software Foundation, Inc. Contributed by Michael Tiemann (tiemann@cygnus.com) This file is part of GNU CC. @@ -16,7 +16,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. */ /* High-level class interface. */ @@ -26,6 +27,8 @@ the Free Software Foundation, 675 Mass A #include #include "cp-tree.h" #include "flags.h" +#include "rtl.h" +#include "output.h" #include "obstack.h" #define obstack_chunk_alloc xmalloc @@ -70,7 +73,6 @@ struct class_level }; tree current_class_decl, C_C_D; /* PARM_DECL: the class instance variable */ -tree current_vtable_decl; /* The following two can be derived from the previous one */ tree current_class_name; /* IDENTIFIER_NODE: name of current class */ @@ -89,6 +91,8 @@ int current_lang_stacksize; tree lang_name_c, lang_name_cplusplus; tree current_lang_name; +char *dont_allow_type_definitions; + /* When layout out an aggregate type, the size of the basetypes (virtual and non-virtual) is passed to layout_record via this node. */ @@ -184,11 +188,14 @@ build_vbase_path (code, type, expr, path tree basetype; tree offset = integer_zero_node; + if (nonnull == 0 && (alias_this && flag_this_is_variable <= 0)) + nonnull = 1; + /* We need additional logic to convert back to the unconverted type (the static type of the complete object), and then convert back to the type we want. Until that is done, or until we can recognize when that is, we cannot do the short cut logic. (mrs) */ - /* Do this, until we can undo any previous convertions. See net35.C + /* Do this, until we can undo any previous conversions. See net35.C for a testcase. */ fixed_type_p = complete_type_p (expr); @@ -235,12 +242,14 @@ build_vbase_path (code, type, expr, path } ind = build_indirect_ref (nonnull_expr, NULL_PTR); nonnull_expr = build_vbase_pointer (ind, last_virtual); - if (nonnull == 0 && !flag_assume_nonnull_objects + if (nonnull == 0 + && (TREE_CODE (type) == POINTER_TYPE + || !flag_assume_nonnull_objects) && null_expr == NULL_TREE) { - null_expr = build1 (NOP_EXPR, TYPE_POINTER_TO (last_virtual), integer_zero_node); - expr = build (COND_EXPR, TYPE_POINTER_TO (last_virtual), - build (EQ_EXPR, integer_type_node, expr, + null_expr = build1 (NOP_EXPR, build_pointer_type (last_virtual), integer_zero_node); + expr = build (COND_EXPR, build_pointer_type (last_virtual), + build (EQ_EXPR, boolean_type_node, expr, integer_zero_node), null_expr, nonnull_expr); } @@ -280,12 +289,9 @@ build_vbase_path (code, type, expr, path if (changed) { tree intype = TREE_TYPE (TREE_TYPE (expr)); - if (TYPE_MAIN_VARIANT (intype) == BINFO_TYPE (last)) - basetype = intype; - else + if (TYPE_MAIN_VARIANT (intype) != BINFO_TYPE (last)) { tree binfo = get_binfo (last, TYPE_MAIN_VARIANT (intype), 0); - basetype = last; offset = BINFO_OFFSET (binfo); } } @@ -303,13 +309,17 @@ build_vbase_path (code, type, expr, path if (TREE_INT_CST_LOW (offset)) { + /* Bash types to make the backend happy. */ + offset = convert (type, offset); + expr = build1 (NOP_EXPR, type, expr); + /* For multiple inheritance: if `this' can be set by any function, then it could be 0 on entry to any function. Preserve such zeroness here. Otherwise, only in the case of constructors need we worry, and in those cases, - it will be zero, or initialized to some legal value to + it will be zero, or initialized to some valid value to which we may add. */ - if (nonnull == 0 && (alias_this == 0 || flag_this_is_variable > 0)) + if (nonnull == 0) { if (null_expr) TREE_TYPE (null_expr) = type; @@ -319,7 +329,7 @@ build_vbase_path (code, type, expr, path expr = save_expr (expr); return build (COND_EXPR, type, - build (EQ_EXPR, integer_type_node, expr, integer_zero_node), + build (EQ_EXPR, boolean_type_node, expr, integer_zero_node), null_expr, build (code, type, expr, offset)); } @@ -422,14 +432,8 @@ build_vfn_ref (ptr_to_instptr, instance, basetype = TREE_TYPE (basetype); if (instance == C_C_D) - { - if (current_vtable_decl == NULL_TREE - || current_vtable_decl == error_mark_node - || !UNIQUELY_DERIVED_FROM_P (DECL_FCONTEXT (CLASSTYPE_VFIELD (current_class_type)), basetype)) - vtbl = build_indirect_ref (build_vfield_ref (instance, basetype), NULL_PTR); - else - vtbl = current_vtable_decl; - } + vtbl = build_indirect_ref (build_vfield_ref (instance, basetype), + NULL_PTR); else { if (optimize) @@ -464,8 +468,6 @@ build_vfn_ref (ptr_to_instptr, instance, } if (IS_AGGR_TYPE (TREE_TYPE (instance)) - && !IS_SIGNATURE_POINTER (TREE_TYPE (instance)) - && !IS_SIGNATURE_REFERENCE (TREE_TYPE (instance)) && (TREE_CODE (instance) == RESULT_DECL || TREE_CODE (instance) == PARM_DECL || TREE_CODE (instance) == VAR_DECL)) @@ -474,8 +476,7 @@ build_vfn_ref (ptr_to_instptr, instance, vtbl = build_indirect_ref (build_vfield_ref (instance, basetype), NULL_PTR); } - if (!flag_vtable_thunks) - assemble_external (vtbl); + assemble_external (vtbl); aref = build_array_ref (vtbl, idx); /* Save the intermediate result in a SAVE_EXPR so we don't have to @@ -487,11 +488,12 @@ build_vfn_ref (ptr_to_instptr, instance, return aref; else { - *ptr_to_instptr - = build (PLUS_EXPR, TREE_TYPE (*ptr_to_instptr), - *ptr_to_instptr, - convert (ptrdiff_type_node, - build_component_ref (aref, delta_identifier, 0, 0))); + if (ptr_to_instptr) + *ptr_to_instptr + = build (PLUS_EXPR, TREE_TYPE (*ptr_to_instptr), + *ptr_to_instptr, + convert (ptrdiff_type_node, + build_component_ref (aref, delta_identifier, 0, 0))); return build_component_ref (aref, pfn_identifier, 0, 0); } } @@ -548,8 +550,7 @@ build_vtable (binfo, type) #endif /* Set TREE_PUBLIC and TREE_EXTERN as appropriate. */ - if (! flag_vtable_thunks) - import_export_vtable (decl, type); + import_export_vtable (decl, type, 0); IDENTIFIER_GLOBAL_VALUE (name) = decl = pushdecl_top_level (decl); /* Initialize the association list for this type, based @@ -640,6 +641,36 @@ build_type_pathname (format, parent, typ return id; } +/* Update the rtti info for this class. */ +static void +set_rtti_entry (virtuals, offset, type) + tree virtuals, offset, type; +{ + if (! flag_vtable_thunks) + TREE_VALUE (virtuals) + = build_vtable_entry (offset, + (flag_rtti + ? build_t_desc (type, 0) + : integer_zero_node)); + else + { + tree vfn = build1 (NOP_EXPR, vfunc_ptr_type_node, offset); + TREE_CONSTANT (vfn) = 1; + + TREE_VALUE (virtuals) + = build_vtable_entry (integer_zero_node, vfn); + /* The second slot is for the tdesc pointer when thunks are used. */ + vfn = flag_rtti + ? build_t_desc (type, 0) + : integer_zero_node; + vfn = build1 (NOP_EXPR, vfunc_ptr_type_node, vfn); + TREE_CONSTANT (vfn) = 1; + + TREE_VALUE (TREE_CHAIN (virtuals)) + = build_vtable_entry (integer_zero_node, vfn); + } +} + /* Give TYPE a new virtual function table which is initialized with a skeleton-copy of its original initialization. The only entry that changes is the `delta' entry, so we can really @@ -659,7 +690,7 @@ prepare_fresh_vtable (binfo, for_type) for_type, and we really want different names. (mrs) */ tree name = build_type_pathname (VTABLE_NAME_FORMAT, basetype, for_type); tree new_decl = build_decl (VAR_DECL, name, TREE_TYPE (orig_decl)); - tree path; + tree path, offset; int result; /* Remember which class this vtable is really for. */ @@ -676,11 +707,16 @@ prepare_fresh_vtable (binfo, for_type) /* Make fresh virtual list, so we can smash it later. */ BINFO_VIRTUALS (binfo) = copy_list (BINFO_VIRTUALS (binfo)); - /* Install the value for `headof' if that's what we're doing. */ - if (flag_dossier) - TREE_VALUE (TREE_CHAIN (BINFO_VIRTUALS (binfo))) - = build_vtable_entry (size_binop (MINUS_EXPR, integer_zero_node, BINFO_OFFSET (binfo)), - FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (TREE_CHAIN (BINFO_VIRTUALS (binfo))))); + + if (TREE_VIA_VIRTUAL (binfo)) + offset = BINFO_OFFSET (binfo_member (BINFO_TYPE (binfo), + CLASSTYPE_VBASECLASSES (for_type))); + else + offset = BINFO_OFFSET (binfo); + + set_rtti_entry (BINFO_VIRTUALS (binfo), + size_binop (MINUS_EXPR, integer_zero_node, offset), + for_type); #ifdef GATHER_STATISTICS n_vtables += 1; @@ -688,8 +724,7 @@ prepare_fresh_vtable (binfo, for_type) #endif /* Set TREE_PUBLIC and TREE_EXTERN as appropriate. */ - if (! flag_vtable_thunks) - import_export_vtable (new_decl, for_type); + import_export_vtable (new_decl, for_type, 0); if (TREE_VIA_VIRTUAL (binfo)) my_friendly_assert (binfo == binfo_member (BINFO_TYPE (binfo), @@ -706,19 +741,19 @@ static tree get_vtable_entry (virtuals, base_fndecl) tree virtuals, base_fndecl; { - unsigned HOST_WIDE_INT i = (HOST_BITS_PER_WIDE_INT >= BITS_PER_WORD + unsigned HOST_WIDE_INT n = (HOST_BITS_PER_WIDE_INT >= BITS_PER_WORD ? (TREE_INT_CST_LOW (DECL_VINDEX (base_fndecl)) & (((unsigned HOST_WIDE_INT)1<<(BITS_PER_WORD-1))-1)) : TREE_INT_CST_LOW (DECL_VINDEX (base_fndecl))); #ifdef GATHER_STATISTICS - n_vtable_searches += i; + n_vtable_searches += n; #endif - while (i > 0 && virtuals) + while (n > 0 && virtuals) { + --n; virtuals = TREE_CHAIN (virtuals); - i -= 1; } return virtuals; } @@ -752,14 +787,14 @@ modify_vtable_entry (old_entry_in_list, /* Access the virtual function table entry i. VIRTUALS is the virtual function table's initializer. */ static tree -get_vtable_entry_n (virtuals, i) +get_vtable_entry_n (virtuals, n) tree virtuals; - unsigned HOST_WIDE_INT i; + unsigned HOST_WIDE_INT n; { - while (i > 0) + while (n > 0) { + --n; virtuals = TREE_CHAIN (virtuals); - i -= 1; } return virtuals; } @@ -792,9 +827,6 @@ add_virtual_function (pending_virtuals, fndecl); #endif - if (!flag_vtable_thunks) - TREE_ADDRESSABLE (fndecl) = CLASSTYPE_VTABLE_NEEDS_WRITING (t); - /* If the virtual function is a redefinition of a prior one, figure out in which base class the new definition goes, and if necessary, make a fresh virtual function table @@ -803,17 +835,24 @@ add_virtual_function (pending_virtuals, { tree entry; - if (flag_dossier && *has_virtual == 0) + if (flag_rtti && *has_virtual == 0) { - /* CLASSTYPE_DOSSIER is only used as a Boolean (NULL or not). */ - CLASSTYPE_DOSSIER (t) = integer_one_node; - *has_virtual = 1; + /* CLASSTYPE_RTTI is only used as a Boolean (NULL or not). */ + CLASSTYPE_RTTI (t) = integer_one_node; } + /* If we are using thunks, use two slots at the front, one + for the offset pointer, one for the tdesc pointer. */ + if (*has_virtual == 0 && flag_vtable_thunks) + { + *has_virtual = 1; + } + /* Build a new INT_CST for this DECL_VINDEX. */ { static tree index_table[256]; tree index; + /* We skip a slot for the offset/tdesc entry. */ int i = ++(*has_virtual); if (i >= 256 || index_table[i] == 0) @@ -1083,19 +1122,21 @@ alter_access (t, fdecl, access) error ("conflicting access specifications for field `%s', ignored", IDENTIFIER_POINTER (DECL_NAME (fdecl))); } - else if (TREE_PRIVATE (fdecl) && access != access_private) - cp_error_at ("cannot make private `%D' non-private", fdecl); + else if (TREE_PRIVATE (fdecl)) + { + if (access != access_private) + cp_error_at ("cannot make private `%D' non-private", fdecl); + goto alter; + } else if (TREE_PROTECTED (fdecl)) { - if (access == access_public) - cp_error_at ("cannot make protected `%D' public", fdecl); + if (access != access_protected) + cp_error_at ("cannot make protected `%D' non-protected", fdecl); goto alter; } /* ARM 11.3: an access declaration may not be used to restrict access to a member that is accessible in the base class. */ - else if (TREE_PUBLIC (fdecl) - && (access == access_private - || access == access_protected)) + else if (access != access_public) cp_error_at ("cannot reduce access of public member `%D'", fdecl); else if (elem == NULL_TREE) { @@ -1401,8 +1442,7 @@ finish_base_struct (t, b, t_binfo) TYPE_NEEDS_CONSTRUCTING (t) |= TYPE_NEEDS_CONSTRUCTING (basetype); TYPE_NEEDS_DESTRUCTOR (t) |= TYPE_NEEDS_DESTRUCTOR (basetype); TYPE_HAS_COMPLEX_ASSIGN_REF (t) |= TYPE_HAS_COMPLEX_ASSIGN_REF (basetype); - TYPE_HAS_COMPLEX_INIT_REF (t) |= (TYPE_HAS_COMPLEX_INIT_REF (basetype) - || TYPE_NEEDS_CONSTRUCTING (basetype)); + TYPE_HAS_COMPLEX_INIT_REF (t) |= TYPE_HAS_COMPLEX_INIT_REF (basetype); TYPE_OVERLOADS_CALL_EXPR (t) |= TYPE_OVERLOADS_CALL_EXPR (basetype); TYPE_OVERLOADS_ARRAY_REF (t) |= TYPE_OVERLOADS_ARRAY_REF (basetype); @@ -1438,6 +1478,7 @@ finish_base_struct (t, b, t_binfo) chain = TREE_VEC_ELT (base_binfos, j); TREE_VIA_PUBLIC (chain) = TREE_VIA_PUBLIC (base_base_binfo); TREE_VIA_PROTECTED (chain) = TREE_VIA_PROTECTED (base_base_binfo); + BINFO_INHERITANCE_CHAIN (chain) = base_binfo; } /* Completely unshare potentially shared data, and @@ -1676,80 +1717,78 @@ finish_struct_bits (t, max_has_virtual) } } - /* Need to test METHOD_VEC here in case all methods - (conversions and otherwise) are inherited. */ - if (TYPE_HAS_CONVERSION (t) && method_vec != NULL_TREE) - { - tree first_conversions[last_conversion_type]; - tree last_conversions[last_conversion_type]; - enum conversion_type conv_index; - tree *tmp; - int i; - - bzero ((char *) first_conversions, sizeof (first_conversions)); - bzero ((char *) last_conversions, sizeof (last_conversions)); - for (tmp = &TREE_VEC_ELT (method_vec, 1); - tmp != TREE_VEC_END (method_vec); tmp += 1) - { - /* ??? This should compare DECL_NAME (*tmp) == ansi_opname[TYPE_EXPR]. */ - if (IDENTIFIER_TYPENAME_P (DECL_ASSEMBLER_NAME (*tmp))) - { - tree fntype = TREE_TYPE (*tmp); - tree return_type = TREE_TYPE (fntype); - my_friendly_assert (TREE_CODE (fntype) == METHOD_TYPE, 171); - - if (typecode_p (return_type, POINTER_TYPE)) - { - if (TYPE_READONLY (TREE_TYPE (return_type))) - conv_index = constptr_conv; - else - conv_index = ptr_conv; - } - else if (typecode_p (return_type, INTEGER_TYPE) - || typecode_p (return_type, BOOLEAN_TYPE) - || typecode_p (return_type, ENUMERAL_TYPE)) - { - TYPE_HAS_INT_CONVERSION (t) = 1; - conv_index = int_conv; - } - else if (typecode_p (return_type, REAL_TYPE)) - { - TYPE_HAS_REAL_CONVERSION (t) = 1; - conv_index = real_conv; - } - else - continue; - - if (first_conversions[(int) conv_index] == NULL_TREE) - first_conversions[(int) conv_index] = *tmp; - last_conversions[(int) conv_index] = *tmp; - } - } - - for (i = 0; i < (int) last_conversion_type; i++) - if (first_conversions[i] != last_conversions[i]) - CLASSTYPE_CONVERSION (t, i) = error_mark_node; - else - CLASSTYPE_CONVERSION (t, i) = first_conversions[i]; - } - - /* If this type has constructors, force its mode to be BLKmode, - and force its TREE_ADDRESSABLE bit to be nonzero. */ - if (TYPE_NEEDS_CONSTRUCTING (t) || TYPE_NEEDS_DESTRUCTOR (t)) + /* If this type has a copy constructor, force its mode to be BLKmode, and + force its TREE_ADDRESSABLE bit to be nonzero. This will cause it to + be passed by invisible reference and prevent it from being returned in + a register. */ + if (! TYPE_HAS_TRIVIAL_INIT_REF (t)) { - tree variants = t; - + tree variants; if (TREE_CODE (TYPE_NAME (t)) == TYPE_DECL) DECL_MODE (TYPE_NAME (t)) = BLKmode; - while (variants) + for (variants = t; variants; variants = TYPE_NEXT_VARIANT (variants)) { TYPE_MODE (variants) = BLKmode; TREE_ADDRESSABLE (variants) = 1; - variants = TYPE_NEXT_VARIANT (variants); } } } +/* Add FN to the method_vec growing on the class_obstack. Used by + finish_struct_methods. */ +static void +grow_method (fn, method_vec_ptr) + tree fn; + tree *method_vec_ptr; +{ + tree method_vec = (tree)obstack_base (&class_obstack); + tree *testp = &TREE_VEC_ELT (method_vec, 0); + if (*testp == NULL_TREE) + testp++; + while (((HOST_WIDE_INT) testp + < (HOST_WIDE_INT) obstack_next_free (&class_obstack)) + && DECL_NAME (*testp) != DECL_NAME (fn)) + testp++; + if ((HOST_WIDE_INT) testp + < (HOST_WIDE_INT) obstack_next_free (&class_obstack)) + { + tree x, prev_x; + + for (x = *testp; x; x = DECL_CHAIN (x)) + { + if (DECL_NAME (fn) == ansi_opname[(int) DELETE_EXPR] + || DECL_NAME (fn) == ansi_opname[(int) VEC_DELETE_EXPR]) + { + /* ANSI C++ June 5 1992 WP 12.5.5.1 */ + cp_error_at ("`%D' overloaded", fn); + cp_error_at ("previous declaration as `%D' here", x); + } + if (DECL_ASSEMBLER_NAME (fn)==DECL_ASSEMBLER_NAME (x)) + { + /* We complain about multiple destructors on sight, + so we do not repeat the warning here. Friend-friend + ambiguities are warned about outside this loop. */ + if (!DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (fn))) + cp_error_at ("ambiguous method `%#D' in structure", fn); + break; + } + prev_x = x; + } + if (x == 0) + { + if (*testp) + DECL_CHAIN (prev_x) = fn; + else + *testp = fn; + } + } + else + { + obstack_ptr_grow (&class_obstack, fn); + *method_vec_ptr = (tree)obstack_base (&class_obstack); + } +} + /* Warn about duplicate methods in fn_fields. Also compact method lists so that lookup can be made faster. @@ -1758,10 +1797,12 @@ finish_struct_bits (t, max_has_virtual) Data Structure: List of method lists. The outer list is a TREE_LIST, whose TREE_PURPOSE field is the field name and the - TREE_VALUE is the TREE_CHAIN of the FUNCTION_DECLs. Friends are - chained in the same way as member functions, but they live in the - TREE_TYPE field of the outer list. That allows them to be quickly - deleted, and requires no extra storage. + TREE_VALUE is the DECL_CHAIN of the FUNCTION_DECLs. TREE_CHAIN + links the entire list of methods for TYPE_METHODS. Friends are + chained in the same way as member functions (? TREE_CHAIN or + DECL_CHAIN), but they live in the TREE_TYPE field of the outer + list. That allows them to be quickly deleted, and requires no + extra storage. If there are any constructors/destructors, they are moved to the front of the list. This makes pushclass more efficient. @@ -1778,6 +1819,8 @@ finish_struct_methods (t, fn_fields, non int nonprivate_method; { tree method_vec; + tree save_fn_fields = tree_cons (NULL_TREE, NULL_TREE, fn_fields); + tree lastp; tree name = constructor_name (t); int i, n_baseclasses = CLASSTYPE_N_BASECLASSES (t); @@ -1791,17 +1834,15 @@ finish_struct_methods (t, fn_fields, non obstack_free (&class_obstack, method_vec); obstack_blank (&class_obstack, sizeof (struct tree_vec)); - while (fn_fields) + /* First fill in entry 0 with the constructors, and the next few with + type conversion operators (if any). */ + + for (lastp = save_fn_fields; fn_fields; fn_fields = TREE_CHAIN (lastp)) { - /* NEXT Pointer, TEST Pointer, and BASE Pointer. */ - tree nextp, *testp; tree fn_name = DECL_NAME (fn_fields); if (fn_name == NULL_TREE) fn_name = name; - nextp = TREE_CHAIN (fn_fields); - TREE_CHAIN (fn_fields) = NULL_TREE; - /* Clear out this flag. @@ Doug may figure out how to break @@ -1829,8 +1870,45 @@ finish_struct_methods (t, fn_fields, non TYPE_HAS_NONPUBLIC_CTOR (t) = 2; } } + /* Constructors are handled easily in search routines. */ + DECL_CHAIN (fn_fields) = TREE_VEC_ELT (method_vec, 0); + TREE_VEC_ELT (method_vec, 0) = fn_fields; } - else if (fn_name == ansi_opname[(int) MODIFY_EXPR]) + else if (IDENTIFIER_TYPENAME_P (fn_name)) + { + tree return_type = TREE_TYPE (TREE_TYPE (fn_fields)); + + if (typecode_p (return_type, INTEGER_TYPE) + || typecode_p (return_type, BOOLEAN_TYPE) + || typecode_p (return_type, ENUMERAL_TYPE)) + TYPE_HAS_INT_CONVERSION (t) = 1; + else if (typecode_p (return_type, REAL_TYPE)) + TYPE_HAS_REAL_CONVERSION (t) = 1; + + grow_method (fn_fields, &method_vec); + } + else + { + lastp = fn_fields; + continue; + } + + TREE_CHAIN (lastp) = TREE_CHAIN (fn_fields); + TREE_CHAIN (fn_fields) = NULL_TREE; + } + + fn_fields = TREE_CHAIN (save_fn_fields); + while (fn_fields) + { + tree nextp; + tree fn_name = DECL_NAME (fn_fields); + if (fn_name == NULL_TREE) + fn_name = name; + + nextp = TREE_CHAIN (fn_fields); + TREE_CHAIN (fn_fields) = NULL_TREE; + + if (fn_name == ansi_opname[(int) MODIFY_EXPR]) { tree parmtype = TREE_VALUE (FUNCTION_ARG_CHAIN (fn_fields)); @@ -1843,62 +1921,7 @@ finish_struct_methods (t, fn_fields, non } } - /* Constructors are handled easily in search routines. */ - if (fn_name == name) - { - DECL_CHAIN (fn_fields) = TREE_VEC_ELT (method_vec, 0); - TREE_VEC_ELT (method_vec, 0) = fn_fields; - } - else - { - testp = &TREE_VEC_ELT (method_vec, 0); - if (*testp == NULL_TREE) - testp++; - while (((HOST_WIDE_INT) testp - < (HOST_WIDE_INT) obstack_next_free (&class_obstack)) - && DECL_NAME (*testp) != fn_name) - testp++; - if ((HOST_WIDE_INT) testp - < (HOST_WIDE_INT) obstack_next_free (&class_obstack)) - { - tree x, prev_x; - - for (x = *testp; x; x = DECL_CHAIN (x)) - { - if (DECL_NAME (fn_fields) == ansi_opname[(int) DELETE_EXPR] - || DECL_NAME (fn_fields) - == ansi_opname[(int) VEC_DELETE_EXPR]) - { - /* ANSI C++ June 5 1992 WP 12.5.5.1 */ - cp_error_at ("`%D' overloaded", fn_fields); - cp_error_at ("previous declaration as `%D' here", x); - } - if (DECL_ASSEMBLER_NAME (fn_fields)==DECL_ASSEMBLER_NAME (x)) - { - /* We complain about multiple destructors on sight, - so we do not repeat the warning here. Friend-friend - ambiguities are warned about outside this loop. */ - if (!DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (fn_fields))) - cp_error_at ("ambiguous method `%#D' in structure", - fn_fields); - break; - } - prev_x = x; - } - if (x == 0) - { - if (*testp) - DECL_CHAIN (prev_x) = fn_fields; - else - *testp = fn_fields; - } - } - else - { - obstack_ptr_grow (&class_obstack, fn_fields); - method_vec = (tree)obstack_base (&class_obstack); - } - } + grow_method (fn_fields, &method_vec); fn_fields = nextp; } @@ -2028,6 +2051,7 @@ duplicate_tag_error (t) tree t; { cp_error ("redefinition of `%#T'", t); + cp_error_at ("previous definition here", t); /* Pretend we haven't defined this type. */ @@ -2105,7 +2129,7 @@ finish_vtbls (binfo, do_self, t) && DECL_INITIAL (decl) != BINFO_VIRTUALS (binfo)) DECL_INITIAL (decl) = build_nt (CONSTRUCTOR, NULL_TREE, BINFO_VIRTUALS (binfo)); - finish_decl (decl, DECL_INITIAL (decl), NULL_TREE, 0); + cp_finish_decl (decl, DECL_INITIAL (decl), NULL_TREE, 0, 0); DECL_CONTEXT (decl) = context; } CLEAR_BINFO_NEW_VTABLE_MARKED (binfo); @@ -2234,17 +2258,57 @@ get_class_offset (context, t, binfo, fnd return offset; } +/* Skip RTTI information at the front of the virtual list. */ +unsigned HOST_WIDE_INT +skip_rtti_stuff (virtuals) + tree *virtuals; +{ + int n; + + n = 0; + if (*virtuals) + { + /* We always reserve a slot for the offset/tdesc entry. */ + ++n; + *virtuals = TREE_CHAIN (*virtuals); + } + if (flag_vtable_thunks && *virtuals) + { + /* The second slot is reserved for the tdesc pointer when thunks + are used. */ + ++n; + *virtuals = TREE_CHAIN (*virtuals); + } + return n; +} + static void modify_one_vtable (binfo, t, fndecl, pfn) tree binfo, t, fndecl, pfn; { tree virtuals = BINFO_VIRTUALS (binfo); + tree old_rtti; unsigned HOST_WIDE_INT n; - n = 0; - /* Skip initial vtable length field and RTTI fake object. */ - for (; virtuals && n < 1 + flag_dossier; n++) - virtuals = TREE_CHAIN (virtuals); + /* update rtti entry */ + if (flag_rtti) + { + if (binfo == TYPE_BINFO (t)) + { + if (! BINFO_NEW_VTABLE_MARKED (binfo)) + build_vtable (TYPE_BINFO (DECL_CONTEXT (CLASSTYPE_VFIELD (t))), t); + } + else + { + if (! BINFO_NEW_VTABLE_MARKED (binfo)) + prepare_fresh_vtable (binfo, t); + } + } + if (fndecl == NULL_TREE) + return; + + n = skip_rtti_stuff (&virtuals); + while (virtuals) { tree current_fndecl = TREE_VALUE (virtuals); @@ -2264,7 +2328,7 @@ modify_one_vtable (binfo, t, fndecl, pfn consideration the virtual base class pointers that we stick in before the virtual function table pointer. - Also, we want just the delta bewteen the most base class + Also, we want just the delta between the most base class that we derived this vfield from and us. */ base_offset = size_binop (PLUS_EXPR, get_derived_offset (binfo, DECL_CONTEXT (current_fndecl)), @@ -2272,13 +2336,9 @@ modify_one_vtable (binfo, t, fndecl, pfn this_offset = size_binop (MINUS_EXPR, offset, base_offset); /* Make sure we can modify the derived association with immunity. */ - if (TREE_USED (binfo)) { + if (TREE_USED (binfo)) my_friendly_assert (0, 999); -#if 0 - my_friendly_assert (*binfo2_ptr == binfo, 999); - *binfo2_ptr = copy_binfo (binfo); -#endif - } + if (binfo == TYPE_BINFO (t)) { /* In this case, it is *type*'s vtable we are modifying. @@ -2334,21 +2394,16 @@ modify_all_direct_vtables (binfo, do_sel } } -/* Fixup all the delta entries in this vtable that need updating. - This happens when we have non-overridden virtual functions from a - virtual base class, that are at a different offset, in the new - hierarchy, because the layout of the virtual bases has changed. */ +/* Fixup all the delta entries in this one vtable that need updating. */ static void -fixup_vtable_deltas (binfo, t) +fixup_vtable_deltas1 (binfo, t) tree binfo, t; { tree virtuals = BINFO_VIRTUALS (binfo); unsigned HOST_WIDE_INT n; - n = 0; - /* Skip initial vtable length field and RTTI fake object. */ - for (; virtuals && n < 1 + flag_dossier; n++) - virtuals = TREE_CHAIN (virtuals); + n = skip_rtti_stuff (&virtuals); + while (virtuals) { tree fndecl = TREE_VALUE (virtuals); @@ -2369,7 +2424,7 @@ fixup_vtable_deltas (binfo, t) consideration the virtual base class pointers that we stick in before the virtual function table pointer. - Also, we want just the delta bewteen the most base class + Also, we want just the delta between the most base class that we derived this vfield from and us. */ base_offset = size_binop (PLUS_EXPR, get_derived_offset (binfo, DECL_CONTEXT (fndecl)), @@ -2410,6 +2465,33 @@ fixup_vtable_deltas (binfo, t) } } +/* Fixup all the delta entries in all the direct vtables that need updating. + This happens when we have non-overridden virtual functions from a + virtual base class, that are at a different offset, in the new + hierarchy, because the layout of the virtual bases has changed. */ +static void +fixup_vtable_deltas (binfo, init_self, t) + tree binfo, t; + int init_self; +{ + tree binfos = BINFO_BASETYPES (binfo); + int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0; + + for (i = 0; i < n_baselinks; i++) + { + tree base_binfo = TREE_VEC_ELT (binfos, i); + int is_not_base_vtable = + i != CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (binfo)); + if (! TREE_VIA_VIRTUAL (base_binfo)) + fixup_vtable_deltas (base_binfo, is_not_base_vtable, t); + } + /* Should we use something besides CLASSTYPE_VFIELDS? */ + if (init_self && CLASSTYPE_VFIELDS (BINFO_TYPE (binfo))) + { + fixup_vtable_deltas1 (binfo, t); + } +} + /* These are the ones that are through virtual base classes. */ static void modify_all_indirect_vtables (binfo, do_self, via_virtual, t, fndecl, pfn) @@ -2489,21 +2571,8 @@ override_one_vtable (binfo, old, t) if (BINFO_NEW_VTABLE_MARKED (binfo)) choose = NEITHER; - /* Skip size entry. */ - virtuals = TREE_CHAIN (virtuals); - /* Skip RTTI fake object. */ - if (flag_dossier) - { - virtuals = TREE_CHAIN (virtuals); - } - - /* Skip size entry. */ - old_virtuals = TREE_CHAIN (old_virtuals); - /* Skip RTTI fake object. */ - if (flag_dossier) - { - old_virtuals = TREE_CHAIN (old_virtuals); - } + skip_rtti_stuff (&virtuals); + skip_rtti_stuff (&old_virtuals); while (virtuals) { @@ -2563,7 +2632,7 @@ override_one_vtable (binfo, old, t) return; } { - /* This MUST be overriden, or the class is ill-formed. */ + /* This MUST be overridden, or the class is ill-formed. */ /* For now, we just make it abstract. */ tree fndecl = TREE_OPERAND (FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (virtuals)), 0); tree vfn; @@ -2624,6 +2693,8 @@ merge_overrides (binfo, old, do_self, t) } } +extern int interface_only, interface_unknown; + /* Create a RECORD_TYPE or UNION_TYPE node for a C struct or union declaration (or C++ class declaration). @@ -2684,22 +2755,19 @@ merge_overrides (binfo, old, do_self, t) or otherwise in a type-consistent manner. */ tree -finish_struct (t, list_of_fieldlists, warn_anon) +finish_struct_1 (t, warn_anon) tree t; - tree list_of_fieldlists; int warn_anon; { - extern int interface_only, interface_unknown; - int old; int round_up_size = 1; + tree name = TYPE_IDENTIFIER (t); enum tree_code code = TREE_CODE (t); - register tree x, last_x, method_vec; + tree fields = TYPE_FIELDS (t); + tree fn_fields = CLASSTYPE_METHODS (t); + tree x, last_x, method_vec; int needs_virtual_dtor; - tree name = TYPE_NAME (t), fields, fn_fields, *tail; - tree *tail_user_methods = &CLASSTYPE_METHODS (t); - enum access_type access; int all_virtual; int has_virtual; int max_has_virtual; @@ -2724,37 +2792,9 @@ finish_struct (t, list_of_fieldlists, wa int nonprivate_method = 0; tree t_binfo = TYPE_BINFO (t); tree access_decls = NULL_TREE; + int aggregate = 1; - if (TREE_CODE (name) == TYPE_DECL) - { -#if 0 /* Maybe later. -jason */ - struct tinst_level *til = tinst_for_decl(); - - if (til) - { - DECL_SOURCE_FILE (name) = til->file; - if (DECL_SOURCE_LINE (name)) - DECL_SOURCE_LINE (name) = til->line; - } - else -#endif - { - extern int lineno; - - DECL_SOURCE_FILE (name) = input_filename; - /* For TYPE_DECL that are not typedefs (those marked with a line - number of zero, we don't want to mark them as real typedefs. - If this fails one needs to make sure real typedefs have a - previous line number, even if it is wrong, that way the below - will fill in the right line number. (mrs) */ - if (DECL_SOURCE_LINE (name)) - DECL_SOURCE_LINE (name) = lineno; - CLASSTYPE_SOURCE_LINE (t) = lineno; - } - name = DECL_NAME (name); - } - - if (warn_anon && code != UNION_TYPE && ANON_AGGRNAME_P (name)) + if (warn_anon && code != UNION_TYPE && ANON_AGGRNAME_P (TYPE_IDENTIFIER (t))) pedwarn ("anonymous class type not used to declare any objects"); if (TYPE_SIZE (t)) @@ -2767,9 +2807,11 @@ finish_struct (t, list_of_fieldlists, wa return t; } - /* Append the fields we need for constructing signature tables. */ - if (IS_SIGNATURE (t)) - append_signature_fields (list_of_fieldlists); + if (dont_allow_type_definitions) + { + pedwarn ("types cannot be defined %s", + dont_allow_type_definitions); + } GNU_xref_decl (current_function_decl, t); @@ -2789,8 +2831,10 @@ finish_struct (t, list_of_fieldlists, wa } #endif - if (flag_dossier) +#if 0 + if (flag_rtti) build_t_desc (t, 0); +#endif TYPE_BINFO (t) = NULL_TREE; @@ -2814,8 +2858,9 @@ finish_struct (t, list_of_fieldlists, wa /* If using multiple inheritance, this may cause variants of our basetypes to be used (instead of their canonical forms). */ - fields = layout_basetypes (t, BINFO_BASETYPES (t_binfo)); - last_x = tree_last (fields); + tree vf = layout_basetypes (t, BINFO_BASETYPES (t_binfo)); + last_x = tree_last (vf); + fields = chainon (vf, fields); first_vfn_base_index = finish_base_struct (t, &base_info, t_binfo); /* Remember where we got our vfield from */ @@ -2832,6 +2877,7 @@ finish_struct (t, list_of_fieldlists, wa no_const_asn_ref = base_info.no_const_asn_ref; needs_virtual_dtor = base_info.needs_virtual_dtor; n_baseclasses = TREE_VEC_LENGTH (BINFO_BASETYPES (t_binfo)); + aggregate = 0; } else { @@ -2840,7 +2886,6 @@ finish_struct (t, list_of_fieldlists, wa max_has_virtual = has_virtual; vfield = NULL_TREE; vfields = NULL_TREE; - fields = NULL_TREE; last_x = NULL_TREE; cant_have_default_ctor = 0; cant_have_const_ctor = 0; @@ -2868,10 +2913,6 @@ finish_struct (t, list_of_fieldlists, wa CLASSTYPE_VFIELDS (t) = vfields; CLASSTYPE_VFIELD (t) = vfield; - tail = &fn_fields; - if (last_x && list_of_fieldlists) - TREE_CHAIN (last_x) = TREE_VALUE (list_of_fieldlists); - if (IS_SIGNATURE (t)) all_virtual = 0; else if (flag_all_virtual == 1 && TYPE_OVERLOADS_METHOD_CALL_EXPR (t)) @@ -2879,400 +2920,359 @@ finish_struct (t, list_of_fieldlists, wa else all_virtual = 0; - /* For signatures, we made all methods `public' in the parser and - reported an error if a access specifier was used. */ - if (CLASSTYPE_DECLARED_CLASS (t) == 0) + for (x = CLASSTYPE_METHODS (t); x; x = TREE_CHAIN (x)) { - nonprivate_method = 1; - if (list_of_fieldlists - && TREE_PURPOSE (list_of_fieldlists) == (tree)access_default) - TREE_PURPOSE (list_of_fieldlists) = (tree)access_public; - } - else if (list_of_fieldlists - && TREE_PURPOSE (list_of_fieldlists) == (tree)access_default) - TREE_PURPOSE (list_of_fieldlists) = (tree)access_private; + GNU_xref_member (current_class_name, x); - while (list_of_fieldlists) - { - access = (enum access_type)TREE_PURPOSE (list_of_fieldlists); + nonprivate_method |= ! TREE_PRIVATE (x); - for (x = TREE_VALUE (list_of_fieldlists); x; x = TREE_CHAIN (x)) - { - TREE_PRIVATE (x) = access == access_private; - TREE_PROTECTED (x) = access == access_protected; - GNU_xref_member (current_class_name, x); + /* If this was an evil function, don't keep it in class. */ + if (IDENTIFIER_ERROR_LOCUS (DECL_ASSEMBLER_NAME (x))) + continue; - if (TREE_CODE (x) == TYPE_DECL) - { - /* Make sure we set this up. In find_scoped_type, it explicitly - looks for a TYPE_DECL in the TYPE_FIELDS list. If we don't - do this here, we'll miss including this TYPE_DECL in the - list. */ - if (! fields) - fields = x; - last_x = x; - continue; - } + DECL_CLASS_CONTEXT (x) = t; - /* Check for inconsistent use of this name in the class body. - Enums, types and static vars have already been checked. */ - if (TREE_CODE (x) != CONST_DECL && TREE_CODE (x) != VAR_DECL) - { - tree name = DECL_NAME (x); - tree icv; + /* Do both of these, even though they're in the same union; + if the insn `r' member and the size `i' member are + different sizes, as on the alpha, the larger of the two + will end up with garbage in it. */ + DECL_SAVED_INSNS (x) = NULL_RTX; + DECL_FIELD_SIZE (x) = 0; + + /* The name of the field is the original field name + Save this in auxiliary field for later overloading. */ + if (DECL_VINDEX (x) + || (all_virtual == 1 && ! DECL_CONSTRUCTOR_P (x))) + { + pending_virtuals = add_virtual_function (pending_virtuals, + &has_virtual, x, t); + if (DECL_ABSTRACT_VIRTUAL_P (x)) + abstract_virtuals = tree_cons (NULL_TREE, x, abstract_virtuals); + else + TREE_USED (x) = 1; + } + } - /* Don't get confused by access decls. */ - if (name && TREE_CODE (name) == IDENTIFIER_NODE) - icv = IDENTIFIER_CLASS_VALUE (name); - else - icv = NULL_TREE; + for (x = TYPE_FIELDS (t); x; x = TREE_CHAIN (x)) + { + GNU_xref_member (current_class_name, x); - if (icv - /* Don't complain about constructors. */ - && name != constructor_name (current_class_type) - /* Or inherited names. */ - && id_in_current_class (name) - /* Or shadowed tags. */ - && !(TREE_CODE (icv) == TYPE_DECL - && DECL_CONTEXT (icv) == t)) - { - cp_error_at ("declaration of identifier `%D' as `%+#D'", - name, x); - cp_error_at ("conflicts with other use in class as `%#D'", - icv); - } - } + /* Handle access declarations. */ + if (DECL_NAME (x) && TREE_CODE (DECL_NAME (x)) == SCOPE_REF) + { + tree fdecl = TREE_OPERAND (DECL_NAME (x), 1); + enum access_type access + = TREE_PRIVATE (x) ? access_private : + TREE_PROTECTED (x) ? access_protected : access_public; - if (TREE_CODE (x) == FUNCTION_DECL) - { - nonprivate_method |= ! TREE_PRIVATE (x); + if (last_x) + TREE_CHAIN (last_x) = TREE_CHAIN (x); + else + fields = TREE_CHAIN (x); - /* If this was an evil function, don't keep it in class. */ - if (IDENTIFIER_ERROR_LOCUS (DECL_ASSEMBLER_NAME (x))) - continue; + access_decls = tree_cons ((tree) access, fdecl, access_decls); + continue; + } - if (last_x) - TREE_CHAIN (last_x) = TREE_CHAIN (x); - /* Link x onto end of fn_fields and CLASSTYPE_METHODS. */ - *tail = x; - tail = &TREE_CHAIN (x); - *tail_user_methods = x; - tail_user_methods = &DECL_NEXT_METHOD (x); + last_x = x; - DECL_CLASS_CONTEXT (x) = t; + if (TREE_CODE (x) == TYPE_DECL) + continue; - DECL_FIELD_SIZE (x) = 0; + /* If we've gotten this far, it's a data member, possibly static, + or an enumerator. */ - /* The name of the field is the original field name - Save this in auxiliary field for later overloading. */ - if (DECL_VINDEX (x) - || (all_virtual == 1 && ! DECL_CONSTRUCTOR_P (x))) - { - pending_virtuals = add_virtual_function (pending_virtuals, - &has_virtual, x, t); - if (DECL_ABSTRACT_VIRTUAL_P (x)) - abstract_virtuals = tree_cons (NULL_TREE, x, abstract_virtuals); - } - continue; - } + DECL_FIELD_CONTEXT (x) = t; - /* Handle access declarations. */ - if (DECL_NAME (x) && TREE_CODE (DECL_NAME (x)) == SCOPE_REF) - { - tree fdecl = TREE_OPERAND (DECL_NAME (x), 1); + /* ``A local class cannot have static data members.'' ARM 9.4 */ + if (current_function_decl && TREE_STATIC (x)) + cp_error_at ("field `%D' in local class cannot be static", x); - if (last_x) - TREE_CHAIN (last_x) = TREE_CHAIN (x); - access_decls = tree_cons ((tree) access, fdecl, access_decls); - continue; - } + /* Perform error checking that did not get done in + grokdeclarator. */ + if (TREE_CODE (TREE_TYPE (x)) == FUNCTION_TYPE) + { + cp_error_at ("field `%D' invalidly declared function type", + x); + TREE_TYPE (x) = build_pointer_type (TREE_TYPE (x)); + } + else if (TREE_CODE (TREE_TYPE (x)) == METHOD_TYPE) + { + cp_error_at ("field `%D' invalidly declared method type", x); + TREE_TYPE (x) = build_pointer_type (TREE_TYPE (x)); + } + else if (TREE_CODE (TREE_TYPE (x)) == OFFSET_TYPE) + { + cp_error_at ("field `%D' invalidly declared offset type", x); + TREE_TYPE (x) = build_pointer_type (TREE_TYPE (x)); + } - /* If we've gotten this far, it's a data member, possibly static, - or an enumerator. */ +#if 0 + if (DECL_NAME (x) == constructor_name (t)) + cant_have_default_ctor = cant_synth_copy_ctor = 1; +#endif - DECL_FIELD_CONTEXT (x) = t; + if (TREE_TYPE (x) == error_mark_node) + continue; + + DECL_SAVED_INSNS (x) = NULL_RTX; + DECL_FIELD_SIZE (x) = 0; - /* ``A local class cannot have static data members.'' ARM 9.4 */ - if (current_function_decl && TREE_STATIC (x)) - cp_error_at ("field `%D' in local class cannot be static", x); + /* When this goes into scope, it will be a non-local reference. */ + DECL_NONLOCAL (x) = 1; - /* Perform error checking that did not get done in - grokdeclarator. */ - if (TREE_CODE (TREE_TYPE (x)) == FUNCTION_TYPE) - { - cp_error_at ("field `%D' invalidly declared function type", - x); - TREE_TYPE (x) = build_pointer_type (TREE_TYPE (x)); - } - else if (TREE_CODE (TREE_TYPE (x)) == METHOD_TYPE) - { - cp_error_at ("field `%D' invalidly declared method type", x); - TREE_TYPE (x) = build_pointer_type (TREE_TYPE (x)); - } - else if (TREE_CODE (TREE_TYPE (x)) == OFFSET_TYPE) - { - cp_error_at ("field `%D' invalidly declared offset type", x); - TREE_TYPE (x) = build_pointer_type (TREE_TYPE (x)); - } + if (TREE_CODE (x) == CONST_DECL) + continue; - if (DECL_NAME (x) == constructor_name (t)) - cant_have_default_ctor = cant_synth_copy_ctor = 1; + if (TREE_CODE (x) == VAR_DECL) + { + if (TREE_CODE (t) == UNION_TYPE) + /* Unions cannot have static members. */ + cp_error_at ("field `%D' declared static in union", x); + + continue; + } - if (TREE_TYPE (x) == error_mark_node) - continue; - - if (! fields) - fields = x; - last_x = x; + /* Now it can only be a FIELD_DECL. */ - DECL_FIELD_SIZE (x) = 0; + if (TREE_PRIVATE (x) || TREE_PROTECTED (x)) + aggregate = 0; - /* When this goes into scope, it will be a non-local reference. */ - DECL_NONLOCAL (x) = 1; + /* If this is of reference type, check if it needs an init. + Also do a little ANSI jig if necessary. */ + if (TREE_CODE (TREE_TYPE (x)) == REFERENCE_TYPE) + { + if (DECL_INITIAL (x) == NULL_TREE) + ref_sans_init = 1; - if (TREE_CODE (x) == CONST_DECL) - continue; + /* ARM $12.6.2: [A member initializer list] (or, for an + aggregate, initialization by a brace-enclosed list) is the + only way to initialize nonstatic const and reference + members. */ + cant_synth_asn_ref = 1; + cant_have_default_ctor = 1; - if (TREE_CODE (x) == VAR_DECL) + if (! TYPE_HAS_CONSTRUCTOR (t) && extra_warnings) { - if (TREE_CODE (t) == UNION_TYPE) - /* Unions cannot have static members. */ - cp_error_at ("field `%D' declared static in union", x); - - continue; + if (DECL_NAME (x)) + cp_warning_at ("non-static reference `%#D' in class without a constructor", x); + else + cp_warning_at ("non-static reference in class without a constructor", x); } + } - /* Now it can only be a FIELD_DECL. */ + /* If any field is const, the structure type is pseudo-const. */ + if (TREE_READONLY (x)) + { + C_TYPE_FIELDS_READONLY (t) = 1; + if (DECL_INITIAL (x) == NULL_TREE) + const_sans_init = 1; - /* If this is of reference type, check if it needs an init. - Also do a little ANSI jig if necessary. */ - if (TREE_CODE (TREE_TYPE (x)) == REFERENCE_TYPE) - { - if (DECL_INITIAL (x) == NULL_TREE) - ref_sans_init = 1; - - /* ARM $12.6.2: [A member initializer list] (or, for an - aggregate, initialization by a brace-enclosed list) is the - only way to initialize nonstatic const and reference - members. */ - cant_synth_asn_ref = 1; - cant_have_default_ctor = 1; - TYPE_HAS_COMPLEX_INIT_REF (t) = 1; + /* ARM $12.6.2: [A member initializer list] (or, for an + aggregate, initialization by a brace-enclosed list) is the + only way to initialize nonstatic const and reference + members. */ + cant_synth_asn_ref = 1; + cant_have_default_ctor = 1; - if (! TYPE_HAS_CONSTRUCTOR (t) && extra_warnings) - { - if (DECL_NAME (x)) - cp_warning_at ("non-static reference `%#D' in class without a constructor", x); - else - cp_warning_at ("non-static reference in class without a constructor", x); - } + if (! TYPE_HAS_CONSTRUCTOR (t) && !IS_SIGNATURE (t) + && extra_warnings) + { + if (DECL_NAME (x)) + cp_warning_at ("non-static const member `%#D' in class without a constructor", x); + else + cp_warning_at ("non-static const member in class without a constructor", x); + } + } + else + { + /* A field that is pseudo-const makes the structure + likewise. */ + tree t1 = TREE_TYPE (x); + while (TREE_CODE (t1) == ARRAY_TYPE) + t1 = TREE_TYPE (t1); + if (IS_AGGR_TYPE (t1)) + { + if (C_TYPE_FIELDS_READONLY (t1)) + C_TYPE_FIELDS_READONLY (t) = 1; + if (CLASSTYPE_READONLY_FIELDS_NEED_INIT (t1)) + const_sans_init = 1; } + } - /* If any field is const, the structure type is pseudo-const. */ - if (TREE_READONLY (x)) + /* We set DECL_BIT_FIELD tentatively in grokbitfield. + If the type and width are valid, we'll keep it set. + Otherwise, the flag is cleared. */ + if (DECL_BIT_FIELD (x)) + { + DECL_BIT_FIELD (x) = 0; + /* Invalid bit-field size done by grokfield. */ + /* Detect invalid bit-field type. */ + if (DECL_INITIAL (x) + && ! INTEGRAL_TYPE_P (TREE_TYPE (x))) { - C_TYPE_FIELDS_READONLY (t) = 1; - if (DECL_INITIAL (x) == NULL_TREE) - const_sans_init = 1; + cp_error_at ("bit-field `%#D' with non-integral type", x); + DECL_INITIAL (x) = NULL; + } - /* ARM $12.6.2: [A member initializer list] (or, for an - aggregate, initialization by a brace-enclosed list) is the - only way to initialize nonstatic const and reference - members. */ - cant_synth_asn_ref = 1; - cant_have_default_ctor = 1; - TYPE_HAS_COMPLEX_INIT_REF (t) = 1; + /* Detect and ignore out of range field width. */ + if (DECL_INITIAL (x)) + { + register int width = TREE_INT_CST_LOW (DECL_INITIAL (x)); - if (! TYPE_HAS_CONSTRUCTOR (t) && !IS_SIGNATURE (t) - && extra_warnings) + if (width < 0) { - if (DECL_NAME (x)) - cp_warning_at ("non-static const member `%#D' in class without a constructor", x); - else - cp_warning_at ("non-static const member in class without a constructor", x); + DECL_INITIAL (x) = NULL; + cp_error_at ("negative width in bit-field `%D'", x); } - } - else - { - /* A field that is pseudo-const makes the structure - likewise. */ - tree t1 = TREE_TYPE (x); - while (TREE_CODE (t1) == ARRAY_TYPE) - t1 = TREE_TYPE (t1); - if (IS_AGGR_TYPE (t1)) + else if (width == 0 && DECL_NAME (x) != 0) { - if (C_TYPE_FIELDS_READONLY (t1)) - C_TYPE_FIELDS_READONLY (t) = 1; - if (CLASSTYPE_READONLY_FIELDS_NEED_INIT (t1)) - const_sans_init = 1; + DECL_INITIAL (x) = NULL; + cp_error_at ("zero width for bit-field `%D'", x); } - } - - /* We set DECL_BIT_FIELD tentatively in grokbitfield. - If the type and width are valid, we'll keep it set. - Otherwise, the flag is cleared. */ - if (DECL_BIT_FIELD (x)) - { - DECL_BIT_FIELD (x) = 0; - /* Invalid bit-field size done by grokfield. */ - /* Detect invalid bit-field type. */ - if (DECL_INITIAL (x) - && ! INTEGRAL_TYPE_P (TREE_TYPE (x))) + else if (width + > TYPE_PRECISION (long_long_unsigned_type_node)) { - cp_error_at ("bit-field `%#D' with non-integral type", x); + /* The backend will dump if you try to use something + too big; avoid that. */ DECL_INITIAL (x) = NULL; + sorry ("bit-fields larger than %d bits", + TYPE_PRECISION (long_long_unsigned_type_node)); + cp_error_at (" in declaration of `%D'", x); } - - /* Detect and ignore out of range field width. */ - if (DECL_INITIAL (x)) + else if (width > TYPE_PRECISION (TREE_TYPE (x)) + && TREE_CODE (TREE_TYPE (x)) != ENUMERAL_TYPE) { - register int width = TREE_INT_CST_LOW (DECL_INITIAL (x)); - - if (width < 0) - { - DECL_INITIAL (x) = NULL; - cp_error_at ("negative width in bit-field `%D'", x); - } - else if (width == 0 && DECL_NAME (x) != 0) - { - DECL_INITIAL (x) = NULL; - cp_error_at ("zero width for bit-field `%D'", x); - } - else if ((unsigned)width > TYPE_PRECISION (TREE_TYPE (x))) - { - DECL_INITIAL (x) = NULL; - cp_error_at ("width of `%D' exceeds its type", x); - } + cp_warning_at ("width of `%D' exceeds its type", x); } - - /* Process valid field width. */ - if (DECL_INITIAL (x)) + else if (TREE_CODE (TREE_TYPE (x)) == ENUMERAL_TYPE + && ((min_precision (TYPE_MIN_VALUE (TREE_TYPE (x)), + TREE_UNSIGNED (TREE_TYPE (x))) > width) + || (min_precision (TYPE_MAX_VALUE (TREE_TYPE (x)), + TREE_UNSIGNED (TREE_TYPE (x))) > width))) { - register int width = TREE_INT_CST_LOW (DECL_INITIAL (x)); + cp_warning_at ("`%D' is too small to hold all values of `%#T'", + x, TREE_TYPE (x)); + } + } - if (width == 0) - { + /* Process valid field width. */ + if (DECL_INITIAL (x)) + { + register int width = TREE_INT_CST_LOW (DECL_INITIAL (x)); + + if (width == 0) + { #ifdef EMPTY_FIELD_BOUNDARY - /* field size 0 => mark following field as "aligned" */ - if (TREE_CHAIN (x)) - DECL_ALIGN (TREE_CHAIN (x)) - = MAX (DECL_ALIGN (TREE_CHAIN (x)), EMPTY_FIELD_BOUNDARY); - /* field of size 0 at the end => round up the size. */ - else - round_up_size = EMPTY_FIELD_BOUNDARY; + /* field size 0 => mark following field as "aligned" */ + if (TREE_CHAIN (x)) + DECL_ALIGN (TREE_CHAIN (x)) + = MAX (DECL_ALIGN (TREE_CHAIN (x)), EMPTY_FIELD_BOUNDARY); + /* field of size 0 at the end => round up the size. */ + else + round_up_size = EMPTY_FIELD_BOUNDARY; #endif #ifdef PCC_BITFIELD_TYPE_MATTERS - DECL_ALIGN (x) = MAX (DECL_ALIGN (x), - TYPE_ALIGN (TREE_TYPE (x))); + DECL_ALIGN (x) = MAX (DECL_ALIGN (x), + TYPE_ALIGN (TREE_TYPE (x))); #endif - } - else - { - DECL_INITIAL (x) = NULL_TREE; - DECL_FIELD_SIZE (x) = width; - DECL_BIT_FIELD (x) = 1; - /* Traditionally a bit field is unsigned - even if declared signed. */ - if (flag_traditional - && TREE_CODE (TREE_TYPE (x)) == INTEGER_TYPE) - TREE_TYPE (x) = unsigned_type_node; - } } else - /* Non-bit-fields are aligned for their type. */ - DECL_ALIGN (x) = MAX (DECL_ALIGN (x), TYPE_ALIGN (TREE_TYPE (x))); + { + DECL_INITIAL (x) = NULL_TREE; + DECL_FIELD_SIZE (x) = width; + DECL_BIT_FIELD (x) = 1; + /* Traditionally a bit field is unsigned + even if declared signed. */ + if (flag_traditional + && TREE_CODE (TREE_TYPE (x)) == INTEGER_TYPE) + TREE_TYPE (x) = unsigned_type_node; + } } else - { - tree type = TREE_TYPE (x); + /* Non-bit-fields are aligned for their type. */ + DECL_ALIGN (x) = MAX (DECL_ALIGN (x), TYPE_ALIGN (TREE_TYPE (x))); + } + else + { + tree type = TREE_TYPE (x); - if (TREE_CODE (type) == ARRAY_TYPE) - type = TREE_TYPE (type); + if (TREE_CODE (type) == ARRAY_TYPE) + type = TREE_TYPE (type); - if (TYPE_LANG_SPECIFIC (type) && ! ANON_UNION_P (x) - && ! TYPE_PTRMEMFUNC_P (type)) - { - /* Never let anything with uninheritable virtuals - make it through without complaint. */ - if (CLASSTYPE_ABSTRACT_VIRTUALS (type)) - abstract_virtuals_error (x, type); + if (TYPE_LANG_SPECIFIC (type) && ! ANON_UNION_P (x) + && ! TYPE_PTRMEMFUNC_P (type)) + { + /* Never let anything with uninheritable virtuals + make it through without complaint. */ + if (CLASSTYPE_ABSTRACT_VIRTUALS (type)) + abstract_virtuals_error (x, type); - /* Don't let signatures make it through either. */ - if (IS_SIGNATURE (type)) - signature_error (x, type); + /* Don't let signatures make it through either. */ + if (IS_SIGNATURE (type)) + signature_error (x, type); - if (code == UNION_TYPE) - { - char *fie = NULL; - if (TYPE_NEEDS_CONSTRUCTING (type)) - fie = "constructor"; - else if (TYPE_NEEDS_DESTRUCTOR (type)) - fie = "destructor"; - else if (TYPE_HAS_REAL_ASSIGNMENT (type)) - fie = "assignment operator"; - if (fie) - cp_error_at ("member `%#D' with %s not allowed in union", x, - fie); - } - else - { - TYPE_NEEDS_CONSTRUCTING (t) |= TYPE_NEEDS_CONSTRUCTING (type); - TYPE_NEEDS_DESTRUCTOR (t) |= TYPE_NEEDS_DESTRUCTOR (type); - TYPE_HAS_COMPLEX_ASSIGN_REF (t) |= TYPE_HAS_COMPLEX_ASSIGN_REF (type); - TYPE_HAS_COMPLEX_INIT_REF (t) - |= (TYPE_HAS_COMPLEX_INIT_REF (type) - || TYPE_NEEDS_CONSTRUCTING (type)); - } + if (code == UNION_TYPE) + { + char *fie = NULL; + if (TYPE_NEEDS_CONSTRUCTING (type)) + fie = "constructor"; + else if (TYPE_NEEDS_DESTRUCTOR (type)) + fie = "destructor"; + else if (TYPE_HAS_REAL_ASSIGNMENT (type)) + fie = "assignment operator"; + if (fie) + cp_error_at ("member `%#D' with %s not allowed in union", x, + fie); + } + else + { + TYPE_NEEDS_CONSTRUCTING (t) |= TYPE_NEEDS_CONSTRUCTING (type); + TYPE_NEEDS_DESTRUCTOR (t) |= TYPE_NEEDS_DESTRUCTOR (type); + TYPE_HAS_COMPLEX_ASSIGN_REF (t) |= TYPE_HAS_COMPLEX_ASSIGN_REF (type); + TYPE_HAS_COMPLEX_INIT_REF (t) |= TYPE_HAS_COMPLEX_INIT_REF (type); + } - if (! TYPE_HAS_INIT_REF (type) - || (TYPE_HAS_NONPUBLIC_CTOR (type) - && ! is_friend (t, type))) - cant_synth_copy_ctor = 1; - else if (!TYPE_HAS_CONST_INIT_REF (type)) - cant_have_const_ctor = 1; - - if (! TYPE_HAS_ASSIGN_REF (type) - || (TYPE_HAS_NONPUBLIC_ASSIGN_REF (type) - && ! is_friend (t, type))) - cant_synth_asn_ref = 1; - else if (!TYPE_HAS_CONST_ASSIGN_REF (type)) - no_const_asn_ref = 1; + if (! TYPE_HAS_INIT_REF (type) + || (TYPE_HAS_NONPUBLIC_CTOR (type) + && ! is_friend (t, type))) + cant_synth_copy_ctor = 1; + else if (!TYPE_HAS_CONST_INIT_REF (type)) + cant_have_const_ctor = 1; + + if (! TYPE_HAS_ASSIGN_REF (type) + || (TYPE_HAS_NONPUBLIC_ASSIGN_REF (type) + && ! is_friend (t, type))) + cant_synth_asn_ref = 1; + else if (!TYPE_HAS_CONST_ASSIGN_REF (type)) + no_const_asn_ref = 1; - if (TYPE_HAS_CONSTRUCTOR (type) - && ! TYPE_HAS_DEFAULT_CONSTRUCTOR (type)) + if (TYPE_HAS_CONSTRUCTOR (type) + && ! TYPE_HAS_DEFAULT_CONSTRUCTOR (type)) + { + cant_have_default_ctor = 1; +#if 0 + /* This is wrong for aggregates. */ + if (! TYPE_HAS_CONSTRUCTOR (t)) { - cant_have_default_ctor = 1; - if (! TYPE_HAS_CONSTRUCTOR (t)) - { - if (DECL_NAME (x)) - cp_pedwarn_at ("member `%#D' with only non-default constructor", x); - else - cp_pedwarn_at ("member with only non-default constructor", x); - cp_pedwarn_at ("in class without a constructor", - x); - } + if (DECL_NAME (x)) + cp_pedwarn_at ("member `%#D' with only non-default constructor", x); + else + cp_pedwarn_at ("member with only non-default constructor", x); + cp_pedwarn_at ("in class without a constructor", + x); } - } - if (DECL_INITIAL (x) != NULL_TREE) - { - /* `build_class_init_list' does not recognize - non-FIELD_DECLs. */ - if (code == UNION_TYPE && any_default_members != 0) - cp_error_at ("multiple fields in union `%T' initialized"); - any_default_members = 1; +#endif } } - } - list_of_fieldlists = TREE_CHAIN (list_of_fieldlists); - /* link the tail while we have it! */ - if (last_x) - { - TREE_CHAIN (last_x) = NULL_TREE; - - if (list_of_fieldlists - && TREE_VALUE (list_of_fieldlists) - && TREE_CODE (TREE_VALUE (list_of_fieldlists)) != FUNCTION_DECL) - TREE_CHAIN (last_x) = TREE_VALUE (list_of_fieldlists); + if (DECL_INITIAL (x) != NULL_TREE) + { + /* `build_class_init_list' does not recognize + non-FIELD_DECLs. */ + if (code == UNION_TYPE && any_default_members != 0) + cp_error_at ("multiple fields in union `%T' initialized"); + any_default_members = 1; + } } } @@ -3287,6 +3287,9 @@ finish_struct (t, list_of_fieldlists, wa /* Synthesize any needed methods. Note that methods will be synthesized for anonymous unions; grok_x_components undoes that. */ + if (! fn_fields) + nonprivate_method = 1; + if (TYPE_NEEDS_DESTRUCTOR (t) && !TYPE_HAS_DESTRUCTOR (t) && !IS_SIGNATURE (t)) { @@ -3299,11 +3302,11 @@ finish_struct (t, list_of_fieldlists, wa else { /* Link dtor onto end of fn_fields. */ - *tail = dtor; - tail = &TREE_CHAIN (dtor); + + TREE_CHAIN (dtor) = fn_fields; + fn_fields = dtor; if (DECL_VINDEX (dtor) == NULL_TREE - && ! CLASSTYPE_DECLARED_EXCEPTION (t) && (needs_virtual_dtor || pending_virtuals != NULL_TREE || pending_hard_virtuals != NULL_TREE)) @@ -3315,20 +3318,20 @@ finish_struct (t, list_of_fieldlists, wa } } - *tail = NULL_TREE; - *tail_user_methods = NULL_TREE; - TYPE_NEEDS_DESTRUCTOR (t) |= TYPE_HAS_DESTRUCTOR (t); - - if (! fn_fields) - nonprivate_method = 1; + if (flag_rtti && (max_has_virtual > 0 || needs_virtual_dtor) && + has_virtual == 0) + has_virtual = 1; TYPE_HAS_COMPLEX_INIT_REF (t) |= (TYPE_HAS_INIT_REF (t) || TYPE_USES_VIRTUAL_BASECLASSES (t) - || has_virtual || any_default_members || first_vfn_base_index >= 0); + || any_default_members); TYPE_NEEDS_CONSTRUCTING (t) |= (TYPE_HAS_CONSTRUCTOR (t) || TYPE_USES_VIRTUAL_BASECLASSES (t) || has_virtual || any_default_members || first_vfn_base_index >= 0); + if (! IS_SIGNATURE (t)) + CLASSTYPE_NON_AGGREGATE (t) + = ! aggregate || has_virtual || TYPE_HAS_CONSTRUCTOR (t); /* ARM $12.1: A default constructor will be generated for a class X only if no constructor has been declared for class X. So we @@ -3357,8 +3360,7 @@ finish_struct (t, list_of_fieldlists, wa TYPE_HAS_REAL_ASSIGNMENT (t) |= TYPE_HAS_ASSIGNMENT (t); TYPE_HAS_REAL_ASSIGN_REF (t) |= TYPE_HAS_ASSIGN_REF (t); TYPE_HAS_COMPLEX_ASSIGN_REF (t) - |= (TYPE_HAS_ASSIGN_REF (t) || TYPE_USES_VIRTUAL_BASECLASSES (t) - || has_virtual || first_vfn_base_index >= 0); + |= TYPE_HAS_ASSIGN_REF (t) || TYPE_USES_VIRTUAL_BASECLASSES (t); if (! TYPE_HAS_ASSIGN_REF (t) && ! cant_synth_asn_ref && ! IS_SIGNATURE (t)) @@ -3374,7 +3376,6 @@ finish_struct (t, list_of_fieldlists, wa method_vec = finish_struct_methods (t, fn_fields, nonprivate_method); if (TYPE_HAS_CONSTRUCTOR (t) - && ! CLASSTYPE_DECLARED_EXCEPTION (t) && CLASSTYPE_FRIEND_CLASSES (t) == NULL_TREE && DECL_FRIENDLIST (TYPE_NAME (t)) == NULL_TREE) { @@ -3483,9 +3484,10 @@ finish_struct (t, list_of_fieldlists, wa DECL_FIELD_CONTEXT (vfield) = t; DECL_CLASS_CONTEXT (vfield) = t; DECL_FCONTEXT (vfield) = t; + DECL_SAVED_INSNS (vfield) = NULL_RTX; DECL_FIELD_SIZE (vfield) = 0; DECL_ALIGN (vfield) = TYPE_ALIGN (ptr_type_node); - if (CLASSTYPE_DOSSIER (t)) + if (CLASSTYPE_RTTI (t)) { /* vfield is always first entry in structure. */ TREE_CHAIN (vfield) = fields; @@ -3554,47 +3556,6 @@ finish_struct (t, list_of_fieldlists, wa TYPE_ALIGN (t) = round_up_size; /* Pass layout information about base classes to layout_type, if any. */ - - { - tree field; - for (field = TYPE_FIELDS (t); field; field = TREE_CHAIN (field)) - { - if (TREE_STATIC (field)) - continue; - if (TREE_CODE (field) != FIELD_DECL) - continue; - - /* If this field is an anonymous union, - give each union-member the same position as the union has. - - ??? This is a real kludge because it makes the structure - of the types look strange. This feature is only used by - C++, which should have build_component_ref build two - COMPONENT_REF operations, one for the union and one for - the inner field. We set the offset of this field to zero - so that either the old or the correct method will work. - Setting DECL_FIELD_CONTEXT is wrong unless the inner fields are - moved into the type of this field, but nothing seems to break - by doing this. */ - - if (DECL_NAME (field) == NULL_TREE - && TREE_CODE (TREE_TYPE (field)) == UNION_TYPE) - { - tree uelt = TYPE_FIELDS (TREE_TYPE (field)); - for (; uelt; uelt = TREE_CHAIN (uelt)) - { - if (TREE_CODE (uelt) != FIELD_DECL) - continue; - - DECL_FIELD_CONTEXT (uelt) = DECL_FIELD_CONTEXT (field); - DECL_FIELD_BITPOS (uelt) = DECL_FIELD_BITPOS (field); - } - - DECL_FIELD_BITPOS (field) = integer_zero_node; - } - } - } - if (n_baseclasses) { tree pseudo_basetype = TREE_TYPE (base_layout_decl); @@ -3643,6 +3604,13 @@ finish_struct (t, list_of_fieldlists, wa if (TREE_CODE (uelt) != FIELD_DECL) continue; + if (TREE_PRIVATE (uelt)) + cp_pedwarn_at ("private member `%#D' in anonymous union", + uelt); + else if (TREE_PROTECTED (uelt)) + cp_pedwarn_at ("protected member `%#D' in anonymous union", + uelt); + DECL_FIELD_CONTEXT (uelt) = DECL_FIELD_CONTEXT (field); DECL_FIELD_BITPOS (uelt) = DECL_FIELD_BITPOS (field); } @@ -3680,14 +3648,16 @@ finish_struct (t, list_of_fieldlists, wa vbases = CLASSTYPE_VBASECLASSES (t); CLASSTYPE_N_VBASECLASSES (t) = list_length (vbases); + /* The rtti code should do this. (mrs) */ +#if 0 while (vbases) { - /* The rtti code should do this. (mrs) */ - /* Update dossier info with offsets for virtual baseclasses. */ - if (flag_dossier && ! BINFO_NEW_VTABLE_MARKED (vbases)) + /* Update rtti info with offsets for virtual baseclasses. */ + if (flag_rtti && ! BINFO_NEW_VTABLE_MARKED (vbases)) prepare_fresh_vtable (vbases, t); vbases = TREE_CHAIN (vbases); } +#endif { /* Now fixup overrides of all functions in vtables from all @@ -3717,11 +3687,11 @@ finish_struct (t, list_of_fieldlists, wa vbases = CLASSTYPE_VBASECLASSES (t); while (vbases) { - /* We might be able to shorten the ammount of work we do by + /* We might be able to shorten the amount of work we do by only doing this for vtables that come from virtual bases that have differing offsets, but don't want to miss any entries. */ - fixup_vtable_deltas (vbases, t); + fixup_vtable_deltas (vbases, 1, t); vbases = TREE_CHAIN (vbases); } } @@ -3750,6 +3720,15 @@ finish_struct (t, list_of_fieldlists, wa #ifdef NOTQUITE cp_warning ("Doing hard virtuals for %T...", t); #endif + + if (has_virtual > max_has_virtual) + max_has_virtual = has_virtual; + if (max_has_virtual > 0) + TYPE_VIRTUAL_P (t) = 1; + + if (flag_rtti && TYPE_VIRTUAL_P (t) && !pending_hard_virtuals) + modify_all_vtables (t, NULL_TREE, NULL_TREE); + while (pending_hard_virtuals) { modify_all_vtables (t, @@ -3761,33 +3740,34 @@ finish_struct (t, list_of_fieldlists, wa /* Under our model of GC, every C++ class gets its own virtual function table, at least virtually. */ - if (pending_virtuals || CLASSTYPE_DOSSIER (t)) + if (pending_virtuals || (flag_rtti && TYPE_VIRTUAL_P (t))) { pending_virtuals = nreverse (pending_virtuals); /* We must enter these virtuals into the table. */ if (first_vfn_base_index < 0) { - if (flag_dossier) - pending_virtuals = tree_cons (NULL_TREE, - build_vtable_entry (integer_zero_node, - build_t_desc (t, 0)), - pending_virtuals); - pending_virtuals = tree_cons (NULL_TREE, the_null_vtable_entry, - pending_virtuals); + /* The first slot is for the rtti offset. */ + pending_virtuals = tree_cons (NULL_TREE, NULL_TREE, pending_virtuals); + + /* The second slot is for the tdesc pointer when thunks are used. */ + if (flag_vtable_thunks) + pending_virtuals = tree_cons (NULL_TREE, NULL_TREE, pending_virtuals); + + set_rtti_entry (pending_virtuals, integer_zero_node, t); build_vtable (NULL_TREE, t); } else { + tree offset; /* Here we know enough to change the type of our virtual function table, but we will wait until later this function. */ if (! BINFO_NEW_VTABLE_MARKED (TYPE_BINFO (t))) build_vtable (TREE_VEC_ELT (TYPE_BINFO_BASETYPES (t), first_vfn_base_index), t); - /* Update the dossier pointer for this class. */ - if (flag_dossier) - TREE_VALUE (TREE_CHAIN (TYPE_BINFO_VIRTUALS (t))) - = build_vtable_entry (integer_zero_node, build_t_desc (t, 0)); + offset = get_derived_offset (TYPE_BINFO (t), NULL_TREE); + offset = size_binop (MINUS_EXPR, integer_zero_node, offset); + set_rtti_entry (TYPE_BINFO_VIRTUALS (t), offset, t); } /* If this type has basetypes with constructors, then those @@ -3815,11 +3795,8 @@ finish_struct (t, list_of_fieldlists, wa CLASSTYPE_NEEDS_VIRTUAL_REINIT (t) = 1; } - if (has_virtual > max_has_virtual) - max_has_virtual = has_virtual; if (max_has_virtual || first_vfn_base_index >= 0) { - TYPE_VIRTUAL_P (t) = 1; CLASSTYPE_VSIZE (t) = has_virtual; if (first_vfn_base_index >= 0) { @@ -3873,6 +3850,7 @@ finish_struct (t, list_of_fieldlists, wa if (TREE_TYPE (TYPE_BINFO_VTABLE (t)) != atype) { TREE_TYPE (TYPE_BINFO_VTABLE (t)) = atype; + DECL_SIZE (TYPE_BINFO_VTABLE (t)) = 0; layout_decl (TYPE_BINFO_VTABLE (t), 0); /* At one time the vtable info was grabbed 2 words at a time. This fails on sparc unless you have 8-byte alignment. (tiemann) */ @@ -3887,29 +3865,10 @@ finish_struct (t, list_of_fieldlists, wa finish_struct_bits (t, max_has_virtual); - /* Promote each bit-field's type to int if it is narrower than that. - There's more: complete the rtl for any static member objects which - is of the same type we're working on. */ + /* Complete the rtl for any static member objects of the type we're + working on. */ for (x = fields; x; x = TREE_CHAIN (x)) { - if (DECL_BIT_FIELD (x) - && (C_PROMOTING_INTEGER_TYPE_P (TREE_TYPE (x)) - || DECL_FIELD_SIZE (x) < TYPE_PRECISION (integer_type_node))) - { - tree type = TREE_TYPE (x); - - /* Preserve unsignedness if traditional or if not really getting - any wider. */ - if (TREE_UNSIGNED (type) - && (flag_traditional - || - (TYPE_PRECISION (type) == TYPE_PRECISION (integer_type_node) - && DECL_FIELD_SIZE (x) == TYPE_PRECISION (integer_type_node)))) - TREE_TYPE (x) = unsigned_type_node; - else - TREE_TYPE (x) = integer_type_node; - } - if (TREE_CODE (x) == VAR_DECL && TREE_STATIC (x) && TREE_TYPE (x) == t) { @@ -3926,12 +3885,15 @@ finish_struct (t, list_of_fieldlists, wa last_x = tree_last (TYPE_FIELDS (t)); while (x) { -#if 0 /* What's wrong with using the decl the type already has? */ - tree tag = build_decl (TYPE_DECL, TREE_PURPOSE (x), TREE_VALUE (x)); - DECL_CONTEXT (tag) = t; -#else tree tag = TYPE_NAME (TREE_VALUE (x)); -#endif + + /* Check to see if it is already there. This will be the case if + was do enum { red; } color; */ + if (chain_member (tag, TYPE_FIELDS (t))) + { + x = TREE_CHAIN (x); + continue; + } #ifdef DWARF_DEBUGGING_INFO if (write_symbols == DWARF_DEBUG) @@ -3970,7 +3932,7 @@ finish_struct (t, list_of_fieldlists, wa else if (TYPE_NEEDS_CONSTRUCTING (t)) build_class_init_list (t); - if (! CLASSTYPE_DECLARED_EXCEPTION (t) && ! IS_SIGNATURE (t)) + if (! IS_SIGNATURE (t)) embrace_waiting_friends (t); /* Write out inline function definitions. */ @@ -3979,13 +3941,6 @@ finish_struct (t, list_of_fieldlists, wa if (CLASSTYPE_VSIZE (t) != 0) { - if ((flag_this_is_variable & 1) == 0) - { - tree vtbl_ptr = build_decl (VAR_DECL, get_identifier (VPTR_NAME), - TREE_TYPE (vfield)); - DECL_REGISTER (vtbl_ptr) = 1; - CLASSTYPE_VTBL_PTR (t) = vtbl_ptr; - } #if 0 /* This is now done above. */ if (DECL_FIELD_CONTEXT (vfield) != t) @@ -4021,33 +3976,7 @@ finish_struct (t, list_of_fieldlists, wa the base types we marked. */ finish_vtbls (TYPE_BINFO (t), 1, t); TYPE_BEING_DEFINED (t) = 0; - - if (flag_dossier && CLASSTYPE_VTABLE_NEEDS_WRITING (t)) - { - tree variants; - tree tdecl; - - /* Now instantiate its type descriptors. */ - tdecl = TREE_OPERAND (build_t_desc (t, 1), 0); - variants = TYPE_POINTER_TO (t); - build_type_variant (variants, 1, 0); - while (variants) - { - build_t_desc (variants, 1); - variants = TYPE_NEXT_VARIANT (variants); - } - variants = build_reference_type (t); - build_type_variant (variants, 1, 0); - while (variants) - { - build_t_desc (variants, 1); - variants = TYPE_NEXT_VARIANT (variants); - } - DECL_CONTEXT (tdecl) = t; - } - /* Still need to instantiate this C struct's type descriptor. */ - else if (flag_dossier && ! CLASSTYPE_DOSSIER (t)) - build_t_desc (t, 1); + hack_incomplete_structures (t); #if 0 if (TYPE_NAME (t) && TYPE_IDENTIFIER (t)) @@ -4058,8 +3987,6 @@ finish_struct (t, list_of_fieldlists, wa else error ("trying to finish struct, but kicked out due to previous parse errors."); - hack_incomplete_structures (t); - resume_momentary (old); if (flag_cadillac) @@ -4107,10 +4034,150 @@ finish_struct (t, list_of_fieldlists, wa } /* Finish debugging output for this type. */ - rest_of_type_compilation (t, global_bindings_p ()); + rest_of_type_compilation (t, toplevel_bindings_p ()); return t; } + +tree +finish_struct (t, list_of_fieldlists, warn_anon) + tree t; + tree list_of_fieldlists; + int warn_anon; +{ + tree fields = NULL_TREE, fn_fields, *tail; + tree *tail_user_methods = &CLASSTYPE_METHODS (t); + tree name = TYPE_NAME (t); + tree x, last_x = NULL_TREE; + enum access_type access; + + if (TREE_CODE (name) == TYPE_DECL) + { + extern int lineno; + + DECL_SOURCE_FILE (name) = input_filename; + /* For TYPE_DECL that are not typedefs (those marked with a line + number of zero, we don't want to mark them as real typedefs. + If this fails one needs to make sure real typedefs have a + previous line number, even if it is wrong, that way the below + will fill in the right line number. (mrs) */ + if (DECL_SOURCE_LINE (name)) + DECL_SOURCE_LINE (name) = lineno; + CLASSTYPE_SOURCE_LINE (t) = lineno; + name = DECL_NAME (name); + } + + /* Append the fields we need for constructing signature tables. */ + if (IS_SIGNATURE (t)) + append_signature_fields (list_of_fieldlists); + + tail = &fn_fields; + if (last_x && list_of_fieldlists) + TREE_CHAIN (last_x) = TREE_VALUE (list_of_fieldlists); + + /* For signatures, we made all methods `public' in the parser and + reported an error if a access specifier was used. */ + if (CLASSTYPE_DECLARED_CLASS (t) == 0) + { + if (list_of_fieldlists + && TREE_PURPOSE (list_of_fieldlists) == (tree)access_default) + TREE_PURPOSE (list_of_fieldlists) = (tree)access_public; + } + else if (list_of_fieldlists + && TREE_PURPOSE (list_of_fieldlists) == (tree)access_default) + TREE_PURPOSE (list_of_fieldlists) = (tree)access_private; + + while (list_of_fieldlists) + { + access = (enum access_type)TREE_PURPOSE (list_of_fieldlists); + + for (x = TREE_VALUE (list_of_fieldlists); x; x = TREE_CHAIN (x)) + { + TREE_PRIVATE (x) = access == access_private; + TREE_PROTECTED (x) = access == access_protected; + + /* Check for inconsistent use of this name in the class body. + Enums, types and static vars have already been checked. */ + if (TREE_CODE (x) != TYPE_DECL + && TREE_CODE (x) != CONST_DECL && TREE_CODE (x) != VAR_DECL) + { + tree name = DECL_NAME (x); + tree icv; + + /* Don't get confused by access decls. */ + if (name && TREE_CODE (name) == IDENTIFIER_NODE) + icv = IDENTIFIER_CLASS_VALUE (name); + else + icv = NULL_TREE; + + if (icv + /* Don't complain about constructors. */ + && name != constructor_name (current_class_type) + /* Or inherited names. */ + && id_in_current_class (name) + /* Or shadowed tags. */ + && !(TREE_CODE (icv) == TYPE_DECL + && DECL_CONTEXT (icv) == t)) + { + cp_error_at ("declaration of identifier `%D' as `%+#D'", + name, x); + cp_error_at ("conflicts with other use in class as `%#D'", + icv); + } + } + + if (TREE_CODE (x) == FUNCTION_DECL) + { + if (last_x) + TREE_CHAIN (last_x) = TREE_CHAIN (x); + /* Link x onto end of fn_fields and CLASSTYPE_METHODS. */ + *tail = x; + tail = &TREE_CHAIN (x); + *tail_user_methods = x; + tail_user_methods = &DECL_NEXT_METHOD (x); + continue; + } + +#if 0 + /* Handle access declarations. */ + if (DECL_NAME (x) && TREE_CODE (DECL_NAME (x)) == SCOPE_REF) + { + tree n = DECL_NAME (x); + x = build_decl + (USING_DECL, DECL_NAME (TREE_OPERAND (n, 1)), TREE_TYPE (x)); + DECL_RESULT (x) = n; + } +#endif + + if (! fields) + fields = x; + last_x = x; + } + list_of_fieldlists = TREE_CHAIN (list_of_fieldlists); + /* link the tail while we have it! */ + if (last_x) + { + TREE_CHAIN (last_x) = NULL_TREE; + + if (list_of_fieldlists + && TREE_VALUE (list_of_fieldlists) + && TREE_CODE (TREE_VALUE (list_of_fieldlists)) != FUNCTION_DECL) + TREE_CHAIN (last_x) = TREE_VALUE (list_of_fieldlists); + } + } + + *tail = NULL_TREE; + *tail_user_methods = NULL_TREE; + TYPE_FIELDS (t) = fields; + + if (0 && processing_template_defn) + { + CLASSTYPE_METHOD_VEC (t) = finish_struct_methods (t, fn_fields, 1); + return t; + } + else + return finish_struct_1 (t, warn_anon); +} /* Return non-zero if the effective type of INSTANCE is static. Used to determine whether the virtual function table is needed @@ -4341,7 +4408,7 @@ pushclass (type, modify) { tree item; - /* Hooray, our cacheing was successful, let's just install the + /* Hooray, we successfully cached; let's just install the cached class_shadowed list, and walk through it to get the IDENTIFIER_TYPE_VALUEs correct. */ set_class_shadows (previous_class_values); @@ -4433,44 +4500,6 @@ popclass (modify) current_class_type = *--current_class_stack; current_class_name = *--current_class_stack; - if (current_class_type) - { - if (CLASSTYPE_VTBL_PTR (current_class_type)) - { - current_vtable_decl - = lookup_name (DECL_NAME (CLASSTYPE_VTBL_PTR (current_class_type)), - 0); - if (current_vtable_decl) - current_vtable_decl = build_indirect_ref (current_vtable_decl, - NULL_PTR); - } - current_class_decl = lookup_name (this_identifier, 0); - if (current_class_decl) - { - if (TREE_CODE (TREE_TYPE (current_class_decl)) == POINTER_TYPE) - { - tree temp; - /* Can't call build_indirect_ref here, because it has special - logic to return C_C_D given this argument. */ - C_C_D = build1 (INDIRECT_REF, current_class_type, current_class_decl); - temp = TREE_TYPE (TREE_TYPE (current_class_decl)); - TREE_READONLY (C_C_D) = TYPE_READONLY (temp); - TREE_SIDE_EFFECTS (C_C_D) = TYPE_VOLATILE (temp); - TREE_THIS_VOLATILE (C_C_D) = TYPE_VOLATILE (temp); - } - else - C_C_D = current_class_decl; - } - else - C_C_D = NULL_TREE; - } - else - { - current_class_decl = NULL_TREE; - current_vtable_decl = NULL_TREE; - C_C_D = NULL_TREE; - } - pop_memoized_context (modify); ret: @@ -4491,7 +4520,7 @@ push_nested_class (type, modify) { tree context; - if (type == error_mark_node || ! IS_AGGR_TYPE (type)) + if (type == NULL_TREE || type == error_mark_node || ! IS_AGGR_TYPE (type)) return; context = DECL_CONTEXT (TYPE_NAME (type)); @@ -4654,7 +4683,7 @@ instantiate_type (lhstype, rhs, complain /* First look for an exact match */ while (field && TREE_TYPE (field) != lhstype) - field = TREE_CHAIN (field); + field = DECL_CHAIN (field); if (field) { TREE_OPERAND (rhs, 1) = field; @@ -4664,13 +4693,13 @@ instantiate_type (lhstype, rhs, complain /* No exact match found, look for a compatible function. */ field = TREE_OPERAND (rhs, 1); while (field && ! comptypes (lhstype, TREE_TYPE (field), 0)) - field = TREE_CHAIN (field); + field = DECL_CHAIN (field); if (field) { TREE_OPERAND (rhs, 1) = field; - field = TREE_CHAIN (field); + field = DECL_CHAIN (field); while (field && ! comptypes (lhstype, TREE_TYPE (field), 0)) - field = TREE_CHAIN (field); + field = DECL_CHAIN (field); if (field) { if (complain) @@ -4702,6 +4731,9 @@ instantiate_type (lhstype, rhs, complain functions or member functions. May have to undo what `default_conversion' might do to lhstype. */ + if (TYPE_PTRMEMFUNC_P (lhstype)) + lhstype = TYPE_PTRMEMFUNC_FN_TYPE (lhstype); + if (TREE_CODE (lhstype) == POINTER_TYPE) if (TREE_CODE (TREE_TYPE (lhstype)) == FUNCTION_TYPE || TREE_CODE (TREE_TYPE (lhstype)) == METHOD_TYPE) @@ -4738,7 +4770,7 @@ instantiate_type (lhstype, rhs, complain { int n = TREE_VEC_LENGTH (DECL_TEMPLATE_PARMS (elem)); tree *t = (tree *) alloca (sizeof (tree) * n); - int i, d; + int i, d = 0; i = type_unification (DECL_TEMPLATE_PARMS (elem), t, TYPE_ARG_TYPES (TREE_TYPE (elem)), TYPE_ARG_TYPES (lhstype), &d, 0); @@ -4762,14 +4794,15 @@ instantiate_type (lhstype, rhs, complain /* No match found, look for a compatible function. */ elem = get_first_fn (rhs); - while (elem && ! comp_target_types (lhstype, TREE_TYPE (elem), 1)) + while (elem && comp_target_types (lhstype, + TREE_TYPE (elem), 1) <= 0) elem = DECL_CHAIN (elem); if (elem) { tree save_elem = elem; elem = DECL_CHAIN (elem); - while (elem && ! comp_target_types (lhstype, TREE_TYPE (elem), - 0)) + while (elem && comp_target_types (lhstype, + TREE_TYPE (elem), 0) <= 0) elem = DECL_CHAIN (elem); if (elem) { @@ -4817,7 +4850,7 @@ instantiate_type (lhstype, rhs, complain if (comptypes (lhstype, TREE_TYPE (elem), 1)) return elem; else - elem = TREE_CHAIN (elem); + elem = DECL_CHAIN (elem); } /* No exact match found, look for a compatible method. */ @@ -4825,14 +4858,16 @@ instantiate_type (lhstype, rhs, complain baselink = next_baselink (baselink)) { elem = TREE_VALUE (baselink); - while (elem && ! comp_target_types (lhstype, TREE_TYPE (elem), 1)) - elem = TREE_CHAIN (elem); + while (elem && comp_target_types (lhstype, + TREE_TYPE (elem), 1) <= 0) + elem = DECL_CHAIN (elem); if (elem) { tree save_elem = elem; - elem = TREE_CHAIN (elem); - while (elem && ! comp_target_types (lhstype, TREE_TYPE (elem), 0)) - elem = TREE_CHAIN (elem); + elem = DECL_CHAIN (elem); + while (elem && comp_target_types (lhstype, + TREE_TYPE (elem), 0) <= 0) + elem = DECL_CHAIN (elem); if (elem) { if (complain) @@ -4857,8 +4892,7 @@ instantiate_type (lhstype, rhs, complain #endif } if (complain) - error ("no static member functions named `%s'", - IDENTIFIER_POINTER (name)); + cp_error ("no compatible member functions named `%D'", name); return error_mark_node; } @@ -4916,7 +4950,7 @@ instantiate_type (lhstype, rhs, complain case POSTINCREMENT_EXPR: case POSTDECREMENT_EXPR: if (complain) - error ("illegal operation on uninstantiated type"); + error ("invalid operation on uninstantiated type"); return error_mark_node; case TRUTH_AND_EXPR: