1
0
mirror of https://github.com/cc65/cc65.git synced 2024-06-07 23:29:39 +00:00

Fixed initialization of union when it has an anonymous bit-field as the first member declaration.

This commit is contained in:
acqn 2023-11-15 21:32:24 +08:00
parent 5537b61e6a
commit 3b7af398a9
2 changed files with 27 additions and 20 deletions

View File

@ -511,18 +511,20 @@ static unsigned ParseStructInit (Type* T, int* Braces, int AllowFlexibleMembers)
/* This may be an anonymous bit-field, in which case it doesn't /* This may be an anonymous bit-field, in which case it doesn't
** have an initializer. ** have an initializer.
*/ */
if (SymIsBitField (TagSym) && (IsAnonName (TagSym->Name))) { if (SymIsBitField (TagSym) && IsAnonName (TagSym->Name)) {
/* Account for the data and output it if we have at least a full if (!IsTypeUnion (T)) {
** byte. We may have more if there was storage unit overlap, for /* Account for the data and output it if we have at least a full
** example two consecutive 7 bit fields. Those would be packed ** byte. We may have more if there was storage unit overlap, for
** into 2 bytes. ** example two consecutive 7 bit fields. Those would be packed
*/ ** into 2 bytes.
SI.ValBits += TagSym->Type->A.B.Width; */
CHECK (SI.ValBits <= CHAR_BIT * sizeof(SI.BitVal)); SI.ValBits += TagSym->Type->A.B.Width;
/* TODO: Generalize this so any type can be used. */ CHECK (SI.ValBits <= CHAR_BIT * sizeof(SI.BitVal));
CHECK (SI.ValBits <= LONG_BITS); /* TODO: Generalize this so any type can be used. */
while (SI.ValBits >= CHAR_BITS) { CHECK (SI.ValBits <= LONG_BITS);
DefineBitFieldData (&SI); while (SI.ValBits >= CHAR_BITS) {
DefineBitFieldData (&SI);
}
} }
/* Avoid consuming the comma if any */ /* Avoid consuming the comma if any */
goto NextMember; goto NextMember;
@ -628,15 +630,15 @@ static unsigned ParseStructInit (Type* T, int* Braces, int AllowFlexibleMembers)
/* Skip the comma next round */ /* Skip the comma next round */
SkipComma = 1; SkipComma = 1;
NextMember: /* For unions, only the first named member can be initialized */
/* Next member. For unions, only the first one can be initialized */
if (IsTypeUnion (T)) { if (IsTypeUnion (T)) {
/* Union */
TagSym = 0; TagSym = 0;
} else { continue;
/* Struct */
TagSym = TagSym->NextSym;
} }
NextMember:
/* Next member */
TagSym = TagSym->NextSym;
} }
if (HasCurly) { if (HasCurly) {

View File

@ -1,5 +1,5 @@
/* /*
Copyright 2020 The cc65 Authors Copyright 2020-2023 The cc65 Authors
This software is provided 'as-is', without any express or implied This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages warranty. In no event will the authors be held liable for any damages
@ -25,6 +25,7 @@
#include <stdio.h> #include <stdio.h>
typedef union { typedef union {
const unsigned int : 1;
unsigned int bf; unsigned int bf;
struct { struct {
@ -38,8 +39,12 @@ static unsigned char failures = 0;
int main (void) int main (void)
{ {
bitfield_t bitfield = {0}; bitfield_t bitfield = { 42 };
printf ("Bitfield: %u\n", bitfield.bf);
if (bitfield.bf != 42) failures++;
bitfield.bf ^= 42;
printf ("Bitfield: %u\n", bitfield.bf); printf ("Bitfield: %u\n", bitfield.bf);
if (bitfield.bf != 0) failures++; if (bitfield.bf != 0) failures++;