===================================================================
@@ -756,7 +756,10 @@ start_record_layout (tree t)
/* If the type has a minimum specified alignment (via an attribute
declaration, for example) use it -- otherwise, start with a
one-byte alignment. */
- rli->record_align = MAX (BITS_PER_UNIT, TYPE_ALIGN (t));
+ if (TYPE_PACKED (t))
+ rli->record_align = BITS_PER_UNIT;
+ else
+ rli->record_align = MAX (BITS_PER_UNIT, TYPE_ALIGN (t));
rli->unpacked_align = rli->record_align;
rli->offset_align = MAX (rli->record_align, BIGGEST_ALIGNMENT);
@@ -952,15 +955,20 @@ update_alignment_for_field (record_layou
meaningless. */
if (targetm.ms_bitfield_layout_p (rli->t))
{
+ if (rli->t && TYPE_PACKED (rli->t)
+ && (is_bitfield || !DECL_PACKED (field)
+ || DECL_SIZE (field) == NULL_TREE
+ || !integer_zerop (DECL_SIZE (field))))
+ desired_align = BITS_PER_UNIT;
/* Here, the alignment of the underlying type of a bitfield can
affect the alignment of a record; even a zero-sized field
can do this. The alignment should be to the alignment of
the type, except that for zero-size bitfields this only
applies if there was an immediately prior, nonzero-size
bitfield. (That's the way it is, experimentally.) */
- if ((!is_bitfield && !DECL_PACKED (field))
- || ((DECL_SIZE (field) == NULL_TREE
- || !integer_zerop (DECL_SIZE (field)))
+ else if ((!is_bitfield && !DECL_PACKED (field))
+ || ((DECL_SIZE (field) == NULL_TREE
+ || !integer_zerop (DECL_SIZE (field)))
? !DECL_PACKED (field)
: (rli->prev_field
&& DECL_BIT_FIELD_TYPE (rli->prev_field)
@@ -1414,7 +1422,12 @@ place_field (record_layout_info rli, tre
}
/* Now align (conventionally) for the new type. */
- type_align = TYPE_ALIGN (TREE_TYPE (field));
+ if (!TYPE_PACKED (rli->t))
+ {
+ type_align = TYPE_ALIGN (TREE_TYPE (field));
+ if (DECL_PACKED (field))
+ type_align = MIN (type_align, BITS_PER_UNIT);
+ }
if (maximum_field_alignment != 0)
type_align = MIN (type_align, maximum_field_alignment);
===================================================================
@@ -0,0 +1,31 @@
+/* Test for MS structure with packed attribute. */
+/* { dg-do run { target *-*-interix* *-*-mingw* *-*-cygwin*
i?86-*-darwin* i?86-*-linux* x86_64-*-linux* } }
+/* { dg-options "-std=gnu99" } */
+
+extern void abort ();
+
+struct A {
+ short s;
+ struct { int i; } __attribute__((__ms_struct__));
+} __attribute__((__ms_struct__, __packed__));
+
+struct B {
+ short s;
+ struct { int i; } __attribute__((__ms_struct__, __packed__));
+} __attribute__((__ms_struct__, __packed__));
+
+struct C {
+ struct { int i; } __attribute__((__ms_struct__));
+ short s;
+} __attribute__((__ms_struct__, __packed__));
+
+int
+main (void)
+{
+ if (sizeof (struct C) != sizeof (struct B)
+ || sizeof (struct A) != sizeof (struct B)
+ || sizeof (struct B) != 6)
+ abort ();
+
+ return 0;