diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index e5c87a61800..c93ce695675 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,12 @@ +2004-07-15 Nathan Sidwell + + * decl.c (xref_basetypes): Refactor. + * tree.c (copy_base_binfos): Replace with ... + (copy_binfo): ... this. Deep copy the given binfo, (not the just + bases of the given base). + * cp-tree.h (copy_base_binfo): Remove. + (copy_binfo): Declare. + 2004-07-15 Mark Mitchell * name-lookup.c (set_inherited_value_binding_p): Add class_type diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 95c633a1f42..1e921d823d2 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -4145,7 +4145,8 @@ extern void init_tree (void); extern int pod_type_p (tree); extern int zero_init_p (tree); extern tree canonical_type_variant (tree); -extern tree copy_base_binfos (tree, tree, tree); +extern tree copy_binfo (tree, tree, tree, + tree *, int); extern int member_p (tree); extern cp_lvalue_kind real_lvalue_p (tree); extern int lvalue_or_else (tree, const char *); diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 1c547f641f9..6aac5bae547 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -9024,28 +9024,30 @@ xref_tag_from_type (tree old, tree id, int globalize) return xref_tag (tag_kind, id, globalize, false); } -/* REF is a type (named NAME), for which we have just seen some - baseclasses. BASE_LIST is a list of those baseclasses; the - TREE_PURPOSE is an access_* node, and the TREE_VALUE is the type of - the base-class. Non-NULL TREE_TYPE indicates virtual inheritance. - CODE_TYPE_NODE indicates whether REF is a class, struct, or - union. */ +/* Create the binfo hierarchy for REF with (possibly NULL) base list + BASE_LIST. For each element on BASE_LIST the TREE_PURPOSE is an + access_* node, and the TREE_VALUE is the type of the base-class. + Non-NULL TREE_TYPE indicates virtual inheritance. */ void xref_basetypes (tree ref, tree base_list) { - /* In the declaration `A : X, Y, ... Z' we mark all the types - (A, X, Y, ..., Z) so we can check for duplicates. */ tree *basep; - unsigned max_vbases = 0; + tree binfo; + unsigned max_vbases = 0; /* Maxium direct & indirect virtual bases. */ + unsigned max_bases = 0; /* Maxium direct bases. */ int i; - enum tag_types tag_code; + tree default_access; + tree igo_prev; /* Track Inheritance Graph Order. */ if (ref == error_mark_node) return; - tag_code = TREE_CODE (ref) == UNION_TYPE ? union_type - : (CLASSTYPE_DECLARED_CLASS (ref) ? class_type : record_type); + /* The base of a derived class is private by default, all others are + public. */ + default_access = (TREE_CODE (ref) == RECORD_TYPE + && CLASSTYPE_DECLARED_CLASS (ref) + ? access_private_node : access_public_node); /* First, make sure that any templates in base-classes are instantiated. This ensures that if we call ourselves recursively @@ -9061,169 +9063,138 @@ xref_basetypes (tree ref, tree base_list) /* An incomplete type. Remove it from the list. */ *basep = TREE_CHAIN (*basep); else - basep = &TREE_CHAIN (*basep); + { + max_bases++; + if (TREE_TYPE (*basep)) + max_vbases++; + if (CLASS_TYPE_P (basetype)) + max_vbases += VEC_length (tree, CLASSTYPE_VBASECLASSES (basetype)); + basep = &TREE_CHAIN (*basep); + } } SET_CLASSTYPE_MARKED (ref); - i = list_length (base_list); + /* The binfo slot should be empty, unless this is an (ill-formed) redefinition. */ my_friendly_assert (!TYPE_BINFO (ref) || TYPE_SIZE (ref), 20040706); my_friendly_assert (TYPE_MAIN_VARIANT (ref) == ref, 20040712); - TYPE_BINFO (ref) = make_tree_binfo (BINFO_LANG_SLOTS); - BINFO_OFFSET (TYPE_BINFO (ref)) = size_zero_node; - BINFO_TYPE (TYPE_BINFO (ref)) = ref; - if (i) + binfo = make_tree_binfo (BINFO_LANG_SLOTS); + TYPE_BINFO (ref) = binfo; + BINFO_OFFSET (binfo) = size_zero_node; + BINFO_TYPE (binfo) = ref; + + if (max_bases) { - tree binfo = TYPE_BINFO (ref); - tree binfos = make_tree_vec (i); - tree accesses = make_tree_vec (i); + BINFO_BASE_BINFOS (binfo) = make_tree_vec (max_bases); + BINFO_BASE_ACCESSES (binfo) = make_tree_vec (max_bases); + /* An aggregate cannot have baseclasses. */ + CLASSTYPE_NON_AGGREGATE (ref) = 1; - BINFO_BASE_BINFOS (binfo) = binfos; - BINFO_BASE_ACCESSES (binfo) = accesses; - - for (i = 0; base_list; base_list = TREE_CHAIN (base_list)) - { - tree access = TREE_PURPOSE (base_list); - int via_virtual = TREE_TYPE (base_list) != NULL_TREE; - tree basetype = TREE_VALUE (base_list); - tree base_binfo; - - if (via_virtual) - max_vbases++; - if (access == access_default_node) - /* The base of a derived struct is public by default. */ - access = (tag_code == class_type - ? access_private_node : access_public_node); - - if (basetype && TREE_CODE (basetype) == TYPE_DECL) - basetype = TREE_TYPE (basetype); - if (!basetype - || (TREE_CODE (basetype) != RECORD_TYPE - && TREE_CODE (basetype) != TYPENAME_TYPE - && TREE_CODE (basetype) != TEMPLATE_TYPE_PARM - && TREE_CODE (basetype) != BOUND_TEMPLATE_TEMPLATE_PARM)) - { - error ("base type `%T' fails to be a struct or class type", - basetype); - continue; - } - - if (CLASSTYPE_MARKED (basetype)) - { - if (basetype == ref) - error ("recursive type `%T' undefined", basetype); - else - error ("duplicate base type `%T' invalid", basetype); - continue; - } - - if (TYPE_FOR_JAVA (basetype) - && (current_lang_depth () == 0)) - TYPE_FOR_JAVA (ref) = 1; - - if (CLASS_TYPE_P (basetype) && !dependent_type_p (basetype)) - { - base_binfo = TYPE_BINFO (basetype); - - my_friendly_assert (base_binfo, 20040706); - } - else - { - base_binfo = make_tree_binfo (BINFO_LANG_SLOTS); - - BINFO_TYPE (base_binfo) = basetype; - BINFO_DEPENDENT_BASE_P (base_binfo) = 1; - } - - TREE_VEC_ELT (binfos, i) = base_binfo; - TREE_VEC_ELT (accesses, i) = access; - /* This flag will be in the binfo of the base type, we must - clear it after copying the base binfos. */ - BINFO_VIRTUAL_P (base_binfo) = via_virtual; - - SET_CLASSTYPE_MARKED (basetype); - - /* We are free to modify these bits because they are meaningless - at top level, and BASETYPE is a top-level type. */ - if (via_virtual || TYPE_USES_VIRTUAL_BASECLASSES (basetype)) - { - TYPE_USES_VIRTUAL_BASECLASSES (ref) = 1; - /* Converting to a virtual base class requires looking - up the offset of the virtual base. */ - TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (ref) = 1; - } - - if (CLASS_TYPE_P (basetype)) - { - TYPE_HAS_NEW_OPERATOR (ref) - |= TYPE_HAS_NEW_OPERATOR (basetype); - TYPE_HAS_ARRAY_NEW_OPERATOR (ref) - |= TYPE_HAS_ARRAY_NEW_OPERATOR (basetype); - TYPE_GETS_DELETE (ref) |= TYPE_GETS_DELETE (basetype); - /* If the base-class uses multiple inheritance, so do we. */ - TYPE_USES_MULTIPLE_INHERITANCE (ref) - |= TYPE_USES_MULTIPLE_INHERITANCE (basetype); - /* Likewise, if converting to a base of the base may require - code, then we may need to generate code to convert to a - base as well. */ - TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (ref) - |= TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (basetype); - TYPE_HAS_CONVERSION (ref) |= TYPE_HAS_CONVERSION (basetype); - max_vbases += VEC_length - (tree, CLASSTYPE_VBASECLASSES (basetype)); - } - i++; - } - if (i) - { - TREE_VEC_LENGTH (accesses) = TREE_VEC_LENGTH (binfos) = i; - /* An aggregate cannot have baseclasses. */ - CLASSTYPE_NON_AGGREGATE (ref) = 1; - } - else - BINFO_BASE_ACCESSES (binfo) = BINFO_BASE_BINFOS (binfo) = NULL_TREE; - if (max_vbases) - CLASSTYPE_VBASECLASSES (ref) = VEC_alloc (tree, max_vbases); - - if (i > 1) - { - TYPE_USES_MULTIPLE_INHERITANCE (ref) = 1; - /* If there is more than one non-empty they cannot be at the same - address. */ - TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (ref) = 1; - } - } - - /* Copy the base binfos, collect the virtual bases and set the - inheritance order chain. */ - copy_base_binfos (TYPE_BINFO (ref), ref, NULL_TREE); - - if (TREE_CODE (ref) == UNION_TYPE) - { - if (i) + if (TREE_CODE (ref) == UNION_TYPE) error ("derived union `%T' invalid", ref); } - - if (TYPE_FOR_JAVA (ref)) + + if (max_bases > 1) { - if (TYPE_USES_MULTIPLE_INHERITANCE (ref)) + TYPE_USES_MULTIPLE_INHERITANCE (ref) = 1; + /* If there is more than one non-empty they cannot be at the + same address. */ + TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (ref) = 1; + + if (TYPE_FOR_JAVA (ref)) error ("Java class '%T' cannot have multiple bases", ref); - if (CLASSTYPE_VBASECLASSES (ref)) + } + + if (max_vbases) + { + CLASSTYPE_VBASECLASSES (ref) = VEC_alloc (tree, max_vbases); + TYPE_USES_VIRTUAL_BASECLASSES (ref) = 1; + /* Converting to a virtual base class requires looking up the + offset of the virtual base. */ + TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (ref) = 1; + + if (TYPE_FOR_JAVA (ref)) error ("Java class '%T' cannot have virtual bases", ref); } - /* Unmark all the types. */ - while (i--) + i = 0; + for (igo_prev = binfo; base_list; base_list = TREE_CHAIN (base_list)) { - tree binfo = BINFO_BASE_BINFO (TYPE_BINFO (ref), i); - tree basetype = BINFO_TYPE (binfo); + tree access = TREE_PURPOSE (base_list); + int via_virtual = TREE_TYPE (base_list) != NULL_TREE; + tree basetype = TREE_VALUE (base_list); + tree base_binfo = NULL_TREE; - CLEAR_CLASSTYPE_MARKED (basetype); - if (!BINFO_DEPENDENT_BASE_P (binfo)) - BINFO_VIRTUAL_P (TYPE_BINFO (basetype)) = 0; + if (access == access_default_node) + access = default_access; + + if (TREE_CODE (basetype) == TYPE_DECL) + basetype = TREE_TYPE (basetype); + if (TREE_CODE (basetype) != RECORD_TYPE + && TREE_CODE (basetype) != TYPENAME_TYPE + && TREE_CODE (basetype) != TEMPLATE_TYPE_PARM + && TREE_CODE (basetype) != BOUND_TEMPLATE_TEMPLATE_PARM) + { + error ("base type `%T' fails to be a struct or class type", + basetype); + continue; + } + + if (CLASSTYPE_MARKED (basetype)) + { + if (basetype == ref) + error ("recursive type `%T' undefined", basetype); + else + error ("duplicate base type `%T' invalid", basetype); + continue; + } + SET_CLASSTYPE_MARKED (basetype); + + if (TYPE_FOR_JAVA (basetype) && (current_lang_depth () == 0)) + TYPE_FOR_JAVA (ref) = 1; + + if (CLASS_TYPE_P (basetype) && !dependent_type_p (basetype)) + { + base_binfo = TYPE_BINFO (basetype); + /* The orignal basetype could have been a typedef'd type. */ + basetype = BINFO_TYPE (base_binfo); + + /* Inherit flags from the base. */ + TYPE_HAS_NEW_OPERATOR (ref) + |= TYPE_HAS_NEW_OPERATOR (basetype); + TYPE_HAS_ARRAY_NEW_OPERATOR (ref) + |= TYPE_HAS_ARRAY_NEW_OPERATOR (basetype); + TYPE_GETS_DELETE (ref) |= TYPE_GETS_DELETE (basetype); + TYPE_USES_MULTIPLE_INHERITANCE (ref) + |= TYPE_USES_MULTIPLE_INHERITANCE (basetype); + TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (ref) + |= TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (basetype); + TYPE_HAS_CONVERSION (ref) |= TYPE_HAS_CONVERSION (basetype); + } + + base_binfo = copy_binfo (base_binfo, basetype, ref, + &igo_prev, via_virtual); + if (!BINFO_INHERITANCE_CHAIN (base_binfo)) + BINFO_INHERITANCE_CHAIN (base_binfo) = binfo; + + TREE_VEC_ELT (BINFO_BASE_ACCESSES (binfo), i) = access; + BINFO_BASE_BINFO (binfo, i) = base_binfo; + i++; } + + if (max_bases) + { + /* If any bases were invalid, we will have allocated too many + slots. */ + TREE_VEC_LENGTH (BINFO_BASE_ACCESSES (binfo)) = i; + TREE_VEC_LENGTH (BINFO_BASE_BINFOS (binfo)) = i; + } + + /* Unmark all the types. */ + for (i = 0; i != BINFO_N_BASE_BINFOS (binfo); i++) + CLEAR_CLASSTYPE_MARKED (BINFO_TYPE (BINFO_BASE_BINFO (binfo, i))); CLEAR_CLASSTYPE_MARKED (ref); } diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index 6cb784ad3ba..4321b8a1a72 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -567,85 +567,92 @@ canonical_type_variant (tree t) return cp_build_qualified_type (TYPE_MAIN_VARIANT (t), cp_type_quals (t)); } -/* Makes new binfos for the indirect bases under BINFO. T is the most - derived TYPE. PREV is the previous binfo, whose TREE_CHAIN we make - point to this binfo. We return the last BINFO created. +/* Makes a copy of BINFO and TYPE, which is to be inherited into a + graph dominated by T. If BINFO is NULL, TYPE is a dependent base, + and we do a shallow copy. If BINFO is non-NULL, we do a deep copy. + VIRT indicates whether TYPE is inherited virtually or not. + IGO_PREV points at the previous binfo of the inheritance graph + order chain. The newly copied binfo's TREE_CHAIN forms this + ordering. - The CLASSTYPE_VBASECLASSES vector of T is constructed in the correct - order. + The CLASSTYPE_VBASECLASSES vector of T is constructed in the + correct order. That is in the order the bases themselves should be + constructed in. The BINFO_INHERITANCE of a virtual base class points to the binfo - og the most derived type. - - The binfo's TREE_CHAIN is set to inheritance graph order, but bases - for non-class types are not included (i.e. those which are - dependent bases in non-instantiated templates). */ + of the most derived type. ??? We could probably change this so that + BINFO_INHERITANCE becomes synonymous with BINFO_PRIMARY, and hence + remove a field. They currently can only differ for primary virtual + virtual bases. */ tree -copy_base_binfos (tree binfo, tree t, tree prev) +copy_binfo (tree binfo, tree type, tree t, tree *igo_prev, int virt) { - tree binfos = BINFO_BASE_BINFOS (binfo); - int n, ix; + tree new_binfo; - if (prev) - TREE_CHAIN (prev) = binfo; - prev = binfo; - - if (binfos == NULL_TREE) - return prev; - - n = TREE_VEC_LENGTH (binfos); - - /* Now copy the structure beneath BINFO. */ - for (ix = 0; ix != n; ix++) + if (virt) { - tree base_binfo = TREE_VEC_ELT (binfos, ix); - tree new_binfo = NULL_TREE; - - if (BINFO_DEPENDENT_BASE_P (base_binfo)) - { - my_friendly_assert (binfo == TYPE_BINFO (t), 20030204); - - new_binfo = base_binfo; - TREE_CHAIN (prev) = new_binfo; - prev = new_binfo; - BINFO_INHERITANCE_CHAIN (new_binfo) = binfo; - BINFO_DEPENDENT_BASE_P (new_binfo) = 1; - } - else if (BINFO_VIRTUAL_P (base_binfo)) - new_binfo = binfo_for_vbase (BINFO_TYPE (base_binfo), t); - - if (!new_binfo) - { - new_binfo = make_tree_binfo (BINFO_LANG_SLOTS); - - BINFO_TYPE (new_binfo) = BINFO_TYPE (base_binfo); - BINFO_OFFSET (new_binfo) = BINFO_OFFSET (base_binfo); - BINFO_VIRTUALS (new_binfo) = BINFO_VIRTUALS (base_binfo); - - if (BINFO_BASE_BINFOS (base_binfo)) - /* Duplicate the binfo's base vector, so we can recurse. */ - BINFO_BASE_BINFOS (new_binfo) - = copy_node (BINFO_BASE_BINFOS (base_binfo)); - /* We do not need to copy the accesses, as they are read only. */ - BINFO_BASE_ACCESSES (new_binfo) = BINFO_BASE_ACCESSES (base_binfo); - - prev = copy_base_binfos (new_binfo, t, prev); - if (BINFO_VIRTUAL_P (base_binfo)) - { - VEC_quick_push (tree, CLASSTYPE_VBASECLASSES (t), new_binfo); - BINFO_VIRTUAL_P (new_binfo) = 1; - BINFO_INHERITANCE_CHAIN (new_binfo) = TYPE_BINFO (t); - } - else - BINFO_INHERITANCE_CHAIN (new_binfo) = binfo; - } - TREE_VEC_ELT (binfos, ix) = new_binfo; + /* See if we've already made this virtual base. */ + new_binfo = binfo_for_vbase (type, t); + if (new_binfo) + return new_binfo; } + + new_binfo = make_tree_binfo (BINFO_LANG_SLOTS); + BINFO_TYPE (new_binfo) = type; - return prev; + /* Chain it into the inheritance graph. */ + TREE_CHAIN (*igo_prev) = new_binfo; + *igo_prev = new_binfo; + + if (binfo) + { + int ix, n = BINFO_N_BASE_BINFOS (binfo); + + my_friendly_assert (!BINFO_DEPENDENT_BASE_P (binfo), 20040712); + my_friendly_assert (type == BINFO_TYPE (binfo), 20040714); + + BINFO_OFFSET (new_binfo) = BINFO_OFFSET (binfo); + BINFO_VIRTUALS (new_binfo) = BINFO_VIRTUALS (binfo); + + /* Create a new base binfo vector. */ + if (n) + { + BINFO_BASE_BINFOS (new_binfo) = make_tree_vec (n); + /* We do not need to copy the accesses, as they are read only. */ + BINFO_BASE_ACCESSES (new_binfo) = BINFO_BASE_ACCESSES (binfo); + } + + /* Recursively copy base binfos of BINFO. */ + for (ix = 0; ix != n; ix++) + { + tree base_binfo = BINFO_BASE_BINFO (binfo, ix); + tree new_base_binfo; + + my_friendly_assert (!BINFO_DEPENDENT_BASE_P (base_binfo), 20040713); + new_base_binfo = copy_binfo (base_binfo, BINFO_TYPE (base_binfo), + t, igo_prev, + BINFO_VIRTUAL_P (base_binfo)); + + if (!BINFO_INHERITANCE_CHAIN (new_base_binfo)) + BINFO_INHERITANCE_CHAIN (new_base_binfo) = new_binfo; + BINFO_BASE_BINFO (new_binfo, ix) = new_base_binfo; + } + } + else + BINFO_DEPENDENT_BASE_P (new_binfo) = 1; + + if (virt) + { + /* Push it onto the list after any virtual bases it contains + will have been pushed. */ + VEC_quick_push (tree, CLASSTYPE_VBASECLASSES (t), new_binfo); + BINFO_VIRTUAL_P (new_binfo) = 1; + BINFO_INHERITANCE_CHAIN (new_binfo) = TYPE_BINFO (t); + } + + return new_binfo; } - /* Hashing of lists so that we don't make duplicates. The entry point is `list_hash_canon'. */