aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/cp')
-rw-r--r--gcc/cp/ChangeLog55
-rw-r--r--gcc/cp/class.c400
-rw-r--r--gcc/cp/cp-tree.h13
-rw-r--r--gcc/cp/error.c2
-rw-r--r--gcc/cp/rtti.c39
-rw-r--r--gcc/cp/search.c45
-rw-r--r--gcc/cp/tinfo.cc5
-rw-r--r--gcc/cp/tree.c3
8 files changed, 275 insertions, 287 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index f53dd40..a787eb3 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,58 @@
+2000-03-28 Mark Mitchell <mark@codesourcery.com>
+
+ Put RTTI entries at negative offsets in new ABI.
+ * class.c (dfs_build_vbase_offset_vtbl_entries): Put the first
+ vbase offset at index -3, not -1.
+ (build_vtabe_offset_vtbl_entries): Use unmarked_vtable_pathp, not
+ dfs_vtable_path_unmarked_real_bases_queue_p to walk bases.
+ (dfs_build_vcall_offset_vtbl_entries): Don't use skip_rtti_stuff.
+ (build_rtti_vtbl_entries): New function.
+ (set_rtti_entry): Remove.
+ (build_primary_vtable): Don't use it.
+ (build_secondary_vtable): Likewise.
+ (start_vtable): Remove.
+ (first_vfun_index): New function.
+ (set_vindex): Likewise.
+ (add_virtual_function): Don't call start_vtable. Do call
+ set_vindex.
+ (set_primary_base): Rename parameter.
+ (determine_primary_base): Likewise.
+ (num_vfun_entries): Don't use skip_rtti_stuff.
+ (num_extra_vtbl_entries): Include RTTI information.
+ (build_vtbl_initializer): Use build_rtti_vtbl_entries.
+ (skip_rtti_stuff): Remove.
+ (dfs_modify_vtables): Don't use it.
+ (modify_all_vtables): Don't use start_vtable. Do use set_vindex.
+ (layout_nonempty_base_or_field): Update size handling.
+ (create_vtable_ptr): Tweak.
+ (layout_class_type): Adjust parameter names.
+ (finish_struct_1): Simplify.
+ * cp-tree.h (CLASSTYPE_VSIZE): Tweak documentation.
+ (skip_rtti_stuff): Remove.
+ (first_vfun_index): New function.
+ (dfs_vtable_path_unmarked_real_bases_queue_p): Remove.
+ (dfs_vtable_path_marked_real_bases_queue_p): Remove.
+ (marked_vtable_pathp): Declare.
+ (unmarked_vtable_pathp): Likewise.
+ * error.c (dump_expr): Use first_vfun_index to calculate vtable
+ offsets.
+ * rtti.c (build_headof): Look for RTTI at negative offsets.
+ (get_tinfo_decl_dynamic): Likewise.
+ (tinfo_base_init): Don't take the address of the TINFO_VTABLE_DECL
+ here.
+ (create_pseudo_type_info): Do it here instead. Adjust so that
+ vptr points at first virtual function.
+ * search.c (marked_vtable_pathp): Make it global.
+ (unmarked_vtable_pathp): Likewise.
+ (dfs_vtable_path_unmarked_real_bases_queue_p): Remove.
+ (dfs_vtable_path_marked_real_bases_queue_p): Likewise.
+ (dfs_get_pure_virtuals): Don't use skip_rtti_stuff.
+ (get_pure_virtuals): Likewise.
+ (expand_upcast_fixups): Likewise.
+ * tree.c (debug_binfo): Likewise.
+ * tinfo.cc (__dynamic_cast): Look for vtable_prefix at appropriate
+ negative offset.
+
Sun Mar 26 20:15:26 2000 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
* class.c (check_field_decl): Fix typo.
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index 1e48e89..a0bbf7f 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -80,7 +80,6 @@ static tree build_vtable_entry PARAMS ((tree, tree, tree));
static tree get_vtable_name PARAMS ((tree));
static tree get_derived_offset PARAMS ((tree, tree));
static tree get_basefndecls PARAMS ((tree, tree));
-static void set_rtti_entry PARAMS ((tree, tree, tree));
static int build_primary_vtable PARAMS ((tree, tree));
static int build_secondary_vtable PARAMS ((tree, tree));
static tree dfs_finish_vtbls PARAMS ((tree, void *));
@@ -142,7 +141,6 @@ 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 start_vtable PARAMS ((tree, int *));
static void layout_vtable_decl PARAMS ((tree, int));
static int num_vfun_entries PARAMS ((tree));
static tree dfs_find_final_overrider PARAMS ((tree, void *));
@@ -162,6 +160,8 @@ 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));
+static void set_vindex PARAMS ((tree, tree, int *));
+static tree build_rtti_vtbl_entries PARAMS ((tree, tree));
/* Variables shared between class.c and call.c. */
@@ -279,7 +279,7 @@ dfs_build_vbase_offset_vtbl_entries (binfo, data)
base. */
vbase = BINFO_FOR_VBASE (BINFO_TYPE (binfo), TREE_PURPOSE (list));
if (!TREE_VALUE (list))
- BINFO_VPTR_FIELD (vbase) = build_int_2 (-1, 0);
+ BINFO_VPTR_FIELD (vbase) = build_int_2 (-3, 0);
else
{
BINFO_VPTR_FIELD (vbase) = TREE_PURPOSE (TREE_VALUE (list));
@@ -333,11 +333,11 @@ build_vbase_offset_vtbl_entries (binfo, t)
TREE_TYPE (list) = binfo;
dfs_walk (binfo,
dfs_build_vbase_offset_vtbl_entries,
- dfs_vtable_path_unmarked_real_bases_queue_p,
+ unmarked_vtable_pathp,
list);
dfs_walk (binfo,
dfs_vtable_path_unmark,
- dfs_vtable_path_marked_real_bases_queue_p,
+ marked_vtable_pathp,
list);
inits = nreverse (TREE_VALUE (list));
@@ -405,9 +405,7 @@ dfs_build_vcall_offset_vtbl_entries (binfo, data)
/* We chain the offsets on in reverse order. That's correct --
build_vtbl_initializer will straighten them out. */
- for (virtuals = skip_rtti_stuff (binfo,
- BINFO_TYPE (binfo),
- NULL);
+ for (virtuals = BINFO_VIRTUALS (binfo);
virtuals;
virtuals = TREE_CHAIN (virtuals))
{
@@ -486,6 +484,82 @@ build_vcall_offset_vtbl_entries (binfo, t)
return vod.inits;
}
+/* Return vtbl initializers for the RTTI entries coresponding to the
+ BINFO's vtable. BINFO is a part of the hierarchy dominated by
+ T. */
+
+static tree
+build_rtti_vtbl_entries (binfo, t)
+ tree binfo;
+ tree t;
+{
+ tree b;
+ tree basetype;
+ tree inits;
+ tree offset;
+ tree decl;
+ tree init;
+
+ basetype = BINFO_TYPE (binfo);
+ inits = NULL_TREE;
+
+ /* For a COM object there is no RTTI entry. */
+ if (CLASSTYPE_COM_INTERFACE (basetype))
+ return inits;
+
+ /* To find the complete object, we will first convert to our most
+ 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);
+ }
+
+ /* 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
+ which returns a typeinfo object. */
+ if (new_abi_rtti_p ())
+ {
+ if (flag_rtti)
+ decl = build_unary_op (ADDR_EXPR, get_tinfo_decl (t), 0);
+ else
+ decl = integer_zero_node;
+
+ /* Convert the declaration to a type that can be stored in the
+ vtable. */
+ init = build1 (NOP_EXPR, vfunc_ptr_type_node, decl);
+ TREE_CONSTANT (init) = 1;
+ }
+ else
+ {
+ if (flag_rtti)
+ decl = get_tinfo_decl (t);
+ else
+ decl = abort_fndecl;
+
+ /* Convert the declaration to a type that can be stored in the
+ vtable. */
+ init = build1 (ADDR_EXPR, vfunc_ptr_type_node, decl);
+ 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);
+
+ return inits;
+}
+
/* Returns a pointer to the virtual base class of EXP that has the
indicated TYPE. EXP is of class type, not a pointer type. */
@@ -945,47 +1019,6 @@ get_derived_offset (binfo, type)
return size_binop (MINUS_EXPR, offset1, offset2);
}
-/* Update the rtti info for this class. */
-
-static void
-set_rtti_entry (virtuals, offset, type)
- tree virtuals, offset, type;
-{
- tree decl;
-
- if (CLASSTYPE_COM_INTERFACE (type))
- return;
-
- if (flag_rtti)
- decl = get_tinfo_decl (type);
- else if (!new_abi_rtti_p ())
- /* If someone tries to get RTTI information for a type compiled
- without RTTI, they're out of luck. By calling __pure_virtual
- in this case, we give a small clue as to what went wrong. We
- could consider having a __no_typeinfo function as well, for a
- more specific hint. */
- decl = abort_fndecl;
- else
- /* For the new-abi, we just point to the type_info object. */
- decl = NULL_TREE;
-
- if (flag_vtable_thunks)
- {
- /* The first slot holds the offset. */
- BV_DELTA (virtuals) = offset;
- BV_VCALL_INDEX (virtuals) = integer_zero_node;
-
- /* The next node holds the decl. */
- virtuals = TREE_CHAIN (virtuals);
- offset = ssize_int (0);
- }
-
- /* This slot holds the function to call. */
- BV_DELTA (virtuals) = offset;
- BV_VCALL_INDEX (virtuals) = integer_zero_node;
- BV_FN (virtuals) = decl;
-}
-
/* Create a VAR_DECL for a primary or secondary vtable for
CLASS_TYPE. Use NAME for the name of the vtable, and VTABLE_TYPE
for its type. */
@@ -1067,8 +1100,6 @@ build_primary_vtable (binfo, type)
if (binfo)
{
- tree offset;
-
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. */
@@ -1079,11 +1110,6 @@ build_primary_vtable (binfo, type)
DECL_SIZE (decl) = TYPE_SIZE (TREE_TYPE (BINFO_VTABLE (binfo)));
DECL_SIZE_UNIT (decl)
= TYPE_SIZE_UNIT (TREE_TYPE (BINFO_VTABLE (binfo)));
-
- /* Now do rtti stuff. */
- offset = get_derived_offset (TYPE_BINFO (type), NULL_TREE);
- offset = size_diffop (size_zero_node, offset);
- set_rtti_entry (virtuals, offset, type);
}
else
{
@@ -1171,10 +1197,6 @@ build_secondary_vtable (binfo, for_type)
else
offset = BINFO_OFFSET (binfo);
- set_rtti_entry (BINFO_VIRTUALS (binfo),
- size_diffop (size_zero_node, offset),
- for_type);
-
/* In the new ABI, secondary vtables are laid out as part of the
same structure as the primary vtable. */
if (merge_primary_and_secondary_vtables_p ())
@@ -1349,42 +1371,52 @@ modify_vtable_entry (t, binfo, fndecl, delta, virtuals)
}
}
-/* Call this function whenever its known that a vtable for T is going
- to be needed. It's safe to call it more than once. *HAS_VIRTUAL_P
- is initialized to the number of slots that are reserved at the
- beginning of the vtable for RTTI information. */
+/* Return the index (in the virtual function table) of the first
+ virtual function. */
+
+int
+first_vfun_index (t)
+ tree t;
+{
+ /* Under the old ABI, the offset-to-top and RTTI entries are at
+ indices zero and one; under the new ABI, the first virtual
+ function is at index zero. */
+ if (!CLASSTYPE_COM_INTERFACE (t) && !flag_new_abi)
+ return flag_vtable_thunks ? 2 : 1;
+
+ return 0;
+}
+
+/* Set DECL_VINDEX for DECL. VINDEX_P is the number of virtual
+ functions present in the vtable so far. */
static void
-start_vtable (t, has_virtual_p)
+set_vindex (t, decl, vfuns_p)
tree t;
- int *has_virtual_p;
+ tree decl;
+ int *vfuns_p;
{
- if (*has_virtual_p == 0 && ! CLASSTYPE_COM_INTERFACE (t))
- {
- /* If we are using thunks, use two slots at the front, one
- for the offset pointer, one for the tdesc pointer.
- For ARM-style vtables, use the same slot for both. */
- if (flag_vtable_thunks)
- *has_virtual_p = 2;
- else
- *has_virtual_p = 1;
- }
+ int vindex;
+
+ vindex = (*vfuns_p)++;
+ vindex += first_vfun_index (t);
+ DECL_VINDEX (decl) = build_shared_int_cst (vindex);
}
/* Add a virtual function to all the appropriate vtables for the class
T. DECL_VINDEX(X) should be error_mark_node, if we want to
allocate a new slot in our table. If it is error_mark_node, we
know that no other function from another vtable is overridden by X.
- HAS_VIRTUAL keeps track of how many virtuals there are in our main
- vtable for the type, and we build upon the NEW_VIRTUALS list
+ VFUNS_P keeps track of how many virtuals there are in our
+ main vtable for the type, and we build upon the NEW_VIRTUALS list
and return it. */
static void
add_virtual_function (new_virtuals_p, overridden_virtuals_p,
- has_virtual, fndecl, t)
+ vfuns_p, fndecl, t)
tree *new_virtuals_p;
tree *overridden_virtuals_p;
- int *has_virtual;
+ int *vfuns_p;
tree fndecl;
tree t; /* Structure type. */
{
@@ -1409,10 +1441,8 @@ add_virtual_function (new_virtuals_p, overridden_virtuals_p,
/* We remember that this was the base sub-object for rtti. */
CLASSTYPE_RTTI (t) = t;
- start_vtable (t, has_virtual);
-
/* Now assign virtual dispatch information. */
- DECL_VINDEX (fndecl) = build_shared_int_cst ((*has_virtual)++);
+ set_vindex (t, fndecl, vfuns_p);
DECL_VIRTUAL_CONTEXT (fndecl) = t;
/* Save the state we've computed on the NEW_VIRTUALS list. */
@@ -1969,10 +1999,10 @@ check_bases (t, cant_have_default_ctor_p, cant_have_const_ctor_p,
/* Make the Ith baseclass of T its primary base. */
static void
-set_primary_base (t, i, has_virtual_p)
+set_primary_base (t, i, vfuns_p)
tree t;
int i;
- int *has_virtual_p;
+ int *vfuns_p;
{
tree basetype;
@@ -1982,15 +2012,15 @@ set_primary_base (t, i, has_virtual_p)
TYPE_BINFO_VIRTUALS (t) = TYPE_BINFO_VIRTUALS (basetype);
TYPE_VFIELD (t) = TYPE_VFIELD (basetype);
CLASSTYPE_RTTI (t) = CLASSTYPE_RTTI (basetype);
- *has_virtual_p = CLASSTYPE_VSIZE (basetype);
+ *vfuns_p = CLASSTYPE_VSIZE (basetype);
}
/* Determine the primary class for T. */
static void
-determine_primary_base (t, has_virtual_p)
+determine_primary_base (t, vfuns_p)
tree t;
- int *has_virtual_p;
+ int *vfuns_p;
{
int i, n_baseclasses = CLASSTYPE_N_BASECLASSES (t);
@@ -1998,7 +2028,7 @@ determine_primary_base (t, has_virtual_p)
if (n_baseclasses == 0)
return;
- *has_virtual_p = 0;
+ *vfuns_p = 0;
for (i = 0; i < n_baseclasses; i++)
{
@@ -2021,7 +2051,7 @@ determine_primary_base (t, has_virtual_p)
if (!CLASSTYPE_HAS_PRIMARY_BASE_P (t))
{
- set_primary_base (t, i, has_virtual_p);
+ set_primary_base (t, i, vfuns_p);
CLASSTYPE_VFIELDS (t) = copy_list (CLASSTYPE_VFIELDS (basetype));
}
else
@@ -2039,8 +2069,8 @@ determine_primary_base (t, has_virtual_p)
VF_BASETYPE_VALUE (vfields),
CLASSTYPE_VFIELDS (t));
- if (*has_virtual_p == 0)
- set_primary_base (t, i, has_virtual_p);
+ if (*vfuns_p == 0)
+ set_primary_base (t, i, vfuns_p);
}
}
}
@@ -2060,7 +2090,7 @@ determine_primary_base (t, has_virtual_p)
if (TREE_VIA_VIRTUAL (base_binfo)
&& CLASSTYPE_NEARLY_EMPTY_P (basetype))
{
- set_primary_base (t, i, has_virtual_p);
+ set_primary_base (t, i, vfuns_p);
CLASSTYPE_VFIELDS (t) = copy_list (CLASSTYPE_VFIELDS (basetype));
break;
}
@@ -2557,9 +2587,7 @@ static int
num_vfun_entries (binfo)
tree binfo;
{
- return list_length (skip_rtti_stuff (binfo,
- BINFO_TYPE (binfo),
- NULL));
+ return list_length (BINFO_VIRTUALS (binfo));
}
/* Called from num_extra_vtbl_entries via dfs_walk. */
@@ -2609,7 +2637,19 @@ num_extra_vtbl_entries (binfo)
entries += vod.offsets;
}
- return entries ? size_int (entries) : size_zero_node;
+ /* 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
@@ -2636,7 +2676,6 @@ build_vtbl_initializer (binfo, t)
{
tree v = BINFO_VIRTUALS (binfo);
tree inits = NULL_TREE;
- tree type = BINFO_TYPE (binfo);
/* Add entries to the vtable that indicate how to adjust the this
pointer when calling a virtual function in this class. */
@@ -2646,48 +2685,8 @@ build_vtbl_initializer (binfo, t)
inits = chainon (build_vbase_offset_vtbl_entries (binfo, t),
inits);
- /* Process the RTTI stuff at the head of the list. If we're not
- using vtable thunks, then the RTTI entry is just an ordinary
- function, and we can process it just like the other virtual
- function entries. */
- if (!CLASSTYPE_COM_INTERFACE (type) && flag_vtable_thunks)
- {
- tree offset;
- tree init;
-
- /* The first entry is an offset. */
- offset = TREE_PURPOSE (v);
- my_friendly_assert (TREE_CODE (offset) == INTEGER_CST,
- 19990727);
-
- /* 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);
-
- v = TREE_CHAIN (v);
-
- if (new_abi_rtti_p ())
- {
- tree decl = TREE_VALUE (v);
-
- if (decl)
- decl = build_unary_op (ADDR_EXPR, decl, 0);
- else
- decl = integer_zero_node;
- decl = build1 (NOP_EXPR, vfunc_ptr_type_node, decl);
- TREE_CONSTANT (decl) = 1;
- decl = build_vtable_entry (integer_zero_node, integer_zero_node,
- decl);
- inits = tree_cons (NULL_TREE, decl, inits);
-
- v = TREE_CHAIN (v);
- }
- /* In the old abi the second entry (the tdesc pointer) is
- just an ordinary function, so it can be dealt with like the
- virtual functions. */
- }
+ /* Add entries to the vtable for RTTI. */
+ inits = chainon (build_rtti_vtbl_entries (binfo, t), inits);
/* Go through all the ordinary virtual functions, building up
initializers. */
@@ -3048,43 +3047,6 @@ find_final_overrider (t, binfo, fn)
return build_tree_list (ffod.overriding_fn, ffod.overriding_base);
}
-/* Return the BINFO_VIRTUALS list for BINFO, without the RTTI stuff at
- the front. If non-NULL, N is set to the number of entries
- skipped. */
-
-tree
-skip_rtti_stuff (binfo, t, n)
- tree binfo;
- tree t;
- HOST_WIDE_INT *n;
-{
- tree virtuals;
-
- if (CLASSTYPE_COM_INTERFACE (t))
- return 0;
-
- if (n)
- *n = 0;
- virtuals = BINFO_VIRTUALS (binfo);
- if (virtuals)
- {
- /* We always reserve a slot for the offset/tdesc entry. */
- if (n)
- ++*n;
- virtuals = TREE_CHAIN (virtuals);
- }
- if (flag_vtable_thunks && virtuals)
- {
- /* The second slot is reserved for the tdesc pointer when thunks
- are used. */
- if (n)
- ++*n;
- virtuals = TREE_CHAIN (virtuals);
- }
-
- return virtuals;
-}
-
/* Called via dfs_walk. Returns BINFO if BINFO has the same type as
DATA (which is really an _TYPE node). */
@@ -3125,10 +3087,8 @@ dfs_modify_vtables (binfo, data)
/* Now, go through each of the virtual functions in the virtual
function table for BINFO. Find the final overrider, and
update the BINFO_VIRTUALS list appropriately. */
- for (virtuals = skip_rtti_stuff (binfo, BINFO_TYPE (binfo), NULL),
- old_virtuals = skip_rtti_stuff (TYPE_BINFO (BINFO_TYPE (binfo)),
- BINFO_TYPE (binfo),
- NULL);
+ for (virtuals = BINFO_VIRTUALS (binfo),
+ old_virtuals = BINFO_VIRTUALS (TYPE_BINFO (BINFO_TYPE (binfo)));
virtuals;
virtuals = TREE_CHAIN (virtuals),
old_virtuals = TREE_CHAIN (old_virtuals))
@@ -3138,17 +3098,16 @@ dfs_modify_vtables (binfo, data)
tree overrider;
tree vindex;
tree delta;
- HOST_WIDE_INT vindex_val, i;
-
+ HOST_WIDE_INT vindex_val;
+ HOST_WIDE_INT i;
/* Find the function which originally caused this vtable
entry to be present. */
fn = BV_FN (old_virtuals);
vindex = DECL_VINDEX (fn);
b = dfs_walk (binfo, dfs_find_base, NULL, DECL_VIRTUAL_CONTEXT (fn));
- fn = skip_rtti_stuff (TYPE_BINFO (BINFO_TYPE (b)),
- BINFO_TYPE (b),
- &i);
+ fn = BINFO_VIRTUALS (TYPE_BINFO (BINFO_TYPE (b)));
+ i = first_vfun_index (BINFO_TYPE (b));
vindex_val = tree_low_cst (vindex, 0);
while (i < vindex_val)
{
@@ -3195,9 +3154,9 @@ dfs_modify_vtables (binfo, data)
which should therefore be appended to the end of the vtable for T. */
static tree
-modify_all_vtables (t, has_virtual_p, overridden_virtuals)
+modify_all_vtables (t, vfuns_p, overridden_virtuals)
tree t;
- int *has_virtual_p;
+ int *vfuns_p;
tree overridden_virtuals;
{
tree binfo;
@@ -3224,11 +3183,8 @@ modify_all_vtables (t, has_virtual_p, overridden_virtuals)
if (BINFO_VIRTUALS (binfo)
&& !value_member (fn, BINFO_VIRTUALS (binfo)))
{
- /* We know we need a vtable for this class now. */
- start_vtable (t, has_virtual_p);
/* Set the vtable index. */
- DECL_VINDEX (fn)
- = build_shared_int_cst ((*has_virtual_p)++);
+ set_vindex (t, fn, vfuns_p);
/* We don't need to convert to a base class when calling
this function. */
DECL_VIRTUAL_CONTEXT (fn) = t;
@@ -4220,9 +4176,10 @@ layout_nonempty_base_or_field (rli, decl, binfo, v)
/* Now that we know where it wil be placed, update its
BINFO_OFFSET. */
- offset = convert (ssizetype, byte_position (decl));
+ offset = byte_position (decl);
if (binfo)
- propagate_binfo_offsets (binfo, offset);
+ propagate_binfo_offsets (binfo,
+ convert (ssizetype, offset));
/* We have to check to see whether or not there is already
something of the same type at the offset we're about to use.
@@ -4243,7 +4200,7 @@ layout_nonempty_base_or_field (rli, decl, binfo, v)
{
/* Undo the propogate_binfo_offsets call. */
offset = size_diffop (size_zero_node, offset);
- propagate_binfo_offsets (binfo, offset);
+ propagate_binfo_offsets (binfo, convert (ssizetype, offset));
/* Strip off the size allocated to this field. That puts us
at the first place we could have put the field with
@@ -4601,11 +4558,11 @@ check_bases_and_members (t, empty_p)
responsibility to do that. */
static tree
-create_vtable_ptr (t, empty_p, has_virtual_p,
+create_vtable_ptr (t, empty_p, vfuns_p,
new_virtuals_p, overridden_virtuals_p)
tree t;
int *empty_p;
- int *has_virtual_p;
+ int *vfuns_p;
tree *new_virtuals_p;
tree *overridden_virtuals_p;
{
@@ -4616,17 +4573,15 @@ create_vtable_ptr (t, empty_p, has_virtual_p,
for (fn = TYPE_METHODS (t); fn; fn = TREE_CHAIN (fn))
if (DECL_VINDEX (fn))
add_virtual_function (new_virtuals_p, overridden_virtuals_p,
- has_virtual_p, fn, t);
+ vfuns_p, fn, t);
- /* Even if there weren't any new virtual functions, we might need a
+ /* If we couldn't find an appropriate base class, create a new field
+ here. Even if there weren't any new virtual functions, we might need a
new virtual function table if we're supposed to include vptrs in
all classes that need them. */
- if (TYPE_CONTAINS_VPTR_P (t) && vptrs_present_everywhere_p ())
- start_vtable (t, has_virtual_p);
-
- /* If we couldn't find an appropriate base class, create a new field
- here. */
- if (*has_virtual_p && !TYPE_VFIELD (t))
+ if (!TYPE_VFIELD (t)
+ && (*vfuns_p
+ || (TYPE_CONTAINS_VPTR_P (t) && vptrs_present_everywhere_p ())))
{
/* We build this decl with vtbl_ptr_type_node, which is a
`vtable_entry_type*'. It might seem more precise to use
@@ -4972,11 +4927,11 @@ end_of_class (t, include_virtuals_p)
pointer. */
static void
-layout_class_type (t, empty_p, has_virtual_p,
+layout_class_type (t, empty_p, vfuns_p,
new_virtuals_p, overridden_virtuals_p)
tree t;
int *empty_p;
- int *has_virtual_p;
+ int *vfuns_p;
tree *new_virtuals_p;
tree *overridden_virtuals_p;
{
@@ -4995,10 +4950,10 @@ layout_class_type (t, empty_p, has_virtual_p,
/* If possible, we reuse the virtual function table pointer from one
of our base classes. */
- determine_primary_base (t, has_virtual_p);
+ determine_primary_base (t, vfuns_p);
/* Create a pointer to our virtual function table. */
- vptr = create_vtable_ptr (t, empty_p, has_virtual_p,
+ vptr = create_vtable_ptr (t, empty_p, vfuns_p,
new_virtuals_p, overridden_virtuals_p);
/* Under the new ABI, the vptr is always the first thing in the
@@ -5215,7 +5170,7 @@ finish_struct_1 (t)
tree t;
{
tree x;
- int has_virtual;
+ int vfuns;
/* The NEW_VIRTUALS is a TREE_LIST. The TREE_VALUE of each node is
a FUNCTION_DECL. Each of these functions is a virtual function
declared in T that does not override any virtual function from a
@@ -5246,7 +5201,7 @@ finish_struct_1 (t)
TYPE_SIZE (t) = NULL_TREE;
CLASSTYPE_GOT_SEMICOLON (t) = 0;
CLASSTYPE_VFIELD_PARENT (t) = -1;
- has_virtual = 0;
+ vfuns = 0;
CLASSTYPE_RTTI (t) = NULL_TREE;
/* Do end-of-class semantic processing: checking the validity of the
@@ -5254,7 +5209,7 @@ finish_struct_1 (t)
check_bases_and_members (t, &empty);
/* Layout the class itself. */
- layout_class_type (t, &empty, &has_virtual,
+ layout_class_type (t, &empty, &vfuns,
&new_virtuals, &overridden_virtuals);
/* Set up the DECL_FIELD_BITPOS of the vfield if we need to, as we
@@ -5278,7 +5233,7 @@ finish_struct_1 (t)
}
overridden_virtuals
- = modify_all_vtables (t, &has_virtual, nreverse (overridden_virtuals));
+ = modify_all_vtables (t, &vfuns, nreverse (overridden_virtuals));
/* If necessary, create the primary vtable for this class. */
if (new_virtuals
@@ -5288,22 +5243,7 @@ finish_struct_1 (t)
new_virtuals = nreverse (new_virtuals);
/* We must enter these virtuals into the table. */
if (!CLASSTYPE_HAS_PRIMARY_BASE_P (t))
- {
- if (! CLASSTYPE_COM_INTERFACE (t))
- {
- /* The second slot is for the tdesc pointer when thunks
- are used. */
- if (flag_vtable_thunks)
- new_virtuals = tree_cons (NULL_TREE, NULL_TREE, new_virtuals);
-
- /* The first slot is for the rtti offset. */
- new_virtuals = tree_cons (NULL_TREE, NULL_TREE, new_virtuals);
-
- set_rtti_entry (new_virtuals,
- convert (ssizetype, integer_zero_node), t);
- }
- build_primary_vtable (NULL_TREE, t);
- }
+ build_primary_vtable (NULL_TREE, 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. */
@@ -5346,7 +5286,7 @@ finish_struct_1 (t)
my_friendly_assert (TYPE_BINFO_VIRTUALS (t) == NULL_TREE,
20000116);
- CLASSTYPE_VSIZE (t) = has_virtual;
+ CLASSTYPE_VSIZE (t) = vfuns;
/* Entries for virtual functions defined in the primary base are
followed by entries for new functions unique to this class. */
TYPE_BINFO_VIRTUALS (t)
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 57c711f..0433135 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -1545,8 +1545,8 @@ struct lang_type
CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (NODE))) \
: NULL_TREE)
-/* The number of virtual functions defined for this
- _CLASSTYPE node. */
+/* The number of virtual functions present in this classes virtual
+ function table. */
#define CLASSTYPE_VSIZE(NODE) (TYPE_LANG_SPECIFIC(NODE)->vsize)
/* A chain of BINFOs for the direct and indirect virtual base classes
@@ -3685,8 +3685,7 @@ extern void push_lang_context PARAMS ((tree));
extern void pop_lang_context PARAMS ((void));
extern tree instantiate_type PARAMS ((tree, tree, int));
extern void print_class_statistics PARAMS ((void));
-extern tree skip_rtti_stuff PARAMS ((tree, tree,
- HOST_WIDE_INT *));
+extern int first_vfun_index PARAMS ((tree));
extern void build_self_reference PARAMS ((void));
extern void warn_hidden PARAMS ((tree));
extern tree get_enclosing_class PARAMS ((tree));
@@ -4212,11 +4211,9 @@ extern tree dfs_skip_nonprimary_vbases_unmarkedp PARAMS ((tree, void *));
extern tree dfs_skip_nonprimary_vbases_markedp PARAMS ((tree, void *));
extern tree dfs_unmarked_real_bases_queue_p PARAMS ((tree, void *));
extern tree dfs_marked_real_bases_queue_p PARAMS ((tree, void *));
-extern tree dfs_vtable_path_unmarked_real_bases_queue_p
- PARAMS ((tree, void *));
-extern tree dfs_vtable_path_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/error.c b/gcc/cp/error.c
index a0be98f..5600176 100644
--- a/gcc/cp/error.c
+++ b/gcc/cp/error.c
@@ -1857,7 +1857,7 @@ dump_expr (t, flags)
t = TYPE_METHOD_BASETYPE (t);
virtuals = TYPE_BINFO_VIRTUALS (TYPE_MAIN_VARIANT (t));
- n = tree_low_cst (idx, 0);
+ n = tree_low_cst (idx, 0) - first_vfun_index (t);
/* Map vtable index back one, to allow for the null pointer to
member. */
diff --git a/gcc/cp/rtti.c b/gcc/cp/rtti.c
index 30a972c..ea21756 100644
--- a/gcc/cp/rtti.c
+++ b/gcc/cp/rtti.c
@@ -132,6 +132,7 @@ build_headof (exp)
tree type = TREE_TYPE (exp);
tree aref;
tree offset;
+ tree index;
my_friendly_assert (TREE_CODE (type) == POINTER_TYPE, 20000112);
type = TREE_TYPE (type);
@@ -151,7 +152,15 @@ build_headof (exp)
/* We use this a couple of times below, protect it. */
exp = save_expr (exp);
- aref = build_vtbl_ref (build_indirect_ref (exp, NULL_PTR), integer_zero_node);
+ /* Under the new ABI, the offset-to-top field is at index -2 from
+ the vptr. */
+ if (new_abi_rtti_p ())
+ index = build_int_2 (-2, -1);
+ /* But under the old ABI, it is at offset zero. */
+ else
+ index = integer_zero_node;
+
+ aref = build_vtbl_ref (build_indirect_ref (exp, NULL_PTR), index);
if (flag_vtable_thunks)
offset = aref;
@@ -230,6 +239,7 @@ get_tinfo_decl_dynamic (exp)
{
/* build reference to type_info from vtable. */
tree t;
+ tree index;
if (! flag_rtti)
error ("taking dynamic typeid of object with -fno-rtti");
@@ -247,10 +257,15 @@ get_tinfo_decl_dynamic (exp)
exp = build_indirect_ref (exp, NULL_PTR);
}
- if (flag_vtable_thunks)
- t = build_vfn_ref ((tree *) 0, exp, integer_one_node);
+ /* The RTTI information is always in the vtable, but it's at
+ different indices depending on the ABI. */
+ if (new_abi_rtti_p ())
+ index = minus_one_node;
+ else if (flag_vtable_thunks)
+ index = integer_one_node;
else
- t = build_vfn_ref ((tree *) 0, exp, integer_zero_node);
+ index = integer_zero_node;
+ t = build_vfn_ref ((tree *) 0, exp, index);
TREE_TYPE (t) = build_pointer_type (tinfo_decl_type);
return t;
}
@@ -1284,8 +1299,7 @@ tinfo_base_init (desc, target)
if (TINFO_VTABLE_DECL (desc))
{
- tree vtbl_ptr = build_unary_op (ADDR_EXPR, TINFO_VTABLE_DECL (desc), 0);
-
+ tree vtbl_ptr = TINFO_VTABLE_DECL (desc);
init = tree_cons (NULL_TREE, vtbl_ptr, init);
}
@@ -1616,7 +1630,18 @@ create_pseudo_type_info VPARAMS((const char *real_name, int ident, ...))
/* Get the vtable decl. */
real_type = xref_tag (class_type_node, get_identifier (real_name), 1);
vtable_decl = get_vtable_decl (real_type, /*complete=*/1);
-
+ vtable_decl = build_unary_op (ADDR_EXPR, vtable_decl, 0);
+
+ /* Under the new ABI, we need to point into the middle of the
+ vtable. */
+ if (vbase_offsets_in_vtable_p ())
+ {
+ vtable_decl = build (PLUS_EXPR, TREE_TYPE (vtable_decl),
+ vtable_decl,
+ size_extra_vtbl_entries (TYPE_BINFO (real_type)));
+ TREE_CONSTANT (vtable_decl) = 1;
+ }
+
/* First field is the pseudo type_info base class. */
fields[0] = build_lang_decl (FIELD_DECL, NULL_TREE, ti_desc_type_node);
diff --git a/gcc/cp/search.c b/gcc/cp/search.c
index cafdfc2..14ceff2 100644
--- a/gcc/cp/search.c
+++ b/gcc/cp/search.c
@@ -104,8 +104,6 @@ static void expand_upcast_fixups
static void fixup_virtual_upcast_offsets
PARAMS ((tree, tree, int, int, tree, tree, tree, tree,
tree *));
-static tree marked_vtable_pathp PARAMS ((tree, void *));
-static tree unmarked_vtable_pathp PARAMS ((tree, void *));
static tree marked_new_vtablep PARAMS ((tree, void *));
static tree unmarked_new_vtablep PARAMS ((tree, void *));
static tree marked_pushdecls_p PARAMS ((tree, void *));
@@ -2346,30 +2344,6 @@ dfs_marked_real_bases_queue_p (binfo, data)
return binfo ? markedp (binfo, NULL) : NULL_TREE;
}
-/* Like dfs_unmarked_real_bases_queue_p but walks only into things
- that are not BINFO_VTABLE_PATH_MARKED. */
-
-tree
-dfs_vtable_path_unmarked_real_bases_queue_p (binfo, data)
- tree binfo;
- void *data;
-{
- binfo = get_shared_vbase_if_not_primary (binfo, data);
- return binfo ? unmarked_vtable_pathp (binfo, NULL): NULL_TREE;
-}
-
-/* Like dfs_unmarked_real_bases_queue_p but walks only into things
- that are BINFO_VTABLE_PATH_MARKED. */
-
-tree
-dfs_vtable_path_marked_real_bases_queue_p (binfo, data)
- tree binfo;
- void *data;
-{
- binfo = get_shared_vbase_if_not_primary (binfo, data);
- return binfo ? marked_vtable_pathp (binfo, NULL): NULL_TREE;
-}
-
/* A queue function that skips all virtual bases (and their
bases). */
@@ -2400,9 +2374,7 @@ dfs_get_pure_virtuals (binfo, data)
{
tree virtuals;
- for (virtuals = skip_rtti_stuff (binfo,
- BINFO_TYPE (binfo),
- NULL);
+ for (virtuals = BINFO_VIRTUALS (binfo);
virtuals;
virtuals = TREE_CHAIN (virtuals))
if (DECL_PURE_VIRTUAL_P (TREE_VALUE (virtuals)))
@@ -2447,7 +2419,7 @@ get_pure_virtuals (type)
{
tree virtuals;
- for (virtuals = skip_rtti_stuff (vbases, BINFO_TYPE (vbases), NULL);
+ for (virtuals = BINFO_VIRTUALS (vbases);
virtuals;
virtuals = TREE_CHAIN (virtuals))
{
@@ -2527,7 +2499,7 @@ unmarkedp (binfo, data)
return !BINFO_MARKED (binfo) ? binfo : NULL_TREE;
}
-static tree
+tree
marked_vtable_pathp (binfo, data)
tree binfo;
void *data ATTRIBUTE_UNUSED;
@@ -2535,7 +2507,7 @@ marked_vtable_pathp (binfo, data)
return BINFO_VTABLE_PATH_MARKED (binfo) ? binfo : NULL_TREE;
}
-static tree
+tree
unmarked_vtable_pathp (binfo, data)
tree binfo;
void *data ATTRIBUTE_UNUSED;
@@ -2863,9 +2835,10 @@ expand_upcast_fixups (binfo, addr, orig_addr, vbase, vbase_addr, t,
*vbase_offsets = delta;
}
- virtuals = skip_rtti_stuff (binfo, BINFO_TYPE (binfo), &n);
-
- while (virtuals)
+ for (virtuals = BINFO_VIRTUALS (binfo),
+ n = first_vfun_index (BINFO_TYPE (binfo));
+ virtuals;
+ virtuals = TREE_CHAIN (virtuals), ++n)
{
tree current_fndecl = TREE_VALUE (virtuals);
@@ -2956,8 +2929,6 @@ expand_upcast_fixups (binfo, addr, orig_addr, vbase, vbase_addr, t,
finish_expr_stmt (build_modify_expr (new_delta, NOP_EXPR,
old_delta));
}
- ++n;
- virtuals = TREE_CHAIN (virtuals);
}
}
diff --git a/gcc/cp/tinfo.cc b/gcc/cp/tinfo.cc
index 90c3058..3bf3c90 100644
--- a/gcc/cp/tinfo.cc
+++ b/gcc/cp/tinfo.cc
@@ -1100,9 +1100,8 @@ __dynamic_cast (const void *src_ptr, // object started from
{
const void *vtable = *static_cast <const void *const *> (src_ptr);
const vtable_prefix *prefix =
- adjust_pointer <vtable_prefix> (vtable, 0);
- // FIXME: the above offset should be -offsetof (vtable_prefix, origin));
- // but we don't currently layout vtables correctly.
+ adjust_pointer <vtable_prefix> (vtable,
+ -offsetof (vtable_prefix, origin));
const void *whole_ptr =
adjust_pointer <void> (src_ptr, prefix->whole_object);
const __class_type_info *whole_type = prefix->whole_type;
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index d1c7d2d..e27ff7b 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -925,7 +925,8 @@ debug_binfo (elem)
else
fprintf (stderr, "no vtable decl yet\n");
fprintf (stderr, "virtuals:\n");
- virtuals = skip_rtti_stuff (elem, BINFO_TYPE (elem), &n);
+ virtuals = BINFO_VIRTUALS (elem);
+ n = first_vfun_index (BINFO_TYPE (elem));
while (virtuals)
{