Merge pull request #2246 from acqn/ArrayFix
[cc65] Fixes for nested unspecified-length/flexible arrays
This commit is contained in:
@@ -514,7 +514,7 @@ void Compile (const char* FileName)
|
|||||||
|
|
||||||
/* Mark as defined; so that it will be exported, not imported */
|
/* Mark as defined; so that it will be exported, not imported */
|
||||||
Entry->Flags |= SC_DEF;
|
Entry->Flags |= SC_DEF;
|
||||||
} else {
|
} else if (!IsTypeArray (Entry->Type)) {
|
||||||
/* Tentative declared variable is still of incomplete type */
|
/* Tentative declared variable is still of incomplete type */
|
||||||
Error ("Definition of '%s' has type '%s' that is never completed",
|
Error ("Definition of '%s' has type '%s' that is never completed",
|
||||||
Entry->Name,
|
Entry->Name,
|
||||||
|
|||||||
@@ -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 */
|
/* Check if data type consists of arrays of incomplete element types */
|
||||||
{
|
{
|
||||||
Type* T = DataType;
|
|
||||||
|
|
||||||
while (T->C != T_END) {
|
while (T->C != T_END) {
|
||||||
if (IsTypeArray (T)) {
|
if (IsTypeArray (T)) {
|
||||||
++T;
|
/* If the array is multi-dimensional, keep going until we get the
|
||||||
if (IsIncompleteESUType (T)) {
|
** true element type.
|
||||||
/* 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)) {
|
++T;
|
||||||
continue;
|
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 */
|
/* 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'",
|
||||||
Error ("Array of 0-size element type '%s'", GetFullTypeName (T));
|
GetFullTypeName (T));
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (IsTypeStruct (T)) {
|
/* Elements cannot contain flexible array members themselves */
|
||||||
|
if (IsClassStruct (T)) {
|
||||||
SymEntry* TagEntry = GetESUTagSym (T);
|
SymEntry* TagEntry = GetESUTagSym (T);
|
||||||
if (TagEntry && SymHasFlexibleArrayMember (TagEntry)) {
|
if (TagEntry && SymHasFlexibleArrayMember (TagEntry)) {
|
||||||
Error ("Invalid use of struct with flexible array member");
|
Error ("Invalid use of struct with flexible array member");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1200,11 +1203,9 @@ static SymEntry* ParseStructSpec (const char* Name, unsigned* DSFlags)
|
|||||||
if (TagEntry && SymHasFlexibleArrayMember (TagEntry)) {
|
if (TagEntry && SymHasFlexibleArrayMember (TagEntry)) {
|
||||||
Field->Flags |= SC_HAVEFAM;
|
Field->Flags |= SC_HAVEFAM;
|
||||||
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");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (!FlexibleMember) {
|
if (!FlexibleMember) {
|
||||||
StructSize += SizeOf (Decl.Type);
|
StructSize += SizeOf (Decl.Type);
|
||||||
|
|||||||
@@ -5,7 +5,12 @@ typedef struct x {
|
|||||||
int b[]; /* Ok: Flexible array member can be last */
|
int b[]; /* Ok: Flexible array member can be last */
|
||||||
} x;
|
} x;
|
||||||
|
|
||||||
|
typedef union u {
|
||||||
|
int a;
|
||||||
|
x x; /* Ok: Union member can contain flexible array member */
|
||||||
|
} u;
|
||||||
|
|
||||||
struct y {
|
struct y {
|
||||||
x x; /* Not ok: Contains flexible array member */
|
u u; /* Not ok: Contains union that contains flexible array member */
|
||||||
int a;
|
int a;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,9 +1,13 @@
|
|||||||
/* Bug #2017 - cc65 erroneously allows arrays of structs with flexible array members */
|
/* Bug #2017 - cc65 erroneously allows arrays of structs with flexible array members */
|
||||||
|
|
||||||
struct z {
|
typedef struct x {
|
||||||
int a;
|
int a;
|
||||||
int c;
|
int b[]; /* Ok: Flexible array member can be last */
|
||||||
int b[];
|
} 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
6
test/err/zero-size.c
Normal 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
31
test/val/fam.c
Normal 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;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user