static void check_field_decl PARAMS ((tree, tree, int *, int *, int *, int *));
static void check_field_decls PARAMS ((tree, tree *, int *, int *, int *,
int *));
-static bool build_base_field PARAMS ((record_layout_info, tree, int *,
- splay_tree, tree));
-static bool build_base_fields PARAMS ((record_layout_info, int *,
- splay_tree, tree));
+static tree *build_base_field PARAMS ((record_layout_info, tree, int *,
+ splay_tree, tree *));
+static void build_base_fields PARAMS ((record_layout_info, int *,
+ splay_tree, tree *));
static void check_methods PARAMS ((tree));
static void remove_zero_width_bit_fields PARAMS ((tree));
static void check_bases PARAMS ((tree, int *, int *, int *));
static void check_bases_and_members PARAMS ((tree, int *));
static tree create_vtable_ptr PARAMS ((tree, int *, tree *));
+static void include_empty_classes (record_layout_info);
static void layout_class_type PARAMS ((tree, int *, int *, tree *));
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, tree));
-static void layout_virtual_bases PARAMS ((tree, splay_tree));
+static void layout_virtual_bases (record_layout_info, 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_vtable PARAMS ((tree, tree));
static void initialize_array PARAMS ((tree, tree));
static void layout_nonempty_base_or_field PARAMS ((record_layout_info,
- tree, tree,
- splay_tree, tree));
-static unsigned HOST_WIDE_INT end_of_class PARAMS ((tree, int));
+ tree, tree, splay_tree));
+static tree end_of_class PARAMS ((tree, int));
static bool layout_empty_base PARAMS ((tree, tree, splay_tree, tree));
static void accumulate_vtbl_inits PARAMS ((tree, tree, tree, tree, tree));
static tree dfs_accumulate_vtbl_inits PARAMS ((tree, tree, tree, tree,
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));
-static void warn_about_ambiguous_direct_bases PARAMS ((tree));
+static void warn_about_ambiguous_bases PARAMS ((tree));
static bool type_requires_array_cookie PARAMS ((tree));
static bool contains_empty_class_p (tree);
if (CLASS_TYPE_P (type))
{
tree field;
+ tree binfo;
int i;
/* Record the location of TYPE. */
/* 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);
+ binfo = BINFO_BASETYPE (TYPE_BINFO (type), i);
+
+ if (abi_version_at_least (2)
+ && TREE_VIA_VIRTUAL (binfo))
+ continue;
if (!vbases_p
&& TREE_VIA_VIRTUAL (binfo)
BINFO_OFFSET (binfo)),
offsets,
max_offset,
- vbases_p);
+ (abi_version_at_least (2)
+ ? /*vbases_p=*/0 : vbases_p));
if (r)
return r;
}
+ /* Iterate through the virtual base classes of TYPE. In G++
+ 3.2, we included virtual bases in the direct base class loop
+ above, which results in incorrect results; the correct
+ offsets for virtual bases are only known when working with
+ the most derived type. */
+ if (abi_version_at_least (2) && vbases_p)
+ {
+ tree vbase;
+
+ for (vbase = CLASSTYPE_VBASECLASSES (type);
+ vbase;
+ vbase = TREE_CHAIN (vbase))
+ {
+ binfo = TREE_VALUE (vbase);
+ r = walk_subobject_offsets (BINFO_TYPE (binfo),
+ f,
+ size_binop (PLUS_EXPR,
+ offset,
+ BINFO_OFFSET (binfo)),
+ offsets,
+ max_offset,
+ /*vbases_p=*/0);
+ }
+ }
+
/* Iterate through the fields of TYPE. */
for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
- if (TREE_CODE (field) == FIELD_DECL)
+ if (TREE_CODE (field) == FIELD_DECL && !DECL_ARTIFICIAL (field))
{
tree field_offset;
tree index;
/* Step through each of the elements in the array. */
- for (index = size_zero_node;
- INT_CST_LT (index, TYPE_MAX_VALUE (domain));
+ for (index = size_zero_node;
+ /* G++ 3.2 had an off-by-one error here. */
+ (abi_version_at_least (2)
+ ? !INT_CST_LT (TYPE_MAX_VALUE (domain), index)
+ : INT_CST_LT (index, TYPE_MAX_VALUE (domain)));
index = size_binop (PLUS_EXPR, index, size_one_node))
{
r = walk_subobject_offsets (TREE_TYPE (type),
/* 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, OFFSETS maps offsets to
- types already located at those offsets. T is the most derived
- type. This function determines the position of the DECL. */
+ types already located at those offsets. This function determines
+ the position of the DECL. */
static void
-layout_nonempty_base_or_field (rli, decl, binfo, offsets, t)
- record_layout_info rli;
- tree decl;
- tree binfo;
- splay_tree offsets;
- tree t;
+layout_nonempty_base_or_field (record_layout_info rli,
+ tree decl,
+ tree binfo,
+ splay_tree offsets)
{
+ tree t = rli->t;
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);
+ bool field_p;
+ tree type;
+
+ if (binfo)
+ {
+ /* For the purposes of determining layout conflicts, we want to
+ use the class type of BINFO; TREE_TYPE (DECL) will be the
+ CLASSTYPE_AS_BASE version, which does not contain entries for
+ zero-sized bases. */
+ type = TREE_TYPE (binfo);
+ field_p = false;
+ }
+ else
+ {
+ type = TREE_TYPE (decl);
+ field_p = true;
+ }
/* 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
empty class, have nonzero size, any overlap can happen only
with a direct or indirect base-class -- it can't happen with
a data member. */
- if (layout_conflict_p (TREE_TYPE (decl),
- offset,
- offsets,
- field_p))
+ if (layout_conflict_p (type, offset, offsets, field_p))
{
/* Strip off the size allocated to this field. That puts us
at the first place we could have put the field with
/* Now that we know where it will be placed, update its
BINFO_OFFSET. */
if (binfo && CLASS_TYPE_P (BINFO_TYPE (binfo)))
+ /* Indirect virtual bases may have a non-zero BINFO_OFFSET at
+ this point because their BINFO_OFFSET is copied from another
+ hierarchy. Therefore, we may not need to add the entire
+ OFFSET. */
propagate_binfo_offsets (binfo,
- convert (ssizetype, offset), t);
+ size_diffop (convert (ssizetype, offset),
+ convert (ssizetype,
+ BINFO_OFFSET (binfo))),
+ t);
}
/* Layout the empty base BINFO. EOC indicates the byte currently just
return atend;
}
-/* 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. OFFSETS gives the location of empty base subobjects. T is
- the most derived type. Return nonzero if the new object cannot be
- nearly-empty. */
+/* Layout the the base given by BINFO in the class indicated by RLI.
+ If the new object is non-empty, and EMPTY_P is non-NULL, clear
+ *EMPTY_P. *BASE_ALIGN is a running maximum of the alignments of
+ any base class. OFFSETS gives the location of empty base
+ subobjects. T is the most derived type. Return nonzero if the new
+ object cannot be nearly-empty. A new FIELD_DECL is inserted at
+ *NEXT_FIELD, unless BINFO is for an empty base class.
-static bool
-build_base_field (rli, binfo, empty_p, offsets, t)
- record_layout_info rli;
- tree binfo;
- int *empty_p;
- splay_tree offsets;
- tree t;
+ Returns the location at which the next field should be inserted. */
+
+static tree *
+build_base_field (record_layout_info rli, tree binfo, int *empty_p,
+ splay_tree offsets, tree *next_field)
{
+ tree t = rli->t;
tree basetype = BINFO_TYPE (binfo);
- tree decl;
- bool atend = false;
if (!COMPLETE_TYPE_P (basetype))
/* This error is now reported in xref_tag, thus giving better
location information. */
- return atend;
-
- decl = build_decl (FIELD_DECL, NULL_TREE, basetype);
- DECL_ARTIFICIAL (decl) = 1;
- DECL_FIELD_CONTEXT (decl) = rli->t;
- DECL_SIZE (decl) = CLASSTYPE_SIZE (basetype);
- DECL_SIZE_UNIT (decl) = CLASSTYPE_SIZE_UNIT (basetype);
- DECL_ALIGN (decl) = CLASSTYPE_ALIGN (basetype);
- DECL_USER_ALIGN (decl) = CLASSTYPE_USER_ALIGN (basetype);
- /* Tell the backend not to round up to TYPE_ALIGN. */
- DECL_PACKED (decl) = 1;
+ return next_field;
- if (!integer_zerop (DECL_SIZE (decl)))
+ /* Place the base class. */
+ if (!is_empty_class (basetype))
{
+ tree decl;
+
/* The containing class is non-empty because it has a non-empty
base class. */
- *empty_p = 0;
-
+ if (empty_p)
+ *empty_p = 0;
+
+ /* Create the FIELD_DECL. */
+ decl = build_decl (FIELD_DECL, NULL_TREE, CLASSTYPE_AS_BASE (basetype));
+ DECL_ARTIFICIAL (decl) = 1;
+ DECL_FIELD_CONTEXT (decl) = t;
+ DECL_SIZE (decl) = CLASSTYPE_SIZE (basetype);
+ DECL_SIZE_UNIT (decl) = CLASSTYPE_SIZE_UNIT (basetype);
+ DECL_ALIGN (decl) = CLASSTYPE_ALIGN (basetype);
+ DECL_USER_ALIGN (decl) = CLASSTYPE_USER_ALIGN (basetype);
+ /* Tell the backend not to round up to TYPE_ALIGN. */
+ DECL_PACKED (decl) = 1;
+
/* 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, offsets, t);
+ layout_nonempty_base_or_field (rli, decl, binfo, offsets);
+ /* Add the new FIELD_DECL to the list of fields for T. */
+ TREE_CHAIN (decl) = *next_field;
+ *next_field = decl;
+ next_field = &TREE_CHAIN (decl);
}
else
{
- unsigned HOST_WIDE_INT eoc;
+ tree eoc;
/* 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_UNIT (decl)) * DECL_ALIGN_UNIT (decl);
- atend |= layout_empty_base (binfo, size_int (eoc), offsets, t);
+ eoc = round_up (rli_size_unit_so_far (rli),
+ CLASSTYPE_ALIGN_UNIT (basetype));
+ if (layout_empty_base (binfo, eoc, offsets, t))
+ CLASSTYPE_NEARLY_EMPTY_P (t) = 0;
+
+ /* We do not create a FIELD_DECL for empty base classes because
+ it might overlap some other field. We want to be able to
+ create CONSTRUCTORs for the class by iterating over the
+ FIELD_DECLs, and the back end does not handle overlapping
+ FIELD_DECLs. */
}
/* Record the offsets of BINFO and its base subobjects. */
BINFO_OFFSET (binfo),
offsets,
/*vbases_p=*/0);
- return atend;
+
+ return next_field;
}
/* Layout all of the non-virtual base classes. Record empty
- subobjects in OFFSETS. T is the most derived type. Return
- nonzero if the type cannot be nearly empty. */
+ subobjects in OFFSETS. T is the most derived type. Return nonzero
+ if the type cannot be nearly empty. The fields created
+ corresponding to the base classes will be inserted at
+ *NEXT_FIELD. */
-static bool
-build_base_fields (rli, empty_p, offsets, t)
- record_layout_info rli;
- int *empty_p;
- splay_tree offsets;
- tree t;
+static void
+build_base_fields (record_layout_info rli, int *empty_p,
+ splay_tree offsets, tree *next_field)
{
/* 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);
+ tree t = rli->t;
+ int n_baseclasses = CLASSTYPE_N_BASECLASSES (t);
int i;
- bool atend = 0;
/* The primary base class is always allocated first. */
- if (CLASSTYPE_HAS_PRIMARY_BASE_P (rec))
- build_base_field (rli, CLASSTYPE_PRIMARY_BINFO (rec),
- empty_p, offsets, t);
+ if (CLASSTYPE_HAS_PRIMARY_BASE_P (t))
+ next_field = build_base_field (rli, CLASSTYPE_PRIMARY_BINFO (t),
+ empty_p, offsets, next_field);
/* 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);
+ base_binfo = BINFO_BASETYPE (TYPE_BINFO (t), i);
/* The primary base was already allocated above, so we don't
need to allocate it again here. */
- if (base_binfo == CLASSTYPE_PRIMARY_BINFO (rec))
+ if (base_binfo == CLASSTYPE_PRIMARY_BINFO (t))
continue;
/* A primary virtual base class is allocated just like any other
&& !BINFO_PRIMARY_P (base_binfo))
continue;
- atend |= build_base_field (rli, base_binfo, empty_p, offsets, t);
+ next_field = build_base_field (rli, base_binfo, empty_p,
+ offsets, next_field);
}
- return atend;
}
/* Go through the TYPE_METHODS of T issuing any appropriate
return NULL_TREE;
}
-/* Set BINFO_OFFSET for all of the virtual bases for T. Update
+/* Set BINFO_OFFSET for all of the virtual bases for RLI->T. Update
TYPE_ALIGN and TYPE_SIZE for T. OFFSETS gives the location of
empty subobjects of T. */
static void
-layout_virtual_bases (t, offsets)
- tree t;
- splay_tree offsets;
+layout_virtual_bases (record_layout_info rli, splay_tree offsets)
{
- tree vbases, dsize;
- unsigned HOST_WIDE_INT eoc;
+ tree vbases;
+ tree t = rli->t;
bool first_vbase = true;
+ tree *next_field;
if (CLASSTYPE_N_BASECLASSES (t) == 0)
return;
+ if (!abi_version_at_least(2))
+ {
+ /* In G++ 3.2, we incorrectly rounded the size before laying out
+ the virtual bases. */
+ finish_record_layout (rli, /*free_p=*/false);
#ifdef STRUCTURE_SIZE_BOUNDARY
- /* Packed structures don't need to have minimum size. */
- if (! TYPE_PACKED (t))
- TYPE_ALIGN (t) = MAX (TYPE_ALIGN (t), STRUCTURE_SIZE_BOUNDARY);
+ /* Packed structures don't need to have minimum size. */
+ if (! TYPE_PACKED (t))
+ TYPE_ALIGN (t) = MAX (TYPE_ALIGN (t), STRUCTURE_SIZE_BOUNDARY);
#endif
+ rli->offset = TYPE_SIZE_UNIT (t);
+ rli->bitpos = bitsize_zero_node;
+ rli->record_align = TYPE_ALIGN (t);
+ }
- /* DSIZE is the size of the class without the virtual bases. */
- if (abi_version_at_least(2))
- dsize = CLASSTYPE_SIZE (t);
- else
- dsize = TYPE_SIZE (t);
-
- /* Make every class have alignment of at least one. */
- TYPE_ALIGN (t) = MAX (TYPE_ALIGN (t), BITS_PER_UNIT);
+ /* Find the last field. The artificial fields created for virtual
+ bases will go after the last extant field to date. */
+ next_field = &TYPE_FIELDS (t);
+ while (*next_field)
+ next_field = &TREE_CHAIN (*next_field);
/* Go through the virtual bases, allocating space for each virtual
base that is not already a primary base class. These are
if (!BINFO_PRIMARY_P (vbase))
{
+ tree basetype = TREE_TYPE (vbase);
+
/* This virtual base is not a primary base of any class in the
hierarchy, so we have to add space for it. */
- tree basetype, usize;
- unsigned int desired_align;
-
- basetype = BINFO_TYPE (vbase);
-
- desired_align = CLASSTYPE_ALIGN (basetype);
- TYPE_ALIGN (t) = MAX (TYPE_ALIGN (t), desired_align);
-
- /* Add padding so that we can put the virtual base class at an
- appropriately aligned offset. */
- dsize = round_up (dsize, desired_align);
- usize = size_binop (CEIL_DIV_EXPR, dsize, bitsize_unit_node);
-
- /* We try to squish empty virtual bases in just like
- ordinary empty bases. */
- if (is_empty_class (basetype))
- layout_empty_base (vbase,
- convert (sizetype, usize),
- offsets, t);
- else
- {
- tree offset;
-
- offset = convert (ssizetype, usize);
- offset = size_diffop (offset,
- convert (ssizetype,
- BINFO_OFFSET (vbase)));
-
- /* And compute the offset of the virtual base. */
- propagate_binfo_offsets (vbase, offset, t);
- /* Every virtual baseclass takes a least a UNIT, so that
- we can take it's address and get something different
- for each base. */
- dsize = size_binop (PLUS_EXPR, dsize,
- size_binop (MAX_EXPR, bitsize_unit_node,
- CLASSTYPE_SIZE (basetype)));
- }
+ next_field = build_base_field (rli, vbase, /*empty_p=*/NULL,
+ offsets, next_field);
/* If the first virtual base might have been placed at a
lower address, had we started from CLASSTYPE_SIZE, rather
the results which is not particularly tractable. */
if (warn_abi
&& first_vbase
- && tree_int_cst_lt (size_binop (CEIL_DIV_EXPR,
- round_up (CLASSTYPE_SIZE (t),
- desired_align),
- bitsize_unit_node),
- BINFO_OFFSET (vbase)))
+ && (tree_int_cst_lt
+ (size_binop (CEIL_DIV_EXPR,
+ round_up (CLASSTYPE_SIZE (t),
+ CLASSTYPE_ALIGN (basetype)),
+ bitsize_unit_node),
+ BINFO_OFFSET (vbase))))
warning ("offset of virtual base `%T' is not ABI-compliant and may change in a future version of GCC",
basetype);
- /* Keep track of the offsets assigned to this virtual base. */
- record_subobject_offsets (BINFO_TYPE (vbase),
- BINFO_OFFSET (vbase),
- offsets,
- /*vbases_p=*/0);
-
first_vbase = false;
}
}
in lookup_base depend on the BINFO_OFFSETs being set
correctly. */
dfs_walk (TYPE_BINFO (t), dfs_set_offset_for_unshared_vbases, NULL, t);
-
- /* If we had empty base classes that protruded beyond the end of the
- class, we didn't update DSIZE above; we were hoping to overlay
- multiple such bases at the same location. */
- eoc = end_of_class (t, /*include_virtuals_p=*/1);
- dsize = size_binop (MAX_EXPR, dsize, bitsize_int (eoc * BITS_PER_UNIT));
-
- /* Now, make sure that the total size of the type is a multiple of
- its alignment. */
- dsize = round_up (dsize, TYPE_ALIGN (t));
- TYPE_SIZE (t) = dsize;
- TYPE_SIZE_UNIT (t) = convert (sizetype,
- size_binop (CEIL_DIV_EXPR, TYPE_SIZE (t),
- bitsize_unit_node));
-
- /* Check for ambiguous virtual bases. */
- if (extra_warnings)
- for (vbases = CLASSTYPE_VBASECLASSES (t);
- vbases;
- vbases = TREE_CHAIN (vbases))
- {
- tree basetype = BINFO_TYPE (TREE_VALUE (vbases));
-
- if (!lookup_base (t, basetype, ba_ignore | ba_quiet, NULL))
- warning ("virtual base `%T' inaccessible in `%T' due to ambiguity",
- basetype, t);
- }
}
/* Returns the offset of the byte just past the end of the base class
with the highest offset in T. If INCLUDE_VIRTUALS_P is zero, then
only non-virtual bases are included. */
-static unsigned HOST_WIDE_INT
+static tree
end_of_class (t, include_virtuals_p)
tree t;
int include_virtuals_p;
{
- unsigned HOST_WIDE_INT result = 0;
+ tree result = size_zero_node;
int i;
for (i = 0; i < CLASSTYPE_N_BASECLASSES (t); ++i)
tree base_binfo;
tree offset;
tree size;
- unsigned HOST_WIDE_INT end_of_base;
base_binfo = BINFO_BASETYPE (TYPE_BINFO (t), i);
offset = size_binop (PLUS_EXPR,
BINFO_OFFSET (base_binfo),
size);
- end_of_base = tree_low_cst (offset, /*pos=*/1);
- if (end_of_base > result)
- result = end_of_base;
+ if (INT_CST_LT_UNSIGNED (result, offset))
+ result = offset;
}
return result;
}
-/* Warn about direct bases of T that are inaccessible because they are
+/* Warn about bases of T that are inaccessible because they are
ambiguous. For example:
struct S {};
subobjects of U. */
static void
-warn_about_ambiguous_direct_bases (t)
+warn_about_ambiguous_bases (t)
tree t;
{
int i;
+ tree vbases;
+ tree basetype;
+ /* Check direct bases. */
for (i = 0; i < CLASSTYPE_N_BASECLASSES (t); ++i)
{
- tree basetype = TYPE_BINFO_BASETYPE (t, i);
+ basetype = TYPE_BINFO_BASETYPE (t, i);
if (!lookup_base (t, basetype, ba_ignore | ba_quiet, NULL))
warning ("direct base `%T' inaccessible in `%T' due to ambiguity",
- basetype, t);
+ basetype, t);
}
+
+ /* Check for ambiguous virtual bases. */
+ if (extra_warnings)
+ for (vbases = CLASSTYPE_VBASECLASSES (t);
+ vbases;
+ vbases = TREE_CHAIN (vbases))
+ {
+ basetype = BINFO_TYPE (TREE_VALUE (vbases));
+
+ if (!lookup_base (t, basetype, ba_ignore | ba_quiet, NULL))
+ warning ("virtual base `%T' inaccessible in `%T' due to ambiguity",
+ basetype, t);
+ }
}
/* Compare two INTEGER_CSTs K1 and K2. */
return tree_int_cst_compare ((tree) k1, (tree) k2);
}
+/* Increase the size indicated in RLI to account for empty classes
+ that are "off the end" of the class. */
+
+static void
+include_empty_classes (record_layout_info rli)
+{
+ tree eoc;
+
+ /* It might be the case that we grew the class to allocate a
+ zero-sized base class. That won't be reflected in RLI, yet,
+ because we are willing to overlay multiple bases at the same
+ offset. However, now we need to make sure that RLI is big enough
+ to reflect the entire class. */
+ eoc = end_of_class (rli->t,
+ CLASSTYPE_AS_BASE (rli->t) != NULL_TREE);
+ if (TREE_CODE (rli_size_unit_so_far (rli)) == INTEGER_CST
+ && INT_CST_LT_UNSIGNED (rli_size_unit_so_far (rli), eoc))
+ {
+ rli->offset = size_binop (MAX_EXPR, rli->offset, eoc);
+ rli->bitpos = bitsize_zero_node;
+ }
+}
+
/* Calculate the TYPE_SIZE, TYPE_ALIGN, etc for T. Calculate
BINFO_OFFSETs for all of the base-classes. Position the vtable
pointer. Accumulate declared virtual functions on VIRTUALS_P. */
tree field;
tree vptr;
record_layout_info rli;
- 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;
/* True if the last field layed out was a bit-field. */
bool last_field_was_bitfield = false;
+ /* The location at which the next field should be inserted. */
+ tree *next_field;
+ /* T, as a base class. */
+ tree base_t;
/* Keep track of the first non-static data member. */
non_static_data_members = TYPE_FIELDS (t);
/* The vptr is always the first thing in the class. */
if (vptr)
{
- TYPE_FIELDS (t) = chainon (vptr, TYPE_FIELDS (t));
+ TREE_CHAIN (vptr) = TYPE_FIELDS (t);
+ TYPE_FIELDS (t) = vptr;
+ next_field = &TREE_CHAIN (vptr);
place_field (rli, vptr);
}
+ else
+ next_field = &TYPE_FIELDS (t);
/* Build FIELD_DECLs for all of the non-virtual base-types. */
empty_base_offsets = splay_tree_new (splay_tree_compare_integer_csts,
NULL, NULL);
- if (build_base_fields (rli, empty_p, empty_base_offsets, t))
- CLASSTYPE_NEARLY_EMPTY_P (t) = 0;
+ build_base_fields (rli, empty_p, empty_base_offsets, next_field);
/* Layout the non-static data members. */
for (field = non_static_data_members; field; field = TREE_CHAIN (field))
padding = NULL_TREE;
layout_nonempty_base_or_field (rli, field, NULL_TREE,
- empty_base_offsets, t);
+ empty_base_offsets);
/* If a bit-field does not immediately follow another bit-field,
and yet it starts in the middle of a byte, we have failed to
DECL_USER_ALIGN (padding_field) = 0;
layout_nonempty_base_or_field (rli, padding_field,
NULL_TREE,
- empty_base_offsets, t);
+ empty_base_offsets);
}
last_field_was_bitfield = DECL_C_BIT_FIELD (field);
}
- /* It might be the case that we grew the class to allocate a
- zero-sized base class. That won't be reflected in RLI, yet,
- because we are willing to overlay multiple bases at the same
- offset. However, now we need to make sure that RLI is big enough
- to reflect the entire class. */
- eoc = end_of_class (t, /*include_virtuals_p=*/0);
- if (TREE_CODE (rli_size_unit_so_far (rli)) == INTEGER_CST
- && compare_tree_int (rli_size_unit_so_far (rli), eoc) < 0)
- {
- rli->offset = size_binop (MAX_EXPR, rli->offset, size_int (eoc));
- rli->bitpos = bitsize_zero_node;
- }
-
- /* We make all structures have at least one element, so that they
- have nonzero size. The class may be empty even if it has
- basetypes. Therefore, we add the fake field after all the other
- fields; if there are already FIELD_DECLs on the list, their
- offsets will not be disturbed. */
- if (!eoc && *empty_p)
- {
- tree padding;
-
- padding = build_decl (FIELD_DECL, NULL_TREE, char_type_node);
- place_field (rli, padding);
- }
- else if (abi_version_at_least (2)
- && !integer_zerop (rli->bitpos))
+ if (abi_version_at_least (2) && !integer_zerop (rli->bitpos))
/* Make sure that we are on a byte boundary so that the size of
the class without virtual bases will always be a round number
of bytes. */
rli->bitpos = round_up (rli->bitpos, BITS_PER_UNIT);
-
- /* Let the back-end lay out the type. Note that at this point we
- have only included non-virtual base-classes; we will lay out the
- virtual base classes later. So, the TYPE_SIZE/TYPE_ALIGN after
- this call are not necessarily correct; they are just the size and
- alignment when no virtual base clases are used. */
- finish_record_layout (rli);
+
+ /* Make sure that empty classes are reflected in RLI at this
+ point. */
+ include_empty_classes(rli);
/* Delete all zero-width bit-fields from the list of fields. Now
that the type is laid out they are no longer important. */
remove_zero_width_bit_fields (t);
- /* Remember the size and alignment of the class before adding
- the virtual bases. */
- if (*empty_p)
+ /* Create the version of T used for virtual bases. We do not use
+ make_aggr_type for this version; this is an artificial type. For
+ a POD type, we just reuse T. */
+ if (CLASSTYPE_NON_POD_P (t) || *empty_p)
{
- CLASSTYPE_SIZE (t) = bitsize_zero_node;
- CLASSTYPE_SIZE_UNIT (t) = size_zero_node;
- }
- /* If this is a POD, we can't reuse its tail padding. */
- else if (!CLASSTYPE_NON_POD_P (t))
- {
- CLASSTYPE_SIZE (t) = TYPE_SIZE (t);
- CLASSTYPE_SIZE_UNIT (t) = TYPE_SIZE_UNIT (t);
+ base_t = make_node (TREE_CODE (t));
+
+ /* Set the size and alignment for the new type. */
+ TYPE_SIZE (base_t) = rli_size_so_far (rli);
+ TYPE_SIZE_UNIT (base_t) = rli_size_unit_so_far (rli);
+ TYPE_ALIGN (base_t) = rli->record_align;
+ TYPE_USER_ALIGN (base_t) = TYPE_USER_ALIGN (t);
+
+ /* Copy the fields from T. */
+ next_field = &TYPE_FIELDS (base_t);
+ for (field = TYPE_FIELDS (t); field; field = TREE_CHAIN (field))
+ if (TREE_CODE (field) == FIELD_DECL)
+ {
+ *next_field = build_decl (FIELD_DECL,
+ DECL_NAME (field),
+ TREE_TYPE (field));
+ DECL_CONTEXT (*next_field) = base_t;
+ DECL_FIELD_OFFSET (*next_field) = DECL_FIELD_OFFSET (field);
+ DECL_FIELD_BIT_OFFSET (*next_field)
+ = DECL_FIELD_BIT_OFFSET (field);
+ next_field = &TREE_CHAIN (*next_field);
+ }
+
+ /* Record the base version of the type. */
+ CLASSTYPE_AS_BASE (t) = base_t;
}
else
- {
- CLASSTYPE_SIZE (t) = TYPE_BINFO_SIZE (t);
- CLASSTYPE_SIZE_UNIT (t) = TYPE_BINFO_SIZE_UNIT (t);
- }
-
- CLASSTYPE_ALIGN (t) = TYPE_ALIGN (t);
- CLASSTYPE_USER_ALIGN (t) = TYPE_USER_ALIGN (t);
+ CLASSTYPE_AS_BASE (t) = t;
/* Set the TYPE_DECL for this type to contain the right
value for DECL_OFFSET, so that we can use it as part
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, empty_base_offsets);
+ layout_virtual_bases (rli, empty_base_offsets);
+
+ /* Make sure that empty classes are reflected in RLI at this
+ point. */
+ include_empty_classes(rli);
+
+ /* Make sure not to create any structures with zero size. */
+ if (integer_zerop (rli_size_unit_so_far (rli)) && *empty_p)
+ place_field (rli,
+ build_decl (FIELD_DECL, NULL_TREE, char_type_node));
+
+ /* Let the back-end lay out the type. */
+ finish_record_layout (rli, /*free_p=*/true);
- /* Warn about direct bases that can't be talked about due to
- ambiguity. */
- warn_about_ambiguous_direct_bases (t);
+ /* Warn about bases that can't be talked about due to ambiguity. */
+ warn_about_ambiguous_bases (t);
/* Clean up. */
splay_tree_delete (empty_base_offsets);
if (contains_empty_class_p (TYPE_BINFO_BASETYPE (type, i)))
return true;
for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
- if (contains_empty_class_p (TREE_TYPE (field)))
+ if (TREE_CODE (field) == FIELD_DECL
+ && !DECL_ARTIFICIAL (field)
+ && is_empty_class (TREE_TYPE (field)))
return true;
}
else if (TREE_CODE (type) == ARRAY_TYPE)
static int unary_op_p PARAMS ((enum tree_code));
static tree store_bindings PARAMS ((tree, tree));
static tree lookup_tag_reverse PARAMS ((tree, tree));
-static tree obscure_complex_init PARAMS ((tree, tree));
static tree lookup_name_real PARAMS ((tree, int, int, int));
static void push_local_name PARAMS ((tree));
static void warn_extern_redeclared_static PARAMS ((tree, tree));
newtype = oldtype;
if (TREE_CODE (newdecl) == VAR_DECL)
- DECL_THIS_EXTERN (newdecl) |= DECL_THIS_EXTERN (olddecl);
+ {
+ DECL_THIS_EXTERN (newdecl) |= DECL_THIS_EXTERN (olddecl);
+ DECL_INITIALIZED_P (newdecl) |= DECL_INITIALIZED_P (olddecl);
+ }
+
/* Do this after calling `merge_types' so that default
parameters don't confuse us. */
else if (TREE_CODE (newdecl) == FUNCTION_DECL
return NULL_TREE;
}
-/* Fill in DECL_INITIAL with some magical value to prevent expand_decl from
- mucking with forces it does not comprehend (i.e. initialization with a
- constructor). If we are at global scope and won't go into COMMON, fill
- it in with a dummy CONSTRUCTOR to force the variable into .data;
- otherwise we can use error_mark_node. */
-
-static tree
-obscure_complex_init (decl, init)
- tree decl, init;
-{
- if (TREE_CODE (decl) == VAR_DECL && DECL_THREAD_LOCAL (decl))
- {
- error ("run-time initialization of thread-local storage");
- return NULL_TREE;
- }
-
- if (! flag_no_inline && TREE_STATIC (decl))
- {
- if (extract_init (decl, init))
- return NULL_TREE;
- }
-
-#if ! defined (ASM_OUTPUT_BSS) && ! defined (ASM_OUTPUT_ALIGNED_BSS)
- if (toplevel_bindings_p () && ! DECL_COMMON (decl))
- DECL_INITIAL (decl) = build (CONSTRUCTOR, TREE_TYPE (decl), NULL_TREE,
- NULL_TREE);
- else
-#endif
- {
- if (zero_init_p (TREE_TYPE (decl)))
- DECL_INITIAL (decl) = error_mark_node;
- /* Otherwise, force_store_init_value will have already stored a
- zero-init initializer in DECL_INITIAL, that should be
- retained. */
- }
-
- return init;
-}
-
/* When parsing `int a[] = {1, 2};' we don't know the size of the
array until we finish parsing the initializer. If that's the
situation we're in, update DECL accordingly. */
tree decl;
tree init;
{
- tree type;
-
- if (TREE_CODE (decl) == FIELD_DECL)
- return init;
-
- type = TREE_TYPE (decl);
+ tree type = TREE_TYPE (decl);
/* If `start_decl' didn't like having an initialization, ignore it now. */
if (init != NULL_TREE && DECL_INITIAL (decl) == NULL_TREE)
init = NULL_TREE;
+ /* If an initializer is present, DECL_INITIAL has been
+ error_mark_node, to indicate that an as-of-yet unevaluated
+ initialization will occur. From now on, DECL_INITIAL reflects
+ the static initialization -- if any -- of DECL. */
+ DECL_INITIAL (decl) = NULL_TREE;
+
/* Check the initializer. */
if (init)
{
init = NULL_TREE;
}
else if (!DECL_EXTERNAL (decl) && TREE_CODE (type) == REFERENCE_TYPE)
- {
- init = grok_reference_init (decl, type, init);
- if (init)
- init = obscure_complex_init (decl, init);
- }
- else if (!DECL_EXTERNAL (decl) && !zero_init_p (type))
- {
- force_store_init_value (decl, build_forced_zero_init (type));
-
- if (init)
- goto process_init;
- }
+ init = grok_reference_init (decl, type, init);
else if (init)
{
- process_init:
if (TYPE_HAS_CONSTRUCTOR (type) || TYPE_NEEDS_CONSTRUCTING (type))
{
if (TREE_CODE (type) == ARRAY_TYPE)
if (TREE_CODE (init) != TREE_VEC)
init = store_init_value (decl, init);
}
-
- if (init)
- /* We must hide the initializer so that expand_decl
- won't try to do something it does not understand. */
- init = obscure_complex_init (decl, init);
}
else if (DECL_EXTERNAL (decl))
;
}
check_for_uninitialized_const_var (decl);
-
- if (COMPLETE_TYPE_P (type) && TYPE_NEEDS_CONSTRUCTING (type))
- init = obscure_complex_init (decl, NULL_TREE);
-
}
else
check_for_uninitialized_const_var (decl);
SET_DECL_ASSEMBLER_NAME (decl, get_identifier (asmspec));
make_decl_rtl (decl, asmspec);
}
-
- /* Deduce size of array from initialization, if not already known. */
- init = check_initializer (decl, init);
- maybe_deduce_size_from_array_init (decl, init);
+ else if (TREE_CODE (decl) == RESULT_DECL)
+ init = check_initializer (decl, init);
+ else if (TREE_CODE (decl) == VAR_DECL)
+ {
+ /* Only PODs can have thread-local storage. Other types may require
+ various kinds of non-trivial initialization. */
+ if (DECL_THREAD_LOCAL (decl) && !pod_type_p (TREE_TYPE (decl)))
+ error ("`%D' cannot be thread-local because it has non-POD type `%T'",
+ decl, TREE_TYPE (decl));
+ /* Convert the initializer to the type of DECL, if we have not
+ already initialized DECL. */
+ if (!DECL_INITIALIZED_P (decl)
+ /* If !DECL_EXTERNAL then DECL is being defined. In the
+ case of a static data memberm initialized inside the
+ class-specifier, there can be an initializer even if DECL
+ is *not* defined. */
+ && (!DECL_EXTERNAL (decl) || init))
+ {
+ init = check_initializer (decl, init);
+ /* If DECL has an array type without a specific bound, deduce the
+ array size from the initializer. Note that this must be done
+ after check_initializer is called because of cases like this:
+
+ struct S { int a; int b; };
+ struct S a[] = { 1, 2 };
+
+ which creates a one-element array, not a two-element array. */
+ maybe_deduce_size_from_array_init (decl, init);
+ /* Handle:
+
+ [dcl.init]
+
+ The memory occupied by any object of static storage
+ duration is zero-initialized at program startup before
+ any other initialization takes place.
+
+ We cannot create an appropriate initializer until after
+ the type of DECL is finalized. If DECL_INITIAL is set,
+ then the DECL is statically initialized, and any
+ necessary zero-initialization has already been performed. */
+ if (TREE_STATIC (decl) && !DECL_INITIAL (decl))
+ DECL_INITIAL (decl) = build_zero_init (TREE_TYPE (decl),
+ /*static_storage_p=*/true);
+ /* Remember that the initialization for this variable has
+ taken place. */
+ DECL_INITIALIZED_P (decl) = 1;
+ }
+ }
/* Add this declaration to the statement-tree. This needs to happen
after the call to check_initializer so that the DECL_STMT for a
dfs_marked_real_bases_queue_p, type);
}
-/* Types containing pointers to data members cannot be
- zero-initialized with zeros, because the NULL value for such
- pointers is -1.
-
- TYPE is a type that requires such zero initialization. The
- returned value is the initializer. */
+/* Return an expression for the zero-initialization of an object with
+ type T. This expression will either be a constant (in the case
+ that T is a scalar), or a CONSTRUCTOR (in the case that T is an
+ aggregate). In either case, the value can be used as DECL_INITIAL
+ for a decl of the indicated TYPE; it is a valid static initializer.
+ If STATIC_STORAGE_P is TRUE, initializers are only generated for
+ entities for which zero-initialization does not simply mean filling
+ the storage with zero bytes. */
tree
-build_forced_zero_init (type)
- tree type;
+build_zero_init (tree type, bool static_storage_p)
{
- tree init = NULL;
+ tree init = NULL_TREE;
+
+ /* [dcl.init]
+
+ To zero-initialization storage for an object of type T means:
+
+ -- if T is a scalar type, the storage is set to the value of zero
+ converted to T.
+
+ -- if T is a non-union class type, the storage for each nonstatic
+ data member and each base-class subobject is zero-initialized.
+
+ -- if T is a union type, the storage for its first data member is
+ zero-initialized.
+
+ -- if T is an array type, the storage for each element is
+ zero-initialized.
+
+ -- if T is a reference type, no initialization is performed. */
- if (AGGREGATE_TYPE_P (type) && !TYPE_PTRMEMFUNC_P (type))
+ if (type == error_mark_node)
+ ;
+ else if (static_storage_p && zero_init_p (type))
+ /* In order to save space, we do not explicitly build initializers
+ for items that do not need them. GCC's semantics are that
+ items with static storage duration that are not otherwise
+ initialized are initialized to zero. */
+ ;
+ else if (SCALAR_TYPE_P (type))
+ init = convert (type, integer_zero_node);
+ else if (CLASS_TYPE_P (type))
+ {
+ tree field;
+ tree inits;
+
+ /* Build a constructor to contain the initializations. */
+ init = build (CONSTRUCTOR, type, NULL_TREE, NULL_TREE);
+ /* Iterate over the fields, building initializations. */
+ inits = NULL_TREE;
+ for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
+ {
+ if (TREE_CODE (field) != FIELD_DECL)
+ continue;
+
+ /* Note that for class types there will be FIELD_DECLs
+ corresponding to base classes as well. Thus, iterating
+ over TYPE_FIELDs will result in correct initialization of
+ all of the subobjects. */
+ if (static_storage_p && !zero_init_p (TREE_TYPE (field)))
+ inits = tree_cons (field,
+ build_zero_init (TREE_TYPE (field),
+ static_storage_p),
+ inits);
+
+ /* For unions, only the first field is initialized. */
+ if (TREE_CODE (type) == UNION_TYPE)
+ break;
+ }
+ CONSTRUCTOR_ELTS (init) = nreverse (inits);
+ }
+ else if (TREE_CODE (type) == ARRAY_TYPE)
{
- /* This is a default initialization of an aggregate, but not one of
- non-POD class type. We cleverly notice that the initialization
- rules in such a case are the same as for initialization with an
- empty brace-initialization list. */
- init = build (CONSTRUCTOR, NULL_TREE, NULL_TREE, NULL_TREE);
+ tree index;
+ tree max_index;
+ tree inits;
+
+ /* Build a constructor to contain the initializations. */
+ init = build (CONSTRUCTOR, type, NULL_TREE, NULL_TREE);
+ /* Iterate over the array elements, building initializations. */
+ inits = NULL_TREE;
+ for (index = size_zero_node, max_index = array_type_nelts (type);
+ !tree_int_cst_lt (max_index, index);
+ index = size_binop (PLUS_EXPR, index, size_one_node))
+ inits = tree_cons (index,
+ build_zero_init (TREE_TYPE (type),
+ static_storage_p),
+ inits);
+ CONSTRUCTOR_ELTS (init) = nreverse (inits);
}
else if (TREE_CODE (type) == REFERENCE_TYPE)
- /* --if T is a reference type, no initialization is performed. */
- return NULL_TREE;
+ ;
else
- {
- init = integer_zero_node;
-
- if (TREE_CODE (type) == ENUMERAL_TYPE)
- /* We must make enumeral types the right type. */
- init = fold (build1 (NOP_EXPR, type, init));
- }
+ abort ();
- init = digest_init (type, init, 0);
+ /* In all cases, the initializer is a constant. */
+ if (init)
+ TREE_CONSTANT (init) = 1;
return init;
}
-/* [dcl.init]:
+/* Build an expression for the default-initialization of an object
+ with type T. If initialization T requires calling constructors,
+ this function returns NULL_TREE; the caller is responsible for
+ arranging for the constructors to be called. */
- To default-initialize an object of type T means:
+static tree
+build_default_init (type)
+ tree type;
+{
+ /* [dcl.init]:
- --if T is a non-POD class type (clause _class_), the default construc-
- tor for T is called (and the initialization is ill-formed if T has
- no accessible default constructor);
+ To default-initialize an object of type T means:
- --if T is an array type, each element is default-initialized;
+ --if T is a non-POD class type (clause _class_), the default construc-
+ tor for T is called (and the initialization is ill-formed if T has
+ no accessible default constructor);
- --otherwise, the storage for the object is zero-initialized.
+ --if T is an array type, each element is default-initialized;
- A program that calls for default-initialization of an entity of refer-
- ence type is ill-formed. */
+ --otherwise, the storage for the object is zero-initialized.
-static tree
-build_default_init (type)
- tree type;
-{
+ A program that calls for default-initialization of an entity of refer-
+ ence type is ill-formed. */
+
+ /* If TYPE_NEEDS_CONSTRUCTING is true, the caller is responsible for
+ performing the initialization. This is confusing in that some
+ non-PODs do not have TYPE_NEEDS_CONSTRUCTING set. (For example,
+ a class with a pointer-to-data member as a non-static data member
+ does not have TYPE_NEEDS_CONSTRUCTING set.) Therefore, we end up
+ passing non-PODs to build_zero_init below, which is contrary to
+ the semantics quoted above from [dcl.init].
+
+ It happens, however, that the behavior of the constructor the
+ standard says we should have generated would be precisely the
+ same as that obtained by calling build_zero_init below, so things
+ work out OK. */
if (TYPE_NEEDS_CONSTRUCTING (type))
- /* Other code will handle running the default constructor. We can't do
- anything with a CONSTRUCTOR for arrays here, as that would imply
- copy-initialization. */
return NULL_TREE;
-
- return build_forced_zero_init (type);
+
+ /* At this point, TYPE is either a POD class type, an array of POD
+ classes, or something even more inoccuous. */
+ return build_zero_init (type, /*static_storage_p=*/false);
}
/* Subroutine of emit_base_init. */
for (fields = TYPE_FIELDS (t); fields; fields = TREE_CHAIN (fields))
{
/* Skip CONST_DECLs for enumeration constants and so forth. */
- if (TREE_CODE (fields) != FIELD_DECL)
+ if (TREE_CODE (fields) != FIELD_DECL || DECL_ARTIFICIAL (fields))
continue;
/* Keep track of whether or not any fields are unions. */
for (member = TYPE_FIELDS (current_class_type); member;
member = TREE_CHAIN (member))
{
- if (TREE_CODE (member) != FIELD_DECL)
+ if (TREE_CODE (member) != FIELD_DECL || DECL_ARTIFICIAL (member))
continue;
if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (member)))
{