1
0
mirror of https://github.com/cc65/cc65.git synced 2024-06-25 13:29:41 +00:00

Allow initialization of flexible array struct members

git-svn-id: svn://svn.cc65.org/cc65/trunk@1928 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
cuz 2003-02-05 22:02:48 +00:00
parent 0166c9f577
commit f817b05fa9
4 changed files with 97 additions and 39 deletions

View File

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

View File

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

View File

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

View File

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