From f817b05fa974ed51a7152bacb9aae566efc66f77 Mon Sep 17 00:00:00 2001 From: cuz Date: Wed, 5 Feb 2003 22:02:48 +0000 Subject: [PATCH] Allow initialization of flexible array struct members git-svn-id: svn://svn.cc65.org/cc65/trunk@1928 b7a2c559-68d2-44c3-8de9-860c34a00d81 --- src/cc65/datatype.c | 9 +++++ src/cc65/datatype.h | 8 +++-- src/cc65/declare.c | 80 +++++++++++++++++++++++++++++++-------------- src/cc65/locals.c | 39 ++++++++++++++-------- 4 files changed, 97 insertions(+), 39 deletions(-) diff --git a/src/cc65/datatype.c b/src/cc65/datatype.c index 781470b65..282385ed7 100644 --- a/src/cc65/datatype.c +++ b/src/cc65/datatype.c @@ -755,3 +755,12 @@ long GetElementCount (const type* T) +type* GetElementType (type* T) +/* Return the element type of the given array type. */ +{ + CHECK (IsTypeArray (T)); + return T + DECODE_SIZE + 1; +} + + + diff --git a/src/cc65/datatype.h b/src/cc65/datatype.h index 2cbebedef..76bd018e1 100644 --- a/src/cc65/datatype.h +++ b/src/cc65/datatype.h @@ -144,8 +144,9 @@ typedef unsigned short type; /* Type elements needed for Encode/Decode */ #define DECODE_SIZE 5 -/* Unspecified size for the element count of an array */ -#define UNSPECIFIED -1L +/* Special encodings for element counts of an array */ +#define UNSPECIFIED -1L /* Element count was not specified */ +#define FLEXIBLE 0L /* Flexible array struct member */ /* Sizes */ #define SIZEOF_CHAR 1 @@ -482,6 +483,9 @@ long GetElementCount (const type* T); * array type). */ +type* GetElementType (type* T); +/* Return the element type of the given array type. */ + /* End of datatype.h */ diff --git a/src/cc65/declare.c b/src/cc65/declare.c index 20db1f6af..b6e78e27c 100644 --- a/src/cc65/declare.c +++ b/src/cc65/declare.c @@ -67,6 +67,9 @@ static void ParseTypeSpec (DeclSpec* D, int Default); /* Parse a type specificier */ +static unsigned ParseInitInternal (type* T, int AllowFlexibleMembers); +/* Parse initialization of variables. Return the number of data bytes. */ + /*****************************************************************************/ @@ -325,7 +328,7 @@ static SymEntry* ParseStructDecl (const char* Name, type StructType) } FlexibleMember = 1; /* Assume zero for size calculations */ - Encode (Decl.Type + 1, 0); + Encode (Decl.Type + 1, FLEXIBLE); } else { StructSize += CheckedSizeOf (Decl.Type); } @@ -1037,22 +1040,22 @@ static unsigned ParseVoidInit (void) case T_UINT: case T_PTR: case T_ARRAY: - if ((lval.Flags & E_MCTYPE) == E_TCONST) { - /* Make it word sized */ - lval.ConstVal &= 0xFFFF; - } - DefineData (&lval); - Size += SIZEOF_INT; + if ((lval.Flags & E_MCTYPE) == E_TCONST) { + /* Make it word sized */ + lval.ConstVal &= 0xFFFF; + } + DefineData (&lval); + Size += SIZEOF_INT; break; case T_LONG: case T_ULONG: - DefineData (&lval); - Size += SIZEOF_LONG; + DefineData (&lval); + Size += SIZEOF_LONG; break; default: - Error ("Illegal type in initialization"); + Error ("Illegal type in initialization"); break; } @@ -1073,7 +1076,7 @@ static unsigned ParseVoidInit (void) -static unsigned ParseStructInit (type* Type) +static unsigned ParseStructInit (type* Type, int AllowFlexibleMembers) /* Parse initialization of a struct or union. Return the number of data bytes. */ { SymEntry* Entry; @@ -1110,7 +1113,11 @@ static unsigned ParseStructInit (type* Type) Error ("Too many initializers"); return Size; } - Size += ParseInit (Entry->Type); + /* Parse initialization of one field. Flexible array members may + * only be initialized if they are the last field (or part of the + * last struct field). + */ + Size += ParseInitInternal (Entry->Type, AllowFlexibleMembers && Entry->NextSym == 0); Entry = Entry->NextSym; if (CurTok.Tok != TOK_COMMA) break; @@ -1123,23 +1130,27 @@ static unsigned ParseStructInit (type* Type) /* If there are struct fields left, reserve additional storage */ if (Size < StructSize) { g_zerobytes (StructSize - Size); + Size = StructSize; } - /* Return the number of bytes initialized */ - return StructSize; + /* Return the actual number of bytes initialized. This number may be + * larger than StructSize if flexible array members are present and were + * initialized (possible in non ANSI mode). + */ + return Size; } -unsigned ParseInit (type* T) +static unsigned ParseInitInternal (type* T, int AllowFlexibleMembers) /* Parse initialization of variables. Return the number of data bytes. */ { ExprDesc lval; - type* t; const char* str; int Count; - long ElementCount; + type* ElementType; unsigned ElementSize; + long ElementCount; switch (UnqualifiedType (*T)) { @@ -1180,21 +1191,28 @@ unsigned ParseInit (type* T) return SIZEOF_LONG; case T_ARRAY: + ElementType = GetElementType (T); + ElementSize = CheckedSizeOf (ElementType); ElementCount = GetElementCount (T); - ElementSize = CheckedSizeOf (T + DECODE_SIZE + 1); - t = T + DECODE_SIZE + 1; - if (IsTypeChar (t) && CurTok.Tok == TOK_SCONST) { + if (IsTypeChar (ElementType) && CurTok.Tok == TOK_SCONST) { + /* Char array initialized by string constant */ str = GetLiteral (CurTok.IVal); Count = GetLiteralPoolOffs () - CurTok.IVal; - TranslateLiteralPool (CurTok.IVal); /* Translate into target charset */ + /* Translate into target charset */ + TranslateLiteralPool (CurTok.IVal); g_defbytes (str, Count); - ResetLiteralPoolOffs (CurTok.IVal); /* Remove string from pool */ + /* Remove string from pool */ + ResetLiteralPoolOffs (CurTok.IVal); NextToken (); } else { ConsumeLCurly (); Count = 0; while (CurTok.Tok != TOK_RCURLY) { - ParseInit (T + DECODE_SIZE + 1); + /* Flexible array members may not be initialized within + * an array (because the size of each element may differ + * otherwise). + */ + ParseInitInternal (ElementType, 0); ++Count; if (CurTok.Tok != TOK_COMMA) break; @@ -1203,7 +1221,14 @@ unsigned ParseInit (type* T) ConsumeRCurly (); } if (ElementCount == UNSPECIFIED) { + /* Number of elements determined by initializer */ Encode (T + 1, Count); + ElementCount = Count; + } else if (ElementCount == FLEXIBLE && AllowFlexibleMembers) { + /* In non ANSI mode, allow initialization of flexible array + * members. + */ + ElementCount = Count; } else if (Count < ElementCount) { g_zerobytes ((ElementCount - Count) * ElementSize); } else if (Count > ElementCount) { @@ -1213,7 +1238,7 @@ unsigned ParseInit (type* T) case T_STRUCT: case T_UNION: - return ParseStructInit (T); + return ParseStructInit (T, AllowFlexibleMembers); case T_VOID: if (!ANSI) { @@ -1231,4 +1256,11 @@ unsigned ParseInit (type* T) +unsigned ParseInit (type* T) +/* Parse initialization of variables. Return the number of data bytes. */ +{ + return ParseInitInternal (T, !ANSI); +} + + diff --git a/src/cc65/locals.c b/src/cc65/locals.c index 5214a85bc..9f4c05088 100644 --- a/src/cc65/locals.c +++ b/src/cc65/locals.c @@ -94,9 +94,16 @@ static unsigned ParseRegisterDecl (Declaration* Decl, unsigned* SC, int Reg) g_defdatalabel (InitLabel); /* Parse the initialization generating a memory image of the - * data in the RODATA segment. + * data in the RODATA segment. The function does return the size + * of the initialization data, which may be greater than the + * actual size of the type, if the type is a structure with a + * flexible array member that has been initialized. Since we must + * know the size of the data in advance for register variables, + * we cannot allow that here. */ - ParseInit (Decl->Type); + if (ParseInit (Decl->Type) != Size) { + Error ("Cannot initialize flexible array members of storage class `register'"); + } /* Generate code to copy this data into the variable space */ g_initregister (InitLabel, Reg, Size); @@ -172,14 +179,6 @@ static unsigned ParseAutoDecl (Declaration* Decl, unsigned* SC) /* Special handling for compound types */ if (IsCompound) { - /* First reserve space for the variable */ - SymData = F_ReserveLocalSpace (CurrentFunc, Size); - - /* Next, allocate the space on the stack. This means that the - * variable is now located at offset 0 from the current sp. - */ - F_AllocLocalSpace (CurrentFunc); - /* Switch to read only data */ g_userodata (); @@ -188,11 +187,25 @@ static unsigned ParseAutoDecl (Declaration* Decl, unsigned* SC) g_defdatalabel (InitLabel); /* Parse the initialization generating a memory image of the - * data in the RODATA segment. + * data in the RODATA segment. The function will return the + * actual size of the initialization data, which may be + * greater than the size of the variable if it is a struct + * that contains a flexible array member and we're not in + * ANSI mode. */ - ParseInit (Decl->Type); + Size = ParseInit (Decl->Type); - /* Generate code to copy this data into the variable space */ + /* Now reserve space for the variable on the stack */ + SymData = F_ReserveLocalSpace (CurrentFunc, Size); + + /* Next, allocate the space on the stack. This means that the + * variable is now located at offset 0 from the current sp. + */ + F_AllocLocalSpace (CurrentFunc); + + /* Generate code to copy the initialization data into the + * variable space + */ g_initauto (InitLabel, Size); } else { -- 2.39.5