Fixed tracking and checking flexible array members.

This commit is contained in:
acqn
2020-08-15 06:27:11 +08:00
committed by Oliver Schmidt
parent f54e01781b
commit 632da3f4ee
2 changed files with 45 additions and 11 deletions

View File

@@ -963,12 +963,19 @@ static SymEntry* ParseUnionDecl (const char* Name)
AddBitField (Decl.Ident, Decl.Type, 0, 0, FieldWidth, AddBitField (Decl.Ident, Decl.Type, 0, 0, FieldWidth,
SignednessSpecified); SignednessSpecified);
} else { } else {
Entry = AddLocalSym (Decl.Ident, Decl.Type, SC_STRUCTFIELD, 0);
if (IsAnonName (Decl.Ident)) { if (IsAnonName (Decl.Ident)) {
Entry = AddLocalSym (Decl.Ident, Decl.Type, SC_STRUCTFIELD, 0);
Entry->V.A.ANumber = UnionTagEntry->V.S.ACount++; Entry->V.A.ANumber = UnionTagEntry->V.S.ACount++;
AliasAnonStructFields (&Decl, Entry); 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"); Error ("Flexible array member cannot be first struct field");
} }
FlexibleMember = 1; FlexibleMember = 1;
Flags |= SC_HAVEFAM;
/* Assume zero for size calculations */ /* Assume zero for size calculations */
SetElementCount (Decl.Type, FLEXIBLE); SetElementCount (Decl.Type, FLEXIBLE);
} }
@@ -1156,13 +1165,21 @@ static SymEntry* ParseStructDecl (const char* Name)
StructSize += BitOffs / CHAR_BITS; StructSize += BitOffs / CHAR_BITS;
BitOffs %= CHAR_BITS; BitOffs %= CHAR_BITS;
} else { } else {
Entry = AddLocalSym (Decl.Ident, Decl.Type, SC_STRUCTFIELD, StructSize);
if (IsAnonName (Decl.Ident)) { if (IsAnonName (Decl.Ident)) {
Entry = AddLocalSym (Decl.Ident, Decl.Type, SC_STRUCTFIELD, StructSize);
Entry->V.A.ANumber = StructTagEntry->V.S.ACount++; Entry->V.A.ANumber = StructTagEntry->V.S.ACount++;
AliasAnonStructFields (&Decl, Entry); 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) { if (!FlexibleMember) {
StructSize += SizeOf (Decl.Type); StructSize += SizeOf (Decl.Type);
} }
@@ -2361,11 +2378,17 @@ static unsigned ParseArrayInit (Type* T, int* Braces, int AllowFlexibleMembers)
/* Number of elements determined by initializer */ /* Number of elements determined by initializer */
SetElementCount (T, Count); SetElementCount (T, Count);
ElementCount = Count; ElementCount = Count;
} else if (ElementCount == FLEXIBLE && AllowFlexibleMembers) { } else if (ElementCount == FLEXIBLE) {
/* In non ANSI mode, allow initialization of flexible array if (AllowFlexibleMembers) {
** members. /* In non ANSI mode, allow initialization of flexible array
*/ ** members.
ElementCount = Count; */
ElementCount = Count;
} else {
/* Forbid */
Error ("Initializing flexible array member is forbidden");
ElementCount = Count;
}
} else if (Count < ElementCount) { } else if (Count < ElementCount) {
g_zerobytes ((ElementCount - Count) * ElementSize); g_zerobytes ((ElementCount - Count) * ElementSize);
} else if (Count > ElementCount && HasCurly) { } else if (Count > ElementCount && HasCurly) {

View File

@@ -107,6 +107,7 @@ struct CodeEntry;
#define SC_ALIAS 0x01000000U /* Alias of anonymous field */ #define SC_ALIAS 0x01000000U /* Alias of anonymous field */
#define SC_FICTITIOUS 0x02000000U /* Symbol is fictitious */ #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); int SymIsOutputFunc (const SymEntry* Sym);
/* Return true if this is a function that must be output */ /* 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) #if defined(HAVE_INLINE)
INLINE const char* SymGetAsmName (const SymEntry* Sym) INLINE const char* SymGetAsmName (const SymEntry* Sym)
/* Return the assembler label name for the symbol (beware: may be NULL!) */ /* Return the assembler label name for the symbol (beware: may be NULL!) */