From 85e63e99a66e71c561aaf6b5fdb5d794bf89acf8 Mon Sep 17 00:00:00 2001 From: acqn Date: Fri, 27 Oct 2023 21:51:45 +0800 Subject: [PATCH 1/2] Fixed regression: array element of incomplete type. --- src/cc65/compile.c | 2 +- src/cc65/declare.c | 34 ++++++++++++++++++---------------- test/err/zero-size.c | 6 ++++++ 3 files changed, 25 insertions(+), 17 deletions(-) create mode 100644 test/err/zero-size.c diff --git a/src/cc65/compile.c b/src/cc65/compile.c index 9d7fbe20a..edd00022c 100644 --- a/src/cc65/compile.c +++ b/src/cc65/compile.c @@ -511,7 +511,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..cf9c13059 100644 --- a/src/cc65/declare.c +++ b/src/cc65/declare.c @@ -493,33 +493,35 @@ 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)) { SymEntry* TagEntry = GetESUTagSym (T); if (TagEntry && SymHasFlexibleArrayMember (TagEntry)) { Error ("Invalid use of struct with flexible array member"); + return; } } } 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; +} From 8e45a4c960b2366a0c6d1d83539be3b029b1bcbe Mon Sep 17 00:00:00 2001 From: acqn Date: Fri, 27 Oct 2023 23:46:10 +0800 Subject: [PATCH 2/2] Fixed the bug that a union type containing a struct with a flexible array member was accepted as a struct member or array element type. --- src/cc65/declare.c | 7 +++---- test/err/bug2016-fam-member.c | 7 ++++++- test/err/bug2017-fam-element.c | 14 +++++++++----- test/val/fam.c | 31 +++++++++++++++++++++++++++++++ 4 files changed, 49 insertions(+), 10 deletions(-) create mode 100644 test/val/fam.c diff --git a/src/cc65/declare.c b/src/cc65/declare.c index cf9c13059..b09c2ea17 100644 --- a/src/cc65/declare.c +++ b/src/cc65/declare.c @@ -517,7 +517,8 @@ static void CheckArrayElementType (const Type* 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"); @@ -1202,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/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; +}