diff options
Diffstat (limited to 'gnu/usr.bin/cc/cc1plus/class.c')
-rw-r--r-- | gnu/usr.bin/cc/cc1plus/class.c | 294 |
1 files changed, 203 insertions, 91 deletions
diff --git a/gnu/usr.bin/cc/cc1plus/class.c b/gnu/usr.bin/cc/cc1plus/class.c index e715c89..a3bcb26 100644 --- a/gnu/usr.bin/cc/cc1plus/class.c +++ b/gnu/usr.bin/cc/cc1plus/class.c @@ -942,7 +942,7 @@ add_method (type, fields, method) * sizeof (char *) + len * sizeof (tree)); tmp_vec = (tree) obstack_base (ob); - bcopy (method_vec, tmp_vec, + bcopy ((char *) method_vec, (char *) tmp_vec, (sizeof (struct tree_common) + tree_code_length[(int) TREE_VEC] * sizeof (char *) + (len-1) * sizeof (tree))); @@ -992,20 +992,18 @@ add_method (type, fields, method) not duplicates, they are just anonymous fields. This happens when we have unnamed bitfields, for example. */ static tree -delete_duplicate_fields_1 (field, field_ptr, fields) - tree field, *field_ptr, fields; +delete_duplicate_fields_1 (field, fields) + tree field, fields; { tree x; - tree prev = field_ptr ? *field_ptr : 0; + tree prev = 0; if (DECL_NAME (field) == 0) { if (TREE_CODE (TREE_TYPE (field)) != UNION_TYPE) return fields; for (x = TYPE_FIELDS (TREE_TYPE (field)); x; x = TREE_CHAIN (x)) - fields = delete_duplicate_fields_1 (x, field_ptr, fields); - if (prev) - TREE_CHAIN (prev) = fields; + fields = delete_duplicate_fields_1 (x, fields); return fields; } else @@ -1017,7 +1015,7 @@ delete_duplicate_fields_1 (field, field_ptr, fields) if (TREE_CODE (TREE_TYPE (x)) != UNION_TYPE) continue; TYPE_FIELDS (TREE_TYPE (x)) - = delete_duplicate_fields_1 (field, (tree *)0, TYPE_FIELDS (TREE_TYPE (x))); + = delete_duplicate_fields_1 (field, TYPE_FIELDS (TREE_TYPE (x))); if (TYPE_FIELDS (TREE_TYPE (x)) == 0) { if (prev == 0) @@ -1039,7 +1037,7 @@ delete_duplicate_fields_1 (field, field_ptr, fields) x); else if (TREE_CODE (field) == TYPE_DECL && TREE_CODE (x) == TYPE_DECL) - cp_error_at ("duplicate class scope type `%D'", x); + cp_error_at ("duplicate nested type `%D'", x); else if (TREE_CODE (field) == TYPE_DECL || TREE_CODE (x) == TYPE_DECL) cp_error_at ("duplicate field `%D' (as type and non-type)", @@ -1063,7 +1061,7 @@ delete_duplicate_fields (fields) { tree x; for (x = fields; x && TREE_CHAIN (x); x = TREE_CHAIN (x)) - TREE_CHAIN (x) = delete_duplicate_fields_1 (x, &x, TREE_CHAIN (x)); + TREE_CHAIN (x) = delete_duplicate_fields_1 (x, TREE_CHAIN (x)); } /* Change the access of FDECL to ACCESS in T. @@ -1121,10 +1119,14 @@ get_vfield_offset (binfo) BINFO_OFFSET (binfo)); } -/* Get the offset to the start of the original binfo that we derived this - binfo from. */ -tree get_derived_offset (binfo) - tree binfo; +/* Get the offset to the start of the original binfo that we derived + this binfo from. If we find TYPE first, return the offset only + that far. The shortened search is useful because the this pointer + on method calling is expected to point to a DECL_CONTEXT (fndecl) + object, and not a baseclass of it. */ +static tree +get_derived_offset (binfo, type) + tree binfo, type; { tree offset1 = get_vfield_offset (TYPE_BINFO (BINFO_TYPE (binfo))); tree offset2; @@ -1133,6 +1135,8 @@ tree get_derived_offset (binfo) && (i=CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (binfo))) != -1) { tree binfos = BINFO_BASETYPES (binfo); + if (BINFO_TYPE (binfo) == type) + break; binfo = TREE_VEC_ELT (binfos, i); } offset2 = get_vfield_offset (TYPE_BINFO (BINFO_TYPE (binfo))); @@ -1340,7 +1344,7 @@ finish_base_struct (t, b, t_binfo) tree binfos = BINFO_BASETYPES (t_binfo); int i, n_baseclasses = binfos ? TREE_VEC_LENGTH (binfos) : 0; int first_vfn_base_index = -1; - bzero (b, sizeof (struct base_info)); + bzero ((char *) b, sizeof (struct base_info)); for (i = 0; i < n_baseclasses; i++) { @@ -1682,8 +1686,8 @@ finish_struct_bits (t, max_has_virtual) tree *tmp; int i; - bzero (first_conversions, sizeof (first_conversions)); - bzero (last_conversions, sizeof (last_conversions)); + 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) { @@ -1830,8 +1834,7 @@ finish_struct_methods (t, fn_fields, nonprivate_method) { tree parmtype = TREE_VALUE (FUNCTION_ARG_CHAIN (fn_fields)); - if (TREE_CODE (parmtype) == REFERENCE_TYPE - && TYPE_MAIN_VARIANT (TREE_TYPE (parmtype)) == t) + if (copy_assignment_arg_p (parmtype, DECL_VIRTUAL_P (fn_fields))) { if (TREE_PROTECTED (fn_fields)) TYPE_HAS_NONPUBLIC_ASSIGN_REF (t) = 1; @@ -1938,8 +1941,8 @@ finish_struct_methods (t, fn_fields, nonprivate_method) && CLASSTYPE_FRIEND_CLASSES (t) == NULL_TREE && DECL_FRIENDLIST (TYPE_NAME (t)) == NULL_TREE && warn_ctor_dtor_privacy) - warning ("class `%s' only defines a private destructor and has no friends", - TYPE_NAME_STRING (t)); + cp_warning ("`%#T' only defines a private destructor and has no friends", + t); break; } } @@ -2060,7 +2063,7 @@ duplicate_tag_error (t) int interface_only = CLASSTYPE_INTERFACE_ONLY (t); int interface_unknown = CLASSTYPE_INTERFACE_UNKNOWN (t); - bzero (TYPE_LANG_SPECIFIC (t), sizeof (struct lang_type)); + bzero ((char *) TYPE_LANG_SPECIFIC (t), sizeof (struct lang_type)); BINFO_BASETYPES(binfo) = NULL_TREE; CLASSTYPE_AS_LIST (t) = as_list; @@ -2151,6 +2154,86 @@ overrides (fndecl, base_fndecl) return 0; } +static tree +get_class_offset_1 (parent, binfo, context, t, fndecl) + tree parent, binfo, context, t, fndecl; +{ + tree binfos = BINFO_BASETYPES (binfo); + int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0; + tree rval = NULL_TREE; + + if (binfo == parent) + return error_mark_node; + + for (i = 0; i < n_baselinks; i++) + { + tree base_binfo = TREE_VEC_ELT (binfos, i); + tree nrval; + + if (TREE_VIA_VIRTUAL (base_binfo)) + base_binfo = binfo_member (BINFO_TYPE (base_binfo), + CLASSTYPE_VBASECLASSES (t)); + nrval = get_class_offset_1 (parent, base_binfo, context, t, fndecl); + /* See if we have a new value */ + if (nrval && (nrval != error_mark_node || rval==0)) + { + /* Only compare if we have two offsets */ + if (rval && rval != error_mark_node + && ! tree_int_cst_equal (nrval, rval)) + { + /* Only give error if the two offsets are different */ + error ("every virtual function must have a unique final overrider"); + cp_error (" found two (or more) `%T' class subobjects in `%T'", context, t); + cp_error (" with virtual `%D' from virtual base class", fndecl); + return rval; + } + rval = nrval; + } + + if (rval && BINFO_TYPE (binfo) == context) + { + my_friendly_assert (rval == error_mark_node + || tree_int_cst_equal (rval, BINFO_OFFSET (binfo)), 999); + rval = BINFO_OFFSET (binfo); + } + } + return rval; +} + +/* Get the offset to the CONTEXT subobject that is related to the + given BINFO. */ +static tree +get_class_offset (context, t, binfo, fndecl) + tree context, t, binfo, fndecl; +{ + tree first_binfo = binfo; + tree offset; + int i; + + if (context == t) + return integer_zero_node; + + if (BINFO_TYPE (binfo) == context) + return BINFO_OFFSET (binfo); + + /* Check less derived binfos first. */ + while (BINFO_BASETYPES (binfo) + && (i=CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (binfo))) != -1) + { + tree binfos = BINFO_BASETYPES (binfo); + binfo = TREE_VEC_ELT (binfos, i); + if (BINFO_TYPE (binfo) == context) + return BINFO_OFFSET (binfo); + } + + /* Ok, not found in the less derived binfos, now check the more + derived binfos. */ + offset = get_class_offset_1 (first_binfo, TYPE_BINFO (t), context, t, fndecl); + if (offset==0 || TREE_CODE (offset) != INTEGER_CST) + my_friendly_abort (999); /* we have to find it. */ + return offset; +} + static void modify_one_vtable (binfo, t, fndecl, pfn) tree binfo, t, fndecl, pfn; @@ -2174,16 +2257,7 @@ modify_one_vtable (binfo, t, fndecl, pfn) tree vfield = CLASSTYPE_VFIELD (t); tree this_offset; - offset = integer_zero_node; - if (context != t && TYPE_USES_COMPLEX_INHERITANCE (t)) - { - offset = virtual_offset (context, CLASSTYPE_VBASECLASSES (t), offset); - if (offset == NULL_TREE) - { - tree binfo = get_binfo (context, t, 0); - offset = BINFO_OFFSET (binfo); - } - } + offset = get_class_offset (context, t, binfo, fndecl); /* Find the right offset for the this pointer based on the base class we just found. We have to take into @@ -2193,7 +2267,7 @@ modify_one_vtable (binfo, t, fndecl, pfn) Also, we want just the delta bewteen the most base class that we derived this vfield from and us. */ base_offset = size_binop (PLUS_EXPR, - get_derived_offset (binfo), + get_derived_offset (binfo, DECL_CONTEXT (current_fndecl)), BINFO_OFFSET (binfo)); this_offset = size_binop (MINUS_EXPR, offset, base_offset); @@ -2288,16 +2362,7 @@ fixup_vtable_deltas (binfo, t) tree vfield = CLASSTYPE_VFIELD (t); tree this_offset; - offset = integer_zero_node; - if (context != t && TYPE_USES_COMPLEX_INHERITANCE (t)) - { - offset = virtual_offset (context, CLASSTYPE_VBASECLASSES (t), offset); - if (offset == NULL_TREE) - { - tree binfo = get_binfo (context, t, 0); - offset = BINFO_OFFSET (binfo); - } - } + offset = get_class_offset (context, t, binfo, fndecl); /* Find the right offset for the this pointer based on the base class we just found. We have to take into @@ -2307,7 +2372,7 @@ fixup_vtable_deltas (binfo, t) Also, we want just the delta bewteen the most base class that we derived this vfield from and us. */ base_offset = size_binop (PLUS_EXPR, - get_derived_offset (binfo), + get_derived_offset (binfo, DECL_CONTEXT (fndecl)), BINFO_OFFSET (binfo)); this_offset = size_binop (MINUS_EXPR, offset, base_offset); @@ -2684,6 +2749,7 @@ finish_struct (t, list_of_fieldlists, warn_anon) 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); } @@ -2713,18 +2779,15 @@ finish_struct (t, list_of_fieldlists, warn_anon) TYPE_SIZE (t) = NULL_TREE; CLASSTYPE_GOT_SEMICOLON (t) = 0; - /* A signature type will contain the fields of the signature table. - Therefore, it's not only an interface. */ - if (IS_SIGNATURE (t)) - { - CLASSTYPE_INTERFACE_ONLY (t) = 0; - SET_CLASSTYPE_INTERFACE_KNOWN (t); - } - else +#if 0 + /* This is in general too late to do this. I moved the main case up to + left_curly, what else needs to move? */ + if (! IS_SIGNATURE (t)) { - CLASSTYPE_INTERFACE_ONLY (t) = interface_only; - SET_CLASSTYPE_INTERFACE_UNKNOWN_X (t, interface_unknown); + my_friendly_assert (CLASSTYPE_INTERFACE_ONLY (t) == interface_only, 999); + my_friendly_assert (CLASSTYPE_INTERFACE_KNOWN (t) == ! interface_unknown, 999); } +#endif if (flag_dossier) build_t_desc (t, 0); @@ -2787,14 +2850,15 @@ finish_struct (t, list_of_fieldlists, warn_anon) needs_virtual_dtor = 0; } +#if 0 + /* Both of these should be done before now. */ if (write_virtuals == 3 && CLASSTYPE_INTERFACE_KNOWN (t) && ! IS_SIGNATURE (t)) { - CLASSTYPE_INTERFACE_ONLY (t) = interface_only; - CLASSTYPE_VTABLE_NEEDS_WRITING (t) = ! interface_only; + my_friendly_assert (CLASSTYPE_INTERFACE_ONLY (t) == interface_only, 999); + my_friendly_assert (CLASSTYPE_VTABLE_NEEDS_WRITING (t) == ! interface_only, 999); } - else if (IS_SIGNATURE (t)) - CLASSTYPE_VTABLE_NEEDS_WRITING (t) = 0; +#endif /* The three of these are approximations which may later be modified. Needed at this point to make add_virtual_function @@ -2951,6 +3015,9 @@ finish_struct (t, list_of_fieldlists, warn_anon) TREE_TYPE (x) = build_pointer_type (TREE_TYPE (x)); } + if (DECL_NAME (x) == constructor_name (t)) + cant_have_default_ctor = cant_synth_copy_ctor = 1; + if (TREE_TYPE (x) == error_mark_node) continue; @@ -3217,12 +3284,14 @@ finish_struct (t, list_of_fieldlists, warn_anon) CLASSTYPE_REF_FIELDS_NEED_INIT (t) = ref_sans_init; CLASSTYPE_ABSTRACT_VIRTUALS (t) = abstract_virtuals; + /* Synthesize any needed methods. Note that methods will be synthesized + for anonymous unions; grok_x_components undoes that. */ + if (TYPE_NEEDS_DESTRUCTOR (t) && !TYPE_HAS_DESTRUCTOR (t) && !IS_SIGNATURE (t)) { /* Here we must cons up a destructor on the fly. */ - tree dtor = cons_up_default_function (t, name, fields, - needs_virtual_dtor != 0); + tree dtor = cons_up_default_function (t, name, needs_virtual_dtor != 0); /* If we couldn't make it work, then pretend we didn't need it. */ if (dtor == void_type_node) @@ -3251,9 +3320,6 @@ finish_struct (t, list_of_fieldlists, warn_anon) TYPE_NEEDS_DESTRUCTOR (t) |= TYPE_HAS_DESTRUCTOR (t); - /* Synthesize any needed methods. Note that methods will be synthesized - for anonymous unions; grok_x_components undoes that. */ - if (! fn_fields) nonprivate_method = 1; @@ -3271,7 +3337,7 @@ finish_struct (t, list_of_fieldlists, warn_anon) if (! TYPE_HAS_CONSTRUCTOR (t) && ! cant_have_default_ctor && ! IS_SIGNATURE (t)) { - tree default_fn = cons_up_default_function (t, name, fields, 2); + tree default_fn = cons_up_default_function (t, name, 2); TREE_CHAIN (default_fn) = fn_fields; fn_fields = default_fn; } @@ -3282,9 +3348,8 @@ finish_struct (t, list_of_fieldlists, warn_anon) { /* ARM 12.18: You get either X(X&) or X(const X&), but not both. --Chip */ - tree default_fn = - cons_up_default_function (t, name, fields, - cant_have_const_ctor ? 4 : 3); + tree default_fn = cons_up_default_function (t, name, + 3 + cant_have_const_ctor); TREE_CHAIN (default_fn) = fn_fields; fn_fields = default_fn; } @@ -3298,9 +3363,8 @@ finish_struct (t, list_of_fieldlists, warn_anon) if (! TYPE_HAS_ASSIGN_REF (t) && ! cant_synth_asn_ref && ! IS_SIGNATURE (t)) { - tree default_fn = - cons_up_default_function (t, name, fields, - no_const_asn_ref ? 6 : 5); + tree default_fn = cons_up_default_function (t, name, + 5 + no_const_asn_ref); TREE_CHAIN (default_fn) = fn_fields; fn_fields = default_fn; } @@ -3351,7 +3415,7 @@ finish_struct (t, list_of_fieldlists, warn_anon) tree flist = NULL_TREE; tree name; enum access_type access = (enum access_type)TREE_PURPOSE(access_decls); - int i = 0; + int i = TREE_VEC_ELT (method_vec, 0) ? 0 : 1; tree tmp; if (TREE_CODE (fdecl) == TREE_LIST) @@ -3459,6 +3523,27 @@ finish_struct (t, list_of_fieldlists, warn_anon) /* Delete all duplicate fields from the fields */ delete_duplicate_fields (fields); + /* Catch function/field name conflict. We don't need to do this for a + signature, since it can only contain the fields constructed in + append_signature_fields. */ + if (! IS_SIGNATURE (t)) + { + int n_methods = method_vec ? TREE_VEC_LENGTH (method_vec) : 0; + for (x = fields; x; x = TREE_CHAIN (x)) + { + tree name = DECL_NAME (x); + int i = /*TREE_VEC_ELT (method_vec, 0) ? 0 : */ 1; + for (; i < n_methods; ++i) + if (DECL_NAME (TREE_VEC_ELT (method_vec, i)) == name) + { + cp_error_at ("data member `%#D' conflicts with", x); + cp_error_at ("function member `%#D'", + TREE_VEC_ELT (method_vec, i)); + break; + } + } + } + /* Now we have the final fieldlist for the data fields. Record it, then lay out the structure or union (including the fields). */ @@ -3498,6 +3583,9 @@ finish_struct (t, list_of_fieldlists, warn_anon) 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); } @@ -3552,6 +3640,9 @@ finish_struct (t, list_of_fieldlists, warn_anon) 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); } @@ -4634,11 +4725,42 @@ instantiate_type (lhstype, rhs, complain) { elem = get_first_fn (rhs); while (elem) - if (TREE_TYPE (elem) != lhstype) + if (! comptypes (lhstype, TREE_TYPE (elem), 1)) elem = DECL_CHAIN (elem); else return elem; - /* No exact match found, look for a compatible function. */ + + /* No exact match found, look for a compatible template. */ + { + tree save_elem = 0; + for (elem = get_first_fn (rhs); elem; elem = DECL_CHAIN (elem)) + if (TREE_CODE (elem) == TEMPLATE_DECL) + { + int n = TREE_VEC_LENGTH (DECL_TEMPLATE_PARMS (elem)); + tree *t = (tree *) alloca (sizeof (tree) * n); + int i, d; + i = type_unification (DECL_TEMPLATE_PARMS (elem), t, + TYPE_ARG_TYPES (TREE_TYPE (elem)), + TYPE_ARG_TYPES (lhstype), &d, 0); + if (i == 0) + { + if (save_elem) + { + cp_error ("ambiguous template instantiation converting to `%#T'", lhstype); + return error_mark_node; + } + save_elem = instantiate_template (elem, t); + /* Check the return type. */ + if (! comptypes (TREE_TYPE (lhstype), + TREE_TYPE (TREE_TYPE (save_elem)), 1)) + save_elem = 0; + } + } + if (save_elem) + return save_elem; + } + + /* No match found, look for a compatible function. */ elem = get_first_fn (rhs); while (elem && ! comp_target_types (lhstype, TREE_TYPE (elem), 1)) elem = DECL_CHAIN (elem); @@ -4660,18 +4782,6 @@ instantiate_type (lhstype, rhs, complain) } return error_mark_node; } - if (TREE_CODE (save_elem) == TEMPLATE_DECL) - { - int ntparms = TREE_VEC_LENGTH - (DECL_TEMPLATE_PARMS (save_elem)); - tree *targs = (tree *) alloca (sizeof (tree) * ntparms); - int i, dummy; - i = type_unification - (DECL_TEMPLATE_PARMS (save_elem), targs, - TYPE_ARG_TYPES (TREE_TYPE (save_elem)), - TYPE_ARG_TYPES (lhstype), &dummy, 0); - save_elem = instantiate_template (save_elem, targs); - } return save_elem; } if (complain) @@ -4864,12 +4974,14 @@ instantiate_type (lhstype, rhs, complain) } TREE_TYPE (rhs) = lhstype; lhstype = TREE_TYPE (lhstype); - TREE_OPERAND (rhs, 0) - = instantiate_type (lhstype, TREE_OPERAND (rhs, 0), complain); - if (TREE_OPERAND (rhs, 0) == error_mark_node) - return error_mark_node; - - mark_addressable (TREE_OPERAND (rhs, 0)); + { + tree fn = instantiate_type (lhstype, TREE_OPERAND (rhs, 0), complain); + if (fn == error_mark_node) + return error_mark_node; + mark_addressable (fn); + TREE_OPERAND (rhs, 0) = fn; + TREE_CONSTANT (rhs) = staticp (fn); + } return rhs; case ENTRY_VALUE_EXPR: |