Commit 3ef397c1 by Mark Mitchell Committed by Mark Mitchell

cp-tree.h (CLASSTYPE_VFIELD_PARENT): Update comments.

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.

From-SVN: r31042
parent 4c6b7393
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 ...
......
......@@ -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)
......
......@@ -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)
......
......@@ -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)))
......
......@@ -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;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment