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

Merge pull request #2246 from acqn/ArrayFix

[cc65] Fixes for nested unspecified-length/flexible arrays
This commit is contained in:
Bob Andrews 2023-10-29 12:10:30 +01:00 committed by GitHub
commit f7cf14bf58
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 74 additions and 27 deletions

View File

@ -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,

View File

@ -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");
}
}

View File

@ -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;
};

View File

@ -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 */

6
test/err/zero-size.c Normal file
View File

@ -0,0 +1,6 @@
char a[][] = { 0, 0 }; /* Error: Array type has incomplete element type 'char[]' */
int main(void)
{
return 0;
}

31
test/val/fam.c Normal file
View File

@ -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;
}