Several g++ tests in tmpdir-g++.dg-struct-layout-1 fail during the compilation with the error message like error: size of array 'foo' is too large with -mms-bitfields. A reduced testcase is typedef long int along __attribute__((aligned (32))); struct S { unsigned char a; along d:130; int e:66; } A[1]; It looks the ms-bitfield code in stor-layout.c doesn't take the bit field with excessive size into account and it makes the negative remaining_in_alignment which causes the above error.
I belive this is a bug in stor-layout.c:place_field() around line 10503 bitpos is calculated as bit_offset of rli->prev_field + type size. However, the prev_field is not really the immediately previous field but the first field of the consecutive same-sized fields. Hence, in this case: struct S { long long d:23; int e:32; int f:32; } a; rli->prev_field is "d" when "field" is f. The correct fix should calculate the bitpos as rli->bitpos + type size.
Oops. Mu previous comment is misplaced. It should have been on PR28161. Please ignore it.
The immediate cause of the problem is in stor-layout.c:place_field(): 1118 if (DECL_SIZE (field) != NULL 1119 && host_integerp (TYPE_SIZE (TREE_TYPE (field)), 0) 1120 && host_integerp (DECL_SIZE (field), 0)) 1121 rli->remaining_in_alignment 1122 = tree_low_cst (TYPE_SIZE (TREE_TYPE(field)), 1) 1123 - tree_low_cst (DECL_SIZE (field), 1); For the field "d", remiaining_in_alignment becomes negative after line 1121-1123 - because the DECL_SIZE is larger than TYPE_SIZE for "d".
Thanks for your comment. Perhaps one solution would be to handle such bit fields with excessive sizes as the case of "no remaining bits in alignment". I'm testing the appended patch which changes lines you've pointed out. --- ORIG/trunk/gcc/stor-layout.c 2006-06-13 09:06:36.000000000 +0900 +++ LOCAL/trunk/gcc/stor-layout.c 2006-06-26 16:43:12.000000000 +0900 @@ -1047,17 +1047,20 @@ place_field (record_layout_info rli, tre if (rli->remaining_in_alignment < bitsize) { + HOST_WIDE_INT typesize = tree_low_cst (TYPE_SIZE (type), 1); + /* out of bits; bump up to next 'word'. */ - rli->offset = DECL_FIELD_OFFSET (rli->prev_field); rli->bitpos - = size_binop (PLUS_EXPR, TYPE_SIZE (type), - DECL_FIELD_BIT_OFFSET (rli->prev_field)); + = size_binop (PLUS_EXPR, rli->bitpos, + bitsize_int (rli->remaining_in_alignment)); rli->prev_field = field; - rli->remaining_in_alignment - = tree_low_cst (TYPE_SIZE (type), 1); + if (typesize < bitsize) + rli->remaining_in_alignment = 0; + else + rli->remaining_in_alignment = typesize - bitsize; } - - rli->remaining_in_alignment -= bitsize; + else + rli->remaining_in_alignment -= bitsize; } else { @@ -1119,9 +1121,16 @@ place_field (record_layout_info rli, tre if (DECL_SIZE (field) != NULL && host_integerp (TYPE_SIZE (TREE_TYPE (field)), 0) && host_integerp (DECL_SIZE (field), 0)) - rli->remaining_in_alignment - = tree_low_cst (TYPE_SIZE (TREE_TYPE(field)), 1) - - tree_low_cst (DECL_SIZE (field), 1); + { + HOST_WIDE_INT bitsize = tree_low_cst (DECL_SIZE (field), 1); + HOST_WIDE_INT typesize + = tree_low_cst (TYPE_SIZE (TREE_TYPE (field)), 1); + + if (typesize < bitsize) + rli->remaining_in_alignment = 0; + else + rli->remaining_in_alignment = typesize - bitsize; + } /* Now align (conventionally) for the new type. */ type_align = TYPE_ALIGN (TREE_TYPE (field));
Subject: Bug number PR middle-end/28160 A patch for this bug has been added to the patch tracker. The mailing list url for the patch is http://gcc.gnu.org/ml/gcc-patches/2006-06/msg01472.html
Subject: Bug 28160 Author: kkojima Date: Sat Jul 15 06:58:57 2006 New Revision: 115464 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=115464 Log: PR middle-end/28160 * stor-layout.c (place_field): Take the bit field with an excessive size into account in the ms-bitfiled case. PR middle-end/28161 * stor-layout.c (place_field): Use DECL_BIT_FIELD_TYPE of the previous bit field. Modified: trunk/gcc/ChangeLog trunk/gcc/stor-layout.c
Fixed.