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 int current_class_stack_size;
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, tree, int *));
static void propagate_binfo_offsets PARAMS ((tree, tree));
-static void layout_virtual_bases PARAMS ((tree, varray_type *));
+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, vtbl_init_data *));
static void add_vcall_offset_vtbl_entries_r PARAMS ((tree, vtbl_init_data *));
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, vtbl_init_data *));
static tree dfs_fixup_binfo_vtbls PARAMS ((tree, void *));
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. */
}
}
\f
-extern struct obstack *current_obstack;
-
/* 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
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;
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;
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;
- 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));
+ if (!is_empty_class (type))
+ return 0;
- return NULL_TREE;
+ /* 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 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;
+
+ /* 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 NULL_TREE;
+ 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 && CLASS_TYPE_P (BINFO_TYPE (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)
&& !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
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;
}
}
/* 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;
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);
}
}
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);
}
/* Build FIELD_DECLs for all of the non-virtual base-types. */
- v = build_base_fields (rli, empty_p);
+ 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));
/* 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);
}
}
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
{
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));
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 (TREE_CODE (TREE_TYPE (fn)) == METHOD_TYPE
+ 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);
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);
}
}
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))
vtbl_init_data vid;
/* Initialize VID. */
- bzero (&vid, sizeof (vid));
+ memset (&vid, 0, sizeof (vid));
vid.binfo = binfo;
vid.derived = t;
vid.last_init = &vid.inits;
build_vcall_and_vbase_vtbl_entries (binfo, &vid);
/* Clean up. */
VARRAY_FREE (vid.fns);
- /* Clear BINFO_VTABLE_PAATH_MARKED; it's set by
+ /* Clear BINFO_VTABLE_PATH_MARKED; it's set by
build_vbase_offset_vtbl_entries. */
for (vbase = CLASSTYPE_VBASECLASSES (t);
vbase;