Fix bitfields init : tiny solution

tccgen.c: Check struct/union size for bitfield.
tests/tcctest.c: Add test code.
This commit is contained in:
herman ten brugge 2020-09-25 12:23:48 +02:00
parent 89ea62481d
commit 8fd7a384e2
2 changed files with 9 additions and 3 deletions

View file

@ -7339,7 +7339,7 @@ static void init_putz(Section *sec, unsigned long c, int size)
'al' contains the already initialized length of the 'al' contains the already initialized length of the
current container (starting at c). This returns the new length of that. */ current container (starting at c). This returns the new length of that. */
static int decl_designator(CType *type, Section *sec, unsigned long c, static int decl_designator(CType *type, Section *sec, unsigned long c,
Sym **cur_field, int flags, int al) Sym **cur_field, int flags, int al, int size)
{ {
Sym *s, *f; Sym *s, *f;
int index, index_last, align, l, nb_elems, elem_size; int index, index_last, align, l, nb_elems, elem_size;
@ -7428,8 +7428,11 @@ static int decl_designator(CType *type, Section *sec, unsigned long c,
ensures that it even works with designators) */ ensures that it even works with designators) */
if (!(flags & DIF_SIZE_ONLY)) { if (!(flags & DIF_SIZE_ONLY)) {
int zlen = c - (corig + al); int zlen = c - (corig + al);
if (type->t & VT_BITFIELD) /* must include current field too */ if (type->t & VT_BITFIELD) { /* must include current field too */
zlen += type_size(type, &align); zlen += type_size(type, &align);
if (al + zlen > size)
zlen = size - al;
}
if (zlen > 0) if (zlen > 0)
init_putz(sec, corig + al, zlen); init_putz(sec, corig + al, zlen);
} }
@ -7783,7 +7786,7 @@ static void decl_initializer(CType *type, Section *sec, unsigned long c,
do_init_list: do_init_list:
len = 0; len = 0;
while (tok != '}' || (flags & DIF_HAVE_ELEM)) { while (tok != '}' || (flags & DIF_HAVE_ELEM)) {
len = decl_designator(type, sec, c, &f, flags, len); len = decl_designator(type, sec, c, &f, flags, len, n*size1);
flags &= ~DIF_HAVE_ELEM; flags &= ~DIF_HAVE_ELEM;
if (type->t & VT_ARRAY) { if (type->t & VT_ARRAY) {
++indexsym.c; ++indexsym.c;

View file

@ -1746,6 +1746,8 @@ struct bfa_SS {int a,b; struct bf_SS c[3]; int d,e; };
struct bfa_SS bfa_init = { .c[1].bit = 1 }; struct bfa_SS bfa_init = { .c[1].bit = 1 };
struct bf_SS bfaa_init[3] = { [1].bit = 1 }; struct bf_SS bfaa_init[3] = { [1].bit = 1 };
struct bf_SS bfaa_vinit[] = { [2].bit = 1 }; struct bf_SS bfaa_vinit[] = { [2].bit = 1 };
struct b2_SS {long long int field : 52; long long int pad : 12; };
struct b2_SS bf_init2 = {0xFFF000FFF000FLL, 0x123};
extern int external_inited = 42; extern int external_inited = 42;
@ -1771,6 +1773,7 @@ void init_test(void)
struct bfa_SS bfa_finit = { .c[1].bit = 1 }; struct bfa_SS bfa_finit = { .c[1].bit = 1 };
struct bf_SS bfaa_finit[3] = { [1].bit = 1 }; struct bf_SS bfaa_finit[3] = { [1].bit = 1 };
struct bf_SS bfaa_fvinit[] = { [2].bit = 1 }; struct bf_SS bfaa_fvinit[] = { [2].bit = 1 };
struct b2_SS bf_finit2 = {0xFFF000FFF000FLL, 0x123};
printf("sinit1=%d\n", sinit1); printf("sinit1=%d\n", sinit1);
printf("sinit2=%d\n", sinit2); printf("sinit2=%d\n", sinit2);