Hi, I added two testcases to this patch. So that we might detect regressions about this issue later more easily.
2012-12-12 Kai Tietz PR c/52991 * stor-layout.c (start_record_layout): Handle packed-attribute for ms-structure-layout. (update_alignment_for_field): Likewise. (place_field): Likewise. 2012-12-12 Kai Tietz PR c/52991 * gcc.dg/attr-ms_struct-packed2.c: New file. * gcc.dg/attr-ms_struct-packed3.c: New file. Ok for apply? Regards, Kai Index: gcc/gcc/stor-layout.c =================================================================== --- gcc.orig/gcc/stor-layout.c +++ gcc/gcc/stor-layout.c @@ -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); Index: gcc/gcc/testsuite/gcc.dg/attr-ms_struct-packed2.c =================================================================== --- /dev/null +++ gcc/gcc/testsuite/gcc.dg/attr-ms_struct-packed2.c @@ -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; +}