Commit e6a66567 by Mark Mitchell Committed by Mark Mitchell

class.c (add_vcall_offset_vtbl_entries_1): Correct ordering of vcall offfsets.

	* class.c (add_vcall_offset_vtbl_entries_1): Correct ordering of
	vcall offfsets.  Split out ...
	(add_vcall_offset): ... new function.

	* g++.dg/abi/vthunk3.C: New test.

From-SVN: r58912
parent 4f2c9d7e
2002-11-07 Mark Mitchell <mark@codesourcery.com> 2002-11-07 Mark Mitchell <mark@codesourcery.com>
* class.c (add_vcall_offset_vtbl_entries_1): Correct ordering of
vcall offfsets. Split out ...
(add_vcall_offset): ... new function.
PR c++/8338 PR c++/8338
* pt.c (for_each_template_parm): Add htab parameter. * pt.c (for_each_template_parm): Add htab parameter.
(process_partial_specialization): Adjust call. (process_partial_specialization): Adjust call.
......
...@@ -156,6 +156,7 @@ static void build_vbase_offset_vtbl_entries PARAMS ((tree, vtbl_init_data *)); ...@@ -156,6 +156,7 @@ static void build_vbase_offset_vtbl_entries PARAMS ((tree, vtbl_init_data *));
static void add_vcall_offset_vtbl_entries_r PARAMS ((tree, vtbl_init_data *)); static void add_vcall_offset_vtbl_entries_r PARAMS ((tree, vtbl_init_data *));
static void add_vcall_offset_vtbl_entries_1 PARAMS ((tree, vtbl_init_data *)); static void add_vcall_offset_vtbl_entries_1 PARAMS ((tree, vtbl_init_data *));
static void build_vcall_offset_vtbl_entries PARAMS ((tree, vtbl_init_data *)); static void build_vcall_offset_vtbl_entries PARAMS ((tree, vtbl_init_data *));
static void add_vcall_offset (tree, tree, vtbl_init_data *);
static void layout_vtable_decl PARAMS ((tree, int)); static void layout_vtable_decl PARAMS ((tree, int));
static tree dfs_find_final_overrider PARAMS ((tree, void *)); static tree dfs_find_final_overrider PARAMS ((tree, void *));
static tree find_final_overrider PARAMS ((tree, tree, tree)); static tree find_final_overrider PARAMS ((tree, tree, tree));
...@@ -7908,16 +7909,36 @@ add_vcall_offset_vtbl_entries_1 (binfo, vid) ...@@ -7908,16 +7909,36 @@ add_vcall_offset_vtbl_entries_1 (binfo, vid)
tree binfo; tree binfo;
vtbl_init_data* vid; vtbl_init_data* vid;
{ {
tree binfo_in_rtti;
if (vid->ctor_vtbl_p)
binfo_in_rtti = (get_original_base
(binfo, TYPE_BINFO (BINFO_TYPE (vid->rtti_binfo))));
else
binfo_in_rtti = binfo;
/* Make entries for the rest of the virtuals. */
if (abi_version_at_least (2))
{
tree orig_fn;
/* The ABI requires that the methods be processed in declaration
order. G++ 3.2 used the order in the vtable. */
for (orig_fn = TYPE_METHODS (BINFO_TYPE (binfo));
orig_fn;
orig_fn = TREE_CHAIN (orig_fn))
if (DECL_VINDEX (orig_fn))
add_vcall_offset (orig_fn, binfo_in_rtti, vid);
}
else
{
tree derived_virtuals; tree derived_virtuals;
tree base_virtuals; tree base_virtuals;
tree orig_virtuals; tree orig_virtuals;
tree binfo_inits; /* If BINFO is a primary base, the most derived class which has
/* If BINFO is a primary base, the most derived class which has BINFO as BINFO as a primary base; otherwise, just BINFO. */
a primary base; otherwise, just BINFO. */
tree non_primary_binfo; tree non_primary_binfo;
binfo_inits = NULL_TREE;
/* We might be a primary base class. Go up the inheritance hierarchy /* 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: 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. */ it is the BINFO_VIRTUALS there that we need to consider. */
...@@ -7952,7 +7973,6 @@ add_vcall_offset_vtbl_entries_1 (binfo, vid) ...@@ -7952,7 +7973,6 @@ add_vcall_offset_vtbl_entries_1 (binfo, vid)
non_primary_binfo = get_original_base non_primary_binfo = get_original_base
(non_primary_binfo, TYPE_BINFO (BINFO_TYPE (vid->rtti_binfo))); (non_primary_binfo, TYPE_BINFO (BINFO_TYPE (vid->rtti_binfo)));
/* Make entries for the rest of the virtuals. */
for (base_virtuals = BINFO_VIRTUALS (binfo), for (base_virtuals = BINFO_VIRTUALS (binfo),
derived_virtuals = BINFO_VIRTUALS (non_primary_binfo), derived_virtuals = BINFO_VIRTUALS (non_primary_binfo),
orig_virtuals = BINFO_VIRTUALS (TYPE_BINFO (BINFO_TYPE (binfo))); orig_virtuals = BINFO_VIRTUALS (TYPE_BINFO (BINFO_TYPE (binfo)));
...@@ -7962,9 +7982,6 @@ add_vcall_offset_vtbl_entries_1 (binfo, vid) ...@@ -7962,9 +7982,6 @@ add_vcall_offset_vtbl_entries_1 (binfo, vid)
orig_virtuals = TREE_CHAIN (orig_virtuals)) orig_virtuals = TREE_CHAIN (orig_virtuals))
{ {
tree orig_fn; tree orig_fn;
tree fn;
size_t i;
tree vcall_offset;
/* Find the declaration that originally caused this function to /* Find the declaration that originally caused this function to
be present in BINFO_TYPE (binfo). */ be present in BINFO_TYPE (binfo). */
...@@ -7976,8 +7993,21 @@ add_vcall_offset_vtbl_entries_1 (binfo, vid) ...@@ -7976,8 +7993,21 @@ add_vcall_offset_vtbl_entries_1 (binfo, vid)
if (!same_type_p (DECL_CONTEXT (orig_fn), BINFO_TYPE (binfo))) if (!same_type_p (DECL_CONTEXT (orig_fn), BINFO_TYPE (binfo)))
continue; continue;
/* Find the overriding function. */ add_vcall_offset (orig_fn, binfo_in_rtti, vid);
fn = BV_FN (derived_virtuals); }
}
}
/* Add a vcall offset entry for ORIG_FN to the vtable. In a
construction vtable, BINFO_IN_RTTI is the base corresponding to the
vtable base in VID->RTTI_BINFO. */
static void
add_vcall_offset (tree orig_fn, tree binfo_in_rtti,
vtbl_init_data *vid)
{
size_t i;
tree vcall_offset;
/* If there is already an entry for a function with the same /* If there is already an entry for a function with the same
signature as FN, then we do not need a second vcall offset. signature as FN, then we do not need a second vcall offset.
...@@ -7988,22 +8018,21 @@ add_vcall_offset_vtbl_entries_1 (binfo, vid) ...@@ -7988,22 +8018,21 @@ add_vcall_offset_vtbl_entries_1 (binfo, vid)
tree derived_entry; tree derived_entry;
derived_entry = VARRAY_TREE (vid->fns, i); derived_entry = VARRAY_TREE (vid->fns, i);
if (same_signature_p (BV_FN (derived_entry), fn) if (same_signature_p (derived_entry, orig_fn)
/* We only use one vcall offset for virtual destructors, /* We only use one vcall offset for virtual destructors,
even though there are two virtual table entries. */ even though there are two virtual table entries. */
|| (DECL_DESTRUCTOR_P (BV_FN (derived_entry)) || (DECL_DESTRUCTOR_P (derived_entry)
&& DECL_DESTRUCTOR_P (fn))) && DECL_DESTRUCTOR_P (orig_fn)))
break; return;
} }
if (i != VARRAY_ACTIVE_SIZE (vid->fns))
continue;
/* If we are building these vcall offsets as part of building /* If we are building these vcall offsets as part of building
the vtable for the most derived class, remember the vcall the vtable for the most derived class, remember the vcall
offset. */ offset. */
if (vid->binfo == TYPE_BINFO (vid->derived)) if (vid->binfo == TYPE_BINFO (vid->derived))
CLASSTYPE_VCALL_INDICES (vid->derived) CLASSTYPE_VCALL_INDICES (vid->derived)
= tree_cons (fn, vid->index, CLASSTYPE_VCALL_INDICES (vid->derived)); = tree_cons (orig_fn, vid->index,
CLASSTYPE_VCALL_INDICES (vid->derived));
/* The next vcall offset will be found at a more negative /* The next vcall offset will be found at a more negative
offset. */ offset. */
...@@ -8011,13 +8040,23 @@ add_vcall_offset_vtbl_entries_1 (binfo, vid) ...@@ -8011,13 +8040,23 @@ add_vcall_offset_vtbl_entries_1 (binfo, vid)
ssize_int (TARGET_VTABLE_DATA_ENTRY_DISTANCE)); ssize_int (TARGET_VTABLE_DATA_ENTRY_DISTANCE));
/* Keep track of this function. */ /* Keep track of this function. */
VARRAY_PUSH_TREE (vid->fns, derived_virtuals); VARRAY_PUSH_TREE (vid->fns, orig_fn);
if (vid->generate_vcall_entries) if (vid->generate_vcall_entries)
{ {
tree base; tree base;
tree base_binfo; tree base_binfo;
tree fn;
/* Find the overriding function. */
fn = find_final_overrider (BINFO_TYPE (vid->rtti_binfo),
binfo_in_rtti, orig_fn);
if (fn == error_mark_node)
vcall_offset = build1 (NOP_EXPR, vtable_entry_type,
integer_zero_node);
else
{
fn = TREE_PURPOSE (fn);
/* The FN comes from BASE. So, we must calculate the /* The FN comes from BASE. So, we must calculate the
adjustment from vid->vbase to BASE. We can just look for adjustment from vid->vbase to BASE. We can just look for
BASE in the complete object because we are converting BASE in the complete object because we are converting
...@@ -8037,11 +8076,11 @@ add_vcall_offset_vtbl_entries_1 (binfo, vid) ...@@ -8037,11 +8076,11 @@ add_vcall_offset_vtbl_entries_1 (binfo, vid)
vcall_offset); vcall_offset);
vcall_offset = fold (build1 (NOP_EXPR, vtable_entry_type, vcall_offset = fold (build1 (NOP_EXPR, vtable_entry_type,
vcall_offset)); vcall_offset));
}
/* Add the intiailizer to the vtable. */
*vid->last_init = build_tree_list (NULL_TREE, vcall_offset); *vid->last_init = build_tree_list (NULL_TREE, vcall_offset);
vid->last_init = &TREE_CHAIN (*vid->last_init); vid->last_init = &TREE_CHAIN (*vid->last_init);
} }
}
} }
/* Return vtbl initializers for the RTTI entries coresponding to the /* Return vtbl initializers for the RTTI entries coresponding to the
......
2002-11-07 Mark Mitchell <mark@codesourcery.com> 2002-11-07 Mark Mitchell <mark@codesourcery.com>
* g++.dg/abi/vthunk3.C: New test.
PR c++/8338 PR c++/8338
* g++.dg/template/crash2.C: New test. * g++.dg/template/crash2.C: New test.
......
// { dg-do compile }
// { dg-options "-fabi-version=0" }
struct A {
virtual void a ();
};
struct B : virtual public A {
virtual void b ();
virtual void a ();
};
struct C {
virtual void c ();
};
struct D : public C, public B {
};
struct E : virtual public D {
void b ();
};
void E::b () {}
// { dg-final { scan-assembler _ZTvn4_n20_N1E1bEv } }
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