aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Mitchell <mark@codesourcery.com>2000-03-22 21:43:45 +0000
committerMark Mitchell <mmitchel@gcc.gnu.org>2000-03-22 21:43:45 +0000
commit3c9d63596fc5b0245704c8f66715c5d03dc4c91a (patch)
tree6d0f3bdb88c1291bb8d71766a4c9bdec7640952d
parent26356fee5ba5a558889329f911024af9e77351ec (diff)
downloadgcc-3c9d63596fc5b0245704c8f66715c5d03dc4c91a.zip
gcc-3c9d63596fc5b0245704c8f66715c5d03dc4c91a.tar.gz
gcc-3c9d63596fc5b0245704c8f66715c5d03dc4c91a.tar.bz2
cp-tree.h (BINFO_FOR_VBASE): Adjust documentation.
* cp-tree.h (BINFO_FOR_VBASE): Adjust documentation. (CANONICAL_BINFO): New macro. (BINFO_NEW_VTABLE_MARKED): Use it. (SET_BINFO_NEW_VTABLE_MARKED): Likewise. (CLEAR_BINFO_NEW_VTABLE_MARKED): Likewise. * class.c (dfs_build_vbase_offset_vtbl_entries): Use BINFO_TYPE, not TREE_TYPE. (build_primary_vtable): Adjust usage of BINFO_NEW_VTABLE_MARKED. (build_secondary_vtable): Likewise. (dfs_finish_vtbls): Likewise. (dfs_accumulate_vtbl_inits): Likewise. (accumulate_vtbl_inits): New function. (finish_vtbls): Make sure that virtual bases come after non-virtual bases in the vtable group. (record_base_offsets): Don't save and restore TREE_VIA_VIRTUAL. (finish_struct_1): Adjust usage of BINFO_NEW_VTABLE_MARKED. * search.c (struct vbase_info): Move definition. (marked_new_vtable_p): Adjust usage of BINFO_NEW_VTABLE_MARKED. (unmarked_new_vtable_p): Likewise. (dfs_mark_vtable_path): Remove. (dfs_mark_new_vtable): Remove. (dfs_unmark_new_vtable): Likewise. (dfs_clear_search_slot): Likewise. (dfs_find_vbases): Adjust usage of BINFO_NEW_VTABLE_MARKED. (dfs_clear_vbase_slots): Likewise. (init_vbase_pointers): LIkewise. From-SVN: r32689
-rw-r--r--gcc/cp/ChangeLog29
-rw-r--r--gcc/cp/class.c91
-rw-r--r--gcc/cp/cp-tree.h24
-rw-r--r--gcc/cp/search.c59
-rw-r--r--gcc/testsuite/g++.old-deja/g++.abi/vtable.C82
5 files changed, 209 insertions, 76 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index de6a2eb..33d688f 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,32 @@
+2000-03-22 Mark Mitchell <mark@codesourcery.com>
+
+ * cp-tree.h (BINFO_FOR_VBASE): Adjust documentation.
+ (CANONICAL_BINFO): New macro.
+ (BINFO_NEW_VTABLE_MARKED): Use it.
+ (SET_BINFO_NEW_VTABLE_MARKED): Likewise.
+ (CLEAR_BINFO_NEW_VTABLE_MARKED): Likewise.
+ * class.c (dfs_build_vbase_offset_vtbl_entries): Use BINFO_TYPE,
+ not TREE_TYPE.
+ (build_primary_vtable): Adjust usage of BINFO_NEW_VTABLE_MARKED.
+ (build_secondary_vtable): Likewise.
+ (dfs_finish_vtbls): Likewise.
+ (dfs_accumulate_vtbl_inits): Likewise.
+ (accumulate_vtbl_inits): New function.
+ (finish_vtbls): Make sure that virtual bases come after
+ non-virtual bases in the vtable group.
+ (record_base_offsets): Don't save and restore TREE_VIA_VIRTUAL.
+ (finish_struct_1): Adjust usage of BINFO_NEW_VTABLE_MARKED.
+ * search.c (struct vbase_info): Move definition.
+ (marked_new_vtable_p): Adjust usage of BINFO_NEW_VTABLE_MARKED.
+ (unmarked_new_vtable_p): Likewise.
+ (dfs_mark_vtable_path): Remove.
+ (dfs_mark_new_vtable): Remove.
+ (dfs_unmark_new_vtable): Likewise.
+ (dfs_clear_search_slot): Likewise.
+ (dfs_find_vbases): Adjust usage of BINFO_NEW_VTABLE_MARKED.
+ (dfs_clear_vbase_slots): Likewise.
+ (init_vbase_pointers): LIkewise.
+
2000-03-22 Jason Merrill <jason@casey.cygnus.com>
* typeck.c (type_after_usual_arithmetic_conversions): Prefer a
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index 12095ad..216d7e3 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -161,6 +161,7 @@ static tree dfs_search_base_offsets PARAMS ((tree, void *));
static int layout_conflict_p PARAMS ((tree, varray_type));
static unsigned HOST_WIDE_INT end_of_class PARAMS ((tree, int));
static void layout_empty_base PARAMS ((tree, tree, varray_type));
+static void accumulate_vtbl_inits PARAMS ((tree, tree));
/* Variables shared between class.c and call.c. */
@@ -276,7 +277,7 @@ dfs_build_vbase_offset_vtbl_entries (binfo, data)
/* Remember the index to the vbase offset for this virtual
base. */
- vbase = BINFO_FOR_VBASE (TREE_TYPE (binfo), TREE_PURPOSE (list));
+ vbase = BINFO_FOR_VBASE (BINFO_TYPE (binfo), TREE_PURPOSE (list));
if (!TREE_VALUE (list))
BINFO_VPTR_FIELD (vbase) = build_int_2 (-1, 0);
else
@@ -1072,7 +1073,7 @@ build_primary_vtable (binfo, type)
{
tree offset;
- if (BINFO_NEW_VTABLE_MARKED (binfo))
+ if (BINFO_NEW_VTABLE_MARKED (binfo, type))
/* We have already created a vtable for this base, so there's
no need to do it again. */
return 0;
@@ -1106,7 +1107,7 @@ build_primary_vtable (binfo, type)
TYPE_BINFO_VIRTUALS (type) = virtuals;
binfo = TYPE_BINFO (type);
- SET_BINFO_NEW_VTABLE_MARKED (binfo);
+ SET_BINFO_NEW_VTABLE_MARKED (binfo, type);
return 1;
}
@@ -1147,14 +1148,14 @@ build_secondary_vtable (binfo, for_type)
current_class_type),
170);
- if (BINFO_NEW_VTABLE_MARKED (binfo))
+ if (BINFO_NEW_VTABLE_MARKED (binfo, current_class_type))
/* We already created a vtable for this base. There's no need to
do it again. */
return 0;
/* Remember that we've created a vtable for this BINFO, so that we
don't try to do so again. */
- SET_BINFO_NEW_VTABLE_MARKED (binfo);
+ SET_BINFO_NEW_VTABLE_MARKED (binfo, current_class_type);
/* Make fresh virtual list, so we can smash it later. */
BINFO_VIRTUALS (binfo) = copy_list (BINFO_VIRTUALS (binfo));
@@ -2760,13 +2761,15 @@ dfs_finish_vtbls (binfo, data)
tree binfo;
void *data;
{
+ tree t = (tree) data;
+
if (!BINFO_PRIMARY_MARKED_P (binfo)
&& CLASSTYPE_VFIELDS (BINFO_TYPE (binfo))
- && BINFO_NEW_VTABLE_MARKED (binfo))
+ && BINFO_NEW_VTABLE_MARKED (binfo, t))
initialize_vtable (binfo,
- build_vtbl_initializer (binfo, (tree) data));
+ build_vtbl_initializer (binfo, t));
- CLEAR_BINFO_NEW_VTABLE_MARKED (binfo);
+ CLEAR_BINFO_NEW_VTABLE_MARKED (binfo, t);
SET_BINFO_MARKED (binfo);
return NULL_TREE;
@@ -2781,15 +2784,16 @@ dfs_accumulate_vtbl_inits (binfo, data)
tree binfo;
void *data;
{
+ tree l;
+ tree t;
+
+ l = (tree) data;
+ t = TREE_PURPOSE (l);
+
if (!BINFO_PRIMARY_MARKED_P (binfo)
&& CLASSTYPE_VFIELDS (BINFO_TYPE (binfo))
- && BINFO_NEW_VTABLE_MARKED (binfo))
+ && BINFO_NEW_VTABLE_MARKED (binfo, t))
{
- tree l;
- tree t;
-
- l = (tree) data;
- t = TREE_PURPOSE (l);
/* If this is a secondary vtable, record its location. */
if (binfo != TYPE_BINFO (t))
@@ -2807,19 +2811,34 @@ dfs_accumulate_vtbl_inits (binfo, data)
size_int (list_length (TREE_VALUE (l)))));
}
- /* Add the initializers for this vtable to the initailizers for
+ /* Add the initializers for this vtable to the initializers for
the other vtables we've already got. */
TREE_VALUE (l)
= chainon (TREE_VALUE (l),
build_vtbl_initializer (binfo, t));
}
- CLEAR_BINFO_NEW_VTABLE_MARKED (binfo);
- SET_BINFO_MARKED (binfo);
+ CLEAR_BINFO_NEW_VTABLE_MARKED (binfo, t);
return NULL_TREE;
}
+/* Add the vtbl initializers for BINFO (and its non-primary,
+ non-virtual bases) to the list of INITS. */
+
+static void
+accumulate_vtbl_inits (binfo, inits)
+ tree binfo;
+ tree inits;
+{
+ /* Walk the BINFO and its bases. */
+ dfs_walk_real (binfo,
+ dfs_accumulate_vtbl_inits,
+ NULL,
+ dfs_skip_vbases,
+ inits);
+}
+
/* Create all the necessary vtables for T and its base classes. */
static void
@@ -2829,26 +2848,31 @@ finish_vtbls (t)
if (merge_primary_and_secondary_vtables_p ())
{
tree list;
+ tree vbase;
/* Under the new ABI, we lay out the primary and secondary
vtables in one contiguous vtable. The primary vtable is
- first, followed by the secondary vtables as encountered in a
- pre-order depth-first left-to-right traversal. */
+ first, followed by the non-virtual secondary vtables in
+ inheritance graph order. */
list = build_tree_list (t, NULL_TREE);
- dfs_walk_real (TYPE_BINFO (t),
- dfs_accumulate_vtbl_inits,
- NULL,
- dfs_unmarked_real_bases_queue_p,
- list);
+ accumulate_vtbl_inits (TYPE_BINFO (t), list);
+ /* Then come the virtual bases, also in inheritance graph
+ order. */
+ for (vbase = CLASSTYPE_VBASECLASSES (t);
+ vbase;
+ vbase = TREE_CHAIN (vbase))
+ accumulate_vtbl_inits (vbase, list);
+
if (TYPE_BINFO_VTABLE (t))
initialize_vtable (TYPE_BINFO (t), TREE_VALUE (list));
}
else
- dfs_walk (TYPE_BINFO (t), dfs_finish_vtbls,
- dfs_unmarked_real_bases_queue_p, t);
-
- dfs_walk (TYPE_BINFO (t), dfs_unmark,
- dfs_marked_real_bases_queue_p, t);
+ {
+ dfs_walk (TYPE_BINFO (t), dfs_finish_vtbls,
+ dfs_unmarked_real_bases_queue_p, t);
+ dfs_walk (TYPE_BINFO (t), dfs_unmark,
+ dfs_marked_real_bases_queue_p, t);
+ }
}
/* True if we should override the given BASE_FNDECL with the given
@@ -4142,17 +4166,10 @@ record_base_offsets (binfo, base_offsets)
tree binfo;
varray_type *base_offsets;
{
- int virtual_p;
-
- /* If BINFO is virtual, we still want to mention its offset in
- BASE_OFFSETS. */
- virtual_p = TREE_VIA_VIRTUAL (binfo);
- TREE_VIA_VIRTUAL (binfo) = 0;
dfs_walk (binfo,
dfs_record_base_offsets,
dfs_skip_vbases,
base_offsets);
- TREE_VIA_VIRTUAL (binfo) = virtual_p;
}
/* Returns non-NULL if there is already an entry in DATA (which is
@@ -5308,7 +5325,7 @@ finish_struct_1 (t)
}
build_primary_vtable (NULL_TREE, t);
}
- else if (! BINFO_NEW_VTABLE_MARKED (TYPE_BINFO (t)))
+ else if (! BINFO_NEW_VTABLE_MARKED (TYPE_BINFO (t), t))
/* Here we know enough to change the type of our virtual
function table, but we will wait until later this function. */
build_primary_vtable (CLASSTYPE_PRIMARY_BINFO (t), t);
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 04fd943..9ccd28a 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -1566,10 +1566,19 @@ struct lang_type
(also distinct from the copies in the TYPE_BINFO hierarchy.) */
#define CLASSTYPE_VBASECLASSES(NODE) (TYPE_LANG_SPECIFIC(NODE)->vbases)
-/* The BINFO (if any) for the virtual baseclass T of the class C. */
+/* The BINFO (if any) for the virtual baseclass T of the class C from
+ the CLASSTYPE_VBASECLASSES list. */
#define BINFO_FOR_VBASE(T, C) \
(binfo_member (T, CLASSTYPE_VBASECLASSES (C)))
+/* For a non-virtual BINFO, the BINFO itself; for a virtual BINFO, the
+ BINFO_FOR_VBASE. C is the most derived class for the hierarchy
+ containing BINFO. */
+#define CANONICAL_BINFO(BINFO, C) \
+ (TREE_VIA_VIRTUAL (BINFO) \
+ ? BINFO_FOR_VBASE (BINFO_TYPE (BINFO), C) \
+ : BINFO)
+
/* Number of direct baseclasses of NODE. */
#define CLASSTYPE_N_BASECLASSES(NODE) \
(BINFO_N_BASETYPES (TYPE_BINFO (NODE)))
@@ -1704,11 +1713,14 @@ struct lang_type
#define SET_BINFO_VTABLE_PATH_MARKED(NODE) (TREE_VIA_VIRTUAL(NODE)?SET_CLASSTYPE_MARKED3(BINFO_TYPE(NODE)):(TREE_LANG_FLAG_3(NODE)=1))
#define CLEAR_BINFO_VTABLE_PATH_MARKED(NODE) (TREE_VIA_VIRTUAL(NODE)?CLEAR_CLASSTYPE_MARKED3(BINFO_TYPE(NODE)):(TREE_LANG_FLAG_3(NODE)=0))
-/* Nonzero means that this class has a new vtable. */
-#define BINFO_NEW_VTABLE_MARKED(NODE) \
- (TREE_VIA_VIRTUAL(NODE)?CLASSTYPE_MARKED4(BINFO_TYPE(NODE)):TREE_LANG_FLAG_4(NODE))
-#define SET_BINFO_NEW_VTABLE_MARKED(NODE) (TREE_VIA_VIRTUAL(NODE)?SET_CLASSTYPE_MARKED4(BINFO_TYPE(NODE)):(TREE_LANG_FLAG_4(NODE)=1))
-#define CLEAR_BINFO_NEW_VTABLE_MARKED(NODE) (TREE_VIA_VIRTUAL(NODE)?CLEAR_CLASSTYPE_MARKED4(BINFO_TYPE(NODE)):(TREE_LANG_FLAG_4(NODE)=0))
+/* Nonzero means B (a BINFO) needs a new vtable. B is part of the
+ hierarchy dominated by C. */
+#define BINFO_NEW_VTABLE_MARKED(B, C) \
+ (TREE_LANG_FLAG_4 (CANONICAL_BINFO (B, C)))
+#define SET_BINFO_NEW_VTABLE_MARKED(B, C) \
+ (BINFO_NEW_VTABLE_MARKED (B, C) = 1)
+#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)
diff --git a/gcc/cp/search.c b/gcc/cp/search.c
index 9d75476..314dab9 100644
--- a/gcc/cp/search.c
+++ b/gcc/cp/search.c
@@ -76,6 +76,15 @@ pop_stack_level (stack)
#define search_level stack_level
static struct search_level *search_stack;
+struct vbase_info
+{
+ /* The class dominating the hierarchy. */
+ tree type;
+ tree decl_ptr;
+ tree inits;
+ tree vbase_types;
+};
+
static tree next_baselink PARAMS ((tree));
static tree get_vbase_1 PARAMS ((tree, tree, unsigned int *));
static tree lookup_field_1 PARAMS ((tree, tree));
@@ -2537,17 +2546,21 @@ unmarked_vtable_pathp (binfo, data)
static tree
marked_new_vtablep (binfo, data)
tree binfo;
- void *data ATTRIBUTE_UNUSED;
+ void *data;
{
- return BINFO_NEW_VTABLE_MARKED (binfo) ? binfo : NULL_TREE;
+ struct vbase_info *vi = (struct vbase_info *) data;
+
+ return BINFO_NEW_VTABLE_MARKED (binfo, vi->type) ? binfo : NULL_TREE;
}
static tree
unmarked_new_vtablep (binfo, data)
tree binfo;
- void *data ATTRIBUTE_UNUSED;
+ void *data;
{
- return !BINFO_NEW_VTABLE_MARKED (binfo) ? binfo : NULL_TREE;
+ struct vbase_info *vi = (struct vbase_info *) data;
+
+ return !BINFO_NEW_VTABLE_MARKED (binfo, vi->type) ? binfo : NULL_TREE;
}
static tree
@@ -2614,31 +2627,7 @@ dfs_vtable_path_unmark (binfo, data)
return NULL_TREE;
}
-#if 0
-static void
-dfs_mark_vtable_path (binfo) tree binfo;
-{ SET_BINFO_VTABLE_PATH_MARKED (binfo); }
-
-static void
-dfs_mark_new_vtable (binfo) tree binfo;
-{ SET_BINFO_NEW_VTABLE_MARKED (binfo); }
-
-static void
-dfs_unmark_new_vtable (binfo) tree binfo;
-{ CLEAR_BINFO_NEW_VTABLE_MARKED (binfo); }
-
-static void
-dfs_clear_search_slot (binfo) tree binfo;
-{ CLASSTYPE_SEARCH_SLOT (BINFO_TYPE (binfo)) = 0; }
-#endif
-struct vbase_info
-{
- tree decl_ptr;
- tree inits;
- tree vbase_types;
-};
-
/* Attach to the type of the virtual base class, the pointer to the
virtual base class. */
@@ -2668,7 +2657,7 @@ dfs_find_vbases (binfo, data)
}
}
SET_BINFO_VTABLE_PATH_MARKED (binfo);
- SET_BINFO_NEW_VTABLE_MARKED (binfo);
+ SET_BINFO_NEW_VTABLE_MARKED (binfo, vi->type);
return NULL_TREE;
}
@@ -2737,12 +2726,14 @@ dfs_init_vbase_pointers (binfo, data)
static tree
dfs_clear_vbase_slots (binfo, data)
tree binfo;
- void *data ATTRIBUTE_UNUSED;
+ void *data;
{
tree type = BINFO_TYPE (binfo);
+ struct vbase_info *vi = (struct vbase_info *) data;
+
CLASSTYPE_SEARCH_SLOT (type) = 0;
CLEAR_BINFO_VTABLE_PATH_MARKED (binfo);
- CLEAR_BINFO_NEW_VTABLE_MARKED (binfo);
+ CLEAR_BINFO_NEW_VTABLE_MARKED (binfo, vi->type);
return NULL_TREE;
}
@@ -2760,6 +2751,7 @@ init_vbase_pointers (type, decl_ptr)
/* Find all the virtual base classes, marking them for later
initialization. */
+ vi.type = type;
vi.decl_ptr = decl_ptr;
vi.vbase_types = CLASSTYPE_VBASECLASSES (type);
vi.inits = NULL_TREE;
@@ -2773,7 +2765,7 @@ init_vbase_pointers (type, decl_ptr)
marked_vtable_pathp,
&vi);
- dfs_walk (binfo, dfs_clear_vbase_slots, marked_new_vtablep, 0);
+ dfs_walk (binfo, dfs_clear_vbase_slots, marked_new_vtablep, &vi);
flag_this_is_variable = old_flag;
return vi.inits;
}
@@ -3088,12 +3080,13 @@ expand_indirect_vtbls_init (binfo, decl_ptr)
{
tree vbases = CLASSTYPE_VBASECLASSES (type);
struct vbase_info vi;
+ vi.type = type;
vi.decl_ptr = decl_ptr;
vi.vbase_types = vbases;
dfs_walk (binfo, dfs_find_vbases, unmarked_new_vtablep, &vi);
fixup_all_virtual_upcast_offsets (type, vi.decl_ptr);
- dfs_walk (binfo, dfs_clear_vbase_slots, marked_new_vtablep, 0);
+ dfs_walk (binfo, dfs_clear_vbase_slots, marked_new_vtablep, &vi);
}
}
diff --git a/gcc/testsuite/g++.old-deja/g++.abi/vtable.C b/gcc/testsuite/g++.old-deja/g++.abi/vtable.C
new file mode 100644
index 0000000..aafcad8
--- /dev/null
+++ b/gcc/testsuite/g++.old-deja/g++.abi/vtable.C
@@ -0,0 +1,82 @@
+// Test various aspects of vtable layout.
+// Special g++ Options: -fno-strict-aliasing
+// Origin: Mark Mitchell <mark@codesourcery.com>
+
+#if defined (__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100
+
+struct S0
+{
+ virtual void h ()
+ {
+ }
+
+ int k;
+};
+
+
+struct S1
+{
+ virtual void f ()
+ {
+ }
+
+ int i;
+};
+
+struct S2 : virtual public S0
+{
+ virtual void g ()
+ {
+ }
+
+ int j;
+};
+
+struct S3
+{
+ virtual void k ()
+ {
+ }
+
+ int l;
+};
+
+struct S4 : public virtual S1, public S2, public S3
+{
+};
+
+inline void* vtable (void *object)
+{
+ // The vptr is always the first part of the object.
+ return * (void **) object;
+}
+
+int main ()
+{
+ // The vtable layout order for S4 should consist of S4's primary
+ // vtable (shared with S2), followed by the vtable for S3 (because
+ // it is a non-virtual base). Then, these should be followed by the
+ // the vtables for S1 and S0, which are virtual.
+ S4 s4;
+ S0 *s0 = &s4;
+ S1 *s1 = &s4;
+ S2 *s2 = &s4;
+ S3 *s3 = &s4;
+
+ if (vtable (&s4) != vtable (s2))
+ return 1;
+ if (vtable (s2) >= vtable (s3))
+ return 2;
+ if (vtable (s3) >= vtable (s1))
+ return 3;
+ if (vtable (s1) >= vtable (s0))
+ return 4;
+}
+
+#else /* !(defined (__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100) */
+
+int main ()
+{
+}
+
+#endif /* !(defined (__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100) */