aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNathan Sidwell <nathan@codesourcery.com>2002-12-31 19:43:16 +0000
committerNathan Sidwell <nathan@gcc.gnu.org>2002-12-31 19:43:16 +0000
commit3cfabe60d4c8f85750afa5cf61a66a13a1140097 (patch)
treefcffe3f938dfc8c7c725a5aa63895202f9d645b5
parent3b41afd944b8413290a47b776d638abfe7321969 (diff)
downloadgcc-3cfabe60d4c8f85750afa5cf61a66a13a1140097.zip
gcc-3cfabe60d4c8f85750afa5cf61a66a13a1140097.tar.gz
gcc-3cfabe60d4c8f85750afa5cf61a66a13a1140097.tar.bz2
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
-rw-r--r--gcc/cp/ChangeLog9
-rw-r--r--gcc/cp/class.c144
-rw-r--r--gcc/cp/cp-tree.h10
-rw-r--r--gcc/cp/decl2.c9
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/g++.dg/inherit/covariant8.C34
6 files changed, 142 insertions, 68 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 921c0de..987e42b 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,12 @@
+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>
* cp-tree.def (RETURN_INIT): Remove.
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index 0ce3f11..b54c1f6 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -716,8 +716,6 @@ modify_vtable_entry (t, binfo, fndecl, delta, virtuals)
if (fndecl != BV_FN (v)
|| !tree_int_cst_equal (delta, BV_DELTA (v)))
{
- tree base_fndecl;
-
/* We need a new vtable for BINFO. */
if (make_new_vtable (t, binfo))
{
@@ -730,7 +728,6 @@ modify_vtable_entry (t, binfo, fndecl, delta, virtuals)
v = *virtuals;
}
- base_fndecl = BV_FN (v);
BV_DELTA (v) = delta;
BV_VCALL_INDEX (v) = NULL_TREE;
BV_FN (v) = fndecl;
@@ -2331,9 +2328,6 @@ get_vcall_index (tree fn, tree type)
{
tree v;
- if (DECL_THUNK_P (fn))
- fn = THUNK_TARGET (fn);
-
for (v = CLASSTYPE_VCALL_INDICES (type); v; v = TREE_CHAIN (v))
if ((DECL_DESTRUCTOR_P (fn) && DECL_DESTRUCTOR_P (TREE_PURPOSE (v)))
|| same_signature_p (fn, TREE_PURPOSE (v)))
@@ -2361,18 +2355,18 @@ update_vtable_entry_for_fn (t, binfo, fn, virtuals)
tree delta;
tree virtual_base;
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;
- if (DECL_THUNK_P (fn))
- fn = THUNK_TARGET (fn);
-
/* 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))
{
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;
/* The nearest definition is from a lost primary. */
@@ -2382,58 +2376,85 @@ update_vtable_entry_for_fn (t, binfo, fn, virtuals)
first_defn = b;
/* 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)
return;
- {
- /* Check for adjusting covariant return types. */
- tree over_return = TREE_TYPE (TREE_TYPE (TREE_PURPOSE (overrider)));
- tree base_return = TREE_TYPE (TREE_TYPE (fn));
-
- if (POINTER_TYPE_P (over_return)
- && TREE_CODE (over_return) == TREE_CODE (base_return)
- && CLASS_TYPE_P (TREE_TYPE (over_return))
- && CLASS_TYPE_P (TREE_TYPE (base_return)))
- {
- tree binfo;
- base_kind kind;
+ overrider_target = overrider_fn = TREE_PURPOSE (overrider);
+
+ /* Check for adjusting covariant return types. */
+ over_return = TREE_TYPE (TREE_TYPE (overrider_target));
+ base_return = TREE_TYPE (TREE_TYPE (target_fn));
+
+ if (POINTER_TYPE_P (over_return)
+ && TREE_CODE (over_return) == TREE_CODE (base_return)
+ && CLASS_TYPE_P (TREE_TYPE (over_return))
+ && CLASS_TYPE_P (TREE_TYPE (base_return)))
+ {
+ /* 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;
- binfo = lookup_base (TREE_TYPE (over_return), TREE_TYPE (base_return),
- ba_check | ba_quiet, &kind);
+ if (!virtual_offset)
+ {
+ /* There was no existing virtual thunk (which takes
+ precidence). */
+ tree thunk_binfo;
+ base_kind kind;
+
+ thunk_binfo = lookup_base (TREE_TYPE (over_return),
+ TREE_TYPE (base_return),
+ ba_check | ba_quiet, &kind);
- if (binfo && (kind == bk_via_virtual || !BINFO_OFFSET_ZEROP (binfo)))
- {
- tree fixed_offset = BINFO_OFFSET (binfo);
- tree virtual_offset = NULL_TREE;
- tree thunk;
-
- if (kind == bk_via_virtual)
- {
- while (!TREE_VIA_VIRTUAL (binfo))
- binfo = BINFO_INHERITANCE_CHAIN (binfo);
-
- /* If the covariant type is within the class hierarchy
- 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));
- fixed_offset = size_diffop (fixed_offset,
- BINFO_OFFSET (virtual_offset));
- }
-
- /* Replace the overriding function with a covariant thunk.
- We will emit the overriding function in its own slot
- as well. */
- thunk = make_thunk (TREE_PURPOSE (overrider), /*this_adjusting=*/0,
- fixed_offset, virtual_offset);
- TREE_PURPOSE (overrider) = thunk;
- if (!virtual_offset && !DECL_NAME (thunk))
- finish_thunk (thunk);
- }
- }
- }
+ if (thunk_binfo && (kind == bk_via_virtual
+ || !BINFO_OFFSET_ZEROP (thunk_binfo)))
+ {
+ tree offset = BINFO_OFFSET (thunk_binfo);
+ if (kind == bk_via_virtual)
+ {
+ /* We convert via virtual base. Find the virtual
+ base and adjust the fixed offset to be from there. */
+ while (!TREE_VIA_VIRTUAL (thunk_binfo))
+ thunk_binfo = BINFO_INHERITANCE_CHAIN (thunk_binfo);
+
+ virtual_offset = binfo_for_vbase (BINFO_TYPE (thunk_binfo),
+ TREE_TYPE (over_return));
+ offset = size_diffop (offset,
+ BINFO_OFFSET (virtual_offset));
+ }
+ if (fixed_offset)
+ /* There was an existing fixed offset, this must be
+ from the base just converted to, and the base the
+ FN was thunking to. */
+ fixed_offset = size_binop (PLUS_EXPR, fixed_offset, offset);
+ else
+ fixed_offset = offset;
+ }
+ }
+
+ 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
the final overrider, and not to an intermediate virtual base. */
virtual_base = NULL_TREE;
@@ -2476,16 +2497,11 @@ update_vtable_entry_for_fn (t, binfo, fn, virtuals)
delta = size_diffop (BINFO_OFFSET (TREE_VALUE (overrider)),
BINFO_OFFSET (binfo));
- modify_vtable_entry (t,
- binfo,
- TREE_PURPOSE (overrider),
- delta,
- virtuals);
+ modify_vtable_entry (t, binfo, overrider_fn, delta, virtuals);
if (virtual_base)
BV_VCALL_INDEX (*virtuals)
- = get_vcall_index (TREE_PURPOSE (overrider),
- BINFO_TYPE (virtual_base));
+ = get_vcall_index (overrider_target, BINFO_TYPE (virtual_base));
}
/* Called from modify_all_vtables via dfs_walk. */
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 3346a1f..e27c668 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -2977,9 +2977,13 @@ struct lang_decl GTY(())
/* 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
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
- offset zero from the this or result pointer. If NULL, then there
- is no virtual adjust. */
+ binfo of the relevant virtual base. If NULL, then there is no
+ virtual adjust. (The vptr is always located at offset zero from
+ 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) \
(LANG_DECL_U2_CHECK (VAR_OR_FUNCTION_DECL_CHECK (DECL), 0)->virtual_offset)
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index 6efb9bd..8e440e9 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -2802,7 +2802,14 @@ finish_file ()
if (TREE_USED (decl) && DECL_DECLARED_INLINE_P (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. */
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index f3378e4..b63e008 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,7 @@
+2002-12-31 Nathan Sidwell <nathan@codesourcery.com>
+
+ * g++.dg/inherit/covariant8.C: New test.
+
2002-12-31 Mark Mitchell <mark@codesourcery.com>
* g++.dg/init/array9.C: New test.
diff --git a/gcc/testsuite/g++.dg/inherit/covariant8.C b/gcc/testsuite/g++.dg/inherit/covariant8.C
new file mode 100644
index 0000000..33dc431
--- /dev/null
+++ b/gcc/testsuite/g++.dg/inherit/covariant8.C
@@ -0,0 +1,34 @@
+// { 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 {};