From 0645ba8f0b34dbbce7a57dcf712cd0cb261edcc2 Mon Sep 17 00:00:00 2001 From: Mark Mitchell Date: Tue, 1 Oct 2002 18:44:49 +0000 Subject: [PATCH] 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 --- gcc/ChangeLog | 6 + gcc/stor-layout.c | 228 ++++++++++++++++------------------ gcc/testsuite/ChangeLog | 2 + gcc/testsuite/gcc.dg/empty1.c | 10 ++ 4 files changed, 124 insertions(+), 122 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/empty1.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index a8a44049391..a860318aa12 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2002-10-01 Mark Mitchell + + * stor-layout.c (update_alignment_for_field): New function. + (place_union_field): Use it. + (place_field): Likewise. + 2002-10-01 Nathan Sidwell * gcc.c (cc1_options): Add space on -auxbase-strip. diff --git a/gcc/stor-layout.c b/gcc/stor-layout.c index 953d58f75ca..dd37d955190 100644 --- a/gcc/stor-layout.c +++ b/gcc/stor-layout.c @@ -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. */ diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index f65519fb3ce..57d265fe7f6 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,7 @@ 2002-10-01 Mark Mitchell + * gcc.dg/empty1.C: New test. + * g++.dg/tls/init-2.C: Tweak error messages. 2002-10-01 Richard Sandiford diff --git a/gcc/testsuite/gcc.dg/empty1.c b/gcc/testsuite/gcc.dg/empty1.c new file mode 100644 index 00000000000..69f778c72b3 --- /dev/null +++ b/gcc/testsuite/gcc.dg/empty1.c @@ -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; +}