https://gcc.gnu.org/bugzilla/show_bug.cgi?id=52991
--- Comment #28 from Jakub Jelinek <jakub at gcc dot gnu.org> --- Trying: --- gcc/stor-layout.c.jj 2018-02-22 14:35:33.135216198 +0100 +++ gcc/stor-layout.c 2018-02-27 17:32:17.934820133 +0100 @@ -1038,7 +1038,7 @@ update_alignment_for_field (record_layou 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)) + if (!is_bitfield || ((DECL_SIZE (field) == NULL_TREE || !integer_zerop (DECL_SIZE (field))) ? !DECL_PACKED (field) @@ -1047,7 +1047,10 @@ update_alignment_for_field (record_layou && ! integer_zerop (DECL_SIZE (rli->prev_field))))) { unsigned int type_align = TYPE_ALIGN (type); - type_align = MAX (type_align, desired_align); + if (!is_bitfield && DECL_PACKED (field)) + type_align = desired_align; + else + type_align = MAX (type_align, desired_align); if (maximum_field_alignment != 0) type_align = MIN (type_align, maximum_field_alignment); rli->record_align = MAX (rli->record_align, type_align); @@ -1303,7 +1306,9 @@ place_field (record_layout_info rli, tre /* Does this field automatically have alignment it needs by virtue of the fields that precede it and the record's own alignment? */ - if (known_align < desired_align) + if (known_align < desired_align + && (! targetm.ms_bitfield_layout_p (rli->t) + || rli->prev_field == NULL)) { /* No, we need to skip space before this field. Bump the cumulative size to multiple of field alignment. */ @@ -1331,8 +1336,6 @@ place_field (record_layout_info rli, tre if (! TREE_CONSTANT (rli->offset)) rli->offset_align = desired_align; - if (targetm.ms_bitfield_layout_p (rli->t)) - rli->prev_field = NULL; } /* Handle compatibility with PCC. Note that if the record has any @@ -1505,6 +1508,31 @@ place_field (record_layout_info rli, tre as if the prior field was not a bitfield. */ prev_saved = NULL; + /* Does this field automatically have alignment it needs by virtue + of the fields that precede it and the record's own alignment? */ + if (known_align < desired_align) + { + /* If the alignment is still within offset_align, just align + the bit position. */ + if (desired_align < rli->offset_align) + rli->bitpos = round_up (rli->bitpos, desired_align); + else + { + /* First adjust OFFSET by the partial bits, then align. */ + tree d = size_binop (CEIL_DIV_EXPR, rli->bitpos, + bitsize_unit_node); + rli->offset = size_binop (PLUS_EXPR, rli->offset, + fold_convert (sizetype, d)); + rli->bitpos = bitsize_zero_node; + + rli->offset = round_up (rli->offset, + desired_align / BITS_PER_UNIT); + } + + if (! TREE_CONSTANT (rli->offset)) + rli->offset_align = desired_align; + } + /* Cause a new bitfield to be captured, either this time (if currently a bitfield) or next time we see one. */ if (!DECL_BIT_FIELD_TYPE (field) @@ -1530,7 +1558,7 @@ place_field (record_layout_info rli, tre if (!DECL_BIT_FIELD_TYPE (field) || (prev_saved != NULL ? !simple_cst_equal (TYPE_SIZE (type), TYPE_SIZE (prev_type)) - : !integer_zerop (DECL_SIZE (field)) )) + : !integer_zerop (DECL_SIZE (field)))) { /* Never smaller than a byte for compatibility. */ unsigned int type_align = BITS_PER_UNIT; @@ -1555,7 +1583,8 @@ place_field (record_layout_info rli, tre } /* Now align (conventionally) for the new type. */ - type_align = TYPE_ALIGN (TREE_TYPE (field)); + if (! DECL_PACKED (field)) + type_align = TYPE_ALIGN (TREE_TYPE (field)); if (maximum_field_alignment != 0) type_align = MIN (type_align, maximum_field_alignment); fixes this testcase, but breaks bf-ms-layout.c and bf-ms-layout-2.c. The tests were adjusted in r186880 and r184519, but perhaps those were just bogus changes. I guess what matters more is whether the layout in those tests and in the above tests match what VC does.