aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2001-06-06 17:52:52 -0400
committerJason Merrill <jason@gcc.gnu.org>2001-06-06 17:52:52 -0400
commitd0cd8b44016194824049ec6ee453d6864b73bc01 (patch)
tree54340a199d71a0aa015fcdf4fe886dffdcb11394 /gcc
parentacf97e0b7570b17a80d9b85d52a7cae9314a8f16 (diff)
downloadgcc-d0cd8b44016194824049ec6ee453d6864b73bc01.zip
gcc-d0cd8b44016194824049ec6ee453d6864b73bc01.tar.gz
gcc-d0cd8b44016194824049ec6ee453d6864b73bc01.tar.bz2
cp-tree.h (THUNK_GENERATE_WITH_VTABLE_P): Lose.
* cp-tree.h (THUNK_GENERATE_WITH_VTABLE_P): Lose. (struct lang_decl_flags): Lose generate_with_vtable_p. (BV_GENERATE_THUNK_WITH_VTABLE_P): Lose. * class.c (copy_virtuals): Adjust. * decl2.c (mark_vtable_entries): Adjust. * method.c (make_thunk, build_vtable_entry): Adjust. * class.c (update_vtable_entry_for_fn): Only look as far as the first defining class. (build_vtbl_initializer): Put nothing in the slot for a function only defined in a lost primary virtual base. (add_vcall_offset_vtbl_entries_1): Use the same code for the lost primary case and the normal case. (dfs_unshared_virtual_bases): Don't lose a non-virtual primary base. (get_vfield_offset, get_derived_offset): Lose. (dfs_find_final_overrider): Use look_for_overrides_here. (get_matching_virtual): New fn. * semantics.c (emit_associated_thunks): Check BV_USE_VCALL_INDEX_P, not BV_VCALL_INDEX. * search.c (look_for_overrides_here): Split out from... (look_for_overrides_r): Here. * class.c (find_final_overrider): Return error_mark_node on error. From-SVN: r42949
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog27
-rw-r--r--gcc/cp/class.c364
-rw-r--r--gcc/cp/cp-tree.h25
-rw-r--r--gcc/cp/decl2.c9
-rw-r--r--gcc/cp/method.c5
-rw-r--r--gcc/cp/search.c72
-rw-r--r--gcc/cp/semantics.c5
-rw-r--r--gcc/testsuite/g++.dg/mangle1.C1
8 files changed, 261 insertions, 247 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 4e458c5..8ba7f9f 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,30 @@
+2001-06-06 Jason Merrill <jason_merrill@redhat.com>
+
+ * cp-tree.h (THUNK_GENERATE_WITH_VTABLE_P): Lose.
+ (struct lang_decl_flags): Lose generate_with_vtable_p.
+ (BV_GENERATE_THUNK_WITH_VTABLE_P): Lose.
+ * class.c (copy_virtuals): Adjust.
+ * decl2.c (mark_vtable_entries): Adjust.
+ * method.c (make_thunk, build_vtable_entry): Adjust.
+ * class.c (update_vtable_entry_for_fn): Only look as far as the
+ first defining class.
+ (build_vtbl_initializer): Put nothing in the slot for a function only
+ defined in a lost primary virtual base.
+ (add_vcall_offset_vtbl_entries_1): Use the same code for
+ the lost primary case and the normal case.
+ (dfs_unshared_virtual_bases): Don't lose a non-virtual primary base.
+ (get_vfield_offset, get_derived_offset): Lose.
+ (dfs_find_final_overrider): Use look_for_overrides_here.
+ (get_matching_virtual): New fn.
+ * semantics.c (emit_associated_thunks): Check BV_USE_VCALL_INDEX_P,
+ not BV_VCALL_INDEX.
+ * search.c (look_for_overrides_here): Split out from...
+ (look_for_overrides_r): Here.
+
+ * class.c (find_final_overrider): Return error_mark_node on error.
+
+ * decl2.c (key_method): #if 0 accidental change.
+
2001-06-06 John David Anglin <dave@hiauly1.hia.nrc.ca>
* call.c (convert_default_arg): Use INTEGRAL_TYPE_P.
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index afe2da4..cdd92b5 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -74,7 +74,7 @@ typedef struct vtbl_init_data_s
/* The negative-index vtable initializers built up so far. These
are in order from least negative index to most negative index. */
tree inits;
- /* The last (i.e., most negative entry in INITS. */
+ /* The last (i.e., most negative) entry in INITS. */
tree* last_init;
/* The binfo for the virtual base for which we're building
vcall offset initializers. */
@@ -107,9 +107,8 @@ varray_type local_classes;
static tree get_vfield_name PARAMS ((tree));
static void finish_struct_anon PARAMS ((tree));
static tree build_vbase_pointer PARAMS ((tree, tree));
-static tree build_vtable_entry PARAMS ((tree, tree, tree, int));
+static tree build_vtable_entry PARAMS ((tree, tree, tree));
static tree get_vtable_name PARAMS ((tree));
-static tree get_derived_offset PARAMS ((tree, tree));
static tree get_basefndecls PARAMS ((tree, tree));
static int build_primary_vtable PARAMS ((tree, tree));
static int build_secondary_vtable PARAMS ((tree, tree));
@@ -684,37 +683,6 @@ get_vtt_name (type)
return mangle_vtt_for_type (type);
}
-/* Return the offset to the main vtable for a given base BINFO. */
-
-tree
-get_vfield_offset (binfo)
- tree binfo;
-{
- return
- size_binop (PLUS_EXPR, byte_position (TYPE_VFIELD (BINFO_TYPE (binfo))),
- BINFO_OFFSET (binfo));
-}
-
-/* Get the offset to the start of the original binfo that we derived
- this binfo from. If we find TYPE first, return the offset only
- that far. The shortened search is useful because the this pointer
- on method calling is expected to point to a DECL_CONTEXT (fndecl)
- object, and not a baseclass of it. */
-
-static tree
-get_derived_offset (binfo, type)
- tree binfo, type;
-{
- tree offset1 = get_vfield_offset (TYPE_BINFO (BINFO_TYPE (binfo)));
- tree offset2;
-
- while (!same_type_p (BINFO_TYPE (binfo), type))
- binfo = get_primary_binfo (binfo);
-
- offset2 = get_vfield_offset (TYPE_BINFO (BINFO_TYPE (binfo)));
- return size_binop (MINUS_EXPR, offset1, offset2);
-}
-
/* Create a VAR_DECL for a primary or secondary vtable for CLASS_TYPE.
(For a secondary vtable for B-in-D, CLASS_TYPE should be D, not B.)
Use NAME for the name of the vtable, and VTABLE_TYPE for its type. */
@@ -796,7 +764,6 @@ copy_virtuals (binfo)
{
BV_VCALL_INDEX (t) = NULL_TREE;
BV_USE_VCALL_INDEX_P (t) = 0;
- BV_GENERATE_THUNK_WITH_VTABLE_P (t) = 0;
}
return copies;
@@ -1024,9 +991,11 @@ make_new_vtable (t, binfo)
{
if (binfo == TYPE_BINFO (t))
/* In this case, it is *type*'s vtable we are modifying. We start
- with the approximation that it's vtable is that of the
+ with the approximation that its vtable is that of the
immediate base class. */
- return build_primary_vtable (TYPE_BINFO (DECL_CONTEXT (TYPE_VFIELD (t))),
+ /* ??? This actually passes TYPE_BINFO (t), not the primary base binfo,
+ since we've updated DECL_CONTEXT (TYPE_VFIELD (t)) by now. */
+ return build_primary_vtable (TYPE_BINFO (DECL_CONTEXT (TYPE_VFIELD (t))),
t);
else
/* This is our very own copy of `basetype' to play with. Later,
@@ -1077,7 +1046,12 @@ modify_vtable_entry (t, binfo, fndecl, delta, virtuals)
BV_FN (v) = fndecl;
/* Now assign virtual dispatch information, if unset. We can
- dispatch this, through any overridden base function. */
+ dispatch this through any overridden base function.
+
+ FIXME this can choose a secondary vtable if the primary is not
+ also lexically first, leading to useless conversions.
+ In the V3 ABI, there's no reason for DECL_VIRTUAL_CONTEXT to
+ ever be different from DECL_CONTEXT. */
if (TREE_CODE (DECL_VINDEX (fndecl)) != INTEGER_CST)
{
DECL_VINDEX (fndecl) = DECL_VINDEX (base_fndecl);
@@ -1808,7 +1782,7 @@ mark_primary_virtual_base (binfo, base_binfo, type)
return base_binfo;
}
-/* If BINFO is an unmarked virtual binfo for a class with a primary
+/* If BINFO is an unmarked virtual binfo for a class with a primary virtual
base, then BINFO has no primary base in this graph. Called from
mark_primary_bases. */
@@ -1817,7 +1791,8 @@ static tree dfs_unshared_virtual_bases (binfo, data)
void *data ATTRIBUTE_UNUSED;
{
if (TREE_VIA_VIRTUAL (binfo) && !BINFO_MARKED (binfo)
- && CLASSTYPE_HAS_PRIMARY_BASE_P (BINFO_TYPE (binfo)))
+ && CLASSTYPE_HAS_PRIMARY_BASE_P (BINFO_TYPE (binfo))
+ && TREE_VIA_VIRTUAL (CLASSTYPE_PRIMARY_BINFO (BINFO_TYPE (binfo))))
BINFO_LOST_PRIMARY_P (binfo) = 1;
CLEAR_BINFO_MARKED (binfo);
@@ -2542,13 +2517,8 @@ dfs_find_final_overrider (binfo, data)
path;
path = TREE_CHAIN (path))
{
- for (method = TYPE_METHODS (BINFO_TYPE (TREE_VALUE (path)));
- method;
- method = TREE_CHAIN (method))
- if (DECL_VIRTUAL_P (method)
- && same_signature_p (method, ffod->fn))
- break;
-
+ method = look_for_overrides_here (BINFO_TYPE (TREE_VALUE (path)),
+ ffod->fn);
if (method)
break;
}
@@ -2676,7 +2646,7 @@ find_final_overrider (t, binfo, fn)
struct T : virtual public R { virtual void f (); };
struct U : public S, public T { };
- is not -- there's no way to decide whether to put `S::f' or
+ is not -- there's no way to decide whether to put `S::f' or
`T::f' in the vtable for `R'.
The solution is to look at all paths to BINFO. If we find
@@ -2695,14 +2665,36 @@ find_final_overrider (t, binfo, fn)
/* If there was no winner, issue an error message. */
if (!ffod.overriding_fn)
- cp_error ("no unique final overrider for `%D' in `%T'", fn, t);
+ {
+ cp_error ("no unique final overrider for `%D' in `%T'", fn, t);
+ return error_mark_node;
+ }
return build_tree_list (ffod.overriding_fn, ffod.overriding_base);
}
-/* Update a entry in the vtable for BINFO, which is in the hierarchy
- dominated by T. FN has been overridden in BINFO; VIRTUALS points
- to the corresponding position in the BINFO_VIRTUALS list. */
+#if 0
+/* Returns the function from the BINFO_VIRTUALS entry in T which matches
+ the signature of FUNCTION_DECL FN, or NULL_TREE if none. In other words,
+ the function that the slot in T's primary vtable points to. */
+
+static tree get_matching_virtual PARAMS ((tree, tree));
+static tree
+get_matching_virtual (t, fn)
+ tree t, fn;
+{
+ tree f;
+
+ for (f = BINFO_VIRTUALS (TYPE_BINFO (t)); f; f = TREE_CHAIN (f))
+ if (same_signature_p (BV_FN (f), fn))
+ return BV_FN (f);
+ return NULL_TREE;
+}
+#endif
+
+/* Update an entry in the vtable for BINFO, which is in the hierarchy
+ dominated by T. FN has been overriden in BINFO; VIRTUALS points to the
+ corresponding position in the BINFO_VIRTUALS list. */
static void
update_vtable_entry_for_fn (t, binfo, fn, virtuals)
@@ -2715,93 +2707,92 @@ update_vtable_entry_for_fn (t, binfo, fn, virtuals)
tree overrider;
tree delta;
tree virtual_base;
- int generate_thunk_with_vtable_p;
+ tree first_defn;
- /* Find the function which originally caused this vtable
- entry to be present. */
- b = binfo;
- while (1)
+ /* 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))
{
- tree primary_base;
- tree f;
-
- primary_base = get_primary_binfo (b);
- if (!primary_base)
+ if (look_for_overrides_here (BINFO_TYPE (b), fn))
break;
-
- for (f = BINFO_VIRTUALS (TYPE_BINFO (BINFO_TYPE (primary_base)));
- f;
- f = TREE_CHAIN (f))
- if (same_signature_p (BV_FN (f), fn))
- break;
-
- if (!f)
- break;
-
- fn = BV_FN (f);
- b = primary_base;
}
+ first_defn = b;
/* Find the final overrider. */
overrider = find_final_overrider (t, b, fn);
if (overrider == error_mark_node)
return;
- /* Compute the constant adjustment to the `this' pointer. The
- `this' pointer, when this function is called, will point at the
- class whose vtable this is. */
- delta = size_binop (PLUS_EXPR,
- get_derived_offset (binfo,
- DECL_VIRTUAL_CONTEXT (fn)),
- BINFO_OFFSET (binfo));
-
/* 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;
- /* Assume that we will always generate thunks with the vtables that
- reference them. */
- generate_thunk_with_vtable_p = 1;
-
/* Under the new ABI, we will convert to an intermediate virtual
base first, and then use the vcall offset located there to finish
the conversion. */
while (b)
{
- /* If we find BINFO, then the final overrider is in a class
- derived from BINFO, so the thunks can be generated with
- the final overrider. */
- if (!virtual_base
- && same_type_p (BINFO_TYPE (b), BINFO_TYPE (binfo)))
- generate_thunk_with_vtable_p = 0;
-
- /* If we find the final overrider, then we can stop
- walking. */
+ /* If we find the final overrider, then we can stop
+ walking. */
if (same_type_p (BINFO_TYPE (b),
BINFO_TYPE (TREE_VALUE (overrider))))
break;
- /* If we find a virtual base, and we haven't yet found the
- overrider, then there is a virtual base between the
- declaring base and the final overrider. */
+ /* If we find a virtual base, and we haven't yet found the
+ overrider, then there is a virtual base between the
+ declaring base (first_defn) and the final overrider. */
if (!virtual_base && TREE_VIA_VIRTUAL (b))
- {
- generate_thunk_with_vtable_p = 1;
- virtual_base = b;
- }
+ virtual_base = b;
b = BINFO_INHERITANCE_CHAIN (b);
}
+ /* Compute the constant adjustment to the `this' pointer. The
+ `this' pointer, when this function is called, will point at BINFO
+ (or one of its primary bases, which are at the same offset). */
+
if (virtual_base)
/* The `this' pointer needs to be adjusted to the nearest virtual
base. */
- delta = size_diffop (BINFO_OFFSET (virtual_base), delta);
+ delta = size_diffop (BINFO_OFFSET (virtual_base),
+ BINFO_OFFSET (binfo));
else
- /* The `this' pointer needs to be adjusted from pointing to
- BINFO to pointing at the base where the final overrider
- appears. */
- delta = size_diffop (BINFO_OFFSET (TREE_VALUE (overrider)), delta);
+ {
+ /* The `this' pointer needs to be adjusted from pointing to
+ BINFO to pointing at the base where the final overrider
+ appears. */
+ delta = size_diffop (BINFO_OFFSET (TREE_VALUE (overrider)),
+ BINFO_OFFSET (binfo));
+
+#if 0
+ /* Disable this optimization pending an ABI change, or until
+ we can force emission of the non-virtual thunk even if we don't
+ use it. */
+ if (! integer_zerop (delta))
+ {
+ /* We'll need a thunk. But if we have a (perhaps formerly)
+ primary virtual base, we have a vcall slot for this function,
+ so we can use it rather than create a non-virtual thunk. */
+
+ b = get_primary_binfo (first_defn);
+ for (; b; b = get_primary_binfo (b))
+ {
+ tree f = get_matching_virtual (BINFO_TYPE (b), fn);
+ if (!f)
+ /* b doesn't have this function; no suitable vbase. */
+ break;
+ if (TREE_VIA_VIRTUAL (b))
+ {
+ /* Found one; we can treat ourselves as a virtual base. */
+ virtual_base = binfo;
+ delta = size_zero_node;
+ break;
+ }
+ }
+ }
+#endif
+ }
modify_vtable_entry (t,
binfo,
@@ -2811,8 +2802,6 @@ update_vtable_entry_for_fn (t, binfo, fn, virtuals)
if (virtual_base)
BV_USE_VCALL_INDEX_P (*virtuals) = 1;
- if (generate_thunk_with_vtable_p)
- BV_GENERATE_THUNK_WITH_VTABLE_P (*virtuals) = 1;
}
/* Called from modify_all_vtables via dfs_walk. */
@@ -2823,9 +2812,9 @@ dfs_modify_vtables (binfo, data)
void *data;
{
if (/* There's no need to modify the vtable for a non-virtual
- primary base; we're not going to use that vtable anyhow
- (virtual primary bases can become non-primary in a
- class derivation of this one.) */
+ primary base; we're not going to use that vtable anyhow.
+ We do still need to do this for virtual primary bases, as they
+ could become non-primary in a construction vtable. */
(!BINFO_PRIMARY_P (binfo) || TREE_VIA_VIRTUAL (binfo))
/* Similarly, a base without a vtable needs no modification. */
&& CLASSTYPE_VFIELDS (BINFO_TYPE (binfo)))
@@ -5310,9 +5299,7 @@ finish_struct_1 (t)
layout_class_type (t, &empty, &vfuns,
&new_virtuals, &overridden_virtuals);
- /* Set up the DECL_FIELD_BITPOS of the vfield if we need to, as we
- might need to know it for setting up the offsets in the vtable
- (or in thunks) below. */
+ /* Make sure that we get our own copy of the vfield FIELD_DECL. */
vfield = TYPE_VFIELD (t);
if (vfield != NULL_TREE
&& DECL_FIELD_CONTEXT (vfield) != t)
@@ -7667,7 +7654,7 @@ build_vtbl_initializer (binfo, orig_binfo, t, rtti_binfo, non_fn_entries_p)
tree rtti_binfo;
int *non_fn_entries_p;
{
- tree v;
+ tree v, b;
tree vfun_inits;
tree vbase;
vtbl_init_data vid;
@@ -7714,7 +7701,6 @@ build_vtbl_initializer (binfo, orig_binfo, t, rtti_binfo, non_fn_entries_p)
tree fn;
tree pfn;
tree init;
- int generate_with_vtable_p = BV_GENERATE_THUNK_WITH_VTABLE_P (v);
/* Pull the offset for `this', and the function to call, out of
the list. */
@@ -7725,15 +7711,6 @@ build_vtbl_initializer (binfo, orig_binfo, t, rtti_binfo, non_fn_entries_p)
vcall_index = BV_VCALL_INDEX (v);
my_friendly_assert (vcall_index != NULL_TREE, 20000621);
}
- else if (vid.ctor_vtbl_p && BV_VCALL_INDEX (v))
- {
- /* In the original, we did not need to use the vcall index, even
- though there was one, but in a ctor vtable things might be
- different (a primary virtual base might have moved). Be
- conservative and use a vcall adjusting thunk. */
- vcall_index = BV_VCALL_INDEX (v);
- generate_with_vtable_p = 1;
- }
else
vcall_index = NULL_TREE;
@@ -7751,9 +7728,35 @@ build_vtbl_initializer (binfo, orig_binfo, t, rtti_binfo, non_fn_entries_p)
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,
- generate_with_vtable_p);
+ init = build_vtable_entry (delta, vcall_index, pfn);
+
+ /* If the only definition of this function signature along our
+ 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
+ requiring extra thunks which cannot be generated with the function.
+
+ We could also handle this in update_vtable_entry_for_fn; doing it
+ here means we zero out unused slots in ctor vtables as well,
+ rather than filling them with erroneous values (though harmless,
+ apart from relocation costs). */
+ if (fn != abort_fndecl)
+ for (b = binfo; ; b = get_primary_binfo (b))
+ {
+ /* We found a defn before a lost primary; go ahead as normal. */
+ 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;
+ }
+ }
+
/* And add it to the chain of initializers. */
vfun_inits = tree_cons (NULL_TREE, init, vfun_inits);
}
@@ -7769,7 +7772,7 @@ build_vtbl_initializer (binfo, orig_binfo, t, rtti_binfo, non_fn_entries_p)
return chainon (vid.inits, vfun_inits);
}
-/* Sets vid->inits to be the initializers for the vbase and vcall
+/* Adds to vid->inits the initializers for the vbase and vcall
offsets in BINFO, which is in the hierarchy dominated by T. */
static void
@@ -7877,8 +7880,8 @@ build_vbase_offset_vtbl_entries (binfo, vid)
}
/* Adds the initializers for the vcall offset entries in the vtable
- for BINFO (which is part of the class hierarchy dominated by T) to
- VID->INITS. */
+ for BINFO (which is part of the class hierarchy dominated by VID->DERIVED)
+ to VID->INITS. */
static void
build_vcall_offset_vtbl_entries (binfo, vid)
@@ -7898,22 +7901,20 @@ build_vcall_offset_vtbl_entries (binfo, vid)
vtable. For example:
class A { virtual void f (); };
- class B : virtual public A { };
- class C: virtual public A, public B {};
-
- Now imagine:
-
- B* b = new C;
- b->f();
-
- The location of `A' is not at a fixed offset relative to `B'; the
- offset depends on the complete object derived from `B'. So,
- `B' vtable contains an entry for `f' that indicates by what
- amount the `this' pointer for `B' needs to be adjusted to arrive
- at `A'.
+ class B1 : virtual public A { virtual void f (); };
+ class B2 : virtual public A { virtual void f (); };
+ class C: public B1, public B2 { virtual void f (); };
+
+ A C object has a primary base of B1, which has a primary base of A. A
+ C also has a secondary base of B2, which no longer has a primary base
+ of A. So the B2-in-C construction vtable needs a secondary vtable for
+ A, which will adjust the A* to a B2* to call f. We have no way of
+ knowing what (or even whether) this offset will be when we define B2,
+ so we store this "vcall offset" in the A sub-vtable and look it up in
+ a "virtual thunk" for B2::f.
We need entries for all the functions in our primary vtable and
- in our non-virtual bases vtables. */
+ in our non-virtual bases' secondary vtables. */
vid->vbase = binfo;
/* Now, walk through the non-virtual bases, adding vcall offsets. */
add_vcall_offset_vtbl_entries_r (binfo, vid);
@@ -7930,7 +7931,9 @@ add_vcall_offset_vtbl_entries_r (binfo, vid)
tree primary_binfo;
/* Don't walk into virtual bases -- except, of course, for the
- virtual base for which we are building vcall offsets. */
+ virtual base for which we are building vcall offsets. Any
+ primary virtual base will have already had its offsets generated
+ through the recursion in build_vcall_and_vbase_vtbl_entries. */
if (TREE_VIA_VIRTUAL (binfo) && vid->vbase != binfo)
return;
@@ -7964,43 +7967,30 @@ add_vcall_offset_vtbl_entries_1 (binfo, vid)
tree base_virtuals;
tree orig_virtuals;
tree binfo_inits;
- int lost_primary = 0;
- /* If BINFO is a primary base, this is the least derived class of
- BINFO that is not a primary base. */
+ /* If BINFO is a primary base, the most derived class which has BINFO as
+ a primary base; otherwise, just BINFO. */
tree non_primary_binfo;
binfo_inits = NULL_TREE;
- /* We might be a primary base class. Go up the inheritance
- hierarchy until we find the class of which we are a primary base:
+ /* We might be a primary base class. Go up the inheritance hierarchy
+ until we find the most derived class of which we are a primary base:
it is the BINFO_VIRTUALS there that we need to consider. */
non_primary_binfo = binfo;
while (BINFO_INHERITANCE_CHAIN (non_primary_binfo))
{
tree b;
- /* If we have reached a virtual base, then it must be the
- virtual base for which we are building vcall offsets. In
- turn, the virtual base must be a (possibly indirect) primary
- base of the class that we are initializing, or we wouldn't
- care about its vtable offsets. */
+ /* If we have reached a virtual base, then it must be vid->vbase,
+ because we ignore other virtual bases in
+ add_vcall_offset_vtbl_entries_r. In turn, it must be a primary
+ base (possibly multi-level) of vid->binfo, or we wouldn't
+ have called build_vcall_and_vbase_vtbl_entries for it. But it
+ might be a lost primary, so just skip down to vid->binfo. */
if (TREE_VIA_VIRTUAL (non_primary_binfo))
{
- if (vid->ctor_vtbl_p)
- {
- tree probe;
-
- for (probe = vid->binfo;
- probe != non_primary_binfo;
- probe = get_primary_binfo (probe))
- {
- if (BINFO_LOST_PRIMARY_P (probe))
- {
- lost_primary = 1;
- break;
- }
- }
- }
+ if (non_primary_binfo != vid->vbase)
+ abort ();
non_primary_binfo = vid->binfo;
break;
}
@@ -8034,13 +8024,12 @@ add_vcall_offset_vtbl_entries_1 (binfo, vid)
tree vcall_offset;
/* Find the declaration that originally caused this function to
- be present. */
+ be present in BINFO_TYPE (binfo). */
orig_fn = BV_FN (orig_virtuals);
- /* We do not need an entry if this function is declared in a
- virtual base (or one of its virtual bases), and not
- overridden in the section of the hierarchy dominated by the
- virtual base for which we are building vcall offsets. */
+ /* When processing BINFO, we only want to generate vcall slots for
+ function slots introduced in BINFO. So don't try to generate
+ one if the function isn't even defined in BINFO. */
if (!same_type_p (DECL_CONTEXT (orig_fn), BINFO_TYPE (binfo)))
continue;
@@ -8071,16 +8060,19 @@ add_vcall_offset_vtbl_entries_1 (binfo, vid)
if (i != VARRAY_ACTIVE_SIZE (vid->fns))
continue;
- /* The FN comes from BASE. So, we must calculate the adjustment
- from the virtual base that derived from BINFO to BASE. */
+ /* The FN comes from BASE. So, we must calculate the adjustment from
+ vid->vbase to BASE. We can just look for BASE in the complete
+ object because we are converting from a virtual base, so if there
+ were multiple copies, there would not be a unique final overrider
+ and vid->derived would be ill-formed. */
base = DECL_CONTEXT (fn);
base_binfo = get_binfo (base, vid->derived, /*protect=*/0);
/* Compute the vcall offset. */
- vcall_offset = BINFO_OFFSET (vid->vbase);
- if (lost_primary)
- vcall_offset = size_binop (PLUS_EXPR, vcall_offset,
- BINFO_OFFSET (vid->binfo));
+ /* As mentioned above, the vbase we're working on is a primary base of
+ vid->binfo. But it might be a lost primary, so its BINFO_OFFSET
+ might be wrong, so we just use the BINFO_OFFSET from vid->binfo. */
+ vcall_offset = BINFO_OFFSET (vid->binfo);
vcall_offset = size_diffop (BINFO_OFFSET (base_binfo),
vcall_offset);
vcall_offset = fold (build1 (NOP_EXPR, vtable_entry_type,
@@ -8091,7 +8083,7 @@ add_vcall_offset_vtbl_entries_1 (binfo, vid)
/* Keep track of the vtable index where this vcall offset can be
found. For a construction vtable, we already made this
- annotation when we build the original vtable. */
+ annotation when we built the original vtable. */
if (!vid->ctor_vtbl_p)
BV_VCALL_INDEX (derived_virtuals) = vid->index;
@@ -8172,11 +8164,10 @@ build_rtti_vtbl_entries (binfo, vid)
ABI.) */
static tree
-build_vtable_entry (delta, vcall_index, entry, generate_with_vtable_p)
+build_vtable_entry (delta, vcall_index, entry)
tree delta;
tree vcall_index;
tree entry;
- int generate_with_vtable_p;
{
if (flag_vtable_thunks)
{
@@ -8186,8 +8177,7 @@ build_vtable_entry (delta, vcall_index, entry, generate_with_vtable_p)
if ((!integer_zerop (delta) || vcall_index != NULL_TREE)
&& fn != abort_fndecl)
{
- entry = make_thunk (entry, delta, vcall_index,
- generate_with_vtable_p);
+ entry = make_thunk (entry, delta, vcall_index);
entry = build1 (ADDR_EXPR, vtable_entry_type, entry);
TREE_READONLY (entry) = 1;
TREE_CONSTANT (entry) = 1;
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index e820303..b73626a 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -55,7 +55,6 @@ Boston, MA 02111-1307, USA. */
BASELINK_P (in TREE_LIST)
ICS_ELLIPSIS_FLAG (in _CONV)
BINFO_ACCESS (in BINFO)
- BV_GENERATE_THUNK_WITH_VTABLE_P (in TREE_LIST)
2: IDENTIFIER_OPNAME_P.
TYPE_POLYMORHPIC_P (in _TYPE)
ICS_THIS_FLAG (in _CONV)
@@ -133,10 +132,6 @@ Boston, MA 02111-1307, USA. */
The BV_FN is the declaration for the virtual function itself.
- The BV_OVERRIDING_BASE is the binfo for the final overrider for
- this function. (That binfo's BINFO_TYPE will always be the same
- as the DECL_CLASS_CONTEXT for the function.)
-
BINFO_VTABLE
Sometimes this is a VAR_DECL. Under the new ABI, it is instead
an expression with POINTER_TYPE pointing that gives the value
@@ -1736,14 +1731,6 @@ struct lang_type
/* Nonzero if we should use a virtual thunk for this entry. */
#define BV_USE_VCALL_INDEX_P(NODE) \
(TREE_LANG_FLAG_0 (NODE))
-
-/* Nonzero if we should generate this thunk when the vtable that
- references it is emitted, rather than with the final overrider. */
-#define BV_GENERATE_THUNK_WITH_VTABLE_P(NODE) \
- (TREE_LANG_FLAG_1 (NODE))
-
-/* The most derived class. */
-
/* Nonzero for TREE_LIST node means that this list of things
is a list of parameters, as opposed to a list of expressions. */
@@ -1806,8 +1793,7 @@ struct lang_decl_flags
unsigned global_dtor_p : 1;
unsigned assignment_operator_p : 1;
unsigned anticipated_p : 1;
- unsigned generate_with_vtable_p : 1;
- /* Two unused bits. */
+ /* Three unused bits. */
union {
/* In a FUNCTION_DECL, VAR_DECL, TYPE_DECL, or TEMPLATE_DECL, this
@@ -3036,11 +3022,6 @@ enum ptrmemfunc_vbit_where_t
#define THUNK_VCALL_OFFSET(DECL) \
(DECL_LANG_SPECIFIC (DECL)->decl_flags.u2.vcall_offset)
-/* Nonzero if this thunk should be generated with the vtable that
- references it. */
-#define THUNK_GENERATE_WITH_VTABLE_P(DECL) \
- (DECL_LANG_SPECIFIC (DECL)->decl_flags.generate_with_vtable_p)
-
/* These macros provide convenient access to the various _STMT nodes
created when parsing template declarations. */
#define TRY_STMTS(NODE) TREE_OPERAND (TRY_BLOCK_CHECK (NODE), 0)
@@ -3716,7 +3697,6 @@ extern tree get_vtable_decl PARAMS ((tree, int));
extern void add_method PARAMS ((tree, tree, int));
extern int currently_open_class PARAMS ((tree));
extern tree currently_open_derived_class PARAMS ((tree));
-extern tree get_vfield_offset PARAMS ((tree));
extern void duplicate_tag_error PARAMS ((tree));
extern tree finish_struct PARAMS ((tree, tree));
extern void finish_struct_1 PARAMS ((tree));
@@ -4083,7 +4063,7 @@ extern void init_method PARAMS ((void));
extern void set_mangled_name_for_decl PARAMS ((tree));
extern tree build_opfncall PARAMS ((enum tree_code, int, tree, tree, tree));
extern tree hack_identifier PARAMS ((tree, tree));
-extern tree make_thunk PARAMS ((tree, tree, tree, int));
+extern tree make_thunk PARAMS ((tree, tree, tree));
extern void use_thunk PARAMS ((tree, int));
extern void synthesize_method PARAMS ((tree));
extern tree implicitly_declare_fn PARAMS ((special_function_kind, tree, int));
@@ -4202,6 +4182,7 @@ extern tree context_for_name_lookup PARAMS ((tree));
extern tree lookup_conversions PARAMS ((tree));
extern tree binfo_for_vtable PARAMS ((tree));
extern tree binfo_from_vbase PARAMS ((tree));
+extern tree look_for_overrides_here PARAMS ((tree, tree));
extern tree dfs_walk PARAMS ((tree,
tree (*) (tree, void *),
tree (*) (tree, void *),
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index c1aa328..56c4dbc 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -2265,7 +2265,7 @@ mark_vtable_entries (decl)
we know all the thunks we'll need when we emit a virtual
function, so we emit the thunks there instead. */
if (DECL_THUNK_P (fn))
- use_thunk (fn, THUNK_GENERATE_WITH_VTABLE_P (fn));
+ use_thunk (fn, /*emit_p=*/0);
mark_used (fn);
}
}
@@ -2369,7 +2369,12 @@ key_method (type)
method = TREE_CHAIN (method))
if (DECL_VINDEX (method) != NULL_TREE
&& ! DECL_DECLARED_INLINE_P (method)
- && (! DECL_PURE_VIRTUAL_P (method) || DECL_DESTRUCTOR_P (method)))
+ && (! DECL_PURE_VIRTUAL_P (method)
+#if 0
+ /* This would be nice, but we didn't think of it in time. */
+ || DECL_DESTRUCTOR_P (method)
+#endif
+ ))
return method;
return NULL_TREE;
diff --git a/gcc/cp/method.c b/gcc/cp/method.c
index e7d2bbb..4acf6b6 100644
--- a/gcc/cp/method.c
+++ b/gcc/cp/method.c
@@ -295,11 +295,10 @@ request for member `%D' is ambiguous in multiple inheritance lattice",
DELTA is the offset to this and VCALL_INDEX is zero. */
tree
-make_thunk (function, delta, vcall_index, generate_with_vtable_p)
+make_thunk (function, delta, vcall_index)
tree function;
tree delta;
tree vcall_index;
- int generate_with_vtable_p;
{
tree thunk_id;
tree thunk;
@@ -348,7 +347,6 @@ make_thunk (function, delta, vcall_index, generate_with_vtable_p)
DECL_INITIAL (thunk) = function;
THUNK_DELTA (thunk) = d;
THUNK_VCALL_OFFSET (thunk) = vcall_offset;
- THUNK_GENERATE_WITH_VTABLE_P (thunk) = generate_with_vtable_p;
/* The thunk itself is not a constructor or destructor, even if
the thing it is thunking to is. */
DECL_INTERFACE_KNOWN (thunk) = 1;
@@ -381,7 +379,6 @@ void
use_thunk (thunk_fndecl, emit_p)
tree thunk_fndecl;
int emit_p;
-
{
tree fnaddr;
tree function;
diff --git a/gcc/cp/search.c b/gcc/cp/search.c
index fe95c95..81826c1 100644
--- a/gcc/cp/search.c
+++ b/gcc/cp/search.c
@@ -2024,56 +2024,72 @@ look_for_overrides (type, fndecl)
return found;
}
-/* Look in TYPE for virtual functions overridden by FNDECL. Check both
- TYPE itself and its bases. */
+/* Look in TYPE for virtual functions with the same signature as FNDECL.
+ This differs from get_matching_virtual in that it will only return
+ a function from TYPE. */
-static int
-look_for_overrides_r (type, fndecl)
+tree
+look_for_overrides_here (type, fndecl)
tree type, fndecl;
{
int ix;
-
- if (DECL_DESTRUCTOR_P (fndecl))
+
+ if (DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (fndecl))
ix = CLASSTYPE_DESTRUCTOR_SLOT;
else
ix = lookup_fnfields_1 (type, DECL_NAME (fndecl));
if (ix >= 0)
{
tree fns = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (type), ix);
- tree dtypes = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
- tree thistype = DECL_STATIC_FUNCTION_P (fndecl)
- ? NULL_TREE : TREE_TYPE (TREE_VALUE (dtypes));
for (; fns; fns = OVL_NEXT (fns))
{
tree fn = OVL_CURRENT (fns);
- tree btypes = TYPE_ARG_TYPES (TREE_TYPE (fn));
-
+
if (!DECL_VIRTUAL_P (fn))
- /* Not a virtual */;
+ /* Not a virtual. */;
else if (DECL_CONTEXT (fn) != type)
- /* Introduced with a using declaration */;
- else if (thistype == NULL_TREE)
+ /* Introduced with a using declaration. */;
+ else if (DECL_STATIC_FUNCTION_P (fndecl))
{
- if (compparms (TREE_CHAIN (btypes), dtypes))
- {
- /* A static member function cannot match an inherited
- virtual member function. */
- cp_error_at ("`%#D' cannot be declared", fndecl);
- cp_error_at (" since `%#D' declared in base class", fn);
- return 1;
- }
+ tree btypes = TYPE_ARG_TYPES (TREE_TYPE (fn));
+ tree dtypes = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
+ if (compparms (TREE_CHAIN (btypes), dtypes))
+ return fn;
}
else if (same_signature_p (fndecl, fn))
- {
- /* It's definitely virtual, even if not explicitly set. */
- DECL_VIRTUAL_P (fndecl) = 1;
- check_final_overrider (fndecl, fn);
+ return fn;
+ }
+ }
+ return NULL_TREE;
+}
- return 1;
- }
+/* Look in TYPE for virtual functions overridden by FNDECL. Check both
+ TYPE itself and its bases. */
+
+static int
+look_for_overrides_r (type, fndecl)
+ tree type, fndecl;
+{
+ tree fn = look_for_overrides_here (type, fndecl);
+ if (fn)
+ {
+ if (DECL_STATIC_FUNCTION_P (fndecl))
+ {
+ /* A static member function cannot match an inherited
+ virtual member function. */
+ cp_error_at ("`%#D' cannot be declared", fndecl);
+ cp_error_at (" since `%#D' declared in base class", fn);
+ }
+ else
+ {
+ /* It's definitely virtual, even if not explicitly set. */
+ DECL_VIRTUAL_P (fndecl) = 1;
+ check_final_overrider (fndecl, fn);
}
+ return 1;
}
+
/* We failed to find one declared in this class. Look in its bases. */
return look_for_overrides (type, fndecl);
}
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index f1a9e77..9dddf23 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -2300,7 +2300,7 @@ emit_associated_thunks (fn)
for (v = BINFO_VIRTUALS (binfo); v; v = TREE_CHAIN (v))
if (BV_FN (v) == fn
&& (!integer_zerop (BV_DELTA (v))
- || BV_VCALL_INDEX (v)))
+ || BV_USE_VCALL_INDEX_P (v)))
{
tree thunk;
tree vcall_index;
@@ -2317,8 +2317,7 @@ emit_associated_thunks (fn)
vfunc_ptr_type_node,
fn),
BV_DELTA (v),
- vcall_index,
- /*generate_with_vtable_p=*/0);
+ vcall_index);
use_thunk (thunk, /*emit_p=*/1);
}
}
diff --git a/gcc/testsuite/g++.dg/mangle1.C b/gcc/testsuite/g++.dg/mangle1.C
index 499367e..808e56d 100644
--- a/gcc/testsuite/g++.dg/mangle1.C
+++ b/gcc/testsuite/g++.dg/mangle1.C
@@ -26,4 +26,3 @@ C c;
// { dg-final { scan-assembler mangle1.C "\n_ZTT1C:" } }
// { dg-final { scan-assembler mangle1.C "\n_ZTV1A:" } }
// { dg-final { scan-assembler mangle1.C "\n_ZTV1C:" } }
-// { dg-final { scan-assembler mangle1.C "\n_ZTv0_n\(12|24\)_N1A1fEv:" } }