From: Mark Mitchell <mark@codesourcery.com>
To: gcc@gcc.gnu.org
Subject: C++ PATCH: Indirect primary bases
Date: Sun, 30 Jul 2000 17:21:00 -0000 [thread overview]
Message-ID: <20000730172116N.mitchell@codesourcery.com> (raw)
The IA64 C++ ABI allows an indirect virtual base to serve as a primary
base. For example:
struct S
{
virtual void f ();
};
struct T: virtual public S {
int i;
};
struct U : virtual public T {
};
U u;
In this hierarchy, U does not share its vptr with T because T contains
more than just a vptr. However, since S is "nearly empty", U shares
its vptr with S. In this example, there's little benefit.
However, given:
struct S {
virtual void f () {}
};
struct T {
virtual void g () {}
};
struct U : virtual public S, virtual public T {
int i;
};
struct V : virtual public U {
};
it's possible to shave a few bytes off of X, reduce the number of
vtables, and otherwise win, by sharing T's vptr with V's. Needless to
say, this necessitated some serious changes in the layout code; bad
enough that we are sharing vptrs with virtual bases, even worse that
we are doing this with indirect virtual bases. Ugh.
I'm not 100% I've shaken all the bugs out of this, but it passes the
regression tests on i686-pc-linux, and passes our internal (but
soon to become public) IA64 C++ ABI testsuite.
I lost my final diffs; the attached patch is what I checked in, except
that I added a couple more comments.
--
Mark Mitchell mark@codesourcery.com
CodeSourcery, LLC http://www.codesourcery.com
2000-07-30 Mark Mitchell <mark@codesourcery.com>
Allow indirect primary bases.
* cp-tree.h (struct lang_type): Remove vfield_parent. Add
primary_base.
(CLASSTYPE_VFIELD_PARENT): Remove.
(CLASSTYPE_PRIMARY_BINFO): Reimplement.
(BINFO_PRIMARY_BINFO): Remove.
(CLASSTYPE_HAS_PRIMARY_BASE_P): Reimplement.
(BINFO_VBASE_PRIMARY_P): Likewise.
(BINFO_PRIMARY_BASE_OF): New macro.
(BINFO_INDIRECT_PRIMARY_P): Likewise.
(get_primary_binfo): New function.
* decl.c (lang_mark_tree): Make lang_type::primary_base.
* class.c (vcall_offset_data_s): Rename to ...
(vtbl_init_data_s): ... this. Rename primary_p to primary_vtbl_p,
and add ctor_vtbl_p.
(get_derived_offset): Use get_primary_binfo.
(dfs_mark_primary_bases): Adjust handling of virtual primary
bases.
(mark_primary_bases): Likewise.
(set_primary_base): Take a binfo, not an integer, as a
representation of the primary base.
(indirect_primary_base_p): Remove.
(determine_primary_base): Adjust for indirect primary bases.
(dfs_find_final_overrider): Fix typo in coment.
(update_vtable_entry_for_fn): Use get_primary_binfo.
(layout_nonempty_base_or_field): Tweak.
(build_base_fields): Adjust for new primary base semantics.
(dfs_propagate_binfo_offsets): Remove.
(propagate_binfo_offsets): Rewrite.
(dfs_set_offset_for_shared_vbases): Remove.
(layout_virtual_bases): Don't use it.
(layout_class_type): Set CLASSTYPE_SIZE correctly under the new
ABI.
(finish_struct_1): Set CLASSTYPE_PRIMARY_BINFO, not
CLASSTYPE_VFIELD_PARENT.
(dfs_get_primary_binfo): New function.
(get_primary_binfo): Likewise.
(dump_class_hierarchy_r): Tweak printing of primary bases.
(build_vtbl_initializer): Fix typo in comments. Use
vtbl_init_data.
(build_vcall_and_vbase_vtbl_entries): Likewise.
(build_vbaes_offset_vtbl_entries): Likewise.
(dfs_build_vcall_offset_vtbl_entries): Adjust setting of
BV_VCALL_INDEX to handle indirect primary bases.
(build_vcall_offset_vtbl_entries): Use vtbl_init_data.
(build_rtti_vtbl_entries): Likewise.
* search.c (get_shared_vbase_if_not_primary): Tweak.
(find_vbase_instance): Likewise.
(binfo_for_vtable): Simplify.
* tree.c (unshare_base_binfos): Clear BINFO_PRIMARY_BASE_OF.
(make_binfo): Make it have 11 entries.
Index: class.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/class.c,v
retrieving revision 1.326
diff -c -p -r1.326 class.c
*** class.c 2000/07/25 20:19:23 1.326
--- class.c 2000/07/31 00:04:40
*************** typedef struct class_stack_node {
*** 62,69 ****
splay_tree names_used;
}* class_stack_node_t;
! typedef struct vcall_offset_data_s
{
/* The binfo for the most-derived type. */
tree derived;
/* The negative-index vtable initializers built up so far. These
--- 62,71 ----
splay_tree names_used;
}* class_stack_node_t;
! typedef struct vtbl_init_data_s
{
+ /* The base for which we're building initializers. */
+ tree binfo;
/* The binfo for the most-derived type. */
tree derived;
/* The negative-index vtable initializers built up so far. These
*************** typedef struct vcall_offset_data_s
*** 72,78 ****
/* The last (i.e., most negative entry in INITS. */
tree* last_init;
/* The binfo for the virtual base for which we're building
! initializers. */
tree vbase;
/* The functions in vbase for which we have already provided vcall
offsets. */
--- 74,80 ----
/* The last (i.e., most negative entry in INITS. */
tree* last_init;
/* The binfo for the virtual base for which we're building
! vcall offset initializers. */
tree vbase;
/* The functions in vbase for which we have already provided vcall
offsets. */
*************** typedef struct vcall_offset_data_s
*** 80,88 ****
/* The vtable index of the next vcall or vbase offset. */
tree index;
/* Nonzero if we are building the initializer for the primary
vtable. */
! int primary_p;
! } vcall_offset_data;
/* The stack itself. This is an dynamically resized array. The
number of elements allocated is CURRENT_CLASS_STACK_SIZE. */
--- 82,93 ----
/* The vtable index of the next vcall or vbase offset. */
tree index;
/* Nonzero if we are building the initializer for the primary
+ vtable. */
+ int primary_vtbl_p;
+ /* Nonzero if we are building the initializer for a construction
vtable. */
! int ctor_vtbl_p;
! } vtbl_init_data;
/* The stack itself. This is an dynamically resized array. The
number of elements allocated is CURRENT_CLASS_STACK_SIZE. */
*************** static tree create_vtable_ptr PARAMS ((t
*** 150,164 ****
static void layout_class_type PARAMS ((tree, int *, int *, tree *, tree *));
static void fixup_pending_inline PARAMS ((struct pending_inline *));
static void fixup_inline_methods PARAMS ((tree));
! static void set_primary_base PARAMS ((tree, int, int *));
! static tree dfs_propagate_binfo_offsets PARAMS ((tree, void *));
static void propagate_binfo_offsets PARAMS ((tree, tree));
static void layout_virtual_bases PARAMS ((tree, varray_type *));
- static tree dfs_set_offset_for_shared_vbases PARAMS ((tree, void *));
static tree dfs_set_offset_for_unshared_vbases PARAMS ((tree, void *));
! static void build_vbase_offset_vtbl_entries PARAMS ((tree, vcall_offset_data *));
static tree dfs_build_vcall_offset_vtbl_entries PARAMS ((tree, void *));
! static void build_vcall_offset_vtbl_entries PARAMS ((tree, vcall_offset_data *));
static void layout_vtable_decl PARAMS ((tree, int));
static tree dfs_find_final_overrider PARAMS ((tree, void *));
static tree find_final_overrider PARAMS ((tree, tree, tree));
--- 155,167 ----
static void layout_class_type PARAMS ((tree, int *, int *, tree *, tree *));
static void fixup_pending_inline PARAMS ((struct pending_inline *));
static void fixup_inline_methods PARAMS ((tree));
! static void set_primary_base PARAMS ((tree, tree, int *));
static void propagate_binfo_offsets PARAMS ((tree, tree));
static void layout_virtual_bases PARAMS ((tree, varray_type *));
static tree dfs_set_offset_for_unshared_vbases PARAMS ((tree, void *));
! static void build_vbase_offset_vtbl_entries PARAMS ((tree, vtbl_init_data *));
static tree dfs_build_vcall_offset_vtbl_entries PARAMS ((tree, void *));
! static void build_vcall_offset_vtbl_entries PARAMS ((tree, vtbl_init_data *));
static void layout_vtable_decl PARAMS ((tree, int));
static tree dfs_find_final_overrider PARAMS ((tree, void *));
static tree find_final_overrider PARAMS ((tree, tree, tree));
*************** static unsigned HOST_WIDE_INT end_of_cla
*** 179,187 ****
static void layout_empty_base PARAMS ((tree, tree, varray_type));
static void accumulate_vtbl_inits PARAMS ((tree, tree, tree, tree, tree));
static void set_vindex PARAMS ((tree, tree, int *));
! static void build_rtti_vtbl_entries PARAMS ((tree, tree, vcall_offset_data *));
static void build_vcall_and_vbase_vtbl_entries PARAMS ((tree,
! vcall_offset_data *));
static tree dfs_mark_primary_bases PARAMS ((tree, void *));
static void mark_primary_bases PARAMS ((tree));
static void clone_constructors_and_destructors PARAMS ((tree));
--- 182,190 ----
static void layout_empty_base PARAMS ((tree, tree, varray_type));
static void accumulate_vtbl_inits PARAMS ((tree, tree, tree, tree, tree));
static void set_vindex PARAMS ((tree, tree, int *));
! static void build_rtti_vtbl_entries PARAMS ((tree, tree, vtbl_init_data *));
static void build_vcall_and_vbase_vtbl_entries PARAMS ((tree,
! vtbl_init_data *));
static tree dfs_mark_primary_bases PARAMS ((tree, void *));
static void mark_primary_bases PARAMS ((tree));
static void clone_constructors_and_destructors PARAMS ((tree));
*************** static void build_vtt PARAMS ((tree));
*** 193,200 ****
static tree *build_vtt_inits PARAMS ((tree, tree, int, tree *, tree *));
static tree dfs_build_secondary_vptr_vtt_inits PARAMS ((tree, void *));
static tree dfs_fixup_binfo_vtbls PARAMS ((tree, void *));
- static int indirect_primary_base_p PARAMS ((tree, tree));
static tree get_matching_base PARAMS ((tree, tree));
/* Variables shared between class.c and call.c. */
--- 196,203 ----
static tree *build_vtt_inits PARAMS ((tree, tree, int, tree *, tree *));
static tree dfs_build_secondary_vptr_vtt_inits PARAMS ((tree, void *));
static tree dfs_fixup_binfo_vtbls PARAMS ((tree, void *));
static tree get_matching_base PARAMS ((tree, tree));
+ static tree dfs_get_primary_binfo PARAMS ((tree, void*));
/* Variables shared between class.c and call.c. */
*************** get_derived_offset (binfo, type)
*** 687,693 ****
tree offset2;
while (!same_type_p (BINFO_TYPE (binfo), type))
! binfo = BINFO_PRIMARY_BINFO (binfo);
offset2 = get_vfield_offset (TYPE_BINFO (BINFO_TYPE (binfo)));
return size_binop (MINUS_EXPR, offset1, offset2);
--- 690,696 ----
tree offset2;
while (!same_type_p (BINFO_TYPE (binfo), type))
! binfo = get_primary_binfo (binfo);
offset2 = get_vfield_offset (TYPE_BINFO (BINFO_TYPE (binfo)));
return size_binop (MINUS_EXPR, offset1, offset2);
*************** dfs_mark_primary_bases (binfo, data)
*** 1701,1719 ****
tree binfo;
void *data;
{
- int i;
tree base_binfo;
if (!CLASSTYPE_HAS_PRIMARY_BASE_P (BINFO_TYPE (binfo)))
return NULL_TREE;
! i = CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (binfo));
! base_binfo = BINFO_BASETYPE (binfo, i);
! if (!TREE_VIA_VIRTUAL (base_binfo))
! /* Non-virtual base classes are easy. */
! BINFO_PRIMARY_MARKED_P (base_binfo) = 1;
! else
{
tree shared_binfo;
tree type;
--- 1704,1717 ----
tree binfo;
void *data;
{
tree base_binfo;
if (!CLASSTYPE_HAS_PRIMARY_BASE_P (BINFO_TYPE (binfo)))
return NULL_TREE;
! base_binfo = get_primary_binfo (binfo);
! if (TREE_VIA_VIRTUAL (base_binfo))
{
tree shared_binfo;
tree type;
*************** dfs_mark_primary_bases (binfo, data)
*** 1723,1729 ****
/* If this virtual base is not already primary somewhere else in
the hiearchy, then we'll be using this copy. */
! if (!BINFO_VBASE_PRIMARY_P (shared_binfo))
{
/* Make sure the CLASSTYPE_VBASECLASSES list contains the
primary copy; it's the one that really exists. */
--- 1721,1727 ----
/* If this virtual base is not already primary somewhere else in
the hiearchy, then we'll be using this copy. */
! if (!BINFO_PRIMARY_MARKED_P (shared_binfo))
{
/* Make sure the CLASSTYPE_VBASECLASSES list contains the
primary copy; it's the one that really exists. */
*************** dfs_mark_primary_bases (binfo, data)
*** 1731,1742 ****
TREE_VALUE (purpose_member (BINFO_TYPE (base_binfo),
CLASSTYPE_VBASECLASSES (type)))
= base_binfo;
-
- BINFO_VBASE_PRIMARY_P (base_binfo) = 1;
- BINFO_PRIMARY_MARKED_P (base_binfo) = 1;
}
}
return NULL_TREE;
}
--- 1729,1742 ----
TREE_VALUE (purpose_member (BINFO_TYPE (base_binfo),
CLASSTYPE_VBASECLASSES (type)))
= base_binfo;
}
+ else
+ base_binfo = NULL_TREE;
}
+ if (base_binfo)
+ BINFO_PRIMARY_BASE_OF (base_binfo) = binfo;
+
return NULL_TREE;
}
*************** mark_primary_bases (type)
*** 1774,1809 ****
continue;
vbase = binfo_for_vbase (BINFO_TYPE (vbases), type);
! if (BINFO_VBASE_PRIMARY_P (vbase))
/* This virtual base was already included in the hierarchy, so
there's nothing to do here. */
continue;
- /* Temporarily pretend that VBASE is primary so that its bases
- will be walked; this is the real copy of VBASE. */
- BINFO_PRIMARY_MARKED_P (vbase) = 1;
-
/* Now, walk its bases. */
dfs_walk_real (vbase, dfs_mark_primary_bases, NULL,
dfs_skip_nonprimary_vbases_unmarkedp, type);
-
- /* VBASE wasn't really primary. */
- BINFO_PRIMARY_MARKED_P (vbase) = 0;
}
}
! /* Make the Ith baseclass of T its primary base. */
static void
! set_primary_base (t, i, vfuns_p)
tree t;
! int i;
int *vfuns_p;
{
tree basetype;
! CLASSTYPE_VFIELD_PARENT (t) = i;
! basetype = BINFO_TYPE (CLASSTYPE_PRIMARY_BINFO (t));
TYPE_BINFO_VTABLE (t) = TYPE_BINFO_VTABLE (basetype);
TYPE_BINFO_VIRTUALS (t) = TYPE_BINFO_VIRTUALS (basetype);
TYPE_VFIELD (t) = TYPE_VFIELD (basetype);
--- 1774,1802 ----
continue;
vbase = binfo_for_vbase (BINFO_TYPE (vbases), type);
! if (BINFO_PRIMARY_MARKED_P (vbase))
/* This virtual base was already included in the hierarchy, so
there's nothing to do here. */
continue;
/* Now, walk its bases. */
dfs_walk_real (vbase, dfs_mark_primary_bases, NULL,
dfs_skip_nonprimary_vbases_unmarkedp, type);
}
}
! /* Make the BINFO the primary base of T. */
static void
! set_primary_base (t, binfo, vfuns_p)
tree t;
! tree binfo;
int *vfuns_p;
{
tree basetype;
! CLASSTYPE_PRIMARY_BINFO (t) = binfo;
! basetype = BINFO_TYPE (binfo);
TYPE_BINFO_VTABLE (t) = TYPE_BINFO_VTABLE (basetype);
TYPE_BINFO_VIRTUALS (t) = TYPE_BINFO_VIRTUALS (basetype);
TYPE_VFIELD (t) = TYPE_VFIELD (basetype);
*************** set_primary_base (t, i, vfuns_p)
*** 1811,1845 ****
*vfuns_p = CLASSTYPE_VSIZE (basetype);
}
- /* Returns true iff BINFO (a direct virtual base of T) is an indirect
- primary base. */
-
- static int
- indirect_primary_base_p (t, binfo)
- tree t;
- tree binfo;
- {
- int i;
-
- for (i = 0; i < CLASSTYPE_N_BASECLASSES (t); ++i)
- {
- tree type;
- tree b;
-
- /* Figure out to which type the Ith base corresponds. */
- type = TYPE_BINFO_BASETYPE (t, i);
- /* See if any of the primary bases have the same type as BINFO. */
- for (b = TYPE_BINFO (type); b; b = TREE_CHAIN (b))
- /* If this base is primary, and has the same type as BINFO,
- then BINFO is an indirect primary base. */
- if (BINFO_PRIMARY_MARKED_P (b)
- && same_type_p (BINFO_TYPE (b), BINFO_TYPE (binfo)))
- return 1;
- }
-
- return 0;
- }
-
/* Determine the primary class for T. */
static void
--- 1804,1809 ----
*************** determine_primary_base (t, vfuns_p)
*** 1848,1863 ****
int *vfuns_p;
{
int i, n_baseclasses = CLASSTYPE_N_BASECLASSES (t);
/* If there are no baseclasses, there is certainly no primary base. */
if (n_baseclasses == 0)
return;
! *vfuns_p = 0;
for (i = 0; i < n_baseclasses; i++)
{
! tree base_binfo = TREE_VEC_ELT (TYPE_BINFO_BASETYPES (t), i);
tree basetype = BINFO_TYPE (base_binfo);
if (TYPE_CONTAINS_VPTR_P (basetype))
--- 1812,1829 ----
int *vfuns_p;
{
int i, n_baseclasses = CLASSTYPE_N_BASECLASSES (t);
+ tree vbases;
+ tree type_binfo;
/* If there are no baseclasses, there is certainly no primary base. */
if (n_baseclasses == 0)
return;
! type_binfo = TYPE_BINFO (t);
for (i = 0; i < n_baseclasses; i++)
{
! tree base_binfo = BINFO_BASETYPE (type_binfo, i);
tree basetype = BINFO_TYPE (base_binfo);
if (TYPE_CONTAINS_VPTR_P (basetype))
*************** determine_primary_base (t, vfuns_p)
*** 1876,1882 ****
if (!CLASSTYPE_HAS_PRIMARY_BASE_P (t))
{
! set_primary_base (t, i, vfuns_p);
CLASSTYPE_VFIELDS (t) = copy_list (CLASSTYPE_VFIELDS (basetype));
}
else
--- 1842,1848 ----
if (!CLASSTYPE_HAS_PRIMARY_BASE_P (t))
{
! set_primary_base (t, base_binfo, vfuns_p);
CLASSTYPE_VFIELDS (t) = copy_list (CLASSTYPE_VFIELDS (basetype));
}
else
*************** determine_primary_base (t, vfuns_p)
*** 1895,1954 ****
CLASSTYPE_VFIELDS (t));
if (!flag_new_abi && *vfuns_p == 0)
! set_primary_base (t, i, vfuns_p);
}
}
}
if (!TYPE_VFIELD (t))
! CLASSTYPE_VFIELD_PARENT (t) = -1;
/* The new ABI allows for the use of a "nearly-empty" virtual base
class as the primary base class if no non-virtual polymorphic
base can be found. */
if (flag_new_abi && !CLASSTYPE_HAS_PRIMARY_BASE_P (t))
{
! /* If not -1, this is the index in TYPE_BINFO_BASETYPEs of the
! best primary base candidate we have found so far. */
! int candidate = -1;
/* Loop over the baseclasses. */
! for (i = 0; i < n_baseclasses; ++i)
{
- tree base_binfo = TREE_VEC_ELT (TYPE_BINFO_BASETYPES (t), i);
tree basetype = BINFO_TYPE (base_binfo);
if (TREE_VIA_VIRTUAL (base_binfo)
&& CLASSTYPE_NEARLY_EMPTY_P (basetype))
{
- int indirect_primary_p;
-
- /* Figure out whether or not this base is an indirect
- primary base. */
- indirect_primary_p = indirect_primary_base_p (t, base_binfo);
-
/* If this is not an indirect primary base, then it's
definitely our primary base. */
! if (!indirect_primary_p)
{
! candidate = i;
break;
}
/* If this was an indirect primary base, it's still our
primary base -- unless there's another nearly-empty
virtual base that isn't an indirect primary base. */
! else if (candidate == -1)
! candidate = i;
}
}
/* If we've got a primary base, use it. */
! if (candidate != -1)
{
set_primary_base (t, candidate, vfuns_p);
CLASSTYPE_VFIELDS (t)
! = copy_list (CLASSTYPE_VFIELDS (TYPE_BINFO_BASETYPE (t,
! candidate)));
}
}
--- 1861,1953 ----
CLASSTYPE_VFIELDS (t));
if (!flag_new_abi && *vfuns_p == 0)
! set_primary_base (t, base_binfo, vfuns_p);
}
}
}
if (!TYPE_VFIELD (t))
! CLASSTYPE_PRIMARY_BINFO (t) = NULL_TREE;
+ /* Mark the indirect primary bases. */
+ for (vbases = CLASSTYPE_VBASECLASSES (t);
+ vbases;
+ vbases = TREE_CHAIN (vbases))
+ {
+ tree binfo = TREE_VALUE (vbases);
+
+ /* See if this virtual base is an indirect primary base. If so,
+ it must be either a primary base or an indirect primary base
+ in one of the direct bases. */
+ for (i = 0; i < n_baseclasses; ++i)
+ {
+ tree basetype;
+ tree v;
+
+ basetype = TYPE_BINFO_BASETYPE (t, i);
+ for (v = CLASSTYPE_VBASECLASSES (basetype);
+ v;
+ v = TREE_CHAIN (v))
+ {
+ tree b = TREE_VALUE (v);
+ if ((BINFO_PRIMARY_MARKED_P (b)
+ || BINFO_INDIRECT_PRIMARY_P (b))
+ && same_type_p (BINFO_TYPE (b), BINFO_TYPE (binfo)))
+ {
+ BINFO_INDIRECT_PRIMARY_P (binfo) = 1;
+ break;
+ }
+ }
+
+ /* If we've discovered that this virtual base is an indirect
+ primary base, then we can move on to the next virtual
+ base. */
+ if (BINFO_INDIRECT_PRIMARY_P (binfo))
+ break;
+ }
+ }
+
/* The new ABI allows for the use of a "nearly-empty" virtual base
class as the primary base class if no non-virtual polymorphic
base can be found. */
if (flag_new_abi && !CLASSTYPE_HAS_PRIMARY_BASE_P (t))
{
! /* If not NULL, this is the best primary base candidate we have
! found so far. */
! tree candidate = NULL_TREE;
! tree base_binfo;
/* Loop over the baseclasses. */
! for (base_binfo = TYPE_BINFO (t);
! base_binfo;
! base_binfo = TREE_CHAIN (base_binfo))
{
tree basetype = BINFO_TYPE (base_binfo);
if (TREE_VIA_VIRTUAL (base_binfo)
&& CLASSTYPE_NEARLY_EMPTY_P (basetype))
{
/* If this is not an indirect primary base, then it's
definitely our primary base. */
! if (!BINFO_INDIRECT_PRIMARY_P (base_binfo))
{
! candidate = base_binfo;
break;
}
/* If this was an indirect primary base, it's still our
primary base -- unless there's another nearly-empty
virtual base that isn't an indirect primary base. */
! else if (!candidate)
! candidate = base_binfo;
}
}
/* If we've got a primary base, use it. */
! if (candidate)
{
set_primary_base (t, candidate, vfuns_p);
CLASSTYPE_VFIELDS (t)
! = copy_list (CLASSTYPE_VFIELDS (BINFO_TYPE (candidate)));
}
}
*************** dfs_find_final_overrider (binfo, data)
*** 2475,2483 ****
{
tree base;
! /* Assume the path is non-virtual. See if there are any base from
! (but not including) the overrider up to and including the
! base where the function is defined. */
for (base = TREE_CHAIN (path); base; base = TREE_CHAIN (base))
if (TREE_VIA_VIRTUAL (TREE_VALUE (base)))
{
--- 2474,2483 ----
{
tree base;
! /* Assume the path is non-virtual. See if there are any
! virtual bases from (but not including) the overrider up
! to and including the base where the function is
! defined. */
for (base = TREE_CHAIN (path); base; base = TREE_CHAIN (base))
if (TREE_VIA_VIRTUAL (TREE_VALUE (base)))
{
*************** update_vtable_entry_for_fn (t, binfo, fn
*** 2612,2618 ****
tree primary_base;
tree f;
! primary_base = BINFO_PRIMARY_BINFO (b);
if (!primary_base)
break;
--- 2612,2618 ----
tree primary_base;
tree f;
! primary_base = get_primary_binfo (b);
if (!primary_base)
break;
*************** layout_nonempty_base_or_field (rli, decl
*** 3792,3798 ****
/* Now that we know where it wil be placed, update its
BINFO_OFFSET. */
offset = byte_position (decl);
! if (binfo)
propagate_binfo_offsets (binfo,
convert (ssizetype, offset));
--- 3792,3798 ----
/* Now that we know where it wil be placed, update its
BINFO_OFFSET. */
offset = byte_position (decl);
! if (binfo && CLASS_TYPE_P (BINFO_TYPE (binfo)))
propagate_binfo_offsets (binfo,
convert (ssizetype, offset));
*************** build_base_fields (rli, empty_p)
*** 3978,3990 ****
{
tree base_binfo;
/* Under the new ABI, the primary base was already allocated
above, so we don't need to allocate it again here. */
! if (flag_new_abi && i == CLASSTYPE_VFIELD_PARENT (rec))
continue;
- base_binfo = BINFO_BASETYPE (TYPE_BINFO (rec), i);
-
/* A primary virtual base class is allocated just like any other
base class, but a non-primary virtual base is allocated
later, in layout_virtual_bases. */
--- 3978,3990 ----
{
tree base_binfo;
+ base_binfo = BINFO_BASETYPE (TYPE_BINFO (rec), i);
+
/* Under the new ABI, the primary base was already allocated
above, so we don't need to allocate it again here. */
! if (flag_new_abi && base_binfo == CLASSTYPE_PRIMARY_BINFO (rec))
continue;
/* A primary virtual base class is allocated just like any other
base class, but a non-primary virtual base is allocated
later, in layout_virtual_bases. */
*************** fixup_inline_methods (type)
*** 4486,4551 ****
CLASSTYPE_INLINE_FRIENDS (type) = NULL_TREE;
}
- /* Called from propagate_binfo_offsets via dfs_walk. */
-
- static tree
- dfs_propagate_binfo_offsets (binfo, data)
- tree binfo;
- void *data;
- {
- tree offset = (tree) data;
-
- /* Update the BINFO_OFFSET for this base. Allow for the case where it
- might be negative. */
- BINFO_OFFSET (binfo)
- = convert (sizetype, size_binop (PLUS_EXPR,
- convert (ssizetype, BINFO_OFFSET (binfo)),
- offset));
- SET_BINFO_MARKED (binfo);
-
- return NULL_TREE;
- }
-
/* Add OFFSET to all base types of BINFO which is a base in the
hierarchy dominated by T.
-
- OFFSET, which is a type offset, is number of bytes.
! Note that we don't have to worry about having two paths to the
! same base type, since this type owns its association list. */
static void
propagate_binfo_offsets (binfo, offset)
tree binfo;
tree offset;
{
! dfs_walk (binfo,
! dfs_propagate_binfo_offsets,
! dfs_skip_nonprimary_vbases_unmarkedp,
! offset);
! dfs_walk (binfo,
! dfs_unmark,
! dfs_skip_nonprimary_vbases_markedp,
! NULL);
! }
!
! /* Called via dfs_walk from layout_virtual bases. */
! static tree
! dfs_set_offset_for_shared_vbases (binfo, data)
! tree binfo;
! void *data;
! {
! if (TREE_VIA_VIRTUAL (binfo) && BINFO_PRIMARY_MARKED_P (binfo))
{
! /* Update the shared copy. */
! tree shared_binfo;
! shared_binfo = binfo_for_vbase (BINFO_TYPE (binfo), (tree) data);
! BINFO_OFFSET (shared_binfo) = BINFO_OFFSET (binfo);
! }
! return NULL_TREE;
}
/* Called via dfs_walk from layout_virtual bases. */
--- 4486,4545 ----
CLASSTYPE_INLINE_FRIENDS (type) = NULL_TREE;
}
/* Add OFFSET to all base types of BINFO which is a base in the
hierarchy dominated by T.
! OFFSET, which is a type offset, is number of bytes. */
static void
propagate_binfo_offsets (binfo, offset)
tree binfo;
tree offset;
{
! int i;
! tree primary_binfo;
! /* Update BINFO's offset. */
! BINFO_OFFSET (binfo)
! = convert (sizetype,
! size_binop (PLUS_EXPR,
! convert (ssizetype, BINFO_OFFSET (binfo)),
! offset));
!
! /* Find the primary base class. */
! primary_binfo = get_primary_binfo (binfo);
!
! /* Scan all of the bases, pushing the BINFO_OFFSET adjust
! downwards. */
! for (i = -1; i < BINFO_N_BASETYPES (binfo); ++i)
{
! tree base_binfo;
! /* On the first through the loop, do the primary base. Because
! the primary base need not be an immediate base, we must
! handle the primary base specially. */
! if (i == -1)
! {
! if (!primary_binfo)
! continue;
! base_binfo = primary_binfo;
! }
! else
! {
! base_binfo = BINFO_BASETYPE (binfo, i);
! /* Don't do the primary base twice. */
! if (base_binfo == primary_binfo)
! continue;
! }
!
! /* Skip virtual bases that aren't our primary base. */
! if (TREE_VIA_VIRTUAL (base_binfo)
! && BINFO_PRIMARY_BASE_OF (base_binfo) != binfo)
! continue;
!
! propagate_binfo_offsets (base_binfo, offset);
! }
}
/* Called via dfs_walk from layout_virtual bases. */
*************** layout_virtual_bases (t, base_offsets)
*** 4622,4628 ****
else
vbase = TREE_VALUE (vbases);
! if (!BINFO_VBASE_PRIMARY_P (vbase))
{
/* This virtual base is not a primary base of any class in the
hierarchy, so we have to add space for it. */
--- 4616,4622 ----
else
vbase = TREE_VALUE (vbases);
! if (!BINFO_PRIMARY_MARKED_P (vbase))
{
/* This virtual base is not a primary base of any class in the
hierarchy, so we have to add space for it. */
*************** layout_virtual_bases (t, base_offsets)
*** 4673,4688 ****
}
}
! /* Make sure that all of the CLASSTYPE_VBASECLASSES have their
! BINFO_OFFSET set correctly. Those we just allocated certainly
! will. The others are primary baseclasses; we walk the hierarchy
! to find the primary copies and update the shared copy. */
! dfs_walk (TYPE_BINFO (t),
! dfs_set_offset_for_shared_vbases,
! dfs_unmarked_real_bases_queue_p,
! t);
!
! /* Now, go through the TYPE_BINFO hierarchy again, setting the
BINFO_OFFSETs correctly for all non-primary copies of the virtual
bases and their direct and indirect bases. The ambiguity checks
in get_base_distance depend on the BINFO_OFFSETs being set
--- 4667,4673 ----
}
}
! /* Now, go through the TYPE_BINFO hierarchy, setting the
BINFO_OFFSETs correctly for all non-primary copies of the virtual
bases and their direct and indirect bases. The ambiguity checks
in get_base_distance depend on the BINFO_OFFSETs being set
*************** layout_class_type (t, empty_p, vfuns_p,
*** 4942,4949 ****
CLASSTYPE_SIZE (t) = bitsize_zero_node;
CLASSTYPE_SIZE_UNIT (t) = size_zero_node;
}
! else if (flag_new_abi && TYPE_HAS_COMPLEX_INIT_REF (t)
! && TYPE_HAS_COMPLEX_ASSIGN_REF (t))
{
CLASSTYPE_SIZE (t) = TYPE_BINFO_SIZE (t);
CLASSTYPE_SIZE_UNIT (t) = TYPE_BINFO_SIZE_UNIT (t);
--- 4927,4933 ----
CLASSTYPE_SIZE (t) = bitsize_zero_node;
CLASSTYPE_SIZE_UNIT (t) = size_zero_node;
}
! else if (flag_new_abi)
{
CLASSTYPE_SIZE (t) = TYPE_BINFO_SIZE (t);
CLASSTYPE_SIZE_UNIT (t) = TYPE_BINFO_SIZE_UNIT (t);
*************** finish_struct_1 (t)
*** 5034,5040 ****
make sure we lay it out again. */
TYPE_SIZE (t) = NULL_TREE;
CLASSTYPE_GOT_SEMICOLON (t) = 0;
! CLASSTYPE_VFIELD_PARENT (t) = -1;
vfuns = 0;
CLASSTYPE_RTTI (t) = NULL_TREE;
--- 5018,5024 ----
make sure we lay it out again. */
TYPE_SIZE (t) = NULL_TREE;
CLASSTYPE_GOT_SEMICOLON (t) = 0;
! CLASSTYPE_PRIMARY_BINFO (t) = NULL_TREE;
vfuns = 0;
CLASSTYPE_RTTI (t) = NULL_TREE;
*************** get_vtbl_decl_for_binfo (binfo)
*** 6472,6477 ****
--- 6456,6521 ----
return decl;
}
+ static tree
+ dfs_get_primary_binfo (binfo, data)
+ tree binfo;
+ void *data;
+ {
+ tree primary_base = (tree) data;
+
+ if (TREE_VIA_VIRTUAL (binfo)
+ && same_type_p (TREE_TYPE (binfo), TREE_TYPE (primary_base)))
+ return binfo;
+
+ return NULL_TREE;
+ }
+
+ /* Returns the binfo for the primary base of BINFO. Note that in a
+ complex hierarchy the resulting BINFO may not actually *be*
+ primary. In particular if the resulting BINFO is a virtual base,
+ and it occurs elsewhere in the hierarchy, then this occurrence may
+ not actually be a primary base in the complete object. Check
+ BINFO_PRIMARY_MARKED_P to be sure. */
+
+ tree
+ get_primary_binfo (binfo)
+ tree binfo;
+ {
+ tree primary_base;
+ tree result;
+
+ primary_base = CLASSTYPE_PRIMARY_BINFO (BINFO_TYPE (binfo));
+ if (!primary_base)
+ return NULL_TREE;
+
+ /* A non-virtual primary base is always a direct base, and easy to
+ find. */
+ if (!TREE_VIA_VIRTUAL (primary_base))
+ {
+ int i;
+
+ /* Scan the direct basetypes until we find a base with the same
+ type as the primary base. */
+ for (i = 0; i < BINFO_N_BASETYPES (binfo); ++i)
+ {
+ tree base_binfo = BINFO_BASETYPE (binfo, i);
+
+ if (same_type_p (BINFO_TYPE (base_binfo),
+ BINFO_TYPE (primary_base)))
+ return base_binfo;
+ }
+
+ /* We should always find the primary base. */
+ my_friendly_abort (20000729);
+ }
+
+ /* For a primary virtual base, we have to scan the entire hierarchy
+ rooted at BINFO; the virtual base be an indirect virtual base. */
+ result = dfs_walk (binfo, dfs_get_primary_binfo, NULL, primary_base);
+ my_friendly_assert (result != NULL_TREE, 20000730);
+ return result;
+ }
+
/* Dump the offsets of all the bases rooted at BINFO (in the hierarchy
dominated by T) to stderr. INDENT should be zero when called from
the top level; it is incremented recursively. */
*************** dump_class_hierarchy_r (t, binfo, indent
*** 6493,6500 ****
fprintf (stderr, " virtual");
if (BINFO_PRIMARY_MARKED_P (binfo)
|| (TREE_VIA_VIRTUAL (binfo)
! && BINFO_VBASE_PRIMARY_P (binfo_for_vbase (BINFO_TYPE (binfo),
! t))))
fprintf (stderr, " primary");
fprintf (stderr, "\n");
--- 6537,6544 ----
fprintf (stderr, " virtual");
if (BINFO_PRIMARY_MARKED_P (binfo)
|| (TREE_VIA_VIRTUAL (binfo)
! && BINFO_PRIMARY_MARKED_P (binfo_for_vbase (BINFO_TYPE (binfo),
! t))))
fprintf (stderr, " primary");
fprintf (stderr, "\n");
*************** dfs_accumulate_vtbl_inits (binfo, orig_b
*** 7021,7027 ****
is part of the hierarchy dominated by T. If we're building a
construction vtable, the ORIG_BINFO is the binfo we should use to
find the actual function pointers to put in the vtable. Otherwise,
! ORIG_BINFO should be the same as BINFO. The RTTI_DOMINATOR is the
BINFO that should be indicated by the RTTI information in the
vtable; it will be a base class of T, rather than T itself, if we
are building a construction vtable.
--- 7065,7071 ----
is part of the hierarchy dominated by T. If we're building a
construction vtable, the ORIG_BINFO is the binfo we should use to
find the actual function pointers to put in the vtable. Otherwise,
! ORIG_BINFO should be the same as BINFO. The RTTI_BINFO is the
BINFO that should be indicated by the RTTI information in the
vtable; it will be a base class of T, rather than T itself, if we
are building a construction vtable.
*************** dfs_accumulate_vtbl_inits (binfo, orig_b
*** 7029,7036 ****
The value returned is a TREE_LIST suitable for wrapping in a
CONSTRUCTOR to use as the DECL_INITIAL for a vtable. If
NON_FN_ENTRIES_P is not NULL, *NON_FN_ENTRIES_P is set to the
! number of non-function entries in the vtable. */
static tree
build_vtbl_initializer (binfo, orig_binfo, t, rtti_binfo, non_fn_entries_p)
tree binfo;
--- 7073,7087 ----
The value returned is a TREE_LIST suitable for wrapping in a
CONSTRUCTOR to use as the DECL_INITIAL for a vtable. If
NON_FN_ENTRIES_P is not NULL, *NON_FN_ENTRIES_P is set to the
! number of non-function entries in the vtable.
+ It might seem that this function should never be called with a
+ BINFO for which BINFO_PRIMARY_MARKED_P holds, the vtable for such a
+ base is always subsumed by a derived class vtable. However, when
+ we are building construction vtables we do build vtables for
+ primary bases; we need these while the primary base is being
+ constructed. */
+
static tree
build_vtbl_initializer (binfo, orig_binfo, t, rtti_binfo, non_fn_entries_p)
tree binfo;
*************** build_vtbl_initializer (binfo, orig_binf
*** 7040,7062 ****
int *non_fn_entries_p;
{
tree v;
! tree vfun_inits;
tree vbase;
! vcall_offset_data vod;
! /* Initialize those parts of VOD that matter. */
! vod.derived = t;
! vod.inits = NULL_TREE;
! vod.last_init = &vod.inits;
! vod.primary_p = (binfo == TYPE_BINFO (t));
/* The first vbase or vcall offset is at index -3 in the vtable. */
! vod.index = ssize_int (-3);
/* Add entries to the vtable for RTTI. */
! build_rtti_vtbl_entries (binfo, rtti_binfo, &vod);
/* Add the vcall and vbase offset entries. */
! build_vcall_and_vbase_vtbl_entries (binfo, &vod);
/* Clear BINFO_VTABLE_PAATH_MARKED; it's set by
build_vbase_offset_vtbl_entries. */
for (vbase = CLASSTYPE_VBASECLASSES (t);
--- 7091,7115 ----
int *non_fn_entries_p;
{
tree v;
! tree vfun_inits;
tree vbase;
! vtbl_init_data vid;
! /* Initialize VID. */
! vid.binfo = binfo;
! vid.derived = t;
! vid.inits = NULL_TREE;
! vid.last_init = &vid.inits;
! vid.primary_vtbl_p = (binfo == TYPE_BINFO (t));
! vid.ctor_vtbl_p = !same_type_p (BINFO_TYPE (rtti_binfo), t);
/* The first vbase or vcall offset is at index -3 in the vtable. */
! vid.index = ssize_int (-3);
/* Add entries to the vtable for RTTI. */
! build_rtti_vtbl_entries (binfo, rtti_binfo, &vid);
/* Add the vcall and vbase offset entries. */
! build_vcall_and_vbase_vtbl_entries (binfo, &vid);
/* Clear BINFO_VTABLE_PAATH_MARKED; it's set by
build_vbase_offset_vtbl_entries. */
for (vbase = CLASSTYPE_VBASECLASSES (t);
*************** build_vtbl_initializer (binfo, orig_binf
*** 7065,7071 ****
CLEAR_BINFO_VTABLE_PATH_MARKED (TREE_VALUE (vbase));
if (non_fn_entries_p)
! *non_fn_entries_p = list_length (vod.inits);
/* Go through all the ordinary virtual functions, building up
initializers. */
--- 7118,7124 ----
CLEAR_BINFO_VTABLE_PATH_MARKED (TREE_VALUE (vbase));
if (non_fn_entries_p)
! *non_fn_entries_p = list_length (vid.inits);
/* Go through all the ordinary virtual functions, building up
initializers. */
*************** build_vtbl_initializer (binfo, orig_binf
*** 7116,7147 ****
vfun_inits = nreverse (vfun_inits);
/* The negative offset initializers are also in reverse order. */
! vod.inits = nreverse (vod.inits);
/* Chain the two together. */
! return chainon (vod.inits, vfun_inits);
}
! /* Sets vod->inits to be the initializers for the vbase and vcall
offsets in BINFO, which is in the hierarchy dominated by T. */
static void
! build_vcall_and_vbase_vtbl_entries (binfo, vod)
tree binfo;
! vcall_offset_data *vod;
{
tree b;
/* If this is a derived class, we must first create entries
corresponding to the primary base class. */
! b = BINFO_PRIMARY_BINFO (binfo);
if (b)
! build_vcall_and_vbase_vtbl_entries (b, vod);
/* Add the vbase entries for this base. */
! build_vbase_offset_vtbl_entries (binfo, vod);
/* Add the vcall entries for this base. */
! build_vcall_offset_vtbl_entries (binfo, vod);
}
/* Returns the initializers for the vbase offset entries in the vtable
--- 7169,7200 ----
vfun_inits = nreverse (vfun_inits);
/* The negative offset initializers are also in reverse order. */
! vid.inits = nreverse (vid.inits);
/* Chain the two together. */
! return chainon (vid.inits, vfun_inits);
}
! /* Sets vid->inits to be the initializers for the vbase and vcall
offsets in BINFO, which is in the hierarchy dominated by T. */
static void
! build_vcall_and_vbase_vtbl_entries (binfo, vid)
tree binfo;
! vtbl_init_data *vid;
{
tree b;
/* If this is a derived class, we must first create entries
corresponding to the primary base class. */
! b = get_primary_binfo (binfo);
if (b)
! build_vcall_and_vbase_vtbl_entries (b, vid);
/* Add the vbase entries for this base. */
! build_vbase_offset_vtbl_entries (binfo, vid);
/* Add the vcall entries for this base. */
! build_vcall_offset_vtbl_entries (binfo, vid);
}
/* Returns the initializers for the vbase offset entries in the vtable
*************** build_vcall_and_vbase_vtbl_entries (binf
*** 7150,7158 ****
where the next vbase offset will go. */
static void
! build_vbase_offset_vtbl_entries (binfo, vod)
tree binfo;
! vcall_offset_data *vod;
{
tree vbase;
tree t;
--- 7203,7211 ----
where the next vbase offset will go. */
static void
! build_vbase_offset_vtbl_entries (binfo, vid)
tree binfo;
! vtbl_init_data *vid;
{
tree vbase;
tree t;
*************** build_vbase_offset_vtbl_entries (binfo,
*** 7167,7173 ****
if (!TYPE_USES_VIRTUAL_BASECLASSES (BINFO_TYPE (binfo)))
return;
! t = vod->derived;
/* Go through the virtual bases, adding the offsets. */
for (vbase = TYPE_BINFO (BINFO_TYPE (binfo));
--- 7220,7226 ----
if (!TYPE_USES_VIRTUAL_BASECLASSES (BINFO_TYPE (binfo)))
return;
! t = vid->derived;
/* Go through the virtual bases, adding the offsets. */
for (vbase = TYPE_BINFO (BINFO_TYPE (binfo));
*************** build_vbase_offset_vtbl_entries (binfo,
*** 7192,7201 ****
/* Figure out where we can find this vbase offset. */
delta = size_binop (MULT_EXPR,
! vod->index,
convert (ssizetype,
TYPE_SIZE_UNIT (vtable_entry_type)));
! if (vod->primary_p)
BINFO_VPTR_FIELD (b) = delta;
if (binfo != TYPE_BINFO (t))
--- 7245,7254 ----
/* Figure out where we can find this vbase offset. */
delta = size_binop (MULT_EXPR,
! vid->index,
convert (ssizetype,
TYPE_SIZE_UNIT (vtable_entry_type)));
! if (vid->primary_vtbl_p)
BINFO_VPTR_FIELD (b) = delta;
if (binfo != TYPE_BINFO (t))
*************** build_vbase_offset_vtbl_entries (binfo,
*** 7213,7231 ****
}
/* The next vbase will come at a more negative offset. */
! vod->index = size_binop (MINUS_EXPR, vod->index, ssize_int (1));
/* The initializer is the delta from BINFO to this virtual base.
The vbase offsets go in reverse inheritance-graph order, and
we are walking in inheritance graph order so these end up in
the right order. */
delta = size_diffop (BINFO_OFFSET (b), BINFO_OFFSET (binfo));
! *vod->last_init
= build_tree_list (NULL_TREE,
fold (build1 (NOP_EXPR,
vtable_entry_type,
delta)));
! vod->last_init = &TREE_CHAIN (*vod->last_init);
}
}
--- 7266,7284 ----
}
/* The next vbase will come at a more negative offset. */
! vid->index = size_binop (MINUS_EXPR, vid->index, ssize_int (1));
/* The initializer is the delta from BINFO to this virtual base.
The vbase offsets go in reverse inheritance-graph order, and
we are walking in inheritance graph order so these end up in
the right order. */
delta = size_diffop (BINFO_OFFSET (b), BINFO_OFFSET (binfo));
! *vid->last_init
= build_tree_list (NULL_TREE,
fold (build1 (NOP_EXPR,
vtable_entry_type,
delta)));
! vid->last_init = &TREE_CHAIN (*vid->last_init);
}
}
*************** dfs_build_vcall_offset_vtbl_entries (bin
*** 7236,7242 ****
tree binfo;
void *data;
{
! vcall_offset_data* vod;
tree derived_virtuals;
tree base_virtuals;
tree binfo_inits;
--- 7289,7295 ----
tree binfo;
void *data;
{
! vtbl_init_data* vid;
tree derived_virtuals;
tree base_virtuals;
tree binfo_inits;
*************** dfs_build_vcall_offset_vtbl_entries (bin
*** 7247,7253 ****
tree primary_binfo;
int i;
! vod = (vcall_offset_data *) data;
binfo_inits = NULL_TREE;
/* We might be a primary base class. Go up the inheritance
--- 7300,7306 ----
tree primary_binfo;
int i;
! vid = (vtbl_init_data *) data;
binfo_inits = NULL_TREE;
/* We might be a primary base class. Go up the inheritance
*************** dfs_build_vcall_offset_vtbl_entries (bin
*** 7256,7263 ****
non_primary_binfo = binfo;
while (BINFO_INHERITANCE_CHAIN (non_primary_binfo))
{
! tree b = BINFO_INHERITANCE_CHAIN (non_primary_binfo);
! if (BINFO_PRIMARY_BINFO (b) != non_primary_binfo)
break;
non_primary_binfo = b;
}
--- 7309,7329 ----
non_primary_binfo = binfo;
while (BINFO_INHERITANCE_CHAIN (non_primary_binfo))
{
! tree b;
!
! /* If we have reached a virtual base, then it must be the
! virtual base for which we are building vcall offsets. In
! turn, the virtual base must be a (possibly indirect) primary
! base of the class that we are initializing, or we wouldn't
! care about its vtable offsets. */
! if (TREE_VIA_VIRTUAL (non_primary_binfo))
! {
! non_primary_binfo = vid->binfo;
! break;
! }
!
! b = BINFO_INHERITANCE_CHAIN (non_primary_binfo);
! if (get_primary_binfo (b) != non_primary_binfo)
break;
non_primary_binfo = b;
}
*************** dfs_build_vcall_offset_vtbl_entries (bin
*** 7266,7272 ****
class. */
base_virtuals = BINFO_VIRTUALS (binfo);
derived_virtuals = BINFO_VIRTUALS (non_primary_binfo);
! primary_binfo = BINFO_PRIMARY_BINFO (binfo);
if (primary_binfo)
for (i = 0; i < CLASSTYPE_VSIZE (BINFO_TYPE (primary_binfo)); ++i)
{
--- 7332,7338 ----
class. */
base_virtuals = BINFO_VIRTUALS (binfo);
derived_virtuals = BINFO_VIRTUALS (non_primary_binfo);
! primary_binfo = get_primary_binfo (binfo);
if (primary_binfo)
for (i = 0; i < CLASSTYPE_VSIZE (BINFO_TYPE (primary_binfo)); ++i)
{
*************** dfs_build_vcall_offset_vtbl_entries (bin
*** 7289,7299 ****
signature as FN, then we do not need a second vcall offset.
Check the list of functions already present in the derived
class vtable. */
! for (i = 0; i < VARRAY_ACTIVE_SIZE (vod->fns); ++i)
{
tree derived_entry;
! derived_entry = VARRAY_TREE (vod->fns, i);
if (same_signature_p (BV_FN (derived_entry), fn))
{
BV_VCALL_INDEX (derived_virtuals)
--- 7355,7365 ----
signature as FN, then we do not need a second vcall offset.
Check the list of functions already present in the derived
class vtable. */
! for (i = 0; i < VARRAY_ACTIVE_SIZE (vid->fns); ++i)
{
tree derived_entry;
! derived_entry = VARRAY_TREE (vid->fns, i);
if (same_signature_p (BV_FN (derived_entry), fn))
{
BV_VCALL_INDEX (derived_virtuals)
*************** dfs_build_vcall_offset_vtbl_entries (bin
*** 7301,7342 ****
break;
}
}
! if (i != VARRAY_ACTIVE_SIZE (vod->fns))
continue;
/* The FN comes from BASE. So, we must caculate the adjustment
from the virtual base that derived from BINFO to BASE. */
base = DECL_CONTEXT (fn);
! base_binfo = get_binfo (base, vod->derived, /*protect=*/0);
/* Compute the vcall offset. */
! *vod->last_init
= (build_tree_list
(NULL_TREE,
fold (build1 (NOP_EXPR, vtable_entry_type,
size_diffop (BINFO_OFFSET (base_binfo),
! BINFO_OFFSET (vod->vbase))))));
! vod->last_init = &TREE_CHAIN (*vod->last_init);
- /* If there is already a vcall index, then we are processing a
- construction vtable. The index should be the same as it was
- when we processed the vtable for the base class. */
- if (BV_VCALL_INDEX (derived_virtuals))
- my_friendly_assert (tree_int_cst_equal (BV_VCALL_INDEX
- (derived_virtuals),
- vod->index),
- 20000516);
/* Keep track of the vtable index where this vcall offset can be
! found. */
! else
! BV_VCALL_INDEX (derived_virtuals) = vod->index;
/* The next vcall offset will be found at a more negative
offset. */
! vod->index = size_binop (MINUS_EXPR, vod->index, ssize_int (1));
/* Keep track of this function. */
! VARRAY_PUSH_TREE (vod->fns, derived_virtuals);
}
return NULL_TREE;
--- 7367,7401 ----
break;
}
}
! if (i != VARRAY_ACTIVE_SIZE (vid->fns))
continue;
/* The FN comes from BASE. So, we must caculate the adjustment
from the virtual base that derived from BINFO to BASE. */
base = DECL_CONTEXT (fn);
! base_binfo = get_binfo (base, vid->derived, /*protect=*/0);
/* Compute the vcall offset. */
! *vid->last_init
= (build_tree_list
(NULL_TREE,
fold (build1 (NOP_EXPR, vtable_entry_type,
size_diffop (BINFO_OFFSET (base_binfo),
! BINFO_OFFSET (vid->vbase))))));
! vid->last_init = &TREE_CHAIN (*vid->last_init);
/* Keep track of the vtable index where this vcall offset can be
! found. For a construction vtable, we already made this
! annotation when we build the original vtable. */
! if (!vid->ctor_vtbl_p)
! BV_VCALL_INDEX (derived_virtuals) = vid->index;
/* The next vcall offset will be found at a more negative
offset. */
! vid->index = size_binop (MINUS_EXPR, vid->index, ssize_int (1));
/* Keep track of this function. */
! VARRAY_PUSH_TREE (vid->fns, derived_virtuals);
}
return NULL_TREE;
*************** dfs_build_vcall_offset_vtbl_entries (bin
*** 7344,7355 ****
/* Adds the initializers for the vcall offset entries in the vtable
for BINFO (which is part of the class hierarchy dominated by T) to
! VOD->INITS. */
static void
! build_vcall_offset_vtbl_entries (binfo, vod)
tree binfo;
! vcall_offset_data *vod;
{
/* Under the old ABI, the adjustments to the `this' pointer were made
elsewhere. */
--- 7403,7414 ----
/* Adds the initializers for the vcall offset entries in the vtable
for BINFO (which is part of the class hierarchy dominated by T) to
! VID->INITS. */
static void
! build_vcall_offset_vtbl_entries (binfo, vid)
tree binfo;
! vtbl_init_data *vid;
{
/* Under the old ABI, the adjustments to the `this' pointer were made
elsewhere. */
*************** build_vcall_offset_vtbl_entries (binfo,
*** 7382,7395 ****
in our non-virtual bases vtables. For each base, the entries
appear in the same order as in the base; but the bases themselves
appear in reverse depth-first, left-to-right order. */
! vod->vbase = binfo;
! VARRAY_TREE_INIT (vod->fns, 32, "fns");
dfs_walk_real (binfo,
dfs_build_vcall_offset_vtbl_entries,
NULL,
dfs_skip_vbases,
! vod);
! VARRAY_FREE (vod->fns);
}
/* Return vtbl initializers for the RTTI entries coresponding to the
--- 7441,7454 ----
in our non-virtual bases vtables. For each base, the entries
appear in the same order as in the base; but the bases themselves
appear in reverse depth-first, left-to-right order. */
! vid->vbase = binfo;
! VARRAY_TREE_INIT (vid->fns, 32, "fns");
dfs_walk_real (binfo,
dfs_build_vcall_offset_vtbl_entries,
NULL,
dfs_skip_vbases,
! vid);
! VARRAY_FREE (vid->fns);
}
/* Return vtbl initializers for the RTTI entries coresponding to the
*************** build_vcall_offset_vtbl_entries (binfo,
*** 7397,7406 ****
by RTTI_BINFO. */
static void
! build_rtti_vtbl_entries (binfo, rtti_binfo, vod)
tree binfo;
tree rtti_binfo;
! vcall_offset_data *vod;
{
tree b;
tree t;
--- 7456,7465 ----
by RTTI_BINFO. */
static void
! build_rtti_vtbl_entries (binfo, rtti_binfo, vid)
tree binfo;
tree rtti_binfo;
! vtbl_init_data *vid;
{
tree b;
tree t;
*************** build_rtti_vtbl_entries (binfo, rtti_bin
*** 7423,7429 ****
{
tree primary_base;
! primary_base = BINFO_PRIMARY_BINFO (b);
if (!BINFO_PRIMARY_MARKED_P (primary_base))
break;
b = primary_base;
--- 7482,7488 ----
{
tree primary_base;
! primary_base = get_primary_binfo (b);
if (!BINFO_PRIMARY_MARKED_P (primary_base))
break;
b = primary_base;
*************** build_rtti_vtbl_entries (binfo, rtti_bin
*** 7459,7466 ****
init = build_vtable_entry (offset, NULL_TREE, init,
/*generate_with_vtable_p=*/0);
}
! *vod->last_init = build_tree_list (NULL_TREE, init);
! vod->last_init = &TREE_CHAIN (*vod->last_init);
/* Add the offset-to-top entry. It comes earlier in the vtable that
the the typeinfo entry. */
--- 7518,7525 ----
init = build_vtable_entry (offset, NULL_TREE, init,
/*generate_with_vtable_p=*/0);
}
! *vid->last_init = build_tree_list (NULL_TREE, init);
! vid->last_init = &TREE_CHAIN (*vid->last_init);
/* Add the offset-to-top entry. It comes earlier in the vtable that
the the typeinfo entry. */
*************** build_rtti_vtbl_entries (binfo, rtti_bin
*** 7470,7477 ****
we can put it in the vtable. */
init = build1 (NOP_EXPR, vfunc_ptr_type_node, offset);
TREE_CONSTANT (init) = 1;
! *vod->last_init = build_tree_list (NULL_TREE, init);
! vod->last_init = &TREE_CHAIN (*vod->last_init);
}
}
--- 7529,7536 ----
we can put it in the vtable. */
init = build1 (NOP_EXPR, vfunc_ptr_type_node, offset);
TREE_CONSTANT (init) = 1;
! *vid->last_init = build_tree_list (NULL_TREE, init);
! vid->last_init = &TREE_CHAIN (*vid->last_init);
}
}
Index: cp-tree.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/cp-tree.h,v
retrieving revision 1.503
diff -c -p -r1.503 cp-tree.h
*** cp-tree.h 2000/07/28 06:05:08 1.503
--- cp-tree.h 2000/07/31 00:04:43
*************** Boston, MA 02111-1307, USA. */
*** 69,77 ****
or FIELD_DECL).
NEED_TEMPORARY_P (in REF_BIND, BASE_CONV)
IDENTIFIER_TYPENAME_P (in IDENTIFIER_NODE)
! 5: BINFO_PRIMARY_MARKED_P (in BINFO)
! 6: BINFO_VBASE_PRIMARY_P (in BINFO)
! BINFO_ACCESS (in BINFO)
Usage of TYPE_LANG_FLAG_?:
0: C_TYPE_FIELDS_READONLY (in RECORD_TYPE or UNION_TYPE).
--- 69,76 ----
or FIELD_DECL).
NEED_TEMPORARY_P (in REF_BIND, BASE_CONV)
IDENTIFIER_TYPENAME_P (in IDENTIFIER_NODE)
! 5: Unused.
! 6: BINFO_ACCESS (in BINFO)
Usage of TYPE_LANG_FLAG_?:
0: C_TYPE_FIELDS_READONLY (in RECORD_TYPE or UNION_TYPE).
*************** Boston, MA 02111-1307, USA. */
*** 100,106 ****
DECL_THUNK_P (in a member FUNCTION_DECL)
Usage of language-independent fields in a language-dependent manner:
!
TYPE_ALIAS_SET
This field is used by TYPENAME_TYPEs, TEMPLATE_TYPE_PARMs, and so
forth as a substitute for the mark bits provided in `lang_type'.
--- 99,108 ----
DECL_THUNK_P (in a member FUNCTION_DECL)
Usage of language-independent fields in a language-dependent manner:
!
! TREE_USED
! This field is BINFO_INDIRECT_PRIMARY_P in a BINFO.
!
TYPE_ALIAS_SET
This field is used by TYPENAME_TYPEs, TEMPLATE_TYPE_PARMs, and so
forth as a substitute for the mark bits provided in `lang_type'.
*************** struct lang_type
*** 1391,1398 ****
unsigned dummy : 8;
int vsize;
- int vfield_parent;
tree vfields;
tree vbases;
tree tags;
--- 1393,1400 ----
unsigned dummy : 8;
int vsize;
+ tree primary_base;
tree vfields;
tree vbases;
tree tags;
*************** struct lang_type
*** 1562,1596 ****
nested member class templates. */
#define CLASSTYPE_TAGS(NODE) (TYPE_LANG_SPECIFIC(NODE)->tags)
- /* 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) \
! (BINFO_PRIMARY_BINFO (TYPE_BINFO (NODE)))
- /* If non-NULL, this is the binfo for the primary base of BINFO. Note
- that in a complex hierarchy the resulting BINFO may not actually
- *be* primary. In particular if the resulting BINFO is a virtual
- base, and it occurs elsewhere in the hierarchy, then this
- occurrence may not actually be a primary base in the complete
- object. Check BINFO_PRIMARY_MARKED_P to be sure. */
- #define BINFO_PRIMARY_BINFO(NODE) \
- (CLASSTYPE_HAS_PRIMARY_BASE_P (BINFO_TYPE (NODE)) \
- ? BINFO_BASETYPE (NODE, \
- CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (NODE))) \
- : NULL_TREE)
-
/* The number of virtual functions present in this class' virtual
function table. */
#define CLASSTYPE_VSIZE(NODE) (TYPE_LANG_SPECIFIC(NODE)->vsize)
--- 1564,1580 ----
nested member class templates. */
#define CLASSTYPE_TAGS(NODE) (TYPE_LANG_SPECIFIC(NODE)->tags)
/* 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_PRIMARY_BINFO (NODE) != NULL_TREE)
/* 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) \
! (TYPE_LANG_SPECIFIC (NODE)->primary_base)
/* The number of virtual functions present in this class' virtual
function table. */
#define CLASSTYPE_VSIZE(NODE) (TYPE_LANG_SPECIFIC(NODE)->vsize)
*************** struct lang_type
*** 1752,1762 ****
class of a non-primary virtual base. This flag is only valid for
paths (given by BINFO_INHERITANCE_CHAIN) that really exist in the
final object. */
! #define BINFO_PRIMARY_MARKED_P(NODE) TREE_LANG_FLAG_5 (NODE)
!
! /* Nonzero if the virtual baseclass with the type given by this BINFO
! is primary *somewhere* in the hierarchy. */
! #define BINFO_VBASE_PRIMARY_P(NODE) TREE_LANG_FLAG_6 (NODE)
/* The index in the VTT where this subobject's sub-VTT can be found.
NULL_TREE if there is no sub-VTT. */
--- 1736,1743 ----
class of a non-primary virtual base. This flag is only valid for
paths (given by BINFO_INHERITANCE_CHAIN) that really exist in the
final object. */
! #define BINFO_PRIMARY_MARKED_P(NODE) \
! (BINFO_PRIMARY_BASE_OF (NODE) != NULL_TREE)
/* The index in the VTT where this subobject's sub-VTT can be found.
NULL_TREE if there is no sub-VTT. */
*************** struct lang_type
*** 1766,1775 ****
--- 1747,1767 ----
found. NULL_TREE if there is no secondary vptr in the VTT. */
#define BINFO_VPTR_INDEX(NODE) TREE_VEC_ELT ((NODE), 9)
+ /* The binfo of which NODE is a primary base. (This is different from
+ BINFO_INHERITANCE_CHAIN for virtual base because a virtual base is
+ sometimes a primary base for a class for which it is not an
+ immediate base.) */
+ #define BINFO_PRIMARY_BASE_OF(NODE) TREE_VEC_ELT ((NODE), 10)
+
/* Nonzero if this binfo declares a virtual function which is
overridden along a virtual path. */
#define BINFO_OVERRIDE_ALONG_VIRTUAL_PATH_P(NODE) TREE_LANG_FLAG_2 (NODE)
+ /* Nonzero if this binfo is an indirect primary base, i.e. a virtual
+ base that is a primary base of some of other class in the
+ hierarchy. */
+ #define BINFO_INDIRECT_PRIMARY_P(NODE) TREE_USED (NODE)
+
/* Used by various search routines. */
#define IDENTIFIER_MARKED(NODE) TREE_LANG_FLAG_0 (NODE)
\f
*************** extern void note_name_declared_in_class
*** 3844,3849 ****
--- 3836,3842 ----
extern tree get_vtbl_decl_for_binfo PARAMS ((tree));
extern tree in_charge_arg_for_name PARAMS ((tree));
extern tree get_vtt_name PARAMS ((tree));
+ extern tree get_primary_binfo PARAMS ((tree));
/* in cvt.c */
extern tree convert_to_reference PARAMS ((tree, tree, int, int, tree));
Index: decl.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/decl.c,v
retrieving revision 1.664
diff -c -p -r1.664 decl.c
*** decl.c 2000/07/28 06:05:09 1.664
--- decl.c 2000/07/31 00:04:52
*************** lang_mark_tree (t)
*** 15007,15012 ****
--- 15007,15013 ----
&& TREE_CODE (TREE_TYPE (t)) == METHOD_TYPE))
{
ggc_mark (lt);
+ ggc_mark_tree (lt->primary_base);
ggc_mark_tree (lt->vfields);
ggc_mark_tree (lt->vbases);
ggc_mark_tree (lt->tags);
Index: search.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/search.c,v
retrieving revision 1.186
diff -c -p -r1.186 search.c
*** search.c 2000/06/30 00:26:03 1.186
--- search.c 2000/07/31 00:04:54
*************** get_shared_vbase_if_not_primary (binfo,
*** 2199,2205 ****
/* This is a non-primary virtual base. If there is no primary
version, get the shared version. */
binfo = binfo_for_vbase (BINFO_TYPE (binfo), type);
! if (BINFO_VBASE_PRIMARY_P (binfo))
return NULL_TREE;
}
--- 2199,2205 ----
/* This is a non-primary virtual base. If there is no primary
version, get the shared version. */
binfo = binfo_for_vbase (BINFO_TYPE (binfo), type);
! if (BINFO_PRIMARY_MARKED_P (binfo))
return NULL_TREE;
}
*************** find_vbase_instance (base, type)
*** 2883,2889 ****
tree instance;
instance = binfo_for_vbase (base, type);
! if (!BINFO_VBASE_PRIMARY_P (instance))
return instance;
return dfs_walk (TYPE_BINFO (type),
--- 2883,2889 ----
tree instance;
instance = binfo_for_vbase (base, type);
! if (!BINFO_PRIMARY_MARKED_P (instance))
return instance;
return dfs_walk (TYPE_BINFO (type),
*************** binfo_for_vtable (var)
*** 3357,3377 ****
tree var;
{
tree binfo = TYPE_BINFO (DECL_CONTEXT (var));
- tree binfos;
- int i;
-
- while (1)
- {
- binfos = BINFO_BASETYPES (binfo);
- if (binfos == NULL_TREE)
- break;
! i = CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (binfo));
! if (i == -1)
! break;
!
! binfo = TREE_VEC_ELT (binfos, i);
! }
return binfo;
}
--- 3357,3365 ----
tree var;
{
tree binfo = TYPE_BINFO (DECL_CONTEXT (var));
! while (CLASSTYPE_HAS_PRIMARY_BASE_P (BINFO_TYPE (binfo)))
! binfo = get_primary_binfo (binfo);
return binfo;
}
Index: tree.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/tree.c,v
retrieving revision 1.207
diff -c -p -r1.207 tree.c
*** tree.c 2000/07/27 21:10:29 1.207
--- tree.c 2000/07/31 00:04:56
*************** unshare_base_binfos (binfo)
*** 687,692 ****
--- 687,693 ----
TREE_VIA_PROTECTED (new_binfo) = TREE_VIA_PROTECTED (base_binfo);
TREE_VIA_VIRTUAL (new_binfo) = TREE_VIA_VIRTUAL (base_binfo);
BINFO_INHERITANCE_CHAIN (new_binfo) = binfo;
+ BINFO_PRIMARY_BASE_OF (new_binfo) = NULL_TREE;
unshare_base_binfos (new_binfo);
}
}
*************** make_binfo (offset, binfo, vtable, virtu
*** 851,857 ****
tree offset, binfo;
tree vtable, virtuals;
{
! tree new_binfo = make_tree_vec (10);
tree type;
if (TREE_CODE (binfo) == TREE_VEC)
--- 852,858 ----
tree offset, binfo;
tree vtable, virtuals;
{
! tree new_binfo = make_tree_vec (11);
tree type;
if (TREE_CODE (binfo) == TREE_VEC)
reply other threads:[~2000-07-30 17:21 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20000730172116N.mitchell@codesourcery.com \
--to=mark@codesourcery.com \
--cc=gcc@gcc.gnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).