aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Mitchell <mark@codesourcery.com>2000-04-04 18:13:22 +0000
committerMark Mitchell <mark@codesourcery.com>2000-04-04 18:13:22 +0000
commitfd2602bdf4535c788a839f9d960d86667a3d61fb (patch)
tree7f6d12b8e8dc1ec65000844a7421f72c20af3673
parent53536c7bda78315de0e1328421b84db09ee9fcc5 (diff)
Correct many new ABI issues regarding vbase and vcall offset
layout. * cp-tree.h (BINFO_VTABLE): Document. (struct lang_type): Tweak formatting. (BINFO_PRIMARY_BINFO): Add to documentation. (CLASSTYPE_VSIZE): Fix typo in comment. (CLASSTYPE_VBASECLASSES): Update documentation. (BINFO_VBASE_MARKED): Remove. (SET_BINFO_VBASE_MARKED): Likewise. (CLEAR_BINFO_VBASE_MARKED): Likewise. (BINFO_FIELDS_MARKED): Remove. (SET_BINFO_FIELDS_MARKED): Likewise. (CLEAR_BINFO_FIELDS_MARKED): Likewise. (enum access_kind): New enumeration. (num_extra_vtbl_entries): Remove declaration. (size_extra_vtbl_entries): Likewise. (get_vtbl_decl_for_binfo): New function. (dfs_vbase_unmark): Remove declaration. (mark_primary_bases): Likewise. * class.c (SAME_FN): Remove. (struct vcall_offset_data_s): Move definition. (build_vbase_pointer): Use `build', not `build_binary_op', to access the vbase pointer under the new ABI. (build_vtable_entry_ref): Use get_vtbl_decl_for_binfo. (build_primary_vtable): Likewise. (dfs_mark_primary_bases): Move here from search.c. (mark_primary_bases): Likewise. (determine_primary_bases): Under the new ABI, don't make a base class a primary base just because we don't yet have any virtual functions. (layout_vtable_decl): Use get_vtbl_decl_for_binfo. (num_vfun_entries): Remove. (dfs_count_virtuals): Likewise. (num_extra_vtbl_entries): Likewise. (size_extra_vtbl_entries): Likewise. (layout_virtual_bases): Iterate in inheritance graph order under the new ABI. (finish_struct_1): Use TYPE_VFIELD, not CLASSTYPE_VSIZE, to indicate that a vfield is present. (init_class_processing): Initialize access_public_node, etc., from ak_public, etc. (get_vtbl_decl_for_binfo): New function. (dump_class_hierarchy_r): Likewise. (dump_class_hierarchy): Use it. (finish_vtbls): Build the vtbls in inheritance graph order. (dfs_finish_vtbls): Adjust call to build_vtbl_initializer. (initialize_vtable): Use get_vtbl_decl_for_binfo. (accumulate_vtbl_inits): Add comments explaining why a pre-order walk is required. (dfs_accumulate_vtbl_inits): Set BINFO_VTABLE to the location where the vptr points, even for primary vtables. (build_vtbl_initializer): Adjust handling of vbase and vcall offsets. (build_vcall_and_vbase_vtable_entries): New function. (dfs_build_vbase_offset_vtbl_entries): Remove. (build_vbase_offset_vtbl_entries): Reimplement. (dfs_build_vcall_offset_vtbl_entries): Don't include virtuals that were already handled in a primary base class vtable. (build_vcall_offset_vtbl_entries): Adjust. (build_rtti_vtbl_entries): Adjust. * decl2.c (output_vtable_inherit): Use get_vtbl_decl_for_binfo. * init.c (expand_virtual_init): Simplify. * repo.c (repo_get_id): Use get_vtbl_decl_for_binfo. * rtti.c (create_pseudo_type_info): Adjust calculation of vptr. * search.c (BINFO_ACCESS): New macro. (SET_BINFO_ACCESS): Likewise. (dfs_access_in_type): Manipulate access_kinds, not access nodes. (access_in_type): Likewise. (dfs_accessible_p): Likewise. (protected_accessible_p): Likewise. (lookup_fnfields_1): Adjust documentation. (dfs_mark_primary_bases): Move to class.c (mark_primary_bases): Likewise. (dfs_vbase_unmark): Remove. (virtual_context): Use BINFO_FOR_VBASE. (dfs_get_vbase_types): Simplify. (dfs_build_inheritance_graph_order): New function. (get_vbase_types): Use it. * tree.c (debug_binfo): Use get_vtbl_decl_for_binfo. * tinfo.cc (get_vbase_offset): New function. (__vmi_class_type_info::do_find_public_src): Use it. (__vmi_class_type_info::do_dyncast): Likewise. (__vmi_class_type_info::do_upcast): Likewise. git-svn-id: https://gcc.gnu.org/svn/gcc/trunk@32905 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/cp/ChangeLog87
-rw-r--r--gcc/cp/class.c865
-rw-r--r--gcc/cp/cp-tree.h88
-rw-r--r--gcc/cp/decl2.c2
-rw-r--r--gcc/cp/init.c30
-rw-r--r--gcc/cp/repo.c2
-rw-r--r--gcc/cp/rtti.c9
-rw-r--r--gcc/cp/search.c225
-rw-r--r--gcc/cp/tinfo.cc21
-rw-r--r--gcc/cp/tree.c2
-rw-r--r--gcc/testsuite/g++.old-deja/g++.abi/layout1.C51
-rw-r--r--gcc/testsuite/g++.old-deja/g++.abi/vtable.C2
-rw-r--r--gcc/testsuite/g++.old-deja/g++.abi/vtable2.C179
-rw-r--r--gcc/testsuite/g++.old-deja/g++.jason/dcast3.C2
14 files changed, 979 insertions, 586 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 1a74fea1c43..8fcacd2720e 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,90 @@
+2000-04-04 Mark Mitchell <mark@codesourcery.com>
+
+ Correct many new ABI issues regarding vbase and vcall offset
+ layout.
+ * cp-tree.h (BINFO_VTABLE): Document.
+ (struct lang_type): Tweak formatting.
+ (BINFO_PRIMARY_BINFO): Add to documentation.
+ (CLASSTYPE_VSIZE): Fix typo in comment.
+ (CLASSTYPE_VBASECLASSES): Update documentation.
+ (BINFO_VBASE_MARKED): Remove.
+ (SET_BINFO_VBASE_MARKED): Likewise.
+ (CLEAR_BINFO_VBASE_MARKED): Likewise.
+ (BINFO_FIELDS_MARKED): Remove.
+ (SET_BINFO_FIELDS_MARKED): Likewise.
+ (CLEAR_BINFO_FIELDS_MARKED): Likewise.
+ (enum access_kind): New enumeration.
+ (num_extra_vtbl_entries): Remove declaration.
+ (size_extra_vtbl_entries): Likewise.
+ (get_vtbl_decl_for_binfo): New function.
+ (dfs_vbase_unmark): Remove declaration.
+ (mark_primary_bases): Likewise.
+ * class.c (SAME_FN): Remove.
+ (struct vcall_offset_data_s): Move definition.
+ (build_vbase_pointer): Use `build', not `build_binary_op', to
+ access the vbase pointer under the new ABI.
+ (build_vtable_entry_ref): Use get_vtbl_decl_for_binfo.
+ (build_primary_vtable): Likewise.
+ (dfs_mark_primary_bases): Move here from search.c.
+ (mark_primary_bases): Likewise.
+ (determine_primary_bases): Under the new ABI, don't make a base
+ class a primary base just because we don't yet have any virtual
+ functions.
+ (layout_vtable_decl): Use get_vtbl_decl_for_binfo.
+ (num_vfun_entries): Remove.
+ (dfs_count_virtuals): Likewise.
+ (num_extra_vtbl_entries): Likewise.
+ (size_extra_vtbl_entries): Likewise.
+ (layout_virtual_bases): Iterate in inheritance graph order under
+ the new ABI.
+ (finish_struct_1): Use TYPE_VFIELD, not CLASSTYPE_VSIZE, to
+ indicate that a vfield is present.
+ (init_class_processing): Initialize access_public_node, etc., from
+ ak_public, etc.
+ (get_vtbl_decl_for_binfo): New function.
+ (dump_class_hierarchy_r): Likewise.
+ (dump_class_hierarchy): Use it.
+ (finish_vtbls): Build the vtbls in inheritance graph order.
+ (dfs_finish_vtbls): Adjust call to build_vtbl_initializer.
+ (initialize_vtable): Use get_vtbl_decl_for_binfo.
+ (accumulate_vtbl_inits): Add comments explaining why a pre-order
+ walk is required.
+ (dfs_accumulate_vtbl_inits): Set BINFO_VTABLE to the location
+ where the vptr points, even for primary vtables.
+ (build_vtbl_initializer): Adjust handling of vbase and vcall
+ offsets.
+ (build_vcall_and_vbase_vtable_entries): New function.
+ (dfs_build_vbase_offset_vtbl_entries): Remove.
+ (build_vbase_offset_vtbl_entries): Reimplement.
+ (dfs_build_vcall_offset_vtbl_entries): Don't include virtuals that
+ were already handled in a primary base class vtable.
+ (build_vcall_offset_vtbl_entries): Adjust.
+ (build_rtti_vtbl_entries): Adjust.
+ * decl2.c (output_vtable_inherit): Use get_vtbl_decl_for_binfo.
+ * init.c (expand_virtual_init): Simplify.
+ * repo.c (repo_get_id): Use get_vtbl_decl_for_binfo.
+ * rtti.c (create_pseudo_type_info): Adjust calculation of vptr.
+ * search.c (BINFO_ACCESS): New macro.
+ (SET_BINFO_ACCESS): Likewise.
+ (dfs_access_in_type): Manipulate access_kinds, not access nodes.
+ (access_in_type): Likewise.
+ (dfs_accessible_p): Likewise.
+ (protected_accessible_p): Likewise.
+ (lookup_fnfields_1): Adjust documentation.
+ (dfs_mark_primary_bases): Move to class.c
+ (mark_primary_bases): Likewise.
+ (dfs_vbase_unmark): Remove.
+ (virtual_context): Use BINFO_FOR_VBASE.
+ (dfs_get_vbase_types): Simplify.
+ (dfs_build_inheritance_graph_order): New function.
+ (get_vbase_types): Use it.
+ * tree.c (debug_binfo): Use get_vtbl_decl_for_binfo.
+
+ * tinfo.cc (get_vbase_offset): New function.
+ (__vmi_class_type_info::do_find_public_src): Use it.
+ (__vmi_class_type_info::do_dyncast): Likewise.
+ (__vmi_class_type_info::do_upcast): Likewise.
+
2000-04-03 Zack Weinberg <zack@wolery.cumb.org>
* lang-specs.h: Pass -fno-show-column to the preprocessor.
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index f3a94dc065c..a9f35951375 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -38,12 +38,6 @@ Boston, MA 02111-1307, USA. */
#define obstack_chunk_alloc xmalloc
#define obstack_chunk_free free
-/* This is how we tell when two virtual member functions are really the
- same. */
-#define SAME_FN(FN1DECL, FN2DECL) (DECL_ASSEMBLER_NAME (FN1DECL) == DECL_ASSEMBLER_NAME (FN2DECL))
-
-extern void set_class_shadows PARAMS ((tree));
-
/* The number of nested classes being processed. If we are not in the
scope of any class, this is zero. */
@@ -68,6 +62,22 @@ typedef struct class_stack_node {
splay_tree names_used;
}* class_stack_node_t;
+typedef struct vcall_offset_data_s
+{
+ /* The binfo for the most-derived type. */
+ tree derived;
+ /* The binfo for the virtual base for which we're building
+ initializers. */
+ tree vbase;
+ /* The vcall offset initializers built up so far. */
+ tree inits;
+ /* The vtable index of the next vcall or vbase offset. */
+ tree index;
+ /* Nonzero if we are building the initializer for the primary
+ vtable. */
+ int primary_p;
+} vcall_offset_data;
+
/* The stack itself. This is an dynamically resized array. The
number of elements allocated is CURRENT_CLASS_STACK_SIZE. */
static int current_class_stack_size;
@@ -108,7 +118,7 @@ static tree fixed_type_or_null PARAMS ((tree, int *));
static tree resolve_address_of_overloaded_function PARAMS ((tree, tree, int,
int, tree));
static void build_vtable_entry_ref PARAMS ((tree, tree, tree));
-static tree build_vtbl_initializer PARAMS ((tree, tree));
+static tree build_vtbl_initializer PARAMS ((tree, tree, int *));
static int count_fields PARAMS ((tree));
static int add_fields_to_vec PARAMS ((tree, tree, int));
static void check_bitfield_decl PARAMS ((tree));
@@ -135,19 +145,17 @@ static void propagate_binfo_offsets PARAMS ((tree, tree));
static void layout_virtual_bases PARAMS ((tree, varray_type *));
static tree dfs_set_offset_for_shared_vbases PARAMS ((tree, void *));
static tree dfs_set_offset_for_unshared_vbases PARAMS ((tree, void *));
-static tree dfs_build_vbase_offset_vtbl_entries PARAMS ((tree, void *));
-static tree build_vbase_offset_vtbl_entries PARAMS ((tree, tree));
+static void build_vbase_offset_vtbl_entries PARAMS ((tree, vcall_offset_data *));
static tree dfs_vcall_offset_queue_p PARAMS ((tree, void *));
static tree dfs_build_vcall_offset_vtbl_entries PARAMS ((tree, void *));
-static tree build_vcall_offset_vtbl_entries PARAMS ((tree, tree));
-static tree dfs_count_virtuals PARAMS ((tree, void *));
+static void build_vcall_offset_vtbl_entries PARAMS ((tree, vcall_offset_data *));
static void layout_vtable_decl PARAMS ((tree, int));
-static int num_vfun_entries PARAMS ((tree));
static tree dfs_find_final_overrider PARAMS ((tree, void *));
static tree find_final_overrider PARAMS ((tree, tree, tree));
static tree dfs_find_base PARAMS ((tree, void *));
static int make_new_vtable PARAMS ((tree, tree));
-extern void dump_class_hierarchy PARAMS ((tree, int));
+static void dump_class_hierarchy_r PARAMS ((tree, tree, int));
+extern void dump_class_hierarchy PARAMS ((tree));
static tree build_vtable PARAMS ((tree, tree, tree));
static void initialize_vtable PARAMS ((tree, tree));
static void layout_nonempty_base_or_field PARAMS ((record_layout_info,
@@ -162,6 +170,10 @@ static void layout_empty_base PARAMS ((tree, tree, varray_type));
static void accumulate_vtbl_inits PARAMS ((tree, tree));
static void set_vindex PARAMS ((tree, tree, int *));
static tree build_rtti_vtbl_entries PARAMS ((tree, tree));
+static void build_vcall_and_vbase_vtbl_entries PARAMS ((tree,
+ vcall_offset_data *));
+static tree dfs_mark_primary_bases PARAMS ((tree, void *));
+static void mark_primary_bases PARAMS ((tree));
/* Variables shared between class.c and call.c. */
@@ -274,9 +286,10 @@ build_vbase_pointer (exp, type)
/* Find the virtual function table pointer. */
vbase_ptr = build_vfield_ref (exp, TREE_TYPE (exp));
/* Compute the location where the offset will lie. */
- vbase_ptr = build_binary_op (PLUS_EXPR,
- vbase_ptr,
- BINFO_VPTR_FIELD (vbase));
+ vbase_ptr = build (PLUS_EXPR,
+ TREE_TYPE (vbase_ptr),
+ vbase_ptr,
+ BINFO_VPTR_FIELD (vbase));
vbase_ptr = build1 (NOP_EXPR,
build_pointer_type (ptrdiff_type_node),
vbase_ptr);
@@ -462,7 +475,7 @@ build_vtable_entry_ref (basetype, vtbl, idx)
static char asm_stmt[] = ".vtable_entry %c0, %c1";
tree s, i, i2;
- s = build_unary_op (ADDR_EXPR, TYPE_BINFO_VTABLE (basetype), 0);
+ s = build_unary_op (ADDR_EXPR, get_vtbl_decl_for_binfo (basetype), 0);
s = build_tree_list (build_string (1, "s"), s);
i = build_array_ref (vtbl, idx);
@@ -533,7 +546,23 @@ build_vtbl_ref (instance, idx)
&& (TREE_CODE (instance) == RESULT_DECL
|| TREE_CODE (instance) == PARM_DECL
|| TREE_CODE (instance) == VAR_DECL))
- vtbl = TYPE_BINFO_VTABLE (basetype);
+ {
+ vtbl = TYPE_BINFO_VTABLE (basetype);
+ /* Knowing the dynamic type of INSTANCE we can easily obtain
+ the correct vtable entry. In the new ABI, we resolve
+ this back to be in terms of the primary vtable. */
+ if (TREE_CODE (vtbl) == PLUS_EXPR)
+ {
+ idx = fold (build (PLUS_EXPR,
+ TREE_TYPE (idx),
+ idx,
+ build (EXACT_DIV_EXPR,
+ TREE_TYPE (idx),
+ TREE_OPERAND (vtbl, 1),
+ TYPE_SIZE_UNIT (vtable_entry_type))));
+ vtbl = get_vtbl_decl_for_binfo (TYPE_BINFO (basetype));
+ }
+ }
else
vtbl = build_vfield_ref (instance, basetype);
}
@@ -733,10 +762,9 @@ build_primary_vtable (binfo, type)
return 0;
virtuals = copy_list (BINFO_VIRTUALS (binfo));
- TREE_TYPE (decl) = TREE_TYPE (BINFO_VTABLE (binfo));
- DECL_SIZE (decl) = TYPE_SIZE (TREE_TYPE (BINFO_VTABLE (binfo)));
- DECL_SIZE_UNIT (decl)
- = TYPE_SIZE_UNIT (TREE_TYPE (BINFO_VTABLE (binfo)));
+ TREE_TYPE (decl) = TREE_TYPE (get_vtbl_decl_for_binfo (binfo));
+ DECL_SIZE (decl) = TYPE_SIZE (TREE_TYPE (decl));
+ DECL_SIZE_UNIT (decl) = TYPE_SIZE_UNIT (TREE_TYPE (decl));
}
else
{
@@ -1623,6 +1651,97 @@ check_bases (t, cant_have_default_ctor_p, cant_have_const_ctor_p,
}
}
+/* Called via dfs_walk from mark_primary_bases. Sets
+ BINFO_PRIMARY_MARKED_P for BINFO, if appropriate. */
+
+static tree
+dfs_mark_primary_bases (binfo, data)
+ tree binfo;
+ void *data;
+{
+ int i;
+ tree base_binfo;
+
+ if (!CLASSTYPE_HAS_PRIMARY_BASE_P (BINFO_TYPE (binfo)))
+ return NULL_TREE;
+
+ i = CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (binfo));
+ base_binfo = BINFO_BASETYPE (binfo, i);
+
+ if (!TREE_VIA_VIRTUAL (base_binfo))
+ /* Non-virtual base classes are easy. */
+ BINFO_PRIMARY_MARKED_P (base_binfo) = 1;
+ else
+ {
+ tree shared_binfo;
+
+ shared_binfo
+ = BINFO_FOR_VBASE (BINFO_TYPE (base_binfo), (tree) data);
+
+ /* If this virtual base is not already primary somewhere else in
+ the hiearchy, then we'll be using this copy. */
+ if (!BINFO_VBASE_PRIMARY_P (shared_binfo))
+ {
+ BINFO_VBASE_PRIMARY_P (shared_binfo) = 1;
+ BINFO_PRIMARY_MARKED_P (base_binfo) = 1;
+ }
+ }
+
+ return NULL_TREE;
+}
+
+/* Set BINFO_PRIMARY_MARKED_P for all binfos in the hierarchy
+ dominated by BINFO that are primary bases. */
+
+static void
+mark_primary_bases (type)
+ tree type;
+{
+ tree vbases;
+
+ /* Mark the TYPE_BINFO hierarchy. We need to mark primary bases in
+ pre-order to deal with primary virtual bases. (The virtual base
+ would be skipped if it were not marked as primary, and that
+ requires getting to dfs_mark_primary_bases before
+ dfs_skip_nonprimary_vbases_unmarkedp has a chance to skip the
+ virtual base.) */
+ dfs_walk_real (TYPE_BINFO (type), dfs_mark_primary_bases, NULL,
+ dfs_skip_nonprimary_vbases_unmarkedp, type);
+
+ /* Now go through the virtual base classes in inheritance graph
+ order. Any that are not already primary will need to be
+ allocated in TYPE, and so we need to mark their primary bases. */
+ for (vbases = TYPE_BINFO (type); vbases; vbases = TREE_CHAIN (vbases))
+ {
+ tree vbase;
+
+ /* Make sure that only BINFOs appear on this list.
+ Historically, the TREE_CHAIN was used for other purposes, and
+ we want to make sure that none of those uses remain. */
+ my_friendly_assert (TREE_CODE (vbases) == TREE_VEC, 20000402);
+
+ if (!TREE_VIA_VIRTUAL (vbases))
+ continue;
+
+ vbase = BINFO_FOR_VBASE (BINFO_TYPE (vbases), type);
+ if (BINFO_VBASE_PRIMARY_P (vbase))
+ /* This virtual base was already included in the hierarchy, so
+ there's nothing to do here. */
+ continue;
+
+ /* Temporarily pretend that VBASE is primary so that its bases
+ will be walked; this is the real copy of VBASE. */
+ BINFO_PRIMARY_MARKED_P (vbase) = 1;
+
+ /* Now, walk its bases. */
+ dfs_walk_real (vbase, dfs_mark_primary_bases, NULL,
+ dfs_skip_nonprimary_vbases_unmarkedp, type);
+
+ /* VBASE wasn't really primary. */
+ BINFO_PRIMARY_MARKED_P (vbase) = 0;
+ }
+}
+
/* Make the Ith baseclass of T its primary base. */
static void
@@ -1696,7 +1815,7 @@ determine_primary_base (t, vfuns_p)
VF_BASETYPE_VALUE (vfields),
CLASSTYPE_VFIELDS (t));
- if (*vfuns_p == 0)
+ if (!flag_new_abi && *vfuns_p == 0)
set_primary_base (t, i, vfuns_p);
}
}
@@ -2184,6 +2303,7 @@ layout_vtable_decl (binfo, n)
{
tree itype;
tree atype;
+ tree vtable;
itype = size_int (n);
atype = build_cplus_array_type (vtable_entry_type,
@@ -2191,12 +2311,11 @@ layout_vtable_decl (binfo, n)
layout_type (atype);
/* We may have to grow the vtable. */
- if (!same_type_p (TREE_TYPE (BINFO_VTABLE (binfo)), atype))
+ vtable = get_vtbl_decl_for_binfo (binfo);
+ if (!same_type_p (TREE_TYPE (vtable), atype))
{
- tree vtable = BINFO_VTABLE (binfo);
-
TREE_TYPE (vtable) = atype;
- DECL_SIZE (vtable) = DECL_SIZE_UNIT (vtable) = 0;
+ DECL_SIZE (vtable) = DECL_SIZE_UNIT (vtable) = NULL_TREE;
layout_decl (vtable, 0);
/* At one time the vtable info was grabbed 2 words at a time. This
@@ -2206,104 +2325,6 @@ layout_vtable_decl (binfo, n)
}
}
-/* Returns the number of virtual function table entries (excluding
- RTTI information, vbase and vcall offests, etc.) in the vtable for
- BINFO. */
-
-static int
-num_vfun_entries (binfo)
- tree binfo;
-{
- return list_length (BINFO_VIRTUALS (binfo));
-}
-
-typedef struct vcall_offset_data_s
-{
- /* The binfo for the most-derived type. */
- tree derived;
- /* The binfo for the virtual base for which we're building
- initializers. */
- tree vbase;
- /* The vcall offset initializers built up so far. */
- tree inits;
- /* The number of vcall offsets accumulated. */
- int offsets;
-} vcall_offset_data;
-
-/* Called from num_extra_vtbl_entries via dfs_walk. */
-
-static tree
-dfs_count_virtuals (binfo, data)
- tree binfo;
- void *data;
-{
- /* Non-primary bases are not interesting; all of the virtual
- function table entries have been overridden. */
- if (!BINFO_PRIMARY_MARKED_P (binfo))
- ((vcall_offset_data *) data)->offsets += num_vfun_entries (binfo);
-
- return NULL_TREE;
-}
-
-/* Returns the number of extra entries (at negative indices) required
- for BINFO's vtable. */
-
-tree
-num_extra_vtbl_entries (binfo)
- tree binfo;
-{
- tree type;
- int entries;
-
- type = BINFO_TYPE (binfo);
- entries = 0;
-
- /* There is an entry for the offset to each virtual base. */
- if (vbase_offsets_in_vtable_p ())
- entries += list_length (CLASSTYPE_VBASECLASSES (type));
-
- /* If this is a virtual base, there are entries for each virtual
- function defined in this class or its bases. */
- if (vcall_offsets_in_vtable_p () && TREE_VIA_VIRTUAL (binfo))
- {
- vcall_offset_data vod;
-
- vod.vbase = binfo;
- vod.offsets = 0;
- dfs_walk (binfo,
- dfs_count_virtuals,
- dfs_vcall_offset_queue_p,
- &vod);
- entries += vod.offsets;
- }
-
- /* When laying out COM-compatible classes, there are no RTTI
- entries. */
- if (CLASSTYPE_COM_INTERFACE (type))
- ;
- /* When using vtable thunks, there are two RTTI entries: the "offset
- to top" value and the RTTI entry itself. */
- else if (flag_vtable_thunks)
- entries += 2;
- /* When not using vtable thunks there is only a single entry. */
- else
- entries += 1;
-
- return size_int (entries);
-}
-
-/* Returns the offset (in bytes) from the beginning of BINFO's vtable
- where the vptr should actually point. */
-
-tree
-size_extra_vtbl_entries (binfo)
- tree binfo;
-{
- tree offset = size_binop (MULT_EXPR, TYPE_SIZE_UNIT (vtable_entry_type),
- num_extra_vtbl_entries (binfo));
- return fold (offset);
-}
-
/* True if we should override the given BASE_FNDECL with the given
FNDECL. */
@@ -3989,7 +4010,7 @@ check_bases_and_members (t, empty_p)
/* If T needs a pointer to its virtual function table, set TYPE_VFIELD
accordingly. If a new vfield was created (because T doesn't have a
primary base class), then the newly created field is returned. It
- is not added to the TYPE_FIELDS list; it is the callers
+ is not added to the TYPE_FIELDS list; it is the caller's
responsibility to do that. */
static tree
@@ -4205,7 +4226,7 @@ layout_virtual_bases (t, base_offsets)
tree t;
varray_type *base_offsets;
{
- tree vbase;
+ tree vbases;
unsigned HOST_WIDE_INT dsize;
unsigned HOST_WIDE_INT eoc;
@@ -4225,53 +4246,70 @@ layout_virtual_bases (t, base_offsets)
TYPE_ALIGN (t) = MAX (TYPE_ALIGN (t), BITS_PER_UNIT);
/* Go through the virtual bases, allocating space for each virtual
- base that is not already a primary base class. */
- for (vbase = CLASSTYPE_VBASECLASSES (t);
- vbase;
- vbase = TREE_CHAIN (vbase))
- if (!BINFO_VBASE_PRIMARY_P (vbase))
- {
- /* This virtual base is not a primary base of any class in the
- hierarchy, so we have to add space for it. */
- tree basetype;
- unsigned int desired_align;
+ base that is not already a primary base class. Under the new
+ ABI, these are allocated according to a depth-first left-to-right
+ postorder traversal; in the new ABI, inheritance graph order is
+ used instead. */
+ for (vbases = (flag_new_abi
+ ? TYPE_BINFO (t)
+ : CLASSTYPE_VBASECLASSES (t));
+ vbases;
+ vbases = TREE_CHAIN (vbases))
+ {
+ tree vbase;
+
+ if (!TREE_VIA_VIRTUAL (vbases))
+ continue;
+
+ if (flag_new_abi)
+ vbase = BINFO_FOR_VBASE (BINFO_TYPE (vbases), t);
+ else
+ vbase = vbases;
+
+ if (!BINFO_VBASE_PRIMARY_P (vbase))
+ {
+ /* This virtual base is not a primary base of any class in the
+ hierarchy, so we have to add space for it. */
+ tree basetype;
+ unsigned int desired_align;
- basetype = BINFO_TYPE (vbase);
+ basetype = BINFO_TYPE (vbase);
- if (flag_new_abi)
- desired_align = CLASSTYPE_ALIGN (basetype);
- else
- /* Under the old ABI, virtual bases were aligned as for the
+ if (flag_new_abi)
+ desired_align = CLASSTYPE_ALIGN (basetype);
+ else
+ /* Under the old ABI, virtual bases were aligned as for the
entire base object (including its virtual bases). That's
wasteful, in general. */
- desired_align = TYPE_ALIGN (basetype);
- TYPE_ALIGN (t) = MAX (TYPE_ALIGN (t), desired_align);
-
- /* Add padding so that we can put the virtual base class at an
- appropriately aligned offset. */
- dsize = CEIL (dsize, desired_align) * desired_align;
-
- /* Under the new ABI, we try to squish empty virtual bases in
- just like ordinary empty bases. */
- if (flag_new_abi && is_empty_class (basetype))
- layout_empty_base (vbase,
- size_int (CEIL (dsize, BITS_PER_UNIT)),
- *base_offsets);
- else
- {
- /* And compute the offset of the virtual base. */
- propagate_binfo_offsets (vbase,
- ssize_int (CEIL (dsize, BITS_PER_UNIT)));
- /* Every virtual baseclass takes a least a UNIT, so that
- we can take it's address and get something different
- for each base. */
- dsize += MAX (BITS_PER_UNIT,
- tree_low_cst (CLASSTYPE_SIZE (basetype), 0));
- }
+ desired_align = TYPE_ALIGN (basetype);
+ TYPE_ALIGN (t) = MAX (TYPE_ALIGN (t), desired_align);
+
+ /* Add padding so that we can put the virtual base class at an
+ appropriately aligned offset. */
+ dsize = CEIL (dsize, desired_align) * desired_align;
+
+ /* Under the new ABI, we try to squish empty virtual bases in
+ just like ordinary empty bases. */
+ if (flag_new_abi && is_empty_class (basetype))
+ layout_empty_base (vbase,
+ size_int (CEIL (dsize, BITS_PER_UNIT)),
+ *base_offsets);
+ else
+ {
+ /* And compute the offset of the virtual base. */
+ propagate_binfo_offsets (vbase,
+ ssize_int (CEIL (dsize, BITS_PER_UNIT)));
+ /* Every virtual baseclass takes a least a UNIT, so that
+ we can take it's address and get something different
+ for each base. */
+ dsize += MAX (BITS_PER_UNIT,
+ tree_low_cst (CLASSTYPE_SIZE (basetype), 0));
+ }
- /* Keep track of the offsets assigned to this virtual base. */
- record_base_offsets (vbase, base_offsets);
- }
+ /* Keep track of the offsets assigned to this virtual base. */
+ record_base_offsets (vbase, base_offsets);
+ }
+ }
/* Make sure that all of the CLASSTYPE_VBASECLASSES have their
BINFO_OFFSET set correctly. Those we just allocated certainly
@@ -4288,10 +4326,10 @@ layout_virtual_bases (t, base_offsets)
in get_base_distance depend on the BINFO_OFFSETs being set
correctly. */
dfs_walk (TYPE_BINFO (t), dfs_set_offset_for_unshared_vbases, NULL, t);
- for (vbase = CLASSTYPE_VBASECLASSES (t);
- vbase;
- vbase = TREE_CHAIN (vbase))
- dfs_walk (vbase, dfs_set_offset_for_unshared_vbases, NULL, t);
+ for (vbases = CLASSTYPE_VBASECLASSES (t);
+ vbases;
+ vbases = TREE_CHAIN (vbases))
+ dfs_walk (vbases, dfs_set_offset_for_unshared_vbases, NULL, t);
/* If we had empty base classes that protruded beyond the end of the
class, we didn't update DSIZE above; we were hoping to overlay
@@ -4310,11 +4348,11 @@ layout_virtual_bases (t, base_offsets)
/* Check for ambiguous virtual bases. */
if (extra_warnings)
- for (vbase = CLASSTYPE_VBASECLASSES (t);
- vbase;
- vbase = TREE_CHAIN (vbase))
+ for (vbases = CLASSTYPE_VBASECLASSES (t);
+ vbases;
+ vbases = TREE_CHAIN (vbases))
{
- tree basetype = BINFO_TYPE (vbase);
+ tree basetype = BINFO_TYPE (vbases);
if (get_base_distance (basetype, t, 0, (tree*)0) == -2)
cp_warning ("virtual base `%T' inaccessible in `%T' due to ambiguity",
basetype, t);
@@ -4572,7 +4610,7 @@ layout_class_type (t, empty_p, vfuns_p,
/* Clean up. */
VARRAY_FREE (v);
}
-
+
/* Create a RECORD_TYPE or UNION_TYPE node for a C struct or union declaration
(or C++ class declaration).
@@ -4791,7 +4829,7 @@ finish_struct_1 (t)
the base types we marked. */
finish_vtbls (t);
- if (CLASSTYPE_VSIZE (t) != 0)
+ if (TYPE_VFIELD (t))
{
/* In addition to this one, all the other vfields should be listed. */
/* Before that can be done, we have to have FIELD_DECLs for them, and
@@ -5030,13 +5068,13 @@ init_class_processing ()
* sizeof (struct class_stack_node));
access_default_node = build_int_2 (0, 0);
- access_public_node = build_int_2 (1, 0);
- access_protected_node = build_int_2 (2, 0);
- access_private_node = build_int_2 (3, 0);
+ access_public_node = build_int_2 (ak_public, 0);
+ access_protected_node = build_int_2 (ak_protected, 0);
+ access_private_node = build_int_2 (ak_private, 0);
access_default_virtual_node = build_int_2 (4, 0);
- access_public_virtual_node = build_int_2 (5, 0);
- access_protected_virtual_node = build_int_2 (6, 0);
- access_private_virtual_node = build_int_2 (7, 0);
+ access_public_virtual_node = build_int_2 (4 | ak_public, 0);
+ access_protected_virtual_node = build_int_2 (4 | ak_protected, 0);
+ access_private_virtual_node = build_int_2 (4 | ak_private, 0);
}
/* Set current scope to NAME. CODE tells us if this is a
@@ -6047,12 +6085,36 @@ note_name_declared_in_class (name, decl)
}
}
-/* Dump the offsets of all the bases rooted at BINFO to stderr.
- INDENT should be zero when called from the top level; it is
- incremented recursively. */
+/* Returns the VAR_DECL for the complete vtable associated with
+ BINFO. (Under the new ABI, secondary vtables are merged with
+ primary vtables; this function will return the VAR_DECL for the
+ primary vtable.) */
-void
-dump_class_hierarchy (binfo, indent)
+tree
+get_vtbl_decl_for_binfo (binfo)
+ tree binfo;
+{
+ tree decl;
+
+ decl = BINFO_VTABLE (binfo);
+ if (decl && TREE_CODE (decl) == PLUS_EXPR)
+ {
+ my_friendly_assert (TREE_CODE (TREE_OPERAND (decl, 0)) == ADDR_EXPR,
+ 2000403);
+ decl = TREE_OPERAND (TREE_OPERAND (decl, 0), 0);
+ }
+ if (decl)
+ my_friendly_assert (TREE_CODE (decl) == VAR_DECL, 20000403);
+ return decl;
+}
+
+/* Dump the offsets of all the bases rooted at BINFO (in the hierarchy
+ dominated by T) to stderr. INDENT should be zero when called from
+ the top level; it is incremented recursively. */
+
+static void
+dump_class_hierarchy_r (t, binfo, indent)
+ tree t;
tree binfo;
int indent;
{
@@ -6063,11 +6125,31 @@ dump_class_hierarchy (binfo, indent)
type_as_string (binfo, TS_PLAIN));
fprintf (stderr, HOST_WIDE_INT_PRINT_DEC,
tree_low_cst (BINFO_OFFSET (binfo), 0));
- fprintf (stderr, " %s\n",
- BINFO_PRIMARY_MARKED_P (binfo) ? "primary" : "");
+ if (TREE_VIA_VIRTUAL (binfo))
+ fprintf (stderr, " virtual");
+ if (BINFO_PRIMARY_MARKED_P (binfo)
+ || (TREE_VIA_VIRTUAL (binfo)
+ && BINFO_VBASE_PRIMARY_P (BINFO_FOR_VBASE (BINFO_TYPE (binfo),
+ t))))
+ fprintf (stderr, " primary");
+ fprintf (stderr, "\n");
for (i = 0; i < BINFO_N_BASETYPES (binfo); ++i)
- dump_class_hierarchy (BINFO_BASETYPE (binfo, i), indent + 2);
+ dump_class_hierarchy_r (t, BINFO_BASETYPE (binfo, i), indent + 2);
+}
+
+/* Dump the BINFO hierarchy for T. */
+
+void
+dump_class_hierarchy (t)
+ tree t;
+{
+ tree vbase;
+
+ dump_class_hierarchy_r (t, TYPE_BINFO (t), 0);
+ fprintf (stderr, "virtual bases\n");
+ for (vbase = CLASSTYPE_VBASECLASSES (t); vbase; vbase = TREE_CHAIN (vbase))
+ dump_class_hierarchy_r (t, vbase, 0);
}
/* Virtual function table initialization. */
@@ -6087,14 +6169,18 @@ finish_vtbls (t)
vtables in one contiguous vtable. The primary vtable is
first, followed by the non-virtual secondary vtables in
inheritance graph order. */
- list = build_tree_list (t, NULL_TREE);
+ list = build_tree_list (TYPE_BINFO_VTABLE (t), NULL_TREE);
+ TREE_TYPE (list) = t;
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);
+ for (vbase = TYPE_BINFO (t); vbase; vbase = TREE_CHAIN (vbase))
+ {
+ if (!TREE_VIA_VIRTUAL (vbase))
+ continue;
+ accumulate_vtbl_inits (BINFO_FOR_VBASE (BINFO_TYPE (vbase), t),
+ list);
+ }
if (TYPE_BINFO_VTABLE (t))
initialize_vtable (TYPE_BINFO (t), TREE_VALUE (list));
@@ -6121,7 +6207,7 @@ dfs_finish_vtbls (binfo, data)
&& CLASSTYPE_VFIELDS (BINFO_TYPE (binfo))
&& BINFO_NEW_VTABLE_MARKED (binfo, t))
initialize_vtable (binfo,
- build_vtbl_initializer (binfo, t));
+ build_vtbl_initializer (binfo, t, NULL));
CLEAR_BINFO_NEW_VTABLE_MARKED (binfo, t);
SET_BINFO_MARKED (binfo);
@@ -6140,7 +6226,7 @@ initialize_vtable (binfo, inits)
tree decl;
layout_vtable_decl (binfo, list_length (inits));
- decl = BINFO_VTABLE (binfo);
+ decl = get_vtbl_decl_for_binfo (binfo);
context = DECL_CONTEXT (decl);
DECL_CONTEXT (decl) = 0;
DECL_INITIAL (decl) = build_nt (CONSTRUCTOR, NULL_TREE, inits);
@@ -6156,10 +6242,12 @@ accumulate_vtbl_inits (binfo, inits)
tree binfo;
tree inits;
{
- /* Walk the BINFO and its bases. */
+ /* Walk the BINFO and its bases. We walk in preorder so that as we
+ initialize each vtable we can figure out at what offset the
+ secondary vtable lies from the primary vtable. */
dfs_walk_real (binfo,
dfs_accumulate_vtbl_inits,
- NULL,
+ NULL,
dfs_skip_vbases,
inits);
}
@@ -6177,33 +6265,37 @@ dfs_accumulate_vtbl_inits (binfo, data)
tree t;
l = (tree) data;
- t = TREE_PURPOSE (l);
+ t = TREE_TYPE (l);
if (!BINFO_PRIMARY_MARKED_P (binfo)
&& CLASSTYPE_VFIELDS (BINFO_TYPE (binfo))
&& BINFO_NEW_VTABLE_MARKED (binfo, t))
{
- /* If this is a secondary vtable, record its location. */
- if (binfo != TYPE_BINFO (t))
- {
- tree vtbl;
-
- vtbl = TYPE_BINFO_VTABLE (t);
- vtbl = build1 (ADDR_EXPR,
- build_pointer_type (TREE_TYPE (vtbl)),
- vtbl);
- BINFO_VTABLE (binfo)
- = build (PLUS_EXPR, TREE_TYPE (vtbl), vtbl,
- size_binop (MULT_EXPR,
- TYPE_SIZE_UNIT (TREE_TYPE (vtbl)),
- size_int (list_length (TREE_VALUE (l)))));
- }
+ tree inits;
+ tree vtbl;
+ tree index;
+ int non_fn_entries;
+
+ /* Compute the initializer for this vtable. */
+ inits = build_vtbl_initializer (binfo, t, &non_fn_entries);
+
+ /* Set BINFO_VTABLE to the address where the VPTR should point. */
+ vtbl = TREE_PURPOSE (l);
+ vtbl = build1 (ADDR_EXPR,
+ build_pointer_type (TREE_TYPE (vtbl)),
+ vtbl);
+ index = size_binop (PLUS_EXPR,
+ size_int (non_fn_entries),
+ size_int (list_length (TREE_VALUE (l))));
+ BINFO_VTABLE (binfo)
+ = build (PLUS_EXPR, TREE_TYPE (vtbl), vtbl,
+ size_binop (MULT_EXPR,
+ TYPE_SIZE_UNIT (TREE_TYPE (vtbl)),
+ index));
/* 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));
+ TREE_VALUE (l) = chainon (TREE_VALUE (l), inits);
}
CLEAR_BINFO_NEW_VTABLE_MARKED (binfo, t);
@@ -6214,29 +6306,48 @@ dfs_accumulate_vtbl_inits (binfo, data)
/* Construct the initializer for BINFOs virtual function table. BINFO
is part of the hierarchy dominated by T. The value returned is a
TREE_LIST suitable for wrapping in a CONSTRUCTOR to use as the
- DECL_INITIAL for a vtable. */
+ DECL_INITIAL for a vtable. If NON_FN_ENTRIES_P is not NULL,
+ *NON_FN_ENTRIES_P is set to the number of non-function entries in
+ the vtable. */
static tree
-build_vtbl_initializer (binfo, t)
+build_vtbl_initializer (binfo, t, non_fn_entries_p)
tree binfo;
tree t;
+ int *non_fn_entries_p;
{
tree v = BINFO_VIRTUALS (binfo);
tree inits = NULL_TREE;
+ tree vfun_inits;
+ tree vbase;
+ vcall_offset_data vod;
- /* Add entries to the vtable that indicate how to adjust the this
- pointer when calling a virtual function in this class. */
- inits = build_vcall_offset_vtbl_entries (binfo, t);
-
- /* Add entries to the vtable for offsets to our virtual bases. */
- inits = chainon (build_vbase_offset_vtbl_entries (binfo, t),
- inits);
+ /* Initialize those parts of VOD that matter. */
+ vod.derived = t;
+ vod.inits = NULL_TREE;
+ vod.primary_p = (binfo == TYPE_BINFO (t));
+ /* The first vbase or vcall offset is at index -3 in the vtable. */
+ vod.index = build_int_2 (-3, -1);
+
+ /* Add the vcall and vbase offset entries. */
+ build_vcall_and_vbase_vtbl_entries (binfo, &vod);
+ inits = vod.inits;
+ /* Clear BINFO_VTABLE_PAATH_MARKED; it's set by
+ build_vbase_offset_vtbl_entries. */
+ for (vbase = CLASSTYPE_VBASECLASSES (t);
+ vbase;
+ vbase = TREE_CHAIN (vbase))
+ CLEAR_BINFO_VTABLE_PATH_MARKED (vbase);
/* Add entries to the vtable for RTTI. */
- inits = chainon (build_rtti_vtbl_entries (binfo, t), inits);
+ inits = chainon (inits, build_rtti_vtbl_entries (binfo, t));
+
+ if (non_fn_entries_p)
+ *non_fn_entries_p = list_length (inits);
/* Go through all the ordinary virtual functions, building up
initializers. */
+ vfun_inits = NULL_TREE;
while (v)
{
tree delta;
@@ -6266,118 +6377,133 @@ build_vtbl_initializer (binfo, t)
/* Enter it in the vtable. */
init = build_vtable_entry (delta, vcall_index, pfn);
/* And add it to the chain of initializers. */
- inits = tree_cons (NULL_TREE, init, inits);
+ vfun_inits = tree_cons (NULL_TREE, init, vfun_inits);
/* Keep going. */
v = TREE_CHAIN (v);
}
- /* The initializers were built up in reverse order; straighten them
- out now. */
- return nreverse (inits);
+ /* The initializers for virtual functions were built up in reverse
+ order; straighten them out now. */
+ vfun_inits = nreverse (vfun_inits);
+
+ /* The complete initializer is the INITS, followed by the
+ VFUN_INITS. */
+ return chainon (inits, vfun_inits);
}
-/* Called from build_vbase_offset_vtbl_entries via dfs_walk. */
+/* Sets vod->inits to be the initializers for the vbase and vcall
+ offsets in BINFO, which is in the hierarchy dominated by T. */
-static tree
-dfs_build_vbase_offset_vtbl_entries (binfo, data)
+static void
+build_vcall_and_vbase_vtbl_entries (binfo, vod)
tree binfo;
- void *data;
+ vcall_offset_data *vod;
{
- tree list = (tree) data;
-
- if (TREE_TYPE (list) == binfo)
- /* The TREE_TYPE of LIST is the base class from which we started
- walking. If that BINFO is virtual it's not a virtual baseclass
- of itself. */
- ;
- else if (TREE_VIA_VIRTUAL (binfo))
- {
- tree init;
- tree vbase;
-
- /* Remember the index to the vbase offset for this virtual
- base. */
- vbase = BINFO_FOR_VBASE (BINFO_TYPE (binfo), TREE_PURPOSE (list));
- if (!TREE_VALUE (list))
- BINFO_VPTR_FIELD (vbase) = build_int_2 (-3, 0);
- else
- {
- BINFO_VPTR_FIELD (vbase) = TREE_PURPOSE (TREE_VALUE (list));
- BINFO_VPTR_FIELD (vbase)
- = fold (build (MINUS_EXPR, integer_type_node,
- BINFO_VPTR_FIELD (vbase), integer_one_node));
- }
-
- /* And record the offset at which this virtual base lies in the
- vtable. */
- init = BINFO_OFFSET (binfo);
- TREE_VALUE (list) = tree_cons (BINFO_VPTR_FIELD (vbase),
- init, TREE_VALUE (list));
- }
+ tree b;
+ tree inits;
- SET_BINFO_VTABLE_PATH_MARKED (binfo);
-
- return NULL_TREE;
+ /* If this is a derived class, we must first create entries
+ corresponding to the base class. These entries must go closer to
+ the vptr, so we save them up and add them to the end of the list
+ later. */
+ inits = vod->inits;
+ vod->inits = NULL_TREE;
+ b = BINFO_PRIMARY_BINFO (binfo);
+ if (b)
+ build_vcall_and_vbase_vtbl_entries (b, vod);
+
+ /* Add the vbase entries for this base. */
+ build_vbase_offset_vtbl_entries (binfo, vod);
+ /* Add the vcall entries for this base. */
+ build_vcall_offset_vtbl_entries (binfo, vod);
+
+ vod->inits = chainon (vod->inits, inits);
}
/* Returns the initializers for the vbase offset entries in the vtable
for BINFO (which is part of the class hierarchy dominated by T), in
- reverse order. */
+ reverse order. VBASE_OFFSET_INDEX gives the vtable index
+ where the next vbase offset will go. */
-static tree
-build_vbase_offset_vtbl_entries (binfo, t)
+static void
+build_vbase_offset_vtbl_entries (binfo, vod)
tree binfo;
- tree t;
+ vcall_offset_data *vod;
{
- tree inits;
- tree init;
- tree list;
+ tree vbase;
+ tree t;
/* Under the old ABI, pointers to virtual bases are stored in each
object. */
if (!vbase_offsets_in_vtable_p ())
- return NULL_TREE;
+ return;
/* If there are no virtual baseclasses, then there is nothing to
do. */
if (!TYPE_USES_VIRTUAL_BASECLASSES (BINFO_TYPE (binfo)))
- return NULL_TREE;
+ return;
- inits = NULL_TREE;
+ t = vod->derived;
- /* The offsets are allocated in the reverse order of a
- depth-first left-to-right traversal of the hierarchy. We use
- BINFO_VTABLE_PATH_MARKED because we are ourselves during a
- dfs_walk, and so BINFO_MARKED is already in use. */
- list = build_tree_list (t, NULL_TREE);
- TREE_TYPE (list) = binfo;
- dfs_walk (binfo,
- dfs_build_vbase_offset_vtbl_entries,
- unmarked_vtable_pathp,
- list);
- dfs_walk (binfo,
- dfs_vtable_path_unmark,
- marked_vtable_pathp,
- list);
- inits = nreverse (TREE_VALUE (list));
-
- /* We've now got offsets in the right order. However, the offsets
- we've stored are offsets from the beginning of the complete
- object, and we need offsets from this BINFO. */
- for (init = inits; init; init = TREE_CHAIN (init))
- {
- /* The dfs_build_vbase_offset_vtbl_entries routine uses the
- TREE_PURPOSE to scribble in. But, we need to clear it now so
- that the values are not perceived as labeled initializers. */
- TREE_PURPOSE (init) = NULL_TREE;
- TREE_VALUE (init)
- = fold (build1 (NOP_EXPR, vtable_entry_type,
- size_diffop (TREE_VALUE (init),
- BINFO_OFFSET (binfo))));
- }
+ /* Go through the virtual bases, adding the offsets. */
+ for (vbase = TYPE_BINFO (BINFO_TYPE (binfo));
+ vbase;
+ vbase = TREE_CHAIN (vbase))
+ {
+ tree b;
+ tree delta;
+
+ if (!TREE_VIA_VIRTUAL (vbase))
+ continue;
- return inits;
+ /* Find the instance of this virtual base in the complete
+ object. */
+ b = BINFO_FOR_VBASE (BINFO_TYPE (vbase), t);
+
+ /* If we've already got an offset for this virtual base, we
+ don't need another one. */
+ if (BINFO_VTABLE_PATH_MARKED (b))
+ continue;
+ SET_BINFO_VTABLE_PATH_MARKED (b);
+
+ /* Figure out where we can find this vbase offset. */
+ delta = size_binop (MULT_EXPR,
+ convert (ssizetype, vod->index),
+ convert (ssizetype,
+ TYPE_SIZE_UNIT (vtable_entry_type)));
+ if (vod->primary_p)
+ BINFO_VPTR_FIELD (b) = delta;
+
+ if (binfo != TYPE_BINFO (t))
+ {
+ tree orig_vbase;
+
+ /* Find the instance of this virtual base in the type of BINFO. */
+ orig_vbase = BINFO_FOR_VBASE (BINFO_TYPE (vbase),
+ BINFO_TYPE (binfo));
+
+ /* The vbase offset had better be the same. */
+ if (!tree_int_cst_equal (delta,
+ BINFO_VPTR_FIELD (orig_vbase)))
+ my_friendly_abort (20000403);
+ }
+
+ /* The next vbase will come at a more negative offset. */
+ vod->index = fold (build (MINUS_EXPR, integer_type_node,
+ vod->index, integer_one_node));
+
+ /* The initializer is the delta from BINFO to this virtual base.
+ The vbase offsets go in reverse inheritance-graph order, and
+ we are walking in inheritance graph order so these end up in
+ the right order. */
+ delta = size_diffop (BINFO_OFFSET (b), BINFO_OFFSET (binfo));
+ vod->inits = tree_cons (NULL_TREE,
+ fold (build1 (NOP_EXPR,
+ vtable_entry_type,
+ delta)),
+ vod->inits);
+ }
}
/* Called from build_vcall_offset_vtbl_entries via dfs_walk. */
@@ -6402,20 +6528,22 @@ dfs_build_vcall_offset_vtbl_entries (binfo, data)
vcall_offset_data* vod;
tree virtuals;
tree binfo_inits;
-
- /* Primary bases are not interesting; all of the virtual
- function table entries have been overridden. */
- if (BINFO_PRIMARY_MARKED_P (binfo))
- return NULL_TREE;
+ tree b;
+ int i;
vod = (vcall_offset_data *) data;
binfo_inits = NULL_TREE;
+
+ /* Skip virtuals that we have already handled in a primary base
+ class. */
+ virtuals = BINFO_VIRTUALS (binfo);
+ b = BINFO_PRIMARY_BINFO (binfo);
+ if (b)
+ for (i = 0; i < CLASSTYPE_VSIZE (BINFO_TYPE (b)); ++i)
+ virtuals = TREE_CHAIN (virtuals);
- /* We chain the offsets on in reverse order. That's correct --
- build_vtbl_initializer will straighten them out. */
- for (virtuals = BINFO_VIRTUALS (binfo);
- virtuals;
- virtuals = TREE_CHAIN (virtuals))
+ /* Make entries for the rest of the virtuals. */
+ while (virtuals)
{
/* Figure out what function we're looking at. */
tree fn = TREE_VALUE (virtuals);
@@ -6430,34 +6558,48 @@ dfs_build_vcall_offset_vtbl_entries (binfo, data)
size_diffop (BINFO_OFFSET (base_binfo),
BINFO_OFFSET (vod->vbase)))),
binfo_inits);
+ vod->index = fold (build (MINUS_EXPR, integer_type_node,
+ vod->index, integer_one_node));
+ virtuals = TREE_CHAIN (virtuals);
}
- /* Now add the initializers we've just created to the list that will
- be returned to our caller. */
- vod->inits = chainon (vod->inits, binfo_inits);
+ /* The offests are built up in reverse order, so we straighten them
+ here. We simultaneously add them to VOD->INITS; we're walking
+ the bases in inheritance graph order, and the initializers are
+ supposed to appear in reverse inheritance order, so that's
+ correct. */
+ while (binfo_inits)
+ {
+ tree next;
+
+ next = TREE_CHAIN (binfo_inits);
+ TREE_CHAIN (binfo_inits) = vod->inits;
+ vod->inits = binfo_inits;
+ binfo_inits = next;
+ }
return NULL_TREE;
}
-/* Returns the initializers for the vcall offset entries in the vtable
- for BINFO (which is part of the class hierarchy dominated by T), in
- reverse order. */
+/* Adds the initializers for the vcall offset entries in the vtable
+ for BINFO (which is part of the class hierarchy dominated by T) to
+ VOD->INITS. */
-static tree
-build_vcall_offset_vtbl_entries (binfo, t)
+static void
+build_vcall_offset_vtbl_entries (binfo, vod)
tree binfo;
- tree t;
+ vcall_offset_data *vod;
{
- vcall_offset_data vod;
+ tree inits;
/* Under the old ABI, the adjustments to the `this' pointer were made
elsewhere. */
if (!vcall_offsets_in_vtable_p ())
- return NULL_TREE;
+ return;
/* We only need these entries if this base is a virtual base. */
if (!TREE_VIA_VIRTUAL (binfo))
- return NULL_TREE;
+ return;
/* We need a vcall offset for each of the virtual functions in this
vtable. For example:
@@ -6481,15 +6623,15 @@ build_vcall_offset_vtbl_entries (binfo, t)
in our non-virtual bases vtables. For each base, the entries
appear in the same order as in the base; but the bases themselves
appear in reverse depth-first, left-to-right order. */
- vod.derived = t;
- vod.vbase = binfo;
- vod.inits = NULL_TREE;
- dfs_walk (binfo,
- dfs_build_vcall_offset_vtbl_entries,
- dfs_vcall_offset_queue_p,
- &vod);
-
- return vod.inits;
+ vod->vbase = binfo;
+ inits = vod->inits;
+ vod->inits = NULL_TREE;
+ dfs_walk_real (binfo,
+ dfs_build_vcall_offset_vtbl_entries,
+ NULL,
+ dfs_vcall_offset_queue_p,
+ vod);
+ vod->inits = chainon (vod->inits, inits);
}
/* Return vtbl initializers for the RTTI entries coresponding to the
@@ -6503,10 +6645,10 @@ build_rtti_vtbl_entries (binfo, t)
{
tree b;
tree basetype;
- tree inits;
tree offset;
tree decl;
tree init;
+ tree inits;
basetype = BINFO_TYPE (binfo);
inits = NULL_TREE;
@@ -6519,19 +6661,15 @@ build_rtti_vtbl_entries (binfo, t)
primary base, and then add the offset in the vtbl to that value. */
b = binfo;
while (CLASSTYPE_HAS_PRIMARY_BASE_P (BINFO_TYPE (b)))
- b = BINFO_BASETYPE (b,
- CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (b)));
- offset = size_diffop (size_zero_node, BINFO_OFFSET (b));
-
- /* Add the offset-to-top entry. */
- if (flag_vtable_thunks)
{
- /* Convert the offset to look like a function pointer, so that
- we can put it in the vtable. */
- init = build1 (NOP_EXPR, vfunc_ptr_type_node, offset);
- TREE_CONSTANT (init) = 1;
- inits = tree_cons (NULL_TREE, init, inits);
+ tree primary_base;
+
+ primary_base = BINFO_PRIMARY_BINFO (b);
+ if (!BINFO_PRIMARY_MARKED_P (primary_base))
+ break;
+ b = primary_base;
}
+ offset = size_diffop (size_zero_node, BINFO_OFFSET (b));
/* The second entry is, in the case of the new ABI, the address of
the typeinfo object, or, in the case of the old ABI, a function
@@ -6561,10 +6699,19 @@ build_rtti_vtbl_entries (binfo, t)
TREE_CONSTANT (init) = 1;
init = build_vtable_entry (offset, integer_zero_node, init);
}
-
- /* Hook the RTTI declaration onto the list. */
inits = tree_cons (NULL_TREE, init, inits);
+ /* Add the offset-to-top entry. It comes earlier in the vtable that
+ the the typeinfo entry. */
+ if (flag_vtable_thunks)
+ {
+ /* Convert the offset to look like a function pointer, so that
+ we can put it in the vtable. */
+ init = build1 (NOP_EXPR, vfunc_ptr_type_node, offset);
+ TREE_CONSTANT (init) = 1;
+ inits = tree_cons (NULL_TREE, init, inits);
+ }
+
return inits;
}
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 0433135fc1c..07b867567e4 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -55,8 +55,6 @@ Boston, MA 02111-1307, USA. */
ICS_ELLIPSIS_FLAG (in _CONV)
STMT_IS_FULL_EXPR_P (in _STMT)
2: IDENTIFIER_OPNAME_P.
- BINFO_VBASE_MARKED.
- BINFO_FIELDS_MARKED.
TYPE_POLYMORHPIC_P (in _TYPE)
ICS_THIS_FLAG (in _CONV)
STMT_LINENO_FOR_FN_P (in _STMT)
@@ -130,6 +128,13 @@ Boston, MA 02111-1307, USA. */
this function. (This binfo's BINFO_TYPE will always be the same
as the DECL_CLASS_CONTEXT for the function.)
+ BINFO_VTABLE
+ Sometimes this is a VAR_DECL. Under the new ABI, it is instead
+ an expression with POINTER_TYPE pointing that gives the value
+ to which the vptr should be initialized. Use get_vtbl_decl_for_binfo
+ to extract the VAR_DECL for the complete vtable; that macro works
+ in both ABIs.
+
DECL_ARGUMENTS
For a VAR_DECL this is DECL_ANON_UNION_ELEMS.
@@ -1356,24 +1361,17 @@ struct lang_type
int vsize;
int vfield_parent;
- union tree_node *vfields;
- union tree_node *vbases;
-
- union tree_node *tags;
-
- union tree_node *search_slot;
-
- union tree_node *size;
- union tree_node *size_unit;
-
- union tree_node *pure_virtuals;
- union tree_node *friend_classes;
-
- union tree_node *rtti;
-
- union tree_node *methods;
-
- union tree_node *template_info;
+ tree vfields;
+ tree vbases;
+ tree tags;
+ tree search_slot;
+ tree size;
+ tree size_unit;
+ tree pure_virtuals;
+ tree friend_classes;
+ tree rtti;
+ tree methods;
+ tree template_info;
tree befriending_classes;
};
@@ -1538,21 +1536,29 @@ struct lang_type
#define CLASSTYPE_PRIMARY_BINFO(NODE) \
(BINFO_PRIMARY_BINFO (TYPE_BINFO (NODE)))
-/* If non-NULL, this is the binfo for the primary base of BINFO. */
+/* If non-NULL, this is the binfo for the primary base of BINFO. Note
+ that in a complex hierarchy the resulting BINFO may not actually
+ *be* primary. In particular if the resulting BINFO is a virtual
+ base, and it occurs elsewhere in the hierarchy, then this
+ occurrence may not actually be a primary base in the complete
+ object. Check BINFO_PRIMARY_MARKED_P to be sure. */
#define BINFO_PRIMARY_BINFO(NODE) \
(CLASSTYPE_HAS_PRIMARY_BASE_P (BINFO_TYPE (NODE)) \
? BINFO_BASETYPE (NODE, \
CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (NODE))) \
: NULL_TREE)
-/* The number of virtual functions present in this classes virtual
+/* The number of virtual functions present in this class' virtual
function table. */
#define CLASSTYPE_VSIZE(NODE) (TYPE_LANG_SPECIFIC(NODE)->vsize)
/* A chain of BINFOs for the direct and indirect virtual base classes
- that this type uses in depth-first left-to-right order. These
- BINFOs are distinct from those in the TYPE_BINFO hierarchy. So,
- given:
+ that this type uses in a post-order depth-first left-to-right
+ order. (In other words, these bases appear in the order that they
+ should be initialized.)
+
+ These BINFOs are distinct from those in the TYPE_BINFO hierarchy.
+ So, given:
struct A {};
struct B : public A {};
@@ -1683,9 +1689,7 @@ struct lang_type
We use TREE_VIA_PROTECTED and TREE_VIA_PUBLIC, but private
inheritance is indicated by the absence of the other two flags, not
- by TREE_VIA_PRIVATE, which is unused.
-
- The TREE_CHAIN is for scratch space in search.c. */
+ by TREE_VIA_PRIVATE, which is unused. */
/* Nonzero means marked by DFS or BFS search, including searches
by `get_binfo' and `get_base_distance'. */
@@ -1695,18 +1699,6 @@ struct lang_type
#define SET_BINFO_MARKED(NODE) (TREE_VIA_VIRTUAL(NODE)?SET_CLASSTYPE_MARKED(BINFO_TYPE(NODE)):(TREE_LANG_FLAG_0(NODE)=1))
#define CLEAR_BINFO_MARKED(NODE) (TREE_VIA_VIRTUAL(NODE)?CLEAR_CLASSTYPE_MARKED(BINFO_TYPE(NODE)):(TREE_LANG_FLAG_0(NODE)=0))
-/* Nonzero means marked in search through virtual inheritance hierarchy. */
-#define BINFO_VBASE_MARKED(NODE) CLASSTYPE_MARKED2 (BINFO_TYPE (NODE))
-/* Modifier macros */
-#define SET_BINFO_VBASE_MARKED(NODE) SET_CLASSTYPE_MARKED2 (BINFO_TYPE (NODE))
-#define CLEAR_BINFO_VBASE_MARKED(NODE) CLEAR_CLASSTYPE_MARKED2 (BINFO_TYPE (NODE))
-
-/* Nonzero means marked in search for members or member functions. */
-#define BINFO_FIELDS_MARKED(NODE) \
- (TREE_VIA_VIRTUAL(NODE)?CLASSTYPE_MARKED2 (BINFO_TYPE (NODE)):TREE_LANG_FLAG_2(NODE))
-#define SET_BINFO_FIELDS_MARKED(NODE) (TREE_VIA_VIRTUAL(NODE)?SET_CLASSTYPE_MARKED2(BINFO_TYPE(NODE)):(TREE_LANG_FLAG_2(NODE)=1))
-#define CLEAR_BINFO_FIELDS_MARKED(NODE) (TREE_VIA_VIRTUAL(NODE)?CLEAR_CLASSTYPE_MARKED2(BINFO_TYPE(NODE)):(TREE_LANG_FLAG_2(NODE)=0))
-
/* Nonzero means that this class is on a path leading to a new vtable. */
#define BINFO_VTABLE_PATH_MARKED(NODE) \
(TREE_VIA_VIRTUAL(NODE)?CLASSTYPE_MARKED3(BINFO_TYPE(NODE)):TREE_LANG_FLAG_3(NODE))
@@ -3081,6 +3073,17 @@ typedef enum tmpl_spec_kind {
tsk_expl_inst /* An explicit instantiation. */
} tmpl_spec_kind;
+/* The various kinds of access. BINFO_ACCESS depends on these being
+ two bit quantities. The numerical values are important; they are
+ used to initialize RTTI data structures, so chaning them changes
+ the ABI. */
+typedef enum access_kind {
+ ak_none = 0, /* Inaccessible. */
+ ak_public = 1, /* Accessible, as a `public' thing. */
+ ak_protected = 2, /* Accessible, as a `protected' thing. */
+ ak_private = 3 /* Accessible, as a `private' thing. */
+} access_kind;
+
/* Zero means prototype weakly, as in ANSI C (no args means nothing).
Each language context defines how this variable should be set. */
extern int strict_prototype;
@@ -3694,8 +3697,7 @@ extern void unreverse_member_declarations PARAMS ((tree));
extern void invalidate_class_lookup_cache PARAMS ((void));
extern void maybe_note_name_used_in_class PARAMS ((tree, tree));
extern void note_name_declared_in_class PARAMS ((tree, tree));
-extern tree num_extra_vtbl_entries PARAMS ((tree));
-extern tree size_extra_vtbl_entries PARAMS ((tree));
+extern tree get_vtbl_decl_for_binfo PARAMS ((tree));
/* in cvt.c */
extern tree convert_to_reference PARAMS ((tree, tree, int, int, tree));
@@ -4203,7 +4205,6 @@ extern tree dfs_walk_real PARAMS ((tree,
tree (*) (tree, void *),
void *));
extern tree dfs_unmark PARAMS ((tree, void *));
-extern tree dfs_vbase_unmark PARAMS ((tree, void *));
extern tree dfs_vtable_path_unmark PARAMS ((tree, void *));
extern tree markedp PARAMS ((tree, void *));
extern tree unmarkedp PARAMS ((tree, void *));
@@ -4214,7 +4215,6 @@ extern tree dfs_marked_real_bases_queue_p PARAMS ((tree, void *));
extern tree dfs_skip_vbases PARAMS ((tree, void *));
extern tree marked_vtable_pathp PARAMS ((tree, void *));
extern tree unmarked_vtable_pathp PARAMS ((tree, void *));
-extern void mark_primary_bases PARAMS ((tree));
extern tree convert_pointer_to_vbase PARAMS ((tree, tree));
extern tree find_vbase_instance PARAMS ((tree, tree));
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index 37a352ed385..be51512e266 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -2544,7 +2544,7 @@ output_vtable_inherit (vars)
op[1] = const0_rtx;
else if (parent)
{
- parent = TYPE_BINFO_VTABLE (BINFO_TYPE (parent));
+ parent = get_vtbl_decl_for_binfo (TYPE_BINFO (BINFO_TYPE (parent)));
op[1] = XEXP (DECL_RTL (parent), 0); /* strip the mem ref */
}
else
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index ff8e0583434..4623abf6fa9 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -653,31 +653,23 @@ expand_virtual_init (binfo, decl)
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);
- vtbl = BINFO_VTABLE (binfo_value (DECL_FIELD_CONTEXT (TYPE_VFIELD (type)), binfo));
+ 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)
- {
- assemble_external (vtbl);
- TREE_USED (vtbl) = 1;
- vtbl = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (vtbl)), vtbl);
- }
- else
- /* Under the new ABI, secondary vtables are stored with the
- primary vtable. So, the BINFO_VTABLE may be an expression for
- computing the secondary vtable, rather than the secondary
- vtable itself. */
- my_friendly_assert (merge_primary_and_secondary_vtables_p (),
- 20000220);
-
- /* Under the new ABI, we need to point into the middle of the
- vtable. */
- if (vbase_offsets_in_vtable_p ())
- vtbl = build (PLUS_EXPR, TREE_TYPE (vtbl), vtbl,
- size_extra_vtbl_entries (binfo));
+ 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);
diff --git a/gcc/cp/repo.c b/gcc/cp/repo.c
index 99d53f089d1..0d3879eebb2 100644
--- a/gcc/cp/repo.c
+++ b/gcc/cp/repo.c
@@ -103,7 +103,7 @@ repo_get_id (t)
if (!COMPLETE_TYPE_P (t) || TYPE_BEING_DEFINED (t))
my_friendly_abort (981113);
- t = TYPE_BINFO_VTABLE (t);
+ t = get_vtbl_decl_for_binfo (TYPE_BINFO (t));
if (t == NULL_TREE)
return t;
}
diff --git a/gcc/cp/rtti.c b/gcc/cp/rtti.c
index e9873ba9718..a5429ecfcc6 100644
--- a/gcc/cp/rtti.c
+++ b/gcc/cp/rtti.c
@@ -1640,11 +1640,14 @@ create_pseudo_type_info VPARAMS((const char *real_name, int ident, ...))
/* Under the new ABI, we need to point into the middle of the
vtable. */
- if (vbase_offsets_in_vtable_p ())
+ if (flag_new_abi)
{
- vtable_decl = build (PLUS_EXPR, TREE_TYPE (vtable_decl),
+ vtable_decl = build (PLUS_EXPR,
+ TREE_TYPE (vtable_decl),
vtable_decl,
- size_extra_vtbl_entries (TYPE_BINFO (real_type)));
+ size_binop (MULT_EXPR,
+ size_int (2),
+ TYPE_SIZE_UNIT (vtable_entry_type)));
TREE_CONSTANT (vtable_decl) = 1;
}
diff --git a/gcc/cp/search.c b/gcc/cp/search.c
index 14ceff28982..4c4b600659f 100644
--- a/gcc/cp/search.c
+++ b/gcc/cp/search.c
@@ -143,7 +143,7 @@ static int dependent_base_p PARAMS ((tree));
static tree dfs_accessible_queue_p PARAMS ((tree, void *));
static tree dfs_accessible_p PARAMS ((tree, void *));
static tree dfs_access_in_type PARAMS ((tree, void *));
-static tree access_in_type PARAMS ((tree, tree));
+static access_kind access_in_type PARAMS ((tree, tree));
static tree dfs_canonical_queue PARAMS ((tree, void *));
static tree dfs_assert_unmarked_p PARAMS ((tree, void *));
static void assert_canonical_unmarked PARAMS ((tree));
@@ -152,7 +152,6 @@ 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 dfs_mark_primary_bases PARAMS ((tree, void *));
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 *));
@@ -811,6 +810,18 @@ shared_unmarked_p (binfo, data)
return unmarkedp (binfo, data);
}
+/* The accessibility routines use BINFO_ACCESS for scratch space
+ during the computation of the accssibility of some declaration. */
+
+#define BINFO_ACCESS(NODE) \
+ ((access_kind) ((TREE_LANG_FLAG_1 (NODE) << 1) | TREE_LANG_FLAG_6 (NODE)))
+
+/* Set the access associated with NODE to ACCESS. */
+
+#define SET_BINFO_ACCESS(NODE, ACCESS) \
+ ((TREE_LANG_FLAG_1 (NODE) = (ACCESS & 2) != 0), \
+ (TREE_LANG_FLAG_6 (NODE) = (ACCESS & 1) != 0))
+
/* Called from access_in_type via dfs_walk. Calculate the access to
DATA (which is really a DECL) in BINFO. */
@@ -821,18 +832,18 @@ dfs_access_in_type (binfo, data)
{
tree decl = (tree) data;
tree type = BINFO_TYPE (binfo);
- tree access = NULL_TREE;
+ access_kind access = ak_none;
if (context_for_name_lookup (decl) == type)
{
/* If we have desceneded to the scope of DECL, just note the
appropriate access. */
if (TREE_PRIVATE (decl))
- access = access_private_node;
+ access = ak_private;
else if (TREE_PROTECTED (decl))
- access = access_protected_node;
+ access = ak_protected;
else
- access = access_public_node;
+ access = ak_public;
}
else
{
@@ -842,9 +853,10 @@ dfs_access_in_type (binfo, data)
DECL_ACCESS. */
if (DECL_LANG_SPECIFIC (decl))
{
- access = purpose_member (type, DECL_ACCESS (decl));
- if (access)
- access = TREE_VALUE (access);
+ tree decl_access = purpose_member (type, DECL_ACCESS (decl));
+ if (decl_access)
+ access = ((access_kind)
+ TREE_INT_CST_LOW (TREE_VALUE (decl_access)));
}
if (!access)
@@ -860,35 +872,36 @@ dfs_access_in_type (binfo, data)
for (i = 0; i < n_baselinks; ++i)
{
tree base_binfo = TREE_VEC_ELT (binfos, i);
- tree base_access = TREE_CHAIN (canonical_binfo (base_binfo));
+ access_kind base_access
+ = BINFO_ACCESS (canonical_binfo (base_binfo));
- if (!base_access || base_access == access_private_node)
+ if (base_access == ak_none || base_access == ak_private)
/* If it was not accessible in the base, or only
accessible as a private member, we can't access it
all. */
- base_access = NULL_TREE;
+ base_access = ak_none;
else if (TREE_VIA_PROTECTED (base_binfo))
/* Public and protected members in the base are
protected here. */
- base_access = access_protected_node;
+ base_access = ak_protected;
else if (!TREE_VIA_PUBLIC (base_binfo))
/* Public and protected members in the base are
private here. */
- base_access = access_private_node;
+ base_access = ak_private;
/* See if the new access, via this base, gives more
access than our previous best access. */
- if (base_access &&
- (base_access == access_public_node
- || (base_access == access_protected_node
- && access != access_public_node)
- || (base_access == access_private_node
- && !access)))
+ if (base_access != ak_none
+ && (base_access == ak_public
+ || (base_access == ak_protected
+ && access != ak_public)
+ || (base_access == ak_private
+ && access == ak_none)))
{
access = base_access;
/* If the new access is public, we can't do better. */
- if (access == access_public_node)
+ if (access == ak_public)
break;
}
}
@@ -896,7 +909,7 @@ dfs_access_in_type (binfo, data)
}
/* Note the access to DECL in TYPE. */
- TREE_CHAIN (binfo) = access;
+ SET_BINFO_ACCESS (binfo, access);
/* Mark TYPE as visited so that if we reach it again we do not
duplicate our efforts here. */
@@ -907,7 +920,7 @@ dfs_access_in_type (binfo, data)
/* Return the access to DECL in TYPE. */
-static tree
+static access_kind
access_in_type (type, decl)
tree type;
tree decl;
@@ -929,7 +942,7 @@ access_in_type (type, decl)
dfs_walk (binfo, dfs_unmark, shared_marked_p, 0);
assert_canonical_unmarked (binfo);
- return TREE_CHAIN (binfo);
+ return BINFO_ACCESS (binfo);
}
/* Called from dfs_accessible_p via dfs_walk. */
@@ -960,17 +973,14 @@ dfs_accessible_p (binfo, data)
void *data;
{
int protected_ok = data != 0;
- tree access;
+ access_kind access;
- /* We marked the binfos while computing the access in each type.
- So, we unmark as we go now. */
SET_BINFO_MARKED (binfo);
-
- access = TREE_CHAIN (binfo);
- if (access == access_public_node
- || (access == access_protected_node && protected_ok))
+ access = BINFO_ACCESS (binfo);
+ if (access == ak_public || (access == ak_protected && protected_ok))
return binfo;
- else if (access && is_friend (BINFO_TYPE (binfo), current_scope ()))
+ else if (access != ak_none
+ && is_friend (BINFO_TYPE (binfo), current_scope ()))
return binfo;
return NULL_TREE;
@@ -985,7 +995,7 @@ protected_accessible_p (decl, derived, binfo)
tree derived;
tree binfo;
{
- tree access;
+ access_kind access;
/* We're checking this clause from [class.access.base]
@@ -1010,7 +1020,7 @@ protected_accessible_p (decl, derived, binfo)
access = access_in_type (derived, decl);
/* If m is inaccessible in DERIVED, then it's not a P. */
- if (access == NULL_TREE)
+ if (access == ak_none)
return 0;
/* [class.protected]
@@ -1752,12 +1762,11 @@ lookup_fnfields_1 (type, name)
If it ever returns a non-NULL value, that value is immediately
returned and the walk is terminated. At each node FN, is passed a
BINFO indicating the path from the curently visited base-class to
- TYPE. The TREE_CHAINs of the BINFOs may be used for scratch space;
- they are otherwise unused. Before each base-class is walked QFN is
- called. If the value returned is non-zero, the base-class is
- walked; otherwise it is not. If QFN is NULL, it is treated as a
- function which always returns 1. Both FN and QFN are passed the
- DATA whenever they are called. */
+ TYPE. Before each base-class is walked QFN is called. If the
+ value returned is non-zero, the base-class is walked; otherwise it
+ is not. If QFN is NULL, it is treated as a function which always
+ returns 1. Both FN and QFN are passed the DATA whenever they are
+ called. */
static tree
bfs_walk (binfo, fn, qfn, data)
@@ -2194,97 +2203,6 @@ dfs_skip_nonprimary_vbases_markedp (binfo, data)
return markedp (binfo, NULL);
}
-/* Called via dfs_walk from mark_primary_bases. */
-
-static tree
-dfs_mark_primary_bases (binfo, data)
- tree binfo;
- void *data;
-{
- int i;
- tree base_binfo;
-
- if (!CLASSTYPE_HAS_PRIMARY_BASE_P (BINFO_TYPE (binfo)))
- return NULL_TREE;
-
- i = CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (binfo));
- base_binfo = BINFO_BASETYPE (binfo, i);
-
- if (!TREE_VIA_VIRTUAL (base_binfo))
- /* Non-virtual base classes are easy. */
- BINFO_PRIMARY_MARKED_P (base_binfo) = 1;
- else
- {
- tree shared_binfo;
-
- shared_binfo
- = BINFO_FOR_VBASE (BINFO_TYPE (base_binfo), (tree) data);
-
- /* If this virtual base is not already primary somewhere else in
- the hiearchy, then we'll be using this copy. */
- if (!BINFO_VBASE_PRIMARY_P (shared_binfo)
- && !BINFO_VBASE_MARKED (shared_binfo))
- {
- BINFO_VBASE_PRIMARY_P (shared_binfo) = 1;
- BINFO_PRIMARY_MARKED_P (base_binfo) = 1;
- }
- }
-
- return NULL_TREE;
-}
-
-/* Set BINFO_PRIMARY_MARKED_P for all binfos in the hierarchy
- dominated by BINFO that are primary bases. */
-
-void
-mark_primary_bases (type)
- tree type;
-{
- tree vbase;
-
- /* Mark the TYPE_BINFO hierarchy. We need to mark primary bases in
- pre-order to deal with primary virtual bases. (The virtual base
- would be skipped if it were not marked as primary, and that
- requires getting to dfs_mark_primary_bases before
- dfs_skip_nonprimary_vbases_unmarkedp has a chance to skip the
- virtual base.) */
- dfs_walk_real (TYPE_BINFO (type), dfs_mark_primary_bases, NULL,
- dfs_skip_nonprimary_vbases_unmarkedp, type);
-
- /* Now go through the virtual base classes. Any that are not
- already primary will need to be allocated in TYPE, and so we need
- to mark their primary bases. */
- for (vbase = CLASSTYPE_VBASECLASSES (type);
- vbase;
- vbase = TREE_CHAIN (vbase))
- {
- if (BINFO_VBASE_PRIMARY_P (vbase))
- /* This virtual base was already included in the hierarchy, so
- there's nothing to do here. */
- continue;
-
- /* Temporarily pretend that VBASE is primary so that its bases
- will be walked; this is the real copy of VBASE. */
- BINFO_PRIMARY_MARKED_P (vbase) = 1;
-
- /* Now, walk its bases. */
- dfs_walk (vbase, dfs_mark_primary_bases,
- dfs_skip_nonprimary_vbases_unmarkedp, type);
-
- /* VBASE wasn't really primary. */
- BINFO_PRIMARY_MARKED_P (vbase) = 0;
- /* And we don't want to allow it to *become* primary if it is a
- base of some subsequent base class. */
- SET_BINFO_VBASE_MARKED (vbase);
- }
-
- /* Clear the VBASE_MARKED bits we set above. */
- for (vbase = CLASSTYPE_VBASECLASSES (type);
- vbase;
- vbase = TREE_CHAIN (vbase))
- CLEAR_BINFO_VBASE_MARKED (vbase);
-}
-
/* If BINFO is a non-primary virtual baseclass (in the hierarchy
dominated by TYPE), and no primary copy appears anywhere in the
hierarchy, return the shared copy. If a primary copy appears
@@ -2577,17 +2495,6 @@ dfs_unmark (binfo, data)
return NULL_TREE;
}
-/* Clear both BINFO_MARKED and BINFO_VBASE_MARKED. */
-
-tree
-dfs_vbase_unmark (binfo, data)
- tree binfo;
- void *data ATTRIBUTE_UNUSED;
-{
- CLEAR_BINFO_VBASE_MARKED (binfo);
- return dfs_unmark (binfo, data);
-}
-
/* Clear BINFO_VTABLE_PATH_MARKED. */
tree
@@ -2781,7 +2688,7 @@ virtual_context (fndecl, t, vbase)
while (path)
{
if (TREE_VIA_VIRTUAL (path))
- return binfo_member (BINFO_TYPE (path), CLASSTYPE_VBASECLASSES (t));
+ return BINFO_FOR_VBASE (BINFO_TYPE (path), t);
path = BINFO_INHERITANCE_CHAIN (path);
}
return 0;
@@ -3072,7 +2979,7 @@ dfs_get_vbase_types (binfo, data)
{
tree type = (tree) data;
- if (TREE_VIA_VIRTUAL (binfo) && ! BINFO_VBASE_MARKED (binfo))
+ if (TREE_VIA_VIRTUAL (binfo))
{
tree new_vbase = make_binfo (size_zero_node,
BINFO_TYPE (binfo),
@@ -3083,24 +2990,50 @@ dfs_get_vbase_types (binfo, data)
BINFO_INHERITANCE_CHAIN (new_vbase) = TYPE_BINFO (type);
TREE_CHAIN (new_vbase) = CLASSTYPE_VBASECLASSES (type);
CLASSTYPE_VBASECLASSES (type) = new_vbase;
- SET_BINFO_VBASE_MARKED (binfo);
}
SET_BINFO_MARKED (binfo);
return NULL_TREE;
}
+/* Called via dfs_walk from mark_primary_bases. Builds the
+ inheritance graph order list of BINFOs. */
+
+static tree
+dfs_build_inheritance_graph_order (binfo, data)
+ tree binfo;
+ void *data;
+{
+ tree *last_binfo = (tree *) data;
+
+ if (*last_binfo)
+ TREE_CHAIN (*last_binfo) = binfo;
+ *last_binfo = binfo;
+ SET_BINFO_MARKED (binfo);
+ return NULL_TREE;
+}
+
/* Set CLASSTYPE_VBASECLASSES for TYPE. */
void
get_vbase_types (type)
tree type;
{
+ tree last_binfo;
+
CLASSTYPE_VBASECLASSES (type) = NULL_TREE;
dfs_walk (TYPE_BINFO (type), dfs_get_vbase_types, unmarkedp, type);
/* Rely upon the reverse dfs ordering from dfs_get_vbase_types, and now
reverse it so that we get normal dfs ordering. */
CLASSTYPE_VBASECLASSES (type) = nreverse (CLASSTYPE_VBASECLASSES (type));
- dfs_walk (TYPE_BINFO (type), dfs_vbase_unmark, markedp, 0);
+ dfs_walk (TYPE_BINFO (type), dfs_unmark, markedp, 0);
+ /* Thread the BINFOs in inheritance-graph order. */
+ last_binfo = NULL;
+ dfs_walk_real (TYPE_BINFO (type),
+ dfs_build_inheritance_graph_order,
+ NULL,
+ unmarkedp,
+ &last_binfo);
+ dfs_walk (TYPE_BINFO (type), dfs_unmark, markedp, NULL);
}
/* Called from find_vbase_instance via dfs_walk. */
diff --git a/gcc/cp/tinfo.cc b/gcc/cp/tinfo.cc
index 71e5c2847c4..fbc498b5d7d 100644
--- a/gcc/cp/tinfo.cc
+++ b/gcc/cp/tinfo.cc
@@ -590,6 +590,14 @@ adjust_pointer (const void *base, ptrdiff_t offset)
(reinterpret_cast <const char *> (base) + offset);
}
+inline ptrdiff_t
+get_vbase_offset (const void *object, ptrdiff_t offset)
+{
+ const char *vtable = *reinterpret_cast <const char *const *> (object);
+ vtable += offset;
+ return *reinterpret_cast <const ptrdiff_t *> (vtable);
+}
+
// some predicate functions for __class_type_info::sub_kind
inline bool contained_p (__class_type_info::sub_kind access_path)
{
@@ -718,9 +726,7 @@ do_find_public_src (ptrdiff_t src2dst,
{
if (src2dst == -3)
continue; // Not a virtual base, so can't be here.
- const ptrdiff_t *vtable = *static_cast <const ptrdiff_t *const *> (base);
-
- offset = vtable[offset];
+ offset = get_vbase_offset (base, offset);
}
base = adjust_pointer <void> (base, offset);
@@ -841,9 +847,7 @@ do_dyncast (ptrdiff_t src2dst,
if (base_list[i].is_virtual_p ())
{
base_access = sub_kind (base_access | contained_virtual_mask);
- const ptrdiff_t *vtable = *static_cast <const ptrdiff_t *const *> (base);
-
- offset = vtable[offset];
+ offset = get_vbase_offset (base, offset);
}
base = adjust_pointer <void> (base, offset);
@@ -1041,10 +1045,7 @@ do_upcast (sub_kind access_path,
sub_access = sub_kind (sub_access | contained_virtual_mask);
if (base)
- {
- const ptrdiff_t *vtable = *static_cast <const ptrdiff_t *const *> (base);
- offset = vtable[offset];
- }
+ offset = get_vbase_offset (base, offset);
}
if (base)
base = adjust_pointer <void> (base, offset);
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index e27ff7b71e2..d5e0a5d667a 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -921,7 +921,7 @@ debug_binfo (elem)
debug_tree (BINFO_TYPE (elem));
if (BINFO_VTABLE (elem))
fprintf (stderr, "vtable decl \"%s\"\n",
- IDENTIFIER_POINTER (DECL_NAME (BINFO_VTABLE (elem))));
+ IDENTIFIER_POINTER (DECL_NAME (get_vtbl_decl_for_binfo (elem))));
else
fprintf (stderr, "no vtable decl yet\n");
fprintf (stderr, "virtuals:\n");
diff --git a/gcc/testsuite/g++.old-deja/g++.abi/layout1.C b/gcc/testsuite/g++.old-deja/g++.abi/layout1.C
new file mode 100644
index 00000000000..a37ef07e75f
--- /dev/null
+++ b/gcc/testsuite/g++.old-deja/g++.abi/layout1.C
@@ -0,0 +1,51 @@
+// Origin: Mark Mitchell <mark@codesourcery.com>
+
+#if defined (__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100
+
+struct R
+{
+ virtual void r ();
+};
+
+struct S
+{
+ virtual void f ();
+};
+
+struct T : virtual public S
+{
+ virtual void g ();
+};
+
+struct U : public R, virtual public T
+{
+ virtual void h ();
+};
+
+struct V : public R, virtual public S, virtual public T
+{
+ virtual void v ();
+};
+
+struct U1
+{
+ R r;
+ T t;
+};
+
+int main ()
+{
+ if (sizeof (U) != sizeof (U1))
+ return 1;
+ if (sizeof (V) != sizeof (U1))
+ return 2;
+}
+
+#else /* !(defined (__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100) */
+
+int main ()
+{
+}
+
+#endif /* !(defined (__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100) */
+
diff --git a/gcc/testsuite/g++.old-deja/g++.abi/vtable.C b/gcc/testsuite/g++.old-deja/g++.abi/vtable.C
index aafcad8d19c..4c811a8c5ab 100644
--- a/gcc/testsuite/g++.old-deja/g++.abi/vtable.C
+++ b/gcc/testsuite/g++.old-deja/g++.abi/vtable.C
@@ -65,7 +65,7 @@ int main ()
if (vtable (&s4) != vtable (s2))
return 1;
- if (vtable (s2) >= vtable (s3))
+ if (vtable (s2) >= vtable (s3))
return 2;
if (vtable (s3) >= vtable (s1))
return 3;
diff --git a/gcc/testsuite/g++.old-deja/g++.abi/vtable2.C b/gcc/testsuite/g++.old-deja/g++.abi/vtable2.C
new file mode 100644
index 00000000000..5d8cf9d0197
--- /dev/null
+++ b/gcc/testsuite/g++.old-deja/g++.abi/vtable2.C
@@ -0,0 +1,179 @@
+// Origin: Mark Mitchell <mark@codesourcery.com>
+
+#if defined (__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100
+
+#include <stddef.h>
+
+struct S0
+{
+ virtual void s0 ();
+};
+
+struct S1 : virtual public S0
+{
+ virtual void s1 ();
+};
+
+struct S2 : virtual public S1
+{
+ virtual void s1 ();
+ virtual void s0 ();
+};
+
+struct S3
+{
+ virtual void s3 ();
+};
+
+struct S4 : public S3, virtual public S2
+{
+ virtual void s1 ();
+};
+
+void S0::s0 ()
+{
+}
+
+void S1::s1 ()
+{
+}
+
+void S2::s1 ()
+{
+}
+
+void S2::s0 ()
+{
+}
+
+void S3::s3 ()
+{
+}
+
+void S4::s1 ()
+{
+}
+
+/* The vtables should look like:
+
+ S0 primary vtable
+
+ S0 offset to top
+ S0 RTTI
+ S0::s0
+
+ =================
+
+ S1 primary vtable
+
+ S0::s0 vcall offset
+ S0 vbase offset
+ S1 offset to top
+ S1 RTTI
+ S0::s0
+ S1::s1
+
+ =================
+
+ S2 primary vtable
+
+ S2::s1 vcall offset
+ S1 vbase offset
+ S2::s0 vcall offset
+ S0 vbase offset
+ S2 offset to top
+ S2 RTTI
+ S2::s0
+ S2::s1
+
+ =================
+
+ S3 primary vtable
+
+ S3 offset to top
+ S3 RTTI
+ S3::s3
+
+ =================
+
+ S4 primary vtable
+
+ vbase offset for S0
+ vbase offset for S1
+ vbase offset for S2
+ S4 offset to top
+ S4 RTTI
+ S3::s3
+ S4::s1
+
+ S2-in-S4 secondary vtable
+
+ S4::s1 vcall offset
+ S1 vbase offset
+ S2:s0 vcall offset
+ S0 vbase offset
+ S2 offset to top
+ S4 RTTI
+ S2::s0
+ S4::s1
+
+*/
+
+// These are tricks to allow us to get raw function pointers for
+// member functions.
+extern "C" {
+void s3__2S3 ();
+void s1__2S4 ();
+}
+
+int main ()
+{
+ S4 s4;
+ ptrdiff_t **vptr;
+ ptrdiff_t *vtbl;
+
+ // Set vtbl to point at the beginning of S4's primary vtable.
+ vptr = (ptrdiff_t **) &s4;
+ vtbl = *vptr;
+ vtbl -= 5;
+
+ if (*vtbl++ != ((char*) (S0*) &s4) - (char*) &s4)
+ return 1;
+ if (*vtbl++ != ((char*) (S1*) &s4) - (char*) &s4)
+ return 2;
+ if (*vtbl++ != ((char*) (S2*) &s4) - (char*) &s4)
+ return 3;
+ if (*vtbl++ != 0)
+ return 4;
+ // Skip the RTTI entry.
+ vtbl++;
+ if (*vtbl++ != (ptrdiff_t) &s3__2S3)
+ return 5;
+ if (*vtbl++ != (ptrdiff_t) &s1__2S4)
+ return 6;
+ // All the vcall and vbase offsets should be zero.
+ if (*vtbl++ != 0)
+ return 7;
+ if (*vtbl++ != 0)
+ return 8;
+ if (*vtbl++ != 0)
+ return 9;
+ if (*vtbl++ != 0)
+ return 10;
+ // Now we're at the S2 offset to top entry.
+ if (*vtbl++ != ((char*) &s4 - (char*) (S2*) &s4))
+ return 11;
+ // Skip the RTTI entry.
+ vtbl++;
+ // Skip the remaining virtual functions -- they are thunks.
+ vtbl++;
+ vtbl++;
+}
+
+#else /* !(defined (__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100) */
+
+int main ()
+{
+}
+
+#endif /* !(defined (__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100) */
diff --git a/gcc/testsuite/g++.old-deja/g++.jason/dcast3.C b/gcc/testsuite/g++.old-deja/g++.jason/dcast3.C
index 6d333f098bc..a67a1ddc9dc 100644
--- a/gcc/testsuite/g++.old-deja/g++.jason/dcast3.C
+++ b/gcc/testsuite/g++.old-deja/g++.jason/dcast3.C
@@ -28,5 +28,5 @@ int main ()
ap = (C2*)&e2;
// ap points to base subobject shared by two Bs; fails
if (dynamic_cast <B2*> (ap) != 0)
- return 1;
+ return 2;
}