cp-tree.h (BINFO_VIRTUALS): Tweak documentation.
* cp-tree.h (BINFO_VIRTUALS): Tweak documentation. (CLASSTYPE_PRIMARY_BINFO): Use BINFO_PRIMARY_BINFO. (BINFO_PRIMARY_BINFO): New macro. (BF_DELTA): Rename to ... (BV_DELTA): ... this. (BF_VCALL_INDEX): Rename to ... (BV_VCALL_INDEX): ... this. (BF_FN): Rename to ... (BV_FN): ... this. * class.c (build_vbase_path): Adjust for changes to reverse_path. (set_rtti_entry): Rename BF_ macros to BV_ variants. (modify_vtable_entry): Simplify. (add_virtual_function): Rename BF_ macros to BV_ variants. (build_vtable_initializer): Likewise. (get_class_offset_1): Remove. (dfs_get_class_offset): Likewise. (get_class_offset): Likewise. (dfs_find_final_overrider): New function. (find_final_overrider): Likewise. (modify_one_vtable): Remove. (dfs_find_base): New function. (dfs_modify_vtables): Fold modify_one_vtable in here. Use find_final_overrider. (modify_all_vtables): Adjust. Set BV_VCALL_INDEX on new virtuals. (dfs_fixup_vtable_deltas): Remove. (override_one_vtable): Remove. (merge_overrides): Likewise. (layout_virtual_bases): Make sure BINFO_OFFSET is set right for unreal chilren of virtual bases. (finish_struct_1): Don't use merge_overrides. Don't use dfs_fixup_vtable_deltas. * tree.c (reverse_path): Return a TREE_LIST, not a chain of BINFOs. From-SVN: r31724
This commit is contained in:
parent
d4cf5733ee
commit
5e19c05390
@ -1,3 +1,40 @@
|
||||
2000-01-31 Mark Mitchell <mark@codesourcery.com>
|
||||
|
||||
* cp-tree.h (BINFO_VIRTUALS): Tweak documentation.
|
||||
(CLASSTYPE_PRIMARY_BINFO): Use BINFO_PRIMARY_BINFO.
|
||||
(BINFO_PRIMARY_BINFO): New macro.
|
||||
(BF_DELTA): Rename to ...
|
||||
(BV_DELTA): ... this.
|
||||
(BF_VCALL_INDEX): Rename to ...
|
||||
(BV_VCALL_INDEX): ... this.
|
||||
(BF_FN): Rename to ...
|
||||
(BV_FN): ... this.
|
||||
* class.c (build_vbase_path): Adjust for changes to reverse_path.
|
||||
(set_rtti_entry): Rename BF_ macros to BV_ variants.
|
||||
(modify_vtable_entry): Simplify.
|
||||
(add_virtual_function): Rename BF_ macros to BV_ variants.
|
||||
(build_vtable_initializer): Likewise.
|
||||
(get_class_offset_1): Remove.
|
||||
(dfs_get_class_offset): Likewise.
|
||||
(get_class_offset): Likewise.
|
||||
(dfs_find_final_overrider): New function.
|
||||
(find_final_overrider): Likewise.
|
||||
(modify_one_vtable): Remove.
|
||||
(dfs_find_base): New function.
|
||||
(dfs_modify_vtables): Fold modify_one_vtable in here. Use
|
||||
find_final_overrider.
|
||||
(modify_all_vtables): Adjust. Set BV_VCALL_INDEX on new
|
||||
virtuals.
|
||||
(dfs_fixup_vtable_deltas): Remove.
|
||||
(override_one_vtable): Remove.
|
||||
(merge_overrides): Likewise.
|
||||
(layout_virtual_bases): Make sure BINFO_OFFSET is set right for
|
||||
unreal chilren of virtual bases.
|
||||
(finish_struct_1): Don't use merge_overrides. Don't use
|
||||
dfs_fixup_vtable_deltas.
|
||||
* tree.c (reverse_path): Return a TREE_LIST, not a chain of
|
||||
BINFOs.
|
||||
|
||||
2000-01-31 Herman A.J. ten Brugge <Haj.Ten.Brugge@net.HCC.nl>
|
||||
Jason Merrill <jason@yorick.cygnus.com>
|
||||
|
||||
|
692
gcc/cp/class.c
692
gcc/cp/class.c
@ -82,10 +82,9 @@ static tree get_basefndecls PARAMS ((tree, tree));
|
||||
static void set_rtti_entry PARAMS ((tree, tree, tree));
|
||||
static int build_primary_vtable PARAMS ((tree, tree));
|
||||
static int build_secondary_vtable PARAMS ((tree, tree));
|
||||
static tree dfs_fixup_vtable_deltas PARAMS ((tree, void *));
|
||||
static tree dfs_finish_vtbls PARAMS ((tree, void *));
|
||||
static void finish_vtbls PARAMS ((tree));
|
||||
static void modify_vtable_entry PARAMS ((tree, tree, tree, tree *));
|
||||
static void modify_vtable_entry PARAMS ((tree, tree, tree, tree, tree *));
|
||||
static void add_virtual_function PARAMS ((tree *, tree *, int *, tree, tree));
|
||||
static tree delete_duplicate_fields_1 PARAMS ((tree, tree));
|
||||
static void delete_duplicate_fields PARAMS ((tree));
|
||||
@ -94,13 +93,8 @@ static int alter_access PARAMS ((tree, tree, tree, tree));
|
||||
static void handle_using_decl PARAMS ((tree, tree));
|
||||
static int overrides PARAMS ((tree, tree));
|
||||
static int strictly_overrides PARAMS ((tree, tree));
|
||||
static void merge_overrides PARAMS ((tree, tree, int, tree));
|
||||
static void override_one_vtable PARAMS ((tree, tree, tree));
|
||||
static void mark_overriders PARAMS ((tree, tree));
|
||||
static void check_for_override PARAMS ((tree, tree));
|
||||
static tree dfs_get_class_offset PARAMS ((tree, void *));
|
||||
static tree get_class_offset PARAMS ((tree, tree, tree, tree));
|
||||
static void modify_one_vtable PARAMS ((tree, tree, tree));
|
||||
static tree dfs_modify_vtables PARAMS ((tree, void *));
|
||||
static tree modify_all_vtables PARAMS ((tree, int *, tree));
|
||||
static void determine_primary_base PARAMS ((tree, int *));
|
||||
@ -151,6 +145,9 @@ static tree dfs_count_virtuals PARAMS ((tree, void *));
|
||||
static void start_vtable PARAMS ((tree, int *));
|
||||
static void layout_vtable_decl PARAMS ((tree, int));
|
||||
static int num_vfun_entries PARAMS ((tree));
|
||||
static tree dfs_find_final_overrider PARAMS ((tree, void *));
|
||||
static tree find_final_overrider PARAMS ((tree, tree, tree));
|
||||
static tree dfs_find_base PARAMS ((tree, void *));
|
||||
static int make_new_vtable PARAMS ((tree, tree));
|
||||
|
||||
/* Variables shared between class.c and call.c. */
|
||||
@ -558,16 +555,15 @@ build_vbase_path (code, type, expr, path, nonnull)
|
||||
expr = save_expr (expr);
|
||||
nonnull_expr = expr;
|
||||
|
||||
if (BINFO_INHERITANCE_CHAIN (path))
|
||||
path = reverse_path (path);
|
||||
path = reverse_path (path);
|
||||
|
||||
basetype = BINFO_TYPE (path);
|
||||
|
||||
while (path)
|
||||
{
|
||||
if (TREE_VIA_VIRTUAL (path))
|
||||
if (TREE_VIA_VIRTUAL (TREE_VALUE (path)))
|
||||
{
|
||||
last_virtual = BINFO_TYPE (path);
|
||||
last_virtual = BINFO_TYPE (TREE_VALUE (path));
|
||||
if (code == PLUS_EXPR)
|
||||
{
|
||||
changed = ! fixed_type_p;
|
||||
@ -609,8 +605,8 @@ build_vbase_path (code, type, expr, path, nonnull)
|
||||
return error_mark_node;
|
||||
}
|
||||
}
|
||||
last = path;
|
||||
path = BINFO_INHERITANCE_CHAIN (path);
|
||||
last = TREE_VALUE (path);
|
||||
path = TREE_CHAIN (path);
|
||||
}
|
||||
/* LAST is now the last basetype assoc on the path. */
|
||||
|
||||
@ -981,8 +977,8 @@ set_rtti_entry (virtuals, offset, type)
|
||||
if (flag_vtable_thunks)
|
||||
{
|
||||
/* The first slot holds the offset. */
|
||||
BF_DELTA (virtuals) = offset;
|
||||
BF_VCALL_INDEX (virtuals) = integer_zero_node;
|
||||
BV_DELTA (virtuals) = offset;
|
||||
BV_VCALL_INDEX (virtuals) = integer_zero_node;
|
||||
|
||||
/* The next node holds the decl. */
|
||||
virtuals = TREE_CHAIN (virtuals);
|
||||
@ -990,9 +986,9 @@ set_rtti_entry (virtuals, offset, type)
|
||||
}
|
||||
|
||||
/* This slot holds the function to call. */
|
||||
BF_DELTA (virtuals) = offset;
|
||||
BF_VCALL_INDEX (virtuals) = integer_zero_node;
|
||||
BF_FN (virtuals) = decl;
|
||||
BV_DELTA (virtuals) = offset;
|
||||
BV_VCALL_INDEX (virtuals) = integer_zero_node;
|
||||
BV_FN (virtuals) = decl;
|
||||
}
|
||||
|
||||
/* Get the VAR_DECL of the vtable for TYPE. TYPE need not be polymorphic,
|
||||
@ -1289,44 +1285,27 @@ make_new_vtable (t, binfo)
|
||||
|
||||
/* Make *VIRTUALS, an entry on the BINFO_VIRTUALS list for BINFO
|
||||
(which is in the hierarchy dominated by T) list FNDECL as its
|
||||
BF_FN. */
|
||||
BV_FN. DELTA is the required adjustment from the `this' pointer
|
||||
where the vtable entry appears to the `this' required when the
|
||||
function is actually called. */
|
||||
|
||||
static void
|
||||
modify_vtable_entry (t, binfo, fndecl, virtuals)
|
||||
modify_vtable_entry (t, binfo, fndecl, delta, virtuals)
|
||||
tree t;
|
||||
tree binfo;
|
||||
tree fndecl;
|
||||
tree delta;
|
||||
tree *virtuals;
|
||||
{
|
||||
tree base_offset;
|
||||
tree offset;
|
||||
tree context;
|
||||
tree this_offset;
|
||||
tree vcall_index;
|
||||
tree v;
|
||||
|
||||
v = *virtuals;
|
||||
context = DECL_CLASS_CONTEXT (fndecl);
|
||||
offset = get_class_offset (context, t, binfo, fndecl);
|
||||
|
||||
/* Find the right offset for ythe this pointer based on the
|
||||
base class we just found. We have to take into
|
||||
consideration the virtual base class pointers that we
|
||||
stick in before the virtual function table pointer.
|
||||
|
||||
Also, we want just the delta between the most base class
|
||||
that we derived this vfield from and us. */
|
||||
base_offset
|
||||
= size_binop (PLUS_EXPR,
|
||||
get_derived_offset (binfo,
|
||||
DECL_VIRTUAL_CONTEXT (BF_FN (v))),
|
||||
BINFO_OFFSET (binfo));
|
||||
this_offset = ssize_binop (MINUS_EXPR, offset, base_offset);
|
||||
vcall_index = integer_zero_node;
|
||||
|
||||
if (fndecl != BF_FN (v)
|
||||
|| !tree_int_cst_equal (this_offset, BF_DELTA (v))
|
||||
|| !tree_int_cst_equal (vcall_index, BF_VCALL_INDEX (v)))
|
||||
if (fndecl != BV_FN (v)
|
||||
|| !tree_int_cst_equal (delta, BV_DELTA (v))
|
||||
|| !tree_int_cst_equal (vcall_index, BV_VCALL_INDEX (v)))
|
||||
{
|
||||
tree base_fndecl;
|
||||
|
||||
@ -1337,15 +1316,15 @@ modify_vtable_entry (t, binfo, fndecl, virtuals)
|
||||
of the BINFO_VIRTUALS list. Now, we have to find the
|
||||
corresponding entry in that list. */
|
||||
*virtuals = BINFO_VIRTUALS (binfo);
|
||||
while (BF_FN (*virtuals) != BF_FN (v))
|
||||
while (BV_FN (*virtuals) != BV_FN (v))
|
||||
*virtuals = TREE_CHAIN (*virtuals);
|
||||
v = *virtuals;
|
||||
}
|
||||
|
||||
base_fndecl = BF_FN (v);
|
||||
BF_DELTA (v) = this_offset;
|
||||
BF_VCALL_INDEX (v) = vcall_index;
|
||||
BF_FN (v) = fndecl;
|
||||
base_fndecl = BV_FN (v);
|
||||
BV_DELTA (v) = delta;
|
||||
BV_VCALL_INDEX (v) = vcall_index;
|
||||
BV_FN (v) = fndecl;
|
||||
|
||||
/* Now assign virtual dispatch information, if unset. We can
|
||||
dispatch this, through any overridden base function. */
|
||||
@ -1407,7 +1386,7 @@ add_virtual_function (new_virtuals_p, overridden_virtuals_p,
|
||||
return;
|
||||
|
||||
new_virtual = build_tree_list (integer_zero_node, fndecl);
|
||||
BF_VCALL_INDEX (new_virtual) = integer_zero_node;
|
||||
BV_VCALL_INDEX (new_virtual) = integer_zero_node;
|
||||
|
||||
if (DECL_VINDEX (fndecl) == error_mark_node)
|
||||
{
|
||||
@ -2713,9 +2692,9 @@ build_vtbl_initializer (binfo, t)
|
||||
|
||||
/* Pull the offset for `this', and the function to call, out of
|
||||
the list. */
|
||||
delta = BF_DELTA (v);
|
||||
vcall_index = BF_VCALL_INDEX (v);
|
||||
fn = BF_FN (v);
|
||||
delta = BV_DELTA (v);
|
||||
vcall_index = BV_VCALL_INDEX (v);
|
||||
fn = BV_FN (v);
|
||||
my_friendly_assert (TREE_CODE (delta) == INTEGER_CST, 19990727);
|
||||
my_friendly_assert (TREE_CODE (fn) == FUNCTION_DECL, 19990727);
|
||||
|
||||
@ -2812,127 +2791,151 @@ overrides (fndecl, base_fndecl)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Returns the BINFO_OFFSET for the base of BINFO that has the same
|
||||
type as CONTEXT. */
|
||||
typedef struct find_final_overrider_data_s {
|
||||
/* The function for which we are trying to find a final overrider. */
|
||||
tree fn;
|
||||
/* The base class in which the function was declared. */
|
||||
tree declaring_base;
|
||||
/* The most derived class in the hierarchy. */
|
||||
tree most_derived_type;
|
||||
/* The final overriding function. */
|
||||
tree overriding_fn;
|
||||
/* The BINFO for the class in which the final overriding function
|
||||
appears. */
|
||||
tree overriding_base;
|
||||
} find_final_overrider_data;
|
||||
|
||||
/* Called from find_final_overrider via dfs_walk. */
|
||||
|
||||
static tree
|
||||
get_class_offset_1 (parent, binfo, context, t, fndecl)
|
||||
tree parent, binfo, context, t, fndecl;
|
||||
{
|
||||
tree binfos = BINFO_BASETYPES (binfo);
|
||||
int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
|
||||
tree rval = NULL_TREE;
|
||||
|
||||
if (binfo == parent)
|
||||
return error_mark_node;
|
||||
|
||||
for (i = 0; i < n_baselinks; i++)
|
||||
{
|
||||
tree base_binfo = TREE_VEC_ELT (binfos, i);
|
||||
tree nrval;
|
||||
|
||||
if (TREE_VIA_VIRTUAL (base_binfo))
|
||||
base_binfo = BINFO_FOR_VBASE (BINFO_TYPE (base_binfo), t);
|
||||
nrval = get_class_offset_1 (parent, base_binfo, context, t, fndecl);
|
||||
/* See if we have a new value */
|
||||
if (nrval && (nrval != error_mark_node || rval==0))
|
||||
{
|
||||
/* Only compare if we have two offsets */
|
||||
if (rval && rval != error_mark_node
|
||||
&& ! tree_int_cst_equal (nrval, rval))
|
||||
{
|
||||
/* Only give error if the two offsets are different */
|
||||
error ("every virtual function must have a unique final overrider");
|
||||
cp_error (" found two (or more) `%T' class subobjects in `%T'", context, t);
|
||||
cp_error (" with virtual `%D' from virtual base class", fndecl);
|
||||
return rval;
|
||||
}
|
||||
rval = nrval;
|
||||
}
|
||||
|
||||
if (rval && BINFO_TYPE (binfo) == context)
|
||||
{
|
||||
my_friendly_assert (rval == error_mark_node
|
||||
|| tree_int_cst_equal (rval, BINFO_OFFSET (binfo)), 999);
|
||||
rval = BINFO_OFFSET (binfo);
|
||||
}
|
||||
}
|
||||
return rval;
|
||||
}
|
||||
|
||||
/* Called from get_class_offset via dfs_walk. */
|
||||
|
||||
static tree
|
||||
dfs_get_class_offset (binfo, data)
|
||||
dfs_find_final_overrider (binfo, data)
|
||||
tree binfo;
|
||||
void *data;
|
||||
{
|
||||
tree list = (tree) data;
|
||||
tree context = TREE_TYPE (list);
|
||||
find_final_overrider_data *ffod = (find_final_overrider_data *) data;
|
||||
|
||||
if (same_type_p (BINFO_TYPE (binfo), context))
|
||||
if (same_type_p (BINFO_TYPE (binfo),
|
||||
BINFO_TYPE (ffod->declaring_base))
|
||||
&& tree_int_cst_equal (BINFO_OFFSET (binfo),
|
||||
BINFO_OFFSET (ffod->declaring_base)))
|
||||
{
|
||||
if (TREE_VALUE (list))
|
||||
return error_mark_node;
|
||||
else
|
||||
TREE_VALUE (list) = BINFO_OFFSET (binfo);
|
||||
tree path;
|
||||
tree method;
|
||||
|
||||
/* We've found a path to the declaring base. Walk down the path
|
||||
looking for an overrider for FN. */
|
||||
for (path = reverse_path (binfo);
|
||||
path;
|
||||
path = TREE_CHAIN (path))
|
||||
{
|
||||
for (method = TYPE_METHODS (BINFO_TYPE (TREE_VALUE (path)));
|
||||
method;
|
||||
method = TREE_CHAIN (method))
|
||||
if (DECL_VIRTUAL_P (method) && overrides (method, ffod->fn))
|
||||
break;
|
||||
|
||||
if (method)
|
||||
break;
|
||||
}
|
||||
|
||||
/* If we found an overrider, record the overriding function, and
|
||||
the base from which it came. */
|
||||
if (path)
|
||||
{
|
||||
if (ffod->overriding_fn && ffod->overriding_fn != method)
|
||||
{
|
||||
/* We've found a different overrider along a different
|
||||
path. That can be OK if the new one overrides the
|
||||
old one. Consider:
|
||||
|
||||
struct S { virtual void f(); };
|
||||
struct T : public virtual S { virtual void f(); };
|
||||
struct U : public virtual S, public virtual T {};
|
||||
|
||||
Here `T::f' is the final overrider for `S::f'. */
|
||||
if (strictly_overrides (method, ffod->overriding_fn))
|
||||
{
|
||||
ffod->overriding_fn = method;
|
||||
ffod->overriding_base = TREE_VALUE (path);
|
||||
}
|
||||
else if (!strictly_overrides (ffod->overriding_fn, method))
|
||||
{
|
||||
cp_error ("no unique final overrider for `%D' in `%T'",
|
||||
ffod->most_derived_type,
|
||||
ffod->fn);
|
||||
cp_error ("candidates are: `%#D'", ffod->overriding_fn);
|
||||
cp_error (" `%#D'", method);
|
||||
return error_mark_node;
|
||||
}
|
||||
}
|
||||
else if (ffod->overriding_base
|
||||
&& (!tree_int_cst_equal
|
||||
(BINFO_OFFSET (TREE_VALUE (path)),
|
||||
BINFO_OFFSET (ffod->overriding_base))))
|
||||
{
|
||||
/* We've found two instances of the same base that
|
||||
provide overriders. */
|
||||
cp_error ("no unique final overrider for `%D' since there two instances of `%T' in `%T'",
|
||||
ffod->fn,
|
||||
BINFO_TYPE (ffod->overriding_base),
|
||||
ffod->most_derived_type);
|
||||
return error_mark_node;
|
||||
}
|
||||
else
|
||||
{
|
||||
ffod->overriding_fn = method;
|
||||
ffod->overriding_base = TREE_VALUE (path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SET_BINFO_MARKED (binfo);
|
||||
|
||||
return NULL_TREE;
|
||||
}
|
||||
|
||||
/* Returns the BINFO_OFFSET for the subobject of BINFO that has the
|
||||
type given by CONTEXT. */
|
||||
/* Returns a TREE_LIST whose TREE_PURPOSE is the final overrider for
|
||||
FN and whose TREE_VALUE is the binfo for the base where the
|
||||
overriding occurs. BINFO (in the hierarchy dominated by T) is the
|
||||
base object in which FN is declared. */
|
||||
|
||||
static tree
|
||||
get_class_offset (context, t, binfo, fndecl)
|
||||
tree context, t, binfo, fndecl;
|
||||
find_final_overrider (t, binfo, fn)
|
||||
tree t;
|
||||
tree binfo;
|
||||
tree fn;
|
||||
{
|
||||
tree list;
|
||||
tree offset;
|
||||
int i;
|
||||
find_final_overrider_data ffod;
|
||||
|
||||
if (context == t)
|
||||
return integer_zero_node;
|
||||
/* Getting this right is a little tricky. This is legal:
|
||||
|
||||
if (BINFO_TYPE (binfo) == context)
|
||||
return BINFO_OFFSET (binfo);
|
||||
struct S { virtual void f (); };
|
||||
struct T { virtual void f (); };
|
||||
struct U : public S, public T { };
|
||||
|
||||
/* Check less derived binfos first. */
|
||||
while (BINFO_BASETYPES (binfo)
|
||||
&& (i=CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (binfo))) != -1)
|
||||
{
|
||||
tree binfos = BINFO_BASETYPES (binfo);
|
||||
binfo = TREE_VEC_ELT (binfos, i);
|
||||
if (BINFO_TYPE (binfo) == context)
|
||||
return BINFO_OFFSET (binfo);
|
||||
}
|
||||
even though calling `f' in `U' is ambiguous. But,
|
||||
|
||||
list = build_tree_list (t, NULL_TREE);
|
||||
TREE_TYPE (list) = context;
|
||||
offset = dfs_walk (TYPE_BINFO (t),
|
||||
dfs_get_class_offset,
|
||||
dfs_unmarked_real_bases_queue_p,
|
||||
list);
|
||||
dfs_walk (TYPE_BINFO (t), dfs_unmark, dfs_marked_real_bases_queue_p, t);
|
||||
struct R { virtual void f(); };
|
||||
struct S : virtual public R { virtual void f (); };
|
||||
struct T : virtual public R { virtual void f (); };
|
||||
struct U : public S, public T { };
|
||||
|
||||
if (offset == error_mark_node)
|
||||
{
|
||||
error ("every virtual function must have a unique final overrider");
|
||||
cp_error (" found two (or more) `%T' class subobjects in `%T'",
|
||||
context, t);
|
||||
cp_error (" with virtual `%D' from virtual base class", fndecl);
|
||||
offset = integer_zero_node;
|
||||
}
|
||||
else
|
||||
offset = TREE_VALUE (list);
|
||||
is not -- there's no way to decide whether to put `S::f' or
|
||||
`T::f' in the vtable for `R'.
|
||||
|
||||
The solution is to look at all paths to BINFO. If we find
|
||||
different overriders along any two, then there is a problem. */
|
||||
ffod.fn = fn;
|
||||
ffod.declaring_base = binfo;
|
||||
ffod.most_derived_type = t;
|
||||
ffod.overriding_fn = NULL_TREE;
|
||||
ffod.overriding_base = NULL_TREE;
|
||||
|
||||
my_friendly_assert (offset != NULL_TREE, 999);
|
||||
my_friendly_assert (TREE_CODE (offset) == INTEGER_CST, 999);
|
||||
if (dfs_walk (TYPE_BINFO (t),
|
||||
dfs_find_final_overrider,
|
||||
NULL,
|
||||
&ffod))
|
||||
return error_mark_node;
|
||||
|
||||
return offset;
|
||||
return build_tree_list (ffod.overriding_fn, ffod.overriding_base);
|
||||
}
|
||||
|
||||
/* Return the BINFO_VIRTUALS list for BINFO, without the RTTI stuff at
|
||||
@ -2972,37 +2975,16 @@ skip_rtti_stuff (binfo, t, n)
|
||||
return virtuals;
|
||||
}
|
||||
|
||||
static void
|
||||
modify_one_vtable (binfo, t, fndecl)
|
||||
tree binfo, t, fndecl;
|
||||
/* Called via dfs_walk. Returns BINFO if BINFO has the same type as
|
||||
DATA (which is really an _TYPE node). */
|
||||
|
||||
static tree
|
||||
dfs_find_base (binfo, data)
|
||||
tree binfo;
|
||||
void *data;
|
||||
{
|
||||
tree virtuals;
|
||||
|
||||
/* If we're support RTTI then we always need a new vtable to point
|
||||
to the RTTI information. Under the new ABI we may need a new
|
||||
vtable to contain vcall and vbase offsets. */
|
||||
if (flag_rtti || flag_new_abi)
|
||||
make_new_vtable (t, binfo);
|
||||
|
||||
if (fndecl == NULL_TREE)
|
||||
return;
|
||||
|
||||
for (virtuals = skip_rtti_stuff (binfo, BINFO_TYPE (binfo), NULL);
|
||||
virtuals;
|
||||
virtuals = TREE_CHAIN (virtuals))
|
||||
{
|
||||
tree current_fndecl = BF_FN (virtuals);
|
||||
|
||||
/* We should never have an instance of __pure_virtual on the
|
||||
BINFO_VIRTUALS list. If we do, then we will never notice
|
||||
that the function that should have been there instead has
|
||||
been overridden. */
|
||||
my_friendly_assert (current_fndecl != abort_fndecl,
|
||||
19990727);
|
||||
|
||||
if (current_fndecl && overrides (fndecl, current_fndecl))
|
||||
modify_vtable_entry (t, binfo, fndecl, &virtuals);
|
||||
}
|
||||
return (same_type_p (BINFO_TYPE (binfo), (tree) data)
|
||||
? binfo : NULL_TREE);
|
||||
}
|
||||
|
||||
/* Called from modify_all_vtables via dfs_walk. */
|
||||
@ -3018,8 +3000,70 @@ dfs_modify_vtables (binfo, data)
|
||||
/* Similarly, a base without a vtable needs no modification. */
|
||||
&& CLASSTYPE_VFIELDS (BINFO_TYPE (binfo)))
|
||||
{
|
||||
tree list = (tree) data;
|
||||
modify_one_vtable (binfo, TREE_PURPOSE (list), TREE_VALUE (list));
|
||||
tree t;
|
||||
tree virtuals;
|
||||
tree old_virtuals;
|
||||
|
||||
t = (tree) data;
|
||||
|
||||
/* If we're support RTTI then we always need a new vtable to point
|
||||
to the RTTI information. Under the new ABI we may need a new
|
||||
vtable to contain vcall and vbase offsets. */
|
||||
if (flag_rtti || flag_new_abi)
|
||||
make_new_vtable (t, binfo);
|
||||
|
||||
/* Now, go through each of the virtual functions in the virtual
|
||||
function table for BINFO. Find the final overrider, and
|
||||
update the BINFO_VIRTUALS list appropriately. */
|
||||
for (virtuals = skip_rtti_stuff (binfo, BINFO_TYPE (binfo), NULL),
|
||||
old_virtuals = skip_rtti_stuff (TYPE_BINFO (BINFO_TYPE (binfo)),
|
||||
BINFO_TYPE (binfo),
|
||||
NULL);
|
||||
virtuals;
|
||||
virtuals = TREE_CHAIN (virtuals),
|
||||
old_virtuals = TREE_CHAIN (old_virtuals))
|
||||
{
|
||||
tree b;
|
||||
tree fn;
|
||||
tree overrider;
|
||||
tree vindex;
|
||||
tree delta;
|
||||
|
||||
/* Find the function which originally caused this vtable
|
||||
entry to be present. */
|
||||
fn = BV_FN (old_virtuals);
|
||||
vindex = DECL_VINDEX (fn);
|
||||
b = dfs_walk (binfo, dfs_find_base, NULL, DECL_VIRTUAL_CONTEXT (fn));
|
||||
fn = skip_rtti_stuff (TYPE_BINFO (BINFO_TYPE (b)),
|
||||
BINFO_TYPE (b),
|
||||
NULL);
|
||||
while (!tree_int_cst_equal (DECL_VINDEX (BV_FN (fn)), vindex))
|
||||
fn = TREE_CHAIN (fn);
|
||||
fn = BV_FN (fn);
|
||||
|
||||
/* Handle the case of a virtual function defined in BINFO
|
||||
itself. */
|
||||
overrider = find_final_overrider (t, b, fn);
|
||||
if (overrider == error_mark_node)
|
||||
continue;
|
||||
|
||||
/* The `this' pointer needs to be adjusted from pointing to
|
||||
BINFO to pointing at the base where the final overrider
|
||||
appears. */
|
||||
delta = size_binop (PLUS_EXPR,
|
||||
get_derived_offset (binfo,
|
||||
DECL_VIRTUAL_CONTEXT (fn)),
|
||||
BINFO_OFFSET (binfo));
|
||||
delta = ssize_binop (MINUS_EXPR,
|
||||
BINFO_OFFSET (TREE_VALUE (overrider)),
|
||||
delta);
|
||||
|
||||
modify_vtable_entry (t,
|
||||
binfo,
|
||||
TREE_PURPOSE (overrider),
|
||||
delta,
|
||||
&virtuals);
|
||||
}
|
||||
}
|
||||
|
||||
SET_BINFO_MARKED (binfo);
|
||||
@ -3042,26 +3086,16 @@ modify_all_vtables (t, has_virtual_p, overridden_virtuals)
|
||||
int *has_virtual_p;
|
||||
tree overridden_virtuals;
|
||||
{
|
||||
tree fns;
|
||||
tree binfo;
|
||||
|
||||
binfo = TYPE_BINFO (t);
|
||||
|
||||
/* Even if there are no overridden virtuals, we want to go through
|
||||
the hierarchy updating RTTI information. */
|
||||
if (!overridden_virtuals && TYPE_CONTAINS_VPTR_P (t) && flag_rtti)
|
||||
overridden_virtuals = build_tree_list (NULL_TREE, NULL_TREE);
|
||||
|
||||
/* Iterate through each of the overriding functions, updating the
|
||||
base vtables. */
|
||||
for (fns = overridden_virtuals; fns; fns = TREE_CHAIN (fns))
|
||||
{
|
||||
tree list;
|
||||
list = build_tree_list (t, TREE_VALUE (fns));
|
||||
dfs_walk (binfo, dfs_modify_vtables,
|
||||
dfs_unmarked_real_bases_queue_p, list);
|
||||
dfs_walk (binfo, dfs_unmark, dfs_marked_real_bases_queue_p, t);
|
||||
}
|
||||
/* Update all of the vtables. */
|
||||
dfs_walk (binfo,
|
||||
dfs_modify_vtables,
|
||||
dfs_unmarked_real_bases_queue_p,
|
||||
t);
|
||||
dfs_walk (binfo, dfs_unmark, dfs_marked_real_bases_queue_p, t);
|
||||
|
||||
/* If we should include overriding functions for secondary vtables
|
||||
in our primary vtable, add them now. */
|
||||
@ -3086,7 +3120,8 @@ modify_all_vtables (t, has_virtual_p, overridden_virtuals)
|
||||
DECL_VIRTUAL_CONTEXT (fn) = t;
|
||||
/* We don't need to adjust the `this' pointer when
|
||||
calling this function. */
|
||||
TREE_PURPOSE (*fnsp) = integer_zero_node;
|
||||
BV_DELTA (*fnsp) = integer_zero_node;
|
||||
BV_VCALL_INDEX (*fnsp) = integer_zero_node;
|
||||
|
||||
/* This is an overridden function not already in our
|
||||
vtable. Keep it. */
|
||||
@ -3104,37 +3139,6 @@ modify_all_vtables (t, has_virtual_p, overridden_virtuals)
|
||||
return overridden_virtuals;
|
||||
}
|
||||
|
||||
/* Fixup all the delta entries in this one vtable that need updating. */
|
||||
|
||||
static tree
|
||||
dfs_fixup_vtable_deltas (binfo, data)
|
||||
tree binfo;
|
||||
void *data;
|
||||
{
|
||||
tree virtuals;
|
||||
tree t = (tree) data;
|
||||
|
||||
while (BINFO_PRIMARY_MARKED_P (binfo))
|
||||
{
|
||||
binfo = BINFO_INHERITANCE_CHAIN (binfo);
|
||||
/* If BINFO is virtual then we'll handle this base later. */
|
||||
if (TREE_VIA_VIRTUAL (binfo))
|
||||
return NULL_TREE;
|
||||
}
|
||||
|
||||
for (virtuals = skip_rtti_stuff (binfo, BINFO_TYPE (binfo), NULL);
|
||||
virtuals;
|
||||
virtuals = TREE_CHAIN (virtuals))
|
||||
{
|
||||
tree fndecl = BF_FN (virtuals);
|
||||
|
||||
if (fndecl)
|
||||
modify_vtable_entry (t, binfo, fndecl, &virtuals);
|
||||
}
|
||||
|
||||
return NULL_TREE;
|
||||
}
|
||||
|
||||
/* Here, we already know that they match in every respect.
|
||||
All we have to check is where they had their declarations. */
|
||||
|
||||
@ -3150,169 +3154,6 @@ strictly_overrides (fndecl1, fndecl2)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Merge overrides for one vtable.
|
||||
If we want to merge in same function, we are fine.
|
||||
else
|
||||
if one has a DECL_CLASS_CONTEXT that is a parent of the
|
||||
other, than choose the more derived one
|
||||
else
|
||||
potentially ill-formed (see 10.3 [class.virtual])
|
||||
we have to check later to see if there was an
|
||||
override in this class. If there was ok, if not
|
||||
then it is ill-formed. (mrs)
|
||||
|
||||
We take special care to reuse a vtable, if we can. */
|
||||
|
||||
static void
|
||||
override_one_vtable (binfo, old, t)
|
||||
tree binfo, old, t;
|
||||
{
|
||||
tree virtuals;
|
||||
tree old_virtuals;
|
||||
tree orig_binfo;
|
||||
tree orig_virtuals;
|
||||
enum { REUSE_NEW, REUSE_OLD, UNDECIDED, NEITHER } choose = UNDECIDED;
|
||||
|
||||
/* Either or both of BINFO or OLD might be primary base classes
|
||||
because merge_overrides is called with a vbase from the class we
|
||||
are definining and the corresponding vbase from one of its direct
|
||||
bases. */
|
||||
orig_binfo = binfo;
|
||||
while (BINFO_PRIMARY_MARKED_P (binfo))
|
||||
{
|
||||
binfo = BINFO_INHERITANCE_CHAIN (binfo);
|
||||
/* If BINFO is virtual, then we'll handle this virtual base when
|
||||
later. */
|
||||
if (TREE_VIA_VIRTUAL (binfo))
|
||||
return;
|
||||
}
|
||||
while (BINFO_PRIMARY_MARKED_P (old))
|
||||
old = BINFO_INHERITANCE_CHAIN (old);
|
||||
|
||||
/* If we have already committed to modifying it, then don't try and
|
||||
reuse another vtable. */
|
||||
if (BINFO_NEW_VTABLE_MARKED (binfo))
|
||||
choose = NEITHER;
|
||||
|
||||
virtuals = skip_rtti_stuff (binfo, BINFO_TYPE (binfo), NULL);
|
||||
old_virtuals = skip_rtti_stuff (old, BINFO_TYPE (binfo), NULL);
|
||||
orig_virtuals = skip_rtti_stuff (orig_binfo, BINFO_TYPE (binfo), NULL);
|
||||
|
||||
while (orig_virtuals)
|
||||
{
|
||||
tree fndecl = BF_FN (virtuals);
|
||||
tree old_fndecl = BF_FN (old_virtuals);
|
||||
|
||||
/* First check to see if they are the same. */
|
||||
if (DECL_ASSEMBLER_NAME (fndecl) == DECL_ASSEMBLER_NAME (old_fndecl))
|
||||
{
|
||||
/* No need to do anything. */
|
||||
}
|
||||
else if (strictly_overrides (fndecl, old_fndecl))
|
||||
{
|
||||
if (choose == UNDECIDED)
|
||||
choose = REUSE_NEW;
|
||||
else if (choose == REUSE_OLD)
|
||||
{
|
||||
choose = NEITHER;
|
||||
if (! BINFO_NEW_VTABLE_MARKED (binfo))
|
||||
{
|
||||
build_secondary_vtable (binfo, t);
|
||||
override_one_vtable (binfo, old, t);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (strictly_overrides (old_fndecl, fndecl))
|
||||
{
|
||||
if (choose == UNDECIDED)
|
||||
choose = REUSE_OLD;
|
||||
else if (choose == REUSE_NEW)
|
||||
{
|
||||
choose = NEITHER;
|
||||
if (! BINFO_NEW_VTABLE_MARKED (binfo))
|
||||
{
|
||||
build_secondary_vtable (binfo, t);
|
||||
override_one_vtable (binfo, old, t);
|
||||
return;
|
||||
}
|
||||
TREE_VALUE (virtuals) = TREE_VALUE (old_virtuals);
|
||||
}
|
||||
else if (choose == NEITHER)
|
||||
{
|
||||
TREE_VALUE (virtuals) = TREE_VALUE (old_virtuals);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
choose = NEITHER;
|
||||
if (! BINFO_NEW_VTABLE_MARKED (binfo))
|
||||
{
|
||||
build_secondary_vtable (binfo, t);
|
||||
override_one_vtable (binfo, old, t);
|
||||
return;
|
||||
}
|
||||
{
|
||||
/* This MUST be overridden, or the class is ill-formed. */
|
||||
tree fndecl = BF_FN (virtuals);
|
||||
|
||||
fndecl = copy_node (fndecl);
|
||||
copy_lang_decl (fndecl);
|
||||
DECL_NEEDS_FINAL_OVERRIDER_P (fndecl) = 1;
|
||||
/* Make sure we search for it later. */
|
||||
if (! CLASSTYPE_PURE_VIRTUALS (t))
|
||||
CLASSTYPE_PURE_VIRTUALS (t) = error_mark_node;
|
||||
|
||||
/* We can use integer_zero_node, as we will core dump
|
||||
if this is used anyway. */
|
||||
BF_DELTA (virtuals) = integer_zero_node;
|
||||
BF_FN (virtuals) = fndecl;
|
||||
}
|
||||
}
|
||||
virtuals = TREE_CHAIN (virtuals);
|
||||
old_virtuals = TREE_CHAIN (old_virtuals);
|
||||
orig_virtuals = TREE_CHAIN (orig_virtuals);
|
||||
}
|
||||
|
||||
/* Let's reuse the old vtable. */
|
||||
if (choose == REUSE_OLD)
|
||||
{
|
||||
BINFO_VTABLE (binfo) = BINFO_VTABLE (old);
|
||||
BINFO_VIRTUALS (binfo) = BINFO_VIRTUALS (old);
|
||||
}
|
||||
}
|
||||
|
||||
/* Merge in overrides for virtual bases.
|
||||
BINFO is the hierarchy we want to modify, and OLD has the potential
|
||||
overrides. */
|
||||
|
||||
static void
|
||||
merge_overrides (binfo, old, do_self, t)
|
||||
tree binfo, old;
|
||||
int do_self;
|
||||
tree t;
|
||||
{
|
||||
tree binfos = BINFO_BASETYPES (binfo);
|
||||
tree old_binfos = BINFO_BASETYPES (old);
|
||||
int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
|
||||
|
||||
/* Should we use something besides CLASSTYPE_VFIELDS? */
|
||||
if (do_self && CLASSTYPE_VFIELDS (BINFO_TYPE (binfo)))
|
||||
{
|
||||
override_one_vtable (binfo, old, t);
|
||||
}
|
||||
|
||||
for (i = 0; i < n_baselinks; i++)
|
||||
{
|
||||
tree base_binfo = TREE_VEC_ELT (binfos, i);
|
||||
tree old_base_binfo = TREE_VEC_ELT (old_binfos, i);
|
||||
int is_not_base_vtable
|
||||
= !BINFO_PRIMARY_MARKED_P (base_binfo);
|
||||
if (! TREE_VIA_VIRTUAL (base_binfo))
|
||||
merge_overrides (base_binfo, old_base_binfo, is_not_base_vtable, t);
|
||||
}
|
||||
}
|
||||
|
||||
/* Get the base virtual function declarations in T that are either
|
||||
overridden or hidden by FNDECL as a list. We set TREE_PURPOSE with
|
||||
the overrider/hider. */
|
||||
@ -4842,6 +4683,10 @@ layout_virtual_bases (t)
|
||||
in get_base_distance depend on the BINFO_OFFSETs being set
|
||||
correctly. */
|
||||
dfs_walk (TYPE_BINFO (t), dfs_set_offset_for_unshared_vbases, NULL, t);
|
||||
for (vbase = CLASSTYPE_VBASECLASSES (t);
|
||||
vbase;
|
||||
vbase = TREE_CHAIN (vbase))
|
||||
dfs_walk (vbase, dfs_set_offset_for_unshared_vbases, NULL, t);
|
||||
|
||||
/* Now, make sure that the total size of the type is a multiple of
|
||||
its alignment. */
|
||||
@ -5065,42 +4910,6 @@ finish_struct_1 (t)
|
||||
layout_class_type (t, &empty, &has_virtual,
|
||||
&new_virtuals, &overridden_virtuals);
|
||||
|
||||
if (TYPE_USES_VIRTUAL_BASECLASSES (t))
|
||||
{
|
||||
tree vbases;
|
||||
|
||||
vbases = CLASSTYPE_VBASECLASSES (t);
|
||||
|
||||
{
|
||||
/* Now fixup overrides of all functions in vtables from all
|
||||
direct or indirect virtual base classes. */
|
||||
tree binfos = BINFO_BASETYPES (TYPE_BINFO (t));
|
||||
int i, n_baseclasses = binfos ? TREE_VEC_LENGTH (binfos) : 0;
|
||||
|
||||
for (i = 0; i < n_baseclasses; i++)
|
||||
{
|
||||
tree base_binfo = TREE_VEC_ELT (binfos, i);
|
||||
tree basetype = BINFO_TYPE (base_binfo);
|
||||
tree vbases;
|
||||
|
||||
vbases = CLASSTYPE_VBASECLASSES (basetype);
|
||||
while (vbases)
|
||||
{
|
||||
tree vbase;
|
||||
tree basetype_vbase;
|
||||
|
||||
vbase
|
||||
= find_vbase_instance (BINFO_TYPE (vbases), t);
|
||||
basetype_vbase
|
||||
= find_vbase_instance (BINFO_TYPE (vbases), basetype);
|
||||
|
||||
merge_overrides (vbase, basetype_vbase, 1, t);
|
||||
vbases = TREE_CHAIN (vbases);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* 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. */
|
||||
@ -5126,28 +4935,7 @@ finish_struct_1 (t)
|
||||
overridden_virtuals
|
||||
= modify_all_vtables (t, &has_virtual, nreverse (overridden_virtuals));
|
||||
|
||||
if (TYPE_USES_VIRTUAL_BASECLASSES (t))
|
||||
{
|
||||
tree vbases;
|
||||
/* Now fixup any virtual function entries from virtual bases
|
||||
that have different deltas. This has to come after we do the
|
||||
overridden virtuals. */
|
||||
vbases = CLASSTYPE_VBASECLASSES (t);
|
||||
while (vbases)
|
||||
{
|
||||
tree vbase;
|
||||
|
||||
/* We might be able to shorten the amount of work we do by
|
||||
only doing this for vtables that come from virtual bases
|
||||
that have differing offsets, but don't want to miss any
|
||||
entries. */
|
||||
vbase = find_vbase_instance (BINFO_TYPE (vbases), t);
|
||||
dfs_walk (vbase, dfs_fixup_vtable_deltas, dfs_skip_vbases, t);
|
||||
vbases = TREE_CHAIN (vbases);
|
||||
}
|
||||
}
|
||||
|
||||
/* If necessary, create the vtable for this class. */
|
||||
/* If necessary, create the primary vtable for this class. */
|
||||
if (new_virtuals
|
||||
|| overridden_virtuals
|
||||
|| (TYPE_CONTAINS_VPTR_P (t) && vptrs_present_everywhere_p ()))
|
||||
|
@ -115,18 +115,22 @@ Boston, MA 02111-1307, USA. */
|
||||
For a static VAR_DECL, this is DECL_INIT_PRIORITY.
|
||||
|
||||
BINFO_VIRTUALS
|
||||
For a binfo, this is a TREE_LIST. The BF_DELTA of each node
|
||||
For a binfo, this is a TREE_LIST. The BV_DELTA of each node
|
||||
gives the amount by which to adjust the `this' pointer when
|
||||
calling the function. If the method is an overriden version of a
|
||||
base class method, then it is assumed that, prior to adjustment,
|
||||
the this pointer points to an object of the base class.
|
||||
|
||||
The BF_VCALL_INDEX of each node, if non-NULL, gives the vtable
|
||||
The BV_VCALL_INDEX of each node, if non-NULL, gives the vtable
|
||||
index of the vcall offset for this entry.
|
||||
|
||||
The BF_FN is the declaration for the virtual function itself.
|
||||
The BV_FN is the declaration for the virtual function itself.
|
||||
When CLASSTYPE_COM_INTERFACE_P does not hold, the first entry
|
||||
does not have a BF_FN; it is just an offset.
|
||||
does not have a BV_FN; it is just an offset.
|
||||
|
||||
The BV_OVERRIDING_BASE is the binfo for the final overrider for
|
||||
this function. (This binfo's BINFO_TYPE will always be the same
|
||||
as the DECL_CLASS_CONTEXT for the function.)
|
||||
|
||||
DECL_ARGUMENTS
|
||||
For a VAR_DECL this is DECL_ANON_UNION_ELEMS.
|
||||
@ -1500,10 +1504,14 @@ struct lang_type
|
||||
/* 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)) \
|
||||
#define CLASSTYPE_PRIMARY_BINFO(NODE) \
|
||||
(BINFO_PRIMARY_BINFO (TYPE_BINFO (NODE)))
|
||||
|
||||
/* If non-NULL, this is the binfo for the primary base of BINFO. */
|
||||
#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 defined for this
|
||||
@ -1726,14 +1734,16 @@ struct lang_type
|
||||
|
||||
/* The number of bytes by which to adjust the `this' pointer when
|
||||
calling this virtual function. */
|
||||
#define BF_DELTA(NODE) (TREE_PURPOSE (NODE))
|
||||
#define BV_DELTA(NODE) (TREE_PURPOSE (NODE))
|
||||
|
||||
/* If non-NULL, the vtable index at which to find the vcall offset
|
||||
when calling this virtual function. */
|
||||
#define BF_VCALL_INDEX(NODE) (TREE_TYPE (NODE))
|
||||
#define BV_VCALL_INDEX(NODE) (TREE_TYPE (NODE))
|
||||
|
||||
/* The function to call. */
|
||||
#define BF_FN(NODE) (TREE_VALUE (NODE))
|
||||
#define BV_FN(NODE) (TREE_VALUE (NODE))
|
||||
|
||||
/* The most derived class. */
|
||||
|
||||
|
||||
/* Nonzero for TREE_LIST node means that this list of things
|
||||
|
@ -883,23 +883,26 @@ binfo_value (elem, type)
|
||||
return get_binfo (elem, type, 0);
|
||||
}
|
||||
|
||||
/* Return a reversed copy of the BINFO-chain given by PATH. (If the
|
||||
BINFO_INHERITANCE_CHAIN points from base classes to derived
|
||||
classes, it will instead point from derived classes to base
|
||||
classes.) Returns the first node in the reversed chain. */
|
||||
/* Return a TREE_LIST whose TREE_VALUE nodes along the
|
||||
BINFO_INHERITANCE_CHAIN for BINFO, but in the opposite order. In
|
||||
other words, while the BINFO_INHERITANCE_CHAIN goes from base
|
||||
classes to derived classes, the reversed path goes from derived
|
||||
classes to base classes. */
|
||||
|
||||
tree
|
||||
reverse_path (path)
|
||||
tree path;
|
||||
reverse_path (binfo)
|
||||
tree binfo;
|
||||
{
|
||||
register tree prev = NULL_TREE, cur;
|
||||
for (cur = path; cur; cur = BINFO_INHERITANCE_CHAIN (cur))
|
||||
tree reversed_path;
|
||||
|
||||
reversed_path = NULL_TREE;
|
||||
while (binfo)
|
||||
{
|
||||
tree r = copy_node (cur);
|
||||
BINFO_INHERITANCE_CHAIN (r) = prev;
|
||||
prev = r;
|
||||
reversed_path = tree_cons (NULL_TREE, binfo, reversed_path);
|
||||
binfo = BINFO_INHERITANCE_CHAIN (binfo);
|
||||
}
|
||||
return prev;
|
||||
|
||||
return reversed_path;
|
||||
}
|
||||
|
||||
void
|
||||
|
Loading…
Reference in New Issue
Block a user