call.c (build_special_member_call): Do not try to lookup VTTs by name.

* call.c (build_special_member_call): Do not try to lookup VTTs by
	name.
	* class.c (vtbl_init_data): Add generate_vcall_entries.
	(get_vtable_decl): Do not look up virtual tables by name.
	(copy_virtuals): Do not use BV_USE_VCALL_INDEX_P.
	(set_primary_base): Do not set CLASSTYPE_RTTI.
	(determine_primary_base): Likewise.
	(get_matching_virtual): Remove.
	(get_vcall_index): New function.
	(update_vtable_entry_for_fn): Do not try to use virtual thunks
	when they are not required.  Assign vcall indices at this point.
	(finish_struct_1): Do not set CLASSTYPE_NEEDS_VIRTUAL_REINIT.
	Do update dynamic_classes.
	(build_vtt): Do not add VTTs to the symbol table.
	(build_ctor_vtbl_group): Likewise.
	(build_vtbl_initializer): Simplify handling of vcall indices.
	(build_vcall_offset_vtbl_entries): Pretend to build vcall offsets
	for the most derived class.
	(add_vcall_offset_vtbl_entries_1): But do not actually add them to
	the vtable.
	* cp-tree.h (dynamic_classes): New macro.
	(lang_type_class): Remove rtti.  Add vtables.  Add vcall_indices.
	(CLASSTYPE_RTTI): Remove.
	(CLASSTYPE_NEEDS_VIRTUAL_REINIT): Remove.
	(CLASSTYPE_VCALL_INDICES): New macro.
	(CLASSTYPE_VTABLES): Likewise.
	(BV_USE_VCALL_INDEX_P): Remove.
	(build_vtable_path): Remove.
	* decl2.c (finish_vtable_vardecl): Remove.
	(key_method): Remove #if 0'd code.
	(finish_vtable_vardecl): Rename to ...
	(maybe_emit_vtables): ... this.
	(finish_file): Use it.
	* search.c (look_for_overrides_here): Update comment.

	* g++.dg/abi/thunk1.C: New test.
	* g++.dg/abi/thunk2.C: Likewise.
	* g++.dg/abi/vtt1.C: Likewise.

From-SVN: r58779
This commit is contained in:
Mark Mitchell 2002-11-04 01:45:58 +00:00 committed by Mark Mitchell
parent 55376e4128
commit 548502d3b1
10 changed files with 294 additions and 248 deletions

View File

@ -1,3 +1,40 @@
2002-11-03 Mark Mitchell <mark@codesourcery.com>
* call.c (build_special_member_call): Do not try to lookup VTTs by
name.
* class.c (vtbl_init_data): Add generate_vcall_entries.
(get_vtable_decl): Do not look up virtual tables by name.
(copy_virtuals): Do not use BV_USE_VCALL_INDEX_P.
(set_primary_base): Do not set CLASSTYPE_RTTI.
(determine_primary_base): Likewise.
(get_matching_virtual): Remove.
(get_vcall_index): New function.
(update_vtable_entry_for_fn): Do not try to use virtual thunks
when they are not required. Assign vcall indices at this point.
(finish_struct_1): Do not set CLASSTYPE_NEEDS_VIRTUAL_REINIT.
Do update dynamic_classes.
(build_vtt): Do not add VTTs to the symbol table.
(build_ctor_vtbl_group): Likewise.
(build_vtbl_initializer): Simplify handling of vcall indices.
(build_vcall_offset_vtbl_entries): Pretend to build vcall offsets
for the most derived class.
(add_vcall_offset_vtbl_entries_1): But do not actually add them to
the vtable.
* cp-tree.h (dynamic_classes): New macro.
(lang_type_class): Remove rtti. Add vtables. Add vcall_indices.
(CLASSTYPE_RTTI): Remove.
(CLASSTYPE_NEEDS_VIRTUAL_REINIT): Remove.
(CLASSTYPE_VCALL_INDICES): New macro.
(CLASSTYPE_VTABLES): Likewise.
(BV_USE_VCALL_INDEX_P): Remove.
(build_vtable_path): Remove.
* decl2.c (finish_vtable_vardecl): Remove.
(key_method): Remove #if 0'd code.
(finish_vtable_vardecl): Rename to ...
(maybe_emit_vtables): ... this.
(finish_file): Use it.
* search.c (look_for_overrides_here): Update comment.
2002-11-01 Zack Weinberg <zack@codesourcery.com>
PR c/7353 redux

View File

@ -4712,7 +4712,7 @@ build_special_member_call (tree instance, tree name, tree args,
/* If the current function is a complete object constructor
or destructor, then we fetch the VTT directly.
Otherwise, we look it up using the VTT we were given. */
vtt = IDENTIFIER_GLOBAL_VALUE (get_vtt_name (current_class_type));
vtt = TREE_CHAIN (CLASSTYPE_VTABLES (current_class_type));
vtt = decay_conversion (vtt);
vtt = build (COND_EXPR, TREE_TYPE (vtt),
build (EQ_EXPR, boolean_type_node,

View File

@ -87,6 +87,9 @@ typedef struct vtbl_init_data_s
/* Nonzero if we are building the initializer for a construction
vtable. */
int ctor_vtbl_p;
/* True when adding vcall offset entries to the vtable. False when
merely computing the indices. */
bool generate_vcall_entries;
} vtbl_init_data;
/* The type of a function passed to walk_subobject_offsets. */
@ -209,6 +212,7 @@ static tree dfs_base_derived_from (tree, void *);
static bool base_derived_from (tree, tree);
static int empty_base_at_nonzero_offset_p (tree, tree, splay_tree);
static tree end_of_base (tree);
static tree get_vcall_index (tree, tree);
/* Macros for dfs walking during vtt construction. See
dfs_ctor_vtable_bases_queue_p, dfs_build_secondary_vptr_vtt_inits
@ -540,21 +544,14 @@ get_vtable_decl (type, complete)
tree type;
int complete;
{
tree name = get_vtable_name (type);
tree decl = IDENTIFIER_GLOBAL_VALUE (name);
if (decl)
{
my_friendly_assert (TREE_CODE (decl) == VAR_DECL
&& DECL_VIRTUAL_P (decl), 20000118);
return decl;
}
decl = build_vtable (type, name, void_type_node);
decl = pushdecl_top_level (decl);
my_friendly_assert (IDENTIFIER_GLOBAL_VALUE (name) == decl,
20000517);
tree decl;
if (CLASSTYPE_VTABLES (type))
return CLASSTYPE_VTABLES (type);
decl = build_vtable (type, get_vtable_name (type), void_type_node);
CLASSTYPE_VTABLES (type) = decl;
/* At one time the vtable info was grabbed 2 words at a time. This
fails on sparc unless you have 8-byte alignment. (tiemann) */
DECL_ALIGN (decl) = MAX (TYPE_ALIGN (double_type_node),
@ -581,10 +578,7 @@ copy_virtuals (binfo)
copies = copy_list (BINFO_VIRTUALS (binfo));
for (t = copies; t; t = TREE_CHAIN (t))
{
BV_VCALL_INDEX (t) = NULL_TREE;
BV_USE_VCALL_INDEX_P (t) = 0;
}
BV_VCALL_INDEX (t) = NULL_TREE;
return copies;
}
@ -1559,7 +1553,6 @@ set_primary_base (t, binfo)
TYPE_BINFO_VTABLE (t) = TYPE_BINFO_VTABLE (basetype);
TYPE_BINFO_VIRTUALS (t) = TYPE_BINFO_VIRTUALS (basetype);
TYPE_VFIELD (t) = TYPE_VFIELD (basetype);
CLASSTYPE_RTTI (t) = CLASSTYPE_RTTI (basetype);
}
/* Determine the primary class for T. */
@ -1585,12 +1578,6 @@ determine_primary_base (t)
if (TYPE_CONTAINS_VPTR_P (basetype))
{
/* Even a virtual baseclass can contain our RTTI
information. But, we prefer a non-virtual polymorphic
baseclass. */
if (!CLASSTYPE_HAS_PRIMARY_BASE_P (t))
CLASSTYPE_RTTI (t) = CLASSTYPE_RTTI (basetype);
/* We prefer a non-virtual base, although a virtual one will
do. */
if (TREE_VIA_VIRTUAL (base_binfo))
@ -2325,21 +2312,23 @@ find_final_overrider (t, binfo, fn)
return ffod.candidates;
}
/* 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. */
/* Return the index of the vcall offset for FN when TYPE is used as a
virtual base. */
static tree get_matching_virtual PARAMS ((tree, tree));
static tree
get_matching_virtual (t, fn)
tree t, fn;
get_vcall_index (tree fn, tree type)
{
tree f;
tree v;
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;
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)))
break;
/* There should always be an appropriate index. */
my_friendly_assert (v, 20021103);
return TREE_VALUE (v);
}
/* Update an entry in the vtable for BINFO, which is in the hierarchy
@ -2407,7 +2396,6 @@ update_vtable_entry_for_fn (t, binfo, fn, virtuals)
/* 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 from the declaration to
the nearest virtual base. */
@ -2420,36 +2408,11 @@ update_vtable_entry_for_fn (t, binfo, fn, virtuals)
will be zero, as it will be a primary base. */
delta = size_zero_node;
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)),
BINFO_OFFSET (binfo));
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;
}
}
}
}
/* 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));
modify_vtable_entry (t,
binfo,
@ -2458,7 +2421,9 @@ update_vtable_entry_for_fn (t, binfo, fn, virtuals)
virtuals);
if (virtual_base)
BV_USE_VCALL_INDEX_P (*virtuals) = 1;
BV_VCALL_INDEX (*virtuals)
= get_vcall_index (TREE_PURPOSE (overrider),
BINFO_TYPE (virtual_base));
}
/* Called from modify_all_vtables via dfs_walk. */
@ -5101,32 +5066,8 @@ layout_class_type (tree t, tree *virtuals_p)
splay_tree_delete (empty_base_offsets);
}
/* Create a RECORD_TYPE or UNION_TYPE node for a C struct or union declaration
(or C++ class declaration).
For C++, we must handle the building of derived classes.
Also, C++ allows static class members. The way that this is
handled is to keep the field name where it is (as the DECL_NAME
of the field), and place the overloaded decl in the bit position
of the field. layout_record and layout_union will know about this.
More C++ hair: inline functions have text in their
DECL_PENDING_INLINE_INFO nodes which must somehow be parsed into
meaningful tree structure. After the struct has been laid out, set
things up so that this can happen.
And still more: virtual functions. In the case of single inheritance,
when a new virtual function is seen which redefines a virtual function
from the base class, the new virtual function is placed into
the virtual function table at exactly the same address that
it had in the base class. When this is extended to multiple
inheritance, the same thing happens, except that multiple virtual
function tables must be maintained. The first virtual function
table is treated in exactly the same way as in the case of single
inheritance. Additional virtual function tables have different
DELTAs, which tell how to adjust `this' to point to the right thing.
ATTRIBUTES is the set of decl attributes to be applied, if any. */
/* Perform processing required when the definition of T (a class type)
is complete. */
void
finish_struct_1 (t)
@ -5153,7 +5094,6 @@ finish_struct_1 (t)
TYPE_SIZE (t) = NULL_TREE;
CLASSTYPE_GOT_SEMICOLON (t) = 0;
CLASSTYPE_PRIMARY_BINFO (t) = NULL_TREE;
CLASSTYPE_RTTI (t) = NULL_TREE;
fixup_inline_methods (t);
@ -5210,24 +5150,6 @@ finish_struct_1 (t)
/* Here we know enough to change the type of our virtual
function table, but we will wait until later this function. */
build_primary_vtable (CLASSTYPE_PRIMARY_BINFO (t), t);
/* If this type has basetypes with constructors, then those
constructors might clobber the virtual function table. But
they don't if the derived class shares the exact vtable of the base
class. */
CLASSTYPE_NEEDS_VIRTUAL_REINIT (t) = 1;
}
/* If we didn't need a new vtable, see if we should copy one from
the base. */
else if (CLASSTYPE_HAS_PRIMARY_BASE_P (t))
{
tree binfo = CLASSTYPE_PRIMARY_BINFO (t);
/* If this class uses a different vtable than its primary base
then when we will need to initialize our vptr after the base
class constructor runs. */
if (TYPE_BINFO_VTABLE (t) != BINFO_VTABLE (binfo))
CLASSTYPE_NEEDS_VIRTUAL_REINIT (t) = 1;
}
if (TYPE_CONTAINS_VPTR_P (t))
@ -5253,6 +5175,9 @@ finish_struct_1 (t)
? TARGET_VTABLE_USES_DESCRIPTORS : 1))
if (TREE_CODE (DECL_VINDEX (BV_FN (fn))) != INTEGER_CST)
DECL_VINDEX (BV_FN (fn)) = build_shared_int_cst (vindex);
/* Add this class to the list of dynamic classes. */
dynamic_classes = tree_cons (NULL_TREE, t, dynamic_classes);
}
finish_struct_bits (t);
@ -7068,8 +6993,10 @@ build_vtt (t)
/* Now, build the VTT object itself. */
vtt = build_vtable (t, get_vtt_name (t), type);
pushdecl_top_level (vtt);
initialize_array (vtt, inits);
/* Add the VTT to the vtables list. */
TREE_CHAIN (vtt) = TREE_CHAIN (CLASSTYPE_VTABLES (t));
TREE_CHAIN (CLASSTYPE_VTABLES (t)) = vtt;
dump_vtt (t, vtt);
}
@ -7404,7 +7331,7 @@ build_ctor_vtbl_group (binfo, t)
TREE_TYPE (vtbl) = type;
/* Initialize the construction vtable. */
pushdecl_top_level (vtbl);
CLASSTYPE_VTABLES (t) = chainon (CLASSTYPE_VTABLES (t), vtbl);
initialize_array (vtbl, inits);
dump_vtable (t, binfo, vtbl);
}
@ -7621,6 +7548,7 @@ build_vtbl_initializer (binfo, orig_binfo, t, rtti_binfo, non_fn_entries_p)
vid.last_init = &vid.inits;
vid.primary_vtbl_p = (binfo == TYPE_BINFO (t));
vid.ctor_vtbl_p = !same_type_p (BINFO_TYPE (rtti_binfo), t);
vid.generate_vcall_entries = true;
/* The first vbase or vcall offset is at index -3 in the vtable. */
vid.index = ssize_int (-3 * TARGET_VTABLE_DATA_ENTRY_DISTANCE);
@ -7704,14 +7632,7 @@ build_vtbl_initializer (binfo, orig_binfo, t, rtti_binfo, non_fn_entries_p)
/* Pull the offset for `this', and the function to call, out of
the list. */
delta = BV_DELTA (v);
if (BV_USE_VCALL_INDEX_P (v))
{
vcall_index = BV_VCALL_INDEX (v);
my_friendly_assert (vcall_index != NULL_TREE, 20000621);
}
else
vcall_index = NULL_TREE;
vcall_index = BV_VCALL_INDEX (v);
my_friendly_assert (TREE_CODE (delta) == INTEGER_CST, 19990727);
my_friendly_assert (TREE_CODE (fn) == FUNCTION_DECL, 19990727);
@ -7900,31 +7821,37 @@ build_vcall_offset_vtbl_entries (binfo, vid)
tree binfo;
vtbl_init_data *vid;
{
/* We only need these entries if this base is a virtual base. */
if (!TREE_VIA_VIRTUAL (binfo))
return;
/* We only need these entries if this base is a virtual base. We
compute the indices -- but do not add to the vtable -- when
building the main vtable for a class. */
if (TREE_VIA_VIRTUAL (binfo) || binfo == TYPE_BINFO (vid->derived))
{
/* We need a vcall offset for each of the virtual functions in this
vtable. For example:
/* We need a vcall offset for each of the virtual functions in this
vtable. For example:
class A { virtual void f (); };
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 (); };
class A { virtual void f (); };
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.
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' secondary vtables. */
vid->vbase = binfo;
/* Now, walk through the non-virtual bases, adding vcall offsets. */
add_vcall_offset_vtbl_entries_r (binfo, vid);
We need entries for all the functions in our primary vtable and
in our non-virtual bases' secondary vtables. */
vid->vbase = binfo;
/* If we are just computing the vcall indices -- but do not need
the actual entries -- not that. */
if (!TREE_VIA_VIRTUAL (binfo))
vid->generate_vcall_entries = false;
/* Now, walk through the non-virtual bases, adding vcall offsets. */
add_vcall_offset_vtbl_entries_r (binfo, vid);
}
}
/* Build vcall offsets, starting with those for BINFO. */
@ -8025,8 +7952,6 @@ add_vcall_offset_vtbl_entries_1 (binfo, vid)
{
tree orig_fn;
tree fn;
tree base;
tree base_binfo;
size_t i;
tree vcall_offset;
@ -8057,42 +7982,17 @@ add_vcall_offset_vtbl_entries_1 (binfo, vid)
even though there are two virtual table entries. */
|| (DECL_DESTRUCTOR_P (BV_FN (derived_entry))
&& DECL_DESTRUCTOR_P (fn)))
{
if (!vid->ctor_vtbl_p)
BV_VCALL_INDEX (derived_virtuals)
= BV_VCALL_INDEX (derived_entry);
break;
}
break;
}
if (i != VARRAY_ACTIVE_SIZE (vid->fns))
continue;
/* 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 = lookup_base (vid->derived, base, ba_any, NULL);
/* Compute the vcall offset. */
/* 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,
vcall_offset));
*vid->last_init = build_tree_list (NULL_TREE, vcall_offset);
vid->last_init = &TREE_CHAIN (*vid->last_init);
/* Keep track of the vtable index where this vcall offset can be
found. For a construction vtable, we already made this
annotation when we built the original vtable. */
if (!vid->ctor_vtbl_p)
BV_VCALL_INDEX (derived_virtuals) = vid->index;
/* If we are building these vcall offsets as part of building
the vtable for the most derived class, remember the vcall
offset. */
if (vid->binfo == TYPE_BINFO (vid->derived))
CLASSTYPE_VCALL_INDICES (vid->derived)
= tree_cons (fn, vid->index, CLASSTYPE_VCALL_INDICES (vid->derived));
/* The next vcall offset will be found at a more negative
offset. */
@ -8101,6 +8001,35 @@ add_vcall_offset_vtbl_entries_1 (binfo, vid)
/* Keep track of this function. */
VARRAY_PUSH_TREE (vid->fns, derived_virtuals);
if (vid->generate_vcall_entries)
{
tree base;
tree base_binfo;
/* 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 = lookup_base (vid->derived, base, ba_any, NULL);
/* Compute the vcall offset. */
/* 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,
vcall_offset));
*vid->last_init = build_tree_list (NULL_TREE, vcall_offset);
vid->last_init = &TREE_CHAIN (*vid->last_init);
}
}
}

View File

@ -47,7 +47,6 @@ struct diagnostic_context;
ICS_USER_FLAG (in _CONV)
CLEANUP_P (in TRY_BLOCK)
AGGR_INIT_VIA_CTOR_P (in AGGR_INIT_EXPR)
BV_USE_VCALL_INDEX_P (in the BINFO_VIRTUALS TREE_LIST)
PTRMEM_OK_P (in ADDR_EXPR, OFFSET_REF)
PARMLIST_ELLIPSIS_P (in PARMLIST)
1: IDENTIFIER_VIRTUAL_P.
@ -133,9 +132,7 @@ struct diagnostic_context;
of the base class.
The BV_VCALL_INDEX of each node, if non-NULL, gives the vtable
index of the vcall offset for this entry. If
BV_USE_VCALL_INDEX_P then the corresponding vtable entry should
use a virtual thunk, as opposed to an ordinary thunk.
index of the vcall offset for this entry.
The BV_FN is the declaration for the virtual function itself.
@ -615,6 +612,8 @@ enum cp_tree_index
CPTI_DSO_HANDLE,
CPTI_DCAST,
CPTI_DYNAMIC_CLASSES,
CPTI_MAX
};
@ -745,6 +744,10 @@ extern GTY(()) tree cp_global_trees[CPTI_MAX];
destructors. */
#define vtt_parm_type cp_global_trees[CPTI_VTT_PARM_TYPE]
/* A TREE_LIST of all of the dynamic classes in the program. */
#define dynamic_classes cp_global_trees[CPTI_DYNAMIC_CLASSES]
/* Global state. */
struct saved_scope GTY(())
@ -1153,12 +1156,13 @@ struct lang_type_class GTY(())
tree primary_base;
tree vfields;
tree vcall_indices;
tree vtables;
tree vbases;
tree tags;
tree as_base;
tree pure_virtuals;
tree friend_classes;
tree rtti;
tree methods;
tree decl_list;
tree template_info;
@ -1257,9 +1261,6 @@ struct lang_type GTY(())
convenient, don't reprocess any methods that appear in its redefinition. */
#define TYPE_REDEFINED(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->redefined)
/* The is the basetype that contains NODE's rtti. */
#define CLASSTYPE_RTTI(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->rtti)
/* Nonzero means that this _CLASSTYPE node overloads operator(). */
#define TYPE_OVERLOADS_CALL_EXPR(NODE) \
(LANG_TYPE_CLASS_CHECK (NODE)->has_call_overloaded)
@ -1431,13 +1432,6 @@ struct lang_type GTY(())
/* Nonzero means that this aggr type has been `closed' by a semicolon. */
#define CLASSTYPE_GOT_SEMICOLON(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->got_semicolon)
/* Nonzero means that the main virtual function table pointer needs to be
set because base constructors have placed the wrong value there.
If this is zero, it means that they placed the right value there,
and there is no need to change it. */
#define CLASSTYPE_NEEDS_VIRTUAL_REINIT(NODE) \
(LANG_TYPE_CLASS_CHECK (NODE)->needs_virtual_reinit)
/* Nonzero means that this type has an X() constructor. */
#define TYPE_HAS_DEFAULT_CONSTRUCTOR(NODE) \
(LANG_TYPE_CLASS_CHECK (NODE)->h.has_default_ctor)
@ -1629,6 +1623,19 @@ struct lang_type GTY(())
/* Used by various search routines. */
#define IDENTIFIER_MARKED(NODE) TREE_LANG_FLAG_0 (NODE)
/* A TREE_LIST of the vcall indices associated with the class NODE.
The TREE_PURPOSE of each node is a FUNCTION_DECL for a virtual
function. The TREE_VALUE is the index into the virtual table where
the vcall offset for that function is stored, when NODE is a
virtual base. */
#define CLASSTYPE_VCALL_INDICES(NODE) \
(LANG_TYPE_CLASS_CHECK (NODE)->vcall_indices)
/* The various vtables for the class NODE. The primary vtable will be
first, followed by the construction vtables and VTT, if any. */
#define CLASSTYPE_VTABLES(NODE) \
(LANG_TYPE_CLASS_CHECK (NODE)->vtables)
/* Accessor macros for the vfield slots in structures. */
/* List of virtual table fields that this type contains (both the primary
@ -1664,8 +1671,6 @@ struct lang_type GTY(())
/* The function to call. */
#define BV_FN(NODE) (TREE_VALUE (NODE))
/* Nonzero if we should use a virtual thunk for this entry. */
#define BV_USE_VCALL_INDEX_P(NODE) (TREE_LANG_FLAG_0 (NODE))
/* Nonzero for TREE_LIST node means that this list of things
is a list of parameters, as opposed to a list of expressions. */
@ -3546,7 +3551,6 @@ extern tree perform_implicit_conversion PARAMS ((tree, tree));
/* in class.c */
extern tree build_base_path PARAMS ((enum tree_code, tree, tree, int));
extern tree convert_to_base (tree, tree, bool);
extern tree build_vbase_path PARAMS ((enum tree_code, tree, tree, tree, int));
extern tree build_vtbl_ref PARAMS ((tree, tree));
extern tree build_vfn_ref PARAMS ((tree, tree));
extern tree get_vtable_decl PARAMS ((tree, int));

View File

@ -60,7 +60,7 @@ typedef struct priority_info_s {
static void mark_vtable_entries PARAMS ((tree));
static void grok_function_init PARAMS ((tree, tree));
static int finish_vtable_vardecl PARAMS ((tree *, void *));
static int maybe_emit_vtables (tree);
static int is_namespace_ancestor PARAMS ((tree, tree));
static void add_using_namespace PARAMS ((tree, tree, int));
static tree ambiguous_decl PARAMS ((tree, tree, tree,int));
@ -1658,12 +1658,7 @@ key_method (type)
method = TREE_CHAIN (method))
if (DECL_VINDEX (method) != NULL_TREE
&& ! DECL_DECLARED_INLINE_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
))
&& ! DECL_PURE_VIRTUAL_P (method))
return method;
return NULL_TREE;
@ -1805,28 +1800,52 @@ output_vtable_inherit (vars)
assemble_vtable_inherit (child_rtx, parent_rtx);
}
static int
finish_vtable_vardecl (t, data)
tree *t;
void *data ATTRIBUTE_UNUSED;
{
tree vars = *t;
tree ctype = DECL_CONTEXT (vars);
import_export_class (ctype);
import_export_vtable (vars, ctype, 1);
/* If necessary, write out the vtables for the dynamic class CTYPE.
Returns non-zero if any vtables were emitted. */
if (! DECL_EXTERNAL (vars)
&& DECL_NEEDED_P (vars)
&& ! TREE_ASM_WRITTEN (vars))
static int
maybe_emit_vtables (tree ctype)
{
tree vtbl;
tree primary_vtbl;
/* If the vtables for this class have already been emitted there is
nothing more to do. */
primary_vtbl = CLASSTYPE_VTABLES (ctype);
if (TREE_ASM_WRITTEN (primary_vtbl))
return 0;
/* Ignore dummy vtables made by get_vtable_decl. */
if (TREE_TYPE (primary_vtbl) == void_type_node)
return 0;
import_export_class (ctype);
import_export_vtable (primary_vtbl, ctype, 1);
/* See if any of the vtables are needed. */
for (vtbl = CLASSTYPE_VTABLES (ctype); vtbl; vtbl = TREE_CHAIN (vtbl))
if (!DECL_EXTERNAL (vtbl) && DECL_NEEDED_P (vtbl))
break;
if (!vtbl)
{
/* If the references to this class' vtables are optimized away,
still emit the appropriate debugging information. See
dfs_debug_mark. */
if (DECL_COMDAT (primary_vtbl)
&& CLASSTYPE_DEBUG_REQUESTED (ctype))
note_debug_info_needed (ctype);
return 0;
}
/* The ABI requires that we emit all of the vtables if we emit any
of them. */
for (vtbl = CLASSTYPE_VTABLES (ctype); vtbl; vtbl = TREE_CHAIN (vtbl))
{
if (TREE_TYPE (vars) == void_type_node)
/* It is a dummy vtable made by get_vtable_decl. Ignore it. */
return 0;
/* Write it out. */
mark_vtable_entries (vars);
if (TREE_TYPE (DECL_INITIAL (vars)) == 0)
store_init_value (vars, DECL_INITIAL (vars));
import_export_vtable (vtbl, ctype, 1);
mark_vtable_entries (vtbl);
if (TREE_TYPE (DECL_INITIAL (vtbl)) == 0)
store_init_value (vtbl, DECL_INITIAL (vtbl));
if (write_symbols == DWARF_DEBUG || write_symbols == DWARF2_DEBUG)
{
@ -1851,37 +1870,29 @@ finish_vtable_vardecl (t, data)
`S' get written (which would solve the problem) but that would
require more intrusive changes to the g++ front end. */
DECL_IGNORED_P (vars) = 1;
DECL_IGNORED_P (vtbl) = 1;
}
/* Always make vtables weak. */
if (flag_weak)
comdat_linkage (vars);
comdat_linkage (vtbl);
rest_of_decl_compilation (vars, NULL, 1, 1);
rest_of_decl_compilation (vtbl, NULL, 1, 1);
if (flag_vtable_gc)
output_vtable_inherit (vars);
output_vtable_inherit (vtbl);
/* Because we're only doing syntax-checking, we'll never end up
actually marking the variable as written. */
if (flag_syntax_only)
TREE_ASM_WRITTEN (vars) = 1;
/* Since we're writing out the vtable here, also write the debug
info. */
note_debug_info_needed (ctype);
return 1;
TREE_ASM_WRITTEN (vtbl) = 1;
}
/* If the references to this class' vtables were optimized away, still
emit the appropriate debugging information. See dfs_debug_mark. */
if (DECL_COMDAT (vars)
&& CLASSTYPE_DEBUG_REQUESTED (ctype))
note_debug_info_needed (ctype);
/* Since we're writing out the vtable here, also write the debug
info. */
note_debug_info_needed (ctype);
return 0;
return 1;
}
/* Determines the proper settings of TREE_PUBLIC and DECL_EXTERNAL for an
@ -2755,6 +2766,8 @@ finish_file ()
do
{
tree t;
reconsider = 0;
/* If there are templates that we've put off instantiating, do
@ -2764,10 +2777,9 @@ finish_file ()
/* Write out virtual tables as required. Note that writing out
the virtual table for a template class may cause the
instantiation of members of that class. */
if (walk_vtables (vtable_decl_p,
finish_vtable_vardecl,
/*data=*/0))
reconsider = 1;
for (t = dynamic_classes; t; t = TREE_CHAIN (t))
if (maybe_emit_vtables (TREE_VALUE (t)))
reconsider = 1;
/* Write out needed type info variables. Writing out one variable
might cause others to be needed. */

View File

@ -1955,9 +1955,8 @@ look_for_overrides (type, fndecl)
return found;
}
/* 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. */
/* Look in TYPE for virtual functions with the same signature as
FNDECL. */
tree
look_for_overrides_here (type, fndecl)

View File

@ -1,3 +1,9 @@
2002-11-03 Mark Mitchell <mark@codesourcery.com>
* g++.dg/abi/thunk1.C: New test.
* g++.dg/abi/thunk2.C: Likewise.
* g++.dg/abi/vtt1.C: Likewise.
2002-11-02 Diego Novillo <dnovillo@redhat.com>
PR optimization/8423

View File

@ -0,0 +1,22 @@
// { dg-do compile { target i?86-*-* } }
struct A {
virtual void f ();
};
struct B : public virtual A {
virtual void f ();
};
struct C {
virtual void g ();
};
struct D : public C, public B {
virtual void f ();
};
void D::f () {}
// { dg-final { scan-assembler _ZThn4_N1D1fEv } }
// { dg-final { scan-assembler _ZTv0_n12_N1D1fEv } }

View File

@ -0,0 +1,26 @@
// { dg-do compile { target i?86-*-* } }
// { dg-options -w }
struct A {
virtual void f2 ();
virtual void f3 ();
};
struct B : virtual public A {
virtual void f3 ();
};
struct C : public A, public B {
virtual void f4 ();
};
struct D : virtual public B, virtual public C, virtual public A
{
virtual void f5 ();
virtual void f6 ();
virtual void f3 ();
};
void D::f3 () {}
// { dg-final { scan-assembler _ZTvn4_n20_N1D2f3Ev } }

View File

@ -0,0 +1,11 @@
// { dg-do compile }
struct A {
};
struct B : virtual public A {
};
B b;
// { dg-final { scan-assembler _ZTT1B } }