Commit d0cd8b44 by Jason Merrill Committed by Jason Merrill

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
parent acf97e0b
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> 2001-06-06 John David Anglin <dave@hiauly1.hia.nrc.ca>
* call.c (convert_default_arg): Use INTEGRAL_TYPE_P. * call.c (convert_default_arg): Use INTEGRAL_TYPE_P.
......
...@@ -74,7 +74,7 @@ typedef struct vtbl_init_data_s ...@@ -74,7 +74,7 @@ typedef struct vtbl_init_data_s
/* The negative-index vtable initializers built up so far. These /* The negative-index vtable initializers built up so far. These
are in order from least negative index to most negative index. */ are in order from least negative index to most negative index. */
tree inits; tree inits;
/* The last (i.e., most negative entry in INITS. */ /* The last (i.e., most negative) entry in INITS. */
tree* last_init; tree* last_init;
/* The binfo for the virtual base for which we're building /* The binfo for the virtual base for which we're building
vcall offset initializers. */ vcall offset initializers. */
...@@ -107,9 +107,8 @@ varray_type local_classes; ...@@ -107,9 +107,8 @@ varray_type local_classes;
static tree get_vfield_name PARAMS ((tree)); static tree get_vfield_name PARAMS ((tree));
static void finish_struct_anon PARAMS ((tree)); static void finish_struct_anon PARAMS ((tree));
static tree build_vbase_pointer PARAMS ((tree, 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_vtable_name PARAMS ((tree));
static tree get_derived_offset PARAMS ((tree, tree));
static tree get_basefndecls PARAMS ((tree, tree)); static tree get_basefndecls PARAMS ((tree, tree));
static int build_primary_vtable PARAMS ((tree, tree)); static int build_primary_vtable PARAMS ((tree, tree));
static int build_secondary_vtable PARAMS ((tree, tree)); static int build_secondary_vtable PARAMS ((tree, tree));
...@@ -684,37 +683,6 @@ get_vtt_name (type) ...@@ -684,37 +683,6 @@ get_vtt_name (type)
return mangle_vtt_for_type (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. /* 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.) (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. */ Use NAME for the name of the vtable, and VTABLE_TYPE for its type. */
...@@ -796,7 +764,6 @@ copy_virtuals (binfo) ...@@ -796,7 +764,6 @@ copy_virtuals (binfo)
{ {
BV_VCALL_INDEX (t) = NULL_TREE; BV_VCALL_INDEX (t) = NULL_TREE;
BV_USE_VCALL_INDEX_P (t) = 0; BV_USE_VCALL_INDEX_P (t) = 0;
BV_GENERATE_THUNK_WITH_VTABLE_P (t) = 0;
} }
return copies; return copies;
...@@ -1024,8 +991,10 @@ make_new_vtable (t, binfo) ...@@ -1024,8 +991,10 @@ make_new_vtable (t, binfo)
{ {
if (binfo == TYPE_BINFO (t)) if (binfo == TYPE_BINFO (t))
/* In this case, it is *type*'s vtable we are modifying. We start /* 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. */ immediate base class. */
/* ??? 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))), return build_primary_vtable (TYPE_BINFO (DECL_CONTEXT (TYPE_VFIELD (t))),
t); t);
else else
...@@ -1077,7 +1046,12 @@ modify_vtable_entry (t, binfo, fndecl, delta, virtuals) ...@@ -1077,7 +1046,12 @@ modify_vtable_entry (t, binfo, fndecl, delta, virtuals)
BV_FN (v) = fndecl; BV_FN (v) = fndecl;
/* Now assign virtual dispatch information, if unset. We can /* 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) if (TREE_CODE (DECL_VINDEX (fndecl)) != INTEGER_CST)
{ {
DECL_VINDEX (fndecl) = DECL_VINDEX (base_fndecl); DECL_VINDEX (fndecl) = DECL_VINDEX (base_fndecl);
...@@ -1808,7 +1782,7 @@ mark_primary_virtual_base (binfo, base_binfo, type) ...@@ -1808,7 +1782,7 @@ mark_primary_virtual_base (binfo, base_binfo, type)
return base_binfo; 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 base, then BINFO has no primary base in this graph. Called from
mark_primary_bases. */ mark_primary_bases. */
...@@ -1817,7 +1791,8 @@ static tree dfs_unshared_virtual_bases (binfo, data) ...@@ -1817,7 +1791,8 @@ static tree dfs_unshared_virtual_bases (binfo, data)
void *data ATTRIBUTE_UNUSED; void *data ATTRIBUTE_UNUSED;
{ {
if (TREE_VIA_VIRTUAL (binfo) && !BINFO_MARKED (binfo) 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; BINFO_LOST_PRIMARY_P (binfo) = 1;
CLEAR_BINFO_MARKED (binfo); CLEAR_BINFO_MARKED (binfo);
...@@ -2542,13 +2517,8 @@ dfs_find_final_overrider (binfo, data) ...@@ -2542,13 +2517,8 @@ dfs_find_final_overrider (binfo, data)
path; path;
path = TREE_CHAIN (path)) path = TREE_CHAIN (path))
{ {
for (method = TYPE_METHODS (BINFO_TYPE (TREE_VALUE (path))); method = look_for_overrides_here (BINFO_TYPE (TREE_VALUE (path)),
method; ffod->fn);
method = TREE_CHAIN (method))
if (DECL_VIRTUAL_P (method)
&& same_signature_p (method, ffod->fn))
break;
if (method) if (method)
break; break;
} }
...@@ -2695,14 +2665,36 @@ find_final_overrider (t, binfo, fn) ...@@ -2695,14 +2665,36 @@ find_final_overrider (t, binfo, fn)
/* If there was no winner, issue an error message. */ /* If there was no winner, issue an error message. */
if (!ffod.overriding_fn) 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); return build_tree_list (ffod.overriding_fn, ffod.overriding_base);
} }
/* Update a entry in the vtable for BINFO, which is in the hierarchy #if 0
dominated by T. FN has been overridden in BINFO; VIRTUALS points /* Returns the function from the BINFO_VIRTUALS entry in T which matches
to the corresponding position in the BINFO_VIRTUALS list. */ 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 static void
update_vtable_entry_for_fn (t, binfo, fn, virtuals) update_vtable_entry_for_fn (t, binfo, fn, virtuals)
...@@ -2715,66 +2707,32 @@ update_vtable_entry_for_fn (t, binfo, fn, virtuals) ...@@ -2715,66 +2707,32 @@ update_vtable_entry_for_fn (t, binfo, fn, virtuals)
tree overrider; tree overrider;
tree delta; tree delta;
tree virtual_base; tree virtual_base;
int generate_thunk_with_vtable_p; tree first_defn;
/* Find the function which originally caused this vtable /* Find the nearest primary base (possibly binfo itself) which defines
entry to be present. */ this function; this is the class the caller will convert to when
b = binfo; calling FN through BINFO. */
while (1) for (b = binfo; ; b = get_primary_binfo (b))
{ {
tree primary_base; if (look_for_overrides_here (BINFO_TYPE (b), fn))
tree f;
primary_base = get_primary_binfo (b);
if (!primary_base)
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; break;
if (!f)
break;
fn = BV_FN (f);
b = primary_base;
} }
first_defn = b;
/* Find the final overrider. */ /* Find the final overrider. */
overrider = find_final_overrider (t, b, fn); overrider = find_final_overrider (t, b, fn);
if (overrider == error_mark_node) if (overrider == error_mark_node)
return; 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 /* Assume that we will produce a thunk that convert all the way to
the final overrider, and not to an intermediate virtual base. */ the final overrider, and not to an intermediate virtual base. */
virtual_base = NULL_TREE; 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 /* Under the new ABI, we will convert to an intermediate virtual
base first, and then use the vcall offset located there to finish base first, and then use the vcall offset located there to finish
the conversion. */ the conversion. */
while (b) 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 /* If we find the final overrider, then we can stop
walking. */ walking. */
if (same_type_p (BINFO_TYPE (b), if (same_type_p (BINFO_TYPE (b),
...@@ -2783,25 +2741,58 @@ update_vtable_entry_for_fn (t, binfo, fn, virtuals) ...@@ -2783,25 +2741,58 @@ update_vtable_entry_for_fn (t, binfo, fn, virtuals)
/* If we find a virtual base, and we haven't yet found the /* If we find a virtual base, and we haven't yet found the
overrider, then there is a virtual base between the overrider, then there is a virtual base between the
declaring base and the final overrider. */ declaring base (first_defn) and the final overrider. */
if (!virtual_base && TREE_VIA_VIRTUAL (b)) if (!virtual_base && TREE_VIA_VIRTUAL (b))
{
generate_thunk_with_vtable_p = 1;
virtual_base = b; virtual_base = b;
}
b = BINFO_INHERITANCE_CHAIN (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) if (virtual_base)
/* The `this' pointer needs to be adjusted to the nearest virtual /* The `this' pointer needs to be adjusted to the nearest virtual
base. */ base. */
delta = size_diffop (BINFO_OFFSET (virtual_base), delta); delta = size_diffop (BINFO_OFFSET (virtual_base),
BINFO_OFFSET (binfo));
else else
{
/* The `this' pointer needs to be adjusted from pointing to /* The `this' pointer needs to be adjusted from pointing to
BINFO to pointing at the base where the final overrider BINFO to pointing at the base where the final overrider
appears. */ appears. */
delta = size_diffop (BINFO_OFFSET (TREE_VALUE (overrider)), delta); 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, modify_vtable_entry (t,
binfo, binfo,
...@@ -2811,8 +2802,6 @@ update_vtable_entry_for_fn (t, binfo, fn, virtuals) ...@@ -2811,8 +2802,6 @@ update_vtable_entry_for_fn (t, binfo, fn, virtuals)
if (virtual_base) if (virtual_base)
BV_USE_VCALL_INDEX_P (*virtuals) = 1; 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. */ /* Called from modify_all_vtables via dfs_walk. */
...@@ -2823,9 +2812,9 @@ dfs_modify_vtables (binfo, data) ...@@ -2823,9 +2812,9 @@ dfs_modify_vtables (binfo, data)
void *data; void *data;
{ {
if (/* There's no need to modify the vtable for a non-virtual if (/* There's no need to modify the vtable for a non-virtual
primary base; we're not going to use that vtable anyhow primary base; we're not going to use that vtable anyhow.
(virtual primary bases can become non-primary in a We do still need to do this for virtual primary bases, as they
class derivation of this one.) */ could become non-primary in a construction vtable. */
(!BINFO_PRIMARY_P (binfo) || TREE_VIA_VIRTUAL (binfo)) (!BINFO_PRIMARY_P (binfo) || TREE_VIA_VIRTUAL (binfo))
/* Similarly, a base without a vtable needs no modification. */ /* Similarly, a base without a vtable needs no modification. */
&& CLASSTYPE_VFIELDS (BINFO_TYPE (binfo))) && CLASSTYPE_VFIELDS (BINFO_TYPE (binfo)))
...@@ -5310,9 +5299,7 @@ finish_struct_1 (t) ...@@ -5310,9 +5299,7 @@ finish_struct_1 (t)
layout_class_type (t, &empty, &vfuns, layout_class_type (t, &empty, &vfuns,
&new_virtuals, &overridden_virtuals); &new_virtuals, &overridden_virtuals);
/* Set up the DECL_FIELD_BITPOS of the vfield if we need to, as we /* Make sure that we get our own copy of the vfield FIELD_DECL. */
might need to know it for setting up the offsets in the vtable
(or in thunks) below. */
vfield = TYPE_VFIELD (t); vfield = TYPE_VFIELD (t);
if (vfield != NULL_TREE if (vfield != NULL_TREE
&& DECL_FIELD_CONTEXT (vfield) != t) && DECL_FIELD_CONTEXT (vfield) != t)
...@@ -7667,7 +7654,7 @@ build_vtbl_initializer (binfo, orig_binfo, t, rtti_binfo, non_fn_entries_p) ...@@ -7667,7 +7654,7 @@ build_vtbl_initializer (binfo, orig_binfo, t, rtti_binfo, non_fn_entries_p)
tree rtti_binfo; tree rtti_binfo;
int *non_fn_entries_p; int *non_fn_entries_p;
{ {
tree v; tree v, b;
tree vfun_inits; tree vfun_inits;
tree vbase; tree vbase;
vtbl_init_data vid; vtbl_init_data vid;
...@@ -7714,7 +7701,6 @@ build_vtbl_initializer (binfo, orig_binfo, t, rtti_binfo, non_fn_entries_p) ...@@ -7714,7 +7701,6 @@ build_vtbl_initializer (binfo, orig_binfo, t, rtti_binfo, non_fn_entries_p)
tree fn; tree fn;
tree pfn; tree pfn;
tree init; 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 /* Pull the offset for `this', and the function to call, out of
the list. */ the list. */
...@@ -7725,15 +7711,6 @@ build_vtbl_initializer (binfo, orig_binfo, t, rtti_binfo, non_fn_entries_p) ...@@ -7725,15 +7711,6 @@ build_vtbl_initializer (binfo, orig_binfo, t, rtti_binfo, non_fn_entries_p)
vcall_index = BV_VCALL_INDEX (v); vcall_index = BV_VCALL_INDEX (v);
my_friendly_assert (vcall_index != NULL_TREE, 20000621); 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 else
vcall_index = NULL_TREE; vcall_index = NULL_TREE;
...@@ -7751,9 +7728,35 @@ build_vtbl_initializer (binfo, orig_binfo, t, rtti_binfo, non_fn_entries_p) ...@@ -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); pfn = build1 (ADDR_EXPR, vfunc_ptr_type_node, fn);
/* The address of a function can't change. */ /* The address of a function can't change. */
TREE_CONSTANT (pfn) = 1; TREE_CONSTANT (pfn) = 1;
/* Enter it in the vtable. */ /* Enter it in the vtable. */
init = build_vtable_entry (delta, vcall_index, pfn, init = build_vtable_entry (delta, vcall_index, pfn);
generate_with_vtable_p);
/* 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. */ /* And add it to the chain of initializers. */
vfun_inits = tree_cons (NULL_TREE, init, vfun_inits); 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) ...@@ -7769,7 +7772,7 @@ build_vtbl_initializer (binfo, orig_binfo, t, rtti_binfo, non_fn_entries_p)
return chainon (vid.inits, vfun_inits); 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. */ offsets in BINFO, which is in the hierarchy dominated by T. */
static void static void
...@@ -7877,8 +7880,8 @@ build_vbase_offset_vtbl_entries (binfo, vid) ...@@ -7877,8 +7880,8 @@ build_vbase_offset_vtbl_entries (binfo, vid)
} }
/* Adds the initializers for the vcall offset entries in the vtable /* Adds the initializers for the vcall offset entries in the vtable
for BINFO (which is part of the class hierarchy dominated by T) to for BINFO (which is part of the class hierarchy dominated by VID->DERIVED)
VID->INITS. */ to VID->INITS. */
static void static void
build_vcall_offset_vtbl_entries (binfo, vid) build_vcall_offset_vtbl_entries (binfo, vid)
...@@ -7898,22 +7901,20 @@ build_vcall_offset_vtbl_entries (binfo, vid) ...@@ -7898,22 +7901,20 @@ build_vcall_offset_vtbl_entries (binfo, vid)
vtable. For example: vtable. For example:
class A { virtual void f (); }; class A { virtual void f (); };
class B : virtual public A { }; class B1 : virtual public A { virtual void f (); };
class C: virtual public A, public B {}; class B2 : virtual public A { virtual void f (); };
class C: public B1, public B2 { virtual void f (); };
Now imagine:
A C object has a primary base of B1, which has a primary base of A. A
B* b = new C; C also has a secondary base of B2, which no longer has a primary base
b->f(); 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
The location of `A' is not at a fixed offset relative to `B'; the knowing what (or even whether) this offset will be when we define B2,
offset depends on the complete object derived from `B'. So, so we store this "vcall offset" in the A sub-vtable and look it up in
`B' vtable contains an entry for `f' that indicates by what a "virtual thunk" for B2::f.
amount the `this' pointer for `B' needs to be adjusted to arrive
at `A'.
We need entries for all the functions in our primary vtable and 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; vid->vbase = binfo;
/* Now, walk through the non-virtual bases, adding vcall offsets. */ /* Now, walk through the non-virtual bases, adding vcall offsets. */
add_vcall_offset_vtbl_entries_r (binfo, vid); add_vcall_offset_vtbl_entries_r (binfo, vid);
...@@ -7930,7 +7931,9 @@ add_vcall_offset_vtbl_entries_r (binfo, vid) ...@@ -7930,7 +7931,9 @@ add_vcall_offset_vtbl_entries_r (binfo, vid)
tree primary_binfo; tree primary_binfo;
/* Don't walk into virtual bases -- except, of course, for the /* 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) if (TREE_VIA_VIRTUAL (binfo) && vid->vbase != binfo)
return; return;
...@@ -7964,43 +7967,30 @@ add_vcall_offset_vtbl_entries_1 (binfo, vid) ...@@ -7964,43 +7967,30 @@ add_vcall_offset_vtbl_entries_1 (binfo, vid)
tree base_virtuals; tree base_virtuals;
tree orig_virtuals; tree orig_virtuals;
tree binfo_inits; tree binfo_inits;
int lost_primary = 0; /* If BINFO is a primary base, the most derived class which has BINFO as
/* If BINFO is a primary base, this is the least derived class of a primary base; otherwise, just BINFO. */
BINFO that is not a primary base. */
tree non_primary_binfo; tree non_primary_binfo;
binfo_inits = NULL_TREE; binfo_inits = NULL_TREE;
/* We might be a primary base class. Go up the inheritance /* We might be a primary base class. Go up the inheritance hierarchy
hierarchy until we find the class of which we are a primary base: 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. */ it is the BINFO_VIRTUALS there that we need to consider. */
non_primary_binfo = binfo; non_primary_binfo = binfo;
while (BINFO_INHERITANCE_CHAIN (non_primary_binfo)) while (BINFO_INHERITANCE_CHAIN (non_primary_binfo))
{ {
tree b; tree b;
/* If we have reached a virtual base, then it must be the /* If we have reached a virtual base, then it must be vid->vbase,
virtual base for which we are building vcall offsets. In because we ignore other virtual bases in
turn, the virtual base must be a (possibly indirect) primary add_vcall_offset_vtbl_entries_r. In turn, it must be a primary
base of the class that we are initializing, or we wouldn't base (possibly multi-level) of vid->binfo, or we wouldn't
care about its vtable offsets. */ 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 (TREE_VIA_VIRTUAL (non_primary_binfo))
{ {
if (vid->ctor_vtbl_p) if (non_primary_binfo != vid->vbase)
{ abort ();
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;
}
}
}
non_primary_binfo = vid->binfo; non_primary_binfo = vid->binfo;
break; break;
} }
...@@ -8034,13 +8024,12 @@ add_vcall_offset_vtbl_entries_1 (binfo, vid) ...@@ -8034,13 +8024,12 @@ add_vcall_offset_vtbl_entries_1 (binfo, vid)
tree vcall_offset; tree vcall_offset;
/* Find the declaration that originally caused this function to /* Find the declaration that originally caused this function to
be present. */ be present in BINFO_TYPE (binfo). */
orig_fn = BV_FN (orig_virtuals); orig_fn = BV_FN (orig_virtuals);
/* We do not need an entry if this function is declared in a /* When processing BINFO, we only want to generate vcall slots for
virtual base (or one of its virtual bases), and not function slots introduced in BINFO. So don't try to generate
overridden in the section of the hierarchy dominated by the one if the function isn't even defined in BINFO. */
virtual base for which we are building vcall offsets. */
if (!same_type_p (DECL_CONTEXT (orig_fn), BINFO_TYPE (binfo))) if (!same_type_p (DECL_CONTEXT (orig_fn), BINFO_TYPE (binfo)))
continue; continue;
...@@ -8071,16 +8060,19 @@ add_vcall_offset_vtbl_entries_1 (binfo, vid) ...@@ -8071,16 +8060,19 @@ add_vcall_offset_vtbl_entries_1 (binfo, vid)
if (i != VARRAY_ACTIVE_SIZE (vid->fns)) if (i != VARRAY_ACTIVE_SIZE (vid->fns))
continue; continue;
/* The FN comes from BASE. So, we must calculate the adjustment /* The FN comes from BASE. So, we must calculate the adjustment from
from the virtual base that derived from BINFO to BASE. */ 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 = DECL_CONTEXT (fn);
base_binfo = get_binfo (base, vid->derived, /*protect=*/0); base_binfo = get_binfo (base, vid->derived, /*protect=*/0);
/* Compute the vcall offset. */ /* Compute the vcall offset. */
vcall_offset = BINFO_OFFSET (vid->vbase); /* As mentioned above, the vbase we're working on is a primary base of
if (lost_primary) vid->binfo. But it might be a lost primary, so its BINFO_OFFSET
vcall_offset = size_binop (PLUS_EXPR, vcall_offset, might be wrong, so we just use the BINFO_OFFSET from vid->binfo. */
BINFO_OFFSET (vid->binfo)); vcall_offset = BINFO_OFFSET (vid->binfo);
vcall_offset = size_diffop (BINFO_OFFSET (base_binfo), vcall_offset = size_diffop (BINFO_OFFSET (base_binfo),
vcall_offset); vcall_offset);
vcall_offset = fold (build1 (NOP_EXPR, vtable_entry_type, vcall_offset = fold (build1 (NOP_EXPR, vtable_entry_type,
...@@ -8091,7 +8083,7 @@ add_vcall_offset_vtbl_entries_1 (binfo, vid) ...@@ -8091,7 +8083,7 @@ add_vcall_offset_vtbl_entries_1 (binfo, vid)
/* Keep track of the vtable index where this vcall offset can be /* Keep track of the vtable index where this vcall offset can be
found. For a construction vtable, we already made this 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) if (!vid->ctor_vtbl_p)
BV_VCALL_INDEX (derived_virtuals) = vid->index; BV_VCALL_INDEX (derived_virtuals) = vid->index;
...@@ -8172,11 +8164,10 @@ build_rtti_vtbl_entries (binfo, vid) ...@@ -8172,11 +8164,10 @@ build_rtti_vtbl_entries (binfo, vid)
ABI.) */ ABI.) */
static tree static tree
build_vtable_entry (delta, vcall_index, entry, generate_with_vtable_p) build_vtable_entry (delta, vcall_index, entry)
tree delta; tree delta;
tree vcall_index; tree vcall_index;
tree entry; tree entry;
int generate_with_vtable_p;
{ {
if (flag_vtable_thunks) if (flag_vtable_thunks)
{ {
...@@ -8186,8 +8177,7 @@ build_vtable_entry (delta, vcall_index, entry, generate_with_vtable_p) ...@@ -8186,8 +8177,7 @@ build_vtable_entry (delta, vcall_index, entry, generate_with_vtable_p)
if ((!integer_zerop (delta) || vcall_index != NULL_TREE) if ((!integer_zerop (delta) || vcall_index != NULL_TREE)
&& fn != abort_fndecl) && fn != abort_fndecl)
{ {
entry = make_thunk (entry, delta, vcall_index, entry = make_thunk (entry, delta, vcall_index);
generate_with_vtable_p);
entry = build1 (ADDR_EXPR, vtable_entry_type, entry); entry = build1 (ADDR_EXPR, vtable_entry_type, entry);
TREE_READONLY (entry) = 1; TREE_READONLY (entry) = 1;
TREE_CONSTANT (entry) = 1; TREE_CONSTANT (entry) = 1;
......
...@@ -55,7 +55,6 @@ Boston, MA 02111-1307, USA. */ ...@@ -55,7 +55,6 @@ Boston, MA 02111-1307, USA. */
BASELINK_P (in TREE_LIST) BASELINK_P (in TREE_LIST)
ICS_ELLIPSIS_FLAG (in _CONV) ICS_ELLIPSIS_FLAG (in _CONV)
BINFO_ACCESS (in BINFO) BINFO_ACCESS (in BINFO)
BV_GENERATE_THUNK_WITH_VTABLE_P (in TREE_LIST)
2: IDENTIFIER_OPNAME_P. 2: IDENTIFIER_OPNAME_P.
TYPE_POLYMORHPIC_P (in _TYPE) TYPE_POLYMORHPIC_P (in _TYPE)
ICS_THIS_FLAG (in _CONV) ICS_THIS_FLAG (in _CONV)
...@@ -133,10 +132,6 @@ Boston, MA 02111-1307, USA. */ ...@@ -133,10 +132,6 @@ Boston, MA 02111-1307, USA. */
The BV_FN is the declaration for the virtual function itself. 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 BINFO_VTABLE
Sometimes this is a VAR_DECL. Under the new ABI, it is instead Sometimes this is a VAR_DECL. Under the new ABI, it is instead
an expression with POINTER_TYPE pointing that gives the value an expression with POINTER_TYPE pointing that gives the value
...@@ -1737,14 +1732,6 @@ struct lang_type ...@@ -1737,14 +1732,6 @@ struct lang_type
#define BV_USE_VCALL_INDEX_P(NODE) \ #define BV_USE_VCALL_INDEX_P(NODE) \
(TREE_LANG_FLAG_0 (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 /* Nonzero for TREE_LIST node means that this list of things
is a list of parameters, as opposed to a list of expressions. */ is a list of parameters, as opposed to a list of expressions. */
#define TREE_PARMLIST(NODE) (TREE_LANG_FLAG_2 (NODE)) #define TREE_PARMLIST(NODE) (TREE_LANG_FLAG_2 (NODE))
...@@ -1806,8 +1793,7 @@ struct lang_decl_flags ...@@ -1806,8 +1793,7 @@ struct lang_decl_flags
unsigned global_dtor_p : 1; unsigned global_dtor_p : 1;
unsigned assignment_operator_p : 1; unsigned assignment_operator_p : 1;
unsigned anticipated_p : 1; unsigned anticipated_p : 1;
unsigned generate_with_vtable_p : 1; /* Three unused bits. */
/* Two unused bits. */
union { union {
/* In a FUNCTION_DECL, VAR_DECL, TYPE_DECL, or TEMPLATE_DECL, this /* In a FUNCTION_DECL, VAR_DECL, TYPE_DECL, or TEMPLATE_DECL, this
...@@ -3036,11 +3022,6 @@ enum ptrmemfunc_vbit_where_t ...@@ -3036,11 +3022,6 @@ enum ptrmemfunc_vbit_where_t
#define THUNK_VCALL_OFFSET(DECL) \ #define THUNK_VCALL_OFFSET(DECL) \
(DECL_LANG_SPECIFIC (DECL)->decl_flags.u2.vcall_offset) (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 /* These macros provide convenient access to the various _STMT nodes
created when parsing template declarations. */ created when parsing template declarations. */
#define TRY_STMTS(NODE) TREE_OPERAND (TRY_BLOCK_CHECK (NODE), 0) #define TRY_STMTS(NODE) TREE_OPERAND (TRY_BLOCK_CHECK (NODE), 0)
...@@ -3716,7 +3697,6 @@ extern tree get_vtable_decl PARAMS ((tree, int)); ...@@ -3716,7 +3697,6 @@ extern tree get_vtable_decl PARAMS ((tree, int));
extern void add_method PARAMS ((tree, tree, int)); extern void add_method PARAMS ((tree, tree, int));
extern int currently_open_class PARAMS ((tree)); extern int currently_open_class PARAMS ((tree));
extern tree currently_open_derived_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 void duplicate_tag_error PARAMS ((tree));
extern tree finish_struct PARAMS ((tree, tree)); extern tree finish_struct PARAMS ((tree, tree));
extern void finish_struct_1 PARAMS ((tree)); extern void finish_struct_1 PARAMS ((tree));
...@@ -4083,7 +4063,7 @@ extern void init_method PARAMS ((void)); ...@@ -4083,7 +4063,7 @@ extern void init_method PARAMS ((void));
extern void set_mangled_name_for_decl PARAMS ((tree)); extern void set_mangled_name_for_decl PARAMS ((tree));
extern tree build_opfncall PARAMS ((enum tree_code, int, tree, tree, tree)); extern tree build_opfncall PARAMS ((enum tree_code, int, tree, tree, tree));
extern tree hack_identifier PARAMS ((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 use_thunk PARAMS ((tree, int));
extern void synthesize_method PARAMS ((tree)); extern void synthesize_method PARAMS ((tree));
extern tree implicitly_declare_fn PARAMS ((special_function_kind, tree, int)); extern tree implicitly_declare_fn PARAMS ((special_function_kind, tree, int));
...@@ -4202,6 +4182,7 @@ extern tree context_for_name_lookup PARAMS ((tree)); ...@@ -4202,6 +4182,7 @@ extern tree context_for_name_lookup PARAMS ((tree));
extern tree lookup_conversions PARAMS ((tree)); extern tree lookup_conversions PARAMS ((tree));
extern tree binfo_for_vtable PARAMS ((tree)); extern tree binfo_for_vtable PARAMS ((tree));
extern tree binfo_from_vbase PARAMS ((tree)); extern tree binfo_from_vbase PARAMS ((tree));
extern tree look_for_overrides_here PARAMS ((tree, tree));
extern tree dfs_walk PARAMS ((tree, extern tree dfs_walk PARAMS ((tree,
tree (*) (tree, void *), tree (*) (tree, void *),
tree (*) (tree, void *), tree (*) (tree, void *),
......
...@@ -2265,7 +2265,7 @@ mark_vtable_entries (decl) ...@@ -2265,7 +2265,7 @@ mark_vtable_entries (decl)
we know all the thunks we'll need when we emit a virtual we know all the thunks we'll need when we emit a virtual
function, so we emit the thunks there instead. */ function, so we emit the thunks there instead. */
if (DECL_THUNK_P (fn)) if (DECL_THUNK_P (fn))
use_thunk (fn, THUNK_GENERATE_WITH_VTABLE_P (fn)); use_thunk (fn, /*emit_p=*/0);
mark_used (fn); mark_used (fn);
} }
} }
...@@ -2369,7 +2369,12 @@ key_method (type) ...@@ -2369,7 +2369,12 @@ key_method (type)
method = TREE_CHAIN (method)) method = TREE_CHAIN (method))
if (DECL_VINDEX (method) != NULL_TREE if (DECL_VINDEX (method) != NULL_TREE
&& ! DECL_DECLARED_INLINE_P (method) && ! 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 method;
return NULL_TREE; return NULL_TREE;
......
...@@ -295,11 +295,10 @@ request for member `%D' is ambiguous in multiple inheritance lattice", ...@@ -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. */ DELTA is the offset to this and VCALL_INDEX is zero. */
tree tree
make_thunk (function, delta, vcall_index, generate_with_vtable_p) make_thunk (function, delta, vcall_index)
tree function; tree function;
tree delta; tree delta;
tree vcall_index; tree vcall_index;
int generate_with_vtable_p;
{ {
tree thunk_id; tree thunk_id;
tree thunk; tree thunk;
...@@ -348,7 +347,6 @@ make_thunk (function, delta, vcall_index, generate_with_vtable_p) ...@@ -348,7 +347,6 @@ make_thunk (function, delta, vcall_index, generate_with_vtable_p)
DECL_INITIAL (thunk) = function; DECL_INITIAL (thunk) = function;
THUNK_DELTA (thunk) = d; THUNK_DELTA (thunk) = d;
THUNK_VCALL_OFFSET (thunk) = vcall_offset; 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 thunk itself is not a constructor or destructor, even if
the thing it is thunking to is. */ the thing it is thunking to is. */
DECL_INTERFACE_KNOWN (thunk) = 1; DECL_INTERFACE_KNOWN (thunk) = 1;
...@@ -381,7 +379,6 @@ void ...@@ -381,7 +379,6 @@ void
use_thunk (thunk_fndecl, emit_p) use_thunk (thunk_fndecl, emit_p)
tree thunk_fndecl; tree thunk_fndecl;
int emit_p; int emit_p;
{ {
tree fnaddr; tree fnaddr;
tree function; tree function;
......
...@@ -2024,56 +2024,72 @@ look_for_overrides (type, fndecl) ...@@ -2024,56 +2024,72 @@ look_for_overrides (type, fndecl)
return found; return found;
} }
/* Look in TYPE for virtual functions overridden by FNDECL. Check both /* Look in TYPE for virtual functions with the same signature as FNDECL.
TYPE itself and its bases. */ This differs from get_matching_virtual in that it will only return
a function from TYPE. */
static int tree
look_for_overrides_r (type, fndecl) look_for_overrides_here (type, fndecl)
tree type, fndecl; tree type, fndecl;
{ {
int ix; int ix;
if (DECL_DESTRUCTOR_P (fndecl)) if (DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (fndecl))
ix = CLASSTYPE_DESTRUCTOR_SLOT; ix = CLASSTYPE_DESTRUCTOR_SLOT;
else else
ix = lookup_fnfields_1 (type, DECL_NAME (fndecl)); ix = lookup_fnfields_1 (type, DECL_NAME (fndecl));
if (ix >= 0) if (ix >= 0)
{ {
tree fns = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (type), ix); 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)) for (; fns; fns = OVL_NEXT (fns))
{ {
tree fn = OVL_CURRENT (fns); tree fn = OVL_CURRENT (fns);
tree btypes = TYPE_ARG_TYPES (TREE_TYPE (fn));
if (!DECL_VIRTUAL_P (fn)) if (!DECL_VIRTUAL_P (fn))
/* Not a virtual */; /* Not a virtual. */;
else if (DECL_CONTEXT (fn) != type) else if (DECL_CONTEXT (fn) != type)
/* Introduced with a using declaration */; /* Introduced with a using declaration. */;
else if (thistype == NULL_TREE) 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)) 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. */
static int
look_for_overrides_r (type, fndecl)
tree type, fndecl;
{
tree fn = look_for_overrides_here (type, fndecl);
if (fn)
{
if (DECL_STATIC_FUNCTION_P (fndecl))
{ {
/* A static member function cannot match an inherited /* A static member function cannot match an inherited
virtual member function. */ virtual member function. */
cp_error_at ("`%#D' cannot be declared", fndecl); cp_error_at ("`%#D' cannot be declared", fndecl);
cp_error_at (" since `%#D' declared in base class", fn); cp_error_at (" since `%#D' declared in base class", fn);
return 1;
} }
} else
else if (same_signature_p (fndecl, fn))
{ {
/* It's definitely virtual, even if not explicitly set. */ /* It's definitely virtual, even if not explicitly set. */
DECL_VIRTUAL_P (fndecl) = 1; DECL_VIRTUAL_P (fndecl) = 1;
check_final_overrider (fndecl, fn); check_final_overrider (fndecl, fn);
return 1;
}
} }
return 1;
} }
/* We failed to find one declared in this class. Look in its bases. */ /* We failed to find one declared in this class. Look in its bases. */
return look_for_overrides (type, fndecl); return look_for_overrides (type, fndecl);
} }
......
...@@ -2300,7 +2300,7 @@ emit_associated_thunks (fn) ...@@ -2300,7 +2300,7 @@ emit_associated_thunks (fn)
for (v = BINFO_VIRTUALS (binfo); v; v = TREE_CHAIN (v)) for (v = BINFO_VIRTUALS (binfo); v; v = TREE_CHAIN (v))
if (BV_FN (v) == fn if (BV_FN (v) == fn
&& (!integer_zerop (BV_DELTA (v)) && (!integer_zerop (BV_DELTA (v))
|| BV_VCALL_INDEX (v))) || BV_USE_VCALL_INDEX_P (v)))
{ {
tree thunk; tree thunk;
tree vcall_index; tree vcall_index;
...@@ -2317,8 +2317,7 @@ emit_associated_thunks (fn) ...@@ -2317,8 +2317,7 @@ emit_associated_thunks (fn)
vfunc_ptr_type_node, vfunc_ptr_type_node,
fn), fn),
BV_DELTA (v), BV_DELTA (v),
vcall_index, vcall_index);
/*generate_with_vtable_p=*/0);
use_thunk (thunk, /*emit_p=*/1); use_thunk (thunk, /*emit_p=*/1);
} }
} }
......
...@@ -26,4 +26,3 @@ C c; ...@@ -26,4 +26,3 @@ C c;
// { dg-final { scan-assembler mangle1.C "\n_ZTT1C:" } } // { dg-final { scan-assembler mangle1.C "\n_ZTT1C:" } }
// { dg-final { scan-assembler mangle1.C "\n_ZTV1A:" } } // { dg-final { scan-assembler mangle1.C "\n_ZTV1A:" } }
// { dg-final { scan-assembler mangle1.C "\n_ZTV1C:" } } // { dg-final { scan-assembler mangle1.C "\n_ZTV1C:" } }
// { dg-final { scan-assembler mangle1.C "\n_ZTv0_n\(12|24\)_N1A1fEv:" } }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment