aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorMark Mitchell <mark@codesourcery.com>2000-05-25 23:27:18 +0000
committerMark Mitchell <mmitchel@gcc.gnu.org>2000-05-25 23:27:18 +0000
commit3ec6bad360a051793659af054b5ecf41318a2a8b (patch)
treedb2ec4264a1fd32d8fe39dfd89a501b714b874ca /gcc
parenta0ee3b83359ace5b2fb7cd0d400d99472e5738c3 (diff)
downloadgcc-3ec6bad360a051793659af054b5ecf41318a2a8b.zip
gcc-3ec6bad360a051793659af054b5ecf41318a2a8b.tar.gz
gcc-3ec6bad360a051793659af054b5ecf41318a2a8b.tar.bz2
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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog50
-rw-r--r--gcc/cp/call.c26
-rw-r--r--gcc/cp/class.c70
-rw-r--r--gcc/cp/cp-tree.h45
-rw-r--r--gcc/cp/decl.c6
-rw-r--r--gcc/cp/decl2.c38
-rw-r--r--gcc/cp/init.c81
-rw-r--r--gcc/cp/optimize.c30
-rw-r--r--gcc/cp/search.c24
-rw-r--r--gcc/cp/semantics.c14
-rw-r--r--gcc/cp/tree.c2
-rw-r--r--gcc/testsuite/g++.old-deja/g++.other/vbase1.C51
-rw-r--r--gcc/testsuite/g++.old-deja/g++.other/vbase2.C36
13 files changed, 403 insertions, 70 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index db9cb15a..33d02be 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -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
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 93feadd..a034f52 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -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;
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index b86bac4..d865fba 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -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;
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 6080abd..d935c35 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -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));
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 05c17f6..5704a17 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -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
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index 5b72098..315e3c8 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -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;
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index 7d6892e..cc5be91 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -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);
-
- /* 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;
-
- /* 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 initializer for vptr. */
+ vtbl = build_vtbl_address (binfo);
+
+ /* 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;
+
+ /* 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);
diff --git a/gcc/cp/optimize.c b/gcc/cp/optimize.c
index b7711d6..52292ff 100644
--- a/gcc/cp/optimize.c
+++ b/gcc/cp/optimize.c
@@ -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. */
diff --git a/gcc/cp/search.c b/gcc/cp/search.c
index bebca05..1160cd4 100644
--- a/gcc/cp/search.c
+++ b/gcc/cp/search.c
@@ -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. */
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index dbeb7f1..77728ba 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -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
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index 078558e..646a892 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -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)
diff --git a/gcc/testsuite/g++.old-deja/g++.other/vbase1.C b/gcc/testsuite/g++.old-deja/g++.other/vbase1.C
new file mode 100644
index 0000000..99a3867
--- /dev/null
+++ b/gcc/testsuite/g++.old-deja/g++.other/vbase1.C
@@ -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;
+}
diff --git a/gcc/testsuite/g++.old-deja/g++.other/vbase2.C b/gcc/testsuite/g++.old-deja/g++.other/vbase2.C
new file mode 100644
index 0000000..2f15249
--- /dev/null
+++ b/gcc/testsuite/g++.old-deja/g++.other/vbase2.C
@@ -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;
+}