aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Mitchell <mark@codesourcery.com>1999-07-27 18:15:21 +0000
committerMark Mitchell <mmitchel@gcc.gnu.org>1999-07-27 18:15:21 +0000
commit83f2ccf4f874f0ec4deb560b82ac87a171bf6617 (patch)
tree6a75d188c0fbbd46be51bc41b17c6e7fcb5cdc03
parentf55dcd41d022f1efd89a609954252be89587b768 (diff)
downloadgcc-83f2ccf4f874f0ec4deb560b82ac87a171bf6617.zip
gcc-83f2ccf4f874f0ec4deb560b82ac87a171bf6617.tar.gz
gcc-83f2ccf4f874f0ec4deb560b82ac87a171bf6617.tar.bz2
cp-tree.h (BINFO_VIRTUALS): Document new format.
* cp-tree.h (BINFO_VIRTUALS): Document new format. * class.c (modify_one_vtable): Change prototype accordingly. (modify_all_vtables): Likewise. (modify_all_direct_vtables): Likewise. (modify_all_indirect_vtables): Likewise. (build_vtable_entry_for_fn): New function. (set_rtti_entry): Simplify for new BINFO_VIRTUALS format. (modify_vtable_entry): Likewise. (add_virtual_function): Likewise. (build_vtbl_initializer): New function. (finish_vtbls): Simplify for new BINFO_VIRTUALS format. (fixup_vtable_deltas1): Likewise. (fixup_vtable_deltas): Likewise. (override_one_vtable): Likewise. (finish_struct_1): Likewise. * error.c (dump_expr): Likewise. * search.c (get_abstract_virtuals_1): Likewise. (get_abstract_virtuals): Likewise. (expand_upcast_fixups): Likewise. * tree.c (debug_binfo): Likewise. * decl2.c (mark_vtable_entries): Don't bash abstract virtuals to __pure_virtual here. From-SVN: r28298
-rw-r--r--gcc/cp/ChangeLog25
-rw-r--r--gcc/cp/class.c283
-rw-r--r--gcc/cp/cp-tree.h9
-rw-r--r--gcc/cp/decl2.c5
-rw-r--r--gcc/cp/error.c4
-rw-r--r--gcc/cp/search.c15
-rw-r--r--gcc/cp/tree.c2
-rw-r--r--gcc/testsuite/g++.old-deja/g++.pt/virtual4.C40
8 files changed, 251 insertions, 132 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index b2e6c07..f3e9d00 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,28 @@
+1999-07-27 Mark Mitchell <mark@codesourcery.com>
+
+ * cp-tree.h (BINFO_VIRTUALS): Document new format.
+ * class.c (modify_one_vtable): Change prototype accordingly.
+ (modify_all_vtables): Likewise.
+ (modify_all_direct_vtables): Likewise.
+ (modify_all_indirect_vtables): Likewise.
+ (build_vtable_entry_for_fn): New function.
+ (set_rtti_entry): Simplify for new BINFO_VIRTUALS format.
+ (modify_vtable_entry): Likewise.
+ (add_virtual_function): Likewise.
+ (build_vtbl_initializer): New function.
+ (finish_vtbls): Simplify for new BINFO_VIRTUALS format.
+ (fixup_vtable_deltas1): Likewise.
+ (fixup_vtable_deltas): Likewise.
+ (override_one_vtable): Likewise.
+ (finish_struct_1): Likewise.
+ * error.c (dump_expr): Likewise.
+ * search.c (get_abstract_virtuals_1): Likewise.
+ (get_abstract_virtuals): Likewise.
+ (expand_upcast_fixups): Likewise.
+ * tree.c (debug_binfo): Likewise.
+ * decl2.c (mark_vtable_entries): Don't bash abstract virtuals to
+ __pure_virtual here.
+
1999-07-26 Mark Mitchell <mark@codesourcery.com>
* tree.c (build_cplus_new): Adjust call to abstract_virtuals_error
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index a4cc5a5..4207d8f 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -121,12 +121,10 @@ static void mark_overriders PROTO((tree, tree));
static void check_for_override PROTO((tree, tree));
static tree get_class_offset_1 PROTO((tree, tree, tree, tree, tree));
static tree get_class_offset PROTO((tree, tree, tree, tree));
-static void modify_one_vtable PROTO((tree, tree, tree, tree));
-static void modify_all_vtables PROTO((tree, tree, tree));
-static void modify_all_direct_vtables PROTO((tree, int, tree, tree,
- tree));
-static void modify_all_indirect_vtables PROTO((tree, int, int, tree,
- tree, tree));
+static void modify_one_vtable PROTO((tree, tree, tree));
+static void modify_all_vtables PROTO((tree, tree));
+static void modify_all_direct_vtables PROTO((tree, int, tree, tree));
+static void modify_all_indirect_vtables PROTO((tree, int, int, tree, tree));
static int finish_base_struct PROTO((tree, struct base_info *));
static void finish_struct_methods PROTO((tree));
static void maybe_warn_about_overly_private_class PROTO ((tree));
@@ -139,6 +137,8 @@ static tree fixed_type_or_null PROTO((tree, int *));
static tree resolve_address_of_overloaded_function PROTO((tree, tree, int,
int, tree));
static void build_vtable_entry_ref PROTO((tree, tree, tree));
+static tree build_vtable_entry_for_fn PROTO((tree, tree));
+static tree build_vtbl_initializer PROTO((tree));
/* Way of stacking language names. */
tree *current_lang_base, *current_lang_stack;
@@ -466,6 +466,25 @@ build_vtable_entry (delta, pfn)
}
}
+/* Build a vtable entry for FNDECL. DELTA is the amount by which we
+ must adjust the this pointer when calling F. */
+
+static tree
+build_vtable_entry_for_fn (delta, fndecl)
+ tree delta;
+ tree fndecl;
+{
+ tree pfn;
+
+ /* Take the address of the function, considering it to be of an
+ appropriate generic type. */
+ pfn = build1 (ADDR_EXPR, vfunc_ptr_type_node, fndecl);
+ /* The address of a function can't change. */
+ TREE_CONSTANT (pfn) = 1;
+ /* Now build the vtable entry itself. */
+ return build_vtable_entry (delta, pfn);
+}
+
/* We want to give the assembler the vtable identifier as well as
the offset to the function pointer. So we generate
@@ -669,30 +688,34 @@ static void
set_rtti_entry (virtuals, offset, type)
tree virtuals, offset, type;
{
- tree vfn;
+ tree fn;
if (CLASSTYPE_COM_INTERFACE (type))
return;
if (flag_rtti)
- vfn = build1 (ADDR_EXPR, vfunc_ptr_type_node, get_tinfo_fn (type));
+ fn = get_tinfo_fn (type);
else
- vfn = build1 (NOP_EXPR, vfunc_ptr_type_node, size_zero_node);
- TREE_CONSTANT (vfn) = 1;
+ /* If someone tries to get RTTI information for a type compiled
+ without RTTI, they're out of luck. By calling __pure_virtual
+ in this case, we give a small clue as to what went wrong. We
+ could consider having a __no_typeinfo function as well, for a
+ more specific hint. */
+ fn = abort_fndecl;
- if (! flag_vtable_thunks)
- TREE_VALUE (virtuals) = build_vtable_entry (offset, vfn);
- else
+ if (flag_vtable_thunks)
{
- tree voff = build1 (NOP_EXPR, vfunc_ptr_type_node, offset);
- TREE_CONSTANT (voff) = 1;
-
- TREE_VALUE (virtuals) = build_vtable_entry (integer_zero_node, voff);
+ /* The first slot holds the offset. */
+ TREE_PURPOSE (virtuals) = offset;
- /* The second slot is for the tdesc pointer when thunks are used. */
- TREE_VALUE (TREE_CHAIN (virtuals))
- = build_vtable_entry (integer_zero_node, vfn);
+ /* The next node holds the function. */
+ virtuals = TREE_CHAIN (virtuals);
+ offset = integer_zero_node;
}
+
+ /* This slot holds the function to call. */
+ TREE_PURPOSE (virtuals) = offset;
+ TREE_VALUE (virtuals) = fn;
}
/* Build a virtual function for type TYPE.
@@ -952,25 +975,21 @@ get_vtable_entry (virtuals, base_fndecl)
}
#endif
-/* Put new entry ENTRY into virtual function table initializer
- VIRTUALS.
-
- Also update DECL_VINDEX (FNDECL). */
+/* Change the offset for the FNDECL entry to NEW_OFFSET. Also update
+ DECL_VINDEX (FNDECL). */
static void
-modify_vtable_entry (old_entry_in_list, new_entry, fndecl)
- tree old_entry_in_list, new_entry, fndecl;
+modify_vtable_entry (old_entry_in_list, new_offset, fndecl)
+ tree old_entry_in_list, new_offset, fndecl;
{
- tree base_fndecl = TREE_OPERAND (FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (old_entry_in_list)), 0);
+ tree base_fndecl = TREE_VALUE (old_entry_in_list);
-#ifdef NOTQUITE
- cp_warning ("replaced %D with %D", DECL_ASSEMBLER_NAME (base_fndecl),
- DECL_ASSEMBLER_NAME (fndecl));
-#endif
- TREE_VALUE (old_entry_in_list) = new_entry;
+ /* Update the entry. */
+ TREE_PURPOSE (old_entry_in_list) = new_offset;
+ TREE_VALUE (old_entry_in_list) = fndecl;
- /* Now assign virtual dispatch information, if unset. */
- /* We can dispatch this, through any overridden base function. */
+ /* Now assign virtual dispatch information, if unset. We can
+ dispatch this, through any overridden base function. */
if (TREE_CODE (DECL_VINDEX (fndecl)) != INTEGER_CST)
{
DECL_VINDEX (fndecl) = DECL_VINDEX (base_fndecl);
@@ -1012,11 +1031,6 @@ add_virtual_function (pv, phv, has_virtual, fndecl, t)
tree pending_virtuals = *pv;
tree pending_hard_virtuals = *phv;
- /* FUNCTION_TYPEs and OFFSET_TYPEs no longer freely
- convert to void *. Make such a conversion here. */
- tree vfn = build1 (ADDR_EXPR, vfunc_ptr_type_node, fndecl);
- TREE_CONSTANT (vfn) = 1;
-
#ifndef DUMB_USER
if (current_class_type == 0)
cp_warning ("internal problem, current_class_type is zero when adding `%D', please report",
@@ -1032,8 +1046,6 @@ add_virtual_function (pv, phv, has_virtual, fndecl, t)
to hold that entry. */
if (DECL_VINDEX (fndecl) == error_mark_node)
{
- tree entry;
-
/* We remember that this was the base sub-object for rtti. */
CLASSTYPE_RTTI (t) = t;
@@ -1068,8 +1080,10 @@ add_virtual_function (pv, phv, has_virtual, fndecl, t)
DECL_VINDEX (fndecl) = idx;
DECL_CONTEXT (fndecl) = t;
}
- entry = build_vtable_entry (integer_zero_node, vfn);
- pending_virtuals = tree_cons (DECL_VINDEX (fndecl), entry, pending_virtuals);
+ /* Save the state we've computed on the PENDING_VIRTUALS list. */
+ pending_virtuals = tree_cons (integer_zero_node,
+ fndecl,
+ pending_virtuals);
}
/* Might already be INTEGER_CST if declared twice in class. We will
give error later or we've already given it. */
@@ -1077,7 +1091,9 @@ add_virtual_function (pv, phv, has_virtual, fndecl, t)
{
/* Need an entry in some other virtual function table.
Deal with this after we have laid out our virtual base classes. */
- pending_hard_virtuals = temp_tree_cons (fndecl, vfn, pending_hard_virtuals);
+ pending_hard_virtuals = temp_tree_cons (NULL_TREE,
+ fndecl,
+ pending_hard_virtuals);
}
*pv = pending_virtuals;
*phv = pending_hard_virtuals;
@@ -2207,6 +2223,78 @@ duplicate_tag_error (t)
TYPE_NONCOPIED_PARTS (t) = NULL_TREE;
}
+/* Construct the initializer for BINFOs virtual function table. */
+
+static tree
+build_vtbl_initializer (binfo)
+ tree binfo;
+{
+ tree v = BINFO_VIRTUALS (binfo);
+ tree inits = NULL_TREE;
+
+ /* Process the RTTI stuff at the head of the list. If we're not
+ using vtable thunks, then the RTTI entry is just an ordinary
+ function, and we can process it just like the other virtual
+ function entries. */
+ if (!CLASSTYPE_COM_INTERFACE (BINFO_TYPE (binfo))
+ && flag_vtable_thunks)
+ {
+ tree offset;
+ tree init;
+
+ /* The first entry is an offset. */
+ offset = TREE_PURPOSE (v);
+ my_friendly_assert (TREE_CODE (offset) == INTEGER_CST,
+ 19990727);
+
+ /* Convert the offset to look like a function pointer, so that
+ we can put it in the vtable. */
+ init = build1 (NOP_EXPR, vfunc_ptr_type_node, offset);
+ TREE_CONSTANT (init) = 1;
+ init = build_vtable_entry (integer_zero_node, init);
+ inits = tree_cons (NULL_TREE, init, inits);
+
+ /* Even in this case, the second entry (the tdesc pointer) is
+ just an ordinary function. */
+ v = TREE_CHAIN (v);
+ }
+
+ /* Go through all the ordinary virtual functions, building up
+ initializers. */
+ while (v)
+ {
+ tree delta;
+ tree fn;
+ tree init;
+
+ /* Pull the offset for `this', and the function to call, out of
+ the list. */
+ delta = TREE_PURPOSE (v);
+ fn = TREE_VALUE (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_ABSTRACT_VIRTUAL_P (fn))
+ fn = abort_fndecl;
+
+ /* Package up that information for the vtable. */
+ init = build_vtable_entry_for_fn (delta, fn);
+ /* And add it to the chain of initializers. */
+ inits = tree_cons (NULL_TREE, init, inits);
+
+ /* Keep going. */
+ v = TREE_CHAIN (v);
+ }
+
+ /* The initializers were built up in reverse order; straighten them
+ out now. */
+ inits = nreverse (inits);
+ /* Package all the initializers up as an array initializer. */
+ return build_nt (CONSTRUCTOR, NULL_TREE, inits);
+}
+
/* finish up all new vtables. */
static void
@@ -2228,14 +2316,7 @@ finish_vtbls (binfo, do_self, t)
decl = BINFO_VTABLE (binfo);
context = DECL_CONTEXT (decl);
DECL_CONTEXT (decl) = 0;
-
- /* We make a copy here in case we need to replace pure
- virtual functions with __pure_virtual. We don't want to
- mess up BINFO_VIRTUALS when we do this. */
- DECL_INITIAL (decl) = copy_list (BINFO_VIRTUALS (binfo));
- DECL_INITIAL (decl) = build_nt (CONSTRUCTOR, NULL_TREE,
- DECL_INITIAL (decl));
-
+ DECL_INITIAL (decl) = build_vtbl_initializer (binfo);
cp_finish_decl (decl, DECL_INITIAL (decl), NULL_TREE, 0, 0);
DECL_CONTEXT (decl) = context;
}
@@ -2248,9 +2329,8 @@ finish_vtbls (binfo, do_self, t)
int is_not_base_vtable
= i != CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (binfo));
if (TREE_VIA_VIRTUAL (base_binfo))
- {
- base_binfo = binfo_member (BINFO_TYPE (base_binfo), CLASSTYPE_VBASECLASSES (t));
- }
+ base_binfo = binfo_member (BINFO_TYPE (base_binfo),
+ CLASSTYPE_VBASECLASSES (t));
finish_vtbls (base_binfo, is_not_base_vtable, t);
}
}
@@ -2396,8 +2476,8 @@ skip_rtti_stuff (virtuals, t)
}
static void
-modify_one_vtable (binfo, t, fndecl, pfn)
- tree binfo, t, fndecl, pfn;
+modify_one_vtable (binfo, t, fndecl)
+ tree binfo, t, fndecl;
{
tree virtuals = BINFO_VIRTUALS (binfo);
unsigned HOST_WIDE_INT n;
@@ -2424,8 +2504,14 @@ modify_one_vtable (binfo, t, fndecl, pfn)
while (virtuals)
{
tree current_fndecl = TREE_VALUE (virtuals);
- current_fndecl = FNADDR_FROM_VTABLE_ENTRY (current_fndecl);
- current_fndecl = TREE_OPERAND (current_fndecl, 0);
+
+ /* We should never have an instance of __pure_virtual on the
+ BINFO_VIRTUALS list. If we do, then we will never notice
+ that the function that should have been there instead has
+ been overridden. */
+ my_friendly_assert (current_fndecl != abort_fndecl,
+ 19990727);
+
if (current_fndecl && overrides (fndecl, current_fndecl))
{
tree base_offset, offset;
@@ -2469,7 +2555,7 @@ modify_one_vtable (binfo, t, fndecl, pfn)
cp_warning ("in %D", DECL_NAME (BINFO_VTABLE (binfo)));
#endif
modify_vtable_entry (get_vtable_entry_n (BINFO_VIRTUALS (binfo), n),
- build_vtable_entry (this_offset, pfn),
+ this_offset,
fndecl);
}
++n;
@@ -2480,19 +2566,17 @@ modify_one_vtable (binfo, t, fndecl, pfn)
/* These are the ones that are not through virtual base classes. */
static void
-modify_all_direct_vtables (binfo, do_self, t, fndecl, pfn)
+modify_all_direct_vtables (binfo, do_self, t, fndecl)
tree binfo;
int do_self;
- tree t, fndecl, pfn;
+ tree t, fndecl;
{
tree binfos = BINFO_BASETYPES (binfo);
int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
/* Should we use something besides CLASSTYPE_VFIELDS? */
if (do_self && CLASSTYPE_VFIELDS (BINFO_TYPE (binfo)))
- {
- modify_one_vtable (binfo, t, fndecl, pfn);
- }
+ modify_one_vtable (binfo, t, fndecl);
for (i = 0; i < n_baselinks; i++)
{
@@ -2500,7 +2584,7 @@ modify_all_direct_vtables (binfo, do_self, t, fndecl, pfn)
int is_not_base_vtable
= i != CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (binfo));
if (! TREE_VIA_VIRTUAL (base_binfo))
- modify_all_direct_vtables (base_binfo, is_not_base_vtable, t, fndecl, pfn);
+ modify_all_direct_vtables (base_binfo, is_not_base_vtable, t, fndecl);
}
}
@@ -2518,9 +2602,8 @@ fixup_vtable_deltas1 (binfo, t)
while (virtuals)
{
tree fndecl = TREE_VALUE (virtuals);
- tree pfn = FNADDR_FROM_VTABLE_ENTRY (fndecl);
- tree delta = DELTA_FROM_VTABLE_ENTRY (fndecl);
- fndecl = TREE_OPERAND (pfn, 0);
+ tree delta = TREE_PURPOSE (virtuals);
+
if (fndecl)
{
tree base_offset, offset;
@@ -2565,7 +2648,7 @@ fixup_vtable_deltas1 (binfo, t)
}
modify_vtable_entry (get_vtable_entry_n (BINFO_VIRTUALS (binfo), n),
- build_vtable_entry (this_offset, pfn),
+ this_offset,
fndecl);
}
}
@@ -2598,27 +2681,23 @@ fixup_vtable_deltas (binfo, init_self, t)
}
/* Should we use something besides CLASSTYPE_VFIELDS? */
if (init_self && CLASSTYPE_VFIELDS (BINFO_TYPE (binfo)))
- {
- fixup_vtable_deltas1 (binfo, t);
- }
+ fixup_vtable_deltas1 (binfo, t);
}
/* These are the ones that are through virtual base classes. */
static void
-modify_all_indirect_vtables (binfo, do_self, via_virtual, t, fndecl, pfn)
+modify_all_indirect_vtables (binfo, do_self, via_virtual, t, fndecl)
tree binfo;
int do_self, via_virtual;
- tree t, fndecl, pfn;
+ tree t, fndecl;
{
tree binfos = BINFO_BASETYPES (binfo);
int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
/* Should we use something besides CLASSTYPE_VFIELDS? */
if (do_self && via_virtual && CLASSTYPE_VFIELDS (BINFO_TYPE (binfo)))
- {
- modify_one_vtable (binfo, t, fndecl, pfn);
- }
+ modify_one_vtable (binfo, t, fndecl);
for (i = 0; i < n_baselinks; i++)
{
@@ -2630,19 +2709,20 @@ modify_all_indirect_vtables (binfo, do_self, via_virtual, t, fndecl, pfn)
via_virtual = 1;
base_binfo = binfo_member (BINFO_TYPE (base_binfo), CLASSTYPE_VBASECLASSES (t));
}
- modify_all_indirect_vtables (base_binfo, is_not_base_vtable, via_virtual, t, fndecl, pfn);
+ modify_all_indirect_vtables (base_binfo, is_not_base_vtable, via_virtual, t, fndecl);
}
}
static void
-modify_all_vtables (t, fndecl, vfn)
- tree t, fndecl, vfn;
+modify_all_vtables (t, fndecl)
+ tree t;
+ tree fndecl;
{
/* Do these first, so that we will make use of any non-virtual class's
vtable, over a virtual classes vtable. */
- modify_all_direct_vtables (TYPE_BINFO (t), 1, t, fndecl, vfn);
+ modify_all_direct_vtables (TYPE_BINFO (t), 1, t, fndecl);
if (TYPE_USES_VIRTUAL_BASECLASSES (t))
- modify_all_indirect_vtables (TYPE_BINFO (t), 1, 0, t, fndecl, vfn);
+ modify_all_indirect_vtables (TYPE_BINFO (t), 1, 0, t, fndecl);
}
/* Here, we already know that they match in every respect.
@@ -2693,10 +2773,7 @@ override_one_vtable (binfo, old, t)
{
tree fndecl = TREE_VALUE (virtuals);
tree old_fndecl = TREE_VALUE (old_virtuals);
- fndecl = FNADDR_FROM_VTABLE_ENTRY (fndecl);
- old_fndecl = FNADDR_FROM_VTABLE_ENTRY (old_fndecl);
- fndecl = TREE_OPERAND (fndecl, 0);
- old_fndecl = TREE_OPERAND (old_fndecl, 0);
+
/* First check to see if they are the same. */
if (DECL_ASSEMBLER_NAME (fndecl) == DECL_ASSEMBLER_NAME (old_fndecl))
{
@@ -2748,8 +2825,7 @@ override_one_vtable (binfo, old, t)
}
{
/* This MUST be overridden, or the class is ill-formed. */
- tree fndecl = TREE_OPERAND (FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (virtuals)), 0);
- tree vfn;
+ tree fndecl = TREE_VALUE (virtuals);
fndecl = copy_node (fndecl);
copy_lang_decl (fndecl);
@@ -2758,12 +2834,10 @@ override_one_vtable (binfo, old, t)
if (! CLASSTYPE_ABSTRACT_VIRTUALS (t))
CLASSTYPE_ABSTRACT_VIRTUALS (t) = error_mark_node;
- vfn = build1 (ADDR_EXPR, vfunc_ptr_type_node, fndecl);
- TREE_CONSTANT (vfn) = 1;
-
/* We can use integer_zero_node, as we will core dump
if this is used anyway. */
- TREE_VALUE (virtuals) = build_vtable_entry (integer_zero_node, vfn);
+ TREE_VALUE (virtuals) = build_vtable_entry (integer_zero_node,
+ fndecl);
}
}
virtuals = TREE_CHAIN (virtuals);
@@ -3960,12 +4034,11 @@ finish_struct_1 (t)
TYPE_VIRTUAL_P (t) = 1;
if (flag_rtti && TYPE_VIRTUAL_P (t) && !pending_hard_virtuals)
- modify_all_vtables (t, NULL_TREE, NULL_TREE);
+ modify_all_vtables (t, NULL_TREE);
while (pending_hard_virtuals)
{
modify_all_vtables (t,
- TREE_PURPOSE (pending_hard_virtuals),
TREE_VALUE (pending_hard_virtuals));
pending_hard_virtuals = TREE_CHAIN (pending_hard_virtuals);
}
@@ -4146,26 +4219,6 @@ finish_struct_1 (t)
if (CLASSTYPE_VSIZE (t) != 0)
{
-#if 0
- /* This is now done above. */
- if (DECL_FIELD_CONTEXT (vfield) != t)
- {
- tree binfo = get_binfo (DECL_FIELD_CONTEXT (vfield), t, 0);
- tree offset = BINFO_OFFSET (binfo);
-
- vfield = copy_node (vfield);
- copy_lang_decl (vfield);
-
- if (! integer_zerop (offset))
- offset = size_binop (MULT_EXPR, offset, size_int (BITS_PER_UNIT));
- DECL_FIELD_CONTEXT (vfield) = t;
- DECL_CLASS_CONTEXT (vfield) = t;
- DECL_FIELD_BITPOS (vfield)
- = size_binop (PLUS_EXPR, offset, DECL_FIELD_BITPOS (vfield));
- CLASSTYPE_VFIELD (t) = vfield;
- }
-#endif
-
/* In addition to this one, all the other vfields should be listed. */
/* Before that can be done, we have to have FIELD_DECLs for them, and
a place to find them. */
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 3852721..4a47e9b 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -98,7 +98,14 @@ Boston, MA 02111-1307, USA. */
DECL_SAVED_INSNS/DECL_FIELD_SIZE
For a static VAR_DECL, this is DECL_INIT_PRIORITY.
-*/
+
+ BINFO_VIRTUALS
+ For a binfo, this is a TREE_LIST. The TREE_PURPOSE of each node
+ gives the amount by which to adjust the `this' pointer when
+ calling the function. The TREE_VALUE is the declaration for the
+ virtual function itself. When CLASSTYPE_COM_INTERFACE_P does not
+ hold, the first entry does not have a TREE_VALUE; it is just an
+ offset. */
/* Language-dependent contents of an identifier. */
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index 0e8962f..d5125fc 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -2414,11 +2414,6 @@ mark_vtable_entries (decl)
fn = TREE_OPERAND (fnaddr, 0);
TREE_ADDRESSABLE (fn) = 1;
- if (DECL_LANG_SPECIFIC (fn) && DECL_ABSTRACT_VIRTUAL_P (fn))
- {
- TREE_OPERAND (fnaddr, 0) = abort_fndecl;
- mark_used (abort_fndecl);
- }
if (TREE_CODE (fn) == THUNK_DECL && DECL_EXTERNAL (fn))
{
DECL_EXTERNAL (fn) = 0;
diff --git a/gcc/cp/error.c b/gcc/cp/error.c
index 60d73de..22be201 100644
--- a/gcc/cp/error.c
+++ b/gcc/cp/error.c
@@ -1670,7 +1670,7 @@ dump_expr (t, nop)
t = TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (TREE_TYPE (t)));
t = TYPE_METHOD_BASETYPE (t);
- virtuals = BINFO_VIRTUALS (TYPE_BINFO (TYPE_MAIN_VARIANT (t)));
+ virtuals = TYPE_BINFO_VIRTUALS (TYPE_MAIN_VARIANT (t));
n = TREE_INT_CST_LOW (idx);
@@ -1685,7 +1685,7 @@ dump_expr (t, nop)
}
if (virtuals)
{
- dump_expr (FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (virtuals)), 0);
+ dump_expr (TREE_VALUE (virtuals), 0);
break;
}
}
diff --git a/gcc/cp/search.c b/gcc/cp/search.c
index b7f3e18..3af71f1 100644
--- a/gcc/cp/search.c
+++ b/gcc/cp/search.c
@@ -2032,10 +2032,10 @@ get_abstract_virtuals_1 (binfo, do_self, abstract_virtuals)
while (virtuals)
{
- tree base_pfn = FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (virtuals));
- tree base_fndecl = TREE_OPERAND (base_pfn, 0);
+ tree base_fndecl = TREE_VALUE (virtuals);
if (DECL_ABSTRACT_VIRTUAL_P (base_fndecl))
- abstract_virtuals = tree_cons (NULL_TREE, base_fndecl, abstract_virtuals);
+ abstract_virtuals = tree_cons (NULL_TREE, base_fndecl,
+ abstract_virtuals);
virtuals = TREE_CHAIN (virtuals);
}
}
@@ -2065,12 +2065,12 @@ get_abstract_virtuals (type)
while (virtuals)
{
- tree base_pfn = FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (virtuals));
- tree base_fndecl = TREE_OPERAND (base_pfn, 0);
+ tree base_fndecl = TREE_VALUE (virtuals);
if (DECL_NEEDS_FINAL_OVERRIDER_P (base_fndecl))
cp_error ("`%#D' needs a final overrider", base_fndecl);
else if (DECL_ABSTRACT_VIRTUAL_P (base_fndecl))
- abstract_virtuals = tree_cons (NULL_TREE, base_fndecl, abstract_virtuals);
+ abstract_virtuals = tree_cons (NULL_TREE, base_fndecl,
+ abstract_virtuals);
virtuals = TREE_CHAIN (virtuals);
}
}
@@ -2541,8 +2541,7 @@ expand_upcast_fixups (binfo, addr, orig_addr, vbase, vbase_addr, t,
while (virtuals)
{
tree current_fndecl = TREE_VALUE (virtuals);
- current_fndecl = FNADDR_FROM_VTABLE_ENTRY (current_fndecl);
- current_fndecl = TREE_OPERAND (current_fndecl, 0);
+
if (current_fndecl
&& current_fndecl != abort_fndecl
&& (vc=virtual_context (current_fndecl, t, vbase)) != vbase)
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index a84a9ba..9076cc7 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -1245,7 +1245,7 @@ debug_binfo (elem)
while (virtuals)
{
- tree fndecl = TREE_OPERAND (FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (virtuals)), 0);
+ tree fndecl = TREE_VALUE (virtuals);
fprintf (stderr, "%s [%ld =? %ld]\n",
IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (fndecl)),
(long) n, (long) TREE_INT_CST_LOW (DECL_VINDEX (fndecl)));
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/virtual4.C b/gcc/testsuite/g++.old-deja/g++.pt/virtual4.C
new file mode 100644
index 0000000..64dc51a
--- /dev/null
+++ b/gcc/testsuite/g++.old-deja/g++.pt/virtual4.C
@@ -0,0 +1,40 @@
+// Origin: Mark Mitchell <mark@codesourcery.com>
+
+struct B
+{
+ B ();
+ virtual void f () = 0;
+};
+
+B::B ()
+{
+}
+
+extern B* bp;
+
+template <class T>
+struct C : public B
+{
+ virtual void f ()
+ {
+ }
+};
+
+template <class T>
+struct D : public B
+{
+ virtual void f ()
+ {
+ bp = new C<T*>;
+ }
+};
+
+B* bp = new D<int>;
+
+int main ()
+{
+ bp->f ();
+ bp->f ();
+}
+
+