This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
C++ PATCH: VTT implementation
- To: gcc-patches at gcc dot gnu dot org
- Subject: C++ PATCH: VTT implementation
- From: Mark Mitchell <mark at codesourcery dot com>
- Date: Thu, 25 May 2000 16:42:49 -0700
- Reply-to: mark at codesourcery dot com
This patch implements VTTs (i.e., the fix for the thunks bug) for the
new ABI -- minus one minor optimization that I'll get to relatively
shortly. VTTs were probably the most major remaining bit of
functionality, except for name-mangling (which Alex has mostly
completed; I'll be making a few additions and checking that in while
Alex implements the ABI all over again in another compiler...), and
exception-handling (which I understand will be contributed soon).
In addition, I came across an interesting code-generation bug that
dates back to (at least) EGCS 1.1:
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;
}
Here, we were not destroying the A subobject when C's constructor
threw an exception. Oops. Fixed, and test included in the patch.
--
Mark Mitchell mark@codesourcery.com
CodeSourcery, LLC http://www.codesourcery.com
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.
Index: testsuite/g++.old-deja/g++.other/vbase1.C
===================================================================
RCS file: vbase1.C
diff -N vbase1.C
*** /dev/null Tue May 5 13:32:27 1998
--- vbase1.C Thu May 25 16:15:14 2000
***************
*** 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;
+ }
Index: testsuite/g++.old-deja/g++.other/vbase2.C
===================================================================
RCS file: vbase2.C
diff -N vbase2.C
*** /dev/null Tue May 5 13:32:27 1998
--- vbase2.C Thu May 25 16:15:14 2000
***************
*** 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;
+ }
Index: cp/call.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/call.c,v
retrieving revision 1.215
diff -c -p -r1.215 call.c
*** call.c 2000/05/24 22:56:53 1.215
--- call.c 2000/05/25 23:14:45
*************** build_new_method_call (instance, name, a
*** 4321,4326 ****
--- 4321,4352 ----
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;
Index: cp/class.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/class.c,v
retrieving revision 1.306
diff -c -p -r1.306 class.c
*** class.c 2000/05/24 06:15:02 1.306
--- class.c 2000/05/25 23:14:50
*************** static void update_vtable_entry_for_fn P
*** 181,187 ****
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 dfs_build_vtt_inits PARAMS ((tree, void *));
static tree dfs_fixup_binfo_vtbls PARAMS ((tree, void *));
--- 181,187 ----
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 *, tree *));
static tree dfs_build_vtt_inits PARAMS ((tree, void *));
static tree dfs_fixup_binfo_vtbls PARAMS ((tree, void *));
*************** get_vtable_name (type)
*** 635,641 ****
/* Return an IDENTIFIER_NODE for the name of the virtual table table
for TYPE. */
! static tree
get_vtt_name (type)
tree type;
{
--- 635,641 ----
/* Return an IDENTIFIER_NODE for the name of the virtual table table
for TYPE. */
! tree
get_vtt_name (type)
tree type;
{
*************** build_clone (fn, name)
*** 3957,3962 ****
--- 3957,3964 ----
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)
*************** build_clone (fn, name)
*** 3981,3986 ****
--- 3983,3992 ----
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)),
*************** build_clone (fn, name)
*** 4002,4007 ****
--- 4008,4025 ----
= 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;
*************** clone_function_decl (fn, update_method_v
*** 4063,4069 ****
{
my_friendly_assert (DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (fn), 20000411);
! /* For each destructor, we need two 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
--- 4081,4087 ----
{
my_friendly_assert (DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (fn), 20000411);
! /* 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
*************** build_vtt (t)
*** 6474,6479 ****
--- 6492,6498 ----
tree inits;
tree type;
tree vtt;
+ tree index;
/* Under the old ABI, we don't use VTTs. */
if (!flag_new_abi)
*************** build_vtt (t)
*** 6481,6487 ****
/* Build up the initializers for the VTT. */
inits = NULL_TREE;
! build_vtt_inits (TYPE_BINFO (t), t, &inits);
/* If we didn't need a VTT, we're done. */
if (!inits)
--- 6500,6507 ----
/* Build up the initializers for the VTT. */
inits = NULL_TREE;
! 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)
*************** build_vtt (t)
*** 6499,6511 ****
/* 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. */
static tree *
! build_vtt_inits (binfo, t, inits)
tree binfo;
tree t;
tree *inits;
{
int i;
tree b;
--- 6519,6533 ----
/* 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. INDEX is the VTT index where the next
! element will be placed. */
static tree *
! build_vtt_inits (binfo, t, inits, index)
tree binfo;
tree t;
tree *inits;
+ tree *index;
{
int i;
tree b;
*************** build_vtt_inits (binfo, t, inits)
*** 6521,6548 ****
VTT. */
ctor_vtbl_p = !same_type_p (TREE_TYPE (binfo), t);
if (ctor_vtbl_p)
! build_ctor_vtbl_group (binfo, t);
/* Add the address of the primary vtable for the complete object. */
init = BINFO_VTABLE (binfo);
if (TREE_CODE (init) == TREE_LIST)
init = TREE_PURPOSE (init);
*inits = build_tree_list (NULL_TREE, init);
inits = &TREE_CHAIN (*inits);
!
/* 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);
}
!
/* 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);
dfs_walk_real (binfo,
dfs_build_vtt_inits,
NULL,
--- 6543,6579 ----
VTT. */
ctor_vtbl_p = !same_type_p (TREE_TYPE (binfo), t);
if (ctor_vtbl_p)
! {
! 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);
if (TREE_CODE (init) == TREE_LIST)
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,
! 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,
*************** build_vtt_inits (binfo, t, inits)
*** 6550,6555 ****
--- 6581,6587 ----
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
*************** build_vtt_inits (binfo, t, inits)
*** 6571,6577 ****
continue;
vbase = binfo_for_vbase (BINFO_TYPE (b), t);
! inits = build_vtt_inits (vbase, t, inits);
}
return inits;
--- 6603,6609 ----
continue;
vbase = binfo_for_vbase (BINFO_TYPE (b), t);
! inits = build_vtt_inits (vbase, t, inits, index);
}
return inits;
*************** dfs_build_vtt_inits (binfo, data)
*** 6587,6592 ****
--- 6619,6625 ----
tree l;
tree t;
tree init;
+ tree index;
l = (tree) data;
t = TREE_PURPOSE (l);
*************** dfs_build_vtt_inits (binfo, data)
*** 6612,6624 ****
/* FIXME: Implement this. */
;
! /* Add the initializer for this secondary vptr. */
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;
}
--- 6645,6662 ----
/* FIXME: Implement this. */
;
! /* 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;
}
*************** build_ctor_vtbl_group (binfo, t)
*** 6665,6671 ****
/* 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);
list = build_tree_list (vtbl, NULL_TREE);
accumulate_vtbl_inits (binfo, TYPE_BINFO (TREE_TYPE (binfo)),
binfo, t, list);
--- 6703,6709 ----
/* 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, ptr_type_node);
list = build_tree_list (vtbl, NULL_TREE);
accumulate_vtbl_inits (binfo, TYPE_BINFO (TREE_TYPE (binfo)),
binfo, t, list);
*************** dfs_accumulate_vtbl_inits (binfo, orig_b
*** 6762,6768 ****
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))
{
tree vtbl;
tree index;
--- 6800,6806 ----
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 && CLASSTYPE_VFIELDS (BINFO_TYPE (binfo))))
{
tree vtbl;
tree index;
Index: cp/cp-tree.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/cp-tree.h,v
retrieving revision 1.460
diff -c -p -r1.460 cp-tree.h
*** cp-tree.h 2000/05/24 22:56:53 1.460
--- cp-tree.h 2000/05/25 23:14:53
*************** enum cp_tree_index
*** 530,535 ****
--- 530,536 ----
CPTI_DELTA_TYPE,
CPTI_VTABLE_INDEX_TYPE,
CPTI_CLEANUP_TYPE,
+ CPTI_VTT_PARM_TYPE,
CPTI_TI_DESC_TYPE,
CPTI_BLTN_DESC_TYPE,
*************** enum cp_tree_index
*** 578,583 ****
--- 579,585 ----
CPTI_DELTA2_IDENTIFIER,
CPTI_DELTA_IDENTIFIER,
CPTI_IN_CHARGE_IDENTIFIER,
+ CPTI_VTT_PARM_IDENTIFIER,
CPTI_INDEX_IDENTIFIER,
CPTI_NELTS_IDENTIFIER,
CPTI_THIS_IDENTIFIER,
*************** extern tree cp_global_trees[CPTI_MAX];
*** 690,695 ****
--- 692,702 ----
#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]
*************** extern tree cp_global_trees[CPTI_MAX];
*** 731,736 ****
--- 738,747 ----
/* 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 {
*************** struct lang_type
*** 1755,1760 ****
--- 1766,1779 ----
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)
*************** struct lang_decl
*** 1884,1889 ****
--- 1903,1911 ----
/* 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;
*************** struct lang_decl
*** 1972,1977 ****
--- 1994,2018 ----
#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)))
*************** extern void maybe_note_name_used_in_clas
*** 3820,3825 ****
--- 3861,3867 ----
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));
*************** extern void mark_used PARAMS ((tree))
*** 4054,4059 ****
--- 4096,4102 ----
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));
*************** extern tree lookup_nested_tag PARAMS (
*** 4303,4309 ****
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));
--- 4346,4351 ----
*************** extern tree unmarked_vtable_pathp
*** 4340,4345 ****
--- 4382,4388 ----
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));
Index: cp/decl.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/decl.c,v
retrieving revision 1.611
diff -c -p -r1.611 decl.c
*** decl.c 2000/05/24 22:56:53 1.611
--- decl.c 2000/05/25 23:15:03
*************** duplicate_decls (newdecl, olddecl)
*** 3369,3374 ****
--- 3369,3375 ----
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
*************** initialize_predefined_identifiers ()
*** 6074,6079 ****
--- 6075,6081 ----
{ "__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 }
};
*************** init_decl_processing ()
*** 6325,6330 ****
--- 6327,6333 ----
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;
*************** grokfndecl (ctype, type, declarator, ori
*** 8740,8746 ****
quals = NULL_TREE;
}
! if (IDENTIFIER_OPNAME_P (DECL_NAME (decl)))
grok_op_properties (decl, virtualp, check < 0);
if (ctype && decl_function_context (decl))
--- 8743,8749 ----
quals = NULL_TREE;
}
! if (DECL_OVERLOADED_OPERATOR_P (decl))
grok_op_properties (decl, virtualp, check < 0);
if (ctype && decl_function_context (decl))
*************** lang_mark_tree (t)
*** 14744,14749 ****
--- 14747,14753 ----
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
Index: cp/decl2.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/decl2.c,v
retrieving revision 1.353
diff -c -p -r1.353 decl2.c
*** decl2.c 2000/05/24 22:56:53 1.353
--- decl2.c 2000/05/25 23:15:06
*************** grok_x_components (specs)
*** 924,929 ****
--- 924,945 ----
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"
*************** maybe_retrofit_in_chrg (fn)
*** 956,965 ****
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;
TREE_READONLY (parm) = 1;
parms = DECL_ARGUMENTS (fn);
TREE_CHAIN (parm) = TREE_CHAIN (parms);
--- 972,978 ----
return;
/* First add it to DECL_ARGUMENTS... */
! parm = build_artificial_parm (in_charge_identifier, integer_type_node);
TREE_READONLY (parm) = 1;
parms = DECL_ARGUMENTS (fn);
TREE_CHAIN (parm) = TREE_CHAIN (parms);
*************** maybe_retrofit_in_chrg (fn)
*** 978,983 ****
--- 991,1008 ----
/* 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.
*************** grokclassfn (ctype, function, flags, qua
*** 1032,1043 ****
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);
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;
--- 1057,1065 ----
assigned to. */
this_quals |= TYPE_QUAL_CONST;
qual_type = cp_build_qualified_type (type, this_quals);
! parm = build_artificial_parm (this_identifier, qual_type);
c_apply_type_quals_to_decl (this_quals, parm);
/* 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;
Index: cp/init.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/init.c,v
retrieving revision 1.193
diff -c -p -r1.193 init.c
*** init.c 2000/05/24 22:56:54 1.193
--- init.c 2000/05/25 23:15:08
*************** static tree build_new_1 PARAMS ((tree));
*** 53,58 ****
--- 53,59 ----
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. */
*************** initialize_vtbl_ptrs (addr)
*** 172,178 ****
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);
}
/* Subroutine of emit_base_init. */
--- 173,186 ----
NULL, dfs_unmarked_real_bases_queue_p, list);
dfs_walk (TYPE_BINFO (type), dfs_unmark,
dfs_marked_real_bases_queue_p, type);
!
! /* 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. */
*************** perform_member_init (member, init, expli
*** 276,282 ****
expr = build_component_ref (current_class_ref, member, NULL_TREE,
explicit);
! expr = build_delete (type, expr, sfk_base_destructor,
LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR, 0);
if (expr != error_mark_node)
--- 284,290 ----
expr = build_component_ref (current_class_ref, member, NULL_TREE,
explicit);
! expr = build_delete (type, expr, sfk_complete_destructor,
LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR, 0);
if (expr != error_mark_node)
*************** emit_base_init ()
*** 726,731 ****
--- 734,765 ----
}
}
+ /* 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.
*************** expand_virtual_init (binfo, decl)
*** 739,761 ****
tree type = BINFO_TYPE (binfo);
tree vtbl, vtbl_ptr;
tree vtype, vtype_binfo;
! tree b;
/* 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 location of the vtpr. */
decl = convert_pointer_to_real (vtype_binfo, decl);
--- 773,812 ----
tree type = BINFO_TYPE (binfo);
tree vtbl, vtbl_ptr;
tree vtype, vtype_binfo;
! 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);
!
! /* 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);
Index: cp/optimize.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/optimize.c,v
retrieving revision 1.33
diff -c -p -r1.33 optimize.c
*** optimize.c 2000/05/23 06:31:16 1.33
--- optimize.c 2000/05/25 23:15:08
*************** maybe_clone_body (fn)
*** 902,907 ****
--- 902,911 ----
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 ();
*************** maybe_clone_body (fn)
*** 934,940 ****
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);
}
/* Map other parameters to their equivalents in the cloned
function. */
--- 938,968 ----
in_charge = in_charge_arg_for_name (DECL_NAME (clone));
splay_tree_insert (id.decl_map,
(splay_tree_key) parm,
! (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. */
Index: cp/search.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/search.c,v
retrieving revision 1.180
diff -c -p -r1.180 search.c
*** search.c 2000/05/22 01:08:46 1.180
--- search.c 2000/05/25 23:15:10
*************** static int protected_accessible_p PARAMS
*** 144,150 ****
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 *));
--- 144,149 ----
*************** fixup_virtual_upcast_offsets (real_binfo
*** 2770,2783 ****
/* 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;
tree decl_ptr;
{
tree if_stmt;
tree in_charge_node;
tree vbases;
/* Only tweak the vtables if we're in charge. */
in_charge_node = current_in_charge_parm;
--- 2769,2782 ----
/* Fixup all the virtual upcast offsets for TYPE. DECL_PTR is the
address of the sub-object being initialized. */
! 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;
*************** fixup_all_virtual_upcast_offsets (type,
*** 2791,2796 ****
--- 2790,2796 ----
/* 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))
*************** fixup_all_virtual_upcast_offsets (type,
*** 2818,2839 ****
/* Close out the if-statement. */
finish_then_clause (if_stmt);
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.
--- 2818,2823 ----
Index: cp/semantics.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/semantics.c,v
retrieving revision 1.144
diff -c -p -r1.144 semantics.c
*** semantics.c 2000/05/24 18:48:08 1.144
--- semantics.c 2000/05/25 23:15:12
*************** setup_vtbl_ptr ()
*** 1257,1271 ****
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
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. */
if_stmt = begin_if_stmt ();
/* If it is not safe to avoid setting up the vtables, then
--- 1257,1271 ----
tree compound_stmt;
int saved_cfnd;
! /* 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. */
if_stmt = begin_if_stmt ();
/* If it is not safe to avoid setting up the vtables, then
Index: cp/tree.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/tree.c,v
retrieving revision 1.197
diff -c -p -r1.197 tree.c
*** tree.c 2000/05/09 19:55:51 1.197
--- tree.c 2000/05/25 23:15:13
*************** make_binfo (offset, binfo, vtable, virtu
*** 847,853 ****
tree offset, binfo;
tree vtable, virtuals;
{
! tree new_binfo = make_tree_vec (8);
tree type;
if (TREE_CODE (binfo) == TREE_VEC)
--- 847,853 ----
tree offset, binfo;
tree vtable, virtuals;
{
! tree new_binfo = make_tree_vec (10);
tree type;
if (TREE_CODE (binfo) == TREE_VEC)