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:
Mark Mitchell 2000-05-25 23:27:18 +00:00 committed by Mark Mitchell
parent a0ee3b8335
commit 3ec6bad360
13 changed files with 401 additions and 68 deletions

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -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));

View File

@ -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

View File

@ -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;

View File

@ -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);

View File

@ -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. */

View File

@ -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. */

View File

@ -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

View File

@ -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)

View 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;
}

View 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;
}