This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
C++ PATCH: VTTs
- To: gcc-patches at gcc dot gnu dot org
- Subject: C++ PATCH: VTTs
- From: Mark Mitchell <mark at codesourcery dot com>
- Date: Wed, 28 Jun 2000 13:41:34 -0700
- Organization: CodeSourcery, LLC
Alex found some bugs in the new-ABI VTT implementation that are fixed
by this patch. I also fixed a new-ABI mangling issue with template
template parameters.
Tested on i686-pc-linux-gnu with both old and new ABIs.
--
Mark Mitchell mark@codesourcery.com
CodeSourcery, LLC http://www.codesourcery.com
2000-06-28 Mark Mitchell <mark@codesourcery.com>
* cp-tree.h (CLEAR_BINFO_NEW_VTABLE_MARKED): Remove.
* class.c (update_vtable_entry_for_fn): Correct logic for deciding
where to emit thunks.
(build_vtt): Adjust call to build_vtt_inits.
(build_vtt_inits): Add parameter to indicate whether or not
sub-VTTs for virtual bases should be included. Adjust handling of
construction vtables.
(get_matching_base): New function.
(dfs_build_vtt_inits): Rename to ...
(dfs_build_secondary_vptr_vtt_inits): Adjust handling of
construction vtables.
(dfs_fixup_binfo_vtbls): Likewise.
(build_ctor_vtbl_groups): Build construction vtables for virtual
bases, too.
(accumulate_vtbl_inits): Tweak logic for deciding whether or not
to build construction vtbls.
(dfs_accumulate_vtbl_inits): Adjust handling of
construction vtables.
* pt.c (tsubst, case TEMPLATE_TEMPLATE_PARM): Handle cv-qualified
types correctly.
Index: class.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/class.c,v
retrieving revision 1.322
diff -c -p -r1.322 class.c
*** class.c 2000/06/23 01:14:37 1.322
--- class.c 2000/06/28 20:37:38
*************** static void update_vtable_entry_for_fn P
*** 190,199 ****
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 *));
static int indirect_primary_base_p PARAMS ((tree, tree));
/* Variables shared between class.c and call.c. */
--- 190,200 ----
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, int, tree *, tree *));
! static tree dfs_build_secondary_vptr_vtt_inits PARAMS ((tree, void *));
static tree dfs_fixup_binfo_vtbls PARAMS ((tree, void *));
static int indirect_primary_base_p PARAMS ((tree, tree));
+ static tree get_matching_base PARAMS ((tree, tree));
/* Variables shared between class.c and call.c. */
*************** update_vtable_entry_for_fn (t, binfo, fn
*** 2643,2649 ****
/* Assume that we will produce a thunk that convert all the way to
the final overrider, and not to an intermediate virtual base. */
! virtual_base = NULL_TREE;
/* Assume that we will always generate thunks with the vtables that
reference them. */
--- 2644,2650 ----
/* Assume that we will produce a thunk that convert all the way to
the final overrider, and not to an intermediate virtual base. */
! virtual_base = NULL_TREE;
/* Assume that we will always generate thunks with the vtables that
reference them. */
*************** update_vtable_entry_for_fn (t, binfo, fn
*** 2659,2665 ****
/* If we find BINFO, then the final overrider is in a class
derived from BINFO, so the thunks can be generated with
the final overrider. */
! if (same_type_p (BINFO_TYPE (b), BINFO_TYPE (binfo)))
generate_thunk_with_vtable_p = 0;
/* If we find the final overrider, then we can stop
--- 2660,2667 ----
/* If we find BINFO, then the final overrider is in a class
derived from BINFO, so the thunks can be generated with
the final overrider. */
! if (!virtual_base
! && same_type_p (BINFO_TYPE (b), BINFO_TYPE (binfo)))
generate_thunk_with_vtable_p = 0;
/* If we find the final overrider, then we can stop
*************** build_vtt (t)
*** 6627,6633 ****
/* 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)
--- 6629,6636 ----
/* Build up the initializers for the VTT. */
inits = NULL_TREE;
index = size_zero_node;
! build_vtt_inits (TYPE_BINFO (t), t, /*virtual_vtts_p=*/1,
! &inits, &index);
/* If we didn't need a VTT, we're done. */
if (!inits)
*************** build_vtt (t)
*** 6643,6657 ****
initialize_array (vtt, inits);
}
/* 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;
{
--- 6646,6690 ----
initialize_array (vtt, inits);
}
+ /* The type corresponding to BINFO is a base class of T, but BINFO is
+ in the base class hierarchy of a class derived from T. Return the
+ base, in T's hierarchy, that corresponds to BINFO. */
+
+ static tree
+ get_matching_base (binfo, t)
+ tree binfo;
+ tree t;
+ {
+ tree derived;
+ int i;
+
+ if (same_type_p (BINFO_TYPE (binfo), t))
+ return binfo;
+
+ if (TREE_VIA_VIRTUAL (binfo))
+ return binfo_for_vbase (BINFO_TYPE (binfo), t);
+
+ derived = get_matching_base (BINFO_INHERITANCE_CHAIN (binfo), t);
+ for (i = 0; i < BINFO_N_BASETYPES (derived); ++i)
+ if (same_type_p (BINFO_TYPE (BINFO_BASETYPE (derived, i)),
+ BINFO_TYPE (binfo)))
+ return BINFO_BASETYPE (derived, i);
+
+ my_friendly_abort (20000628);
+ return NULL_TREE;
+ }
+
/* Recursively build the VTT-initializer for BINFO (which is in the
! hierarchy dominated by T). If VIRTUAL_VTTS_P is non-zero, then
! sub-VTTs for virtual bases are included. 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, virtual_vtts_p, inits, index)
tree binfo;
tree t;
+ int virtual_vtts_p;
tree *inits;
tree *index;
{
*************** build_vtt_inits (binfo, t, inits, index)
*** 6679,6685 ****
/* 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;
--- 6712,6718 ----
/* Add the address of the primary vtable for the complete object. */
init = BINFO_VTABLE (binfo);
if (TREE_CODE (init) == TREE_LIST)
! init = TREE_VALUE (init);
*inits = build_tree_list (NULL_TREE, init);
inits = &TREE_CHAIN (*inits);
BINFO_VPTR_INDEX (binfo) = *index;
*************** build_vtt_inits (binfo, t, inits, index)
*** 6690,6712 ****
{
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,
dfs_unmarked_real_bases_queue_p,
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
--- 6723,6745 ----
{
b = BINFO_BASETYPE (binfo, i);
if (!TREE_VIA_VIRTUAL (b))
! inits = build_vtt_inits (BINFO_BASETYPE (binfo, i), t,
! /*virtuals_vtts_p=*/0,
! 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 = tree_cons (t, NULL_TREE, BINFO_TYPE (binfo));
TREE_TYPE (secondary_vptrs) = *index;
dfs_walk_real (binfo,
! dfs_build_secondary_vptr_vtt_inits,
NULL,
dfs_unmarked_real_bases_queue_p,
secondary_vptrs);
! dfs_walk (binfo, dfs_unmark, dfs_marked_real_bases_queue_p, t);
*index = TREE_TYPE (secondary_vptrs);
/* The secondary vptrs come back in reverse order. After we reverse
*************** build_vtt_inits (binfo, t, inits, index)
*** 6721,6736 ****
}
/* Add the secondary VTTs for virtual bases. */
! for (b = TYPE_BINFO (BINFO_TYPE (binfo)); b; b = TREE_CHAIN (b))
! {
! tree vbase;
!
! if (!TREE_VIA_VIRTUAL (b))
! continue;
! vbase = binfo_for_vbase (BINFO_TYPE (b), t);
! inits = build_vtt_inits (vbase, t, inits, index);
! }
return inits;
}
--- 6754,6775 ----
}
/* Add the secondary VTTs for virtual bases. */
! if (virtual_vtts_p)
! for (b = TYPE_BINFO (BINFO_TYPE (binfo)); b; b = TREE_CHAIN (b))
! {
! tree vbase;
!
! if (!TREE_VIA_VIRTUAL (b))
! continue;
!
! vbase = binfo_for_vbase (BINFO_TYPE (b), t);
! inits = build_vtt_inits (vbase, t, /*virtual_vtts_p=*/0,
! inits, index);
! }
! dfs_walk (binfo, dfs_fixup_binfo_vtbls,
! dfs_unmarked_real_bases_queue_p,
! build_tree_list (t, binfo));
return inits;
}
*************** build_vtt_inits (binfo, t, inits, index)
*** 6738,6744 ****
/* Called from build_vtt_inits via dfs_walk. */
static tree
! dfs_build_vtt_inits (binfo, data)
tree binfo;
void *data;
{
--- 6777,6783 ----
/* Called from build_vtt_inits via dfs_walk. */
static tree
! dfs_build_secondary_vptr_vtt_inits (binfo, data)
tree binfo;
void *data;
{
*************** dfs_build_vtt_inits (binfo, data)
*** 6748,6754 ****
tree index;
l = (tree) data;
! t = TREE_PURPOSE (l);
SET_BINFO_MARKED (binfo);
--- 6787,6793 ----
tree index;
l = (tree) data;
! t = TREE_CHAIN (l);
SET_BINFO_MARKED (binfo);
*************** dfs_build_vtt_inits (binfo, data)
*** 6769,6775 ****
virtual path. The point is that given:
struct V { virtual void f(); int i; };
! struct C : public V { void f (); };
when we constrct C we need a secondary vptr for V-in-C because we
don't know what the vcall offset for `f' should be. If `V' ends
--- 6808,6814 ----
virtual path. The point is that given:
struct V { virtual void f(); int i; };
! struct C : public virtual V { void f (); };
when we constrct C we need a secondary vptr for V-in-C because we
don't know what the vcall offset for `f' should be. If `V' ends
*************** dfs_build_vtt_inits (binfo, data)
*** 6777,6783 ****
different vcall offset than that present in the normal V-in-C
vtable. */
if (!TYPE_USES_VIRTUAL_BASECLASSES (BINFO_TYPE (binfo))
! && !BINFO_OVERRIDE_ALONG_VIRTUAL_PATH_P (binfo))
return NULL_TREE;
/* Record the index where this secondary vptr can be found. */
--- 6816,6822 ----
different vcall offset than that present in the normal V-in-C
vtable. */
if (!TYPE_USES_VIRTUAL_BASECLASSES (BINFO_TYPE (binfo))
! && !BINFO_OVERRIDE_ALONG_VIRTUAL_PATH_P (get_matching_base (binfo, t)))
return NULL_TREE;
/* Record the index where this secondary vptr can be found. */
*************** dfs_build_vtt_inits (binfo, data)
*** 6789,6795 ****
/* 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;
--- 6828,6834 ----
/* Add the initializer for the secondary vptr itself. */
init = BINFO_VTABLE (binfo);
if (TREE_CODE (init) == TREE_LIST)
! init = TREE_VALUE (init);
TREE_VALUE (l) = tree_cons (NULL_TREE, init, TREE_VALUE (l));
return NULL_TREE;
*************** dfs_build_vtt_inits (binfo, data)
*** 6800,6806 ****
static tree
dfs_fixup_binfo_vtbls (binfo, data)
tree binfo;
! void *data ATTRIBUTE_UNUSED;
{
CLEAR_BINFO_MARKED (binfo);
--- 6839,6845 ----
static tree
dfs_fixup_binfo_vtbls (binfo, data)
tree binfo;
! void *data;
{
CLEAR_BINFO_MARKED (binfo);
*************** dfs_fixup_binfo_vtbls (binfo, data)
*** 6810,6817 ****
/* If we scribbled the construction vtable vptr into BINFO, clear it
out now. */
! if (TREE_CODE (BINFO_VTABLE (binfo)) == TREE_LIST)
! BINFO_VTABLE (binfo) = TREE_VALUE (BINFO_VTABLE (binfo));
return NULL_TREE;
}
--- 6849,6858 ----
/* If we scribbled the construction vtable vptr into BINFO, clear it
out now. */
! if (TREE_CODE (BINFO_VTABLE (binfo)) == TREE_LIST
! && (TREE_PURPOSE (BINFO_VTABLE (binfo))
! == TREE_VALUE ((tree) data)))
! BINFO_VTABLE (binfo) = TREE_CHAIN (BINFO_VTABLE (binfo));
return NULL_TREE;
}
*************** build_ctor_vtbl_group (binfo, t)
*** 6829,6834 ****
--- 6870,6876 ----
tree vtbl;
tree inits;
tree id;
+ tree vbase;
/* See if we've already create this construction vtable group. */
if (flag_new_abi)
*************** build_ctor_vtbl_group (binfo, t)
*** 6845,6850 ****
--- 6887,6905 ----
list = build_tree_list (vtbl, NULL_TREE);
accumulate_vtbl_inits (binfo, TYPE_BINFO (TREE_TYPE (binfo)),
binfo, t, list);
+ for (vbase = TYPE_BINFO (TREE_TYPE (binfo));
+ vbase;
+ vbase = TREE_CHAIN (vbase))
+ {
+ tree b;
+
+ if (!TREE_VIA_VIRTUAL (vbase))
+ continue;
+
+ b = binfo_for_vbase (BINFO_TYPE (vbase), t);
+ accumulate_vtbl_inits (b, vbase, binfo, t, list);
+ }
+
inits = TREE_VALUE (list);
/* Figure out the type of the construction vtable. */
*************** accumulate_vtbl_inits (binfo, orig_binfo
*** 6886,6892 ****
/* If we're building a construction vtable, we're not interested in
subobjects that don't require construction vtables. */
if (ctor_vtbl_p
! && !TYPE_USES_VIRTUAL_BASECLASSES (BINFO_TYPE (binfo)))
return;
/* Build the initializers for the BINFO-in-T vtable. */
--- 6941,6949 ----
/* If we're building a construction vtable, we're not interested in
subobjects that don't require construction vtables. */
if (ctor_vtbl_p
! && !TYPE_USES_VIRTUAL_BASECLASSES (BINFO_TYPE (binfo))
! && !(BINFO_OVERRIDE_ALONG_VIRTUAL_PATH_P
! (get_matching_base (binfo, BINFO_TYPE (rtti_binfo)))))
return;
/* Build the initializers for the BINFO-in-T vtable. */
*************** dfs_accumulate_vtbl_inits (binfo, orig_b
*** 6929,6944 ****
tree l;
{
tree inits = NULL_TREE;
- int ctor_vtbl_p;
-
- /* This is a construction vtable if the RTTI type is not the most
- derived type in the hierarchy. */
- ctor_vtbl_p = !same_type_p (BINFO_TYPE (rtti_binfo), t);
! 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;
--- 6986,6993 ----
tree l;
{
tree inits = NULL_TREE;
! if (BINFO_NEW_VTABLE_MARKED (orig_binfo, t))
{
tree vtbl;
tree index;
*************** dfs_accumulate_vtbl_inits (binfo, orig_b
*** 6963,6976 ****
TREE_CONSTANT (vtbl) = 1;
/* For an ordinary vtable, set BINFO_VTABLE. */
! if (!ctor_vtbl_p)
BINFO_VTABLE (binfo) = vtbl;
/* For a construction vtable, we can't overwrite BINFO_VTABLE.
So, we make a TREE_LIST. Later, dfs_fixup_binfo_vtbls will
straighten this out. */
else
! BINFO_VTABLE (binfo) = build_tree_list (vtbl,
! BINFO_VTABLE (binfo));
}
return inits;
--- 7012,7025 ----
TREE_CONSTANT (vtbl) = 1;
/* For an ordinary vtable, set BINFO_VTABLE. */
! if (same_type_p (BINFO_TYPE (rtti_binfo), t))
BINFO_VTABLE (binfo) = vtbl;
/* For a construction vtable, we can't overwrite BINFO_VTABLE.
So, we make a TREE_LIST. Later, dfs_fixup_binfo_vtbls will
straighten this out. */
else
! BINFO_VTABLE (binfo) =
! tree_cons (rtti_binfo, vtbl, BINFO_VTABLE (binfo));
}
return inits;
Index: cp-tree.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/cp-tree.h,v
retrieving revision 1.489
diff -c -p -r1.489 cp-tree.h
*** cp-tree.h 2000/06/26 02:18:14 1.489
--- cp-tree.h 2000/06/28 20:37:42
*************** struct lang_type
*** 1781,1788 ****
my_friendly_assert (!BINFO_PRIMARY_MARKED_P (B), 20000517), \
my_friendly_assert (CLASSTYPE_VFIELDS (BINFO_TYPE (B)) != NULL_TREE, \
20000517))
- #define CLEAR_BINFO_NEW_VTABLE_MARKED(B, C) \
- (BINFO_NEW_VTABLE_MARKED (B, C) = 0)
/* Nonzero means this class has done dfs_pushdecls. */
#define BINFO_PUSHDECLS_MARKED(NODE) BINFO_VTABLE_PATH_MARKED (NODE)
--- 1781,1786 ----
Index: pt.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/pt.c,v
retrieving revision 1.446
diff -c -p -r1.446 pt.c
*** pt.c 2000/06/23 06:49:44 1.446
--- pt.c 2000/06/28 20:37:50
*************** tsubst (t, args, complain, in_decl)
*** 6361,6385 ****
{
case TEMPLATE_TYPE_PARM:
case TEMPLATE_TEMPLATE_PARM:
! r = copy_node (t);
! TEMPLATE_TYPE_PARM_INDEX (r)
! = reduce_template_parm_level (TEMPLATE_TYPE_PARM_INDEX (t),
! r, levels);
! TYPE_STUB_DECL (r) = TYPE_NAME (r) = TEMPLATE_TYPE_DECL (r);
! TYPE_MAIN_VARIANT (r) = r;
! TYPE_POINTER_TO (r) = NULL_TREE;
! TYPE_REFERENCE_TO (r) = NULL_TREE;
!
! if (TREE_CODE (t) == TEMPLATE_TEMPLATE_PARM
! && TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO (t))
{
! tree argvec = tsubst (TYPE_TI_ARGS (t), args,
! complain, in_decl);
! if (argvec == error_mark_node)
! return error_mark_node;
! TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO (r)
! = tree_cons (TYPE_TI_TEMPLATE (t), argvec, NULL_TREE);
}
break;
--- 6361,6394 ----
{
case TEMPLATE_TYPE_PARM:
case TEMPLATE_TEMPLATE_PARM:
! if (CP_TYPE_QUALS (t))
! {
! r = tsubst (TYPE_MAIN_VARIANT (t), args, complain, in_decl);
! r = cp_build_qualified_type_real (r, CP_TYPE_QUALS (t),
! complain);
! }
! else
{
! r = copy_node (t);
! TEMPLATE_TYPE_PARM_INDEX (r)
! = reduce_template_parm_level (TEMPLATE_TYPE_PARM_INDEX (t),
! r, levels);
! TYPE_STUB_DECL (r) = TYPE_NAME (r) = TEMPLATE_TYPE_DECL (r);
! TYPE_MAIN_VARIANT (r) = r;
! TYPE_POINTER_TO (r) = NULL_TREE;
! TYPE_REFERENCE_TO (r) = NULL_TREE;
!
! if (TREE_CODE (t) == TEMPLATE_TEMPLATE_PARM
! && TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO (t))
! {
! tree argvec = tsubst (TYPE_TI_ARGS (t), args,
! complain, in_decl);
! if (argvec == error_mark_node)
! return error_mark_node;
! TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO (r)
! = tree_cons (TYPE_TI_TEMPLATE (t), argvec, NULL_TREE);
! }
}
break;