Finish implementation of VTTs.
* cp-tree.h (cp_tree_index): Add CPTI_VTT_PARM_TYPE and CPTI_VTT_PARM_IDENTIFIER. (vtt_parm_identifier): New macro. (vtt_parm_type): Likewise. (BINFO_SUBVTT_INDEX): Likewise. (BINFO_VPTR_INDEX): Likewise. (struct lang_decl): Add vtt_parm. (DECL_VTT_PARM): New macro. (DECL_USE_VTT_PARM): Likewise. (DECL_NEEDS_VTT_PARM_P): Likewise. (get_vtt_name): Declare. (build_artifical_parm): Likewise. (fixup_all_virtual_upcast_offsets): Likewise. (expand_indirect_vtbls_init): Remove. * call.c (build_new_method_call): Pass the vtt to subobject constructors and destructors. * class.c (get_vtt_name): Give it external linkage. (build_clone): Handle the magic VTT parameters for clones. (clone_function_decl): Fix typo in comment. (build_vtt): Keep track of the indices in the VTTs where various entities are stored. (build_vtt_inits): Likewise. (dfs_build_vtt_inits): Likewise. (build_ctor_vtbl_group): Tweak type of construction vtables. (dfs_accumulate_vtbl_inits): Build vtables for all bases, even primary bases, when building construction vtables. * decl.c (duplicate_decls): Handle DECL_VTT_PARM. (initialize_predefined_identifiers): Add vtt_parm_identifier. (init_decl_processing): Initialize vtt_parm_type. (grokfndecl): Use DECL_OVERLOADED_OPERATOR_P. (lang_mark_tree): Make vtt_parm. * decl2.c (build_artificial_parm): New function. (maybe_retrofit_in_chrg): Use it. Add VTT parameters. (grokclassfn): Use build_artificial_parm. * init.c (initialize_vtbl_ptrs): Call fixup_all_virtual_upcast_offsets directly. (perform_member_init): Use the complete subobject destructor for member cleanups. (build_vtbl_address): New function. (expand_virtual_init): Handle VTTs. * optimize (maybe_clone_body): Likewise. * search.c (fixup_all_virtual_upcast_offsets): Give it external linkage. (expand_indirect_vtbls_init): Remove. * semantics.c (setup_vtbl_ptr): Fix typos in comment. * tree.c (make_binfo): Make them bigger. From-SVN: r34177
This commit is contained in:
parent
a0ee3b8335
commit
3ec6bad360
@ -1,3 +1,53 @@
|
||||
2000-05-25 Mark Mitchell <mark@codesourcery.com>
|
||||
|
||||
Finish implementation of VTTs.
|
||||
* cp-tree.h (cp_tree_index): Add CPTI_VTT_PARM_TYPE and
|
||||
CPTI_VTT_PARM_IDENTIFIER.
|
||||
(vtt_parm_identifier): New macro.
|
||||
(vtt_parm_type): Likewise.
|
||||
(BINFO_SUBVTT_INDEX): Likewise.
|
||||
(BINFO_VPTR_INDEX): Likewise.
|
||||
(struct lang_decl): Add vtt_parm.
|
||||
(DECL_VTT_PARM): New macro.
|
||||
(DECL_USE_VTT_PARM): Likewise.
|
||||
(DECL_NEEDS_VTT_PARM_P): Likewise.
|
||||
(get_vtt_name): Declare.
|
||||
(build_artifical_parm): Likewise.
|
||||
(fixup_all_virtual_upcast_offsets): Likewise.
|
||||
(expand_indirect_vtbls_init): Remove.
|
||||
* call.c (build_new_method_call): Pass the vtt to subobject
|
||||
constructors and destructors.
|
||||
* class.c (get_vtt_name): Give it external linkage.
|
||||
(build_clone): Handle the magic VTT parameters for clones.
|
||||
(clone_function_decl): Fix typo in comment.
|
||||
(build_vtt): Keep track of the indices in the VTTs where various
|
||||
entities are stored.
|
||||
(build_vtt_inits): Likewise.
|
||||
(dfs_build_vtt_inits): Likewise.
|
||||
(build_ctor_vtbl_group): Tweak type of construction vtables.
|
||||
(dfs_accumulate_vtbl_inits): Build vtables for all bases, even
|
||||
primary bases, when building construction vtables.
|
||||
* decl.c (duplicate_decls): Handle DECL_VTT_PARM.
|
||||
(initialize_predefined_identifiers): Add vtt_parm_identifier.
|
||||
(init_decl_processing): Initialize vtt_parm_type.
|
||||
(grokfndecl): Use DECL_OVERLOADED_OPERATOR_P.
|
||||
(lang_mark_tree): Make vtt_parm.
|
||||
* decl2.c (build_artificial_parm): New function.
|
||||
(maybe_retrofit_in_chrg): Use it. Add VTT parameters.
|
||||
(grokclassfn): Use build_artificial_parm.
|
||||
* init.c (initialize_vtbl_ptrs): Call
|
||||
fixup_all_virtual_upcast_offsets directly.
|
||||
(perform_member_init): Use the complete subobject destructor for
|
||||
member cleanups.
|
||||
(build_vtbl_address): New function.
|
||||
(expand_virtual_init): Handle VTTs.
|
||||
* optimize (maybe_clone_body): Likewise.
|
||||
* search.c (fixup_all_virtual_upcast_offsets): Give it external
|
||||
linkage.
|
||||
(expand_indirect_vtbls_init): Remove.
|
||||
* semantics.c (setup_vtbl_ptr): Fix typos in comment.
|
||||
* tree.c (make_binfo): Make them bigger.
|
||||
|
||||
2000-05-25 Nathan Sidwell <nathan@codesourcery.com>
|
||||
|
||||
* inc/cxxabi.h (__pbase_type_info): Define, based on
|
||||
|
@ -4321,6 +4321,32 @@ build_new_method_call (instance, name, args, basetype_path, flags)
|
||||
old ABI. */
|
||||
name = constructor_p ? ctor_identifier : dtor_identifier;
|
||||
}
|
||||
/* If we're call a subobject constructor or destructor for a
|
||||
subobject that uses virtual base classes, then we need to
|
||||
pass down a pointer to a VTT for the subobject. */
|
||||
else if ((name == base_ctor_identifier
|
||||
|| name == base_dtor_identifier)
|
||||
&& TYPE_USES_VIRTUAL_BASECLASSES (basetype))
|
||||
{
|
||||
tree vtt;
|
||||
tree sub_vtt;
|
||||
|
||||
/* 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 = build_unary_op (ADDR_EXPR, vtt, /*noconvert=*/1);
|
||||
vtt = build (COND_EXPR, TREE_TYPE (vtt),
|
||||
DECL_USE_VTT_PARM (current_function_decl),
|
||||
DECL_VTT_PARM (current_function_decl),
|
||||
vtt);
|
||||
|
||||
sub_vtt = build (PLUS_EXPR, TREE_TYPE (vtt), vtt,
|
||||
BINFO_SUBVTT_INDEX (basetype_path));
|
||||
sub_vtt = build_indirect_ref (sub_vtt, NULL);
|
||||
|
||||
args = tree_cons (NULL_TREE, sub_vtt, args);
|
||||
}
|
||||
}
|
||||
else
|
||||
pretty_name = name;
|
||||
|
@ -181,7 +181,7 @@ static void update_vtable_entry_for_fn PARAMS ((tree, tree, tree, tree *));
|
||||
static tree copy_virtuals PARAMS ((tree));
|
||||
static void build_ctor_vtbl_group PARAMS ((tree, tree));
|
||||
static void build_vtt PARAMS ((tree));
|
||||
static tree *build_vtt_inits PARAMS ((tree, tree, tree *));
|
||||
static tree *build_vtt_inits PARAMS ((tree, tree, tree *, tree *));
|
||||
static tree dfs_build_vtt_inits PARAMS ((tree, void *));
|
||||
static tree dfs_fixup_binfo_vtbls PARAMS ((tree, void *));
|
||||
|
||||
@ -635,7 +635,7 @@ get_vtable_name (type)
|
||||
/* Return an IDENTIFIER_NODE for the name of the virtual table table
|
||||
for TYPE. */
|
||||
|
||||
static tree
|
||||
tree
|
||||
get_vtt_name (type)
|
||||
tree type;
|
||||
{
|
||||
@ -3957,6 +3957,8 @@ build_clone (fn, name)
|
||||
DECL_PENDING_INLINE_P (clone) = 0;
|
||||
/* And it hasn't yet been deferred. */
|
||||
DECL_DEFERRED_FN (clone) = 0;
|
||||
/* There's no magic VTT parameter in the clone. */
|
||||
DECL_VTT_PARM (clone) = NULL_TREE;
|
||||
|
||||
/* The base-class destructor is not virtual. */
|
||||
if (name == base_dtor_identifier)
|
||||
@ -3981,6 +3983,10 @@ build_clone (fn, name)
|
||||
parmtypes = TREE_CHAIN (parmtypes);
|
||||
/* Skip the in-charge parameter. */
|
||||
parmtypes = TREE_CHAIN (parmtypes);
|
||||
/* If this is subobject constructor or destructor, add the vtt
|
||||
parameter. */
|
||||
if (DECL_NEEDS_VTT_PARM_P (clone))
|
||||
parmtypes = hash_tree_chain (vtt_parm_type, parmtypes);
|
||||
TREE_TYPE (clone)
|
||||
= build_cplus_method_type (basetype,
|
||||
TREE_TYPE (TREE_TYPE (clone)),
|
||||
@ -4002,6 +4008,18 @@ build_clone (fn, name)
|
||||
= TREE_CHAIN (TREE_CHAIN (DECL_ARGUMENTS (clone)));
|
||||
DECL_HAS_IN_CHARGE_PARM_P (clone) = 0;
|
||||
}
|
||||
|
||||
/* Add the VTT parameter. */
|
||||
if (DECL_NEEDS_VTT_PARM_P (clone))
|
||||
{
|
||||
tree parm;
|
||||
|
||||
parm = build_artificial_parm (vtt_parm_identifier,
|
||||
vtt_parm_type);
|
||||
TREE_CHAIN (parm) = TREE_CHAIN (DECL_ARGUMENTS (clone));
|
||||
TREE_CHAIN (DECL_ARGUMENTS (clone)) = parm;
|
||||
}
|
||||
|
||||
for (parms = DECL_ARGUMENTS (clone); parms; parms = TREE_CHAIN (parms))
|
||||
{
|
||||
DECL_CONTEXT (parms) = clone;
|
||||
@ -4063,7 +4081,7 @@ clone_function_decl (fn, update_method_vec_p)
|
||||
{
|
||||
my_friendly_assert (DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (fn), 20000411);
|
||||
|
||||
/* For each destructor, we need two variants: an in-charge
|
||||
/* For each destructor, we need three variants: an in-charge
|
||||
version, a not-in-charge version, and an in-charge deleting
|
||||
version. We clone the deleting version first because that
|
||||
means it will go second on the TYPE_METHODS list -- and that
|
||||
@ -6474,6 +6492,7 @@ build_vtt (t)
|
||||
tree inits;
|
||||
tree type;
|
||||
tree vtt;
|
||||
tree index;
|
||||
|
||||
/* Under the old ABI, we don't use VTTs. */
|
||||
if (!flag_new_abi)
|
||||
@ -6481,7 +6500,8 @@ build_vtt (t)
|
||||
|
||||
/* Build up the initializers for the VTT. */
|
||||
inits = NULL_TREE;
|
||||
build_vtt_inits (TYPE_BINFO (t), t, &inits);
|
||||
index = size_zero_node;
|
||||
build_vtt_inits (TYPE_BINFO (t), t, &inits, &index);
|
||||
|
||||
/* If we didn't need a VTT, we're done. */
|
||||
if (!inits)
|
||||
@ -6499,13 +6519,15 @@ build_vtt (t)
|
||||
|
||||
/* Recursively build the VTT-initializer for BINFO (which is in the
|
||||
hierarchy dominated by T). INITS points to the end of the
|
||||
initializer list to date. */
|
||||
initializer list to date. INDEX is the VTT index where the next
|
||||
element will be placed. */
|
||||
|
||||
static tree *
|
||||
build_vtt_inits (binfo, t, inits)
|
||||
build_vtt_inits (binfo, t, inits, index)
|
||||
tree binfo;
|
||||
tree t;
|
||||
tree *inits;
|
||||
tree *index;
|
||||
{
|
||||
int i;
|
||||
tree b;
|
||||
@ -6521,7 +6543,12 @@ build_vtt_inits (binfo, t, inits)
|
||||
VTT. */
|
||||
ctor_vtbl_p = !same_type_p (TREE_TYPE (binfo), t);
|
||||
if (ctor_vtbl_p)
|
||||
build_ctor_vtbl_group (binfo, t);
|
||||
{
|
||||
build_ctor_vtbl_group (binfo, t);
|
||||
|
||||
/* Record the offset in the VTT where this sub-VTT can be found. */
|
||||
BINFO_SUBVTT_INDEX (binfo) = *index;
|
||||
}
|
||||
|
||||
/* Add the address of the primary vtable for the complete object. */
|
||||
init = BINFO_VTABLE (binfo);
|
||||
@ -6529,20 +6556,24 @@ build_vtt_inits (binfo, t, inits)
|
||||
init = TREE_PURPOSE (init);
|
||||
*inits = build_tree_list (NULL_TREE, init);
|
||||
inits = &TREE_CHAIN (*inits);
|
||||
|
||||
BINFO_VPTR_INDEX (binfo) = *index;
|
||||
*index = size_binop (PLUS_EXPR, *index, TYPE_SIZE_UNIT (ptr_type_node));
|
||||
|
||||
/* Recursively add the secondary VTTs for non-virtual bases. */
|
||||
for (i = 0; i < BINFO_N_BASETYPES (binfo); ++i)
|
||||
{
|
||||
b = BINFO_BASETYPE (binfo, i);
|
||||
if (!TREE_VIA_VIRTUAL (b))
|
||||
inits = build_vtt_inits (BINFO_BASETYPE (binfo, i), t, inits);
|
||||
inits = build_vtt_inits (BINFO_BASETYPE (binfo, i), t, inits,
|
||||
index);
|
||||
}
|
||||
|
||||
|
||||
/* Add secondary virtual pointers for all subobjects of BINFO with
|
||||
either virtual bases or virtual functions overridden along a
|
||||
virtual path between the declaration and D, except subobjects
|
||||
that are non-virtual primary bases. */
|
||||
secondary_vptrs = build_tree_list (BINFO_TYPE (binfo), NULL_TREE);
|
||||
TREE_TYPE (secondary_vptrs) = *index;
|
||||
dfs_walk_real (binfo,
|
||||
dfs_build_vtt_inits,
|
||||
NULL,
|
||||
@ -6550,6 +6581,7 @@ build_vtt_inits (binfo, t, inits)
|
||||
secondary_vptrs);
|
||||
dfs_walk (binfo, dfs_fixup_binfo_vtbls, dfs_marked_real_bases_queue_p,
|
||||
BINFO_TYPE (binfo));
|
||||
*index = TREE_TYPE (secondary_vptrs);
|
||||
|
||||
/* The secondary vptrs come back in reverse order. After we reverse
|
||||
them, and add the INITS, the last init will be the first element
|
||||
@ -6571,7 +6603,7 @@ build_vtt_inits (binfo, t, inits)
|
||||
continue;
|
||||
|
||||
vbase = binfo_for_vbase (BINFO_TYPE (b), t);
|
||||
inits = build_vtt_inits (vbase, t, inits);
|
||||
inits = build_vtt_inits (vbase, t, inits, index);
|
||||
}
|
||||
|
||||
return inits;
|
||||
@ -6587,6 +6619,7 @@ dfs_build_vtt_inits (binfo, data)
|
||||
tree l;
|
||||
tree t;
|
||||
tree init;
|
||||
tree index;
|
||||
|
||||
l = (tree) data;
|
||||
t = TREE_PURPOSE (l);
|
||||
@ -6612,13 +6645,18 @@ dfs_build_vtt_inits (binfo, data)
|
||||
/* FIXME: Implement this. */
|
||||
;
|
||||
|
||||
/* Add the initializer for this secondary vptr. */
|
||||
/* Record the index where this secondary vptr can be found. */
|
||||
index = TREE_TYPE (l);
|
||||
BINFO_VPTR_INDEX (binfo) = index;
|
||||
TREE_TYPE (l) = size_binop (PLUS_EXPR, index,
|
||||
TYPE_SIZE_UNIT (ptr_type_node));
|
||||
|
||||
/* Add the initializer for the secondary vptr itself. */
|
||||
init = BINFO_VTABLE (binfo);
|
||||
if (TREE_CODE (init) == TREE_LIST)
|
||||
init = TREE_PURPOSE (init);
|
||||
|
||||
TREE_VALUE (l) = tree_cons (NULL_TREE, init, TREE_VALUE (l));
|
||||
|
||||
|
||||
return NULL_TREE;
|
||||
}
|
||||
|
||||
@ -6665,7 +6703,7 @@ build_ctor_vtbl_group (binfo, t)
|
||||
/* Build a version of VTBL (with the wrong type) for use in
|
||||
constructing the addresses of secondary vtables in the
|
||||
construction vtable group. */
|
||||
vtbl = build_vtable (BINFO_TYPE (binfo), id, vtable_entry_type);
|
||||
vtbl = build_vtable (BINFO_TYPE (binfo), id, ptr_type_node);
|
||||
list = build_tree_list (vtbl, NULL_TREE);
|
||||
accumulate_vtbl_inits (binfo, TYPE_BINFO (TREE_TYPE (binfo)),
|
||||
binfo, t, list);
|
||||
@ -6762,7 +6800,7 @@ dfs_accumulate_vtbl_inits (binfo, orig_binfo, rtti_binfo, t, l)
|
||||
if (BINFO_NEW_VTABLE_MARKED (binfo, t)
|
||||
/* We need a new vtable, even for a primary base, when we're
|
||||
building a construction vtable. */
|
||||
|| (ctor_vtbl_p && orig_binfo == rtti_binfo))
|
||||
|| (ctor_vtbl_p && CLASSTYPE_VFIELDS (BINFO_TYPE (binfo))))
|
||||
{
|
||||
tree vtbl;
|
||||
tree index;
|
||||
|
@ -530,6 +530,7 @@ enum cp_tree_index
|
||||
CPTI_DELTA_TYPE,
|
||||
CPTI_VTABLE_INDEX_TYPE,
|
||||
CPTI_CLEANUP_TYPE,
|
||||
CPTI_VTT_PARM_TYPE,
|
||||
|
||||
CPTI_TI_DESC_TYPE,
|
||||
CPTI_BLTN_DESC_TYPE,
|
||||
@ -578,6 +579,7 @@ enum cp_tree_index
|
||||
CPTI_DELTA2_IDENTIFIER,
|
||||
CPTI_DELTA_IDENTIFIER,
|
||||
CPTI_IN_CHARGE_IDENTIFIER,
|
||||
CPTI_VTT_PARM_IDENTIFIER,
|
||||
CPTI_INDEX_IDENTIFIER,
|
||||
CPTI_NELTS_IDENTIFIER,
|
||||
CPTI_THIS_IDENTIFIER,
|
||||
@ -690,6 +692,11 @@ extern tree cp_global_trees[CPTI_MAX];
|
||||
#define delta2_identifier cp_global_trees[CPTI_DELTA2_IDENTIFIER]
|
||||
#define delta_identifier cp_global_trees[CPTI_DELTA_IDENTIFIER]
|
||||
#define in_charge_identifier cp_global_trees[CPTI_IN_CHARGE_IDENTIFIER]
|
||||
|
||||
/* The name of the parameter that contains a pointer to the VTT to use
|
||||
for this subobject constructor or destructor. */
|
||||
#define vtt_parm_identifier cp_global_trees[CPTI_VTT_PARM_IDENTIFIER]
|
||||
|
||||
#define index_identifier cp_global_trees[CPTI_INDEX_IDENTIFIER]
|
||||
#define nelts_identifier cp_global_trees[CPTI_NELTS_IDENTIFIER]
|
||||
#define this_identifier cp_global_trees[CPTI_THIS_IDENTIFIER]
|
||||
@ -731,6 +738,10 @@ extern tree cp_global_trees[CPTI_MAX];
|
||||
/* The type of a destructor. */
|
||||
#define cleanup_type cp_global_trees[CPTI_CLEANUP_TYPE]
|
||||
|
||||
/* The type of the vtt parameter passed to subobject constructors and
|
||||
destructors. */
|
||||
#define vtt_parm_type cp_global_trees[CPTI_VTT_PARM_TYPE]
|
||||
|
||||
/* Global state. */
|
||||
|
||||
struct stmt_tree {
|
||||
@ -1755,6 +1766,14 @@ struct lang_type
|
||||
is primary *somewhere* in the hierarchy. */
|
||||
#define BINFO_VBASE_PRIMARY_P(NODE) TREE_LANG_FLAG_6 (NODE)
|
||||
|
||||
/* The index in the VTT where this subobject's sub-VTT can be found.
|
||||
NULL_TREE if there is no sub-VTT. */
|
||||
#define BINFO_SUBVTT_INDEX(NODE) TREE_VEC_ELT ((NODE), 8)
|
||||
|
||||
/* The index in the VTT where the vptr for this subobject can be
|
||||
found. NULL_TREE if there is no secondary vptr in the VTT. */
|
||||
#define BINFO_VPTR_INDEX(NODE) TREE_VEC_ELT ((NODE), 9)
|
||||
|
||||
/* Used by various search routines. */
|
||||
#define IDENTIFIER_MARKED(NODE) TREE_LANG_FLAG_0 (NODE)
|
||||
|
||||
@ -1884,6 +1903,9 @@ struct lang_decl
|
||||
/* In a FUNCTION_DECL, this is DECL_CLONED_FUNCTION. */
|
||||
tree cloned_function;
|
||||
|
||||
/* In a FUNCTION_DECL, this is VTT_PARM. */
|
||||
tree vtt_parm;
|
||||
|
||||
union
|
||||
{
|
||||
tree sorted_fields;
|
||||
@ -1972,6 +1994,25 @@ struct lang_decl
|
||||
#define DECL_CLONED_FUNCTION(NODE) \
|
||||
(DECL_LANG_SPECIFIC (NODE)->cloned_function)
|
||||
|
||||
/* In a maybe-in-charge constructor or destructor, this is the VTT
|
||||
parameter. It's not actually on the DECL_ARGUMENTS list. */
|
||||
#define DECL_VTT_PARM(NODE) \
|
||||
(DECL_LANG_SPECIFIC (NODE)->vtt_parm)
|
||||
|
||||
/* If there's a DECL_VTT_PARM, this is a magic variable that indicates
|
||||
whether or not the VTT parm should be used. In a subobject
|
||||
constructor, `true' is substituted for this value; in a complete
|
||||
object constructor, `false' is substituted instead. */
|
||||
#define DECL_USE_VTT_PARM(NODE) \
|
||||
(TREE_CHAIN (DECL_VTT_PARM (NODE)))
|
||||
|
||||
/* Non-zero if NODE is a FUNCTION_DECL for which a VTT parameter is
|
||||
required. */
|
||||
#define DECL_NEEDS_VTT_PARM_P(NODE) \
|
||||
(TYPE_USES_VIRTUAL_BASECLASSES (DECL_CONTEXT (NODE)) \
|
||||
&& (DECL_BASE_CONSTRUCTOR_P (NODE) \
|
||||
|| DECL_BASE_DESTRUCTOR_P (NODE)))
|
||||
|
||||
/* Non-zero if NODE is a user-defined conversion operator. */
|
||||
#define DECL_CONV_FN_P(NODE) \
|
||||
(IDENTIFIER_TYPENAME_P (DECL_NAME (NODE)))
|
||||
@ -3820,6 +3861,7 @@ extern void maybe_note_name_used_in_class PARAMS ((tree, tree));
|
||||
extern void note_name_declared_in_class PARAMS ((tree, tree));
|
||||
extern tree get_vtbl_decl_for_binfo PARAMS ((tree));
|
||||
extern tree in_charge_arg_for_name PARAMS ((tree));
|
||||
extern tree get_vtt_name PARAMS ((tree));
|
||||
|
||||
/* in cvt.c */
|
||||
extern tree convert_to_reference PARAMS ((tree, tree, int, int, tree));
|
||||
@ -4054,6 +4096,7 @@ extern void mark_used PARAMS ((tree));
|
||||
extern tree handle_class_head PARAMS ((tree, tree, tree));
|
||||
extern tree lookup_arg_dependent PARAMS ((tree, tree, tree));
|
||||
extern void finish_static_data_member_decl PARAMS ((tree, tree, tree, int));
|
||||
extern tree build_artificial_parm PARAMS ((tree, tree));
|
||||
|
||||
/* in parse.y */
|
||||
extern void cp_parse_init PARAMS ((void));
|
||||
@ -4303,7 +4346,6 @@ extern tree lookup_nested_tag PARAMS ((tree, tree));
|
||||
extern tree get_matching_virtual PARAMS ((tree, tree, int));
|
||||
extern void get_pure_virtuals PARAMS ((tree));
|
||||
extern tree init_vbase_pointers PARAMS ((tree, tree));
|
||||
extern void expand_indirect_vtbls_init PARAMS ((tree));
|
||||
extern void get_vbase_types PARAMS ((tree));
|
||||
extern void maybe_suppress_debug_info PARAMS ((tree));
|
||||
extern void note_debug_info_needed PARAMS ((tree));
|
||||
@ -4340,6 +4382,7 @@ extern tree unmarked_vtable_pathp PARAMS ((tree, void *));
|
||||
extern tree convert_pointer_to_vbase PARAMS ((tree, tree));
|
||||
extern tree find_vbase_instance PARAMS ((tree, tree));
|
||||
extern tree binfo_for_vbase PARAMS ((tree, tree));
|
||||
extern void fixup_all_virtual_upcast_offsets PARAMS ((tree));
|
||||
|
||||
/* in semantics.c */
|
||||
extern void finish_expr_stmt PARAMS ((tree));
|
||||
|
@ -3369,6 +3369,7 @@ duplicate_decls (newdecl, olddecl)
|
||||
DECL_VIRTUAL_P (newdecl) |= DECL_VIRTUAL_P (olddecl);
|
||||
DECL_NEEDS_FINAL_OVERRIDER_P (newdecl) |= DECL_NEEDS_FINAL_OVERRIDER_P (olddecl);
|
||||
DECL_THIS_STATIC (newdecl) |= DECL_THIS_STATIC (olddecl);
|
||||
DECL_VTT_PARM (newdecl) = DECL_VTT_PARM (olddecl);
|
||||
new_defines_function = DECL_INITIAL (newdecl) != NULL_TREE;
|
||||
|
||||
/* Optionally warn about more than one declaration for the same
|
||||
@ -6074,6 +6075,7 @@ initialize_predefined_identifiers ()
|
||||
{ "__pfn_or_delta2", &pfn_or_delta2_identifier, 0 },
|
||||
{ "_vptr", &vptr_identifier, 0 },
|
||||
{ "__cp_push_exception", &cp_push_exception_identifier, 0 },
|
||||
{ "__vtt_parm", &vtt_parm_identifier, 0 },
|
||||
{ NULL, NULL, 0 }
|
||||
};
|
||||
|
||||
@ -6325,6 +6327,7 @@ init_decl_processing ()
|
||||
const_ptr_type_node
|
||||
= build_pointer_type (build_qualified_type (void_type_node,
|
||||
TYPE_QUAL_CONST));
|
||||
vtt_parm_type = build_pointer_type (const_ptr_type_node);
|
||||
c_common_nodes_and_builtins (1, flag_no_builtin, flag_no_nonansi_builtin);
|
||||
lang_type_promotes_to = convert_type_from_ellipsis;
|
||||
|
||||
@ -8740,7 +8743,7 @@ grokfndecl (ctype, type, declarator, orig_declarator, virtualp, flags, quals,
|
||||
quals = NULL_TREE;
|
||||
}
|
||||
|
||||
if (IDENTIFIER_OPNAME_P (DECL_NAME (decl)))
|
||||
if (DECL_OVERLOADED_OPERATOR_P (decl))
|
||||
grok_op_properties (decl, virtualp, check < 0);
|
||||
|
||||
if (ctype && decl_function_context (decl))
|
||||
@ -14744,6 +14747,7 @@ lang_mark_tree (t)
|
||||
ggc_mark_tree (ld->befriending_classes);
|
||||
ggc_mark_tree (ld->saved_tree);
|
||||
ggc_mark_tree (ld->cloned_function);
|
||||
ggc_mark_tree (ld->vtt_parm);
|
||||
if (TREE_CODE (t) == TYPE_DECL)
|
||||
ggc_mark_tree (ld->u.sorted_fields);
|
||||
else if (TREE_CODE (t) == FUNCTION_DECL
|
||||
|
@ -924,6 +924,22 @@ grok_x_components (specs)
|
||||
break;
|
||||
}
|
||||
|
||||
/* Returns a PARM_DECL for a parameter of the indicated TYPE, with the
|
||||
indicated NAME. */
|
||||
|
||||
tree
|
||||
build_artificial_parm (name, type)
|
||||
tree name;
|
||||
tree type;
|
||||
{
|
||||
tree parm;
|
||||
|
||||
parm = build_decl (PARM_DECL, name, type);
|
||||
SET_DECL_ARTIFICIAL (parm);
|
||||
DECL_ARG_TYPE (parm) = type;
|
||||
return parm;
|
||||
}
|
||||
|
||||
/* Constructors for types with virtual baseclasses need an "in-charge" flag
|
||||
saying whether this constructor is responsible for initialization of
|
||||
virtual baseclasses or not. All destructors also need this "in-charge"
|
||||
@ -956,10 +972,7 @@ maybe_retrofit_in_chrg (fn)
|
||||
return;
|
||||
|
||||
/* First add it to DECL_ARGUMENTS... */
|
||||
parm = build_decl (PARM_DECL, in_charge_identifier, integer_type_node);
|
||||
/* Mark the artificial `__in_chrg' parameter as "artificial". */
|
||||
SET_DECL_ARTIFICIAL (parm);
|
||||
DECL_ARG_TYPE (parm) = integer_type_node;
|
||||
parm = build_artificial_parm (in_charge_identifier, integer_type_node);
|
||||
TREE_READONLY (parm) = 1;
|
||||
parms = DECL_ARGUMENTS (fn);
|
||||
TREE_CHAIN (parm) = TREE_CHAIN (parms);
|
||||
@ -978,6 +991,18 @@ maybe_retrofit_in_chrg (fn)
|
||||
|
||||
/* Now we've got the in-charge parameter. */
|
||||
DECL_HAS_IN_CHARGE_PARM_P (fn) = 1;
|
||||
|
||||
/* If this is a subobject constructor or destructor, our caller will
|
||||
pass us a pointer to our VTT. */
|
||||
if (flag_new_abi && TYPE_USES_VIRTUAL_BASECLASSES (DECL_CONTEXT (fn)))
|
||||
{
|
||||
DECL_VTT_PARM (fn) = build_artificial_parm (vtt_parm_identifier,
|
||||
vtt_parm_type);
|
||||
DECL_CONTEXT (DECL_VTT_PARM (fn)) = fn;
|
||||
DECL_USE_VTT_PARM (fn) = build_artificial_parm (NULL_TREE,
|
||||
boolean_type_node);
|
||||
DECL_CONTEXT (DECL_USE_VTT_PARM (fn)) = fn;
|
||||
}
|
||||
}
|
||||
|
||||
/* Classes overload their constituent function names automatically.
|
||||
@ -1032,12 +1057,9 @@ grokclassfn (ctype, function, flags, quals)
|
||||
assigned to. */
|
||||
this_quals |= TYPE_QUAL_CONST;
|
||||
qual_type = cp_build_qualified_type (type, this_quals);
|
||||
parm = build_decl (PARM_DECL, this_identifier, qual_type);
|
||||
parm = build_artificial_parm (this_identifier, qual_type);
|
||||
c_apply_type_quals_to_decl (this_quals, parm);
|
||||
|
||||
/* Mark the artificial `this' parameter as "artificial". */
|
||||
SET_DECL_ARTIFICIAL (parm);
|
||||
DECL_ARG_TYPE (parm) = type;
|
||||
/* We can make this a register, so long as we don't
|
||||
accidentally complain if someone tries to take its address. */
|
||||
DECL_REGISTER (parm) = 1;
|
||||
|
@ -53,6 +53,7 @@ static tree build_new_1 PARAMS ((tree));
|
||||
static tree get_cookie_size PARAMS ((tree));
|
||||
static tree build_dtor_call PARAMS ((tree, special_function_kind, int));
|
||||
static tree build_field_list PARAMS ((tree, tree, int *));
|
||||
static tree build_vtbl_address PARAMS ((tree));
|
||||
|
||||
/* Set up local variable for this file. MUST BE CALLED AFTER
|
||||
INIT_DECL_PROCESSING. */
|
||||
@ -172,7 +173,14 @@ initialize_vtbl_ptrs (addr)
|
||||
NULL, dfs_unmarked_real_bases_queue_p, list);
|
||||
dfs_walk (TYPE_BINFO (type), dfs_unmark,
|
||||
dfs_marked_real_bases_queue_p, type);
|
||||
expand_indirect_vtbls_init (addr);
|
||||
|
||||
/* If we're not using thunks, we may need to adjust the deltas in
|
||||
the vtable to handle virtual base classes correctly. When we are
|
||||
using thunks, we either use construction vtables (which are
|
||||
preloaded with the right answers) or nothing (in which case
|
||||
vitual function calls sometimes don't work right.) */
|
||||
if (TYPE_USES_VIRTUAL_BASECLASSES (type) && !flag_vtable_thunks)
|
||||
fixup_all_virtual_upcast_offsets (addr);
|
||||
}
|
||||
|
||||
/* Subroutine of emit_base_init. */
|
||||
@ -276,7 +284,7 @@ perform_member_init (member, init, explicit)
|
||||
|
||||
expr = build_component_ref (current_class_ref, member, NULL_TREE,
|
||||
explicit);
|
||||
expr = build_delete (type, expr, sfk_base_destructor,
|
||||
expr = build_delete (type, expr, sfk_complete_destructor,
|
||||
LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR, 0);
|
||||
|
||||
if (expr != error_mark_node)
|
||||
@ -726,6 +734,32 @@ emit_base_init ()
|
||||
}
|
||||
}
|
||||
|
||||
/* Returns the address of the vtable (i.e., the value that should be
|
||||
assigned to the vptr) for BINFO. */
|
||||
|
||||
static tree
|
||||
build_vtbl_address (binfo)
|
||||
tree binfo;
|
||||
{
|
||||
tree vtbl;
|
||||
|
||||
/* Figure out what vtable BINFO's vtable is based on, and mark it as
|
||||
used. */
|
||||
vtbl = get_vtbl_decl_for_binfo (binfo);
|
||||
assemble_external (vtbl);
|
||||
TREE_USED (vtbl) = 1;
|
||||
|
||||
/* Now compute the address to use when initializing the vptr. */
|
||||
vtbl = BINFO_VTABLE (binfo);
|
||||
if (TREE_CODE (vtbl) == VAR_DECL)
|
||||
{
|
||||
vtbl = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (vtbl)), vtbl);
|
||||
TREE_CONSTANT (vtbl) = 1;
|
||||
}
|
||||
|
||||
return vtbl;
|
||||
}
|
||||
|
||||
/* This code sets up the virtual function tables appropriate for
|
||||
the pointer DECL. It is a one-ply initialization.
|
||||
|
||||
@ -739,23 +773,40 @@ expand_virtual_init (binfo, decl)
|
||||
tree type = BINFO_TYPE (binfo);
|
||||
tree vtbl, vtbl_ptr;
|
||||
tree vtype, vtype_binfo;
|
||||
tree b;
|
||||
tree vtt_index;
|
||||
|
||||
/* Compute the location of the vtable. */
|
||||
vtype = DECL_CONTEXT (TYPE_VFIELD (type));
|
||||
vtype_binfo = get_binfo (vtype, TREE_TYPE (TREE_TYPE (decl)), 0);
|
||||
b = binfo_value (DECL_FIELD_CONTEXT (TYPE_VFIELD (type)), binfo);
|
||||
|
||||
/* Compute the initializer for vptr. */
|
||||
vtbl = build_vtbl_address (binfo);
|
||||
|
||||
/* Figure out what vtable BINFO's vtable is based on, and mark it as
|
||||
used. */
|
||||
vtbl = get_vtbl_decl_for_binfo (b);
|
||||
assemble_external (vtbl);
|
||||
TREE_USED (vtbl) = 1;
|
||||
/* Under the new ABI, we may get this vptr from a VTT, if this is a
|
||||
subobject constructor or subobject destructor. */
|
||||
vtt_index = BINFO_VPTR_INDEX (binfo);
|
||||
if (vtt_index)
|
||||
{
|
||||
tree vtbl2;
|
||||
tree vtt_parm;
|
||||
|
||||
/* Now compute the address to use when initializing the vptr. */
|
||||
vtbl = BINFO_VTABLE (b);
|
||||
if (TREE_CODE (vtbl) == VAR_DECL)
|
||||
vtbl = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (vtbl)), vtbl);
|
||||
/* Compute the value to use, when there's a VTT. */
|
||||
vtt_parm = DECL_VTT_PARM (current_function_decl);
|
||||
vtbl2 = build (PLUS_EXPR,
|
||||
TREE_TYPE (vtt_parm),
|
||||
vtt_parm,
|
||||
vtt_index);
|
||||
vtbl2 = build1 (INDIRECT_REF, TREE_TYPE (vtbl), vtbl2);
|
||||
|
||||
/* The actual initializer is the VTT value only in the subobject
|
||||
constructor. In maybe_clone_body we'll substitute NULL for
|
||||
the vtt_parm in the case of the non-subobject constructor. */
|
||||
vtbl = build (COND_EXPR,
|
||||
TREE_TYPE (vtbl),
|
||||
DECL_USE_VTT_PARM (current_function_decl),
|
||||
vtbl2,
|
||||
vtbl);
|
||||
}
|
||||
|
||||
/* Compute the location of the vtpr. */
|
||||
decl = convert_pointer_to_real (vtype_binfo, decl);
|
||||
|
@ -902,6 +902,10 @@ maybe_clone_body (fn)
|
||||
DECL_SOURCE_LINE (clone) = DECL_SOURCE_LINE (fn);
|
||||
DECL_INLINE (clone) = DECL_INLINE (fn);
|
||||
DECL_THIS_INLINE (clone) = DECL_THIS_INLINE (fn);
|
||||
DECL_COMDAT (clone) = DECL_COMDAT (fn);
|
||||
DECL_WEAK (clone) = DECL_WEAK (fn);
|
||||
DECL_ONE_ONLY (clone) = DECL_ONE_ONLY (fn);
|
||||
DECL_SECTION_NAME (clone) = DECL_SECTION_NAME (fn);
|
||||
|
||||
/* Start processing the function. */
|
||||
push_to_top_level ();
|
||||
@ -934,7 +938,31 @@ maybe_clone_body (fn)
|
||||
in_charge = in_charge_arg_for_name (DECL_NAME (clone));
|
||||
splay_tree_insert (id.decl_map,
|
||||
(splay_tree_key) parm,
|
||||
(splay_tree_key) in_charge);
|
||||
(splay_tree_value) in_charge);
|
||||
|
||||
/* For a subobject constructor or destructor, the next
|
||||
argument is the VTT parameter. Remap the VTT_PARM
|
||||
from the CLONE to this parameter. */
|
||||
if (DECL_NEEDS_VTT_PARM_P (clone))
|
||||
{
|
||||
splay_tree_insert (id.decl_map,
|
||||
(splay_tree_key) DECL_VTT_PARM (fn),
|
||||
(splay_tree_value) clone_parm);
|
||||
splay_tree_insert (id.decl_map,
|
||||
(splay_tree_key) DECL_USE_VTT_PARM (fn),
|
||||
(splay_tree_value) boolean_true_node);
|
||||
clone_parm = TREE_CHAIN (clone_parm);
|
||||
}
|
||||
/* Otherwise, map the VTT parameter to `NULL'. */
|
||||
else if (DECL_VTT_PARM (fn))
|
||||
{
|
||||
splay_tree_insert (id.decl_map,
|
||||
(splay_tree_key) DECL_VTT_PARM (fn),
|
||||
(splay_tree_value) null_pointer_node);
|
||||
splay_tree_insert (id.decl_map,
|
||||
(splay_tree_key) DECL_USE_VTT_PARM (fn),
|
||||
(splay_tree_value) boolean_false_node);
|
||||
}
|
||||
}
|
||||
/* Map other parameters to their equivalents in the cloned
|
||||
function. */
|
||||
|
@ -144,7 +144,6 @@ static int protected_accessible_p PARAMS ((tree, tree, tree));
|
||||
static int friend_accessible_p PARAMS ((tree, tree, tree));
|
||||
static void setup_class_bindings PARAMS ((tree, int));
|
||||
static int template_self_reference_p PARAMS ((tree, tree));
|
||||
static void fixup_all_virtual_upcast_offsets PARAMS ((tree, tree));
|
||||
static tree get_shared_vbase_if_not_primary PARAMS ((tree, void *));
|
||||
static tree dfs_find_vbase_instance PARAMS ((tree, void *));
|
||||
static tree dfs_get_pure_virtuals PARAMS ((tree, void *));
|
||||
@ -2770,14 +2769,14 @@ fixup_virtual_upcast_offsets (real_binfo, binfo, init_self, can_elide, addr, ori
|
||||
/* Fixup all the virtual upcast offsets for TYPE. DECL_PTR is the
|
||||
address of the sub-object being initialized. */
|
||||
|
||||
static void
|
||||
fixup_all_virtual_upcast_offsets (type, decl_ptr)
|
||||
tree type;
|
||||
void
|
||||
fixup_all_virtual_upcast_offsets (decl_ptr)
|
||||
tree decl_ptr;
|
||||
{
|
||||
tree if_stmt;
|
||||
tree in_charge_node;
|
||||
tree vbases;
|
||||
tree type;
|
||||
|
||||
/* Only tweak the vtables if we're in charge. */
|
||||
in_charge_node = current_in_charge_parm;
|
||||
@ -2791,6 +2790,7 @@ fixup_all_virtual_upcast_offsets (type, decl_ptr)
|
||||
|
||||
/* Iterate through the virtual bases, fixing up the upcast offset
|
||||
for each one. */
|
||||
type = TREE_TYPE (TREE_TYPE (decl_ptr));
|
||||
for (vbases = CLASSTYPE_VBASECLASSES (type);
|
||||
vbases;
|
||||
vbases = TREE_CHAIN (vbases))
|
||||
@ -2820,22 +2820,6 @@ fixup_all_virtual_upcast_offsets (type, decl_ptr)
|
||||
finish_if_stmt ();
|
||||
}
|
||||
|
||||
/* Generate the code needed to initialize all the virtual function
|
||||
table slots of all the virtual baseclasses. ADDR points to the
|
||||
address of the complete object we are initializing. */
|
||||
|
||||
void
|
||||
expand_indirect_vtbls_init (addr)
|
||||
tree addr;
|
||||
{
|
||||
tree type;
|
||||
|
||||
type = TREE_TYPE (TREE_TYPE (addr));
|
||||
|
||||
if (TYPE_USES_VIRTUAL_BASECLASSES (type))
|
||||
fixup_all_virtual_upcast_offsets (type, addr);
|
||||
}
|
||||
|
||||
/* get virtual base class types.
|
||||
This adds type to the vbase_types list in reverse dfs order.
|
||||
Ordering is very important, so don't change it. */
|
||||
|
@ -1257,15 +1257,15 @@ setup_vtbl_ptr ()
|
||||
tree compound_stmt;
|
||||
int saved_cfnd;
|
||||
|
||||
/* If the dtor is empty, and we know there is not possible way we
|
||||
could use any vtable entries, before they are possibly set by
|
||||
a base class dtor, we don't have to setup the vtables, as we
|
||||
know that any base class dtoring will set up any vtables it
|
||||
needs. We avoid MI, because one base class dtor can do a
|
||||
/* If the dtor is empty, and we know there is not any possible
|
||||
way we could use any vtable entries, before they are possibly
|
||||
set by a base class dtor, we don't have to setup the vtables,
|
||||
as we know that any base class dtor will set up any vtables
|
||||
it needs. We avoid MI, because one base class dtor can do a
|
||||
virtual dispatch to an overridden function that would need to
|
||||
have a non-related vtable set up, we cannot avoid setting up
|
||||
vtables in that case. We could change this to see if there is
|
||||
just one vtable. */
|
||||
vtables in that case. We could change this to see if there
|
||||
is just one vtable. */
|
||||
if_stmt = begin_if_stmt ();
|
||||
|
||||
/* If it is not safe to avoid setting up the vtables, then
|
||||
|
@ -847,7 +847,7 @@ make_binfo (offset, binfo, vtable, virtuals)
|
||||
tree offset, binfo;
|
||||
tree vtable, virtuals;
|
||||
{
|
||||
tree new_binfo = make_tree_vec (8);
|
||||
tree new_binfo = make_tree_vec (10);
|
||||
tree type;
|
||||
|
||||
if (TREE_CODE (binfo) == TREE_VEC)
|
||||
|
51
gcc/testsuite/g++.old-deja/g++.other/vbase1.C
Normal file
51
gcc/testsuite/g++.old-deja/g++.other/vbase1.C
Normal file
@ -0,0 +1,51 @@
|
||||
// Origin: Mark Mitchell <mark@codesourcery.com>
|
||||
// Special g++ Options: -w
|
||||
|
||||
int result;
|
||||
|
||||
struct A {
|
||||
A ();
|
||||
|
||||
int i;
|
||||
};
|
||||
|
||||
A* ap;
|
||||
|
||||
A::A ()
|
||||
{
|
||||
ap = this;
|
||||
}
|
||||
|
||||
struct B : virtual public A
|
||||
{
|
||||
B ();
|
||||
~B ();
|
||||
|
||||
int j;
|
||||
};
|
||||
|
||||
B::B () {
|
||||
if ((A*) this != ap)
|
||||
result = 1;
|
||||
}
|
||||
|
||||
B::~B () {
|
||||
if ((A*) this != ap)
|
||||
result = 1;
|
||||
}
|
||||
|
||||
struct C : public B {
|
||||
};
|
||||
|
||||
struct D : public C, public B
|
||||
{
|
||||
};
|
||||
|
||||
int main ()
|
||||
{
|
||||
{
|
||||
D d;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
36
gcc/testsuite/g++.old-deja/g++.other/vbase2.C
Normal file
36
gcc/testsuite/g++.old-deja/g++.other/vbase2.C
Normal file
@ -0,0 +1,36 @@
|
||||
// Origin: Mark Mitchell <mark@codesourcery.com>
|
||||
|
||||
int i;
|
||||
|
||||
struct A
|
||||
{
|
||||
~A ();
|
||||
};
|
||||
|
||||
A::~A () {
|
||||
i = 1;
|
||||
}
|
||||
|
||||
struct B : virtual public A {
|
||||
};
|
||||
|
||||
struct C {
|
||||
C ();
|
||||
|
||||
B b;
|
||||
};
|
||||
|
||||
C::C () {
|
||||
throw 3;
|
||||
}
|
||||
|
||||
int main ()
|
||||
{
|
||||
try {
|
||||
C c;
|
||||
} catch (...) {
|
||||
}
|
||||
|
||||
if (i != 1)
|
||||
return 1;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user