aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp/class.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/cp/class.c')
-rw-r--r--gcc/cp/class.c66
1 files changed, 45 insertions, 21 deletions
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index b57200fae3e..0e3e6570359 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -1,6 +1,7 @@
/* Functions related to building classes and their related objects.
Copyright (C) 1987, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+ 1999, 2000, 2001, 2002, 2003, 2004, 2005
+ Free Software Foundation, Inc.
Contributed by Michael Tiemann (tiemann@cygnus.com)
This file is part of GCC.
@@ -2115,6 +2116,9 @@ update_vtable_entry_for_fn (tree t, tree binfo, tree fn, tree* virtuals,
also be converting to the return type of FN, we have to
combine the two conversions here. */
tree fixed_offset, virtual_offset;
+
+ over_return = TREE_TYPE (over_return);
+ base_return = TREE_TYPE (base_return);
if (DECL_THUNK_P (fn))
{
@@ -2132,32 +2136,51 @@ update_vtable_entry_for_fn (tree t, tree binfo, tree fn, tree* virtuals,
virtual_offset =
TREE_VALUE (purpose_member
(BINFO_TYPE (virtual_offset),
- CLASSTYPE_VBASECLASSES (TREE_TYPE (over_return))));
- else if (!same_type_p (TREE_TYPE (over_return),
- TREE_TYPE (base_return)))
+ CLASSTYPE_VBASECLASSES (over_return)));
+ else if (!same_type_ignoring_top_level_qualifiers_p
+ (over_return, base_return))
{
- /* There was no existing virtual thunk (which takes
- precedence). */
- tree thunk_binfo;
- base_kind kind;
+ /* There was no existing virtual thunk (which takes
+ precedence). So find the binfo of the base function's
+ return type within the overriding function's return type.
+ We cannot call lookup base here, because we're inside a
+ dfs_walk, and will therefore clobber the BINFO_MARKED
+ flags. Fortunately we know the covariancy is valid (it
+ has already been checked), so we can just iterate along
+ the binfos, which have been chained in inheritance graph
+ order. Of course it is lame that we have to repeat the
+ search here anyway -- we should really be caching pieces
+ of the vtable and avoiding this repeated work. */
+ tree thunk_binfo, base_binfo;
+
+ /* Find the base binfo within the overriding function's
+ return type. We will always find a thunk_binfo, except
+ when the covariancy is invalid (which we will have
+ already diagnosed). */
+ for (base_binfo = TYPE_BINFO (base_return),
+ thunk_binfo = TYPE_BINFO (over_return);
+ thunk_binfo;
+ thunk_binfo = TREE_CHAIN (thunk_binfo))
+ if (same_type_p (BINFO_TYPE (thunk_binfo),
+ BINFO_TYPE (base_binfo)))
+ break;
- thunk_binfo = lookup_base (TREE_TYPE (over_return),
- TREE_TYPE (base_return),
- ba_check | ba_quiet, &kind);
-
- if (thunk_binfo && (kind == bk_via_virtual
- || !BINFO_OFFSET_ZEROP (thunk_binfo)))
+ /* See if virtual inheritance is involved. */
+ for (virtual_offset = thunk_binfo;
+ virtual_offset;
+ virtual_offset = BINFO_INHERITANCE_CHAIN (virtual_offset))
+ if (TREE_VIA_VIRTUAL (virtual_offset))
+ break;
+
+ if (virtual_offset
+ || (thunk_binfo && !BINFO_OFFSET_ZEROP (thunk_binfo)))
{
tree offset = convert (ssizetype, BINFO_OFFSET (thunk_binfo));
- if (kind == bk_via_virtual)
+ if (virtual_offset)
{
- /* 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 = thunk_binfo;
+ /* We convert via virtual base. Adjust the fixed
+ offset to be from there. */
offset = size_diffop
(offset, convert
(ssizetype, BINFO_OFFSET (virtual_offset)));
@@ -5232,6 +5255,7 @@ finish_struct (tree t, tree attributes)
{
finish_struct_methods (t);
TYPE_SIZE (t) = bitsize_zero_node;
+ TYPE_SIZE_UNIT (t) = size_zero_node;
}
else
finish_struct_1 (t);