splay_tree names_used;
}* class_stack_node_t;
-typedef struct vcall_offset_data_s
+typedef struct vtbl_init_data_s
{
+ /* The base for which we're building initializers. */
+ tree binfo;
/* The binfo for the most-derived type. */
tree derived;
/* The negative-index vtable initializers built up so far. These
/* The last (i.e., most negative entry in INITS. */
tree* last_init;
/* The binfo for the virtual base for which we're building
- initializers. */
+ vcall offset initializers. */
tree vbase;
/* The functions in vbase for which we have already provided vcall
offsets. */
tree index;
/* Nonzero if we are building the initializer for the primary
vtable. */
- int primary_p;
-} vcall_offset_data;
+ int primary_vtbl_p;
+ /* Nonzero if we are building the initializer for a construction
+ vtable. */
+ int ctor_vtbl_p;
+} vtbl_init_data;
+
+/* The type of a function passed to walk_subobject_offsets. */
+typedef int (*subobject_offset_fn) PARAMS ((tree, tree, splay_tree));
/* The stack itself. This is an dynamically resized array. The
number of elements allocated is CURRENT_CLASS_STACK_SIZE. */
static tree get_vfield_name PARAMS ((tree));
static void finish_struct_anon PARAMS ((tree));
static tree build_vbase_pointer PARAMS ((tree, tree));
-static tree build_vtable_entry PARAMS ((tree, tree, tree));
+static tree build_vtable_entry PARAMS ((tree, tree, tree, int));
static tree get_vtable_name PARAMS ((tree));
static tree get_derived_offset PARAMS ((tree, tree));
static tree get_basefndecls PARAMS ((tree, tree));
static tree add_implicitly_declared_members PARAMS ((tree, int, int, int));
static tree fixed_type_or_null PARAMS ((tree, int *));
static tree resolve_address_of_overloaded_function PARAMS ((tree, tree, int,
- int, tree));
+ int, int, tree));
static void build_vtable_entry_ref PARAMS ((tree, tree, tree));
static tree build_vtbl_initializer PARAMS ((tree, tree, tree, tree, int *));
static int count_fields PARAMS ((tree));
static void check_field_decls PARAMS ((tree, tree *, int *, int *, int *,
int *));
static void build_base_field PARAMS ((record_layout_info, tree, int *,
- unsigned int *, varray_type *));
-static varray_type build_base_fields PARAMS ((record_layout_info, int *));
+ unsigned int *, splay_tree));
+static void build_base_fields PARAMS ((record_layout_info, int *,
+ splay_tree));
static tree build_vbase_pointer_fields PARAMS ((record_layout_info, int *));
static tree build_vtbl_or_vbase_field PARAMS ((tree, tree, tree, tree, tree,
int *));
static void check_bases_and_members PARAMS ((tree, int *));
static tree create_vtable_ptr PARAMS ((tree, int *, int *, tree *, tree *));
static void layout_class_type PARAMS ((tree, int *, int *, tree *, tree *));
-static void fixup_pending_inline PARAMS ((struct pending_inline *));
+static void fixup_pending_inline PARAMS ((tree));
static void fixup_inline_methods PARAMS ((tree));
-static void set_primary_base PARAMS ((tree, int, int *));
-static tree dfs_propagate_binfo_offsets PARAMS ((tree, void *));
+static void set_primary_base PARAMS ((tree, tree, int *));
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 void layout_virtual_bases PARAMS ((tree, splay_tree));
static tree dfs_set_offset_for_unshared_vbases PARAMS ((tree, void *));
-static void build_vbase_offset_vtbl_entries PARAMS ((tree, vcall_offset_data *));
-static tree dfs_build_vcall_offset_vtbl_entries PARAMS ((tree, void *));
-static void build_vcall_offset_vtbl_entries PARAMS ((tree, vcall_offset_data *));
+static void build_vbase_offset_vtbl_entries PARAMS ((tree, vtbl_init_data *));
+static void add_vcall_offset_vtbl_entries_r PARAMS ((tree, vtbl_init_data *));
+static void add_vcall_offset_vtbl_entries_1 PARAMS ((tree, vtbl_init_data *));
+static void build_vcall_offset_vtbl_entries PARAMS ((tree, vtbl_init_data *));
static void layout_vtable_decl PARAMS ((tree, int));
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));
static void dump_class_hierarchy_r PARAMS ((tree, tree, int));
extern void dump_class_hierarchy PARAMS ((tree));
static void initialize_array PARAMS ((tree, tree));
static void layout_nonempty_base_or_field PARAMS ((record_layout_info,
tree, tree,
- varray_type));
-static tree dfs_record_base_offsets PARAMS ((tree, void *));
-static void record_base_offsets PARAMS ((tree, varray_type *));
-static tree dfs_search_base_offsets PARAMS ((tree, void *));
-static int layout_conflict_p PARAMS ((tree, varray_type));
+ splay_tree));
static unsigned HOST_WIDE_INT end_of_class PARAMS ((tree, int));
-static void layout_empty_base PARAMS ((tree, tree, varray_type));
+static void layout_empty_base PARAMS ((tree, tree, splay_tree));
static void accumulate_vtbl_inits PARAMS ((tree, tree, tree, tree, tree));
static void set_vindex PARAMS ((tree, tree, int *));
-static void build_rtti_vtbl_entries PARAMS ((tree, tree, vcall_offset_data *));
+static void build_rtti_vtbl_entries PARAMS ((tree, tree, vtbl_init_data *));
static void build_vcall_and_vbase_vtbl_entries PARAMS ((tree,
- vcall_offset_data *));
+ vtbl_init_data *));
static tree dfs_mark_primary_bases PARAMS ((tree, void *));
static void mark_primary_bases PARAMS ((tree));
static void clone_constructors_and_destructors PARAMS ((tree));
static tree copy_virtuals PARAMS ((tree));
static void build_ctor_vtbl_group PARAMS ((tree, tree));
static void build_vtt PARAMS ((tree));
-static tree *build_vtt_inits PARAMS ((tree, tree, tree *, tree *));
-static tree dfs_build_vtt_inits PARAMS ((tree, void *));
+static tree *build_vtt_inits PARAMS ((tree, tree, int, tree *, tree *));
+static tree dfs_build_secondary_vptr_vtt_inits PARAMS ((tree, void *));
static tree dfs_fixup_binfo_vtbls PARAMS ((tree, void *));
-static int indirect_primary_base_p PARAMS ((tree, tree));
+static tree get_matching_base PARAMS ((tree, tree));
+static tree dfs_get_primary_binfo PARAMS ((tree, void*));
+static int record_subobject_offset PARAMS ((tree, tree, splay_tree));
+static int check_subobject_offset PARAMS ((tree, tree, splay_tree));
+static int walk_subobject_offsets PARAMS ((tree, subobject_offset_fn,
+ tree, splay_tree, int));
+static void record_subobject_offsets PARAMS ((tree, tree, splay_tree, int));
+static int layout_conflict_p PARAMS ((tree, tree, splay_tree, int));
+static int splay_tree_compare_integer_csts PARAMS ((splay_tree_key k1,
+ splay_tree_key k2));
/* Variables shared between class.c and call.c. */
i = build_c_cast (ptrdiff_type_node, build_unary_op (ADDR_EXPR, i, 0));
i2 = build_array_ref (vtbl, build_int_2(0,0));
i2 = build_c_cast (ptrdiff_type_node, build_unary_op (ADDR_EXPR, i2, 0));
- i = build_binary_op (MINUS_EXPR, i, i2);
+ i = cp_build_binary_op (MINUS_EXPR, i, i2);
i = build_tree_list (build_string (1, "i"), i);
finish_asm_stmt (ridpointers[RID_VOLATILE],
{
tree offset1 = get_vfield_offset (TYPE_BINFO (BINFO_TYPE (binfo)));
tree offset2;
- int i;
- while (BINFO_BASETYPES (binfo)
- && (i = CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (binfo))) != -1)
- {
- tree binfos = BINFO_BASETYPES (binfo);
- if (BINFO_TYPE (binfo) == type)
- break;
- binfo = TREE_VEC_ELT (binfos, i);
- }
+ while (!same_type_p (BINFO_TYPE (binfo), type))
+ binfo = get_primary_binfo (binfo);
offset2 = get_vfield_offset (TYPE_BINFO (BINFO_TYPE (binfo)));
return size_binop (MINUS_EXPR, offset1, offset2);
copies = copy_list (BINFO_VIRTUALS (binfo));
for (t = copies; t; t = TREE_CHAIN (t))
- BV_VCALL_INDEX (t) = NULL_TREE;
+ {
+ BV_VCALL_INDEX (t) = NULL_TREE;
+ BV_USE_VCALL_INDEX_P (t) = 0;
+ BV_GENERATE_THUNK_WITH_VTABLE_P (t) = 0;
+ }
return copies;
}
build_primary_vtable (binfo, type)
tree binfo, type;
{
- tree virtuals, decl;
+ tree decl;
+ tree virtuals;
decl = get_vtable_decl (type, /*complete=*/0);
on our first approximation. */
TYPE_BINFO_VTABLE (type) = decl;
TYPE_BINFO_VIRTUALS (type) = virtuals;
-
- binfo = TYPE_BINFO (type);
- SET_BINFO_NEW_VTABLE_MARKED (binfo, type);
+ SET_BINFO_NEW_VTABLE_MARKED (TYPE_BINFO (type), type);
return 1;
}
tree new_decl;
tree offset;
tree path = binfo;
- char *buf, *buf2;
+ char *buf;
+ const char *buf2;
char joiner = '_';
int i;
/* We've already dealt with this function. */
return;
- new_virtual = build_tree_list (NULL_TREE, fndecl);
+ new_virtual = make_node (TREE_LIST);
+ BV_FN (new_virtual) = fndecl;
BV_DELTA (new_virtual) = integer_zero_node;
if (DECL_VINDEX (fndecl) == error_mark_node)
}
}
\f
-extern struct obstack *current_obstack;
-
-/* Add method METHOD to class TYPE.
-
- If non-NULL, FIELDS is the entry in the METHOD_VEC vector entry of
- the class type where the method should be added. */
+/* Add method METHOD to class TYPE. If ERROR_P is true, we are adding
+ the method after the class has already been defined because a
+ declaration for it was seen. (Even though that is erroneous, we
+ add the method for improved error recovery.) */
void
-add_method (type, fields, method)
- tree type, *fields, method;
+add_method (type, method, error_p)
+ tree type;
+ tree method;
+ int error_p;
{
int using = (DECL_CONTEXT (method) != type);
-
- if (fields && *fields)
- *fields = build_overload (method, *fields);
- else
+ int len;
+ int slot;
+ tree method_vec;
+
+ if (!CLASSTYPE_METHOD_VEC (type))
+ /* Make a new method vector. We start with 8 entries. We must
+ allocate at least two (for constructors and destructors), and
+ we're going to end up with an assignment operator at some point
+ as well.
+
+ We could use a TREE_LIST for now, and convert it to a TREE_VEC
+ in finish_struct, but we would probably waste more memory
+ making the links in the list than we would by over-allocating
+ the size of the vector here. Furthermore, we would complicate
+ all the code that expects this to be a vector. */
+ CLASSTYPE_METHOD_VEC (type) = make_tree_vec (8);
+
+ method_vec = CLASSTYPE_METHOD_VEC (type);
+ len = TREE_VEC_LENGTH (method_vec);
+
+ /* Constructors and destructors go in special slots. */
+ if (DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (method))
+ slot = CLASSTYPE_CONSTRUCTOR_SLOT;
+ else if (DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (method))
+ slot = CLASSTYPE_DESTRUCTOR_SLOT;
+ else
{
- int len;
- int slot;
- tree method_vec;
-
- if (!CLASSTYPE_METHOD_VEC (type))
- /* Make a new method vector. We start with 8 entries. We must
- allocate at least two (for constructors and destructors), and
- we're going to end up with an assignment operator at some
- point as well.
-
- We could use a TREE_LIST for now, and convert it to a
- TREE_VEC in finish_struct, but we would probably waste more
- memory making the links in the list than we would by
- over-allocating the size of the vector here. Furthermore,
- we would complicate all the code that expects this to be a
- vector. */
- CLASSTYPE_METHOD_VEC (type) = make_tree_vec (8);
-
- method_vec = CLASSTYPE_METHOD_VEC (type);
- len = TREE_VEC_LENGTH (method_vec);
-
- /* Constructors and destructors go in special slots. */
- if (DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (method))
- slot = CLASSTYPE_CONSTRUCTOR_SLOT;
- else if (DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (method))
- slot = CLASSTYPE_DESTRUCTOR_SLOT;
- else
- {
- /* See if we already have an entry with this name. */
- for (slot = CLASSTYPE_FIRST_CONVERSION_SLOT; slot < len; ++slot)
- if (!TREE_VEC_ELT (method_vec, slot)
- || (DECL_NAME (OVL_CURRENT (TREE_VEC_ELT (method_vec,
- slot)))
- == DECL_NAME (method)))
- break;
+ /* See if we already have an entry with this name. */
+ for (slot = CLASSTYPE_FIRST_CONVERSION_SLOT; slot < len; ++slot)
+ if (!TREE_VEC_ELT (method_vec, slot)
+ || (DECL_NAME (OVL_CURRENT (TREE_VEC_ELT (method_vec,
+ slot)))
+ == DECL_NAME (method)))
+ break;
- if (slot == len)
- {
- /* We need a bigger method vector. */
- tree new_vec = make_tree_vec (2 * len);
- bcopy ((PTR) &TREE_VEC_ELT (method_vec, 0),
- (PTR) &TREE_VEC_ELT (new_vec, 0),
- len * sizeof (tree));
- len = 2 * len;
- method_vec = CLASSTYPE_METHOD_VEC (type) = new_vec;
- }
+ if (slot == len)
+ {
+ /* We need a bigger method vector. */
+ int new_len;
+ tree new_vec;
+
+ /* In the non-error case, we are processing a class
+ definition. Double the size of the vector to give room
+ for new methods. */
+ if (!error_p)
+ new_len = 2 * len;
+ /* In the error case, the vector is already complete. We
+ don't expect many errors, and the rest of the front-end
+ will get confused if there are empty slots in the vector. */
+ else
+ new_len = len + 1;
+
+ new_vec = make_tree_vec (new_len);
+ bcopy ((PTR) &TREE_VEC_ELT (method_vec, 0),
+ (PTR) &TREE_VEC_ELT (new_vec, 0),
+ len * sizeof (tree));
+ len = new_len;
+ method_vec = CLASSTYPE_METHOD_VEC (type) = new_vec;
+ }
- if (DECL_CONV_FN_P (method) && !TREE_VEC_ELT (method_vec, slot))
+ if (DECL_CONV_FN_P (method) && !TREE_VEC_ELT (method_vec, slot))
+ {
+ /* Type conversion operators have to come before ordinary
+ methods; add_conversions depends on this to speed up
+ looking for conversion operators. So, if necessary, we
+ slide some of the vector elements up. In theory, this
+ makes this algorithm O(N^2) but we don't expect many
+ conversion operators. */
+ for (slot = 2; slot < len; ++slot)
{
- /* Type conversion operators have to come before
- ordinary methods; add_conversions depends on this to
- speed up looking for conversion operators. So, if
- necessary, we slide some of the vector elements up.
- In theory, this makes this algorithm O(N^2) but we
- don't expect many conversion operators. */
- for (slot = 2; slot < len; ++slot)
- {
- tree fn = TREE_VEC_ELT (method_vec, slot);
+ tree fn = TREE_VEC_ELT (method_vec, slot);
- if (!fn)
- /* There are no more entries in the vector, so we
- can insert the new conversion operator here. */
- break;
+ if (!fn)
+ /* There are no more entries in the vector, so we
+ can insert the new conversion operator here. */
+ break;
- if (!DECL_CONV_FN_P (OVL_CURRENT (fn)))
- /* We can insert the new function right at the
- SLOTth position. */
- break;
- }
+ if (!DECL_CONV_FN_P (OVL_CURRENT (fn)))
+ /* We can insert the new function right at the
+ SLOTth position. */
+ break;
+ }
- if (!TREE_VEC_ELT (method_vec, slot))
- /* There is nothing in the Ith slot, so we can avoid
- moving anything. */
+ if (!TREE_VEC_ELT (method_vec, slot))
+ /* There is nothing in the Ith slot, so we can avoid
+ moving anything. */
;
- else
- {
- /* We know the last slot in the vector is empty
- because we know that at this point there's room
- for a new function. */
- bcopy ((PTR) &TREE_VEC_ELT (method_vec, slot),
- (PTR) &TREE_VEC_ELT (method_vec, slot + 1),
- (len - slot - 1) * sizeof (tree));
- TREE_VEC_ELT (method_vec, slot) = NULL_TREE;
- }
+ else
+ {
+ /* We know the last slot in the vector is empty
+ because we know that at this point there's room
+ for a new function. */
+ bcopy ((PTR) &TREE_VEC_ELT (method_vec, slot),
+ (PTR) &TREE_VEC_ELT (method_vec, slot + 1),
+ (len - slot - 1) * sizeof (tree));
+ TREE_VEC_ELT (method_vec, slot) = NULL_TREE;
}
}
+ }
- if (template_class_depth (type))
- /* TYPE is a template class. Don't issue any errors now; wait
- until instantiation time to complain. */
- ;
- else
- {
- tree fns;
+ if (template_class_depth (type))
+ /* TYPE is a template class. Don't issue any errors now; wait
+ until instantiation time to complain. */
+ ;
+ else
+ {
+ tree fns;
- /* Check to see if we've already got this method. */
- for (fns = TREE_VEC_ELT (method_vec, slot);
- fns;
- fns = OVL_NEXT (fns))
- {
- tree fn = OVL_CURRENT (fns);
+ /* Check to see if we've already got this method. */
+ for (fns = TREE_VEC_ELT (method_vec, slot);
+ fns;
+ fns = OVL_NEXT (fns))
+ {
+ tree fn = OVL_CURRENT (fns);
- if (TREE_CODE (fn) != TREE_CODE (method))
- continue;
+ if (TREE_CODE (fn) != TREE_CODE (method))
+ continue;
- if (TREE_CODE (method) != TEMPLATE_DECL)
+ if (TREE_CODE (method) != TEMPLATE_DECL)
+ {
+ /* [over.load] Member function declarations with the
+ same name and the same parameter types cannot be
+ overloaded if any of them is a static member
+ function declaration. */
+ if ((DECL_STATIC_FUNCTION_P (fn)
+ != DECL_STATIC_FUNCTION_P (method))
+ || using)
{
- /* [over.load] Member function declarations with the
- same name and the same parameter types cannot be
- overloaded if any of them is a static member
- function declaration. */
- if ((DECL_STATIC_FUNCTION_P (fn)
- != DECL_STATIC_FUNCTION_P (method))
- || using)
+ tree parms1 = TYPE_ARG_TYPES (TREE_TYPE (fn));
+ tree parms2 = TYPE_ARG_TYPES (TREE_TYPE (method));
+
+ if (! DECL_STATIC_FUNCTION_P (fn))
+ parms1 = TREE_CHAIN (parms1);
+ if (! DECL_STATIC_FUNCTION_P (method))
+ parms2 = TREE_CHAIN (parms2);
+
+ if (compparms (parms1, parms2))
{
- tree parms1 = TYPE_ARG_TYPES (TREE_TYPE (fn));
- tree parms2 = TYPE_ARG_TYPES (TREE_TYPE (method));
-
- if (! DECL_STATIC_FUNCTION_P (fn))
- parms1 = TREE_CHAIN (parms1);
- if (! DECL_STATIC_FUNCTION_P (method))
- parms2 = TREE_CHAIN (parms2);
-
- if (compparms (parms1, parms2))
- {
- if (using)
- /* Defer to the local function. */
- return;
- else
- cp_error ("`%#D' and `%#D' cannot be overloaded",
- fn, method);
- }
+ if (using)
+ /* Defer to the local function. */
+ return;
+ else
+ cp_error ("`%#D' and `%#D' cannot be overloaded",
+ fn, method);
}
-
- /* Since this is an ordinary function in a
- non-template class, it's mangled name can be used
- as a unique identifier. This technique is only
- an optimization; we would get the same results if
- we just used decls_match here. */
- if (DECL_ASSEMBLER_NAME (fn)
- != DECL_ASSEMBLER_NAME (method))
- continue;
}
- else if (!decls_match (fn, method))
+
+ /* Since this is an ordinary function in a
+ non-template class, it's mangled name can be used
+ as a unique identifier. This technique is only
+ an optimization; we would get the same results if
+ we just used decls_match here. */
+ if (DECL_ASSEMBLER_NAME (fn)
+ != DECL_ASSEMBLER_NAME (method))
continue;
+ }
+ else if (!decls_match (fn, method))
+ continue;
- /* There has already been a declaration of this method
- or member template. */
- cp_error_at ("`%D' has already been declared in `%T'",
- method, type);
+ /* There has already been a declaration of this method
+ or member template. */
+ cp_error_at ("`%D' has already been declared in `%T'",
+ method, type);
- /* We don't call duplicate_decls here to merge the
- declarations because that will confuse things if the
- methods have inline definitions. In particular, we
- will crash while processing the definitions. */
- return;
- }
+ /* We don't call duplicate_decls here to merge the
+ declarations because that will confuse things if the
+ methods have inline definitions. In particular, we
+ will crash while processing the definitions. */
+ return;
}
+ }
- /* Actually insert the new method. */
- TREE_VEC_ELT (method_vec, slot)
- = build_overload (method, TREE_VEC_ELT (method_vec, slot));
+ /* Actually insert the new method. */
+ TREE_VEC_ELT (method_vec, slot)
+ = build_overload (method, TREE_VEC_ELT (method_vec, slot));
/* Add the new binding. */
- if (!DECL_CONSTRUCTOR_P (method)
- && !DECL_DESTRUCTOR_P (method))
- push_class_level_binding (DECL_NAME (method),
- TREE_VEC_ELT (method_vec, slot));
- }
+ if (!DECL_CONSTRUCTOR_P (method)
+ && !DECL_DESTRUCTOR_P (method))
+ push_class_level_binding (DECL_NAME (method),
+ TREE_VEC_ELT (method_vec, slot));
}
/* Subroutines of finish_struct. */
if (flist)
for (; flist; flist = OVL_NEXT (flist))
{
- add_method (t, 0, OVL_CURRENT (flist));
+ add_method (t, OVL_CURRENT (flist), /*error_p=*/0);
alter_access (t, OVL_CURRENT (flist), access);
}
else
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);
+ base_binfo = get_primary_binfo (binfo);
- if (!TREE_VIA_VIRTUAL (base_binfo))
- /* Non-virtual base classes are easy. */
- BINFO_PRIMARY_MARKED_P (base_binfo) = 1;
- else
+ if (TREE_VIA_VIRTUAL (base_binfo))
{
tree shared_binfo;
tree type;
/* 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))
+ if (!BINFO_PRIMARY_MARKED_P (shared_binfo))
{
/* Make sure the CLASSTYPE_VBASECLASSES list contains the
primary copy; it's the one that really exists. */
TREE_VALUE (purpose_member (BINFO_TYPE (base_binfo),
CLASSTYPE_VBASECLASSES (type)))
= base_binfo;
-
- BINFO_VBASE_PRIMARY_P (base_binfo) = 1;
- BINFO_PRIMARY_MARKED_P (base_binfo) = 1;
}
+ else
+ base_binfo = NULL_TREE;
}
+ if (base_binfo)
+ BINFO_PRIMARY_BASE_OF (base_binfo) = binfo;
+
return NULL_TREE;
}
continue;
vbase = binfo_for_vbase (BINFO_TYPE (vbases), type);
- if (BINFO_VBASE_PRIMARY_P (vbase))
+ if (BINFO_PRIMARY_MARKED_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. */
+/* Make the BINFO the primary base of T. */
static void
-set_primary_base (t, i, vfuns_p)
+set_primary_base (t, binfo, vfuns_p)
tree t;
- int i;
+ tree binfo;
int *vfuns_p;
{
tree basetype;
- CLASSTYPE_VFIELD_PARENT (t) = i;
- basetype = BINFO_TYPE (CLASSTYPE_PRIMARY_BINFO (t));
+ CLASSTYPE_PRIMARY_BINFO (t) = binfo;
+ basetype = BINFO_TYPE (binfo);
TYPE_BINFO_VTABLE (t) = TYPE_BINFO_VTABLE (basetype);
TYPE_BINFO_VIRTUALS (t) = TYPE_BINFO_VIRTUALS (basetype);
TYPE_VFIELD (t) = TYPE_VFIELD (basetype);
*vfuns_p = CLASSTYPE_VSIZE (basetype);
}
-/* Returns true iff BINFO (a direct virtual base of T) is an indirect
- primary base. */
-
-static int
-indirect_primary_base_p (t, binfo)
- tree t;
- tree binfo;
-{
- int i;
-
- for (i = 0; i < CLASSTYPE_N_BASECLASSES (t); ++i)
- {
- tree type;
- tree b;
-
- /* Figure out to which type the Ith base corresponds. */
- type = TYPE_BINFO_BASETYPE (t, i);
- /* See if any of the primary bases have the same type as BINFO. */
- for (b = TYPE_BINFO (type); b; b = TREE_CHAIN (b))
- /* If this base is primary, and has the same type as BINFO,
- then BINFO is an indirect primary base. */
- if (BINFO_PRIMARY_MARKED_P (b)
- && same_type_p (BINFO_TYPE (b), BINFO_TYPE (binfo)))
- return 1;
- }
-
- return 0;
-}
-
/* Determine the primary class for T. */
static void
int *vfuns_p;
{
int i, n_baseclasses = CLASSTYPE_N_BASECLASSES (t);
+ tree vbases;
+ tree type_binfo;
/* If there are no baseclasses, there is certainly no primary base. */
if (n_baseclasses == 0)
return;
- *vfuns_p = 0;
+ type_binfo = TYPE_BINFO (t);
for (i = 0; i < n_baseclasses; i++)
{
- tree base_binfo = TREE_VEC_ELT (TYPE_BINFO_BASETYPES (t), i);
+ tree base_binfo = BINFO_BASETYPE (type_binfo, i);
tree basetype = BINFO_TYPE (base_binfo);
if (TYPE_CONTAINS_VPTR_P (basetype))
if (!CLASSTYPE_HAS_PRIMARY_BASE_P (t))
{
- set_primary_base (t, i, vfuns_p);
+ set_primary_base (t, base_binfo, vfuns_p);
CLASSTYPE_VFIELDS (t) = copy_list (CLASSTYPE_VFIELDS (basetype));
}
else
CLASSTYPE_VFIELDS (t));
if (!flag_new_abi && *vfuns_p == 0)
- set_primary_base (t, i, vfuns_p);
+ set_primary_base (t, base_binfo, vfuns_p);
}
}
}
if (!TYPE_VFIELD (t))
- CLASSTYPE_VFIELD_PARENT (t) = -1;
+ CLASSTYPE_PRIMARY_BINFO (t) = NULL_TREE;
+
+ /* Mark the indirect primary bases. */
+ for (vbases = CLASSTYPE_VBASECLASSES (t);
+ vbases;
+ vbases = TREE_CHAIN (vbases))
+ {
+ tree binfo = TREE_VALUE (vbases);
+
+ /* See if this virtual base is an indirect primary base. If so,
+ it must be either a primary base or an indirect primary base
+ in one of the direct bases. */
+ for (i = 0; i < n_baseclasses; ++i)
+ {
+ tree basetype;
+ tree v;
+
+ basetype = TYPE_BINFO_BASETYPE (t, i);
+ for (v = CLASSTYPE_VBASECLASSES (basetype);
+ v;
+ v = TREE_CHAIN (v))
+ {
+ tree b = TREE_VALUE (v);
+ if ((BINFO_PRIMARY_MARKED_P (b)
+ || BINFO_INDIRECT_PRIMARY_P (b))
+ && same_type_p (BINFO_TYPE (b), BINFO_TYPE (binfo)))
+ {
+ BINFO_INDIRECT_PRIMARY_P (binfo) = 1;
+ break;
+ }
+ }
+
+ /* If we've discovered that this virtual base is an indirect
+ primary base, then we can move on to the next virtual
+ base. */
+ if (BINFO_INDIRECT_PRIMARY_P (binfo))
+ break;
+ }
+ }
/* The new ABI allows for the use of a "nearly-empty" virtual base
class as the primary base class if no non-virtual polymorphic
base can be found. */
if (flag_new_abi && !CLASSTYPE_HAS_PRIMARY_BASE_P (t))
{
- /* If not -1, this is the index in TYPE_BINFO_BASETYPEs of the
- best primary base candidate we have found so far. */
- int candidate = -1;
+ /* If not NULL, this is the best primary base candidate we have
+ found so far. */
+ tree candidate = NULL_TREE;
+ tree base_binfo;
/* Loop over the baseclasses. */
- for (i = 0; i < n_baseclasses; ++i)
+ for (base_binfo = TYPE_BINFO (t);
+ base_binfo;
+ base_binfo = TREE_CHAIN (base_binfo))
{
- tree base_binfo = TREE_VEC_ELT (TYPE_BINFO_BASETYPES (t), i);
tree basetype = BINFO_TYPE (base_binfo);
if (TREE_VIA_VIRTUAL (base_binfo)
&& CLASSTYPE_NEARLY_EMPTY_P (basetype))
{
- int indirect_primary_p;
-
- /* Figure out whether or not this base is an indirect
- primary base. */
- indirect_primary_p = indirect_primary_base_p (t, base_binfo);
-
/* If this is not an indirect primary base, then it's
definitely our primary base. */
- if (!indirect_primary_p)
+ if (!BINFO_INDIRECT_PRIMARY_P (base_binfo))
{
- candidate = i;
+ candidate = base_binfo;
break;
}
/* If this was an indirect primary base, it's still our
primary base -- unless there's another nearly-empty
virtual base that isn't an indirect primary base. */
- else if (candidate == -1)
- candidate = i;
+ else if (!candidate)
+ candidate = base_binfo;
}
}
/* If we've got a primary base, use it. */
- if (candidate != -1)
+ if (candidate)
{
set_primary_base (t, candidate, vfuns_p);
CLASSTYPE_VFIELDS (t)
- = copy_list (CLASSTYPE_VFIELDS (TYPE_BINFO_BASETYPE (t,
- candidate)));
+ = copy_list (CLASSTYPE_VFIELDS (BINFO_TYPE (candidate)));
}
}
tree template_info = CLASSTYPE_TEMPLATE_INFO (t);
int use_template = CLASSTYPE_USE_TEMPLATE (t);
- bzero ((char *) TYPE_LANG_SPECIFIC (t), sizeof (struct lang_type));
+ memset ((char *) TYPE_LANG_SPECIFIC (t), 0, sizeof (struct lang_type));
BINFO_BASETYPES(binfo) = NULL_TREE;
TYPE_BINFO (t) = binfo;
tree path;
tree method;
+ /* We haven't found an overrider yet. */
+ method = NULL_TREE;
/* We've found a path to the declaring base. Walk down the path
looking for an overrider for FN. */
- for (path = reverse_path (binfo);
+ for (path = reverse_path (binfo);
path;
path = TREE_CHAIN (path))
{
the base from which it came. */
if (path)
{
+ tree base;
+
+ /* Assume the path is non-virtual. See if there are any
+ virtual bases from (but not including) the overrider up
+ to and including the base where the function is
+ defined. */
+ for (base = TREE_CHAIN (path); base; base = TREE_CHAIN (base))
+ if (TREE_VIA_VIRTUAL (TREE_VALUE (base)))
+ {
+ base = ffod->declaring_base;
+ while (BINFO_PRIMARY_MARKED_P (base))
+ {
+ BINFO_OVERRIDE_ALONG_VIRTUAL_PATH_P (base) = 1;
+ base = BINFO_INHERITANCE_CHAIN (base);
+ }
+ BINFO_OVERRIDE_ALONG_VIRTUAL_PATH_P (base) = 1;
+ break;
+ }
+
if (ffod->overriding_fn && ffod->overriding_fn != method)
{
/* We've found a different overrider along a different
return build_tree_list (ffod.overriding_fn, ffod.overriding_base);
}
-/* Called via dfs_walk. Returns BINFO if BINFO has the same type as
- DATA (which is really an _TYPE node). */
-
-static tree
-dfs_find_base (binfo, data)
- tree binfo;
- void *data;
-{
- return (same_type_p (BINFO_TYPE (binfo), (tree) data)
- ? binfo : NULL_TREE);
-}
-
/* Update a entry in the vtable for BINFO, which is in the hierarchy
dominated by T. FN has been overridden in BINFO; VIRTUALS points
to the corresponding position in the BINFO_VIRTUALS list. */
{
tree b;
tree overrider;
- tree vindex;
tree delta;
- HOST_WIDE_INT vindex_val;
- HOST_WIDE_INT i;
+ tree virtual_base;
+ int generate_thunk_with_vtable_p;
/* Find the function which originally caused this vtable
entry to be present. */
- vindex = DECL_VINDEX (fn);
- b = dfs_walk (binfo, dfs_find_base, NULL, DECL_VIRTUAL_CONTEXT (fn));
- 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)
+ b = binfo;
+ while (1)
{
- fn = TREE_CHAIN (fn);
- ++i;
+ tree primary_base;
+ tree f;
+
+ primary_base = get_primary_binfo (b);
+ if (!primary_base)
+ break;
+
+ for (f = BINFO_VIRTUALS (TYPE_BINFO (BINFO_TYPE (primary_base)));
+ f;
+ f = TREE_CHAIN (f))
+ if (same_signature_p (BV_FN (f), fn))
+ break;
+
+ if (!f)
+ break;
+
+ fn = BV_FN (f);
+ b = primary_base;
}
- fn = BV_FN (fn);
- /* Handle the case of a virtual function defined in BINFO itself. */
+ /* Find the final overrider. */
overrider = find_final_overrider (t, b, fn);
if (overrider == error_mark_node)
return;
get_derived_offset (binfo,
DECL_VIRTUAL_CONTEXT (fn)),
BINFO_OFFSET (binfo));
+
+ /* Assume that we will produce a thunk that convert all the way to
+ the final overrider, and not to an intermediate virtual base. */
+ virtual_base = NULL_TREE;
+
+ /* Assume that we will always generate thunks with the vtables that
+ reference them. */
+ generate_thunk_with_vtable_p = 1;
+
+ /* Under the new ABI, we will convert to an intermediate virtual
+ base first, and then use the vcall offset located there to finish
+ the conversion. */
if (flag_new_abi)
{
- /* Under the new ABI, we only need to adjust as far as the
- nearest virtual base. Then we use the vcall offset in the
- virtual bases vtable. */
- for (b = binfo; b; b = BINFO_INHERITANCE_CHAIN (b))
+ while (b)
{
- if (TREE_VIA_VIRTUAL (b))
- break;
+ /* If we find BINFO, then the final overrider is in a class
+ derived from BINFO, so the thunks can be generated with
+ the final overrider. */
+ if (!virtual_base
+ && same_type_p (BINFO_TYPE (b), BINFO_TYPE (binfo)))
+ generate_thunk_with_vtable_p = 0;
+
+ /* If we find the final overrider, then we can stop
+ walking. */
if (same_type_p (BINFO_TYPE (b),
BINFO_TYPE (TREE_VALUE (overrider))))
break;
+
+ /* If we find a virtual base, and we haven't yet found the
+ overrider, then there is a virtual base between the
+ declaring base and the final overrider. */
+ if (!virtual_base && TREE_VIA_VIRTUAL (b))
+ {
+ generate_thunk_with_vtable_p = 1;
+ virtual_base = b;
+ }
+
+ b = BINFO_INHERITANCE_CHAIN (b);
}
}
else
- b = NULL_TREE;
+ virtual_base = NULL_TREE;
- if (b && TREE_VIA_VIRTUAL (b))
+ if (virtual_base)
/* The `this' pointer needs to be adjusted to the nearest virtual
base. */
- delta = size_diffop (BINFO_OFFSET (b), delta);
+ delta = size_diffop (BINFO_OFFSET (virtual_base), delta);
else
/* The `this' pointer needs to be adjusted from pointing to
BINFO to pointing at the base where the final overrider
TREE_PURPOSE (overrider),
delta,
virtuals);
+
+ if (virtual_base)
+ BV_USE_VCALL_INDEX_P (*virtuals) = 1;
+ if (generate_thunk_with_vtable_p)
+ BV_GENERATE_THUNK_WITH_VTABLE_P (*virtuals) = 1;
}
/* Called from modify_all_vtables via dfs_walk. */
check_for_override (decl, ctype)
tree decl, ctype;
{
- tree binfos = BINFO_BASETYPES (TYPE_BINFO (ctype));
- int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
- int virtualp = DECL_VIRTUAL_P (decl);
- int found_overriden_fn = 0;
+ if (TREE_CODE (decl) == TEMPLATE_DECL)
+ /* In [temp.mem] we have:
- for (i = 0; i < n_baselinks; i++)
+ A specialization of a member function template does not
+ override a virtual function from a base class. */
+ return;
+ if ((DECL_DESTRUCTOR_P (decl)
+ || IDENTIFIER_VIRTUAL_P (DECL_NAME (decl)))
+ && look_for_overrides (ctype, decl)
+ && !DECL_STATIC_FUNCTION_P (decl))
{
- tree base_binfo = TREE_VEC_ELT (binfos, i);
- if (TYPE_POLYMORPHIC_P (BINFO_TYPE (base_binfo)))
- {
- tree tmp = get_matching_virtual
- (base_binfo, decl, DECL_DESTRUCTOR_P (decl));
-
- if (tmp && !found_overriden_fn)
- {
- /* If this function overrides some virtual in some base
- class, then the function itself is also necessarily
- virtual, even if the user didn't explicitly say so. */
- DECL_VIRTUAL_P (decl) = 1;
-
- /* The TMP we really want is the one from the deepest
- baseclass on this path, taking care not to
- duplicate if we have already found it (via another
- path to its virtual baseclass. */
- if (TREE_CODE (TREE_TYPE (decl)) == FUNCTION_TYPE)
- {
- cp_error_at ("`static %#D' cannot be declared", decl);
- cp_error_at (" since `virtual %#D' declared in base class",
- tmp);
- break;
- }
- virtualp = 1;
-
- /* Set DECL_VINDEX to a value that is neither an
- INTEGER_CST nor the error_mark_node so that
- add_virtual_function will realize this is an
- overridden function. */
- DECL_VINDEX (decl)
- = tree_cons (tmp, NULL_TREE, DECL_VINDEX (decl));
-
- /* We now know that DECL overrides something,
- which is all that is important. But, we must
- continue to iterate through all the base-classes
- in order to allow get_matching_virtual to check for
- various illegal overrides. */
- found_overriden_fn = 1;
- }
- }
+ /* Set DECL_VINDEX to a value that is neither an
+ INTEGER_CST nor the error_mark_node so that
+ add_virtual_function will realize this is an
+ overriding function. */
+ DECL_VINDEX (decl) = decl;
}
- if (virtualp)
+ if (DECL_VIRTUAL_P (decl))
{
if (DECL_VINDEX (decl) == NULL_TREE)
DECL_VINDEX (decl) = error_mark_node;
/* Now, hook all of the new functions on to TYPE_METHODS,
and add them to the CLASSTYPE_METHOD_VEC. */
for (f = &implicit_fns; *f; f = &TREE_CHAIN (*f))
- add_method (t, 0, *f);
+ add_method (t, *f, /*error_p=*/0);
*f = TYPE_METHODS (t);
TYPE_METHODS (t) = implicit_fns;
TYPE_HAS_COMPLEX_ASSIGN_REF (t) = 1;
if (! TYPE_HAS_CONSTRUCTOR (t) && extra_warnings)
- {
- if (DECL_NAME (x))
- cp_warning_at ("non-static reference `%#D' in class without a constructor", x);
- else
- cp_warning_at ("non-static reference in class without a constructor", x);
- }
+ cp_warning_at ("non-static reference `%#D' in class without a constructor", x);
}
type = strip_array_types (type);
TYPE_HAS_COMPLEX_ASSIGN_REF (t) = 1;
if (! TYPE_HAS_CONSTRUCTOR (t) && extra_warnings)
- {
- if (DECL_NAME (x))
- cp_warning_at ("non-static const member `%#D' in class without a constructor", x);
- else
- cp_warning_at ("non-static const member in class without a constructor", x);
- }
+ cp_warning_at ("non-static const member `%#D' in class without a constructor", x);
}
/* A field that is pseudo-const makes the structure likewise. */
else if (IS_AGGR_TYPE (type))
return field;
}
-/* Record the type of BINFO in the slot in DATA (which is really a
- `varray_type *') corresponding to the BINFO_OFFSET. */
+/* If TYPE is an empty class type, records its OFFSET in the table of
+ OFFSETS. */
-static tree
-dfs_record_base_offsets (binfo, data)
- tree binfo;
- void *data;
+static int
+record_subobject_offset (type, offset, offsets)
+ tree type;
+ tree offset;
+ splay_tree offsets;
{
- varray_type *v;
- unsigned HOST_WIDE_INT offset = tree_low_cst (BINFO_OFFSET (binfo), 1);
+ splay_tree_node n;
+
+ if (!is_empty_class (type))
+ return 0;
- v = (varray_type *) data;
- while (VARRAY_SIZE (*v) <= offset)
- VARRAY_GROW (*v, 2 * VARRAY_SIZE (*v));
- VARRAY_TREE (*v, offset) = tree_cons (NULL_TREE,
- BINFO_TYPE (binfo),
- VARRAY_TREE (*v, offset));
+ /* Record the location of this empty object in OFFSETS. */
+ n = splay_tree_lookup (offsets, (splay_tree_key) offset);
+ if (!n)
+ n = splay_tree_insert (offsets,
+ (splay_tree_key) offset,
+ (splay_tree_value) NULL_TREE);
+ n->value = ((splay_tree_value)
+ tree_cons (NULL_TREE,
+ type,
+ (tree) n->value));
- return NULL_TREE;
+ return 0;
}
-/* Add the offset of BINFO and its bases to BASE_OFFSETS. */
+/* Returns non-zero if TYPE is an empty class type and there is
+ already an entry in OFFSETS for the same TYPE as the same OFFSET. */
-static void
-record_base_offsets (binfo, base_offsets)
- tree binfo;
- varray_type *base_offsets;
+static int
+check_subobject_offset (type, offset, offsets)
+ tree type;
+ tree offset;
+ splay_tree offsets;
{
- dfs_walk (binfo,
- dfs_record_base_offsets,
- dfs_skip_vbases,
- base_offsets);
+ splay_tree_node n;
+ tree t;
+
+ if (!is_empty_class (type))
+ return 0;
+
+ /* Record the location of this empty object in OFFSETS. */
+ n = splay_tree_lookup (offsets, (splay_tree_key) offset);
+ if (!n)
+ return 0;
+
+ for (t = (tree) n->value; t; t = TREE_CHAIN (t))
+ if (same_type_p (TREE_VALUE (t), type))
+ return 1;
+
+ return 0;
}
-/* Returns non-NULL if there is already an entry in DATA (which is
- really a `varray_type') indicating that an object with the same
- type of BINFO is already at the BINFO_OFFSET for BINFO. */
+/* Walk through all the subobjects of TYPE (located at OFFSET). Call
+ F for every subobject, passing it the type, offset, and table of
+ OFFSETS. If VBASES_P is non-zero, then even non-virtual primary
+ bases should be traversed; otherwise, they are ignored. If F
+ returns a non-zero value, the traversal ceases, and that value is
+ returned. Otherwise, returns zero. */
-static tree
-dfs_search_base_offsets (binfo, data)
- tree binfo;
- void *data;
+static int
+walk_subobject_offsets (type, f, offset, offsets, vbases_p)
+ tree type;
+ subobject_offset_fn f;
+ tree offset;
+ splay_tree offsets;
+ int vbases_p;
{
- if (is_empty_class (BINFO_TYPE (binfo)))
+ int r = 0;
+
+ if (CLASS_TYPE_P (type))
{
- varray_type v = (varray_type) data;
- /* Find the offset for this BINFO. */
- unsigned HOST_WIDE_INT offset = tree_low_cst (BINFO_OFFSET (binfo), 1);
- tree t;
+ tree field;
+ int i;
- /* If we haven't yet encountered any objects at offsets that
- big, then there's no conflict. */
- if (VARRAY_SIZE (v) <= offset)
- return NULL_TREE;
- /* Otherwise, go through the objects already allocated at this
- offset. */
- for (t = VARRAY_TREE (v, offset); t; t = TREE_CHAIN (t))
- if (same_type_p (TREE_VALUE (t), BINFO_TYPE (binfo)))
- return binfo;
+ /* Record the location of TYPE. */
+ r = (*f) (type, offset, offsets);
+ if (r)
+ return r;
+
+ /* Iterate through the direct base classes of TYPE. */
+ for (i = 0; i < CLASSTYPE_N_BASECLASSES (type); ++i)
+ {
+ tree binfo = BINFO_BASETYPE (TYPE_BINFO (type), i);
+
+ if (!vbases_p
+ && TREE_VIA_VIRTUAL (binfo)
+ && !BINFO_PRIMARY_MARKED_P (binfo))
+ continue;
+
+ r = walk_subobject_offsets (BINFO_TYPE (binfo),
+ f,
+ size_binop (PLUS_EXPR,
+ offset,
+ BINFO_OFFSET (binfo)),
+ offsets,
+ vbases_p);
+ if (r)
+ return r;
+ }
+
+ /* Iterate through the fields of TYPE. */
+ for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
+ if (TREE_CODE (field) == FIELD_DECL)
+ {
+ r = walk_subobject_offsets (TREE_TYPE (field),
+ f,
+ size_binop (PLUS_EXPR,
+ offset,
+ DECL_FIELD_OFFSET (field)),
+ offsets,
+ /*vbases_p=*/1);
+ if (r)
+ return r;
+ }
}
+ else if (TREE_CODE (type) == ARRAY_TYPE)
+ {
+ tree domain = TYPE_DOMAIN (type);
+ tree index;
- return NULL_TREE;
+ /* Step through each of the elements in the array. */
+ for (index = size_zero_node;
+ INT_CST_LT (index, TYPE_MAX_VALUE (domain));
+ index = size_binop (PLUS_EXPR, index, size_one_node))
+ {
+ r = walk_subobject_offsets (TREE_TYPE (type),
+ f,
+ offset,
+ offsets,
+ /*vbases_p=*/1);
+ if (r)
+ return r;
+ offset = size_binop (PLUS_EXPR, offset,
+ TYPE_SIZE_UNIT (TREE_TYPE (type)));
+ }
+ }
+
+ return 0;
+}
+
+/* Record all of the empty subobjects of TYPE (located at OFFSET) in
+ OFFSETS. If VBASES_P is non-zero, virtual bases of TYPE are
+ examined. */
+
+static void
+record_subobject_offsets (type, offset, offsets, vbases_p)
+ tree type;
+ tree offset;
+ splay_tree offsets;
+ int vbases_p;
+{
+ walk_subobject_offsets (type, record_subobject_offset, offset,
+ offsets, vbases_p);
}
-/* Returns non-zero if there's a conflict between BINFO and a base
- already mentioned in BASE_OFFSETS if BINFO is placed at its current
- BINFO_OFFSET. */
+/* Returns non-zero if any of the empty subobjects of TYPE (located at
+ OFFSET) conflict with entries in OFFSETS. If VBASES_P is non-zero,
+ virtual bases of TYPE are examined. */
static int
-layout_conflict_p (binfo, base_offsets)
- tree binfo;
- varray_type base_offsets;
+layout_conflict_p (type, offset, offsets, vbases_p)
+ tree type;
+ tree offset;
+ splay_tree offsets;
+ int vbases_p;
{
- return dfs_walk (binfo, dfs_search_base_offsets, dfs_skip_vbases,
- base_offsets) != NULL_TREE;
+ return walk_subobject_offsets (type, check_subobject_offset, offset,
+ offsets, vbases_p);
}
/* DECL is a FIELD_DECL corresponding either to a base subobject of a
non-static data member of the type indicated by RLI. BINFO is the
- binfo corresponding to the base subobject, or, if this is a
- non-static data-member, a dummy BINFO for the type of the data
- member. BINFO may be NULL if checks to see if the field overlaps
- an existing field with the same type are not required. V maps
- offsets to types already located at those offsets. This function
- determines the position of the DECL. */
+ binfo corresponding to the base subobject, OFFSETS maps offsets to
+ types already located at those offsets. This function determines
+ the position of the DECL. */
static void
-layout_nonempty_base_or_field (rli, decl, binfo, v)
+layout_nonempty_base_or_field (rli, decl, binfo, offsets)
record_layout_info rli;
tree decl;
tree binfo;
- varray_type v;
+ splay_tree offsets;
{
+ tree offset = NULL_TREE;
+ tree type = TREE_TYPE (decl);
+ /* If we are laying out a base class, rather than a field, then
+ DECL_ARTIFICIAL will be set on the FIELD_DECL. */
+ int field_p = !DECL_ARTIFICIAL (decl);
+
/* Try to place the field. It may take more than one try if we have
a hard time placing the field without putting two objects of the
same type at the same address. */
while (1)
{
- tree offset;
struct record_layout_info_s old_rli = *rli;
/* Place this field. */
place_field (rli, decl);
-
- /* Now that we know where it wil be placed, update its
- BINFO_OFFSET. */
offset = byte_position (decl);
- if (binfo)
- 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.
empty class, have non-zero size, any overlap can happen only
with a direct or indirect base-class -- it can't happen with
a data member. */
- if (binfo && flag_new_abi && layout_conflict_p (binfo, v))
+ if (flag_new_abi && layout_conflict_p (TREE_TYPE (decl),
+ offset,
+ offsets,
+ field_p))
{
- /* Undo the propagate_binfo_offsets call. */
- offset = size_diffop (size_zero_node, 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
proper alignment. */
*rli = old_rli;
- /* Bump up by the alignment required for the type, without
- virtual base classes. */
+ /* Bump up by the alignment required for the type. */
rli->bitpos
- = size_binop (PLUS_EXPR, rli->bitpos,
- bitsize_int (CLASSTYPE_ALIGN (BINFO_TYPE (binfo))));
+ = size_binop (PLUS_EXPR, rli->bitpos,
+ bitsize_int (binfo
+ ? CLASSTYPE_ALIGN (type)
+ : TYPE_ALIGN (type)));
normalize_rli (rli);
}
else
/* There was no conflict. We're done laying out this field. */
break;
}
+
+ /* Now that we know where it wil be placed, update its
+ BINFO_OFFSET. */
+ if (binfo && CLASS_TYPE_P (BINFO_TYPE (binfo)))
+ propagate_binfo_offsets (binfo,
+ convert (ssizetype, offset));
}
/* Layout the empty base BINFO. EOC indicates the byte currently just
past the end of the class, and should be correctly aligned for a
- class of the type indicated by BINFO; BINFO_OFFSETS gives the
- offsets of the other bases allocated so far. */
+ class of the type indicated by BINFO; OFFSETS gives the offsets of
+ the empty bases allocated so far. */
static void
-layout_empty_base (binfo, eoc, binfo_offsets)
+layout_empty_base (binfo, eoc, offsets)
tree binfo;
tree eoc;
- varray_type binfo_offsets;
+ splay_tree offsets;
{
tree alignment;
tree basetype = BINFO_TYPE (binfo);
/* This is an empty base class. We first try to put it at offset
zero. */
- if (layout_conflict_p (binfo, binfo_offsets))
+ if (layout_conflict_p (BINFO_TYPE (binfo),
+ BINFO_OFFSET (binfo),
+ offsets,
+ /*vbases_p=*/0))
{
/* That didn't work. Now, we move forward from the next
available spot in the class. */
propagate_binfo_offsets (binfo, convert (ssizetype, eoc));
while (1)
{
- if (!layout_conflict_p (binfo, binfo_offsets))
+ if (!layout_conflict_p (BINFO_TYPE (binfo),
+ BINFO_OFFSET (binfo),
+ offsets,
+ /*vbases_p=*/0))
/* We finally found a spot where there's no overlap. */
break;
/* Build a FIELD_DECL for the base given by BINFO in the class
indicated by RLI. If the new object is non-empty, clear *EMPTY_P.
*BASE_ALIGN is a running maximum of the alignments of any base
- class. */
+ class. OFFSETS gives the location of empty base subobjects. */
static void
-build_base_field (rli, binfo, empty_p, base_align, v)
+build_base_field (rli, binfo, empty_p, base_align, offsets)
record_layout_info rli;
tree binfo;
int *empty_p;
unsigned int *base_align;
- varray_type *v;
+ splay_tree offsets;
{
tree basetype = BINFO_TYPE (binfo);
tree decl;
/* Try to place the field. It may take more than one try if we
have a hard time placing the field without putting two
objects of the same type at the same address. */
- layout_nonempty_base_or_field (rli, decl, binfo, *v);
+ layout_nonempty_base_or_field (rli, decl, binfo, offsets);
}
else
{
/* On some platforms (ARM), even empty classes will not be
byte-aligned. */
eoc = tree_low_cst (rli_size_unit_so_far (rli), 0);
- eoc = CEIL (eoc, DECL_ALIGN (decl)) * DECL_ALIGN (decl);
- layout_empty_base (binfo, size_int (eoc), *v);
+ eoc = CEIL (eoc, DECL_ALIGN_UNIT (decl)) * DECL_ALIGN_UNIT (decl);
+ layout_empty_base (binfo, size_int (eoc), offsets);
}
/* Check for inaccessible base classes. If the same base class
basetype, rli->t);
/* Record the offsets of BINFO and its base subobjects. */
- record_base_offsets (binfo, v);
+ record_subobject_offsets (BINFO_TYPE (binfo),
+ BINFO_OFFSET (binfo),
+ offsets,
+ /*vbases_p=*/0);
}
-/* Layout all of the non-virtual base classes. Returns a map from
- offsets to types present at those offsets. */
+/* Layout all of the non-virtual base classes. Record empty
+ subobjects in OFFSETS. */
-static varray_type
-build_base_fields (rli, empty_p)
+static void
+build_base_fields (rli, empty_p, offsets)
record_layout_info rli;
int *empty_p;
+ splay_tree offsets;
{
/* Chain to hold all the new FIELD_DECLs which stand in for base class
subobjects. */
tree rec = rli->t;
int n_baseclasses = CLASSTYPE_N_BASECLASSES (rec);
int i;
- varray_type v;
unsigned int base_align = 0;
- /* Create the table mapping offsets to empty base classes. */
- VARRAY_TREE_INIT (v, 32, "v");
-
/* Under the new ABI, the primary base class is always allocated
first. */
if (flag_new_abi && CLASSTYPE_HAS_PRIMARY_BASE_P (rec))
build_base_field (rli, CLASSTYPE_PRIMARY_BINFO (rec),
- empty_p, &base_align, &v);
+ empty_p, &base_align, offsets);
/* Now allocate the rest of the bases. */
for (i = 0; i < n_baseclasses; ++i)
{
tree base_binfo;
+ base_binfo = BINFO_BASETYPE (TYPE_BINFO (rec), i);
+
/* Under the new ABI, the primary base was already allocated
above, so we don't need to allocate it again here. */
- if (flag_new_abi && i == CLASSTYPE_VFIELD_PARENT (rec))
+ if (flag_new_abi && base_binfo == CLASSTYPE_PRIMARY_BINFO (rec))
continue;
- base_binfo = BINFO_BASETYPE (TYPE_BINFO (rec), i);
-
/* A primary virtual base class is allocated just like any other
base class, but a non-primary virtual base is allocated
later, in layout_virtual_bases. */
&& !BINFO_PRIMARY_MARKED_P (base_binfo))
continue;
- build_base_field (rli, base_binfo, empty_p, &base_align, &v);
+ build_base_field (rli, base_binfo, empty_p, &base_align, offsets);
}
-
- return v;
}
/* Go through the TYPE_METHODS of T issuing any appropriate
{
tree clone;
+ /* Avoid inappropriate cloning. */
+ if (! flag_new_abi
+ || (TREE_CHAIN (fn)
+ && DECL_CLONED_FUNCTION (TREE_CHAIN (fn))))
+ return;
+
if (DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (fn))
{
/* For each constructor, we need two variants: an in-charge version
and a not-in-charge version. */
clone = build_clone (fn, complete_ctor_identifier);
if (update_method_vec_p)
- add_method (DECL_CONTEXT (clone), NULL, clone);
+ add_method (DECL_CONTEXT (clone), clone, /*error_p=*/0);
clone = build_clone (fn, base_ctor_identifier);
if (update_method_vec_p)
- add_method (DECL_CONTEXT (clone), NULL, clone);
+ add_method (DECL_CONTEXT (clone), clone, /*error_p=*/0);
}
else
{
function table. */
clone = build_clone (fn, deleting_dtor_identifier);
if (update_method_vec_p)
- add_method (DECL_CONTEXT (clone), NULL, clone);
+ add_method (DECL_CONTEXT (clone), clone, /*error_p=*/0);
clone = build_clone (fn, complete_dtor_identifier);
if (update_method_vec_p)
- add_method (DECL_CONTEXT (clone), NULL, clone);
+ add_method (DECL_CONTEXT (clone), clone, /*error_p=*/0);
clone = build_clone (fn, base_dtor_identifier);
if (update_method_vec_p)
- add_method (DECL_CONTEXT (clone), NULL, clone);
+ add_method (DECL_CONTEXT (clone), clone, /*error_p=*/0);
}
}
complete. */
static void
-fixup_pending_inline (info)
- struct pending_inline *info;
+fixup_pending_inline (fn)
+ tree fn;
{
- if (info)
+ if (DECL_PENDING_INLINE_INFO (fn))
{
- tree args;
- tree fn = info->fndecl;
-
- args = DECL_ARGUMENTS (fn);
+ tree args = DECL_ARGUMENTS (fn);
while (args)
{
DECL_CONTEXT (args) = fn;
/* Do inline member functions. */
for (; method; method = TREE_CHAIN (method))
- fixup_pending_inline (DECL_PENDING_INLINE_INFO (method));
+ fixup_pending_inline (method);
/* Do friends. */
for (method = CLASSTYPE_INLINE_FRIENDS (type);
method;
method = TREE_CHAIN (method))
- fixup_pending_inline (DECL_PENDING_INLINE_INFO (TREE_VALUE (method)));
+ fixup_pending_inline (TREE_VALUE (method));
CLASSTYPE_INLINE_FRIENDS (type) = NULL_TREE;
}
-/* Called from propagate_binfo_offsets via dfs_walk. */
-
-static tree
-dfs_propagate_binfo_offsets (binfo, data)
- tree binfo;
- void *data;
-{
- tree offset = (tree) data;
-
- /* Update the BINFO_OFFSET for this base. Allow for the case where it
- might be negative. */
- BINFO_OFFSET (binfo)
- = convert (sizetype, size_binop (PLUS_EXPR,
- convert (ssizetype, BINFO_OFFSET (binfo)),
- offset));
- SET_BINFO_MARKED (binfo);
-
- return NULL_TREE;
-}
-
/* Add OFFSET to all base types of BINFO which is a base in the
hierarchy dominated by T.
- OFFSET, which is a type offset, is number of bytes.
-
- Note that we don't have to worry about having two paths to the
- same base type, since this type owns its association list. */
+ OFFSET, which is a type offset, is number of bytes. */
static void
propagate_binfo_offsets (binfo, offset)
tree binfo;
tree offset;
{
- dfs_walk (binfo,
- dfs_propagate_binfo_offsets,
- dfs_skip_nonprimary_vbases_unmarkedp,
- offset);
- dfs_walk (binfo,
- dfs_unmark,
- dfs_skip_nonprimary_vbases_markedp,
- NULL);
-}
+ int i;
+ tree primary_binfo;
-/* Called via dfs_walk from layout_virtual bases. */
+ /* Update BINFO's offset. */
+ BINFO_OFFSET (binfo)
+ = convert (sizetype,
+ size_binop (PLUS_EXPR,
+ convert (ssizetype, BINFO_OFFSET (binfo)),
+ offset));
-static tree
-dfs_set_offset_for_shared_vbases (binfo, data)
- tree binfo;
- void *data;
-{
- if (TREE_VIA_VIRTUAL (binfo) && BINFO_PRIMARY_MARKED_P (binfo))
+ /* Find the primary base class. */
+ primary_binfo = get_primary_binfo (binfo);
+
+ /* Scan all of the bases, pushing the BINFO_OFFSET adjust
+ downwards. */
+ for (i = -1; i < BINFO_N_BASETYPES (binfo); ++i)
{
- /* Update the shared copy. */
- tree shared_binfo;
+ tree base_binfo;
- shared_binfo = binfo_for_vbase (BINFO_TYPE (binfo), (tree) data);
- BINFO_OFFSET (shared_binfo) = BINFO_OFFSET (binfo);
- }
+ /* On the first through the loop, do the primary base. Because
+ the primary base need not be an immediate base, we must
+ handle the primary base specially. */
+ if (i == -1)
+ {
+ if (!primary_binfo)
+ continue;
- return NULL_TREE;
+ base_binfo = primary_binfo;
+ }
+ else
+ {
+ base_binfo = BINFO_BASETYPE (binfo, i);
+ /* Don't do the primary base twice. */
+ if (base_binfo == primary_binfo)
+ continue;
+ }
+
+ /* Skip virtual bases that aren't our primary base. */
+ if (TREE_VIA_VIRTUAL (base_binfo)
+ && BINFO_PRIMARY_BASE_OF (base_binfo) != binfo)
+ continue;
+
+ propagate_binfo_offsets (base_binfo, offset);
+ }
}
/* Called via dfs_walk from layout_virtual bases. */
}
/* Set BINFO_OFFSET for all of the virtual bases for T. Update
- TYPE_ALIGN and TYPE_SIZE for T. BASE_OFFSETS is a varray mapping
- offsets to the types at those offsets. */
+ TYPE_ALIGN and TYPE_SIZE for T. OFFSETS gives the location of
+ empty subobjects of T. */
static void
-layout_virtual_bases (t, base_offsets)
+layout_virtual_bases (t, offsets)
tree t;
- varray_type *base_offsets;
+ splay_tree offsets;
{
tree vbases;
unsigned HOST_WIDE_INT dsize;
else
vbase = TREE_VALUE (vbases);
- if (!BINFO_VBASE_PRIMARY_P (vbase))
+ if (!BINFO_PRIMARY_MARKED_P (vbase))
{
/* This virtual base is not a primary base of any class in the
hierarchy, so we have to add space for it. */
if (flag_new_abi && is_empty_class (basetype))
layout_empty_base (vbase,
size_int (CEIL (dsize, BITS_PER_UNIT)),
- *base_offsets);
+ offsets);
else
{
tree offset;
}
/* Keep track of the offsets assigned to this virtual base. */
- record_base_offsets (vbase, base_offsets);
+ record_subobject_offsets (BINFO_TYPE (vbase),
+ BINFO_OFFSET (vbase),
+ offsets,
+ /*vbases_p=*/0);
}
}
- /* Make sure that all of the CLASSTYPE_VBASECLASSES have their
- BINFO_OFFSET set correctly. Those we just allocated certainly
- will. The others are primary baseclasses; we walk the hierarchy
- to find the primary copies and update the shared copy. */
- dfs_walk (TYPE_BINFO (t),
- dfs_set_offset_for_shared_vbases,
- dfs_unmarked_real_bases_queue_p,
- t);
-
- /* Now, go through the TYPE_BINFO hierarchy again, setting the
+ /* Now, go through the TYPE_BINFO hierarchy, setting the
BINFO_OFFSETs correctly for all non-primary copies of the virtual
bases and their direct and indirect bases. The ambiguity checks
in get_base_distance depend on the BINFO_OFFSETs being set
return result;
}
+/* Compare two INTEGER_CSTs K1 and K2. */
+
+static int
+splay_tree_compare_integer_csts (k1, k2)
+ splay_tree_key k1;
+ splay_tree_key k2;
+{
+ return tree_int_cst_compare ((tree) k1, (tree) k2);
+}
+
/* Calculate the TYPE_SIZE, TYPE_ALIGN, etc for T. Calculate
BINFO_OFFSETs for all of the base-classes. Position the vtable
pointer. */
tree field;
tree vptr;
record_layout_info rli;
- varray_type v;
unsigned HOST_WIDE_INT eoc;
+ /* Maps offsets (represented as INTEGER_CSTs) to a TREE_LIST of
+ types that appear at that offset. */
+ splay_tree empty_base_offsets;
/* Keep track of the first non-static data member. */
non_static_data_members = TYPE_FIELDS (t);
place_field (rli, vptr);
}
+ /* Build FIELD_DECLs for all of the non-virtual base-types. */
+ empty_base_offsets = splay_tree_new (splay_tree_compare_integer_csts,
+ NULL, NULL);
+ build_base_fields (rli, empty_p, empty_base_offsets);
/* Add pointers to all of our virtual base-classes. */
TYPE_FIELDS (t) = chainon (build_vbase_pointer_fields (rli, empty_p),
TYPE_FIELDS (t));
- /* Build FIELD_DECLs for all of the non-virtual base-types. */
- v = build_base_fields (rli, empty_p);
/* CLASSTYPE_INLINE_FRIENDS is really TYPE_NONCOPIED_PARTS. Thus,
we have to save this before we start modifying
/* Layout the non-static data members. */
for (field = non_static_data_members; field; field = TREE_CHAIN (field))
{
- tree binfo;
tree type;
tree padding;
else
padding = NULL_TREE;
- /* Create a dummy BINFO corresponding to this field. */
- binfo = make_binfo (size_zero_node, type, NULL_TREE, NULL_TREE);
- unshare_base_binfos (binfo);
- layout_nonempty_base_or_field (rli, field, binfo, v);
+ layout_nonempty_base_or_field (rli, field, NULL_TREE,
+ empty_base_offsets);
/* If we needed additional padding after this field, add it
now. */
DECL_SIZE (padding_field) = padding;
DECL_ALIGN (padding_field) = 1;
DECL_USER_ALIGN (padding_field) = 0;
- layout_nonempty_base_or_field (rli, padding_field, NULL_TREE, v);
+ layout_nonempty_base_or_field (rli, padding_field,
+ NULL_TREE,
+ empty_base_offsets);
}
}
CLASSTYPE_SIZE (t) = bitsize_zero_node;
CLASSTYPE_SIZE_UNIT (t) = size_zero_node;
}
- else if (flag_new_abi && TYPE_HAS_COMPLEX_INIT_REF (t)
- && TYPE_HAS_COMPLEX_ASSIGN_REF (t))
+ else if (flag_new_abi)
{
CLASSTYPE_SIZE (t) = TYPE_BINFO_SIZE (t);
CLASSTYPE_SIZE_UNIT (t) = TYPE_BINFO_SIZE_UNIT (t);
around. We must get these done before we try to lay out the
virtual function table. As a side-effect, this will remove the
base subobject fields. */
- layout_virtual_bases (t, &v);
+ layout_virtual_bases (t, empty_base_offsets);
/* Clean up. */
- VARRAY_FREE (v);
+ splay_tree_delete (empty_base_offsets);
}
/* Create a RECORD_TYPE or UNION_TYPE node for a C struct or union declaration
make sure we lay it out again. */
TYPE_SIZE (t) = NULL_TREE;
CLASSTYPE_GOT_SEMICOLON (t) = 0;
- CLASSTYPE_VFIELD_PARENT (t) = -1;
+ CLASSTYPE_PRIMARY_BINFO (t) = NULL_TREE;
vfuns = 0;
CLASSTYPE_RTTI (t) = NULL_TREE;
{
tree binfo = CLASSTYPE_PRIMARY_BINFO (t);
- /* This class contributes nothing new to the virtual function
- table. However, it may have declared functions which
- went into the virtual function table "inherited" from the
- base class. If so, we grab a copy of those updated functions,
- and pretend they are ours. */
-
- /* See if we should steal the virtual info from base class. */
- if (TYPE_BINFO_VTABLE (t) == NULL_TREE)
- TYPE_BINFO_VTABLE (t) = BINFO_VTABLE (binfo);
- if (TYPE_BINFO_VIRTUALS (t) == NULL_TREE)
- TYPE_BINFO_VIRTUALS (t) = BINFO_VIRTUALS (binfo);
+ /* If this class uses a different vtable than its primary base
+ then when we will need to initialize our vptr after the base
+ class constructor runs. */
if (TYPE_BINFO_VTABLE (t) != BINFO_VTABLE (binfo))
CLASSTYPE_NEEDS_VIRTUAL_REINIT (t) = 1;
}
maybe_suppress_debug_info (t);
/* Finish debugging output for this type. */
- rest_of_type_compilation (t, toplevel_bindings_p ());
+ rest_of_type_compilation (t, ! LOCAL_CLASS_P (t));
}
/* When T was built up, the member declarations were added in reverse
{
tree scope = current_scope ();
if (scope && TREE_CODE (scope) == FUNCTION_DECL)
- add_tree (build_min (TAG_DEFN, t));
+ add_stmt (build_min (TAG_DEFN, t));
}
return t;
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);
+
+ ridpointers[(int) RID_PUBLIC] = access_public_node;
+ ridpointers[(int) RID_PRIVATE] = access_private_node;
+ ridpointers[(int) RID_PROTECTED] = access_protected_node;
}
/* Set current scope to NAME. CODE tells us if this is a
pushlevel_class ();
-#if 0
- if (CLASSTYPE_TEMPLATE_INFO (type))
- overload_template_name (type);
-#endif
-
if (modify)
{
if (type != previous_class_type || current_class_depth > 1)
|| TREE_CODE (type) == NAMESPACE_DECL
|| ! IS_AGGR_TYPE (type)
|| TREE_CODE (type) == TEMPLATE_TYPE_PARM
- || TREE_CODE (type) == TEMPLATE_TEMPLATE_PARM)
+ || TREE_CODE (type) == BOUND_TEMPLATE_TEMPLATE_PARM)
return;
context = DECL_CONTEXT (TYPE_MAIN_DECL (type));
if (name == lang_name_cplusplus)
{
- strict_prototype = strict_prototypes_lang_cplusplus;
current_lang_name = name;
}
else if (name == lang_name_java)
{
- strict_prototype = strict_prototypes_lang_cplusplus;
current_lang_name = name;
/* DECL_IGNORED_P is initially set for these types, to avoid clutter.
(See record_builtin_java_type in decl.c.) However, that causes
incorrect debug entries if these types are actually used.
So we re-enable debug output after extern "Java". */
- DECL_IGNORED_P (java_byte_type_node) = 0;
- DECL_IGNORED_P (java_short_type_node) = 0;
- DECL_IGNORED_P (java_int_type_node) = 0;
- DECL_IGNORED_P (java_long_type_node) = 0;
- DECL_IGNORED_P (java_float_type_node) = 0;
- DECL_IGNORED_P (java_double_type_node) = 0;
- DECL_IGNORED_P (java_char_type_node) = 0;
- DECL_IGNORED_P (java_boolean_type_node) = 0;
+ DECL_IGNORED_P (TYPE_NAME (java_byte_type_node)) = 0;
+ DECL_IGNORED_P (TYPE_NAME (java_short_type_node)) = 0;
+ DECL_IGNORED_P (TYPE_NAME (java_int_type_node)) = 0;
+ DECL_IGNORED_P (TYPE_NAME (java_long_type_node)) = 0;
+ DECL_IGNORED_P (TYPE_NAME (java_float_type_node)) = 0;
+ DECL_IGNORED_P (TYPE_NAME (java_double_type_node)) = 0;
+ DECL_IGNORED_P (TYPE_NAME (java_char_type_node)) = 0;
+ DECL_IGNORED_P (TYPE_NAME (java_boolean_type_node)) = 0;
}
else if (name == lang_name_c)
{
- strict_prototype = strict_prototypes_lang_c;
current_lang_name = name;
}
else
to it. */
*current_lang_stack = NULL_TREE;
current_lang_name = *--current_lang_stack;
- if (current_lang_name == lang_name_cplusplus
- || current_lang_name == lang_name_java)
- strict_prototype = strict_prototypes_lang_cplusplus;
- else if (current_lang_name == lang_name_c)
- strict_prototype = strict_prototypes_lang_c;
}
\f
/* Type instantiation routines. */
/* Given an OVERLOAD and a TARGET_TYPE, return the function that
matches the TARGET_TYPE. If there is no satisfactory match, return
error_mark_node, and issue an error message if COMPLAIN is
- non-zero. If TEMPLATE_ONLY, the name of the overloaded function
+ non-zero. Permit pointers to member function if PTRMEM is non-zero.
+ If TEMPLATE_ONLY, the name of the overloaded function
was a template-id, and EXPLICIT_TARGS are the explicitly provided
template arguments. */
static tree
resolve_address_of_overloaded_function (target_type,
overload,
- complain,
+ complain,
+ ptrmem,
template_only,
explicit_targs)
tree target_type;
tree overload;
int complain;
+ int ptrmem;
int template_only;
tree explicit_targs;
{
target_fn_type = TREE_TYPE (target_type);
target_arg_types = TYPE_ARG_TYPES (target_fn_type);
target_ret_type = TREE_TYPE (target_fn_type);
+
+ /* Never do unification on the 'this' parameter. */
+ if (TREE_CODE (target_fn_type) == METHOD_TYPE)
+ target_arg_types = TREE_CHAIN (target_arg_types);
for (fns = overload; fns; fns = OVL_CHAIN (fns))
{
targs = make_tree_vec (DECL_NTPARMS (fn));
if (fn_type_unification (fn, explicit_targs, targs,
target_arg_types, target_ret_type,
- DEDUCE_EXACT) != 0)
+ DEDUCE_EXACT, -1) != 0)
/* Argument deduction failed. */
continue;
/* Now, remove all but the most specialized of the matches. */
if (matches)
{
- tree match = most_specialized_instantiation (matches,
- explicit_targs);
+ tree match = most_specialized_instantiation (matches);
if (match != error_mark_node)
matches = tree_cons (match, NULL_TREE, NULL_TREE);
/* Good, exactly one match. Now, convert it to the correct type. */
fn = TREE_PURPOSE (matches);
+ if (DECL_NONSTATIC_MEMBER_FUNCTION_P (fn)
+ && !ptrmem && !flag_ms_extensions)
+ {
+ static int explained;
+
+ if (!complain)
+ return error_mark_node;
+
+ cp_pedwarn ("assuming pointer to member `%D'", fn);
+ if (!explained)
+ {
+ cp_pedwarn ("(a pointer to member can only be formed with `&%E')", fn);
+ explained = 1;
+ }
+ }
mark_used (fn);
if (TYPE_PTRFN_P (target_type) || TYPE_PTRMEMFUNC_P (target_type))
/* This function will instantiate the type of the expression given in
RHS to match the type of LHSTYPE. If errors exist, then return
- error_mark_node. We only complain is COMPLAIN is set. If we are
- not complaining, never modify rhs, as overload resolution wants to
- try many possible instantiations, in hopes that at least one will
- work.
-
- FLAGS is a bitmask, as we see at the top of the function.
-
+ error_mark_node. FLAGS is a bit mask. If ITF_COMPLAIN is set, then
+ we complain on errors. If we are not complaining, never modify rhs,
+ as overload resolution wants to try many possible instantiations, in
+ the hope that at least one will work.
+
For non-recursive calls, LHSTYPE should be a function, pointer to
function, or a pointer to member function. */
tree
instantiate_type (lhstype, rhs, flags)
tree lhstype, rhs;
- int flags;
+ enum instantiate_type_flags flags;
{
- int complain = (flags & 1);
- int strict = (flags & 2) ? COMPARE_NO_ATTRIBUTES : COMPARE_STRICT;
- tree r;
-
+ int complain = (flags & itf_complain);
+ int strict = (flags & itf_no_attributes)
+ ? COMPARE_NO_ATTRIBUTES : COMPARE_STRICT;
+ int allow_ptrmem = flags & itf_ptrmem_ok;
+
+ flags &= ~itf_ptrmem_ok;
+
if (TREE_CODE (lhstype) == UNKNOWN_TYPE)
{
if (complain)
return instantiate_type (lhstype, rhs, flags);
case COMPONENT_REF:
- {
- r = instantiate_type (lhstype, TREE_OPERAND (rhs, 1), flags);
-
- comp:
- if (r != error_mark_node && TYPE_PTRMEMFUNC_P (lhstype)
- && complain && !flag_ms_extensions)
- {
- /* Note: we check this after the recursive call to avoid
- complaining about cases where overload resolution fails. */
-
- tree t = TREE_TYPE (TREE_OPERAND (rhs, 0));
- tree fn = PTRMEM_CST_MEMBER (r);
-
- my_friendly_assert (TREE_CODE (r) == PTRMEM_CST, 990811);
-
- cp_pedwarn
- ("object-dependent reference to `%E' can only be used in a call",
- DECL_NAME (fn));
- cp_pedwarn
- (" to form a pointer to member function, say `&%T::%E'",
- t, DECL_NAME (fn));
- }
-
- return r;
- }
+ return instantiate_type (lhstype, TREE_OPERAND (rhs, 1), flags);
case OFFSET_REF:
rhs = TREE_OPERAND (rhs, 1);
if (BASELINK_P (rhs))
- return instantiate_type (lhstype, TREE_VALUE (rhs), flags);
+ return instantiate_type (lhstype, TREE_VALUE (rhs),
+ flags | allow_ptrmem);
/* This can happen if we are forming a pointer-to-member for a
member template. */
tree fns = TREE_OPERAND (rhs, 0);
tree args = TREE_OPERAND (rhs, 1);
- r =
+ return
resolve_address_of_overloaded_function (lhstype,
fns,
complain,
+ allow_ptrmem,
/*template_only=*/1,
args);
- if (TREE_CODE (fns) == COMPONENT_REF)
- {
- rhs = fns;
- goto comp;
- }
- return r;
}
case OVERLOAD:
resolve_address_of_overloaded_function (lhstype,
rhs,
complain,
+ allow_ptrmem,
/*template_only=*/0,
/*explicit_targs=*/NULL_TREE);
return rhs;
case ADDR_EXPR:
+ {
+ if (PTRMEM_OK_P (rhs))
+ flags |= itf_ptrmem_ok;
+
return instantiate_type (lhstype, TREE_OPERAND (rhs, 0), flags);
-
+ }
case ENTRY_VALUE_EXPR:
my_friendly_abort (184);
return error_mark_node;
in its context and when re-evaluated in the completed scope of
S. */
cp_error ("declaration of `%#D'", decl);
- cp_error_at ("changes meaning of `%s' from `%+#D'",
- IDENTIFIER_POINTER (DECL_NAME (OVL_CURRENT (decl))),
+ cp_error_at ("changes meaning of `%D' from `%+#D'",
+ DECL_NAME (OVL_CURRENT (decl)),
(tree) n->value);
}
}
return decl;
}
+/* Called from get_primary_binfo via dfs_walk. */
+
+static tree
+dfs_get_primary_binfo (binfo, data)
+ tree binfo;
+ void *data;
+{
+ tree primary_base = (tree) data;
+
+ if (TREE_VIA_VIRTUAL (binfo)
+ && same_type_p (TREE_TYPE (binfo), TREE_TYPE (primary_base)))
+ return binfo;
+
+ return NULL_TREE;
+}
+
+/* Returns 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. */
+
+tree
+get_primary_binfo (binfo)
+ tree binfo;
+{
+ tree primary_base;
+ tree result;
+
+ primary_base = CLASSTYPE_PRIMARY_BINFO (BINFO_TYPE (binfo));
+ if (!primary_base)
+ return NULL_TREE;
+
+ /* A non-virtual primary base is always a direct base, and easy to
+ find. */
+ if (!TREE_VIA_VIRTUAL (primary_base))
+ {
+ int i;
+
+ /* Scan the direct basetypes until we find a base with the same
+ type as the primary base. */
+ for (i = 0; i < BINFO_N_BASETYPES (binfo); ++i)
+ {
+ tree base_binfo = BINFO_BASETYPE (binfo, i);
+
+ if (same_type_p (BINFO_TYPE (base_binfo),
+ BINFO_TYPE (primary_base)))
+ return base_binfo;
+ }
+
+ /* We should always find the primary base. */
+ my_friendly_abort (20000729);
+ }
+
+ /* For a primary virtual base, we have to scan the entire hierarchy
+ rooted at BINFO; the virtual base could be an indirect virtual
+ base. */
+ result = dfs_walk (binfo, dfs_get_primary_binfo, NULL, primary_base);
+ my_friendly_assert (result != NULL_TREE, 20000730);
+ return result;
+}
+
/* 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. */
fprintf (stderr, "%*s0x%lx (%s) ", indent, "",
(unsigned long) binfo,
- type_as_string (binfo, TS_PLAIN));
+ type_as_string (binfo, TFF_PLAIN_IDENTIFIER));
fprintf (stderr, HOST_WIDE_INT_PRINT_DEC,
tree_low_cst (BINFO_OFFSET (binfo), 0));
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))))
+ && BINFO_PRIMARY_MARKED_P (binfo_for_vbase (BINFO_TYPE (binfo),
+ t))))
fprintf (stderr, " primary");
fprintf (stderr, "\n");
/* Build up the initializers for the VTT. */
inits = NULL_TREE;
index = size_zero_node;
- build_vtt_inits (TYPE_BINFO (t), t, &inits, &index);
+ build_vtt_inits (TYPE_BINFO (t), t, /*virtual_vtts_p=*/1,
+ &inits, &index);
/* If we didn't need a VTT, we're done. */
if (!inits)
initialize_array (vtt, inits);
}
+/* The type corresponding to BINFO is a base class of T, but BINFO is
+ in the base class hierarchy of a class derived from T. Return the
+ base, in T's hierarchy, that corresponds to BINFO. */
+
+static tree
+get_matching_base (binfo, t)
+ tree binfo;
+ tree t;
+{
+ tree derived;
+ int i;
+
+ if (same_type_p (BINFO_TYPE (binfo), t))
+ return binfo;
+
+ if (TREE_VIA_VIRTUAL (binfo))
+ return binfo_for_vbase (BINFO_TYPE (binfo), t);
+
+ derived = get_matching_base (BINFO_INHERITANCE_CHAIN (binfo), t);
+ for (i = 0; i < BINFO_N_BASETYPES (derived); ++i)
+ if (same_type_p (BINFO_TYPE (BINFO_BASETYPE (derived, i)),
+ BINFO_TYPE (binfo)))
+ return BINFO_BASETYPE (derived, i);
+
+ my_friendly_abort (20000628);
+ return NULL_TREE;
+}
+
/* Recursively build the VTT-initializer for BINFO (which is in the
- hierarchy dominated by T). INITS points to the end of the
- initializer list to date. INDEX is the VTT index where the next
- element will be placed. */
+ hierarchy dominated by T). If VIRTUAL_VTTS_P is non-zero, then
+ sub-VTTs for virtual bases are included. INITS points to the end
+ of the initializer list to date. INDEX is the VTT index where the
+ next element will be placed. */
static tree *
-build_vtt_inits (binfo, t, inits, index)
+build_vtt_inits (binfo, t, virtual_vtts_p, inits, index)
tree binfo;
tree t;
+ int virtual_vtts_p;
tree *inits;
tree *index;
{
/* Add the address of the primary vtable for the complete object. */
init = BINFO_VTABLE (binfo);
if (TREE_CODE (init) == TREE_LIST)
- init = TREE_PURPOSE (init);
+ init = TREE_VALUE (init);
*inits = build_tree_list (NULL_TREE, init);
inits = &TREE_CHAIN (*inits);
BINFO_VPTR_INDEX (binfo) = *index;
{
b = BINFO_BASETYPE (binfo, i);
if (!TREE_VIA_VIRTUAL (b))
- inits = build_vtt_inits (BINFO_BASETYPE (binfo, i), t, inits,
- index);
+ inits = build_vtt_inits (BINFO_BASETYPE (binfo, i), t,
+ /*virtuals_vtts_p=*/0,
+ inits, index);
}
/* Add secondary virtual pointers for all subobjects of BINFO with
either virtual bases or virtual functions overridden along a
virtual path between the declaration and D, except subobjects
that are non-virtual primary bases. */
- secondary_vptrs = build_tree_list (BINFO_TYPE (binfo), NULL_TREE);
+ secondary_vptrs = tree_cons (t, NULL_TREE, BINFO_TYPE (binfo));
TREE_TYPE (secondary_vptrs) = *index;
dfs_walk_real (binfo,
- dfs_build_vtt_inits,
+ dfs_build_secondary_vptr_vtt_inits,
NULL,
dfs_unmarked_real_bases_queue_p,
secondary_vptrs);
- dfs_walk (binfo, dfs_fixup_binfo_vtbls, dfs_marked_real_bases_queue_p,
- BINFO_TYPE (binfo));
+ dfs_walk (binfo, dfs_unmark, dfs_marked_real_bases_queue_p, t);
*index = TREE_TYPE (secondary_vptrs);
/* The secondary vptrs come back in reverse order. After we reverse
}
/* Add the secondary VTTs for virtual bases. */
- for (b = TYPE_BINFO (BINFO_TYPE (binfo)); b; b = TREE_CHAIN (b))
- {
- tree vbase;
-
- if (!TREE_VIA_VIRTUAL (b))
- continue;
+ if (virtual_vtts_p)
+ for (b = TYPE_BINFO (BINFO_TYPE (binfo)); b; b = TREE_CHAIN (b))
+ {
+ tree vbase;
+
+ if (!TREE_VIA_VIRTUAL (b))
+ continue;
+
+ vbase = binfo_for_vbase (BINFO_TYPE (b), t);
+ inits = build_vtt_inits (vbase, t, /*virtual_vtts_p=*/0,
+ inits, index);
+ }
- vbase = binfo_for_vbase (BINFO_TYPE (b), t);
- inits = build_vtt_inits (vbase, t, inits, index);
- }
+ dfs_walk (binfo, dfs_fixup_binfo_vtbls,
+ dfs_unmarked_real_bases_queue_p,
+ build_tree_list (t, binfo));
return inits;
}
/* Called from build_vtt_inits via dfs_walk. */
static tree
-dfs_build_vtt_inits (binfo, data)
+dfs_build_secondary_vptr_vtt_inits (binfo, data)
tree binfo;
void *data;
{
tree index;
l = (tree) data;
- t = TREE_PURPOSE (l);
+ t = TREE_CHAIN (l);
SET_BINFO_MARKED (binfo);
/* If BINFO doesn't have virtual bases, then we have to look to see
whether or not any virtual functions were overidden along a
- virtual path between the declaration and T. */
- if (!TYPE_USES_VIRTUAL_BASECLASSES (BINFO_TYPE (binfo)))
- /* FIXME: Implement this. */
- ;
+ virtual path. The point is that given:
+
+ struct V { virtual void f(); int i; };
+ struct C : public virtual V { void f (); };
+
+ when we constrct C we need a secondary vptr for V-in-C because we
+ don't know what the vcall offset for `f' should be. If `V' ends
+ up in a different place in the complete object, then we'll need a
+ different vcall offset than that present in the normal V-in-C
+ vtable. */
+ if (!TYPE_USES_VIRTUAL_BASECLASSES (BINFO_TYPE (binfo))
+ && !BINFO_OVERRIDE_ALONG_VIRTUAL_PATH_P (get_matching_base (binfo, t)))
+ return NULL_TREE;
/* Record the index where this secondary vptr can be found. */
index = TREE_TYPE (l);
/* Add the initializer for the secondary vptr itself. */
init = BINFO_VTABLE (binfo);
if (TREE_CODE (init) == TREE_LIST)
- init = TREE_PURPOSE (init);
+ init = TREE_VALUE (init);
TREE_VALUE (l) = tree_cons (NULL_TREE, init, TREE_VALUE (l));
return NULL_TREE;
static tree
dfs_fixup_binfo_vtbls (binfo, data)
tree binfo;
- void *data ATTRIBUTE_UNUSED;
+ void *data;
{
CLEAR_BINFO_MARKED (binfo);
/* If we scribbled the construction vtable vptr into BINFO, clear it
out now. */
- if (TREE_CODE (BINFO_VTABLE (binfo)) == TREE_LIST)
- BINFO_VTABLE (binfo) = TREE_VALUE (BINFO_VTABLE (binfo));
+ if (TREE_CODE (BINFO_VTABLE (binfo)) == TREE_LIST
+ && (TREE_PURPOSE (BINFO_VTABLE (binfo))
+ == TREE_VALUE ((tree) data)))
+ BINFO_VTABLE (binfo) = TREE_CHAIN (BINFO_VTABLE (binfo));
return NULL_TREE;
}
tree vtbl;
tree inits;
tree id;
+ tree vbase;
/* See if we've already create this construction vtable group. */
if (flag_new_abi)
list = build_tree_list (vtbl, NULL_TREE);
accumulate_vtbl_inits (binfo, TYPE_BINFO (TREE_TYPE (binfo)),
binfo, t, list);
+ for (vbase = TYPE_BINFO (TREE_TYPE (binfo));
+ vbase;
+ vbase = TREE_CHAIN (vbase))
+ {
+ tree b;
+
+ if (!TREE_VIA_VIRTUAL (vbase))
+ continue;
+
+ b = binfo_for_vbase (BINFO_TYPE (vbase), t);
+ accumulate_vtbl_inits (b, vbase, binfo, t, list);
+ }
+
inits = TREE_VALUE (list);
/* Figure out the type of the construction vtable. */
/* If we're building a construction vtable, we're not interested in
subobjects that don't require construction vtables. */
if (ctor_vtbl_p
- && !TYPE_USES_VIRTUAL_BASECLASSES (BINFO_TYPE (binfo)))
+ && !TYPE_USES_VIRTUAL_BASECLASSES (BINFO_TYPE (binfo))
+ && !(BINFO_OVERRIDE_ALONG_VIRTUAL_PATH_P
+ (get_matching_base (binfo, BINFO_TYPE (rtti_binfo)))))
return;
/* Build the initializers for the BINFO-in-T vtable. */
tree l;
{
tree inits = NULL_TREE;
- int ctor_vtbl_p;
-
- /* This is a construction vtable if the RTTI type is not the most
- derived type in the hierarchy. */
- ctor_vtbl_p = !same_type_p (BINFO_TYPE (rtti_binfo), t);
- if (BINFO_NEW_VTABLE_MARKED (binfo, t)
- /* We need a new vtable, even for a primary base, when we're
- building a construction vtable. */
- || (ctor_vtbl_p && CLASSTYPE_VFIELDS (BINFO_TYPE (binfo))))
+ if (BINFO_NEW_VTABLE_MARKED (orig_binfo, t))
{
tree vtbl;
tree index;
TREE_CONSTANT (vtbl) = 1;
/* For an ordinary vtable, set BINFO_VTABLE. */
- if (!ctor_vtbl_p)
+ if (same_type_p (BINFO_TYPE (rtti_binfo), t))
BINFO_VTABLE (binfo) = vtbl;
/* For a construction vtable, we can't overwrite BINFO_VTABLE.
So, we make a TREE_LIST. Later, dfs_fixup_binfo_vtbls will
straighten this out. */
else
- BINFO_VTABLE (binfo) = build_tree_list (vtbl,
- BINFO_VTABLE (binfo));
+ BINFO_VTABLE (binfo) =
+ tree_cons (rtti_binfo, vtbl, BINFO_VTABLE (binfo));
}
return inits;
is part of the hierarchy dominated by T. If we're building a
construction vtable, the ORIG_BINFO is the binfo we should use to
find the actual function pointers to put in the vtable. Otherwise,
- ORIG_BINFO should be the same as BINFO. The RTTI_DOMINATOR is the
+ ORIG_BINFO should be the same as BINFO. The RTTI_BINFO is the
BINFO that should be indicated by the RTTI information in the
vtable; it will be a base class of T, rather than T itself, if we
are building a construction vtable.
The value returned is a TREE_LIST suitable for wrapping in a
CONSTRUCTOR to use as the 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. */
+ number of non-function entries in the vtable.
+
+ It might seem that this function should never be called with a
+ BINFO for which BINFO_PRIMARY_MARKED_P holds, the vtable for such a
+ base is always subsumed by a derived class vtable. However, when
+ we are building construction vtables we do build vtables for
+ primary bases; we need these while the primary base is being
+ constructed. */
static tree
build_vtbl_initializer (binfo, orig_binfo, t, rtti_binfo, non_fn_entries_p)
int *non_fn_entries_p;
{
tree v;
- tree vfun_inits;
+ tree vfun_inits;
tree vbase;
- vcall_offset_data vod;
-
- /* Initialize those parts of VOD that matter. */
- vod.derived = t;
- vod.inits = NULL_TREE;
- vod.last_init = &vod.inits;
- vod.primary_p = (binfo == TYPE_BINFO (t));
+ vtbl_init_data vid;
+
+ /* Initialize VID. */
+ memset (&vid, 0, sizeof (vid));
+ vid.binfo = binfo;
+ vid.derived = t;
+ vid.last_init = &vid.inits;
+ vid.primary_vtbl_p = (binfo == TYPE_BINFO (t));
+ vid.ctor_vtbl_p = !same_type_p (BINFO_TYPE (rtti_binfo), t);
/* The first vbase or vcall offset is at index -3 in the vtable. */
- vod.index = build_int_2 (-3, -1);
+ vid.index = ssize_int (-3);
/* Add entries to the vtable for RTTI. */
- build_rtti_vtbl_entries (binfo, rtti_binfo, &vod);
+ build_rtti_vtbl_entries (binfo, rtti_binfo, &vid);
+ /* Create an array for keeping track of the functions we've
+ processed. When we see multiple functions with the same
+ signature, we share the vcall offsets. */
+ VARRAY_TREE_INIT (vid.fns, 32, "fns");
/* Add the vcall and vbase offset entries. */
- build_vcall_and_vbase_vtbl_entries (binfo, &vod);
- /* Clear BINFO_VTABLE_PAATH_MARKED; it's set by
+ build_vcall_and_vbase_vtbl_entries (binfo, &vid);
+ /* Clean up. */
+ VARRAY_FREE (vid.fns);
+ /* Clear BINFO_VTABLE_PATH_MARKED; it's set by
build_vbase_offset_vtbl_entries. */
for (vbase = CLASSTYPE_VBASECLASSES (t);
vbase;
CLEAR_BINFO_VTABLE_PATH_MARKED (TREE_VALUE (vbase));
if (non_fn_entries_p)
- *non_fn_entries_p = list_length (vod.inits);
+ *non_fn_entries_p = list_length (vid.inits);
/* Go through all the ordinary virtual functions, building up
initializers. */
/* Pull the offset for `this', and the function to call, out of
the list. */
delta = BV_DELTA (v);
- vcall_index = BV_VCALL_INDEX (v);
+
+ if (BV_USE_VCALL_INDEX_P (v))
+ {
+ vcall_index = BV_VCALL_INDEX (v);
+ my_friendly_assert (vcall_index != NULL_TREE, 20000621);
+ }
+ else
+ vcall_index = NULL_TREE;
+
fn = BV_FN (v);
my_friendly_assert (TREE_CODE (delta) == INTEGER_CST, 19990727);
my_friendly_assert (TREE_CODE (fn) == FUNCTION_DECL, 19990727);
/* The address of a function can't change. */
TREE_CONSTANT (pfn) = 1;
/* Enter it in the vtable. */
- init = build_vtable_entry (delta, vcall_index, pfn);
+ init = build_vtable_entry (delta, vcall_index, pfn,
+ BV_GENERATE_THUNK_WITH_VTABLE_P (v));
/* And add it to the chain of initializers. */
vfun_inits = tree_cons (NULL_TREE, init, vfun_inits);
}
vfun_inits = nreverse (vfun_inits);
/* The negative offset initializers are also in reverse order. */
- vod.inits = nreverse (vod.inits);
+ vid.inits = nreverse (vid.inits);
/* Chain the two together. */
- return chainon (vod.inits, vfun_inits);
+ return chainon (vid.inits, vfun_inits);
}
-/* Sets vod->inits to be the initializers for the vbase and vcall
+/* Sets vid->inits to be the initializers for the vbase and vcall
offsets in BINFO, which is in the hierarchy dominated by T. */
static void
-build_vcall_and_vbase_vtbl_entries (binfo, vod)
+build_vcall_and_vbase_vtbl_entries (binfo, vid)
tree binfo;
- vcall_offset_data *vod;
+ vtbl_init_data *vid;
{
tree b;
/* If this is a derived class, we must first create entries
corresponding to the primary base class. */
- b = BINFO_PRIMARY_BINFO (binfo);
+ b = get_primary_binfo (binfo);
if (b)
- build_vcall_and_vbase_vtbl_entries (b, vod);
+ build_vcall_and_vbase_vtbl_entries (b, vid);
/* Add the vbase entries for this base. */
- build_vbase_offset_vtbl_entries (binfo, vod);
+ build_vbase_offset_vtbl_entries (binfo, vid);
/* Add the vcall entries for this base. */
- build_vcall_offset_vtbl_entries (binfo, vod);
+ build_vcall_offset_vtbl_entries (binfo, vid);
}
/* Returns the initializers for the vbase offset entries in the vtable
where the next vbase offset will go. */
static void
-build_vbase_offset_vtbl_entries (binfo, vod)
+build_vbase_offset_vtbl_entries (binfo, vid)
tree binfo;
- vcall_offset_data *vod;
+ vtbl_init_data *vid;
{
tree vbase;
tree t;
if (!TYPE_USES_VIRTUAL_BASECLASSES (BINFO_TYPE (binfo)))
return;
- t = vod->derived;
+ t = vid->derived;
/* Go through the virtual bases, adding the offsets. */
for (vbase = TYPE_BINFO (BINFO_TYPE (binfo));
/* Figure out where we can find this vbase offset. */
delta = size_binop (MULT_EXPR,
- convert (ssizetype, vod->index),
+ vid->index,
convert (ssizetype,
TYPE_SIZE_UNIT (vtable_entry_type)));
- if (vod->primary_p)
+ if (vid->primary_vtbl_p)
BINFO_VPTR_FIELD (b) = delta;
if (binfo != TYPE_BINFO (t))
}
/* The next vbase will come at a more negative offset. */
- vod->index = fold (build (MINUS_EXPR, integer_type_node,
- vod->index, integer_one_node));
+ vid->index = size_binop (MINUS_EXPR, vid->index, ssize_int (1));
/* 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->last_init
+ *vid->last_init
= build_tree_list (NULL_TREE,
fold (build1 (NOP_EXPR,
vtable_entry_type,
delta)));
- vod->last_init = &TREE_CHAIN (*vod->last_init);
+ vid->last_init = &TREE_CHAIN (*vid->last_init);
+ }
+}
+
+/* Adds the initializers for the vcall offset entries in the vtable
+ for BINFO (which is part of the class hierarchy dominated by T) to
+ VID->INITS. */
+
+static void
+build_vcall_offset_vtbl_entries (binfo, vid)
+ tree binfo;
+ vtbl_init_data *vid;
+{
+ /* Under the old ABI, the adjustments to the `this' pointer were made
+ elsewhere. */
+ if (!vcall_offsets_in_vtable_p ())
+ return;
+
+ /* We only need these entries if this base is a virtual base. */
+ if (!TREE_VIA_VIRTUAL (binfo))
+ return;
+
+ /* We need a vcall offset for each of the virtual functions in this
+ vtable. For example:
+
+ class A { virtual void f (); };
+ class B : virtual public A { };
+ class C: virtual public A, public B {};
+
+ Now imagine:
+
+ B* b = new C;
+ b->f();
+
+ The location of `A' is not at a fixed offset relative to `B'; the
+ offset depends on the complete object derived from `B'. So,
+ `B' vtable contains an entry for `f' that indicates by what
+ amount the `this' pointer for `B' needs to be adjusted to arrive
+ at `A'.
+
+ We need entries for all the functions in our primary vtable and
+ in our non-virtual bases vtables. */
+ vid->vbase = binfo;
+ /* Now, walk through the non-virtual bases, adding vcall offsets. */
+ add_vcall_offset_vtbl_entries_r (binfo, vid);
+}
+
+/* Build vcall offsets, starting with those for BINFO. */
+
+static void
+add_vcall_offset_vtbl_entries_r (binfo, vid)
+ tree binfo;
+ vtbl_init_data *vid;
+{
+ int i;
+ tree primary_binfo;
+
+ /* Don't walk into virtual bases -- except, of course, for the
+ virtual base for which we are building vcall offsets. */
+ if (TREE_VIA_VIRTUAL (binfo) && vid->vbase != binfo)
+ return;
+
+ /* If BINFO has a primary base, process it first. */
+ primary_binfo = get_primary_binfo (binfo);
+ if (primary_binfo)
+ add_vcall_offset_vtbl_entries_r (primary_binfo, vid);
+
+ /* Add BINFO itself to the list. */
+ add_vcall_offset_vtbl_entries_1 (binfo, vid);
+
+ /* Scan the non-primary bases of BINFO. */
+ for (i = 0; i < BINFO_N_BASETYPES (binfo); ++i)
+ {
+ tree base_binfo;
+
+ base_binfo = BINFO_BASETYPE (binfo, i);
+ if (base_binfo != primary_binfo)
+ add_vcall_offset_vtbl_entries_r (base_binfo, vid);
}
}
/* Called from build_vcall_offset_vtbl_entries via dfs_walk. */
-static tree
-dfs_build_vcall_offset_vtbl_entries (binfo, data)
+static void
+add_vcall_offset_vtbl_entries_1 (binfo, vid)
tree binfo;
- void *data;
+ vtbl_init_data* vid;
{
- vcall_offset_data* vod;
tree derived_virtuals;
tree base_virtuals;
+ tree orig_virtuals;
tree binfo_inits;
+ /* If BINFO is a primary base, this is the least derived class of
+ BINFO that is not a primary base. */
tree non_primary_binfo;
- tree b;
- int i;
- vod = (vcall_offset_data *) data;
binfo_inits = NULL_TREE;
/* We might be a primary base class. Go up the inheritance
hierarchy until we find the class of which we are a primary base:
it is the BINFO_VIRTUALS there that we need to consider. */
non_primary_binfo = binfo;
- while (BINFO_PRIMARY_MARKED_P (non_primary_binfo))
- non_primary_binfo = BINFO_INHERITANCE_CHAIN (non_primary_binfo);
+ while (BINFO_INHERITANCE_CHAIN (non_primary_binfo))
+ {
+ tree b;
- /* Skip virtuals that we have already handled in a primary base
- class. */
- base_virtuals = BINFO_VIRTUALS (binfo);
- derived_virtuals = BINFO_VIRTUALS (non_primary_binfo);
- b = BINFO_PRIMARY_BINFO (binfo);
- if (b)
- for (i = 0; i < CLASSTYPE_VSIZE (BINFO_TYPE (b)); ++i)
- {
- base_virtuals = TREE_CHAIN (base_virtuals);
- derived_virtuals = TREE_CHAIN (derived_virtuals);
- }
+ /* If we have reached a virtual base, then it must be the
+ virtual base for which we are building vcall offsets. In
+ turn, the virtual base must be a (possibly indirect) primary
+ base of the class that we are initializing, or we wouldn't
+ care about its vtable offsets. */
+ if (TREE_VIA_VIRTUAL (non_primary_binfo))
+ {
+ non_primary_binfo = vid->binfo;
+ break;
+ }
+
+ b = BINFO_INHERITANCE_CHAIN (non_primary_binfo);
+ if (get_primary_binfo (b) != non_primary_binfo)
+ break;
+ non_primary_binfo = b;
+ }
/* Make entries for the rest of the virtuals. */
- for (; base_virtuals;
- derived_virtuals = TREE_CHAIN (derived_virtuals),
- base_virtuals = TREE_CHAIN (base_virtuals))
- {
- /* Figure out what function we're looking at. */
- tree fn = TREE_VALUE (derived_virtuals);
+ for (base_virtuals = BINFO_VIRTUALS (binfo),
+ derived_virtuals = BINFO_VIRTUALS (non_primary_binfo),
+ orig_virtuals = BINFO_VIRTUALS (TYPE_BINFO (BINFO_TYPE (binfo)));
+ base_virtuals;
+ base_virtuals = TREE_CHAIN (base_virtuals),
+ derived_virtuals = TREE_CHAIN (derived_virtuals),
+ orig_virtuals = TREE_CHAIN (orig_virtuals))
+ {
+ tree orig_fn;
+ tree fn;
tree base;
tree base_binfo;
size_t i;
+ /* Find the declaration that originally caused this function to
+ be present. */
+ orig_fn = BV_FN (orig_virtuals);
+
+ /* We do not need an entry if this function is declared in a
+ virtual base (or one of its virtual bases), and not
+ overridden in the section of the hierarchy dominated by the
+ virtual base for which we are building vcall offsets. */
+ if (!same_type_p (DECL_CONTEXT (orig_fn), BINFO_TYPE (binfo)))
+ continue;
+
+ /* Find the overriding function. */
+ fn = BV_FN (derived_virtuals);
+
/* If there is already an entry for a function with the same
signature as FN, then we do not need a second vcall offset.
Check the list of functions already present in the derived
class vtable. */
- for (i = 0; i < VARRAY_ACTIVE_SIZE (vod->fns); ++i)
+ for (i = 0; i < VARRAY_ACTIVE_SIZE (vid->fns); ++i)
{
tree derived_entry;
- derived_entry = VARRAY_TREE (vod->fns, i);
- if (same_signature_p (TREE_VALUE (derived_entry), fn))
+ derived_entry = VARRAY_TREE (vid->fns, i);
+ if (same_signature_p (BV_FN (derived_entry), fn))
{
BV_VCALL_INDEX (derived_virtuals)
= BV_VCALL_INDEX (derived_entry);
break;
}
}
- if (i != VARRAY_ACTIVE_SIZE (vod->fns))
+ if (i != VARRAY_ACTIVE_SIZE (vid->fns))
continue;
/* The FN comes from BASE. So, we must caculate the adjustment
from the virtual base that derived from BINFO to BASE. */
base = DECL_CONTEXT (fn);
- base_binfo = get_binfo (base, vod->derived, /*protect=*/0);
+ base_binfo = get_binfo (base, vid->derived, /*protect=*/0);
/* Compute the vcall offset. */
- *vod->last_init
+ *vid->last_init
= (build_tree_list
(NULL_TREE,
fold (build1 (NOP_EXPR, vtable_entry_type,
size_diffop (BINFO_OFFSET (base_binfo),
- BINFO_OFFSET (vod->vbase))))));
- vod->last_init = &TREE_CHAIN (*vod->last_init);
-
- /* If there is already a vcall index, then we are processing a
- construction vtable. The index should be the same as it was
- when we processed the vtable for the base class. */
- if (BV_VCALL_INDEX (derived_virtuals))
- my_friendly_assert (tree_int_cst_equal (BV_VCALL_INDEX
- (derived_virtuals),
- vod->index),
- 20000516);
+ BINFO_OFFSET (vid->vbase))))));
+ vid->last_init = &TREE_CHAIN (*vid->last_init);
+
/* Keep track of the vtable index where this vcall offset can be
- found. */
- else
- BV_VCALL_INDEX (derived_virtuals) = vod->index;
+ found. For a construction vtable, we already made this
+ annotation when we build the original vtable. */
+ if (!vid->ctor_vtbl_p)
+ BV_VCALL_INDEX (derived_virtuals) = vid->index;
/* The next vcall offset will be found at a more negative
offset. */
- vod->index = fold (build (MINUS_EXPR, integer_type_node,
- vod->index, integer_one_node));
+ vid->index = size_binop (MINUS_EXPR, vid->index, ssize_int (1));
/* Keep track of this function. */
- VARRAY_PUSH_TREE (vod->fns, derived_virtuals);
+ VARRAY_PUSH_TREE (vid->fns, derived_virtuals);
}
-
- return NULL_TREE;
-}
-
-/* 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 void
-build_vcall_offset_vtbl_entries (binfo, vod)
- tree binfo;
- vcall_offset_data *vod;
-{
- /* Under the old ABI, the adjustments to the `this' pointer were made
- elsewhere. */
- if (!vcall_offsets_in_vtable_p ())
- return;
-
- /* We only need these entries if this base is a virtual base. */
- if (!TREE_VIA_VIRTUAL (binfo))
- return;
-
- /* We need a vcall offset for each of the virtual functions in this
- vtable. For example:
-
- class A { virtual void f (); };
- class B : virtual public A { };
- class C: virtual public A, public B {};
-
- Now imagine:
-
- B* b = new C;
- b->f();
-
- The location of `A' is not at a fixed offset relative to `B'; the
- offset depends on the complete object derived from `B'. So,
- `B' vtable contains an entry for `f' that indicates by what
- amount the `this' pointer for `B' needs to be adjusted to arrive
- at `A'.
-
- We need entries for all the functions in our primary vtable and
- 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->vbase = binfo;
- VARRAY_TREE_INIT (vod->fns, 32, "fns");
- dfs_walk_real (binfo,
- dfs_build_vcall_offset_vtbl_entries,
- NULL,
- dfs_skip_vbases,
- vod);
- VARRAY_FREE (vod->fns);
}
/* Return vtbl initializers for the RTTI entries coresponding to the
by RTTI_BINFO. */
static void
-build_rtti_vtbl_entries (binfo, rtti_binfo, vod)
+build_rtti_vtbl_entries (binfo, rtti_binfo, vid)
tree binfo;
tree rtti_binfo;
- vcall_offset_data *vod;
+ vtbl_init_data *vid;
{
tree b;
tree t;
{
tree primary_base;
- primary_base = BINFO_PRIMARY_BINFO (b);
+ primary_base = get_primary_binfo (b);
if (!BINFO_PRIMARY_MARKED_P (primary_base))
break;
b = primary_base;
vtable. */
init = build1 (ADDR_EXPR, vfunc_ptr_type_node, decl);
TREE_CONSTANT (init) = 1;
- init = build_vtable_entry (offset, integer_zero_node, init);
+ init = build_vtable_entry (offset, NULL_TREE, init,
+ /*generate_with_vtable_p=*/0);
}
- *vod->last_init = build_tree_list (NULL_TREE, init);
- vod->last_init = &TREE_CHAIN (*vod->last_init);
+ *vid->last_init = build_tree_list (NULL_TREE, init);
+ vid->last_init = &TREE_CHAIN (*vid->last_init);
/* Add the offset-to-top entry. It comes earlier in the vtable that
the the typeinfo entry. */
we can put it in the vtable. */
init = build1 (NOP_EXPR, vfunc_ptr_type_node, offset);
TREE_CONSTANT (init) = 1;
- *vod->last_init = build_tree_list (NULL_TREE, init);
- vod->last_init = &TREE_CHAIN (*vod->last_init);
+ *vid->last_init = build_tree_list (NULL_TREE, init);
+ vid->last_init = &TREE_CHAIN (*vid->last_init);
}
}
ABI.) */
static tree
-build_vtable_entry (delta, vcall_index, entry)
+build_vtable_entry (delta, vcall_index, entry, generate_with_vtable_p)
tree delta;
tree vcall_index;
tree entry;
+ int generate_with_vtable_p;
{
- if (!vcall_index)
- vcall_index = integer_zero_node;
-
if (flag_vtable_thunks)
{
- HOST_WIDE_INT idelta;
- HOST_WIDE_INT ivindex;
tree fn;
- idelta = tree_low_cst (delta, 0);
- ivindex = tree_low_cst (vcall_index, 0);
fn = TREE_OPERAND (entry, 0);
- if ((idelta || ivindex)
+ if ((!integer_zerop (delta) || vcall_index != NULL_TREE)
&& fn != abort_fndecl
&& !DECL_TINFO_FN_P (fn))
{
- entry = make_thunk (entry, idelta, ivindex);
+ entry = make_thunk (entry, delta, vcall_index,
+ generate_with_vtable_p);
entry = build1 (ADDR_EXPR, vtable_entry_type, entry);
TREE_READONLY (entry) = 1;
TREE_CONSTANT (entry) = 1;
tree entry = build (CONSTRUCTOR, vtable_entry_type, NULL_TREE, elems);
/* We don't use vcall offsets when not using vtable thunks. */
- my_friendly_assert (integer_zerop (vcall_index), 20000125);
+ my_friendly_assert (vcall_index == NULL_TREE, 20000125);
/* DELTA used to be constructed by `size_int' and/or size_binop,
which caused overflow problems when it was negative. That should