diff --git a/src/cc65/anonname.c b/src/cc65/anonname.c index d02253d82..23891bf0e 100644 --- a/src/cc65/anonname.c +++ b/src/cc65/anonname.c @@ -61,6 +61,17 @@ static const char AnonTag[] = "$anon"; +char* AnonFieldName (char* Buf, const char* Spec, int ANumber) +/* Get a name for an anonymous field of a struct or union. The given buffer is +** expected to be IDENTSIZE characters long. A pointer to the buffer is returned. +*/ +{ + xsprintf (Buf, IDENTSIZE, "%s-%s-%04X", AnonTag, Spec, ANumber); + return Buf; +} + + + char* AnonName (char* Buf, const char* Spec) /* Get a name for an anonymous variable or type. The given buffer is expected ** to be IDENTSIZE characters long. A pointer to the buffer is returned. diff --git a/src/cc65/anonname.h b/src/cc65/anonname.h index dfaa1bdaa..a88b131b5 100644 --- a/src/cc65/anonname.h +++ b/src/cc65/anonname.h @@ -44,6 +44,11 @@ +char* AnonFieldName (char* Buf, const char* Spec, int ANumber); +/* Get a name for an anonymous field of a struct or union. The given buffer is +** expected to be IDENTSIZE characters long. A pointer to the buffer is returned. +*/ + char* AnonName (char* Buf, const char* Spec); /* Get a name for an anonymous variable or type. The given buffer is expected ** to be IDENTSIZE characters long. A pointer to the buffer is returned. diff --git a/src/cc65/declare.c b/src/cc65/declare.c index 1ebae4123..a1d23c20b 100644 --- a/src/cc65/declare.c +++ b/src/cc65/declare.c @@ -89,7 +89,7 @@ struct StructInitData { static void ParseTypeSpec (DeclSpec* D, long Default, TypeCode Qualifiers); /* Parse a type specifier */ -static unsigned ParseInitInternal (Type* T, int AllowFlexibleMembers); +static unsigned ParseInitInternal (Type* T, int* Braces, int AllowFlexibleMembers); /* Parse initialization of variables. Return the number of data bytes. */ @@ -717,24 +717,24 @@ static int ParseFieldWidth (Declaration* Decl) -static unsigned CopyAnonStructFields (const Declaration* Decl, int Offs) -/* Copy fields from an anon union/struct into the current lexical level. The -** function returns the size of the embedded struct/union. +static unsigned AliasAnonStructFields (const Declaration* Decl, SymEntry* Anon) +/* Create alias fields from an anon union/struct in the current lexical level. +** The function returns the count of created aliases. */ { + unsigned Count = 0; + SymEntry* Alias; + /* Get the pointer to the symbol table entry of the anon struct */ SymEntry* Entry = GetSymEntry (Decl->Type); - /* Get the size of the anon struct */ - unsigned Size = Entry->V.S.Size; - /* Get the symbol table containing the fields. If it is empty, there has ** been an error before, so bail out. */ SymTable* Tab = Entry->V.S.SymTab; if (Tab == 0) { /* Incomplete definition - has been flagged before */ - return Size; + return 0; } /* Get a pointer to the list of symbols. Then walk the list adding copies @@ -743,10 +743,13 @@ static unsigned CopyAnonStructFields (const Declaration* Decl, int Offs) Entry = Tab->SymHead; while (Entry) { - /* Enter a copy of this symbol adjusting the offset. We will just - ** reuse the type string here. - */ - AddLocalSym (Entry->Name, Entry->Type, SC_STRUCTFIELD, Offs + Entry->V.Offs); + /* Enter an alias of this symbol */ + if (!IsAnonName (Entry->Name)) { + Alias = AddLocalSym (Entry->Name, Entry->Type, SC_STRUCTFIELD|SC_ALIAS, 0); + Alias->V.A.Field = Entry; + Alias->V.A.Offs = Anon->V.Offs + Entry->V.Offs; + ++Count; + } /* Currently, there can not be any attributes, but if there will be ** some in the future, we want to know this. @@ -757,8 +760,8 @@ static unsigned CopyAnonStructFields (const Declaration* Decl, int Offs) Entry = Entry->NextSym; } - /* Return the size of the embedded struct */ - return Size; + /* Return the count of created aliases */ + return Count; } @@ -771,6 +774,8 @@ static SymEntry* ParseUnionDecl (const char* Name) unsigned FieldSize; int FieldWidth; /* Width in bits, -1 if not a bit-field */ SymTable* FieldTab; + SymEntry* StructTypeEntry; + SymEntry* Entry; if (CurTok.Tok != TOK_LCURLY) { @@ -779,7 +784,9 @@ static SymEntry* ParseUnionDecl (const char* Name) } /* Add a forward declaration for the struct in the current lexical level */ - AddStructSym (Name, SC_UNION, 0, 0); + StructTypeEntry = AddStructSym (Name, SC_UNION, 0, 0); + + StructTypeEntry->V.S.ACount = 0; /* Skip the curly brace */ NextToken (); @@ -821,16 +828,11 @@ static SymEntry* ParseUnionDecl (const char* Name) /* This is an anonymous struct or union. Copy the fields ** into the current level. */ - FieldSize = CopyAnonStructFields (&Decl, 0); - if (FieldSize > UnionSize) { - UnionSize = FieldSize; - } - + AnonFieldName (Decl.Ident, "field", StructTypeEntry->V.S.ACount); } else { /* A non bit-field without a name is legal but useless */ Warning ("Declaration does not declare anything"); } - goto NextMember; } /* Handle sizes */ @@ -843,7 +845,13 @@ static SymEntry* ParseUnionDecl (const char* Name) if (FieldWidth > 0) { AddBitField (Decl.Ident, 0, 0, FieldWidth); } else { - 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 = StructTypeEntry->V.S.ACount++; + AliasAnonStructFields (&Decl, Entry); + } else { + AddLocalSym (Decl.Ident, Decl.Type, SC_STRUCTFIELD, 0); + } } NextMember: if (CurTok.Tok != TOK_COMMA) { @@ -876,6 +884,8 @@ static SymEntry* ParseStructDecl (const char* Name) unsigned BitOffs; /* Bit offset for bit-fields */ int FieldWidth; /* Width in bits, -1 if not a bit-field */ SymTable* FieldTab; + SymEntry* StructTypeEntry; + SymEntry* Entry; if (CurTok.Tok != TOK_LCURLY) { @@ -884,7 +894,9 @@ static SymEntry* ParseStructDecl (const char* Name) } /* Add a forward declaration for the struct in the current lexical level */ - AddStructSym (Name, SC_STRUCT, 0, 0); + StructTypeEntry = AddStructSym (Name, SC_STRUCT, 0, 0); + + StructTypeEntry->V.S.ACount = 0; /* Skip the curly brace */ NextToken (); @@ -981,13 +993,11 @@ static SymEntry* ParseStructDecl (const char* Name) /* This is an anonymous struct or union. Copy the ** fields into the current level. */ - StructSize += CopyAnonStructFields (&Decl, StructSize); - + AnonFieldName (Decl.Ident, "field", StructTypeEntry->V.S.ACount); } else { /* A non bit-field without a name is legal but useless */ Warning ("Declaration does not declare anything"); } - goto NextMember; } else { /* A bit-field without a name will get an anonymous one */ AnonName (Decl.Ident, "bit-field"); @@ -1009,7 +1019,13 @@ static SymEntry* ParseStructDecl (const char* Name) StructSize += BitOffs / CHAR_BITS; BitOffs %= CHAR_BITS; } else { - 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 = StructTypeEntry->V.S.ACount++; + AliasAnonStructFields (&Decl, Entry); + } else { + AddLocalSym (Decl.Ident, Decl.Type, SC_STRUCTFIELD, StructSize); + } if (!FlexibleMember) { StructSize += CheckedSizeOf (Decl.Type); } @@ -1874,18 +1890,20 @@ void CheckEmptyDecl (const DeclSpec* D) -static void SkipInitializer (unsigned BracesExpected) +static void SkipInitializer (int BracesExpected) /* Skip the remainder of an initializer in case of errors. Try to be somewhat ** smart so we don't have too many following errors. */ { - while (CurTok.Tok != TOK_CEOF && CurTok.Tok != TOK_SEMI && BracesExpected > 0) { + while (CurTok.Tok != TOK_CEOF && CurTok.Tok != TOK_SEMI && BracesExpected >= 0) { switch (CurTok.Tok) { case TOK_RCURLY: --BracesExpected; break; case TOK_LCURLY: ++BracesExpected; break; default: break; } - NextToken (); + if (BracesExpected >= 0) { + NextToken (); + } } } @@ -1917,6 +1935,7 @@ static void ClosingCurlyBraces (unsigned BracesExpected) */ { while (BracesExpected) { + /* TODO: Skip all excess initializers until next closing curly brace */ if (CurTok.Tok == TOK_RCURLY) { NextToken (); } else if (CurTok.Tok == TOK_COMMA && NextTok.Tok == TOK_RCURLY) { @@ -2069,7 +2088,7 @@ static unsigned ParsePointerInit (Type* T) -static unsigned ParseArrayInit (Type* T, int AllowFlexibleMembers) +static unsigned ParseArrayInit (Type* T, int* Braces, int AllowFlexibleMembers) /* Parse initializaton for arrays. Return the number of data bytes. */ { int Count; @@ -2135,7 +2154,7 @@ static unsigned ParseArrayInit (Type* T, int AllowFlexibleMembers) ** an array (because the size of each element may differ ** otherwise). */ - ParseInitInternal (ElementType, 0); + ParseInitInternal (ElementType, Braces, 0); ++Count; if (CurTok.Tok != TOK_COMMA) break; @@ -2158,23 +2177,29 @@ static unsigned ParseArrayInit (Type* T, int AllowFlexibleMembers) } else if (Count < ElementCount) { g_zerobytes ((ElementCount - Count) * ElementSize); } else if (Count > ElementCount) { - Error ("Too many initializers"); + Error ("Excess elements in array initializer"); } return ElementCount * ElementSize; } -static unsigned ParseStructInit (Type* T, int AllowFlexibleMembers) +static unsigned ParseStructInit (Type* T, int* Braces, int AllowFlexibleMembers) /* Parse initialization of a struct or union. Return the number of data bytes. */ { SymEntry* Entry; SymTable* Tab; StructInitData SI; + int HasCurly = 0; + int SkipComma = 0; - /* Consume the opening curly brace */ - ConsumeLCurly (); + /* Fields can be initialized without a pair of curly braces */ + if (*Braces == 0 || CurTok.Tok == TOK_LCURLY) { + /* Consume the opening curly brace */ + HasCurly = ConsumeLCurly (); + *Braces += HasCurly; + } /* Get a pointer to the struct entry from the type */ Entry = GetSymEntry (T); @@ -2189,7 +2214,7 @@ static unsigned ParseStructInit (Type* T, int AllowFlexibleMembers) if (Tab == 0) { Error ("Cannot initialize variables with incomplete type"); /* Try error recovery */ - SkipInitializer (1); + SkipInitializer (HasCurly); /* Nothing initialized */ return 0; } @@ -2203,18 +2228,50 @@ static unsigned ParseStructInit (Type* T, int AllowFlexibleMembers) SI.ValBits = 0; while (CurTok.Tok != TOK_RCURLY) { - /* */ + /* Check for excess elements */ if (Entry == 0) { - Error ("Too many initializers"); - SkipInitializer (1); + if (HasCurly) { + Error ("Excess elements in %s initializer", GetBasicTypeName (T)); + SkipInitializer (HasCurly); + } return SI.Offs; } - /* Parse initialization of one field. Bit-fields need a special - ** handling. + /* Check for special members that don't consume the initializer */ + if ((Entry->Flags & SC_ALIAS) == SC_ALIAS) { + /* Just skip */ + goto NextMember; + } + + /* This may be an anonymous bit-field, in which case it doesn't + ** have an initializer. */ + if (SymIsBitField (Entry) && (IsAnonName (Entry->Name))) { + /* Account for the data and output it if we have at least a full + ** word. We may have more if there was storage unit overlap, for + ** example two consecutive 10 bit fields. These will be packed + ** into 3 bytes. + */ + SI.ValBits += Entry->V.B.BitWidth; + CHECK (SI.ValBits <= CHAR_BITS + INT_BITS - 2); + while (SI.ValBits >= CHAR_BITS) { + OutputBitFieldData (&SI); + } + /* Avoid consuming the comma if any */ + goto NextMember; + } + + /* Skip comma this round */ + if (SkipComma) { + NextToken (); + SkipComma = 0; + } + if (SymIsBitField (Entry)) { + /* Parse initialization of one field. Bit-fields need a special + ** handling. + */ ExprDesc ED; unsigned Val; unsigned Shift; @@ -2226,36 +2283,17 @@ static unsigned ParseStructInit (Type* T, int AllowFlexibleMembers) CHECK (Entry->V.B.Offs * CHAR_BITS + Entry->V.B.BitOffs == SI.Offs * CHAR_BITS + SI.ValBits); - /* This may be an anonymous bit-field, in which case it doesn't - ** have an initializer. - */ - if (IsAnonName (Entry->Name)) { - /* Account for the data and output it if we have at least a - ** full word. We may have more if there was storage unit - ** overlap, for example two consecutive 10 bit fields. - ** These will be packed into 3 bytes. - */ - SI.ValBits += Entry->V.B.BitWidth; - CHECK (SI.ValBits <= CHAR_BITS + INT_BITS - 2); - while (SI.ValBits >= CHAR_BITS) { - OutputBitFieldData (&SI); - } - goto NextMember; - } else { - /* Read the data, check for a constant integer, do a range - ** check. - */ - ParseScalarInitInternal (type_uint, &ED); - if (!ED_IsConstAbsInt (&ED)) { - Error ("Constant initializer expected"); - ED_MakeConstAbsInt (&ED, 1); - } - if (ED.IVal > (long) Mask) { - Warning ("Truncating value in bit-field initializer"); - ED.IVal &= (long) Mask; - } - Val = (unsigned) ED.IVal; + /* Read the data, check for a constant integer, do a range check */ + ParseScalarInitInternal (type_uint, &ED); + if (!ED_IsConstAbsInt (&ED)) { + Error ("Constant initializer expected"); + ED_MakeConstAbsInt (&ED, 1); } + if (ED.IVal > (long) Mask) { + Warning ("Truncating value in bit-field initializer"); + ED.IVal &= (long) Mask; + } + Val = (unsigned) ED.IVal; /* Add the value to the currently stored bit-field value */ Shift = (Entry->V.B.Offs - SI.Offs) * CHAR_BITS + Entry->V.B.BitOffs; @@ -2285,7 +2323,7 @@ static unsigned ParseStructInit (Type* T, int AllowFlexibleMembers) /* Flexible array members may only be initialized if they are ** the last field (or part of the last struct field). */ - SI.Offs += ParseInitInternal (Entry->Type, AllowFlexibleMembers && Entry->NextSym == 0); + SI.Offs += ParseInitInternal (Entry->Type, Braces, AllowFlexibleMembers && Entry->NextSym == 0); } /* More initializers? */ @@ -2293,8 +2331,8 @@ static unsigned ParseStructInit (Type* T, int AllowFlexibleMembers) break; } - /* Skip the comma */ - NextToken (); + /* Skip the comma next round */ + SkipComma = 1; NextMember: /* Next member. For unions, only the first one can be initialized */ @@ -2307,8 +2345,10 @@ NextMember: } } - /* Consume the closing curly brace */ - ConsumeRCurly (); + if (HasCurly) { + /* Consume the closing curly brace */ + ConsumeRCurly (); + } /* If we have data from a bit-field left, output it now */ CHECK (SI.ValBits < CHAR_BITS); @@ -2405,7 +2445,7 @@ static unsigned ParseVoidInit (Type* T) -static unsigned ParseInitInternal (Type* T, int AllowFlexibleMembers) +static unsigned ParseInitInternal (Type* T, int *Braces, int AllowFlexibleMembers) /* Parse initialization of variables. Return the number of data bytes. */ { switch (GetUnderlyingTypeCode (T)) { @@ -2426,11 +2466,11 @@ static unsigned ParseInitInternal (Type* T, int AllowFlexibleMembers) return ParsePointerInit (T); case T_ARRAY: - return ParseArrayInit (T, AllowFlexibleMembers); + return ParseArrayInit (T, Braces, AllowFlexibleMembers); case T_STRUCT: case T_UNION: - return ParseStructInit (T, AllowFlexibleMembers); + return ParseStructInit (T, Braces, AllowFlexibleMembers); case T_VOID: if (IS_Get (&Standard) == STD_CC65) { @@ -2451,10 +2491,13 @@ static unsigned ParseInitInternal (Type* T, int AllowFlexibleMembers) unsigned ParseInit (Type* T) /* Parse initialization of variables. Return the number of data bytes. */ { + /* Current curly braces layers */ + int Braces = 0; + /* Parse the initialization. Flexible array members can only be initialized ** in cc65 mode. */ - unsigned Size = ParseInitInternal (T, IS_Get (&Standard) == STD_CC65); + unsigned Size = ParseInitInternal (T, &Braces, IS_Get (&Standard) == STD_CC65); /* The initialization may not generate code on global level, because code ** outside function scope will never get executed. diff --git a/src/cc65/expr.c b/src/cc65/expr.c index a35ad59a9..fd8a48002 100644 --- a/src/cc65/expr.c +++ b/src/cc65/expr.c @@ -1201,7 +1201,6 @@ static void StructRef (ExprDesc* Expr) /* Process struct/union field after . or ->. */ { ident Ident; - SymEntry* Field; Type* FinalType; TypeCode Q; @@ -1217,8 +1216,8 @@ static void StructRef (ExprDesc* Expr) /* Get the symbol table entry and check for a struct/union field */ strcpy (Ident, CurTok.Ident); NextToken (); - Field = FindStructField (Expr->Type, Ident); - if (Field == 0) { + const SymEntry Field = FindStructField (Expr->Type, Ident); + if (Field.Type == 0) { Error ("No field named '%s' found in %s", Ident, GetBasicTypeName (Expr->Type)); /* Make the expression an integer at address zero */ ED_MakeConstAbs (Expr, 0, type_int); @@ -1264,10 +1263,10 @@ static void StructRef (ExprDesc* Expr) } else { Q = GetQualifier (Indirect (Expr->Type)); } - if (GetQualifier (Field->Type) == (GetQualifier (Field->Type) | Q)) { - FinalType = Field->Type; + if (GetQualifier (Field.Type) == (GetQualifier (Field.Type) | Q)) { + FinalType = Field.Type; } else { - FinalType = TypeDup (Field->Type); + FinalType = TypeDup (Field.Type); FinalType->C |= Q; } @@ -1278,10 +1277,10 @@ static void StructRef (ExprDesc* Expr) /* Get the size of the type */ unsigned StructSize = SizeOf (Expr->Type); - unsigned FieldSize = SizeOf (Field->Type); + unsigned FieldSize = SizeOf (Field.Type); /* Safety check */ - CHECK (Field->V.Offs + FieldSize <= StructSize); + CHECK (Field.V.Offs + FieldSize <= StructSize); /* The type of the operation depends on the type of the struct/union */ switch (StructSize) { @@ -1304,16 +1303,16 @@ static void StructRef (ExprDesc* Expr) /* Generate a shift to get the field in the proper position in the ** primary. For bit fields, mask the value. */ - BitOffs = Field->V.Offs * CHAR_BITS; - if (SymIsBitField (Field)) { - BitOffs += Field->V.B.BitOffs; + BitOffs = Field.V.Offs * CHAR_BITS; + if (SymIsBitField (&Field)) { + BitOffs += Field.V.B.BitOffs; g_asr (Flags, BitOffs); /* Mask the value. This is unnecessary if the shift executed above ** moved only zeroes into the value. */ - if (BitOffs + Field->V.B.BitWidth != FieldSize * CHAR_BITS) { + if (BitOffs + Field.V.B.BitWidth != FieldSize * CHAR_BITS) { g_and (CF_INT | CF_UNSIGNED | CF_CONST, - (0x0001U << Field->V.B.BitWidth) - 1U); + (0x0001U << Field.V.B.BitWidth) - 1U); } } else { g_asr (Flags, BitOffs); @@ -1325,7 +1324,7 @@ static void StructRef (ExprDesc* Expr) } else { /* Set the struct/union field offset */ - Expr->IVal += Field->V.Offs; + Expr->IVal += Field.V.Offs; /* Use the new type */ Expr->Type = FinalType; @@ -1341,8 +1340,8 @@ static void StructRef (ExprDesc* Expr) } /* Make the expression a bit field if necessary */ - if (SymIsBitField (Field)) { - ED_MakeBitField (Expr, Field->V.B.BitOffs, Field->V.B.BitWidth); + if (SymIsBitField (&Field)) { + ED_MakeBitField (Expr, Field.V.B.BitOffs, Field.V.B.BitWidth); } } diff --git a/src/cc65/symentry.h b/src/cc65/symentry.h index b030d8b8b..e59bf2a35 100644 --- a/src/cc65/symentry.h +++ b/src/cc65/symentry.h @@ -105,6 +105,7 @@ struct CodeEntry; #define SC_SPADJUSTMENT 0x400000U #define SC_GOTO_IND 0x800000U /* Indirect goto */ +#define SC_ALIAS 0x01000000U /* Alias of anonymous field */ @@ -138,6 +139,14 @@ struct SymEntry { /* Offset for locals or struct members */ int Offs; + /* Data for anonymous struct or union members */ + struct { + int Offs; /* Byte offset into struct */ + unsigned ANumber; /* Numeric ID */ + SymEntry* Field; /* The real field aliased */ + } A; + + /* Label name for static symbols */ struct { unsigned Label; @@ -163,6 +172,7 @@ struct SymEntry { struct { struct SymTable* SymTab; /* Member symbol table */ unsigned Size; /* Size of the union/struct */ + unsigned ACount; /* Count of anonymous fields */ } S; /* Data for enums */ diff --git a/src/cc65/symtab.c b/src/cc65/symtab.c index 6472a0792..f7a7862cf 100644 --- a/src/cc65/symtab.c +++ b/src/cc65/symtab.c @@ -490,10 +490,15 @@ SymEntry* FindTagSym (const char* Name) -SymEntry* FindStructField (const Type* T, const char* Name) -/* Find a struct/union field in the fields list */ +SymEntry FindStructField (const Type* T, const char* Name) +/* Find a struct/union field in the fields list. +** Return the info about the found field symbol filled in an entry struct by +** value, or an empty entry struct if the field is not found. +*/ { - SymEntry* Field = 0; + SymEntry* Entry = 0; + SymEntry Field; + int Offs = 0; /* The given type may actually be a pointer to struct/union */ if (IsTypePtr (T)) { @@ -511,10 +516,26 @@ SymEntry* FindStructField (const Type* T, const char* Name) ** not exist. */ if (Struct->V.S.SymTab) { - Field = FindSymInTable (Struct->V.S.SymTab, Name, HashStr (Name)); + Entry = FindSymInTable (Struct->V.S.SymTab, Name, HashStr (Name)); + + if (Entry != 0) { + Offs = Entry->V.Offs; + } + + while (Entry != 0 && (Entry->Flags & SC_ALIAS) == SC_ALIAS) { + /* Get the real field */ + Entry = Entry->V.A.Field; + } } } + if (Entry != 0) { + Field = *Entry; + Field.V.Offs = Offs; + } else { + memset (&Field, 0, sizeof(SymEntry)); + } + return Field; } @@ -1001,7 +1022,13 @@ SymEntry* AddLocalSym (const char* Name, const Type* T, unsigned Flags, int Offs /* Set the symbol attributes */ Entry->Type = TypeDup (T); - if ((Flags & SC_AUTO) == SC_AUTO || (Flags & SC_TYPEMASK) == SC_TYPEDEF) { + + if ((Flags & SC_STRUCTFIELD) == SC_STRUCTFIELD || + (Flags & SC_TYPEDEF) == SC_TYPEDEF) { + if ((Flags & SC_ALIAS) != SC_ALIAS) { + Entry->V.Offs = Offs; + } + } else if ((Flags & SC_AUTO) == SC_AUTO) { Entry->V.Offs = Offs; } else if ((Flags & SC_REGISTER) == SC_REGISTER) { Entry->V.R.RegOffs = Offs; @@ -1013,8 +1040,6 @@ SymEntry* AddLocalSym (const char* Name, const Type* T, unsigned Flags, int Offs /* Generate the assembler name from the label number */ Entry->V.L.Label = Offs; Entry->AsmName = xstrdup (LocalLabelName (Entry->V.L.Label)); - } else if ((Flags & SC_STRUCTFIELD) == SC_STRUCTFIELD) { - Entry->V.Offs = Offs; } else { Internal ("Invalid flags in AddLocalSym: %04X", Flags); } diff --git a/src/cc65/symtab.h b/src/cc65/symtab.h index dd4b3aa37..79f656f95 100644 --- a/src/cc65/symtab.h +++ b/src/cc65/symtab.h @@ -133,8 +133,11 @@ SymEntry* FindLocalSym (const char* Name); SymEntry* FindTagSym (const char* Name); /* Find the symbol with the given name in the tag table */ -SymEntry* FindStructField (const Type* TypeArray, const char* Name); -/* Find a struct/union field in the fields list */ +SymEntry FindStructField (const Type* TypeArray, const char* Name); +/* Find a struct/union field in the fields list. +** Return the info about the found field symbol filled in an entry struct by +** value, or an empty entry struct if the field is not found. +*/ unsigned short FindSPAdjustment (const char* Name); /* Search for an entry in the table of SP adjustments */