From 632da3f4eefc6675484fc547b34c525983ba9d34 Mon Sep 17 00:00:00 2001 From: acqn Date: Sat, 15 Aug 2020 06:27:11 +0800 Subject: [PATCH] Fixed tracking and checking flexible array members. --- src/cc65/declare.c | 45 ++++++++++++++++++++++++++++++++++----------- src/cc65/symentry.h | 11 +++++++++++ 2 files changed, 45 insertions(+), 11 deletions(-) diff --git a/src/cc65/declare.c b/src/cc65/declare.c index 0bfbcedd2..d7851bd44 100644 --- a/src/cc65/declare.c +++ b/src/cc65/declare.c @@ -963,12 +963,19 @@ static SymEntry* ParseUnionDecl (const char* Name) AddBitField (Decl.Ident, Decl.Type, 0, 0, FieldWidth, SignednessSpecified); } else { + Entry = AddLocalSym (Decl.Ident, Decl.Type, SC_STRUCTFIELD, 0); if (IsAnonName (Decl.Ident)) { - Entry = AddLocalSym (Decl.Ident, Decl.Type, SC_STRUCTFIELD, 0); Entry->V.A.ANumber = UnionTagEntry->V.S.ACount++; AliasAnonStructFields (&Decl, Entry); - } else { - AddLocalSym (Decl.Ident, Decl.Type, SC_STRUCTFIELD, 0); + } + + /* Check if the field itself has a flexible array member */ + if (IsClassStruct (Decl.Type)) { + SymEntry* Sym = GetSymType (Decl.Type); + if (Sym && SymHasFlexibleArrayMember (Sym)) { + Entry->Flags |= SC_HAVEFAM; + Flags |= SC_HAVEFAM; + } } } @@ -1107,6 +1114,8 @@ static SymEntry* ParseStructDecl (const char* Name) Error ("Flexible array member cannot be first struct field"); } FlexibleMember = 1; + Flags |= SC_HAVEFAM; + /* Assume zero for size calculations */ SetElementCount (Decl.Type, FLEXIBLE); } @@ -1156,13 +1165,21 @@ static SymEntry* ParseStructDecl (const char* Name) StructSize += BitOffs / CHAR_BITS; BitOffs %= CHAR_BITS; } else { + Entry = AddLocalSym (Decl.Ident, Decl.Type, SC_STRUCTFIELD, StructSize); if (IsAnonName (Decl.Ident)) { - Entry = AddLocalSym (Decl.Ident, Decl.Type, SC_STRUCTFIELD, StructSize); Entry->V.A.ANumber = StructTagEntry->V.S.ACount++; AliasAnonStructFields (&Decl, Entry); - } else { - AddLocalSym (Decl.Ident, Decl.Type, SC_STRUCTFIELD, StructSize); } + + /* Check if the field itself has a flexible array member */ + if (IsClassStruct (Decl.Type)) { + SymEntry* Sym = GetSymType (Decl.Type); + if (Sym && SymHasFlexibleArrayMember (Sym)) { + Entry->Flags |= SC_HAVEFAM; + Flags |= SC_HAVEFAM; + } + } + if (!FlexibleMember) { StructSize += SizeOf (Decl.Type); } @@ -2361,11 +2378,17 @@ static unsigned ParseArrayInit (Type* T, int* Braces, int AllowFlexibleMembers) /* Number of elements determined by initializer */ SetElementCount (T, Count); ElementCount = Count; - } else if (ElementCount == FLEXIBLE && AllowFlexibleMembers) { - /* In non ANSI mode, allow initialization of flexible array - ** members. - */ - ElementCount = Count; + } else if (ElementCount == FLEXIBLE) { + if (AllowFlexibleMembers) { + /* In non ANSI mode, allow initialization of flexible array + ** members. + */ + ElementCount = Count; + } else { + /* Forbid */ + Error ("Initializing flexible array member is forbidden"); + ElementCount = Count; + } } else if (Count < ElementCount) { g_zerobytes ((ElementCount - Count) * ElementSize); } else if (Count > ElementCount && HasCurly) { diff --git a/src/cc65/symentry.h b/src/cc65/symentry.h index 94fe66032..0224507ac 100644 --- a/src/cc65/symentry.h +++ b/src/cc65/symentry.h @@ -107,6 +107,7 @@ struct CodeEntry; #define SC_ALIAS 0x01000000U /* Alias of anonymous field */ #define SC_FICTITIOUS 0x02000000U /* Symbol is fictitious */ +#define SC_HAVEFAM 0x04000000U /* Type has a Flexible Array Member */ @@ -272,6 +273,16 @@ INLINE int SymIsRegVar (const SymEntry* Sym) int SymIsOutputFunc (const SymEntry* Sym); /* Return true if this is a function that must be output */ +#if defined(HAVE_INLINE) +INLINE int SymHasFlexibleArrayMember (const SymEntry* Sym) +/* Return true if the given entry has a flexible array member */ +{ + return ((Sym->Flags & SC_HAVEFAM) == SC_HAVEFAM); +} +#else +# define SymHasFlexibleArrayMember(Sym) (((Sym)->Flags & SC_HAVEFAM) == SC_HAVEFAM) +#endif + #if defined(HAVE_INLINE) INLINE const char* SymGetAsmName (const SymEntry* Sym) /* Return the assembler label name for the symbol (beware: may be NULL!) */