Commit f11ee281 by Jason Merrill Committed by Jason Merrill

class.c (update_vtable_entry_for_fn): Set delta to zero for a lost primary.

        * class.c (update_vtable_entry_for_fn): Set delta to zero for a
        lost primary.

        * class.c (build_vtbl_initializer): Check for a lost primary
        before calculating the vtable entry to throw away.

From-SVN: r48535
parent 7b4795cc
2002-01-04 Jason Merrill <jason@redhat.com>
* class.c (update_vtable_entry_for_fn): Set delta to zero for a
lost primary.
* class.c (build_vtbl_initializer): Check for a lost primary
before calculating the vtable entry to throw away.
2002-01-02 Jason Merrill <jason@redhat.com> 2002-01-02 Jason Merrill <jason@redhat.com>
* semantics.c (expand_body): Call outlining_inline_function when * semantics.c (expand_body): Call outlining_inline_function when
......
...@@ -2494,6 +2494,7 @@ update_vtable_entry_for_fn (t, binfo, fn, virtuals) ...@@ -2494,6 +2494,7 @@ update_vtable_entry_for_fn (t, binfo, fn, virtuals)
tree delta; tree delta;
tree virtual_base; tree virtual_base;
tree first_defn; tree first_defn;
bool lost = false;
/* Find the nearest primary base (possibly binfo itself) which defines /* Find the nearest primary base (possibly binfo itself) which defines
this function; this is the class the caller will convert to when this function; this is the class the caller will convert to when
...@@ -2502,6 +2503,10 @@ update_vtable_entry_for_fn (t, binfo, fn, virtuals) ...@@ -2502,6 +2503,10 @@ update_vtable_entry_for_fn (t, binfo, fn, virtuals)
{ {
if (look_for_overrides_here (BINFO_TYPE (b), fn)) if (look_for_overrides_here (BINFO_TYPE (b), fn))
break; break;
/* The nearest definition is from a lost primary. */
if (BINFO_LOST_PRIMARY_P (b))
lost = true;
} }
first_defn = b; first_defn = b;
...@@ -2514,9 +2519,9 @@ update_vtable_entry_for_fn (t, binfo, fn, virtuals) ...@@ -2514,9 +2519,9 @@ update_vtable_entry_for_fn (t, binfo, fn, virtuals)
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;
/* We will convert to an intermediate virtual base first, and then /* See if we can convert to an intermediate virtual base first, and then
use the vcall offset located there to finish the conversion. */ use the vcall offset located there to finish the conversion. */
while (b) for (; b; b = BINFO_INHERITANCE_CHAIN (b))
{ {
/* If we find the final overrider, then we can stop /* If we find the final overrider, then we can stop
walking. */ walking. */
...@@ -2529,8 +2534,6 @@ update_vtable_entry_for_fn (t, binfo, fn, virtuals) ...@@ -2529,8 +2534,6 @@ update_vtable_entry_for_fn (t, binfo, fn, virtuals)
declaring base (first_defn) 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))
virtual_base = b; virtual_base = b;
b = BINFO_INHERITANCE_CHAIN (b);
} }
/* Compute the constant adjustment to the `this' pointer. The /* Compute the constant adjustment to the `this' pointer. The
...@@ -2542,6 +2545,12 @@ update_vtable_entry_for_fn (t, binfo, fn, virtuals) ...@@ -2542,6 +2545,12 @@ update_vtable_entry_for_fn (t, binfo, fn, virtuals)
the nearest virtual base. */ the nearest virtual base. */
delta = size_diffop (BINFO_OFFSET (virtual_base), delta = size_diffop (BINFO_OFFSET (virtual_base),
BINFO_OFFSET (first_defn)); BINFO_OFFSET (first_defn));
else if (lost)
/* If the nearest definition is in a lost primary, we don't need an
entry in our vtable. Except possibly in a constructor vtable,
if we happen to get our primary back. In that case, the offset
will be zero, as it will be a primary base. */
delta = size_zero_node;
else else
{ {
/* The `this' pointer needs to be adjusted from pointing to /* The `this' pointer needs to be adjusted from pointing to
...@@ -7502,62 +7511,66 @@ build_vtbl_initializer (binfo, orig_binfo, t, rtti_binfo, non_fn_entries_p) ...@@ -7502,62 +7511,66 @@ build_vtbl_initializer (binfo, orig_binfo, t, rtti_binfo, non_fn_entries_p)
tree vcall_index; tree vcall_index;
tree fn; tree fn;
tree pfn; tree pfn;
tree init; tree init = NULL_TREE;
/* Pull the offset for `this', and the function to call, out of
the list. */
delta = BV_DELTA (v);
if (BV_USE_VCALL_INDEX_P (v))
{
vcall_index = BV_VCALL_INDEX (v);
my_friendly_assert (vcall_index != NULL_TREE, 20000621);
}
else
vcall_index = NULL_TREE;
fn = BV_FN (v); fn = BV_FN (v);
my_friendly_assert (TREE_CODE (delta) == INTEGER_CST, 19990727);
my_friendly_assert (TREE_CODE (fn) == FUNCTION_DECL, 19990727);
/* You can't call an abstract virtual function; it's abstract.
So, we replace these functions with __pure_virtual. */
if (DECL_PURE_VIRTUAL_P (fn))
fn = abort_fndecl;
/* Take the address of the function, considering it to be of an
appropriate generic type. */
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);
/* If the only definition of this function signature along our /* If the only definition of this function signature along our
primary base chain is from a lost primary, this vtable slot will 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 never be used, so just zero it out. This is important to avoid
requiring extra thunks which cannot be generated with the function. requiring extra thunks which cannot be generated with the function.
We could also handle this in update_vtable_entry_for_fn; doing it We first check this in update_vtable_entry_for_fn, so we handle
here means we zero out unused slots in ctor vtables as well, restored primary bases properly; we also need to do it here so we
rather than filling them with erroneous values (though harmless, zero out unused slots in ctor vtables, rather than filling themff
apart from relocation costs). */ with erroneous values (though harmless, apart from relocation
if (fn != abort_fndecl) costs). */
for (b = binfo; ; b = get_primary_binfo (b)) for (b = binfo; ; b = get_primary_binfo (b))
{ {
/* We found a defn before a lost primary; go ahead as normal. */ /* We found a defn before a lost primary; go ahead as normal. */
if (look_for_overrides_here (BINFO_TYPE (b), fn)) 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; break;
}
}
/* The nearest definition is from a lost primary; clear the if (! init)
slot. */ {
if (BINFO_LOST_PRIMARY_P (b)) /* Pull the offset for `this', and the function to call, out of
{ the list. */
init = size_zero_node; delta = BV_DELTA (v);
break;
} if (BV_USE_VCALL_INDEX_P (v))
} {
vcall_index = BV_VCALL_INDEX (v);
my_friendly_assert (vcall_index != NULL_TREE, 20000621);
}
else
vcall_index = NULL_TREE;
my_friendly_assert (TREE_CODE (delta) == INTEGER_CST, 19990727);
my_friendly_assert (TREE_CODE (fn) == FUNCTION_DECL, 19990727);
/* You can't call an abstract virtual function; it's abstract.
So, we replace these functions with __pure_virtual. */
if (DECL_PURE_VIRTUAL_P (fn))
fn = abort_fndecl;
/* Take the address of the function, considering it to be of an
appropriate generic type. */
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);
}
/* And add it to the chain of initializers. */ /* And add it to the chain of initializers. */
if (TARGET_VTABLE_USES_DESCRIPTORS) if (TARGET_VTABLE_USES_DESCRIPTORS)
......
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