diff --git a/src/cc65/compile.c b/src/cc65/compile.c index 713e70d2a..a591a60b8 100644 --- a/src/cc65/compile.c +++ b/src/cc65/compile.c @@ -514,7 +514,7 @@ void Compile (const char* FileName) /* Mark as defined; so that it will be exported, not imported */ Entry->Flags |= SC_DEF; - } else { + } else if (!IsTypeArray (Entry->Type)) { /* Tentative declared variable is still of incomplete type */ Error ("Definition of '%s' has type '%s' that is never completed", Entry->Name, diff --git a/src/cc65/declare.c b/src/cc65/declare.c index cd174c92d..b09c2ea17 100644 --- a/src/cc65/declare.c +++ b/src/cc65/declare.c @@ -493,33 +493,36 @@ static void FixQualifiers (Type* DataType) -static void CheckArrayElementType (Type* DataType) +static void CheckArrayElementType (const Type* T) /* Check if data type consists of arrays of incomplete element types */ { - Type* T = DataType; - while (T->C != T_END) { if (IsTypeArray (T)) { + /* If the array is multi-dimensional, keep going until we get the + ** true element type. + */ ++T; - if (IsIncompleteESUType (T)) { - /* We cannot have an array of incomplete elements */ - Error ("Array of incomplete element type '%s'", GetFullTypeName (T)); - } else if (SizeOf (T) == 0) { - /* If the array is multi-dimensional, try to get the true - ** element type. - */ - if (IsTypeArray (T)) { - continue; - } - /* We could support certain 0-size element types as an extension */ - if (!IsTypeVoid (T) || IS_Get (&Standard) != STD_CC65) { - Error ("Array of 0-size element type '%s'", GetFullTypeName (T)); + if (SizeOf (T) == 0) { + if (IsTypeArray (T) || IsIncompleteESUType (T)) { + /* We cannot have an array of incomplete elements */ + if (!IsTypeArray (T) || GetElementCount (T) == UNSPECIFIED) { + Error ("Array of incomplete element type '%s'", + GetFullTypeName (T)); + return; + } + } else if (!IsTypeVoid (T) || IS_Get (&Standard) != STD_CC65) { + /* We could support certain 0-size element types as an extension */ + Error ("Array of 0-size element type '%s'", + GetFullTypeName (T)); + return; } } else { - if (IsTypeStruct (T)) { + /* Elements cannot contain flexible array members themselves */ + if (IsClassStruct (T)) { SymEntry* TagEntry = GetESUTagSym (T); if (TagEntry && SymHasFlexibleArrayMember (TagEntry)) { Error ("Invalid use of struct with flexible array member"); + return; } } } @@ -1200,9 +1203,7 @@ static SymEntry* ParseStructSpec (const char* Name, unsigned* DSFlags) if (TagEntry && SymHasFlexibleArrayMember (TagEntry)) { Field->Flags |= SC_HAVEFAM; Flags |= SC_HAVEFAM; - if (IsTypeStruct (Decl.Type)) { - Error ("Invalid use of struct with flexible array member"); - } + Error ("Invalid use of struct with flexible array member"); } } diff --git a/test/err/bug2016-fam-member.c b/test/err/bug2016-fam-member.c index 02c9ec275..473aae702 100644 --- a/test/err/bug2016-fam-member.c +++ b/test/err/bug2016-fam-member.c @@ -5,7 +5,12 @@ typedef struct x { int b[]; /* Ok: Flexible array member can be last */ } x; +typedef union u { + int a; + x x; /* Ok: Union member can contain flexible array member */ +} u; + struct y { - x x; /* Not ok: Contains flexible array member */ + u u; /* Not ok: Contains union that contains flexible array member */ int a; }; diff --git a/test/err/bug2017-fam-element.c b/test/err/bug2017-fam-element.c index 195ca6597..c97ae42ec 100644 --- a/test/err/bug2017-fam-element.c +++ b/test/err/bug2017-fam-element.c @@ -1,9 +1,13 @@ /* Bug #2017 - cc65 erroneously allows arrays of structs with flexible array members */ -struct z { +typedef struct x { int a; - int c; - int b[]; -}; + int b[]; /* Ok: Flexible array member can be last */ +} x; -struct z y[3]; /* Should be an error */ +typedef union u { + int a; + x x; /* Ok: Union member can contain flexible array member */ +} u; + +union u y[3]; /* Should be an error */ diff --git a/test/err/zero-size.c b/test/err/zero-size.c new file mode 100644 index 000000000..9e7510c91 --- /dev/null +++ b/test/err/zero-size.c @@ -0,0 +1,6 @@ +char a[][] = { 0, 0 }; /* Error: Array type has incomplete element type 'char[]' */ + +int main(void) +{ + return 0; +} diff --git a/test/val/fam.c b/test/val/fam.c new file mode 100644 index 000000000..df5df2876 --- /dev/null +++ b/test/val/fam.c @@ -0,0 +1,31 @@ +/* Bug #2016 and #2017 - flexible array members */ + +typedef struct { + int a; + int b[]; /* Ok: Flexible array member can be last */ +} X; + +typedef union { + X x; /* Ok: Contains flexible array member */ + int a; +} U; + +typedef struct { + struct { + int a; + }; + int b[]; /* Ok: Flexible array member can be last */ +} Y; + +X x; +U u; +Y y; + +_Static_assert(sizeof x == sizeof (int), "sizeof x != sizeof (int)"); +_Static_assert(sizeof u == sizeof (int), "sizeof u != sizeof (int)"); +_Static_assert(sizeof y == sizeof (int), "sizeof y != sizeof (int)"); + +int main(void) +{ + return 0; +}