Commit 3cfabe60 by Nathan Sidwell Committed by Nathan Sidwell

class.c (modify_vtable_entry): Remove unused variable.

cp:
	* class.c (modify_vtable_entry): Remove unused variable.
	(get_vcall_index): Always expect a non-thunk.
	(update_vtable_entry_for_fn): Combine covariant adjustments, when
	overriding a thunk. Pass get_vcall_index a non-thunk.

	* decl2.c (finish_file): Mark undefined inlines as extern.
testsuite:
	* g++.dg/inherit/covariant8.C: New test.

From-SVN: r60710
parent 3b41afd9
2002-12-31 Nathan Sidwell <nathan@codesourcery.com>
* class.c (modify_vtable_entry): Remove unused variable.
(get_vcall_index): Always expect a non-thunk.
(update_vtable_entry_for_fn): Combine covariant adjustments, when
overriding a thunk. Pass get_vcall_index a non-thunk.
* decl2.c (finish_file): Mark undefined inlines as extern.
2002-12-31 Mark Mitchell <mark@codesourcery.com> 2002-12-31 Mark Mitchell <mark@codesourcery.com>
* cp-tree.def (RETURN_INIT): Remove. * cp-tree.def (RETURN_INIT): Remove.
......
...@@ -716,8 +716,6 @@ modify_vtable_entry (t, binfo, fndecl, delta, virtuals) ...@@ -716,8 +716,6 @@ modify_vtable_entry (t, binfo, fndecl, delta, virtuals)
if (fndecl != BV_FN (v) if (fndecl != BV_FN (v)
|| !tree_int_cst_equal (delta, BV_DELTA (v))) || !tree_int_cst_equal (delta, BV_DELTA (v)))
{ {
tree base_fndecl;
/* We need a new vtable for BINFO. */ /* We need a new vtable for BINFO. */
if (make_new_vtable (t, binfo)) if (make_new_vtable (t, binfo))
{ {
...@@ -730,7 +728,6 @@ modify_vtable_entry (t, binfo, fndecl, delta, virtuals) ...@@ -730,7 +728,6 @@ modify_vtable_entry (t, binfo, fndecl, delta, virtuals)
v = *virtuals; v = *virtuals;
} }
base_fndecl = BV_FN (v);
BV_DELTA (v) = delta; BV_DELTA (v) = delta;
BV_VCALL_INDEX (v) = NULL_TREE; BV_VCALL_INDEX (v) = NULL_TREE;
BV_FN (v) = fndecl; BV_FN (v) = fndecl;
...@@ -2331,9 +2328,6 @@ get_vcall_index (tree fn, tree type) ...@@ -2331,9 +2328,6 @@ get_vcall_index (tree fn, tree type)
{ {
tree v; tree v;
if (DECL_THUNK_P (fn))
fn = THUNK_TARGET (fn);
for (v = CLASSTYPE_VCALL_INDICES (type); v; v = TREE_CHAIN (v)) for (v = CLASSTYPE_VCALL_INDICES (type); v; v = TREE_CHAIN (v))
if ((DECL_DESTRUCTOR_P (fn) && DECL_DESTRUCTOR_P (TREE_PURPOSE (v))) if ((DECL_DESTRUCTOR_P (fn) && DECL_DESTRUCTOR_P (TREE_PURPOSE (v)))
|| same_signature_p (fn, TREE_PURPOSE (v))) || same_signature_p (fn, TREE_PURPOSE (v)))
...@@ -2361,18 +2355,18 @@ update_vtable_entry_for_fn (t, binfo, fn, virtuals) ...@@ -2361,18 +2355,18 @@ 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;
tree overrider_fn, overrider_target;
tree target_fn = DECL_THUNK_P (fn) ? THUNK_TARGET (fn) : fn;
tree over_return, base_return;
bool lost = false; bool lost = false;
if (DECL_THUNK_P (fn))
fn = THUNK_TARGET (fn);
/* 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
calling FN through BINFO. */ calling FN through BINFO. */
for (b = binfo; ; b = get_primary_binfo (b)) for (b = binfo; ; b = get_primary_binfo (b))
{ {
my_friendly_assert (b, 20021227); my_friendly_assert (b, 20021227);
if (look_for_overrides_here (BINFO_TYPE (b), fn)) if (look_for_overrides_here (BINFO_TYPE (b), target_fn))
break; break;
/* The nearest definition is from a lost primary. */ /* The nearest definition is from a lost primary. */
...@@ -2382,57 +2376,84 @@ update_vtable_entry_for_fn (t, binfo, fn, virtuals) ...@@ -2382,57 +2376,84 @@ update_vtable_entry_for_fn (t, binfo, fn, virtuals)
first_defn = b; first_defn = b;
/* Find the final overrider. */ /* Find the final overrider. */
overrider = find_final_overrider (TYPE_BINFO (t), b, fn); overrider = find_final_overrider (TYPE_BINFO (t), b, target_fn);
if (overrider == error_mark_node) if (overrider == error_mark_node)
return; return;
{ overrider_target = overrider_fn = TREE_PURPOSE (overrider);
/* Check for adjusting covariant return types. */ /* Check for adjusting covariant return types. */
tree over_return = TREE_TYPE (TREE_TYPE (TREE_PURPOSE (overrider))); over_return = TREE_TYPE (TREE_TYPE (overrider_target));
tree base_return = TREE_TYPE (TREE_TYPE (fn)); base_return = TREE_TYPE (TREE_TYPE (target_fn));
if (POINTER_TYPE_P (over_return) if (POINTER_TYPE_P (over_return)
&& TREE_CODE (over_return) == TREE_CODE (base_return) && TREE_CODE (over_return) == TREE_CODE (base_return)
&& CLASS_TYPE_P (TREE_TYPE (over_return)) && CLASS_TYPE_P (TREE_TYPE (over_return))
&& CLASS_TYPE_P (TREE_TYPE (base_return))) && CLASS_TYPE_P (TREE_TYPE (base_return)))
{ {
tree binfo; /* If FN is a covariant thunk, we must figure out the adjustment
to the final base FN was converting to. As OVERRIDER_TARGET might
also be converting to the return type of FN, we have to
combine the two conversions here. */
tree fixed_offset, virtual_offset;
if (DECL_THUNK_P (fn))
{
fixed_offset = ssize_int (THUNK_FIXED_OFFSET (fn));
virtual_offset = THUNK_VIRTUAL_OFFSET (fn);
if (virtual_offset)
virtual_offset = binfo_for_vbase (BINFO_TYPE (virtual_offset),
TREE_TYPE (over_return));
}
else
fixed_offset = virtual_offset = NULL_TREE;
if (!virtual_offset)
{
/* There was no existing virtual thunk (which takes
precidence). */
tree thunk_binfo;
base_kind kind; base_kind kind;
binfo = lookup_base (TREE_TYPE (over_return), TREE_TYPE (base_return), thunk_binfo = lookup_base (TREE_TYPE (over_return),
TREE_TYPE (base_return),
ba_check | ba_quiet, &kind); ba_check | ba_quiet, &kind);
if (binfo && (kind == bk_via_virtual || !BINFO_OFFSET_ZEROP (binfo))) if (thunk_binfo && (kind == bk_via_virtual
|| !BINFO_OFFSET_ZEROP (thunk_binfo)))
{ {
tree fixed_offset = BINFO_OFFSET (binfo); tree offset = BINFO_OFFSET (thunk_binfo);
tree virtual_offset = NULL_TREE;
tree thunk;
if (kind == bk_via_virtual) if (kind == bk_via_virtual)
{ {
while (!TREE_VIA_VIRTUAL (binfo)) /* We convert via virtual base. Find the virtual
binfo = BINFO_INHERITANCE_CHAIN (binfo); base and adjust the fixed offset to be from there. */
while (!TREE_VIA_VIRTUAL (thunk_binfo))
thunk_binfo = BINFO_INHERITANCE_CHAIN (thunk_binfo);
/* If the covariant type is within the class hierarchy virtual_offset = binfo_for_vbase (BINFO_TYPE (thunk_binfo),
we are currently laying out, the vbase index is not
yet known, so we have to remember the virtual base
binfo. */
virtual_offset = binfo_for_vbase (BINFO_TYPE (binfo),
TREE_TYPE (over_return)); TREE_TYPE (over_return));
fixed_offset = size_diffop (fixed_offset, offset = size_diffop (offset,
BINFO_OFFSET (virtual_offset)); BINFO_OFFSET (virtual_offset));
} }
if (fixed_offset)
/* Replace the overriding function with a covariant thunk. /* There was an existing fixed offset, this must be
We will emit the overriding function in its own slot from the base just converted to, and the base the
as well. */ FN was thunking to. */
thunk = make_thunk (TREE_PURPOSE (overrider), /*this_adjusting=*/0, fixed_offset = size_binop (PLUS_EXPR, fixed_offset, offset);
fixed_offset, virtual_offset); else
TREE_PURPOSE (overrider) = thunk; fixed_offset = offset;
if (!virtual_offset && !DECL_NAME (thunk))
finish_thunk (thunk);
} }
} }
if (fixed_offset || virtual_offset)
/* Replace the overriding function with a covariant thunk. We
will emit the overriding function in its own slot as
well. */
overrider_fn = make_thunk (overrider_target, /*this_adjusting=*/0,
fixed_offset, virtual_offset);
} }
else
my_friendly_assert (!DECL_THUNK_P (fn), 20021231);
/* 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. */
...@@ -2476,16 +2497,11 @@ update_vtable_entry_for_fn (t, binfo, fn, virtuals) ...@@ -2476,16 +2497,11 @@ update_vtable_entry_for_fn (t, binfo, fn, virtuals)
delta = size_diffop (BINFO_OFFSET (TREE_VALUE (overrider)), delta = size_diffop (BINFO_OFFSET (TREE_VALUE (overrider)),
BINFO_OFFSET (binfo)); BINFO_OFFSET (binfo));
modify_vtable_entry (t, modify_vtable_entry (t, binfo, overrider_fn, delta, virtuals);
binfo,
TREE_PURPOSE (overrider),
delta,
virtuals);
if (virtual_base) if (virtual_base)
BV_VCALL_INDEX (*virtuals) BV_VCALL_INDEX (*virtuals)
= get_vcall_index (TREE_PURPOSE (overrider), = get_vcall_index (overrider_target, BINFO_TYPE (virtual_base));
BINFO_TYPE (virtual_base));
} }
/* Called from modify_all_vtables via dfs_walk. */ /* Called from modify_all_vtables via dfs_walk. */
......
...@@ -2977,9 +2977,13 @@ struct lang_decl GTY(()) ...@@ -2977,9 +2977,13 @@ struct lang_decl GTY(())
/* A tree indicating how to perform the virtual adjustment. For a this /* A tree indicating how to perform the virtual adjustment. For a this
adjusting thunk it is the number of bytes to be added to the vtable adjusting thunk it is the number of bytes to be added to the vtable
to find the vcall offset. For a result adjusting thunk, it is the to find the vcall offset. For a result adjusting thunk, it is the
binfo of the relevant virtual base. The vptr is always located at binfo of the relevant virtual base. If NULL, then there is no
offset zero from the this or result pointer. If NULL, then there virtual adjust. (The vptr is always located at offset zero from
is no virtual adjust. */ the this or result pointer.) (If the covariant type is within the
class hierarchy being layed out, the vbase index is not yet known
at the point we need to create the thunks, hence the need to use
binfos.) */
#define THUNK_VIRTUAL_OFFSET(DECL) \ #define THUNK_VIRTUAL_OFFSET(DECL) \
(LANG_DECL_U2_CHECK (VAR_OR_FUNCTION_DECL_CHECK (DECL), 0)->virtual_offset) (LANG_DECL_U2_CHECK (VAR_OR_FUNCTION_DECL_CHECK (DECL), 0)->virtual_offset)
......
...@@ -2802,7 +2802,14 @@ finish_file () ...@@ -2802,7 +2802,14 @@ finish_file ()
if (TREE_USED (decl) && DECL_DECLARED_INLINE_P (decl) if (TREE_USED (decl) && DECL_DECLARED_INLINE_P (decl)
&& !(TREE_ASM_WRITTEN (decl) || DECL_SAVED_TREE (decl))) && !(TREE_ASM_WRITTEN (decl) || DECL_SAVED_TREE (decl)))
{
cp_warning_at ("inline function `%D' used but never defined", decl); cp_warning_at ("inline function `%D' used but never defined", decl);
/* This symbol is effectively an "extern" declaration now.
This is not strictly necessary, but removes a duplicate
warning. */
TREE_PUBLIC (decl) = 1;
}
} }
/* We give C linkage to static constructors and destructors. */ /* We give C linkage to static constructors and destructors. */
......
2002-12-31 Nathan Sidwell <nathan@codesourcery.com>
* g++.dg/inherit/covariant8.C: New test.
2002-12-31 Mark Mitchell <mark@codesourcery.com> 2002-12-31 Mark Mitchell <mark@codesourcery.com>
* g++.dg/init/array9.C: New test. * g++.dg/init/array9.C: New test.
......
// { dg-do compile }
// Copyright (C) 2002 Free Software Foundation, Inc.
// Contributed by Nathan Sidwell 31 Dec 2002 <nathan@codesourcery.com>
// ICE with covariant thunks.
struct c0 {};
struct c1 : virtual c0
{
virtual c0 &f2 ();
};
struct c2
{
int m;
};
struct c3 : virtual c0, virtual c1, c2
{
virtual c1 &f2 ();
};
c1 &c3::f2 ()
{
throw 0;
}
struct c4 : virtual c3, virtual c0, virtual c1 {};
struct c8 : virtual c2, virtual c0 {};
struct c12 : virtual c4, virtual c3, virtual c8 {};
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