aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Mitchell <mark@codesourcery.com>1999-12-21 02:11:10 +0000
committerMark Mitchell <mark@codesourcery.com>1999-12-21 02:11:10 +0000
commitc9a8d58573cfc65fc95bd29108f1a8999b31d805 (patch)
tree1baa694ed75cd886a2915d1c87150fa270a1062e
parent9b468c62f46019c8a81117cde3a4973dd389f337 (diff)
1999-12-20 Mark Mitchell <mark@codesourcery.com>
* cp-tree.h (CLASSTYPE_VFIELD_PARENT): Update comments. (CLASSTYPE_HAS_PRIMARY_BASE_P): New macro. (CLASSTYPE_PRIMARY_BINFO): Likewise. * class.c (check_methods): Don't set TYPE_HAS_COMPLEX_INIT_REF, TYPE_NEEDS_CONSTRUCTING, and CLASSTYPE_NON_AGGREGATE here. (check_bases_and_members): Set them here instead. (create_vtable_ptr): New function, split out from ... (finish_struct_1): ... here. Use it. Tidy. Use CLASSTYPE_HAS_PRIMARY_BASE_P and CLASSTYPE_PRIMARY_BINFO. * search.c (dfs_init_vbase_pointers): Handle seeing TYPE_VFIELD as the first field in the class. * tree.c (layout_basetypes): Use CLASSTYPE_N_BASECLASSES. Handle seeing TYPE_VFIELD as the first field in the class. git-svn-id: https://gcc.gnu.org/svn/gcc/trunk@31042 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/cp/ChangeLog14
-rw-r--r--gcc/cp/class.c220
-rw-r--r--gcc/cp/cp-tree.h23
-rw-r--r--gcc/cp/search.c17
-rw-r--r--gcc/cp/tree.c38
5 files changed, 182 insertions, 130 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 2e23f2fd5a6..9fa42692d0d 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,5 +1,19 @@
1999-12-20 Mark Mitchell <mark@codesourcery.com>
+ * cp-tree.h (CLASSTYPE_VFIELD_PARENT): Update comments.
+ (CLASSTYPE_HAS_PRIMARY_BASE_P): New macro.
+ (CLASSTYPE_PRIMARY_BINFO): Likewise.
+ * class.c (check_methods): Don't set TYPE_HAS_COMPLEX_INIT_REF,
+ TYPE_NEEDS_CONSTRUCTING, and CLASSTYPE_NON_AGGREGATE here.
+ (check_bases_and_members): Set them here instead.
+ (create_vtable_ptr): New function, split out from ...
+ (finish_struct_1): ... here. Use it. Tidy. Use
+ CLASSTYPE_HAS_PRIMARY_BASE_P and CLASSTYPE_PRIMARY_BINFO.
+ * search.c (dfs_init_vbase_pointers): Handle seeing TYPE_VFIELD as
+ the first field in the class.
+ * tree.c (layout_basetypes): Use CLASSTYPE_N_BASECLASSES. Handle
+ seeing TYPE_VFIELD as the first field in the class.
+
* cp-tree.h (TYPE_VIRTUAL_P): Rename to ...
(TYPE_POLYMORPHIC_P): ... this.
(TYPE_USES_COMPLEX_INHERITANCE): Rename to ...
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index 02b034aa416..14c67af4a77 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -133,6 +133,7 @@ static void check_methods PROTO((tree));
static void remove_zero_width_bit_fields PROTO((tree));
static void check_bases PROTO((tree, int *, int *, int *));
static void check_bases_and_members PROTO((tree, int *));
+static void create_vtable_ptr PROTO((tree, int *, int *, int *, tree *, tree *));
/* Variables shared between class.c and call.c. */
@@ -3897,18 +3898,13 @@ build_base_fields (rec, empty_p)
/* Go through the TYPE_METHODS of T issuing any appropriate
diagnostics, figuring out which methods override which other
- methods, and so forth. Returns non-zero if this class has any
- virtual methods. */
+ methods, and so forth. */
static void
check_methods (t)
tree t;
{
tree x;
- int has_virtual;
-
- /* Assume there are no virtual methods. */
- has_virtual = 0;
for (x = TYPE_METHODS (t); x; x = TREE_CHAIN (x))
{
@@ -3933,21 +3929,12 @@ check_methods (t)
Save this in auxiliary field for later overloading. */
if (DECL_VINDEX (x))
{
- has_virtual = 1;
+ TYPE_POLYMORPHIC_P (t) = 1;
if (DECL_ABSTRACT_VIRTUAL_P (x))
CLASSTYPE_ABSTRACT_VIRTUALS (t)
= tree_cons (NULL_TREE, x, CLASSTYPE_ABSTRACT_VIRTUALS (t));
}
}
-
- /* A class with virtual functions needs constructing because, if
- nothing else, the vtable pointer must be initialized. */
- TYPE_HAS_COMPLEX_INIT_REF (t) |= has_virtual;
- TYPE_NEEDS_CONSTRUCTING (t) |= has_virtual;
- /* [dcl.init.aggr]
-
- An aggregate is a ... class ... with ... no virtual functions. */
- CLASSTYPE_NON_AGGREGATE (t) |= has_virtual;
}
/* Remove all zero-width bit-fields from T. */
@@ -4014,10 +4001,15 @@ check_bases_and_members (t, empty_p)
/* Do some bookkeeping that will guide the generation of implicitly
declared member functions. */
TYPE_HAS_COMPLEX_INIT_REF (t)
- |= (TYPE_HAS_INIT_REF (t) || TYPE_USES_VIRTUAL_BASECLASSES (t));
+ |= (TYPE_HAS_INIT_REF (t)
+ || TYPE_USES_VIRTUAL_BASECLASSES (t)
+ || TYPE_POLYMORPHIC_P (t));
TYPE_NEEDS_CONSTRUCTING (t)
- |= (TYPE_HAS_CONSTRUCTOR (t) || TYPE_USES_VIRTUAL_BASECLASSES (t));
- CLASSTYPE_NON_AGGREGATE (t) |= TYPE_HAS_CONSTRUCTOR (t);
+ |= (TYPE_HAS_CONSTRUCTOR (t)
+ || TYPE_USES_VIRTUAL_BASECLASSES (t)
+ || TYPE_POLYMORPHIC_P (t));
+ CLASSTYPE_NON_AGGREGATE (t) |= (TYPE_HAS_CONSTRUCTOR (t)
+ || TYPE_POLYMORPHIC_P (t));
CLASSTYPE_NON_POD_P (t)
|= (CLASSTYPE_NON_AGGREGATE (t) || TYPE_HAS_DESTRUCTOR (t)
|| TYPE_HAS_ASSIGN_REF (t));
@@ -4044,6 +4036,84 @@ check_bases_and_members (t, empty_p)
}
}
+/* If T needs a pointer to its virtual function table, set TYPE_VFIELD
+ accordingly, and, if necessary, add the TYPE_VFIELD to the
+ TYPE_FIELDS list. */
+
+static void
+create_vtable_ptr (t, empty_p, has_virtual_p, max_has_virtual_p,
+ pending_virtuals_p, pending_hard_virtuals_p)
+ tree t;
+ int *empty_p;
+ int *has_virtual_p;
+ int *max_has_virtual_p;
+ tree *pending_virtuals_p;
+ tree *pending_hard_virtuals_p;
+{
+ tree fn;
+
+ /* If possible, we reuse the virtual function table pointer from one
+ of our base classes. */
+ if (CLASSTYPE_N_BASECLASSES (t))
+ {
+ struct base_info base_info;
+
+ /* Remember where we got our vfield from. */
+ CLASSTYPE_VFIELD_PARENT (t) = finish_base_struct (t, &base_info);
+ *has_virtual_p = base_info.has_virtual;
+ *max_has_virtual_p = base_info.max_has_virtual;
+ TYPE_VFIELD (t) = base_info.vfield;
+ CLASSTYPE_VFIELDS (t) = base_info.vfields;
+ CLASSTYPE_RTTI (t) = base_info.rtti;
+ }
+
+ /* Loop over the virtual functions, adding them to our various
+ vtables. */
+ for (fn = TYPE_METHODS (t); fn; fn = TREE_CHAIN (fn))
+ if (DECL_VINDEX (fn))
+ add_virtual_function (pending_virtuals_p, pending_hard_virtuals_p,
+ has_virtual_p, fn, t);
+
+ /* If we couldn't find an appropriate base class, create a new field
+ here. */
+ if (*has_virtual_p && !TYPE_VFIELD (t))
+ {
+ /* We build this decl with vtbl_ptr_type_node, which is a
+ `vtable_entry_type*'. It might seem more precise to use
+ `vtable_entry_type (*)[N]' where N is the number of firtual
+ functions. However, that would require the vtable pointer in
+ base classes to have a different type than the vtable pointer
+ in derived classes. We could make that happen, but that
+ still wouldn't solve all the problems. In particular, the
+ type-based alias analysis code would decide that assignments
+ to the base class vtable pointer can't alias assignments to
+ the derived class vtable pointer, since they have different
+ types. Thus, in an derived class destructor, where the base
+ class constructor was inlined, we could generate bad code for
+ setting up the vtable pointer.
+
+ Therefore, we use one type for all vtable pointers. We still
+ use a type-correct type; it's just doesn't indicate the array
+ bounds. That's better than using `void*' or some such; it's
+ cleaner, and it let's the alias analysis code know that these
+ stores cannot alias stores to void*! */
+ TYPE_VFIELD (t)
+ = build_vtbl_or_vbase_field (get_vfield_name (t),
+ get_identifier (VFIELD_BASE),
+ vtbl_ptr_type_node,
+ t,
+ empty_p);
+
+ /* Add the new field to the list of fields in this class. */
+ TYPE_FIELDS (t) = chainon (TYPE_FIELDS (t), TYPE_VFIELD (t));
+
+ /* We can't yet add this new field to the list of all virtual
+ function table pointers in this class. The
+ modify_all_vtables function depends on this not being done.
+ So, it is done later, in finish_struct_1. */
+ }
+}
+
/* Create a RECORD_TYPE or UNION_TYPE node for a C struct or union declaration
(or C++ class declaration).
@@ -4080,14 +4150,8 @@ finish_struct_1 (t)
int max_has_virtual;
tree pending_virtuals = NULL_TREE;
tree pending_hard_virtuals = NULL_TREE;
- tree vfield;
- tree vfields;
int n_fields = 0;
-
- /* The index of the first base class which has virtual
- functions. Only applied to non-virtual baseclasses. */
- int first_vfn_base_index;
-
+ tree vfield;
int n_baseclasses;
int empty = 1;
tree inline_friends;
@@ -4110,11 +4174,9 @@ finish_struct_1 (t)
TYPE_SIZE (t) = NULL_TREE;
CLASSTYPE_GOT_SEMICOLON (t) = 0;
- first_vfn_base_index = -1;
+ CLASSTYPE_VFIELD_PARENT (t) = -1;
has_virtual = 0;
max_has_virtual = 0;
- vfield = NULL_TREE;
- vfields = NULL_TREE;
CLASSTYPE_RTTI (t) = NULL_TREE;
n_baseclasses = CLASSTYPE_N_BASECLASSES (t);
@@ -4129,59 +4191,9 @@ finish_struct_1 (t)
TYPE_FIELDS (t) = chainon (build_base_fields (t, &empty),
TYPE_FIELDS (t));
- if (n_baseclasses > 0)
- {
- struct base_info base_info;
-
- first_vfn_base_index = finish_base_struct (t, &base_info);
- /* Remember where we got our vfield from. */
- CLASSTYPE_VFIELD_PARENT (t) = first_vfn_base_index;
- has_virtual = base_info.has_virtual;
- max_has_virtual = base_info.max_has_virtual;
- vfield = base_info.vfield;
- TYPE_VFIELD (t) = vfield;
- vfields = base_info.vfields;
- CLASSTYPE_VFIELDS (t) = vfields;
- CLASSTYPE_RTTI (t) = base_info.rtti;
- }
-
- /* Loop over the virtual functions, adding them to our various
- vtables. */
- for (x = TYPE_METHODS (t); x; x = TREE_CHAIN (x))
- if (DECL_VINDEX (x))
- add_virtual_function (&pending_virtuals, &pending_hard_virtuals,
- &has_virtual, x, t);
-
- if (vfield == NULL_TREE && has_virtual)
- {
- /* We build this decl with vtbl_ptr_type_node, which is a
- `vtable_entry_type*'. It might seem more precise to use
- `vtable_entry_type (*)[N]' where N is the number of firtual
- functions. However, that would require the vtable pointer in
- base classes to have a different type than the vtable pointer
- in derived classes. We could make that happen, but that
- still wouldn't solve all the problems. In particular, the
- type-based alias analysis code would decide that assignments
- to the base class vtable pointer can't alias assignments to
- the derived class vtable pointer, since they have different
- types. Thus, in an derived class destructor, where the base
- class constructor was inlined, we could generate bad code for
- setting up the vtable pointer.
-
- Therefore, we use one type for all vtable pointers. We still
- use a type-correct type; it's just doesn't indicate the array
- bounds. That's better than using `void*' or some such; it's
- cleaner, and it let's the alias analysis code know that these
- stores cannot alias stores to void*! */
- vfield = build_vtbl_or_vbase_field (get_vfield_name (t),
- get_identifier (VFIELD_BASE),
- vtbl_ptr_type_node,
- t,
- &empty);
- TYPE_VFIELD (t) = vfield;
- TYPE_FIELDS (t) = chainon (TYPE_FIELDS (t), vfield);
- vfields = chainon (vfields, build_tree_list (NULL_TREE, t));
- }
+ /* Create a pointer to our virtual function table. */
+ create_vtable_ptr (t, &empty, &has_virtual, &max_has_virtual,
+ &pending_virtuals, &pending_hard_virtuals);
/* CLASSTYPE_INLINE_FRIENDS is really TYPE_NONCOPIED_PARTS. Thus,
we have to save this before we start modifying
@@ -4205,6 +4217,11 @@ finish_struct_1 (t)
TREE_STATIC (TYPE_NONCOPIED_PARTS (t)) = 1;
}
+ /* Let the back-end lay out the type. Note that at this point we
+ have only included non-virtual base-classes; we will lay out the
+ virtual base classes later. So, the TYPE_SIZE/TYPE_ALIGN after
+ this call are not necessarily correct; they are just the size and
+ alignment when no virtual base clases are used. */
layout_type (t);
/* If we added an extra field to make this class non-empty, remove
@@ -4212,6 +4229,10 @@ finish_struct_1 (t)
if (empty)
TYPE_FIELDS (t) = TREE_CHAIN (TYPE_FIELDS (t));
+ /* Delete all zero-width bit-fields from the list of fields. Now
+ that the type is laid out they are no longer important. */
+ remove_zero_width_bit_fields (t);
+
/* Remember the size and alignment of the class before adding
the virtual bases. */
if (empty && flag_new_abi)
@@ -4232,16 +4253,11 @@ finish_struct_1 (t)
/* Now fix up any virtual base class types that we left lying
around. We must get these done before we try to lay out the
virtual function table. */
- pending_hard_virtuals = nreverse (pending_hard_virtuals);
if (n_baseclasses)
/* layout_basetypes will remove the base subobject fields. */
max_has_virtual = layout_basetypes (t, max_has_virtual);
- /* Delete all zero-width bit-fields from the list of fields. Now
- that we have layed out the type they are no longer important. */
- remove_zero_width_bit_fields (t);
-
if (TYPE_USES_VIRTUAL_BASECLASSES (t))
{
tree vbases;
@@ -4275,6 +4291,7 @@ finish_struct_1 (t)
/* Set up the DECL_FIELD_BITPOS of the vfield if we need to, as we
might need to know it for setting up the offsets in the vtable
(or in thunks) below. */
+ vfield = TYPE_VFIELD (t);
if (vfield != NULL_TREE
&& DECL_FIELD_CONTEXT (vfield) != t)
{
@@ -4293,9 +4310,6 @@ finish_struct_1 (t)
TYPE_VFIELD (t) = vfield;
}
- /* If this vtbl pointer is new, add it to the list of vtbl
- pointers in this class. */
-
if (has_virtual > max_has_virtual)
max_has_virtual = has_virtual;
if (max_has_virtual > 0)
@@ -4335,7 +4349,7 @@ finish_struct_1 (t)
{
pending_virtuals = nreverse (pending_virtuals);
/* We must enter these virtuals into the table. */
- if (first_vfn_base_index < 0)
+ if (!CLASSTYPE_HAS_PRIMARY_BASE_P (t))
{
if (! CLASSTYPE_COM_INTERFACE (t))
{
@@ -4357,7 +4371,7 @@ finish_struct_1 (t)
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);
+ build_vtable (CLASSTYPE_PRIMARY_BINFO (t), t);
}
/* If this type has basetypes with constructors, then those
@@ -4367,9 +4381,10 @@ finish_struct_1 (t)
CLASSTYPE_NEEDS_VIRTUAL_REINIT (t) = 1;
}
- else if (first_vfn_base_index >= 0)
+ else if (CLASSTYPE_HAS_PRIMARY_BASE_P (t))
{
- tree binfo = TREE_VEC_ELT (TYPE_BINFO_BASETYPES (t), first_vfn_base_index);
+ tree binfo = CLASSTYPE_PRIMARY_BINFO (t);
+
/* This class contributes nothing new to the virtual function
table. However, it may have declared functions which
went into the virtual function table "inherited" from the
@@ -4385,10 +4400,10 @@ finish_struct_1 (t)
CLASSTYPE_NEEDS_VIRTUAL_REINIT (t) = 1;
}
- if (max_has_virtual || first_vfn_base_index >= 0)
+ if (max_has_virtual || CLASSTYPE_HAS_PRIMARY_BASE_P (t))
{
CLASSTYPE_VSIZE (t) = has_virtual;
- if (first_vfn_base_index >= 0)
+ if (CLASSTYPE_HAS_PRIMARY_BASE_P (t))
{
if (pending_virtuals)
TYPE_BINFO_VIRTUALS (t) = chainon (TYPE_BINFO_VIRTUALS (t),
@@ -4410,8 +4425,6 @@ finish_struct_1 (t)
layout_type (atype);
- TYPE_VFIELD (t) = vfield;
-
/* We may have to grow the vtable. */
if (TREE_TYPE (TYPE_BINFO_VTABLE (t)) != atype)
{
@@ -4425,9 +4438,12 @@ finish_struct_1 (t)
DECL_ALIGN (TYPE_BINFO_VTABLE (t)));
}
}
- else if (first_vfn_base_index >= 0)
- TYPE_VFIELD (t) = vfield;
- CLASSTYPE_VFIELDS (t) = vfields;
+
+ /* If we created a new vtbl pointer for this class, add it to the
+ list. */
+ if (TYPE_VFIELD (t) && CLASSTYPE_VFIELD_PARENT (t) == -1)
+ CLASSTYPE_VFIELDS (t)
+ = chainon (CLASSTYPE_VFIELDS (t), build_tree_list (NULL_TREE, t));
finish_struct_bits (t, max_has_virtual);
@@ -4488,7 +4504,7 @@ finish_struct_1 (t)
a place to find them. */
TYPE_NONCOPIED_PARTS (t)
= tree_cons (default_conversion (TYPE_BINFO_VTABLE (t)),
- vfield, TYPE_NONCOPIED_PARTS (t));
+ TYPE_VFIELD (t), TYPE_NONCOPIED_PARTS (t));
if (warn_nonvdtor && TYPE_HAS_DESTRUCTOR (t)
&& DECL_VINDEX (TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (t), 1)) == NULL_TREE)
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 3708dfa60b9..995bc516694 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -1382,13 +1382,26 @@ struct lang_type
nested member class templates. */
#define CLASSTYPE_TAGS(NODE) (TYPE_LANG_SPECIFIC(NODE)->tags)
-/* If this class has any bases, this is the number of the base class from
- which our VFIELD is based, -1 otherwise. If this class has no base
- classes, this is not used.
- In D : B1, B2, PARENT would be 0, if D's vtable came from B1,
- 1, if D's vtable came from B2. */
+/* If this value is non-negative, it is the index (in the
+ TYPE_BINFO_BASETYPES) for the base-class whose vtable pointer we
+ are reusing. For example, in D : B1, B2, PARENT would be 0, if D's
+ vtable came from B1, 1, if D's vtable came from B2. */
#define CLASSTYPE_VFIELD_PARENT(NODE) (TYPE_LANG_SPECIFIC(NODE)->vfield_parent)
+/* Nonzero if NODE has a primary base class, i.e., a base class with
+ which it shares the virtual fucntion table pointer. */
+#define CLASSTYPE_HAS_PRIMARY_BASE_P(NODE) \
+ (CLASSTYPE_VFIELD_PARENT (NODE) != -1)
+
+/* If non-NULL, this is the binfo for the primary base class, i.e.,
+ the base class which contains the virtual function table pointer
+ for this class. */
+#define CLASSTYPE_PRIMARY_BINFO(NODE) \
+ (CLASSTYPE_HAS_PRIMARY_BASE_P (NODE) \
+ ? TREE_VEC_ELT (TYPE_BINFO_BASETYPES (NODE), \
+ CLASSTYPE_VFIELD_PARENT (NODE)) \
+ : NULL_TREE)
+
/* The number of virtual functions defined for this
_CLASSTYPE node. */
#define CLASSTYPE_VSIZE(NODE) (TYPE_LANG_SPECIFIC(NODE)->vsize)
diff --git a/gcc/cp/search.c b/gcc/cp/search.c
index 60f9405547d..8ee63f162cd 100644
--- a/gcc/cp/search.c
+++ b/gcc/cp/search.c
@@ -2432,18 +2432,11 @@ dfs_init_vbase_pointers (binfo, data)
{
struct vbase_info *vi = (struct vbase_info *) data;
tree type = BINFO_TYPE (binfo);
- tree fields = TYPE_FIELDS (type);
+ tree fields;
tree this_vbase_ptr;
CLEAR_BINFO_VTABLE_PATH_MARKED (binfo);
-#if 0
- /* See finish_struct_1 for when we can enable this. */
- /* If we have a vtable pointer first, skip it. */
- if (VFIELD_NAME_P (DECL_NAME (fields)))
- fields = TREE_CHAIN (fields);
-#endif
-
if (BINFO_INHERITANCE_CHAIN (binfo))
{
this_vbase_ptr = TREE_CHAIN (BINFO_INHERITANCE_CHAIN (binfo));
@@ -2457,6 +2450,14 @@ dfs_init_vbase_pointers (binfo, data)
else
this_vbase_ptr = TREE_CHAIN (binfo);
+ /* We're going to iterate through all the pointers to virtual
+ base-classes. They come at the beginning of the class. */
+ fields = TYPE_FIELDS (type);
+ if (fields == TYPE_VFIELD (type))
+ /* If the first field is the vtbl pointer (as happens in the new
+ ABI), skip it. */
+ fields = TREE_CHAIN (fields);
+
if (fields == NULL_TREE
|| DECL_NAME (fields) == NULL_TREE
|| ! VBASE_NAME_P (DECL_NAME (fields)))
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index cd837e68a5c..39447eee1c7 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -693,15 +693,7 @@ propagate_binfo_offsets (binfo, offset)
break;
}
-#if 0
- if (BINFO_OFFSET_ZEROP (base_binfo))
- BINFO_OFFSET (base_binfo) = offset;
- else
- BINFO_OFFSET (base_binfo)
- = size_binop (PLUS_EXPR, BINFO_OFFSET (base_binfo), offset);
-#else
BINFO_OFFSET (base_binfo) = offset;
-#endif
propagate_binfo_offsets (base_binfo, offset);
@@ -759,9 +751,9 @@ layout_basetypes (rec, max)
int max;
{
tree binfos = TYPE_BINFO_BASETYPES (rec);
- int i, n_baseclasses = binfos ? TREE_VEC_LENGTH (binfos) : 0;
-
+ int i, n_baseclasses = CLASSTYPE_N_BASECLASSES (rec);
tree vbase_types;
+ tree *field;
unsigned int record_align = MAX (BITS_PER_UNIT, TYPE_ALIGN (rec));
unsigned int desired_align;
@@ -835,27 +827,43 @@ layout_basetypes (rec, max)
size_int (BITS_PER_UNIT));
}
- /* Now propagate offset information throughout the lattice. */
+ /* Now propagate offset information throughout the lattice.
+ Simultaneously, remove the temporary FIELD_DECLS we created in
+ build_base_fields to refer to base types. */
+ field = &TYPE_FIELDS (rec);
+ if (TYPE_VFIELD (rec) == *field)
+ {
+ /* If this class did not have a primary base, we create a
+ virtual function table pointer. It will be the first thing
+ in the class, under the new ABI. Skip it; the base fields
+ will follow it. */
+ my_friendly_assert (flag_new_abi
+ && !CLASSTYPE_HAS_PRIMARY_BASE_P (rec),
+ 19991218);
+ field = &TREE_CHAIN (*field);
+ }
+
for (i = 0; i < n_baseclasses; i++)
{
register tree base_binfo = TREE_VEC_ELT (binfos, i);
register tree basetype = BINFO_TYPE (base_binfo);
- tree field = TYPE_FIELDS (rec);
if (TREE_VIA_VIRTUAL (base_binfo))
continue;
- my_friendly_assert (TREE_TYPE (field) == basetype, 23897);
+ my_friendly_assert (TREE_TYPE (*field) == basetype, 23897);
if (get_base_distance (basetype, rec, 0, (tree*)0) == -2)
cp_warning ("direct base `%T' inaccessible in `%T' due to ambiguity",
basetype, rec);
BINFO_OFFSET (base_binfo)
- = size_int (CEIL (TREE_INT_CST_LOW (DECL_FIELD_BITPOS (field)),
+ = size_int (CEIL (TREE_INT_CST_LOW (DECL_FIELD_BITPOS (*field)),
BITS_PER_UNIT));
propagate_binfo_offsets (base_binfo, BINFO_OFFSET (base_binfo));
- TYPE_FIELDS (rec) = TREE_CHAIN (field);
+
+ /* Remove this field. */
+ *field = TREE_CHAIN (*field);
}
for (vbase_types = CLASSTYPE_VBASECLASSES (rec); vbase_types;