mirror of
git://gcc.gnu.org/git/gcc.git
synced 2024-12-19 13:00:09 +08:00
stor-layout.c (update_alignment_for_field): New function.
* stor-layout.c (update_alignment_for_field): New function. (place_union_field): Use it. (place_field): Likewise. * gcc.dg/empty1.C: New test. From-SVN: r57697
This commit is contained in:
parent
b4c20e524c
commit
0645ba8f0b
@ -1,3 +1,9 @@
|
||||
2002-10-01 Mark Mitchell <mark@codesourcery.com>
|
||||
|
||||
* stor-layout.c (update_alignment_for_field): New function.
|
||||
(place_union_field): Use it.
|
||||
(place_field): Likewise.
|
||||
|
||||
2002-10-01 Nathan Sidwell <nathan@codesourcery.com>
|
||||
|
||||
* gcc.c (cc1_options): Add space on -auxbase-strip.
|
||||
|
@ -60,6 +60,9 @@ static int reference_types_internal = 0;
|
||||
static void finalize_record_size PARAMS ((record_layout_info));
|
||||
static void finalize_type_size PARAMS ((tree));
|
||||
static void place_union_field PARAMS ((record_layout_info, tree));
|
||||
static unsigned int update_alignment_for_field
|
||||
PARAMS ((record_layout_info, tree,
|
||||
unsigned int));
|
||||
extern void debug_rli PARAMS ((record_layout_info));
|
||||
|
||||
/* SAVE_EXPRs for sizes of types and decls, waiting to be expanded. */
|
||||
@ -644,130 +647,23 @@ rli_size_so_far (rli)
|
||||
return bit_from_pos (rli->offset, rli->bitpos);
|
||||
}
|
||||
|
||||
/* Called from place_field to handle unions. */
|
||||
/* FIELD is about to be added to RLI->T. The alignment (in bits) of
|
||||
the next available location is given by KNOWN_ALIGN. Update the
|
||||
variable alignment fields in RLI, and return the alignment to give
|
||||
the FIELD. */
|
||||
|
||||
static void
|
||||
place_union_field (rli, field)
|
||||
record_layout_info rli;
|
||||
tree field;
|
||||
{
|
||||
unsigned int desired_align;
|
||||
|
||||
layout_decl (field, 0);
|
||||
|
||||
DECL_FIELD_OFFSET (field) = size_zero_node;
|
||||
DECL_FIELD_BIT_OFFSET (field) = bitsize_zero_node;
|
||||
SET_DECL_OFFSET_ALIGN (field, BIGGEST_ALIGNMENT);
|
||||
|
||||
desired_align = DECL_ALIGN (field);
|
||||
|
||||
#ifdef BIGGEST_FIELD_ALIGNMENT
|
||||
/* Some targets (i.e. i386) limit union field alignment
|
||||
to a lower boundary than alignment of variables unless
|
||||
it was overridden by attribute aligned. */
|
||||
if (! DECL_USER_ALIGN (field))
|
||||
desired_align =
|
||||
MIN (desired_align, (unsigned) BIGGEST_FIELD_ALIGNMENT);
|
||||
#endif
|
||||
|
||||
#ifdef ADJUST_FIELD_ALIGN
|
||||
if (! DECL_USER_ALIGN (field))
|
||||
desired_align = ADJUST_FIELD_ALIGN (field, desired_align);
|
||||
#endif
|
||||
|
||||
TYPE_USER_ALIGN (rli->t) |= DECL_USER_ALIGN (field);
|
||||
|
||||
/* Union must be at least as aligned as any field requires. */
|
||||
rli->record_align = MAX (rli->record_align, desired_align);
|
||||
rli->unpadded_align = MAX (rli->unpadded_align, desired_align);
|
||||
|
||||
#ifdef PCC_BITFIELD_TYPE_MATTERS
|
||||
/* On the m88000, a bit field of declare type `int' forces the
|
||||
entire union to have `int' alignment. */
|
||||
if (PCC_BITFIELD_TYPE_MATTERS && DECL_BIT_FIELD_TYPE (field))
|
||||
{
|
||||
unsigned int type_align = TYPE_ALIGN (TREE_TYPE (field));
|
||||
|
||||
#ifdef ADJUST_FIELD_ALIGN
|
||||
if (! TYPE_USER_ALIGN (TREE_TYPE (field)))
|
||||
type_align = ADJUST_FIELD_ALIGN (field, type_align);
|
||||
#endif
|
||||
rli->record_align = MAX (rli->record_align, type_align);
|
||||
rli->unpadded_align = MAX (rli->unpadded_align, type_align);
|
||||
TYPE_USER_ALIGN (rli->t) |= TYPE_USER_ALIGN (TREE_TYPE (field));
|
||||
}
|
||||
#endif
|
||||
|
||||
/* We assume the union's size will be a multiple of a byte so we don't
|
||||
bother with BITPOS. */
|
||||
if (TREE_CODE (rli->t) == UNION_TYPE)
|
||||
rli->offset = size_binop (MAX_EXPR, rli->offset, DECL_SIZE_UNIT (field));
|
||||
else if (TREE_CODE (rli->t) == QUAL_UNION_TYPE)
|
||||
rli->offset = fold (build (COND_EXPR, sizetype,
|
||||
DECL_QUALIFIER (field),
|
||||
DECL_SIZE_UNIT (field), rli->offset));
|
||||
}
|
||||
|
||||
/* RLI contains information about the layout of a RECORD_TYPE. FIELD
|
||||
is a FIELD_DECL to be added after those fields already present in
|
||||
T. (FIELD is not actually added to the TYPE_FIELDS list here;
|
||||
callers that desire that behavior must manually perform that step.) */
|
||||
|
||||
void
|
||||
place_field (rli, field)
|
||||
static unsigned int
|
||||
update_alignment_for_field (rli, field, known_align)
|
||||
record_layout_info rli;
|
||||
tree field;
|
||||
unsigned int known_align;
|
||||
{
|
||||
/* The alignment required for FIELD. */
|
||||
unsigned int desired_align;
|
||||
/* The alignment FIELD would have if we just dropped it into the
|
||||
record as it presently stands. */
|
||||
unsigned int known_align;
|
||||
unsigned int actual_align;
|
||||
unsigned int user_align;
|
||||
/* The type of this field. */
|
||||
tree type = TREE_TYPE (field);
|
||||
|
||||
if (TREE_CODE (field) == ERROR_MARK || TREE_CODE (type) == ERROR_MARK)
|
||||
return;
|
||||
|
||||
/* If FIELD is static, then treat it like a separate variable, not
|
||||
really like a structure field. If it is a FUNCTION_DECL, it's a
|
||||
method. In both cases, all we do is lay out the decl, and we do
|
||||
it *after* the record is laid out. */
|
||||
if (TREE_CODE (field) == VAR_DECL)
|
||||
{
|
||||
rli->pending_statics = tree_cons (NULL_TREE, field,
|
||||
rli->pending_statics);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Enumerators and enum types which are local to this class need not
|
||||
be laid out. Likewise for initialized constant fields. */
|
||||
else if (TREE_CODE (field) != FIELD_DECL)
|
||||
return;
|
||||
|
||||
/* Unions are laid out very differently than records, so split
|
||||
that code off to another function. */
|
||||
else if (TREE_CODE (rli->t) != RECORD_TYPE)
|
||||
{
|
||||
place_union_field (rli, field);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Work out the known alignment so far. Note that A & (-A) is the
|
||||
value of the least-significant bit in A that is one. */
|
||||
if (! integer_zerop (rli->bitpos))
|
||||
known_align = (tree_low_cst (rli->bitpos, 1)
|
||||
& - tree_low_cst (rli->bitpos, 1));
|
||||
else if (integer_zerop (rli->offset))
|
||||
known_align = BIGGEST_ALIGNMENT;
|
||||
else if (host_integerp (rli->offset, 1))
|
||||
known_align = (BITS_PER_UNIT
|
||||
* (tree_low_cst (rli->offset, 1)
|
||||
& - tree_low_cst (rli->offset, 1)));
|
||||
else
|
||||
known_align = rli->offset_align;
|
||||
/* True if the field was explicitly aligned by the user. */
|
||||
bool user_align;
|
||||
|
||||
/* Lay out the field so we know what alignment it needs. For a
|
||||
packed field, use the alignment as specified, disregarding what
|
||||
@ -785,13 +681,13 @@ place_field (rli, field)
|
||||
to a lower boundary than alignment of variables unless
|
||||
it was overridden by attribute aligned. */
|
||||
#ifdef BIGGEST_FIELD_ALIGNMENT
|
||||
if (! user_align)
|
||||
if (!user_align)
|
||||
desired_align
|
||||
= MIN (desired_align, (unsigned) BIGGEST_FIELD_ALIGNMENT);
|
||||
#endif
|
||||
|
||||
#ifdef ADJUST_FIELD_ALIGN
|
||||
if (! user_align)
|
||||
if (!user_align)
|
||||
desired_align = ADJUST_FIELD_ALIGN (field, desired_align);
|
||||
#endif
|
||||
|
||||
@ -873,6 +769,96 @@ place_field (rli, field)
|
||||
rli->unpadded_align = MAX (rli->unpadded_align, DECL_ALIGN (field));
|
||||
}
|
||||
|
||||
TYPE_USER_ALIGN (rli->t) |= user_align;
|
||||
|
||||
return desired_align;
|
||||
}
|
||||
|
||||
/* Called from place_field to handle unions. */
|
||||
|
||||
static void
|
||||
place_union_field (rli, field)
|
||||
record_layout_info rli;
|
||||
tree field;
|
||||
{
|
||||
update_alignment_for_field (rli, field, /*known_align=*/0);
|
||||
|
||||
DECL_FIELD_OFFSET (field) = size_zero_node;
|
||||
DECL_FIELD_BIT_OFFSET (field) = bitsize_zero_node;
|
||||
SET_DECL_OFFSET_ALIGN (field, BIGGEST_ALIGNMENT);
|
||||
|
||||
/* We assume the union's size will be a multiple of a byte so we don't
|
||||
bother with BITPOS. */
|
||||
if (TREE_CODE (rli->t) == UNION_TYPE)
|
||||
rli->offset = size_binop (MAX_EXPR, rli->offset, DECL_SIZE_UNIT (field));
|
||||
else if (TREE_CODE (rli->t) == QUAL_UNION_TYPE)
|
||||
rli->offset = fold (build (COND_EXPR, sizetype,
|
||||
DECL_QUALIFIER (field),
|
||||
DECL_SIZE_UNIT (field), rli->offset));
|
||||
}
|
||||
|
||||
/* RLI contains information about the layout of a RECORD_TYPE. FIELD
|
||||
is a FIELD_DECL to be added after those fields already present in
|
||||
T. (FIELD is not actually added to the TYPE_FIELDS list here;
|
||||
callers that desire that behavior must manually perform that step.) */
|
||||
|
||||
void
|
||||
place_field (rli, field)
|
||||
record_layout_info rli;
|
||||
tree field;
|
||||
{
|
||||
/* The alignment required for FIELD. */
|
||||
unsigned int desired_align;
|
||||
/* The alignment FIELD would have if we just dropped it into the
|
||||
record as it presently stands. */
|
||||
unsigned int known_align;
|
||||
unsigned int actual_align;
|
||||
/* The type of this field. */
|
||||
tree type = TREE_TYPE (field);
|
||||
|
||||
if (TREE_CODE (field) == ERROR_MARK || TREE_CODE (type) == ERROR_MARK)
|
||||
return;
|
||||
|
||||
/* If FIELD is static, then treat it like a separate variable, not
|
||||
really like a structure field. If it is a FUNCTION_DECL, it's a
|
||||
method. In both cases, all we do is lay out the decl, and we do
|
||||
it *after* the record is laid out. */
|
||||
if (TREE_CODE (field) == VAR_DECL)
|
||||
{
|
||||
rli->pending_statics = tree_cons (NULL_TREE, field,
|
||||
rli->pending_statics);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Enumerators and enum types which are local to this class need not
|
||||
be laid out. Likewise for initialized constant fields. */
|
||||
else if (TREE_CODE (field) != FIELD_DECL)
|
||||
return;
|
||||
|
||||
/* Unions are laid out very differently than records, so split
|
||||
that code off to another function. */
|
||||
else if (TREE_CODE (rli->t) != RECORD_TYPE)
|
||||
{
|
||||
place_union_field (rli, field);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Work out the known alignment so far. Note that A & (-A) is the
|
||||
value of the least-significant bit in A that is one. */
|
||||
if (! integer_zerop (rli->bitpos))
|
||||
known_align = (tree_low_cst (rli->bitpos, 1)
|
||||
& - tree_low_cst (rli->bitpos, 1));
|
||||
else if (integer_zerop (rli->offset))
|
||||
known_align = BIGGEST_ALIGNMENT;
|
||||
else if (host_integerp (rli->offset, 1))
|
||||
known_align = (BITS_PER_UNIT
|
||||
* (tree_low_cst (rli->offset, 1)
|
||||
& - tree_low_cst (rli->offset, 1)));
|
||||
else
|
||||
known_align = rli->offset_align;
|
||||
|
||||
desired_align = update_alignment_for_field (rli, field, known_align);
|
||||
|
||||
if (warn_packed && DECL_PACKED (field))
|
||||
{
|
||||
if (known_align > TYPE_ALIGN (type))
|
||||
@ -956,7 +942,7 @@ place_field (rli, field)
|
||||
> tree_low_cst (TYPE_SIZE (type), 1) / type_align)
|
||||
rli->bitpos = round_up (rli->bitpos, type_align);
|
||||
|
||||
user_align |= TYPE_USER_ALIGN (type);
|
||||
TYPE_USER_ALIGN (rli->t) |= TYPE_USER_ALIGN (type);
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -999,7 +985,7 @@ place_field (rli, field)
|
||||
/ type_align))
|
||||
rli->bitpos = round_up (rli->bitpos, type_align);
|
||||
|
||||
user_align |= TYPE_USER_ALIGN (type);
|
||||
TYPE_USER_ALIGN (rli->t) |= TYPE_USER_ALIGN (type);
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -1153,8 +1139,6 @@ place_field (rli, field)
|
||||
DECL_FIELD_BIT_OFFSET (field) = rli->bitpos;
|
||||
SET_DECL_OFFSET_ALIGN (field, rli->offset_align);
|
||||
|
||||
TYPE_USER_ALIGN (rli->t) |= user_align;
|
||||
|
||||
/* If this field ended up more aligned than we thought it would be (we
|
||||
approximate this by seeing if its position changed), lay out the field
|
||||
again; perhaps we can use an integral mode for it now. */
|
||||
|
@ -1,5 +1,7 @@
|
||||
2002-10-01 Mark Mitchell <mark@codesourcery.com>
|
||||
|
||||
* gcc.dg/empty1.C: New test.
|
||||
|
||||
* g++.dg/tls/init-2.C: Tweak error messages.
|
||||
|
||||
2002-10-01 Richard Sandiford <rsandifo@redhat.com>
|
||||
|
10
gcc/testsuite/gcc.dg/empty1.c
Normal file
10
gcc/testsuite/gcc.dg/empty1.c
Normal file
@ -0,0 +1,10 @@
|
||||
/* { dg-do run } */
|
||||
/* { dg-options "" } */
|
||||
|
||||
struct S { int : 0; };
|
||||
union U { int : 0; };
|
||||
|
||||
int main () {
|
||||
if (__alignof__ (struct S) != __alignof__ (union U))
|
||||
return 1;
|
||||
}
|
Loading…
Reference in New Issue
Block a user