diff --git a/src/cc65/declare.c b/src/cc65/declare.c index ccea0098a..6615998ce 100644 --- a/src/cc65/declare.c +++ b/src/cc65/declare.c @@ -983,33 +983,36 @@ static SymEntry* ParseUnionSpec (const char* Name, unsigned* DSFlags) /* Check for a bit-field declaration */ FieldWidth = ParseFieldWidth (&Decl); - /* Ignore zero sized bit fields in a union */ - if (FieldWidth == 0) { - goto NextMember; - } - - /* Check for fields without a name */ + /* Check for fields without names */ if (Decl.Ident[0] == '\0') { - /* In cc65 mode, we allow anonymous structs/unions within - ** a union. - */ - if (IS_Get (&Standard) >= STD_CC65 && IsClassStruct (Decl.Type)) { - /* This is an anonymous struct or union */ - AnonFieldName (Decl.Ident, GetBasicTypeName (Decl.Type), UnionTagEntry->V.S.ACount); + if (FieldWidth < 0) { + /* In cc65 mode, we allow anonymous structs/unions within + ** a union. + */ + SymEntry* TagEntry; + if (IS_Get (&Standard) >= STD_CC65 && + IsClassStruct (Decl.Type) && + (TagEntry = GetESUTagSym (Decl.Type)) && + SymHasAnonName (TagEntry)) { + /* This is an anonymous struct or union */ + AnonFieldName (Decl.Ident, GetBasicTypeName (Decl.Type), UnionTagEntry->V.S.ACount); - /* Ignore CVR qualifiers */ - if (IsQualConst (Decl.Type) || IsQualVolatile (Decl.Type) || IsQualRestrict (Decl.Type)) { - Warning ("Anonymous %s qualifiers are ignored", GetBasicTypeName (Decl.Type)); - Decl.Type[0].C &= ~T_QUAL_CVR; + /* Ignore CVR qualifiers */ + if (IsQualConst (Decl.Type) || IsQualVolatile (Decl.Type) || IsQualRestrict (Decl.Type)) { + Warning ("Anonymous %s qualifiers are ignored", GetBasicTypeName (Decl.Type)); + Decl.Type[0].C &= ~T_QUAL_CVR; + } + } else { + /* A non bit-field without a name is legal but useless */ + Warning ("Declaration does not declare anything"); + + goto NextMember; } - } else { - /* A non bit-field without a name is legal but useless */ - Warning ("Declaration does not declare anything"); + } else if (FieldWidth > 0) { + /* A bit-field without a name will get an anonymous one */ + AnonName (Decl.Ident, "bit-field"); } - } - - /* Check for incomplete types including 'void' */ - if (IsIncompleteType (Decl.Type)) { + } else if (IsIncompleteType (Decl.Type)) { Error ("Field '%s' has incomplete type '%s'", Decl.Ident, GetFullTypeName (Decl.Type)); @@ -1020,6 +1023,11 @@ static SymEntry* ParseUnionSpec (const char* Name, unsigned* DSFlags) Flags |= SC_HAVECONST; } + /* Ignore zero sized bit fields in a union */ + if (FieldWidth == 0) { + goto NextMember; + } + /* Handle sizes */ FieldSize = SizeOf (Decl.Type); if (FieldSize > UnionSize) { @@ -1180,36 +1188,17 @@ static SymEntry* ParseStructSpec (const char* Name, unsigned* DSFlags) } } - /* Apart from the above, a bit field with width 0 is not processed - ** further. - */ - if (FieldWidth == 0) { - goto NextMember; - } - - /* Check if this field is a flexible array member, and - ** calculate the size of the field. - */ - if (IsTypeArray (Decl.Type) && GetElementCount (Decl.Type) == UNSPECIFIED) { - /* Array with unspecified size */ - if (StructSize == 0) { - Error ("Flexible array member cannot be first struct field"); - } - FlexibleMember = 1; - Flags |= SC_HAVEFAM; - - /* Assume zero for size calculations */ - SetElementCount (Decl.Type, FLEXIBLE); - } - /* Check for fields without names */ if (Decl.Ident[0] == '\0') { if (FieldWidth < 0) { /* In cc65 mode, we allow anonymous structs/unions within ** a struct. */ - if (IS_Get (&Standard) >= STD_CC65 && IsClassStruct (Decl.Type)) { - + SymEntry* TagEntry; + if (IS_Get (&Standard) >= STD_CC65 && + IsClassStruct (Decl.Type) && + (TagEntry = GetESUTagSym (Decl.Type)) && + SymHasAnonName (TagEntry)) { /* This is an anonymous struct or union */ AnonFieldName (Decl.Ident, GetBasicTypeName (Decl.Type), StructTagEntry->V.S.ACount); @@ -1221,18 +1210,34 @@ static SymEntry* ParseStructSpec (const char* Name, unsigned* DSFlags) } else { /* A non bit-field without a name is legal but useless */ Warning ("Declaration does not declare anything"); + + goto NextMember; } - } else { + } else if (FieldWidth > 0) { /* A bit-field without a name will get an anonymous one */ AnonName (Decl.Ident, "bit-field"); } - } + } else { + /* Check if this field is a flexible array member, and + ** calculate the size of the field. + */ + if (IsTypeArray (Decl.Type) && GetElementCount (Decl.Type) == UNSPECIFIED) { + /* Array with unspecified size */ + if (StructSize == 0) { + Error ("Flexible array member cannot be first struct field"); + } + FlexibleMember = 1; + Flags |= SC_HAVEFAM; - /* Check for incomplete types including 'void' */ - if (IsIncompleteType (Decl.Type)) { - Error ("Field '%s' has incomplete type '%s'", - Decl.Ident, - GetFullTypeName (Decl.Type)); + /* Assume zero for size calculations */ + SetElementCount (Decl.Type, FLEXIBLE); + } + + if (IsIncompleteType (Decl.Type)) { + Error ("Field '%s' has incomplete type '%s'", + Decl.Ident, + GetFullTypeName (Decl.Type)); + } } /* Check for const types */ @@ -1240,6 +1245,13 @@ static SymEntry* ParseStructSpec (const char* Name, unsigned* DSFlags) Flags |= SC_HAVECONST; } + /* Apart from the above, a bit field with width 0 is not processed + ** further. + */ + if (FieldWidth == 0) { + goto NextMember; + } + /* Add a field entry to the table */ if (FieldWidth > 0) { /* Full bytes have already been added to the StructSize, diff --git a/test/val/bug2018-ok.c b/test/val/bug2018-ok.c index 7046e1d1f..567beb301 100644 --- a/test/val/bug2018-ok.c +++ b/test/val/bug2018-ok.c @@ -5,6 +5,11 @@ unsigned failures; struct X { + const int; /* Useless empty declaration */ + const void; /* Useless empty declaration */ + const struct U; /* Useless(?) declaration */ + const struct V { int a; }; /* Useless(?) declaration */ + const struct { /* Qualifier ignored in cc65 */ int a; }; @@ -14,6 +19,11 @@ struct X { }; union Y { + const int; /* Useless empty declaration */ + const void; /* Useless empty declaration */ + const union W; /* Useless(?) declaration */ + const union T { int a; }; /* Useless(?) declaration */ + const struct { /* Qualifier ignored in cc65 */ int a; };