cp-tree.h (THUNK_GENERATE_WITH_VTABLE_P): Lose.
* cp-tree.h (THUNK_GENERATE_WITH_VTABLE_P): Lose. (struct lang_decl_flags): Lose generate_with_vtable_p. (BV_GENERATE_THUNK_WITH_VTABLE_P): Lose. * class.c (copy_virtuals): Adjust. * decl2.c (mark_vtable_entries): Adjust. * method.c (make_thunk, build_vtable_entry): Adjust. * class.c (update_vtable_entry_for_fn): Only look as far as the first defining class. (build_vtbl_initializer): Put nothing in the slot for a function only defined in a lost primary virtual base. (add_vcall_offset_vtbl_entries_1): Use the same code for the lost primary case and the normal case. (dfs_unshared_virtual_bases): Don't lose a non-virtual primary base. (get_vfield_offset, get_derived_offset): Lose. (dfs_find_final_overrider): Use look_for_overrides_here. (get_matching_virtual): New fn. * semantics.c (emit_associated_thunks): Check BV_USE_VCALL_INDEX_P, not BV_VCALL_INDEX. * search.c (look_for_overrides_here): Split out from... (look_for_overrides_r): Here. * class.c (find_final_overrider): Return error_mark_node on error. From-SVN: r42949
This commit is contained in:
parent
acf97e0b75
commit
d0cd8b4401
8 changed files with 272 additions and 258 deletions
|
@ -1,3 +1,30 @@
|
|||
2001-06-06 Jason Merrill <jason_merrill@redhat.com>
|
||||
|
||||
* cp-tree.h (THUNK_GENERATE_WITH_VTABLE_P): Lose.
|
||||
(struct lang_decl_flags): Lose generate_with_vtable_p.
|
||||
(BV_GENERATE_THUNK_WITH_VTABLE_P): Lose.
|
||||
* class.c (copy_virtuals): Adjust.
|
||||
* decl2.c (mark_vtable_entries): Adjust.
|
||||
* method.c (make_thunk, build_vtable_entry): Adjust.
|
||||
* class.c (update_vtable_entry_for_fn): Only look as far as the
|
||||
first defining class.
|
||||
(build_vtbl_initializer): Put nothing in the slot for a function only
|
||||
defined in a lost primary virtual base.
|
||||
(add_vcall_offset_vtbl_entries_1): Use the same code for
|
||||
the lost primary case and the normal case.
|
||||
(dfs_unshared_virtual_bases): Don't lose a non-virtual primary base.
|
||||
(get_vfield_offset, get_derived_offset): Lose.
|
||||
(dfs_find_final_overrider): Use look_for_overrides_here.
|
||||
(get_matching_virtual): New fn.
|
||||
* semantics.c (emit_associated_thunks): Check BV_USE_VCALL_INDEX_P,
|
||||
not BV_VCALL_INDEX.
|
||||
* search.c (look_for_overrides_here): Split out from...
|
||||
(look_for_overrides_r): Here.
|
||||
|
||||
* class.c (find_final_overrider): Return error_mark_node on error.
|
||||
|
||||
* decl2.c (key_method): #if 0 accidental change.
|
||||
|
||||
2001-06-06 John David Anglin <dave@hiauly1.hia.nrc.ca>
|
||||
|
||||
* call.c (convert_default_arg): Use INTEGRAL_TYPE_P.
|
||||
|
|
362
gcc/cp/class.c
362
gcc/cp/class.c
|
@ -74,7 +74,7 @@ typedef struct vtbl_init_data_s
|
|||
/* The negative-index vtable initializers built up so far. These
|
||||
are in order from least negative index to most negative index. */
|
||||
tree inits;
|
||||
/* The last (i.e., most negative entry in INITS. */
|
||||
/* 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. */
|
||||
|
@ -107,9 +107,8 @@ varray_type local_classes;
|
|||
static tree get_vfield_name PARAMS ((tree));
|
||||
static void finish_struct_anon PARAMS ((tree));
|
||||
static tree build_vbase_pointer PARAMS ((tree, tree));
|
||||
static tree build_vtable_entry PARAMS ((tree, tree, tree, int));
|
||||
static tree build_vtable_entry PARAMS ((tree, tree, tree));
|
||||
static tree get_vtable_name PARAMS ((tree));
|
||||
static tree get_derived_offset PARAMS ((tree, tree));
|
||||
static tree get_basefndecls PARAMS ((tree, tree));
|
||||
static int build_primary_vtable PARAMS ((tree, tree));
|
||||
static int build_secondary_vtable PARAMS ((tree, tree));
|
||||
|
@ -684,37 +683,6 @@ get_vtt_name (type)
|
|||
return mangle_vtt_for_type (type);
|
||||
}
|
||||
|
||||
/* Return the offset to the main vtable for a given base BINFO. */
|
||||
|
||||
tree
|
||||
get_vfield_offset (binfo)
|
||||
tree binfo;
|
||||
{
|
||||
return
|
||||
size_binop (PLUS_EXPR, byte_position (TYPE_VFIELD (BINFO_TYPE (binfo))),
|
||||
BINFO_OFFSET (binfo));
|
||||
}
|
||||
|
||||
/* Get the offset to the start of the original binfo that we derived
|
||||
this binfo from. If we find TYPE first, return the offset only
|
||||
that far. The shortened search is useful because the this pointer
|
||||
on method calling is expected to point to a DECL_CONTEXT (fndecl)
|
||||
object, and not a baseclass of it. */
|
||||
|
||||
static tree
|
||||
get_derived_offset (binfo, type)
|
||||
tree binfo, type;
|
||||
{
|
||||
tree offset1 = get_vfield_offset (TYPE_BINFO (BINFO_TYPE (binfo)));
|
||||
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);
|
||||
}
|
||||
|
||||
/* Create a VAR_DECL for a primary or secondary vtable for CLASS_TYPE.
|
||||
(For a secondary vtable for B-in-D, CLASS_TYPE should be D, not B.)
|
||||
Use NAME for the name of the vtable, and VTABLE_TYPE for its type. */
|
||||
|
@ -796,7 +764,6 @@ copy_virtuals (binfo)
|
|||
{
|
||||
BV_VCALL_INDEX (t) = NULL_TREE;
|
||||
BV_USE_VCALL_INDEX_P (t) = 0;
|
||||
BV_GENERATE_THUNK_WITH_VTABLE_P (t) = 0;
|
||||
}
|
||||
|
||||
return copies;
|
||||
|
@ -1024,9 +991,11 @@ make_new_vtable (t, binfo)
|
|||
{
|
||||
if (binfo == TYPE_BINFO (t))
|
||||
/* In this case, it is *type*'s vtable we are modifying. We start
|
||||
with the approximation that it's vtable is that of the
|
||||
with the approximation that its vtable is that of the
|
||||
immediate base class. */
|
||||
return build_primary_vtable (TYPE_BINFO (DECL_CONTEXT (TYPE_VFIELD (t))),
|
||||
/* ??? This actually passes TYPE_BINFO (t), not the primary base binfo,
|
||||
since we've updated DECL_CONTEXT (TYPE_VFIELD (t)) by now. */
|
||||
return build_primary_vtable (TYPE_BINFO (DECL_CONTEXT (TYPE_VFIELD (t))),
|
||||
t);
|
||||
else
|
||||
/* This is our very own copy of `basetype' to play with. Later,
|
||||
|
@ -1077,7 +1046,12 @@ modify_vtable_entry (t, binfo, fndecl, delta, virtuals)
|
|||
BV_FN (v) = fndecl;
|
||||
|
||||
/* Now assign virtual dispatch information, if unset. We can
|
||||
dispatch this, through any overridden base function. */
|
||||
dispatch this through any overridden base function.
|
||||
|
||||
FIXME this can choose a secondary vtable if the primary is not
|
||||
also lexically first, leading to useless conversions.
|
||||
In the V3 ABI, there's no reason for DECL_VIRTUAL_CONTEXT to
|
||||
ever be different from DECL_CONTEXT. */
|
||||
if (TREE_CODE (DECL_VINDEX (fndecl)) != INTEGER_CST)
|
||||
{
|
||||
DECL_VINDEX (fndecl) = DECL_VINDEX (base_fndecl);
|
||||
|
@ -1808,7 +1782,7 @@ mark_primary_virtual_base (binfo, base_binfo, type)
|
|||
return base_binfo;
|
||||
}
|
||||
|
||||
/* If BINFO is an unmarked virtual binfo for a class with a primary
|
||||
/* If BINFO is an unmarked virtual binfo for a class with a primary virtual
|
||||
base, then BINFO has no primary base in this graph. Called from
|
||||
mark_primary_bases. */
|
||||
|
||||
|
@ -1817,7 +1791,8 @@ static tree dfs_unshared_virtual_bases (binfo, data)
|
|||
void *data ATTRIBUTE_UNUSED;
|
||||
{
|
||||
if (TREE_VIA_VIRTUAL (binfo) && !BINFO_MARKED (binfo)
|
||||
&& CLASSTYPE_HAS_PRIMARY_BASE_P (BINFO_TYPE (binfo)))
|
||||
&& CLASSTYPE_HAS_PRIMARY_BASE_P (BINFO_TYPE (binfo))
|
||||
&& TREE_VIA_VIRTUAL (CLASSTYPE_PRIMARY_BINFO (BINFO_TYPE (binfo))))
|
||||
BINFO_LOST_PRIMARY_P (binfo) = 1;
|
||||
|
||||
CLEAR_BINFO_MARKED (binfo);
|
||||
|
@ -2542,13 +2517,8 @@ dfs_find_final_overrider (binfo, data)
|
|||
path;
|
||||
path = TREE_CHAIN (path))
|
||||
{
|
||||
for (method = TYPE_METHODS (BINFO_TYPE (TREE_VALUE (path)));
|
||||
method;
|
||||
method = TREE_CHAIN (method))
|
||||
if (DECL_VIRTUAL_P (method)
|
||||
&& same_signature_p (method, ffod->fn))
|
||||
break;
|
||||
|
||||
method = look_for_overrides_here (BINFO_TYPE (TREE_VALUE (path)),
|
||||
ffod->fn);
|
||||
if (method)
|
||||
break;
|
||||
}
|
||||
|
@ -2676,7 +2646,7 @@ find_final_overrider (t, binfo, fn)
|
|||
struct T : virtual public R { virtual void f (); };
|
||||
struct U : public S, public T { };
|
||||
|
||||
is not -- there's no way to decide whether to put `S::f' or
|
||||
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
|
||||
|
@ -2695,14 +2665,36 @@ find_final_overrider (t, binfo, fn)
|
|||
|
||||
/* If there was no winner, issue an error message. */
|
||||
if (!ffod.overriding_fn)
|
||||
cp_error ("no unique final overrider for `%D' in `%T'", fn, t);
|
||||
{
|
||||
cp_error ("no unique final overrider for `%D' in `%T'", fn, t);
|
||||
return error_mark_node;
|
||||
}
|
||||
|
||||
return build_tree_list (ffod.overriding_fn, ffod.overriding_base);
|
||||
}
|
||||
|
||||
/* Update a entry in the vtable for BINFO, which is in the hierarchy
|
||||
dominated by T. FN has been overridden in BINFO; VIRTUALS points
|
||||
to the corresponding position in the BINFO_VIRTUALS list. */
|
||||
#if 0
|
||||
/* Returns the function from the BINFO_VIRTUALS entry in T which matches
|
||||
the signature of FUNCTION_DECL FN, or NULL_TREE if none. In other words,
|
||||
the function that the slot in T's primary vtable points to. */
|
||||
|
||||
static tree get_matching_virtual PARAMS ((tree, tree));
|
||||
static tree
|
||||
get_matching_virtual (t, fn)
|
||||
tree t, fn;
|
||||
{
|
||||
tree f;
|
||||
|
||||
for (f = BINFO_VIRTUALS (TYPE_BINFO (t)); f; f = TREE_CHAIN (f))
|
||||
if (same_signature_p (BV_FN (f), fn))
|
||||
return BV_FN (f);
|
||||
return NULL_TREE;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Update an entry in the vtable for BINFO, which is in the hierarchy
|
||||
dominated by T. FN has been overriden in BINFO; VIRTUALS points to the
|
||||
corresponding position in the BINFO_VIRTUALS list. */
|
||||
|
||||
static void
|
||||
update_vtable_entry_for_fn (t, binfo, fn, virtuals)
|
||||
|
@ -2715,93 +2707,92 @@ update_vtable_entry_for_fn (t, binfo, fn, virtuals)
|
|||
tree overrider;
|
||||
tree delta;
|
||||
tree virtual_base;
|
||||
int generate_thunk_with_vtable_p;
|
||||
tree first_defn;
|
||||
|
||||
/* Find the function which originally caused this vtable
|
||||
entry to be present. */
|
||||
b = binfo;
|
||||
while (1)
|
||||
/* Find the nearest primary base (possibly binfo itself) which defines
|
||||
this function; this is the class the caller will convert to when
|
||||
calling FN through BINFO. */
|
||||
for (b = binfo; ; b = get_primary_binfo (b))
|
||||
{
|
||||
tree primary_base;
|
||||
tree f;
|
||||
|
||||
primary_base = get_primary_binfo (b);
|
||||
if (!primary_base)
|
||||
if (look_for_overrides_here (BINFO_TYPE (b), fn))
|
||||
break;
|
||||
|
||||
for (f = BINFO_VIRTUALS (TYPE_BINFO (BINFO_TYPE (primary_base)));
|
||||
f;
|
||||
f = TREE_CHAIN (f))
|
||||
if (same_signature_p (BV_FN (f), fn))
|
||||
break;
|
||||
|
||||
if (!f)
|
||||
break;
|
||||
|
||||
fn = BV_FN (f);
|
||||
b = primary_base;
|
||||
}
|
||||
first_defn = b;
|
||||
|
||||
/* Find the final overrider. */
|
||||
overrider = find_final_overrider (t, b, fn);
|
||||
if (overrider == error_mark_node)
|
||||
return;
|
||||
|
||||
/* Compute the constant adjustment to the `this' pointer. The
|
||||
`this' pointer, when this function is called, will point at the
|
||||
class whose vtable this is. */
|
||||
delta = size_binop (PLUS_EXPR,
|
||||
get_derived_offset (binfo,
|
||||
DECL_VIRTUAL_CONTEXT (fn)),
|
||||
BINFO_OFFSET (binfo));
|
||||
|
||||
/* Assume that we will produce a thunk that convert all the way to
|
||||
the final overrider, and not to an intermediate virtual base. */
|
||||
virtual_base = NULL_TREE;
|
||||
|
||||
/* Assume that we will always generate thunks with the vtables that
|
||||
reference them. */
|
||||
generate_thunk_with_vtable_p = 1;
|
||||
|
||||
/* Under the new ABI, we will convert to an intermediate virtual
|
||||
base first, and then use the vcall offset located there to finish
|
||||
the conversion. */
|
||||
while (b)
|
||||
{
|
||||
/* If we find BINFO, then the final overrider is in a class
|
||||
derived from BINFO, so the thunks can be generated with
|
||||
the final overrider. */
|
||||
if (!virtual_base
|
||||
&& same_type_p (BINFO_TYPE (b), BINFO_TYPE (binfo)))
|
||||
generate_thunk_with_vtable_p = 0;
|
||||
|
||||
/* If we find the final overrider, then we can stop
|
||||
walking. */
|
||||
/* If we find the final overrider, then we can stop
|
||||
walking. */
|
||||
if (same_type_p (BINFO_TYPE (b),
|
||||
BINFO_TYPE (TREE_VALUE (overrider))))
|
||||
break;
|
||||
|
||||
/* If we find a virtual base, and we haven't yet found the
|
||||
overrider, then there is a virtual base between the
|
||||
declaring base and the final overrider. */
|
||||
/* If we find a virtual base, and we haven't yet found the
|
||||
overrider, then there is a virtual base between the
|
||||
declaring base (first_defn) and the final overrider. */
|
||||
if (!virtual_base && TREE_VIA_VIRTUAL (b))
|
||||
{
|
||||
generate_thunk_with_vtable_p = 1;
|
||||
virtual_base = b;
|
||||
}
|
||||
virtual_base = b;
|
||||
|
||||
b = BINFO_INHERITANCE_CHAIN (b);
|
||||
}
|
||||
|
||||
/* Compute the constant adjustment to the `this' pointer. The
|
||||
`this' pointer, when this function is called, will point at BINFO
|
||||
(or one of its primary bases, which are at the same offset). */
|
||||
|
||||
if (virtual_base)
|
||||
/* The `this' pointer needs to be adjusted to the nearest virtual
|
||||
base. */
|
||||
delta = size_diffop (BINFO_OFFSET (virtual_base), delta);
|
||||
delta = size_diffop (BINFO_OFFSET (virtual_base),
|
||||
BINFO_OFFSET (binfo));
|
||||
else
|
||||
/* The `this' pointer needs to be adjusted from pointing to
|
||||
BINFO to pointing at the base where the final overrider
|
||||
appears. */
|
||||
delta = size_diffop (BINFO_OFFSET (TREE_VALUE (overrider)), delta);
|
||||
{
|
||||
/* The `this' pointer needs to be adjusted from pointing to
|
||||
BINFO to pointing at the base where the final overrider
|
||||
appears. */
|
||||
delta = size_diffop (BINFO_OFFSET (TREE_VALUE (overrider)),
|
||||
BINFO_OFFSET (binfo));
|
||||
|
||||
#if 0
|
||||
/* Disable this optimization pending an ABI change, or until
|
||||
we can force emission of the non-virtual thunk even if we don't
|
||||
use it. */
|
||||
if (! integer_zerop (delta))
|
||||
{
|
||||
/* We'll need a thunk. But if we have a (perhaps formerly)
|
||||
primary virtual base, we have a vcall slot for this function,
|
||||
so we can use it rather than create a non-virtual thunk. */
|
||||
|
||||
b = get_primary_binfo (first_defn);
|
||||
for (; b; b = get_primary_binfo (b))
|
||||
{
|
||||
tree f = get_matching_virtual (BINFO_TYPE (b), fn);
|
||||
if (!f)
|
||||
/* b doesn't have this function; no suitable vbase. */
|
||||
break;
|
||||
if (TREE_VIA_VIRTUAL (b))
|
||||
{
|
||||
/* Found one; we can treat ourselves as a virtual base. */
|
||||
virtual_base = binfo;
|
||||
delta = size_zero_node;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
modify_vtable_entry (t,
|
||||
binfo,
|
||||
|
@ -2811,8 +2802,6 @@ update_vtable_entry_for_fn (t, binfo, fn, virtuals)
|
|||
|
||||
if (virtual_base)
|
||||
BV_USE_VCALL_INDEX_P (*virtuals) = 1;
|
||||
if (generate_thunk_with_vtable_p)
|
||||
BV_GENERATE_THUNK_WITH_VTABLE_P (*virtuals) = 1;
|
||||
}
|
||||
|
||||
/* Called from modify_all_vtables via dfs_walk. */
|
||||
|
@ -2823,9 +2812,9 @@ dfs_modify_vtables (binfo, data)
|
|||
void *data;
|
||||
{
|
||||
if (/* There's no need to modify the vtable for a non-virtual
|
||||
primary base; we're not going to use that vtable anyhow
|
||||
(virtual primary bases can become non-primary in a
|
||||
class derivation of this one.) */
|
||||
primary base; we're not going to use that vtable anyhow.
|
||||
We do still need to do this for virtual primary bases, as they
|
||||
could become non-primary in a construction vtable. */
|
||||
(!BINFO_PRIMARY_P (binfo) || TREE_VIA_VIRTUAL (binfo))
|
||||
/* Similarly, a base without a vtable needs no modification. */
|
||||
&& CLASSTYPE_VFIELDS (BINFO_TYPE (binfo)))
|
||||
|
@ -5310,9 +5299,7 @@ finish_struct_1 (t)
|
|||
layout_class_type (t, &empty, &vfuns,
|
||||
&new_virtuals, &overridden_virtuals);
|
||||
|
||||
/* 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. */
|
||||
/* Make sure that we get our own copy of the vfield FIELD_DECL. */
|
||||
vfield = TYPE_VFIELD (t);
|
||||
if (vfield != NULL_TREE
|
||||
&& DECL_FIELD_CONTEXT (vfield) != t)
|
||||
|
@ -7667,7 +7654,7 @@ build_vtbl_initializer (binfo, orig_binfo, t, rtti_binfo, non_fn_entries_p)
|
|||
tree rtti_binfo;
|
||||
int *non_fn_entries_p;
|
||||
{
|
||||
tree v;
|
||||
tree v, b;
|
||||
tree vfun_inits;
|
||||
tree vbase;
|
||||
vtbl_init_data vid;
|
||||
|
@ -7714,7 +7701,6 @@ build_vtbl_initializer (binfo, orig_binfo, t, rtti_binfo, non_fn_entries_p)
|
|||
tree fn;
|
||||
tree pfn;
|
||||
tree init;
|
||||
int generate_with_vtable_p = BV_GENERATE_THUNK_WITH_VTABLE_P (v);
|
||||
|
||||
/* Pull the offset for `this', and the function to call, out of
|
||||
the list. */
|
||||
|
@ -7725,15 +7711,6 @@ build_vtbl_initializer (binfo, orig_binfo, t, rtti_binfo, non_fn_entries_p)
|
|||
vcall_index = BV_VCALL_INDEX (v);
|
||||
my_friendly_assert (vcall_index != NULL_TREE, 20000621);
|
||||
}
|
||||
else if (vid.ctor_vtbl_p && BV_VCALL_INDEX (v))
|
||||
{
|
||||
/* In the original, we did not need to use the vcall index, even
|
||||
though there was one, but in a ctor vtable things might be
|
||||
different (a primary virtual base might have moved). Be
|
||||
conservative and use a vcall adjusting thunk. */
|
||||
vcall_index = BV_VCALL_INDEX (v);
|
||||
generate_with_vtable_p = 1;
|
||||
}
|
||||
else
|
||||
vcall_index = NULL_TREE;
|
||||
|
||||
|
@ -7751,9 +7728,35 @@ build_vtbl_initializer (binfo, orig_binfo, t, rtti_binfo, non_fn_entries_p)
|
|||
pfn = build1 (ADDR_EXPR, vfunc_ptr_type_node, fn);
|
||||
/* The address of a function can't change. */
|
||||
TREE_CONSTANT (pfn) = 1;
|
||||
|
||||
/* Enter it in the vtable. */
|
||||
init = build_vtable_entry (delta, vcall_index, pfn,
|
||||
generate_with_vtable_p);
|
||||
init = build_vtable_entry (delta, vcall_index, pfn);
|
||||
|
||||
/* If the only definition of this function signature along our
|
||||
primary base chain is from a lost primary, this vtable slot will
|
||||
never be used, so just zero it out. This is important to avoid
|
||||
requiring extra thunks which cannot be generated with the function.
|
||||
|
||||
We could also handle this in update_vtable_entry_for_fn; doing it
|
||||
here means we zero out unused slots in ctor vtables as well,
|
||||
rather than filling them with erroneous values (though harmless,
|
||||
apart from relocation costs). */
|
||||
if (fn != abort_fndecl)
|
||||
for (b = binfo; ; b = get_primary_binfo (b))
|
||||
{
|
||||
/* We found a defn before a lost primary; go ahead as normal. */
|
||||
if (look_for_overrides_here (BINFO_TYPE (b), fn))
|
||||
break;
|
||||
|
||||
/* The nearest definition is from a lost primary; clear the
|
||||
slot. */
|
||||
if (BINFO_LOST_PRIMARY_P (b))
|
||||
{
|
||||
init = size_zero_node;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* And add it to the chain of initializers. */
|
||||
vfun_inits = tree_cons (NULL_TREE, init, vfun_inits);
|
||||
}
|
||||
|
@ -7769,7 +7772,7 @@ build_vtbl_initializer (binfo, orig_binfo, t, rtti_binfo, non_fn_entries_p)
|
|||
return chainon (vid.inits, vfun_inits);
|
||||
}
|
||||
|
||||
/* Sets vid->inits to be the initializers for the vbase and vcall
|
||||
/* Adds to vid->inits the initializers for the vbase and vcall
|
||||
offsets in BINFO, which is in the hierarchy dominated by T. */
|
||||
|
||||
static void
|
||||
|
@ -7877,8 +7880,8 @@ build_vbase_offset_vtbl_entries (binfo, vid)
|
|||
}
|
||||
|
||||
/* 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. */
|
||||
for BINFO (which is part of the class hierarchy dominated by VID->DERIVED)
|
||||
to VID->INITS. */
|
||||
|
||||
static void
|
||||
build_vcall_offset_vtbl_entries (binfo, vid)
|
||||
|
@ -7898,22 +7901,20 @@ build_vcall_offset_vtbl_entries (binfo, vid)
|
|||
vtable. For example:
|
||||
|
||||
class A { virtual void f (); };
|
||||
class B : virtual public A { };
|
||||
class C: virtual public A, public B {};
|
||||
|
||||
Now imagine:
|
||||
class B1 : virtual public A { virtual void f (); };
|
||||
class B2 : virtual public A { virtual void f (); };
|
||||
class C: public B1, public B2 { virtual void f (); };
|
||||
|
||||
B* b = new C;
|
||||
b->f();
|
||||
|
||||
The location of `A' is not at a fixed offset relative to `B'; the
|
||||
offset depends on the complete object derived from `B'. So,
|
||||
`B' vtable contains an entry for `f' that indicates by what
|
||||
amount the `this' pointer for `B' needs to be adjusted to arrive
|
||||
at `A'.
|
||||
A C object has a primary base of B1, which has a primary base of A. A
|
||||
C also has a secondary base of B2, which no longer has a primary base
|
||||
of A. So the B2-in-C construction vtable needs a secondary vtable for
|
||||
A, which will adjust the A* to a B2* to call f. We have no way of
|
||||
knowing what (or even whether) this offset will be when we define B2,
|
||||
so we store this "vcall offset" in the A sub-vtable and look it up in
|
||||
a "virtual thunk" for B2::f.
|
||||
|
||||
We need entries for all the functions in our primary vtable and
|
||||
in our non-virtual bases vtables. */
|
||||
in our non-virtual bases' secondary vtables. */
|
||||
vid->vbase = binfo;
|
||||
/* Now, walk through the non-virtual bases, adding vcall offsets. */
|
||||
add_vcall_offset_vtbl_entries_r (binfo, vid);
|
||||
|
@ -7930,7 +7931,9 @@ add_vcall_offset_vtbl_entries_r (binfo, vid)
|
|||
tree primary_binfo;
|
||||
|
||||
/* Don't walk into virtual bases -- except, of course, for the
|
||||
virtual base for which we are building vcall offsets. */
|
||||
virtual base for which we are building vcall offsets. Any
|
||||
primary virtual base will have already had its offsets generated
|
||||
through the recursion in build_vcall_and_vbase_vtbl_entries. */
|
||||
if (TREE_VIA_VIRTUAL (binfo) && vid->vbase != binfo)
|
||||
return;
|
||||
|
||||
|
@ -7964,43 +7967,30 @@ add_vcall_offset_vtbl_entries_1 (binfo, vid)
|
|||
tree base_virtuals;
|
||||
tree orig_virtuals;
|
||||
tree binfo_inits;
|
||||
int lost_primary = 0;
|
||||
/* If BINFO is a primary base, this is the least derived class of
|
||||
BINFO that is not a primary base. */
|
||||
/* If BINFO is a primary base, the most derived class which has BINFO as
|
||||
a primary base; otherwise, just BINFO. */
|
||||
tree non_primary_binfo;
|
||||
|
||||
binfo_inits = NULL_TREE;
|
||||
|
||||
/* We might be a primary base class. Go up the inheritance
|
||||
hierarchy until we find the class of which we are a primary base:
|
||||
/* We might be a primary base class. Go up the inheritance hierarchy
|
||||
until we find the most derived class of which we are a primary base:
|
||||
it is the BINFO_VIRTUALS there that we need to consider. */
|
||||
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 we have reached a virtual base, then it must be vid->vbase,
|
||||
because we ignore other virtual bases in
|
||||
add_vcall_offset_vtbl_entries_r. In turn, it must be a primary
|
||||
base (possibly multi-level) of vid->binfo, or we wouldn't
|
||||
have called build_vcall_and_vbase_vtbl_entries for it. But it
|
||||
might be a lost primary, so just skip down to vid->binfo. */
|
||||
if (TREE_VIA_VIRTUAL (non_primary_binfo))
|
||||
{
|
||||
if (vid->ctor_vtbl_p)
|
||||
{
|
||||
tree probe;
|
||||
|
||||
for (probe = vid->binfo;
|
||||
probe != non_primary_binfo;
|
||||
probe = get_primary_binfo (probe))
|
||||
{
|
||||
if (BINFO_LOST_PRIMARY_P (probe))
|
||||
{
|
||||
lost_primary = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (non_primary_binfo != vid->vbase)
|
||||
abort ();
|
||||
non_primary_binfo = vid->binfo;
|
||||
break;
|
||||
}
|
||||
|
@ -8034,13 +8024,12 @@ add_vcall_offset_vtbl_entries_1 (binfo, vid)
|
|||
tree vcall_offset;
|
||||
|
||||
/* Find the declaration that originally caused this function to
|
||||
be present. */
|
||||
be present in BINFO_TYPE (binfo). */
|
||||
orig_fn = BV_FN (orig_virtuals);
|
||||
|
||||
/* We do not need an entry if this function is declared in a
|
||||
virtual base (or one of its virtual bases), and not
|
||||
overridden in the section of the hierarchy dominated by the
|
||||
virtual base for which we are building vcall offsets. */
|
||||
/* When processing BINFO, we only want to generate vcall slots for
|
||||
function slots introduced in BINFO. So don't try to generate
|
||||
one if the function isn't even defined in BINFO. */
|
||||
if (!same_type_p (DECL_CONTEXT (orig_fn), BINFO_TYPE (binfo)))
|
||||
continue;
|
||||
|
||||
|
@ -8071,16 +8060,19 @@ add_vcall_offset_vtbl_entries_1 (binfo, vid)
|
|||
if (i != VARRAY_ACTIVE_SIZE (vid->fns))
|
||||
continue;
|
||||
|
||||
/* The FN comes from BASE. So, we must calculate the adjustment
|
||||
from the virtual base that derived from BINFO to BASE. */
|
||||
/* The FN comes from BASE. So, we must calculate the adjustment from
|
||||
vid->vbase to BASE. We can just look for BASE in the complete
|
||||
object because we are converting from a virtual base, so if there
|
||||
were multiple copies, there would not be a unique final overrider
|
||||
and vid->derived would be ill-formed. */
|
||||
base = DECL_CONTEXT (fn);
|
||||
base_binfo = get_binfo (base, vid->derived, /*protect=*/0);
|
||||
|
||||
/* Compute the vcall offset. */
|
||||
vcall_offset = BINFO_OFFSET (vid->vbase);
|
||||
if (lost_primary)
|
||||
vcall_offset = size_binop (PLUS_EXPR, vcall_offset,
|
||||
BINFO_OFFSET (vid->binfo));
|
||||
/* As mentioned above, the vbase we're working on is a primary base of
|
||||
vid->binfo. But it might be a lost primary, so its BINFO_OFFSET
|
||||
might be wrong, so we just use the BINFO_OFFSET from vid->binfo. */
|
||||
vcall_offset = BINFO_OFFSET (vid->binfo);
|
||||
vcall_offset = size_diffop (BINFO_OFFSET (base_binfo),
|
||||
vcall_offset);
|
||||
vcall_offset = fold (build1 (NOP_EXPR, vtable_entry_type,
|
||||
|
@ -8091,7 +8083,7 @@ add_vcall_offset_vtbl_entries_1 (binfo, vid)
|
|||
|
||||
/* 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. */
|
||||
annotation when we built the original vtable. */
|
||||
if (!vid->ctor_vtbl_p)
|
||||
BV_VCALL_INDEX (derived_virtuals) = vid->index;
|
||||
|
||||
|
@ -8172,11 +8164,10 @@ build_rtti_vtbl_entries (binfo, vid)
|
|||
ABI.) */
|
||||
|
||||
static tree
|
||||
build_vtable_entry (delta, vcall_index, entry, generate_with_vtable_p)
|
||||
build_vtable_entry (delta, vcall_index, entry)
|
||||
tree delta;
|
||||
tree vcall_index;
|
||||
tree entry;
|
||||
int generate_with_vtable_p;
|
||||
{
|
||||
if (flag_vtable_thunks)
|
||||
{
|
||||
|
@ -8186,8 +8177,7 @@ build_vtable_entry (delta, vcall_index, entry, generate_with_vtable_p)
|
|||
if ((!integer_zerop (delta) || vcall_index != NULL_TREE)
|
||||
&& fn != abort_fndecl)
|
||||
{
|
||||
entry = make_thunk (entry, delta, vcall_index,
|
||||
generate_with_vtable_p);
|
||||
entry = make_thunk (entry, delta, vcall_index);
|
||||
entry = build1 (ADDR_EXPR, vtable_entry_type, entry);
|
||||
TREE_READONLY (entry) = 1;
|
||||
TREE_CONSTANT (entry) = 1;
|
||||
|
|
|
@ -55,7 +55,6 @@ Boston, MA 02111-1307, USA. */
|
|||
BASELINK_P (in TREE_LIST)
|
||||
ICS_ELLIPSIS_FLAG (in _CONV)
|
||||
BINFO_ACCESS (in BINFO)
|
||||
BV_GENERATE_THUNK_WITH_VTABLE_P (in TREE_LIST)
|
||||
2: IDENTIFIER_OPNAME_P.
|
||||
TYPE_POLYMORHPIC_P (in _TYPE)
|
||||
ICS_THIS_FLAG (in _CONV)
|
||||
|
@ -133,10 +132,6 @@ Boston, MA 02111-1307, USA. */
|
|||
|
||||
The BV_FN is the declaration for the virtual function itself.
|
||||
|
||||
The BV_OVERRIDING_BASE is the binfo for the final overrider for
|
||||
this function. (That binfo's BINFO_TYPE will always be the same
|
||||
as the DECL_CLASS_CONTEXT for the function.)
|
||||
|
||||
BINFO_VTABLE
|
||||
Sometimes this is a VAR_DECL. Under the new ABI, it is instead
|
||||
an expression with POINTER_TYPE pointing that gives the value
|
||||
|
@ -1736,14 +1731,6 @@ struct lang_type
|
|||
/* Nonzero if we should use a virtual thunk for this entry. */
|
||||
#define BV_USE_VCALL_INDEX_P(NODE) \
|
||||
(TREE_LANG_FLAG_0 (NODE))
|
||||
|
||||
/* Nonzero if we should generate this thunk when the vtable that
|
||||
references it is emitted, rather than with the final overrider. */
|
||||
#define BV_GENERATE_THUNK_WITH_VTABLE_P(NODE) \
|
||||
(TREE_LANG_FLAG_1 (NODE))
|
||||
|
||||
/* The most derived class. */
|
||||
|
||||
|
||||
/* Nonzero for TREE_LIST node means that this list of things
|
||||
is a list of parameters, as opposed to a list of expressions. */
|
||||
|
@ -1806,8 +1793,7 @@ struct lang_decl_flags
|
|||
unsigned global_dtor_p : 1;
|
||||
unsigned assignment_operator_p : 1;
|
||||
unsigned anticipated_p : 1;
|
||||
unsigned generate_with_vtable_p : 1;
|
||||
/* Two unused bits. */
|
||||
/* Three unused bits. */
|
||||
|
||||
union {
|
||||
/* In a FUNCTION_DECL, VAR_DECL, TYPE_DECL, or TEMPLATE_DECL, this
|
||||
|
@ -3036,11 +3022,6 @@ enum ptrmemfunc_vbit_where_t
|
|||
#define THUNK_VCALL_OFFSET(DECL) \
|
||||
(DECL_LANG_SPECIFIC (DECL)->decl_flags.u2.vcall_offset)
|
||||
|
||||
/* Nonzero if this thunk should be generated with the vtable that
|
||||
references it. */
|
||||
#define THUNK_GENERATE_WITH_VTABLE_P(DECL) \
|
||||
(DECL_LANG_SPECIFIC (DECL)->decl_flags.generate_with_vtable_p)
|
||||
|
||||
/* These macros provide convenient access to the various _STMT nodes
|
||||
created when parsing template declarations. */
|
||||
#define TRY_STMTS(NODE) TREE_OPERAND (TRY_BLOCK_CHECK (NODE), 0)
|
||||
|
@ -3716,7 +3697,6 @@ extern tree get_vtable_decl PARAMS ((tree, int));
|
|||
extern void add_method PARAMS ((tree, tree, int));
|
||||
extern int currently_open_class PARAMS ((tree));
|
||||
extern tree currently_open_derived_class PARAMS ((tree));
|
||||
extern tree get_vfield_offset PARAMS ((tree));
|
||||
extern void duplicate_tag_error PARAMS ((tree));
|
||||
extern tree finish_struct PARAMS ((tree, tree));
|
||||
extern void finish_struct_1 PARAMS ((tree));
|
||||
|
@ -4083,7 +4063,7 @@ extern void init_method PARAMS ((void));
|
|||
extern void set_mangled_name_for_decl PARAMS ((tree));
|
||||
extern tree build_opfncall PARAMS ((enum tree_code, int, tree, tree, tree));
|
||||
extern tree hack_identifier PARAMS ((tree, tree));
|
||||
extern tree make_thunk PARAMS ((tree, tree, tree, int));
|
||||
extern tree make_thunk PARAMS ((tree, tree, tree));
|
||||
extern void use_thunk PARAMS ((tree, int));
|
||||
extern void synthesize_method PARAMS ((tree));
|
||||
extern tree implicitly_declare_fn PARAMS ((special_function_kind, tree, int));
|
||||
|
@ -4202,6 +4182,7 @@ extern tree context_for_name_lookup PARAMS ((tree));
|
|||
extern tree lookup_conversions PARAMS ((tree));
|
||||
extern tree binfo_for_vtable PARAMS ((tree));
|
||||
extern tree binfo_from_vbase PARAMS ((tree));
|
||||
extern tree look_for_overrides_here PARAMS ((tree, tree));
|
||||
extern tree dfs_walk PARAMS ((tree,
|
||||
tree (*) (tree, void *),
|
||||
tree (*) (tree, void *),
|
||||
|
|
|
@ -2265,7 +2265,7 @@ mark_vtable_entries (decl)
|
|||
we know all the thunks we'll need when we emit a virtual
|
||||
function, so we emit the thunks there instead. */
|
||||
if (DECL_THUNK_P (fn))
|
||||
use_thunk (fn, THUNK_GENERATE_WITH_VTABLE_P (fn));
|
||||
use_thunk (fn, /*emit_p=*/0);
|
||||
mark_used (fn);
|
||||
}
|
||||
}
|
||||
|
@ -2369,7 +2369,12 @@ key_method (type)
|
|||
method = TREE_CHAIN (method))
|
||||
if (DECL_VINDEX (method) != NULL_TREE
|
||||
&& ! DECL_DECLARED_INLINE_P (method)
|
||||
&& (! DECL_PURE_VIRTUAL_P (method) || DECL_DESTRUCTOR_P (method)))
|
||||
&& (! DECL_PURE_VIRTUAL_P (method)
|
||||
#if 0
|
||||
/* This would be nice, but we didn't think of it in time. */
|
||||
|| DECL_DESTRUCTOR_P (method)
|
||||
#endif
|
||||
))
|
||||
return method;
|
||||
|
||||
return NULL_TREE;
|
||||
|
|
|
@ -295,11 +295,10 @@ request for member `%D' is ambiguous in multiple inheritance lattice",
|
|||
DELTA is the offset to this and VCALL_INDEX is zero. */
|
||||
|
||||
tree
|
||||
make_thunk (function, delta, vcall_index, generate_with_vtable_p)
|
||||
make_thunk (function, delta, vcall_index)
|
||||
tree function;
|
||||
tree delta;
|
||||
tree vcall_index;
|
||||
int generate_with_vtable_p;
|
||||
{
|
||||
tree thunk_id;
|
||||
tree thunk;
|
||||
|
@ -348,7 +347,6 @@ make_thunk (function, delta, vcall_index, generate_with_vtable_p)
|
|||
DECL_INITIAL (thunk) = function;
|
||||
THUNK_DELTA (thunk) = d;
|
||||
THUNK_VCALL_OFFSET (thunk) = vcall_offset;
|
||||
THUNK_GENERATE_WITH_VTABLE_P (thunk) = generate_with_vtable_p;
|
||||
/* The thunk itself is not a constructor or destructor, even if
|
||||
the thing it is thunking to is. */
|
||||
DECL_INTERFACE_KNOWN (thunk) = 1;
|
||||
|
@ -381,7 +379,6 @@ void
|
|||
use_thunk (thunk_fndecl, emit_p)
|
||||
tree thunk_fndecl;
|
||||
int emit_p;
|
||||
|
||||
{
|
||||
tree fnaddr;
|
||||
tree function;
|
||||
|
|
|
@ -2024,6 +2024,46 @@ look_for_overrides (type, fndecl)
|
|||
return found;
|
||||
}
|
||||
|
||||
/* Look in TYPE for virtual functions with the same signature as FNDECL.
|
||||
This differs from get_matching_virtual in that it will only return
|
||||
a function from TYPE. */
|
||||
|
||||
tree
|
||||
look_for_overrides_here (type, fndecl)
|
||||
tree type, fndecl;
|
||||
{
|
||||
int ix;
|
||||
|
||||
if (DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (fndecl))
|
||||
ix = CLASSTYPE_DESTRUCTOR_SLOT;
|
||||
else
|
||||
ix = lookup_fnfields_1 (type, DECL_NAME (fndecl));
|
||||
if (ix >= 0)
|
||||
{
|
||||
tree fns = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (type), ix);
|
||||
|
||||
for (; fns; fns = OVL_NEXT (fns))
|
||||
{
|
||||
tree fn = OVL_CURRENT (fns);
|
||||
|
||||
if (!DECL_VIRTUAL_P (fn))
|
||||
/* Not a virtual. */;
|
||||
else if (DECL_CONTEXT (fn) != type)
|
||||
/* Introduced with a using declaration. */;
|
||||
else if (DECL_STATIC_FUNCTION_P (fndecl))
|
||||
{
|
||||
tree btypes = TYPE_ARG_TYPES (TREE_TYPE (fn));
|
||||
tree dtypes = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
|
||||
if (compparms (TREE_CHAIN (btypes), dtypes))
|
||||
return fn;
|
||||
}
|
||||
else if (same_signature_p (fndecl, fn))
|
||||
return fn;
|
||||
}
|
||||
}
|
||||
return NULL_TREE;
|
||||
}
|
||||
|
||||
/* Look in TYPE for virtual functions overridden by FNDECL. Check both
|
||||
TYPE itself and its bases. */
|
||||
|
||||
|
@ -2031,49 +2071,25 @@ static int
|
|||
look_for_overrides_r (type, fndecl)
|
||||
tree type, fndecl;
|
||||
{
|
||||
int ix;
|
||||
|
||||
if (DECL_DESTRUCTOR_P (fndecl))
|
||||
ix = CLASSTYPE_DESTRUCTOR_SLOT;
|
||||
else
|
||||
ix = lookup_fnfields_1 (type, DECL_NAME (fndecl));
|
||||
if (ix >= 0)
|
||||
tree fn = look_for_overrides_here (type, fndecl);
|
||||
if (fn)
|
||||
{
|
||||
tree fns = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (type), ix);
|
||||
tree dtypes = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
|
||||
tree thistype = DECL_STATIC_FUNCTION_P (fndecl)
|
||||
? NULL_TREE : TREE_TYPE (TREE_VALUE (dtypes));
|
||||
|
||||
for (; fns; fns = OVL_NEXT (fns))
|
||||
{
|
||||
tree fn = OVL_CURRENT (fns);
|
||||
tree btypes = TYPE_ARG_TYPES (TREE_TYPE (fn));
|
||||
|
||||
if (!DECL_VIRTUAL_P (fn))
|
||||
/* Not a virtual */;
|
||||
else if (DECL_CONTEXT (fn) != type)
|
||||
/* Introduced with a using declaration */;
|
||||
else if (thistype == NULL_TREE)
|
||||
{
|
||||
if (compparms (TREE_CHAIN (btypes), dtypes))
|
||||
{
|
||||
/* A static member function cannot match an inherited
|
||||
virtual member function. */
|
||||
cp_error_at ("`%#D' cannot be declared", fndecl);
|
||||
cp_error_at (" since `%#D' declared in base class", fn);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else if (same_signature_p (fndecl, fn))
|
||||
{
|
||||
/* It's definitely virtual, even if not explicitly set. */
|
||||
DECL_VIRTUAL_P (fndecl) = 1;
|
||||
check_final_overrider (fndecl, fn);
|
||||
|
||||
return 1;
|
||||
}
|
||||
if (DECL_STATIC_FUNCTION_P (fndecl))
|
||||
{
|
||||
/* A static member function cannot match an inherited
|
||||
virtual member function. */
|
||||
cp_error_at ("`%#D' cannot be declared", fndecl);
|
||||
cp_error_at (" since `%#D' declared in base class", fn);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* It's definitely virtual, even if not explicitly set. */
|
||||
DECL_VIRTUAL_P (fndecl) = 1;
|
||||
check_final_overrider (fndecl, fn);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* We failed to find one declared in this class. Look in its bases. */
|
||||
return look_for_overrides (type, fndecl);
|
||||
}
|
||||
|
|
|
@ -2300,7 +2300,7 @@ emit_associated_thunks (fn)
|
|||
for (v = BINFO_VIRTUALS (binfo); v; v = TREE_CHAIN (v))
|
||||
if (BV_FN (v) == fn
|
||||
&& (!integer_zerop (BV_DELTA (v))
|
||||
|| BV_VCALL_INDEX (v)))
|
||||
|| BV_USE_VCALL_INDEX_P (v)))
|
||||
{
|
||||
tree thunk;
|
||||
tree vcall_index;
|
||||
|
@ -2317,8 +2317,7 @@ emit_associated_thunks (fn)
|
|||
vfunc_ptr_type_node,
|
||||
fn),
|
||||
BV_DELTA (v),
|
||||
vcall_index,
|
||||
/*generate_with_vtable_p=*/0);
|
||||
vcall_index);
|
||||
use_thunk (thunk, /*emit_p=*/1);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,4 +26,3 @@ C c;
|
|||
// { dg-final { scan-assembler mangle1.C "\n_ZTT1C:" } }
|
||||
// { dg-final { scan-assembler mangle1.C "\n_ZTV1A:" } }
|
||||
// { dg-final { scan-assembler mangle1.C "\n_ZTV1C:" } }
|
||||
// { dg-final { scan-assembler mangle1.C "\n_ZTv0_n\(12|24\)_N1A1fEv:" } }
|
||||
|
|
Loading…
Add table
Reference in a new issue