mirror of
https://github.com/cc65/cc65.git
synced 2024-12-27 00:29:31 +00:00
Merge pull request #1879 from acqn/SymEntryFix
[cc65] SymEntry cleanups
This commit is contained in:
commit
7146dbc87d
@ -79,7 +79,7 @@ static void Parse (void)
|
|||||||
/* Top level parser routine. */
|
/* Top level parser routine. */
|
||||||
{
|
{
|
||||||
int comma;
|
int comma;
|
||||||
SymEntry* Entry;
|
SymEntry* Sym;
|
||||||
FuncDesc* FuncDef = 0;
|
FuncDesc* FuncDef = 0;
|
||||||
|
|
||||||
/* Initialization for deferred operations */
|
/* Initialization for deferred operations */
|
||||||
@ -142,7 +142,7 @@ static void Parse (void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Read declarations for this type */
|
/* Read declarations for this type */
|
||||||
Entry = 0;
|
Sym = 0;
|
||||||
comma = 0;
|
comma = 0;
|
||||||
while (1) {
|
while (1) {
|
||||||
|
|
||||||
@ -196,10 +196,10 @@ static void Parse (void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Add an entry to the symbol table */
|
/* Add an entry to the symbol table */
|
||||||
Entry = AddGlobalSym (Decl.Ident, Decl.Type, Decl.StorageClass);
|
Sym = AddGlobalSym (Decl.Ident, Decl.Type, Decl.StorageClass);
|
||||||
|
|
||||||
/* Add declaration attributes */
|
/* Add declaration attributes */
|
||||||
SymUseAttr (Entry, &Decl);
|
SymUseAttr (Sym, &Decl);
|
||||||
|
|
||||||
/* Reserve storage for the variable if we need to */
|
/* Reserve storage for the variable if we need to */
|
||||||
if (Decl.StorageClass & SC_STORAGE) {
|
if (Decl.StorageClass & SC_STORAGE) {
|
||||||
@ -211,11 +211,11 @@ static void Parse (void)
|
|||||||
if (CurTok.Tok == TOK_ASSIGN) {
|
if (CurTok.Tok == TOK_ASSIGN) {
|
||||||
|
|
||||||
/* This is a definition with storage */
|
/* This is a definition with storage */
|
||||||
if (SymIsDef (Entry)) {
|
if (SymIsDef (Sym)) {
|
||||||
Error ("Global variable '%s' has already been defined",
|
Error ("Global variable '%s' has already been defined",
|
||||||
Entry->Name);
|
Sym->Name);
|
||||||
}
|
}
|
||||||
Entry->Flags |= SC_DEF;
|
Sym->Flags |= SC_DEF;
|
||||||
|
|
||||||
/* We cannot initialize types of unknown size, or
|
/* We cannot initialize types of unknown size, or
|
||||||
** void types in ISO modes.
|
** void types in ISO modes.
|
||||||
@ -245,21 +245,21 @@ static void Parse (void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Define a label */
|
/* Define a label */
|
||||||
g_defgloblabel (Entry->Name);
|
g_defgloblabel (Sym->Name);
|
||||||
|
|
||||||
/* Skip the '=' */
|
/* Skip the '=' */
|
||||||
NextToken ();
|
NextToken ();
|
||||||
|
|
||||||
/* Parse the initialization */
|
/* Parse the initialization */
|
||||||
ParseInit (Entry->Type);
|
ParseInit (Sym->Type);
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
/* This is a declaration */
|
/* This is a declaration */
|
||||||
if (IsTypeVoid (Decl.Type)) {
|
if (IsTypeVoid (Decl.Type)) {
|
||||||
/* We cannot declare variables of type void */
|
/* We cannot declare variables of type void */
|
||||||
Error ("Illegal type for variable '%s'", Decl.Ident);
|
Error ("Illegal type for variable '%s'", Decl.Ident);
|
||||||
Entry->Flags &= ~(SC_STORAGE | SC_DEF);
|
Sym->Flags &= ~(SC_STORAGE | SC_DEF);
|
||||||
} else if (Size == 0 && SymIsDef (Entry) && !IsEmptiableObjectType (Decl.Type)) {
|
} else if (Size == 0 && SymIsDef (Sym) && !IsEmptiableObjectType (Decl.Type)) {
|
||||||
/* Size is unknown. Is it an array? */
|
/* Size is unknown. Is it an array? */
|
||||||
if (!IsTypeArray (Decl.Type)) {
|
if (!IsTypeArray (Decl.Type)) {
|
||||||
Error ("Variable '%s' has unknown size", Decl.Ident);
|
Error ("Variable '%s' has unknown size", Decl.Ident);
|
||||||
@ -286,11 +286,11 @@ static void Parse (void)
|
|||||||
*/
|
*/
|
||||||
const char* bssName = GetSegName (SEG_BSS);
|
const char* bssName = GetSegName (SEG_BSS);
|
||||||
|
|
||||||
if (Entry->V.BssName && strcmp (Entry->V.BssName, bssName) != 0) {
|
if (Sym->V.BssName && strcmp (Sym->V.BssName, bssName) != 0) {
|
||||||
Error ("Global variable '%s' already was defined in the '%s' segment.",
|
Error ("Global variable '%s' already was defined in the '%s' segment.",
|
||||||
Entry->Name, Entry->V.BssName);
|
Sym->Name, Sym->V.BssName);
|
||||||
}
|
}
|
||||||
Entry->V.BssName = xstrdup (bssName);
|
Sym->V.BssName = xstrdup (bssName);
|
||||||
|
|
||||||
/* This is to make the automatical zeropage setting of the symbol
|
/* This is to make the automatical zeropage setting of the symbol
|
||||||
** work right.
|
** work right.
|
||||||
@ -300,9 +300,9 @@ static void Parse (void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Make the symbol zeropage according to the segment address size */
|
/* Make the symbol zeropage according to the segment address size */
|
||||||
if ((Entry->Flags & SC_STATIC) != 0) {
|
if ((Sym->Flags & SC_STATIC) != 0) {
|
||||||
if (GetSegAddrSize (GetSegName (CS->CurDSeg)) == ADDR_SIZE_ZP) {
|
if (GetSegAddrSize (GetSegName (CS->CurDSeg)) == ADDR_SIZE_ZP) {
|
||||||
Entry->Flags |= SC_ZEROPAGE;
|
Sym->Flags |= SC_ZEROPAGE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -318,7 +318,7 @@ static void Parse (void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Function declaration? */
|
/* Function declaration? */
|
||||||
if (Entry && IsTypeFunc (Entry->Type)) {
|
if (Sym && IsTypeFunc (Sym->Type)) {
|
||||||
|
|
||||||
/* Function */
|
/* Function */
|
||||||
if (!comma) {
|
if (!comma) {
|
||||||
@ -327,7 +327,7 @@ static void Parse (void)
|
|||||||
NextToken ();
|
NextToken ();
|
||||||
} else {
|
} else {
|
||||||
/* Parse the function body */
|
/* Parse the function body */
|
||||||
NewFunc (Entry, FuncDef);
|
NewFunc (Sym, FuncDef);
|
||||||
|
|
||||||
/* Make sure we aren't omitting any work */
|
/* Make sure we aren't omitting any work */
|
||||||
CheckDeferredOpAllDone ();
|
CheckDeferredOpAllDone ();
|
||||||
@ -478,8 +478,9 @@ void Compile (const char* FileName)
|
|||||||
for (Entry = GetGlobalSymTab ()->SymHead; Entry; Entry = Entry->NextSym) {
|
for (Entry = GetGlobalSymTab ()->SymHead; Entry; Entry = Entry->NextSym) {
|
||||||
if ((Entry->Flags & (SC_STORAGE | SC_DEF | SC_STATIC)) == (SC_STORAGE | SC_STATIC)) {
|
if ((Entry->Flags & (SC_STORAGE | SC_DEF | SC_STATIC)) == (SC_STORAGE | SC_STATIC)) {
|
||||||
/* Assembly definition of uninitialized global variable */
|
/* Assembly definition of uninitialized global variable */
|
||||||
SymEntry* Sym = GetSymType (Entry->Type);
|
SymEntry* TagSym = GetESUTagSym (Entry->Type);
|
||||||
unsigned Size = SizeOf (Entry->Type);
|
unsigned Size = SizeOf (Entry->Type);
|
||||||
|
|
||||||
if (Size == 0 && IsTypeArray (Entry->Type)) {
|
if (Size == 0 && IsTypeArray (Entry->Type)) {
|
||||||
if (GetElementCount (Entry->Type) == UNSPECIFIED) {
|
if (GetElementCount (Entry->Type) == UNSPECIFIED) {
|
||||||
/* Assume array size of 1 */
|
/* Assume array size of 1 */
|
||||||
@ -488,11 +489,11 @@ void Compile (const char* FileName)
|
|||||||
Warning ("Incomplete array '%s[]' assumed to have one element", Entry->Name);
|
Warning ("Incomplete array '%s[]' assumed to have one element", Entry->Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
Sym = GetSymType (GetElementType (Entry->Type));
|
TagSym = GetESUTagSym (GetElementType (Entry->Type));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* For non-ESU types, Size != 0 */
|
/* For non-ESU types, Size != 0 */
|
||||||
if (Size != 0 || (Sym != 0 && SymIsDef (Sym))) {
|
if (Size != 0 || (TagSym != 0 && SymIsDef (TagSym))) {
|
||||||
/* Set the segment name only when it changes */
|
/* Set the segment name only when it changes */
|
||||||
if (strcmp (GetSegName (SEG_BSS), Entry->V.BssName) != 0) {
|
if (strcmp (GetSegName (SEG_BSS), Entry->V.BssName) != 0) {
|
||||||
SetSegName (SEG_BSS, Entry->V.BssName);
|
SetSegName (SEG_BSS, Entry->V.BssName);
|
||||||
|
@ -48,6 +48,7 @@
|
|||||||
#include "fp.h"
|
#include "fp.h"
|
||||||
#include "funcdesc.h"
|
#include "funcdesc.h"
|
||||||
#include "global.h"
|
#include "global.h"
|
||||||
|
#include "ident.h"
|
||||||
#include "symtab.h"
|
#include "symtab.h"
|
||||||
|
|
||||||
|
|
||||||
@ -86,6 +87,83 @@ const Type type_c_void_p[] = { TYPE(T_PTR), TYPE(T_C_VOID), TYPE(T_END) };
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const char* GetBasicTypeName (const Type* T)
|
||||||
|
/* Return a const name string of the basic type.
|
||||||
|
** Return "type" for unknown basic types.
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
switch (GetRawType (T)) {
|
||||||
|
case T_TYPE_ENUM: return "enum";
|
||||||
|
case T_TYPE_BITFIELD: return "bit-field";
|
||||||
|
case T_TYPE_FLOAT: return "float";
|
||||||
|
case T_TYPE_DOUBLE: return "double";
|
||||||
|
case T_TYPE_VOID: return "void";
|
||||||
|
case T_TYPE_STRUCT: return "struct";
|
||||||
|
case T_TYPE_UNION: return "union";
|
||||||
|
case T_TYPE_ARRAY: return "array";
|
||||||
|
case T_TYPE_PTR: return "pointer";
|
||||||
|
case T_TYPE_FUNC: return "function";
|
||||||
|
case T_TYPE_NONE: /* FALLTHROUGH */
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
if (IsClassInt (T)) {
|
||||||
|
if (IsRawSignSigned (T)) {
|
||||||
|
switch (GetRawType (T)) {
|
||||||
|
case T_TYPE_CHAR: return "signed char";
|
||||||
|
case T_TYPE_SHORT: return "short";
|
||||||
|
case T_TYPE_INT: return "int";
|
||||||
|
case T_TYPE_LONG: return "long";
|
||||||
|
case T_TYPE_LONGLONG: return "long long";
|
||||||
|
default:
|
||||||
|
return "signed integer";
|
||||||
|
}
|
||||||
|
} else if (IsRawSignUnsigned (T)) {
|
||||||
|
switch (GetRawType (T)) {
|
||||||
|
case T_TYPE_CHAR: return "unsigned char";
|
||||||
|
case T_TYPE_SHORT: return "unsigned short";
|
||||||
|
case T_TYPE_INT: return "unsigned int";
|
||||||
|
case T_TYPE_LONG: return "unsigned long";
|
||||||
|
case T_TYPE_LONGLONG: return "unsigned long long";
|
||||||
|
default:
|
||||||
|
return "unsigned integer";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
switch (GetRawType (T)) {
|
||||||
|
case T_TYPE_CHAR: return "char";
|
||||||
|
case T_TYPE_SHORT: return "short";
|
||||||
|
case T_TYPE_INT: return "int";
|
||||||
|
case T_TYPE_LONG: return "long";
|
||||||
|
case T_TYPE_LONGLONG: return "long long";
|
||||||
|
default:
|
||||||
|
return "integer";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "type";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static const char* GetTagSymName (const Type* T)
|
||||||
|
/* Return a name string of the type or the symbol name if it is an ESU type.
|
||||||
|
** Note: This may use a static buffer that could be overwritten by other calls.
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
static char TypeName [IDENTSIZE + 16];
|
||||||
|
SymEntry* TagSym;
|
||||||
|
|
||||||
|
TagSym = GetESUTagSym (T);
|
||||||
|
if (TagSym == 0) {
|
||||||
|
return GetBasicTypeName (T);
|
||||||
|
}
|
||||||
|
sprintf (TypeName, "%s %s", GetBasicTypeName (T),
|
||||||
|
TagSym->Name[0] != '\0' ? TagSym->Name : "<unknown>");
|
||||||
|
|
||||||
|
return TypeName;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static struct StrBuf* GetFullTypeNameWestEast (struct StrBuf* West, struct StrBuf* East, const Type* T)
|
static struct StrBuf* GetFullTypeNameWestEast (struct StrBuf* West, struct StrBuf* East, const Type* T)
|
||||||
/* Return the name string of the given type split into a western part and an
|
/* Return the name string of the given type split into a western part and an
|
||||||
** eastern part.
|
** eastern part.
|
||||||
@ -208,7 +286,7 @@ static struct StrBuf* GetFullTypeNameWestEast (struct StrBuf* West, struct StrBu
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!IsTypeBitField (T)) {
|
if (!IsTypeBitField (T)) {
|
||||||
SB_AppendStr (&Buf, GetSymTypeName (T));
|
SB_AppendStr (&Buf, GetTagSymName (T));
|
||||||
} else {
|
} else {
|
||||||
SB_AppendStr (&Buf, GetBasicTypeName (T + 1));
|
SB_AppendStr (&Buf, GetBasicTypeName (T + 1));
|
||||||
}
|
}
|
||||||
@ -228,63 +306,6 @@ static struct StrBuf* GetFullTypeNameWestEast (struct StrBuf* West, struct StrBu
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
const char* GetBasicTypeName (const Type* T)
|
|
||||||
/* Return a const name string of the basic type.
|
|
||||||
** Return "type" for unknown basic types.
|
|
||||||
*/
|
|
||||||
{
|
|
||||||
switch (GetRawType (T)) {
|
|
||||||
case T_TYPE_ENUM: return "enum";
|
|
||||||
case T_TYPE_BITFIELD: return "bit-field";
|
|
||||||
case T_TYPE_FLOAT: return "float";
|
|
||||||
case T_TYPE_DOUBLE: return "double";
|
|
||||||
case T_TYPE_VOID: return "void";
|
|
||||||
case T_TYPE_STRUCT: return "struct";
|
|
||||||
case T_TYPE_UNION: return "union";
|
|
||||||
case T_TYPE_ARRAY: return "array";
|
|
||||||
case T_TYPE_PTR: return "pointer";
|
|
||||||
case T_TYPE_FUNC: return "function";
|
|
||||||
case T_TYPE_NONE: /* FALLTHROUGH */
|
|
||||||
default: break;
|
|
||||||
}
|
|
||||||
if (IsClassInt (T)) {
|
|
||||||
if (IsRawSignSigned (T)) {
|
|
||||||
switch (GetRawType (T)) {
|
|
||||||
case T_TYPE_CHAR: return "signed char";
|
|
||||||
case T_TYPE_SHORT: return "short";
|
|
||||||
case T_TYPE_INT: return "int";
|
|
||||||
case T_TYPE_LONG: return "long";
|
|
||||||
case T_TYPE_LONGLONG: return "long long";
|
|
||||||
default:
|
|
||||||
return "signed integer";
|
|
||||||
}
|
|
||||||
} else if (IsRawSignUnsigned (T)) {
|
|
||||||
switch (GetRawType (T)) {
|
|
||||||
case T_TYPE_CHAR: return "unsigned char";
|
|
||||||
case T_TYPE_SHORT: return "unsigned short";
|
|
||||||
case T_TYPE_INT: return "unsigned int";
|
|
||||||
case T_TYPE_LONG: return "unsigned long";
|
|
||||||
case T_TYPE_LONGLONG: return "unsigned long long";
|
|
||||||
default:
|
|
||||||
return "unsigned integer";
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
switch (GetRawType (T)) {
|
|
||||||
case T_TYPE_CHAR: return "char";
|
|
||||||
case T_TYPE_SHORT: return "short";
|
|
||||||
case T_TYPE_INT: return "int";
|
|
||||||
case T_TYPE_LONG: return "long";
|
|
||||||
case T_TYPE_LONGLONG: return "long long";
|
|
||||||
default:
|
|
||||||
return "integer";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return "type";
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const char* GetFullTypeName (const Type* T)
|
const char* GetFullTypeName (const Type* T)
|
||||||
/* Return the full name string of the given type */
|
/* Return the full name string of the given type */
|
||||||
{
|
{
|
||||||
@ -1307,9 +1328,9 @@ int IsESUType (const Type* T)
|
|||||||
int IsIncompleteESUType (const Type* T)
|
int IsIncompleteESUType (const Type* T)
|
||||||
/* Return true if this is an incomplete ESU type */
|
/* Return true if this is an incomplete ESU type */
|
||||||
{
|
{
|
||||||
SymEntry* Sym = GetSymType (T);
|
SymEntry* TagSym = GetESUTagSym (T);
|
||||||
|
|
||||||
return Sym != 0 && !SymIsDef (Sym);
|
return TagSym != 0 && !SymIsDef (TagSym);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1486,20 +1507,21 @@ const Type* GetBaseElementType (const Type* T)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
struct SymEntry* GetESUSymEntry (const Type* T)
|
struct SymEntry* GetESUTagSym (const Type* T)
|
||||||
/* Return a SymEntry pointer from an enum/struct/union type */
|
/* Get the tag symbol entry of the enum/struct/union type.
|
||||||
|
** Return 0 if it is not an enum/struct/union.
|
||||||
|
*/
|
||||||
{
|
{
|
||||||
/* Only enums, structs or unions have a SymEntry attribute */
|
if ((IsClassStruct (T) || IsTypeEnum (T))) {
|
||||||
CHECK (IsClassStruct (T) || IsTypeEnum (T));
|
return T->A.S;
|
||||||
|
}
|
||||||
/* Return the attribute */
|
return 0;
|
||||||
return T->A.S;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void SetESUSymEntry (Type* T, struct SymEntry* S)
|
void SetESUTagSym (Type* T, struct SymEntry* S)
|
||||||
/* Set the SymEntry pointer for an enum/struct/union type */
|
/* Set the tag symbol entry of the enum/struct/union type */
|
||||||
{
|
{
|
||||||
/* Only enums, structs or unions have a SymEntry attribute */
|
/* Only enums, structs or unions have a SymEntry attribute */
|
||||||
CHECK (IsClassStruct (T) || IsTypeEnum (T));
|
CHECK (IsClassStruct (T) || IsTypeEnum (T));
|
||||||
@ -1570,7 +1592,7 @@ void PrintFuncSig (FILE* F, const char* Name, const Type* T)
|
|||||||
if (SymIsRegVar (Param)) {
|
if (SymIsRegVar (Param)) {
|
||||||
SB_AppendStr (&ParamList, "register ");
|
SB_AppendStr (&ParamList, "register ");
|
||||||
}
|
}
|
||||||
if (!HasAnonName (Param)) {
|
if (!SymHasAnonName (Param)) {
|
||||||
SB_AppendStr (&Buf, Param->Name);
|
SB_AppendStr (&Buf, Param->Name);
|
||||||
}
|
}
|
||||||
SB_AppendStr (&ParamList, SB_GetConstBuf (GetFullTypeNameBuf (&Buf, Param->Type)));
|
SB_AppendStr (&ParamList, SB_GetConstBuf (GetFullTypeNameBuf (&Buf, Param->Type)));
|
||||||
|
@ -943,11 +943,13 @@ const Type* GetBaseElementType (const Type* T);
|
|||||||
** the element type that is not an array.
|
** the element type that is not an array.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
struct SymEntry* GetESUSymEntry (const Type* T) attribute ((const));
|
struct SymEntry* GetESUTagSym (const Type* T) attribute ((const));
|
||||||
/* Return a SymEntry pointer from an enum/struct/union type */
|
/* Get the tag symbol entry of the enum/struct/union type.
|
||||||
|
** Return 0 if it is not an enum/struct/union.
|
||||||
|
*/
|
||||||
|
|
||||||
void SetESUSymEntry (Type* T, struct SymEntry* S);
|
void SetESUTagSym (Type* T, struct SymEntry* S);
|
||||||
/* Set the SymEntry pointer for an enum/struct/union type */
|
/* Set the tag symbol entry of the enum/struct/union type */
|
||||||
|
|
||||||
TypeCode AddrSizeQualifier (unsigned AddrSize);
|
TypeCode AddrSizeQualifier (unsigned AddrSize);
|
||||||
/* Return T_QUAL_NEAR or T_QUAL_FAR depending on the address size */
|
/* Return T_QUAL_NEAR or T_QUAL_FAR depending on the address size */
|
||||||
|
@ -502,18 +502,18 @@ static SymEntry* ESUForwardDecl (const char* Name, unsigned Flags, unsigned* DSF
|
|||||||
/* Try to find an enum/struct/union with the given name. If there is none,
|
/* Try to find an enum/struct/union with the given name. If there is none,
|
||||||
** insert a forward declaration into the current lexical level.
|
** insert a forward declaration into the current lexical level.
|
||||||
*/
|
*/
|
||||||
SymEntry* Entry = FindTagSym (Name);
|
SymEntry* TagEntry = FindTagSym (Name);
|
||||||
if (Entry == 0) {
|
if (TagEntry == 0) {
|
||||||
if ((Flags & SC_ESUTYPEMASK) != SC_ENUM) {
|
if ((Flags & SC_ESUTYPEMASK) != SC_ENUM) {
|
||||||
Entry = AddStructSym (Name, Flags, 0, 0, DSFlags);
|
TagEntry = AddStructSym (Name, Flags, 0, 0, DSFlags);
|
||||||
} else {
|
} else {
|
||||||
Entry = AddEnumSym (Name, Flags, 0, 0, DSFlags);
|
TagEntry = AddEnumSym (Name, Flags, 0, 0, DSFlags);
|
||||||
}
|
}
|
||||||
} else if ((Entry->Flags & SC_TYPEMASK) != (Flags & SC_ESUTYPEMASK)) {
|
} else if ((TagEntry->Flags & SC_TYPEMASK) != (Flags & SC_ESUTYPEMASK)) {
|
||||||
/* Already defined, but not the same type class */
|
/* Already defined, but not the same type class */
|
||||||
Error ("Symbol '%s' is already different kind", Name);
|
Error ("Symbol '%s' is already different kind", Name);
|
||||||
}
|
}
|
||||||
return Entry;
|
return TagEntry;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -810,15 +810,13 @@ static unsigned AliasAnonStructFields (const Declaration* D, SymEntry* Anon)
|
|||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
unsigned Count = 0;
|
unsigned Count = 0;
|
||||||
|
SymEntry* Field;
|
||||||
SymEntry* Alias;
|
SymEntry* Alias;
|
||||||
|
|
||||||
/* Get the pointer to the symbol table entry of the anon struct */
|
|
||||||
SymEntry* Entry = GetESUSymEntry (D->Type);
|
|
||||||
|
|
||||||
/* Get the symbol table containing the fields. If it is empty, there has
|
/* Get the symbol table containing the fields. If it is empty, there has
|
||||||
** been an error before, so bail out.
|
** been an error before, so bail out.
|
||||||
*/
|
*/
|
||||||
SymTable* Tab = Entry->V.S.SymTab;
|
SymTable* Tab = GetESUTagSym (D->Type)->V.S.SymTab;
|
||||||
if (Tab == 0) {
|
if (Tab == 0) {
|
||||||
/* Incomplete definition - has been flagged before */
|
/* Incomplete definition - has been flagged before */
|
||||||
return 0;
|
return 0;
|
||||||
@ -827,24 +825,24 @@ static unsigned AliasAnonStructFields (const Declaration* D, SymEntry* Anon)
|
|||||||
/* Get a pointer to the list of symbols. Then walk the list adding copies
|
/* Get a pointer to the list of symbols. Then walk the list adding copies
|
||||||
** of the embedded struct to the current level.
|
** of the embedded struct to the current level.
|
||||||
*/
|
*/
|
||||||
Entry = Tab->SymHead;
|
Field = Tab->SymHead;
|
||||||
while (Entry) {
|
while (Field) {
|
||||||
|
|
||||||
/* Enter an alias of this symbol */
|
/* Enter an alias of this symbol */
|
||||||
if (!IsAnonName (Entry->Name)) {
|
if (!IsAnonName (Field->Name)) {
|
||||||
Alias = AddLocalSym (Entry->Name, Entry->Type, SC_STRUCTFIELD|SC_ALIAS, 0);
|
Alias = AddLocalSym (Field->Name, Field->Type, SC_STRUCTFIELD|SC_ALIAS, 0);
|
||||||
Alias->V.A.Field = Entry;
|
Alias->V.A.Field = Field;
|
||||||
Alias->V.A.Offs = Anon->V.Offs + Entry->V.Offs;
|
Alias->V.A.Offs = Anon->V.Offs + Field->V.Offs;
|
||||||
++Count;
|
++Count;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Currently, there can not be any attributes, but if there will be
|
/* Currently, there can not be any attributes, but if there will be
|
||||||
** some in the future, we want to know this.
|
** some in the future, we want to know this.
|
||||||
*/
|
*/
|
||||||
CHECK (Entry->Attr == 0);
|
CHECK (Field->Attr == 0);
|
||||||
|
|
||||||
/* Next entry */
|
/* Next entry */
|
||||||
Entry = Entry->NextSym;
|
Field = Field->NextSym;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return the count of created aliases */
|
/* Return the count of created aliases */
|
||||||
@ -862,7 +860,7 @@ static SymEntry* ParseUnionDecl (const char* Name, unsigned* DSFlags)
|
|||||||
int FieldWidth; /* Width in bits, -1 if not a bit-field */
|
int FieldWidth; /* Width in bits, -1 if not a bit-field */
|
||||||
SymTable* FieldTab;
|
SymTable* FieldTab;
|
||||||
SymEntry* UnionTagEntry;
|
SymEntry* UnionTagEntry;
|
||||||
SymEntry* Entry;
|
SymEntry* Field;
|
||||||
unsigned Flags = 0;
|
unsigned Flags = 0;
|
||||||
unsigned PrevErrorCount = ErrorCount;
|
unsigned PrevErrorCount = ErrorCount;
|
||||||
|
|
||||||
@ -946,17 +944,17 @@ static SymEntry* ParseUnionDecl (const char* Name, unsigned* DSFlags)
|
|||||||
AddBitField (Decl.Ident, Decl.Type, 0, 0, FieldWidth,
|
AddBitField (Decl.Ident, Decl.Type, 0, 0, FieldWidth,
|
||||||
SignednessSpecified);
|
SignednessSpecified);
|
||||||
} else if (Decl.Ident[0] != '\0') {
|
} else if (Decl.Ident[0] != '\0') {
|
||||||
Entry = AddLocalSym (Decl.Ident, Decl.Type, SC_STRUCTFIELD, 0);
|
Field = AddLocalSym (Decl.Ident, Decl.Type, SC_STRUCTFIELD, 0);
|
||||||
if (IsAnonName (Decl.Ident)) {
|
if (IsAnonName (Decl.Ident)) {
|
||||||
Entry->V.A.ANumber = UnionTagEntry->V.S.ACount++;
|
Field->V.A.ANumber = UnionTagEntry->V.S.ACount++;
|
||||||
AliasAnonStructFields (&Decl, Entry);
|
AliasAnonStructFields (&Decl, Field);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check if the field itself has a flexible array member */
|
/* Check if the field itself has a flexible array member */
|
||||||
if (IsClassStruct (Decl.Type)) {
|
if (IsClassStruct (Decl.Type)) {
|
||||||
SymEntry* Sym = GetSymType (Decl.Type);
|
SymEntry* TagEntry = GetESUTagSym (Decl.Type);
|
||||||
if (Sym && SymHasFlexibleArrayMember (Sym)) {
|
if (TagEntry && SymHasFlexibleArrayMember (TagEntry)) {
|
||||||
Entry->Flags |= SC_HAVEFAM;
|
Field->Flags |= SC_HAVEFAM;
|
||||||
Flags |= SC_HAVEFAM;
|
Flags |= SC_HAVEFAM;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1003,7 +1001,7 @@ static SymEntry* ParseStructDecl (const char* Name, unsigned* DSFlags)
|
|||||||
int FieldWidth; /* Width in bits, -1 if not a bit-field */
|
int FieldWidth; /* Width in bits, -1 if not a bit-field */
|
||||||
SymTable* FieldTab;
|
SymTable* FieldTab;
|
||||||
SymEntry* StructTagEntry;
|
SymEntry* StructTagEntry;
|
||||||
SymEntry* Entry;
|
SymEntry* Field;
|
||||||
unsigned Flags = 0;
|
unsigned Flags = 0;
|
||||||
unsigned PrevErrorCount = ErrorCount;
|
unsigned PrevErrorCount = ErrorCount;
|
||||||
|
|
||||||
@ -1148,17 +1146,17 @@ static SymEntry* ParseStructDecl (const char* Name, unsigned* DSFlags)
|
|||||||
StructSize += BitOffs / CHAR_BITS;
|
StructSize += BitOffs / CHAR_BITS;
|
||||||
BitOffs %= CHAR_BITS;
|
BitOffs %= CHAR_BITS;
|
||||||
} else if (Decl.Ident[0] != '\0') {
|
} else if (Decl.Ident[0] != '\0') {
|
||||||
Entry = AddLocalSym (Decl.Ident, Decl.Type, SC_STRUCTFIELD, StructSize);
|
Field = AddLocalSym (Decl.Ident, Decl.Type, SC_STRUCTFIELD, StructSize);
|
||||||
if (IsAnonName (Decl.Ident)) {
|
if (IsAnonName (Decl.Ident)) {
|
||||||
Entry->V.A.ANumber = StructTagEntry->V.S.ACount++;
|
Field->V.A.ANumber = StructTagEntry->V.S.ACount++;
|
||||||
AliasAnonStructFields (&Decl, Entry);
|
AliasAnonStructFields (&Decl, Field);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check if the field itself has a flexible array member */
|
/* Check if the field itself has a flexible array member */
|
||||||
if (IsClassStruct (Decl.Type)) {
|
if (IsClassStruct (Decl.Type)) {
|
||||||
SymEntry* Sym = GetSymType (Decl.Type);
|
SymEntry* TagEntry = GetESUTagSym (Decl.Type);
|
||||||
if (Sym && SymHasFlexibleArrayMember (Sym)) {
|
if (TagEntry && SymHasFlexibleArrayMember (TagEntry)) {
|
||||||
Entry->Flags |= SC_HAVEFAM;
|
Field->Flags |= SC_HAVEFAM;
|
||||||
Flags |= SC_HAVEFAM;
|
Flags |= SC_HAVEFAM;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1215,7 +1213,7 @@ static void ParseTypeSpec (DeclSpec* D, long Default, TypeCode Qualifiers,
|
|||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
ident Ident;
|
ident Ident;
|
||||||
SymEntry* Entry;
|
SymEntry* TagEntry;
|
||||||
|
|
||||||
if (SignednessSpecified != NULL) {
|
if (SignednessSpecified != NULL) {
|
||||||
*SignednessSpecified = 0;
|
*SignednessSpecified = 0;
|
||||||
@ -1385,10 +1383,10 @@ static void ParseTypeSpec (DeclSpec* D, long Default, TypeCode Qualifiers,
|
|||||||
/* Remember we have an extra type decl */
|
/* Remember we have an extra type decl */
|
||||||
D->Flags |= DS_EXTRA_TYPE;
|
D->Flags |= DS_EXTRA_TYPE;
|
||||||
/* Declare the union in the current scope */
|
/* Declare the union in the current scope */
|
||||||
Entry = ParseUnionDecl (Ident, &D->Flags);
|
TagEntry = ParseUnionDecl (Ident, &D->Flags);
|
||||||
/* Encode the union entry into the type */
|
/* Encode the union entry into the type */
|
||||||
D->Type[0].C = T_UNION;
|
D->Type[0].C = T_UNION;
|
||||||
SetESUSymEntry (D->Type, Entry);
|
SetESUTagSym (D->Type, TagEntry);
|
||||||
D->Type[1].C = T_END;
|
D->Type[1].C = T_END;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -1404,10 +1402,10 @@ static void ParseTypeSpec (DeclSpec* D, long Default, TypeCode Qualifiers,
|
|||||||
/* Remember we have an extra type decl */
|
/* Remember we have an extra type decl */
|
||||||
D->Flags |= DS_EXTRA_TYPE;
|
D->Flags |= DS_EXTRA_TYPE;
|
||||||
/* Declare the struct in the current scope */
|
/* Declare the struct in the current scope */
|
||||||
Entry = ParseStructDecl (Ident, &D->Flags);
|
TagEntry = ParseStructDecl (Ident, &D->Flags);
|
||||||
/* Encode the struct entry into the type */
|
/* Encode the struct entry into the type */
|
||||||
D->Type[0].C = T_STRUCT;
|
D->Type[0].C = T_STRUCT;
|
||||||
SetESUSymEntry (D->Type, Entry);
|
SetESUTagSym (D->Type, TagEntry);
|
||||||
D->Type[1].C = T_END;
|
D->Type[1].C = T_END;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -1427,10 +1425,10 @@ static void ParseTypeSpec (DeclSpec* D, long Default, TypeCode Qualifiers,
|
|||||||
/* Remember we have an extra type decl */
|
/* Remember we have an extra type decl */
|
||||||
D->Flags |= DS_EXTRA_TYPE;
|
D->Flags |= DS_EXTRA_TYPE;
|
||||||
/* Parse the enum decl */
|
/* Parse the enum decl */
|
||||||
Entry = ParseEnumDecl (Ident, &D->Flags);
|
TagEntry = ParseEnumDecl (Ident, &D->Flags);
|
||||||
/* Encode the enum entry into the type */
|
/* Encode the enum entry into the type */
|
||||||
D->Type[0].C |= T_ENUM;
|
D->Type[0].C |= T_ENUM;
|
||||||
SetESUSymEntry (D->Type, Entry);
|
SetESUTagSym (D->Type, TagEntry);
|
||||||
D->Type[1].C = T_END;
|
D->Type[1].C = T_END;
|
||||||
/* The signedness of enums is determined by the type, so say this is specified to avoid
|
/* The signedness of enums is determined by the type, so say this is specified to avoid
|
||||||
** the int -> unsigned int handling for plain int bit-fields in AddBitField.
|
** the int -> unsigned int handling for plain int bit-fields in AddBitField.
|
||||||
@ -1443,11 +1441,11 @@ static void ParseTypeSpec (DeclSpec* D, long Default, TypeCode Qualifiers,
|
|||||||
case TOK_IDENT:
|
case TOK_IDENT:
|
||||||
/* This could be a label */
|
/* This could be a label */
|
||||||
if (NextTok.Tok != TOK_COLON || GetLexicalLevel () == LEX_LEVEL_STRUCT) {
|
if (NextTok.Tok != TOK_COLON || GetLexicalLevel () == LEX_LEVEL_STRUCT) {
|
||||||
Entry = FindSym (CurTok.Ident);
|
TagEntry = FindSym (CurTok.Ident);
|
||||||
if (Entry && SymIsTypeDef (Entry)) {
|
if (TagEntry && SymIsTypeDef (TagEntry)) {
|
||||||
/* It's a typedef */
|
/* It's a typedef */
|
||||||
NextToken ();
|
NextToken ();
|
||||||
TypeCopy (D->Type, Entry->Type);
|
TypeCopy (D->Type, TagEntry->Type);
|
||||||
/* If it's a typedef, we should actually use whether the signedness was
|
/* If it's a typedef, we should actually use whether the signedness was
|
||||||
** specified on the typedef, but that information has been lost. Treat the
|
** specified on the typedef, but that information has been lost. Treat the
|
||||||
** signedness as being specified to work around the ICE in #1267.
|
** signedness as being specified to work around the ICE in #1267.
|
||||||
@ -1592,19 +1590,19 @@ static void ParseOldStyleParamList (FuncDesc* F)
|
|||||||
if (Decl.Ident[0] != '\0') {
|
if (Decl.Ident[0] != '\0') {
|
||||||
|
|
||||||
/* We have a name given. Search for the symbol */
|
/* We have a name given. Search for the symbol */
|
||||||
SymEntry* Sym = FindLocalSym (Decl.Ident);
|
SymEntry* Param = FindLocalSym (Decl.Ident);
|
||||||
if (Sym) {
|
if (Param) {
|
||||||
/* Check if we already changed the type for this
|
/* Check if we already changed the type for this
|
||||||
** parameter
|
** parameter
|
||||||
*/
|
*/
|
||||||
if (Sym->Flags & SC_DEFTYPE) {
|
if (Param->Flags & SC_DEFTYPE) {
|
||||||
/* Found it, change the default type to the one given */
|
/* Found it, change the default type to the one given */
|
||||||
ChangeSymType (Sym, ParamTypeCvt (Decl.Type));
|
SymChangeType (Param, ParamTypeCvt (Decl.Type));
|
||||||
/* Reset the "default type" flag */
|
/* Reset the "default type" flag */
|
||||||
Sym->Flags &= ~SC_DEFTYPE;
|
Param->Flags &= ~SC_DEFTYPE;
|
||||||
} else {
|
} else {
|
||||||
/* Type has already been changed */
|
/* Type has already been changed */
|
||||||
Error ("Redefinition for parameter '%s'", Sym->Name);
|
Error ("Redefinition for parameter '%s'", Param->Name);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Error ("Unknown identifier: '%s'", Decl.Ident);
|
Error ("Unknown identifier: '%s'", Decl.Ident);
|
||||||
@ -1634,7 +1632,7 @@ static void ParseAnsiParamList (FuncDesc* F)
|
|||||||
|
|
||||||
DeclSpec Spec;
|
DeclSpec Spec;
|
||||||
Declaration Decl;
|
Declaration Decl;
|
||||||
SymEntry* Sym;
|
SymEntry* Param;
|
||||||
|
|
||||||
/* Allow an ellipsis as last parameter */
|
/* Allow an ellipsis as last parameter */
|
||||||
if (CurTok.Tok == TOK_ELLIPSIS) {
|
if (CurTok.Tok == TOK_ELLIPSIS) {
|
||||||
@ -1682,10 +1680,10 @@ static void ParseAnsiParamList (FuncDesc* F)
|
|||||||
ParseAttribute (&Decl);
|
ParseAttribute (&Decl);
|
||||||
|
|
||||||
/* Create a symbol table entry */
|
/* Create a symbol table entry */
|
||||||
Sym = AddLocalSym (Decl.Ident, ParamTypeCvt (Decl.Type), Decl.StorageClass, 0);
|
Param = AddLocalSym (Decl.Ident, ParamTypeCvt (Decl.Type), Decl.StorageClass, 0);
|
||||||
|
|
||||||
/* Add attributes if we have any */
|
/* Add attributes if we have any */
|
||||||
SymUseAttr (Sym, &Decl);
|
SymUseAttr (Param, &Decl);
|
||||||
|
|
||||||
/* If the parameter is a struct or union, emit a warning */
|
/* If the parameter is a struct or union, emit a warning */
|
||||||
if (IsClassStruct (Decl.Type)) {
|
if (IsClassStruct (Decl.Type)) {
|
||||||
|
@ -280,11 +280,10 @@ static unsigned ExprCheckedSizeOf (const Type* T)
|
|||||||
/* Specially checked SizeOf() used in 'sizeof' expressions */
|
/* Specially checked SizeOf() used in 'sizeof' expressions */
|
||||||
{
|
{
|
||||||
unsigned Size = SizeOf (T);
|
unsigned Size = SizeOf (T);
|
||||||
SymEntry* Sym;
|
|
||||||
|
|
||||||
if (Size == 0) {
|
if (Size == 0) {
|
||||||
Sym = GetSymType (T);
|
SymEntry* TagSym = GetESUTagSym (T);
|
||||||
if (Sym == 0 || !SymIsDef (Sym)) {
|
if (TagSym == 0 || !SymIsDef (TagSym)) {
|
||||||
Error ("Cannot apply 'sizeof' to incomplete type '%s'", GetFullTypeName (T));
|
Error ("Cannot apply 'sizeof' to incomplete type '%s'", GetFullTypeName (T));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -613,7 +613,7 @@ void NewFunc (SymEntry* Func, FuncDesc* D)
|
|||||||
/* Could we allocate a register? */
|
/* Could we allocate a register? */
|
||||||
if (Reg < 0) {
|
if (Reg < 0) {
|
||||||
/* No register available: Convert parameter to auto */
|
/* No register available: Convert parameter to auto */
|
||||||
CvtRegVarToAuto (Param);
|
SymCvtRegVarToAuto (Param);
|
||||||
} else {
|
} else {
|
||||||
/* Remember the register offset */
|
/* Remember the register offset */
|
||||||
Param->V.R.RegOffs = Reg;
|
Param->V.R.RegOffs = Reg;
|
||||||
|
@ -437,7 +437,7 @@ static unsigned ParseArrayInit (Type* T, int* Braces, int AllowFlexibleMembers)
|
|||||||
static unsigned ParseStructInit (Type* T, int* Braces, int AllowFlexibleMembers)
|
static unsigned ParseStructInit (Type* T, int* Braces, int AllowFlexibleMembers)
|
||||||
/* Parse initialization of a struct or union. Return the number of data bytes. */
|
/* Parse initialization of a struct or union. Return the number of data bytes. */
|
||||||
{
|
{
|
||||||
SymEntry* Sym;
|
SymEntry* TagSym;
|
||||||
SymTable* Tab;
|
SymTable* Tab;
|
||||||
StructInitData SI;
|
StructInitData SI;
|
||||||
int HasCurly = 0;
|
int HasCurly = 0;
|
||||||
@ -452,15 +452,15 @@ static unsigned ParseStructInit (Type* T, int* Braces, int AllowFlexibleMembers)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Get a pointer to the struct entry from the type */
|
/* Get a pointer to the struct entry from the type */
|
||||||
Sym = GetESUSymEntry (T);
|
TagSym = GetESUTagSym (T);
|
||||||
|
|
||||||
/* Get the size of the struct from the symbol table entry */
|
/* Get the size of the struct from the symbol table entry */
|
||||||
SI.Size = Sym->V.S.Size;
|
SI.Size = TagSym->V.S.Size;
|
||||||
|
|
||||||
/* Check if this struct definition has a field table. If it doesn't, it
|
/* Check if this struct definition has a field table. If it doesn't, it
|
||||||
** is an incomplete definition.
|
** is an incomplete definition.
|
||||||
*/
|
*/
|
||||||
Tab = Sym->V.S.SymTab;
|
Tab = TagSym->V.S.SymTab;
|
||||||
if (Tab == 0) {
|
if (Tab == 0) {
|
||||||
Error ("Cannot initialize variables with incomplete type");
|
Error ("Cannot initialize variables with incomplete type");
|
||||||
/* Try error recovery */
|
/* Try error recovery */
|
||||||
@ -470,7 +470,7 @@ static unsigned ParseStructInit (Type* T, int* Braces, int AllowFlexibleMembers)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Get a pointer to the list of symbols */
|
/* Get a pointer to the list of symbols */
|
||||||
Sym = Tab->SymHead;
|
TagSym = Tab->SymHead;
|
||||||
|
|
||||||
/* Initialize fields */
|
/* Initialize fields */
|
||||||
SI.Offs = 0;
|
SI.Offs = 0;
|
||||||
@ -479,7 +479,7 @@ static unsigned ParseStructInit (Type* T, int* Braces, int AllowFlexibleMembers)
|
|||||||
while (CurTok.Tok != TOK_RCURLY) {
|
while (CurTok.Tok != TOK_RCURLY) {
|
||||||
|
|
||||||
/* Check for excess elements */
|
/* Check for excess elements */
|
||||||
if (Sym == 0) {
|
if (TagSym == 0) {
|
||||||
/* Is there just one trailing comma before a closing curly? */
|
/* Is there just one trailing comma before a closing curly? */
|
||||||
if (NextTok.Tok == TOK_RCURLY && CurTok.Tok == TOK_COMMA) {
|
if (NextTok.Tok == TOK_RCURLY && CurTok.Tok == TOK_COMMA) {
|
||||||
/* Skip comma and exit scope */
|
/* Skip comma and exit scope */
|
||||||
@ -495,7 +495,7 @@ static unsigned ParseStructInit (Type* T, int* Braces, int AllowFlexibleMembers)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Check for special members that don't consume the initializer */
|
/* Check for special members that don't consume the initializer */
|
||||||
if ((Sym->Flags & SC_ALIAS) == SC_ALIAS) {
|
if ((TagSym->Flags & SC_ALIAS) == SC_ALIAS) {
|
||||||
/* Just skip */
|
/* Just skip */
|
||||||
goto NextMember;
|
goto NextMember;
|
||||||
}
|
}
|
||||||
@ -503,13 +503,13 @@ static unsigned ParseStructInit (Type* T, int* Braces, int AllowFlexibleMembers)
|
|||||||
/* This may be an anonymous bit-field, in which case it doesn't
|
/* This may be an anonymous bit-field, in which case it doesn't
|
||||||
** have an initializer.
|
** have an initializer.
|
||||||
*/
|
*/
|
||||||
if (SymIsBitField (Sym) && (IsAnonName (Sym->Name))) {
|
if (SymIsBitField (TagSym) && (IsAnonName (TagSym->Name))) {
|
||||||
/* Account for the data and output it if we have at least a full
|
/* Account for the data and output it if we have at least a full
|
||||||
** byte. We may have more if there was storage unit overlap, for
|
** byte. We may have more if there was storage unit overlap, for
|
||||||
** example two consecutive 7 bit fields. Those would be packed
|
** example two consecutive 7 bit fields. Those would be packed
|
||||||
** into 2 bytes.
|
** into 2 bytes.
|
||||||
*/
|
*/
|
||||||
SI.ValBits += Sym->Type->A.B.Width;
|
SI.ValBits += TagSym->Type->A.B.Width;
|
||||||
CHECK (SI.ValBits <= CHAR_BIT * sizeof(SI.BitVal));
|
CHECK (SI.ValBits <= CHAR_BIT * sizeof(SI.BitVal));
|
||||||
/* TODO: Generalize this so any type can be used. */
|
/* TODO: Generalize this so any type can be used. */
|
||||||
CHECK (SI.ValBits <= LONG_BITS);
|
CHECK (SI.ValBits <= LONG_BITS);
|
||||||
@ -526,7 +526,7 @@ static unsigned ParseStructInit (Type* T, int* Braces, int AllowFlexibleMembers)
|
|||||||
SkipComma = 0;
|
SkipComma = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (SymIsBitField (Sym)) {
|
if (SymIsBitField (TagSym)) {
|
||||||
|
|
||||||
/* Parse initialization of one field. Bit-fields need a special
|
/* Parse initialization of one field. Bit-fields need a special
|
||||||
** handling.
|
** handling.
|
||||||
@ -537,14 +537,14 @@ static unsigned ParseStructInit (Type* T, int* Braces, int AllowFlexibleMembers)
|
|||||||
unsigned Shift;
|
unsigned Shift;
|
||||||
|
|
||||||
/* Calculate the bitmask from the bit-field data */
|
/* Calculate the bitmask from the bit-field data */
|
||||||
unsigned long Mask = shl_l (1UL, Sym->Type->A.B.Width) - 1UL;
|
unsigned long Mask = shl_l (1UL, TagSym->Type->A.B.Width) - 1UL;
|
||||||
|
|
||||||
/* Safety ... */
|
/* Safety ... */
|
||||||
CHECK (Sym->V.Offs * CHAR_BITS + Sym->Type->A.B.Offs ==
|
CHECK (TagSym->V.Offs * CHAR_BITS + TagSym->Type->A.B.Offs ==
|
||||||
SI.Offs * CHAR_BITS + SI.ValBits);
|
SI.Offs * CHAR_BITS + SI.ValBits);
|
||||||
|
|
||||||
/* Read the data, check for a constant integer, do a range check */
|
/* Read the data, check for a constant integer, do a range check */
|
||||||
Field = ParseScalarInitInternal (IntPromotion (Sym->Type));
|
Field = ParseScalarInitInternal (IntPromotion (TagSym->Type));
|
||||||
if (!ED_IsConstAbsInt (&Field)) {
|
if (!ED_IsConstAbsInt (&Field)) {
|
||||||
Error ("Constant initializer expected");
|
Error ("Constant initializer expected");
|
||||||
ED_MakeConstAbsInt (&Field, 1);
|
ED_MakeConstAbsInt (&Field, 1);
|
||||||
@ -554,19 +554,19 @@ static unsigned ParseStructInit (Type* T, int* Braces, int AllowFlexibleMembers)
|
|||||||
** any useful bits.
|
** any useful bits.
|
||||||
*/
|
*/
|
||||||
Val = (unsigned long) Field.IVal & Mask;
|
Val = (unsigned long) Field.IVal & Mask;
|
||||||
if (IsSignUnsigned (Sym->Type)) {
|
if (IsSignUnsigned (TagSym->Type)) {
|
||||||
if (Field.IVal < 0 || (unsigned long) Field.IVal != Val) {
|
if (Field.IVal < 0 || (unsigned long) Field.IVal != Val) {
|
||||||
Warning (IsSignUnsigned (Field.Type) ?
|
Warning (IsSignUnsigned (Field.Type) ?
|
||||||
"Implicit truncation from '%s' to '%s : %u' in bit-field initializer"
|
"Implicit truncation from '%s' to '%s : %u' in bit-field initializer"
|
||||||
" changes value from %lu to %lu" :
|
" changes value from %lu to %lu" :
|
||||||
"Implicit truncation from '%s' to '%s : %u' in bit-field initializer"
|
"Implicit truncation from '%s' to '%s : %u' in bit-field initializer"
|
||||||
" changes value from %ld to %lu",
|
" changes value from %ld to %lu",
|
||||||
GetFullTypeName (Field.Type), GetFullTypeName (Sym->Type),
|
GetFullTypeName (Field.Type), GetFullTypeName (TagSym->Type),
|
||||||
Sym->Type->A.B.Width, Field.IVal, Val);
|
TagSym->Type->A.B.Width, Field.IVal, Val);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* Sign extend back to full width of host long. */
|
/* Sign extend back to full width of host long. */
|
||||||
unsigned ShiftBits = sizeof (long) * CHAR_BIT - Sym->Type->A.B.Width;
|
unsigned ShiftBits = sizeof (long) * CHAR_BIT - TagSym->Type->A.B.Width;
|
||||||
long RestoredVal = asr_l (asl_l (Val, ShiftBits), ShiftBits);
|
long RestoredVal = asr_l (asl_l (Val, ShiftBits), ShiftBits);
|
||||||
if (Field.IVal != RestoredVal) {
|
if (Field.IVal != RestoredVal) {
|
||||||
Warning (IsSignUnsigned (Field.Type) ?
|
Warning (IsSignUnsigned (Field.Type) ?
|
||||||
@ -574,17 +574,17 @@ static unsigned ParseStructInit (Type* T, int* Braces, int AllowFlexibleMembers)
|
|||||||
" changes value from %lu to %ld" :
|
" changes value from %lu to %ld" :
|
||||||
"Implicit truncation from '%s' to '%s : %u' in bit-field initializer"
|
"Implicit truncation from '%s' to '%s : %u' in bit-field initializer"
|
||||||
" changes value from %ld to %ld",
|
" changes value from %ld to %ld",
|
||||||
GetFullTypeName (Field.Type), GetFullTypeName (Sym->Type),
|
GetFullTypeName (Field.Type), GetFullTypeName (TagSym->Type),
|
||||||
Sym->Type->A.B.Width, Field.IVal, RestoredVal);
|
TagSym->Type->A.B.Width, Field.IVal, RestoredVal);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Add the value to the currently stored bit-field value */
|
/* Add the value to the currently stored bit-field value */
|
||||||
Shift = (Sym->V.Offs - SI.Offs) * CHAR_BITS + Sym->Type->A.B.Offs;
|
Shift = (TagSym->V.Offs - SI.Offs) * CHAR_BITS + TagSym->Type->A.B.Offs;
|
||||||
SI.BitVal |= (Val << Shift);
|
SI.BitVal |= (Val << Shift);
|
||||||
|
|
||||||
/* Account for the data and output any full bytes we have. */
|
/* Account for the data and output any full bytes we have. */
|
||||||
SI.ValBits += Sym->Type->A.B.Width;
|
SI.ValBits += TagSym->Type->A.B.Width;
|
||||||
/* Make sure unsigned is big enough to hold the value, 32 bits.
|
/* Make sure unsigned is big enough to hold the value, 32 bits.
|
||||||
** This cannot be more than 32 bits because a 16-bit or 32-bit
|
** This cannot be more than 32 bits because a 16-bit or 32-bit
|
||||||
** bit-field will always be byte-aligned with padding before it
|
** bit-field will always be byte-aligned with padding before it
|
||||||
@ -609,7 +609,7 @@ static unsigned ParseStructInit (Type* T, int* Braces, int AllowFlexibleMembers)
|
|||||||
/* Flexible array members may only be initialized if they are
|
/* Flexible array members may only be initialized if they are
|
||||||
** the last field (or part of the last struct field).
|
** the last field (or part of the last struct field).
|
||||||
*/
|
*/
|
||||||
SI.Offs += ParseInitInternal (Sym->Type, Braces, AllowFlexibleMembers && Sym->NextSym == 0);
|
SI.Offs += ParseInitInternal (TagSym->Type, Braces, AllowFlexibleMembers && TagSym->NextSym == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* More initializers? */
|
/* More initializers? */
|
||||||
@ -624,10 +624,10 @@ NextMember:
|
|||||||
/* Next member. For unions, only the first one can be initialized */
|
/* Next member. For unions, only the first one can be initialized */
|
||||||
if (IsTypeUnion (T)) {
|
if (IsTypeUnion (T)) {
|
||||||
/* Union */
|
/* Union */
|
||||||
Sym = 0;
|
TagSym = 0;
|
||||||
} else {
|
} else {
|
||||||
/* Struct */
|
/* Struct */
|
||||||
Sym = Sym->NextSym;
|
TagSym = TagSym->NextSym;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,6 +40,7 @@
|
|||||||
|
|
||||||
/* cc65 */
|
/* cc65 */
|
||||||
#include "anonname.h"
|
#include "anonname.h"
|
||||||
|
#include "asmlabel.h"
|
||||||
#include "declare.h"
|
#include "declare.h"
|
||||||
#include "error.h"
|
#include "error.h"
|
||||||
#include "symentry.h"
|
#include "symentry.h"
|
||||||
@ -65,13 +66,12 @@ SymEntry* NewSymEntry (const char* Name, unsigned Flags)
|
|||||||
E->NextHash = 0;
|
E->NextHash = 0;
|
||||||
E->PrevSym = 0;
|
E->PrevSym = 0;
|
||||||
E->NextSym = 0;
|
E->NextSym = 0;
|
||||||
E->Link = 0;
|
|
||||||
E->Owner = 0;
|
E->Owner = 0;
|
||||||
E->Flags = Flags;
|
E->Flags = Flags;
|
||||||
E->Type = 0;
|
E->Type = 0;
|
||||||
E->Attr = 0;
|
E->Attr = 0;
|
||||||
E->AsmName = 0;
|
E->AsmName = 0;
|
||||||
E->V.BssName = 0;
|
memset (&E->V, 0, sizeof (E->V));
|
||||||
memcpy (E->Name, Name, Len+1);
|
memcpy (E->Name, Name, Len+1);
|
||||||
|
|
||||||
/* Return the new entry */
|
/* Return the new entry */
|
||||||
@ -250,7 +250,9 @@ void SymUseAttr (SymEntry* Sym, struct Declaration* D)
|
|||||||
|
|
||||||
|
|
||||||
void SymSetAsmName (SymEntry* Sym)
|
void SymSetAsmName (SymEntry* Sym)
|
||||||
/* Set the assembler name for an external symbol from the name of the symbol */
|
/* Set the assembler name for an external symbol from the name of the symbol.
|
||||||
|
** The symbol must have no assembler name set yet.
|
||||||
|
*/
|
||||||
{
|
{
|
||||||
unsigned Len;
|
unsigned Len;
|
||||||
|
|
||||||
@ -266,7 +268,7 @@ void SymSetAsmName (SymEntry* Sym)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void CvtRegVarToAuto (SymEntry* Sym)
|
void SymCvtRegVarToAuto (SymEntry* Sym)
|
||||||
/* Convert a register variable to an auto variable */
|
/* Convert a register variable to an auto variable */
|
||||||
{
|
{
|
||||||
/* Change the storage class */
|
/* Change the storage class */
|
||||||
@ -278,59 +280,26 @@ void CvtRegVarToAuto (SymEntry* Sym)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
SymEntry* GetSymType (const Type* T)
|
void SymChangeType (SymEntry* Sym, const Type* T)
|
||||||
/* Get the symbol entry of the enum/struct/union type
|
|
||||||
** Return 0 if it is not an enum/struct/union.
|
|
||||||
*/
|
|
||||||
{
|
|
||||||
if ((IsClassStruct (T) || IsTypeEnum (T))) {
|
|
||||||
return T->A.S;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const char* GetSymTypeName (const Type* T)
|
|
||||||
/* Return a name string of the type or the symbol name if it is an ESU type.
|
|
||||||
** Note: This may use a static buffer that could be overwritten by other calls.
|
|
||||||
*/
|
|
||||||
{
|
|
||||||
static char TypeName [IDENTSIZE + 16];
|
|
||||||
SymEntry* Sym;
|
|
||||||
|
|
||||||
Sym = GetSymType (T);
|
|
||||||
if (Sym == 0) {
|
|
||||||
return GetBasicTypeName (T);
|
|
||||||
}
|
|
||||||
sprintf (TypeName, "%s %s", GetBasicTypeName (T),
|
|
||||||
Sym->Name[0] != '\0' ? Sym->Name : "<unknown>");
|
|
||||||
|
|
||||||
return TypeName;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void ChangeSymType (SymEntry* Entry, const Type* T)
|
|
||||||
/* Change the type of the given symbol */
|
/* Change the type of the given symbol */
|
||||||
{
|
{
|
||||||
TypeFree (Entry->Type);
|
TypeFree (Sym->Type);
|
||||||
Entry->Type = TypeDup (T);
|
Sym->Type = TypeDup (T);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void ChangeAsmName (SymEntry* Entry, const char* NewAsmName)
|
void SymChangeAsmName (SymEntry* Sym, const char* NewAsmName)
|
||||||
/* Change the assembler name of the symbol */
|
/* Change the assembler name of the symbol */
|
||||||
{
|
{
|
||||||
xfree (Entry->AsmName);
|
xfree (Sym->AsmName);
|
||||||
Entry->AsmName = xstrdup (NewAsmName);
|
Sym->AsmName = xstrdup (NewAsmName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int HasAnonName (const SymEntry* Entry)
|
int SymHasAnonName (const SymEntry* Sym)
|
||||||
/* Return true if the symbol entry has an anonymous name */
|
/* Return true if the symbol entry has an anonymous name */
|
||||||
{
|
{
|
||||||
return IsAnonName (Entry->Name);
|
return IsAnonName (Sym->Name);
|
||||||
}
|
}
|
||||||
|
@ -128,7 +128,6 @@ struct SymEntry {
|
|||||||
SymEntry* NextHash; /* Next entry in hash list */
|
SymEntry* NextHash; /* Next entry in hash list */
|
||||||
SymEntry* PrevSym; /* Previous symbol in dl list */
|
SymEntry* PrevSym; /* Previous symbol in dl list */
|
||||||
SymEntry* NextSym; /* Next symbol double linked list */
|
SymEntry* NextSym; /* Next symbol double linked list */
|
||||||
SymEntry* Link; /* General purpose single linked list */
|
|
||||||
struct SymTable* Owner; /* Symbol table the symbol is in */
|
struct SymTable* Owner; /* Symbol table the symbol is in */
|
||||||
unsigned Flags; /* Symbol flags */
|
unsigned Flags; /* Symbol flags */
|
||||||
Type* Type; /* Symbol type */
|
Type* Type; /* Symbol type */
|
||||||
@ -138,27 +137,9 @@ struct SymEntry {
|
|||||||
/* Data that differs for the different symbol types */
|
/* Data that differs for the different symbol types */
|
||||||
union {
|
union {
|
||||||
|
|
||||||
/* Offset for locals or struct members */
|
/* Offset for locals */
|
||||||
int Offs;
|
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;
|
|
||||||
Collection *DefsOrRefs;
|
|
||||||
struct CodeEntry *IndJumpFrom;
|
|
||||||
} L;
|
|
||||||
|
|
||||||
/* Value of SP adjustment needed after forward 'goto' */
|
|
||||||
unsigned short SPAdjustment;
|
|
||||||
|
|
||||||
/* Register bank offset and offset of the saved copy on stack for
|
/* Register bank offset and offset of the saved copy on stack for
|
||||||
** register variables.
|
** register variables.
|
||||||
*/
|
*/
|
||||||
@ -167,32 +148,50 @@ struct SymEntry {
|
|||||||
int SaveOffs;
|
int SaveOffs;
|
||||||
} R;
|
} R;
|
||||||
|
|
||||||
/* Value for constants (including enums) */
|
/* Segment name for tentantive global definitions */
|
||||||
|
const char* BssName;
|
||||||
|
|
||||||
|
/* Value for integer constants (including enumerators) */
|
||||||
long ConstVal;
|
long ConstVal;
|
||||||
|
|
||||||
/* Data for structs/unions */
|
|
||||||
struct {
|
|
||||||
struct SymTable* SymTab; /* Member symbol table */
|
|
||||||
unsigned Size; /* Size of the union/struct */
|
|
||||||
unsigned ACount; /* Count of anonymous fields */
|
|
||||||
} S;
|
|
||||||
|
|
||||||
/* Data for enums */
|
|
||||||
struct {
|
|
||||||
struct SymTable* SymTab; /* Member symbol table */
|
|
||||||
const Type* Type; /* Underlying type */
|
|
||||||
} E;
|
|
||||||
|
|
||||||
/* Data for functions */
|
/* Data for functions */
|
||||||
struct {
|
struct {
|
||||||
struct Segments* Seg; /* Segments for this function */
|
struct Segments* Seg; /* Segments for this function */
|
||||||
struct LiteralPool* LitPool; /* Literal pool for this function */
|
struct LiteralPool* LitPool; /* Literal pool for this function */
|
||||||
} F;
|
} F;
|
||||||
|
|
||||||
/* Segment name for tentantive global definitions */
|
/* Label name for static symbols */
|
||||||
const char* BssName;
|
struct {
|
||||||
|
unsigned Label;
|
||||||
|
Collection *DefsOrRefs;
|
||||||
|
struct CodeEntry *IndJumpFrom;
|
||||||
|
} L;
|
||||||
|
|
||||||
|
/* Value of SP adjustment needed after forward 'goto' */
|
||||||
|
unsigned short SPAdjustment;
|
||||||
|
|
||||||
|
/* 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;
|
||||||
|
|
||||||
|
/* Data for structs/unions tags */
|
||||||
|
struct {
|
||||||
|
struct SymTable* SymTab; /* Member symbol table */
|
||||||
|
unsigned Size; /* Size of the union/struct */
|
||||||
|
unsigned ACount; /* Count of anonymous fields */
|
||||||
|
} S;
|
||||||
|
|
||||||
|
/* Data for enums tags */
|
||||||
|
struct {
|
||||||
|
struct SymTable* SymTab; /* Member symbol table */
|
||||||
|
const Type* Type; /* Underlying type */
|
||||||
|
} E;
|
||||||
|
|
||||||
} V;
|
} V;
|
||||||
char Name[1]; /* Name, dynamically allocated */
|
char Name[1]; /* Name, dynamically allocated */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -303,28 +302,20 @@ void SymUseAttr (SymEntry* Sym, struct Declaration* D);
|
|||||||
/* Use the attributes from the declaration for this symbol */
|
/* Use the attributes from the declaration for this symbol */
|
||||||
|
|
||||||
void SymSetAsmName (SymEntry* Sym);
|
void SymSetAsmName (SymEntry* Sym);
|
||||||
/* Set the assembler name for an external symbol from the name of the symbol */
|
/* Set the assembler name for an external symbol from the name of the symbol.
|
||||||
|
** The symbol must have no assembler name set yet.
|
||||||
|
*/
|
||||||
|
|
||||||
void CvtRegVarToAuto (SymEntry* Sym);
|
void SymCvtRegVarToAuto (SymEntry* Sym);
|
||||||
/* Convert a register variable to an auto variable */
|
/* Convert a register variable to an auto variable */
|
||||||
|
|
||||||
SymEntry* GetSymType (const Type* T);
|
void SymChangeType (SymEntry* Sym, const Type* T);
|
||||||
/* Get the symbol entry of the enum/struct/union type
|
|
||||||
** Return 0 if it is not an enum/struct/union.
|
|
||||||
*/
|
|
||||||
|
|
||||||
const char* GetSymTypeName (const Type* T);
|
|
||||||
/* Return a name string of the type or the symbol name if it is an ESU type.
|
|
||||||
** Note: This may use a static buffer that could be overwritten by other calls.
|
|
||||||
*/
|
|
||||||
|
|
||||||
void ChangeSymType (SymEntry* Entry, const Type* T);
|
|
||||||
/* Change the type of the given symbol */
|
/* Change the type of the given symbol */
|
||||||
|
|
||||||
void ChangeAsmName (SymEntry* Entry, const char* NewAsmName);
|
void SymChangeAsmName (SymEntry* Sym, const char* NewAsmName);
|
||||||
/* Change the assembler name of the symbol */
|
/* Change the assembler name of the symbol */
|
||||||
|
|
||||||
int HasAnonName (const SymEntry* Entry);
|
int SymHasAnonName (const SymEntry* Sym);
|
||||||
/* Return true if the symbol entry has an anonymous name */
|
/* Return true if the symbol entry has an anonymous name */
|
||||||
|
|
||||||
|
|
||||||
|
@ -625,8 +625,8 @@ SymEntry FindStructField (const Type* T, const char* Name)
|
|||||||
** value, or an empty entry struct if the field is not found.
|
** value, or an empty entry struct if the field is not found.
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
SymEntry* Entry = 0;
|
SymEntry* Field = 0;
|
||||||
SymEntry Field;
|
SymEntry Res;
|
||||||
int Offs = 0;
|
int Offs = 0;
|
||||||
|
|
||||||
/* The given type may actually be a pointer to struct/union */
|
/* The given type may actually be a pointer to struct/union */
|
||||||
@ -637,35 +637,35 @@ SymEntry FindStructField (const Type* T, const char* Name)
|
|||||||
/* Only structs/unions have struct/union fields... */
|
/* Only structs/unions have struct/union fields... */
|
||||||
if (IsClassStruct (T)) {
|
if (IsClassStruct (T)) {
|
||||||
|
|
||||||
/* Get a pointer to the struct/union type */
|
/* Get a pointer to the struct/union tag */
|
||||||
const SymEntry* Struct = GetESUSymEntry (T);
|
const SymEntry* TagSym = GetESUTagSym (T);
|
||||||
CHECK (Struct != 0);
|
CHECK (TagSym != 0);
|
||||||
|
|
||||||
/* Now search in the struct/union symbol table. Beware: The table may
|
/* Now search in the struct/union symbol table. Beware: The table may
|
||||||
** not exist.
|
** not exist.
|
||||||
*/
|
*/
|
||||||
if (Struct->V.S.SymTab) {
|
if (TagSym->V.S.SymTab) {
|
||||||
Entry = FindSymInTable (Struct->V.S.SymTab, Name, HashStr (Name));
|
Field = FindSymInTable (TagSym->V.S.SymTab, Name, HashStr (Name));
|
||||||
|
|
||||||
if (Entry != 0) {
|
if (Field != 0) {
|
||||||
Offs = Entry->V.Offs;
|
Offs = Field->V.Offs;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (Entry != 0 && (Entry->Flags & SC_ALIAS) == SC_ALIAS) {
|
while (Field != 0 && (Field->Flags & SC_ALIAS) == SC_ALIAS) {
|
||||||
/* Get the real field */
|
/* Get the real field */
|
||||||
Entry = Entry->V.A.Field;
|
Field = Field->V.A.Field;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Entry != 0) {
|
if (Field != 0) {
|
||||||
Field = *Entry;
|
Res = *Field;
|
||||||
Field.V.Offs = Offs;
|
Res.V.Offs = Offs;
|
||||||
} else {
|
} else {
|
||||||
memset (&Field, 0, sizeof(SymEntry));
|
memset (&Res, 0, sizeof(SymEntry));
|
||||||
}
|
}
|
||||||
|
|
||||||
return Field;
|
return Res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -689,15 +689,15 @@ static int IsDistinctRedef (const Type* lhst, const Type* rhst, typecmpcode_t Co
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int HandleSymRedefinition (SymEntry* Entry, const Type* T, unsigned Flags)
|
static int HandleSymRedefinition (SymEntry* Sym, const Type* T, unsigned Flags)
|
||||||
/* Check and handle redefinition of existing symbols.
|
/* Check and handle redefinition of existing symbols.
|
||||||
** Complete array sizes and function descriptors as well.
|
** Complete array sizes and function descriptors as well.
|
||||||
** Return true if there *is* an error.
|
** Return true if there *is* an error.
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
/* Get the type info of the existing symbol */
|
/* Get the type info of the existing symbol */
|
||||||
Type* E_Type = Entry->Type;
|
Type* E_Type = Sym->Type;
|
||||||
unsigned E_SCType = Entry->Flags & SC_TYPEMASK;
|
unsigned E_SCType = Sym->Flags & SC_TYPEMASK;
|
||||||
unsigned SCType = Flags & SC_TYPEMASK;
|
unsigned SCType = Flags & SC_TYPEMASK;
|
||||||
|
|
||||||
/* Some symbols may be redeclared if certain requirements are met */
|
/* Some symbols may be redeclared if certain requirements are met */
|
||||||
@ -706,16 +706,16 @@ static int HandleSymRedefinition (SymEntry* Entry, const Type* T, unsigned Flags
|
|||||||
/* Existing typedefs cannot be redeclared as anything different */
|
/* Existing typedefs cannot be redeclared as anything different */
|
||||||
if (SCType == SC_TYPEDEF) {
|
if (SCType == SC_TYPEDEF) {
|
||||||
if (IsDistinctRedef (E_Type, T, TC_IDENTICAL, TCF_MASK_QUAL)) {
|
if (IsDistinctRedef (E_Type, T, TC_IDENTICAL, TCF_MASK_QUAL)) {
|
||||||
Error ("Conflicting types for typedef '%s'", Entry->Name);
|
Error ("Conflicting types for typedef '%s'", Sym->Name);
|
||||||
Note ("'%s' vs '%s'", GetFullTypeName (T), GetFullTypeName (E_Type));
|
Note ("'%s' vs '%s'", GetFullTypeName (T), GetFullTypeName (E_Type));
|
||||||
Entry = 0;
|
Sym = 0;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Error ("Redefinition of typedef '%s' as different kind of symbol", Entry->Name);
|
Error ("Redefinition of typedef '%s' as different kind of symbol", Sym->Name);
|
||||||
Entry = 0;
|
Sym = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if ((Entry->Flags & SC_FUNC) == SC_FUNC) {
|
} else if ((Sym->Flags & SC_FUNC) == SC_FUNC) {
|
||||||
|
|
||||||
/* In case of a function, use the new type descriptor, since it
|
/* In case of a function, use the new type descriptor, since it
|
||||||
** contains pointers to the new symbol tables that are needed if
|
** contains pointers to the new symbol tables that are needed if
|
||||||
@ -726,27 +726,27 @@ static int HandleSymRedefinition (SymEntry* Entry, const Type* T, unsigned Flags
|
|||||||
if (IsTypeFunc (T)) {
|
if (IsTypeFunc (T)) {
|
||||||
|
|
||||||
/* Check for duplicate function definitions */
|
/* Check for duplicate function definitions */
|
||||||
if (SymIsDef (Entry) && (Flags & SC_DEF) == SC_DEF) {
|
if (SymIsDef (Sym) && (Flags & SC_DEF) == SC_DEF) {
|
||||||
Error ("Body for function '%s' has already been defined",
|
Error ("Body for function '%s' has already been defined",
|
||||||
Entry->Name);
|
Sym->Name);
|
||||||
Entry = 0;
|
Sym = 0;
|
||||||
} else {
|
} else {
|
||||||
/* New type must be compatible with the composite prototype */
|
/* New type must be compatible with the composite prototype */
|
||||||
if (IsDistinctRedef (E_Type, T, TC_EQUAL, TCF_MASK_QUAL)) {
|
if (IsDistinctRedef (E_Type, T, TC_EQUAL, TCF_MASK_QUAL)) {
|
||||||
Error ("Conflicting function types for '%s'", Entry->Name);
|
Error ("Conflicting function types for '%s'", Sym->Name);
|
||||||
Note ("'%s' vs '%s'", GetFullTypeName (T), GetFullTypeName (E_Type));
|
Note ("'%s' vs '%s'", GetFullTypeName (T), GetFullTypeName (E_Type));
|
||||||
Entry = 0;
|
Sym = 0;
|
||||||
} else {
|
} else {
|
||||||
/* Refine the existing composite prototype with this new
|
/* Refine the existing composite prototype with this new
|
||||||
** one.
|
** one.
|
||||||
*/
|
*/
|
||||||
RefineFuncDesc (Entry->Type, T);
|
RefineFuncDesc (Sym->Type, T);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
Error ("Redefinition of function '%s' as different kind of symbol", Entry->Name);
|
Error ("Redefinition of function '%s' as different kind of symbol", Sym->Name);
|
||||||
Entry = 0;
|
Sym = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
@ -765,9 +765,9 @@ static int HandleSymRedefinition (SymEntry* Entry, const Type* T, unsigned Flags
|
|||||||
if ((Size != UNSPECIFIED && ESize != UNSPECIFIED && Size != ESize) ||
|
if ((Size != UNSPECIFIED && ESize != UNSPECIFIED && Size != ESize) ||
|
||||||
IsDistinctRedef (E_Type + 1, T + 1, TC_IDENTICAL, TCF_MASK_QUAL)) {
|
IsDistinctRedef (E_Type + 1, T + 1, TC_IDENTICAL, TCF_MASK_QUAL)) {
|
||||||
/* Conflicting element types */
|
/* Conflicting element types */
|
||||||
Error ("Conflicting array types for '%s[]'", Entry->Name);
|
Error ("Conflicting array types for '%s[]'", Sym->Name);
|
||||||
Note ("'%s' vs '%s'", GetFullTypeName (T), GetFullTypeName (E_Type));
|
Note ("'%s' vs '%s'", GetFullTypeName (T), GetFullTypeName (E_Type));
|
||||||
Entry = 0;
|
Sym = 0;
|
||||||
} else {
|
} else {
|
||||||
/* Check if we have a size in the existing definition */
|
/* Check if we have a size in the existing definition */
|
||||||
if (ESize == UNSPECIFIED) {
|
if (ESize == UNSPECIFIED) {
|
||||||
@ -780,25 +780,25 @@ static int HandleSymRedefinition (SymEntry* Entry, const Type* T, unsigned Flags
|
|||||||
|
|
||||||
/* New type must be equivalent */
|
/* New type must be equivalent */
|
||||||
if (SCType != E_SCType) {
|
if (SCType != E_SCType) {
|
||||||
Error ("Redefinition of '%s' as different kind of symbol", Entry->Name);
|
Error ("Redefinition of '%s' as different kind of symbol", Sym->Name);
|
||||||
Entry = 0;
|
Sym = 0;
|
||||||
} else if (IsDistinctRedef (E_Type, T, TC_EQUAL, TCF_MASK_QUAL)) {
|
} else if (IsDistinctRedef (E_Type, T, TC_EQUAL, TCF_MASK_QUAL)) {
|
||||||
Error ("Conflicting types for '%s'", Entry->Name);
|
Error ("Conflicting types for '%s'", Sym->Name);
|
||||||
Note ("'%s' vs '%s'", GetFullTypeName (T), GetFullTypeName (E_Type));
|
Note ("'%s' vs '%s'", GetFullTypeName (T), GetFullTypeName (E_Type));
|
||||||
Entry = 0;
|
Sym = 0;
|
||||||
} else if (E_SCType == SC_ENUMERATOR) {
|
} else if (E_SCType == SC_ENUMERATOR) {
|
||||||
/* Enumerators aren't allowed to be redeclared at all, even if
|
/* Enumerators aren't allowed to be redeclared at all, even if
|
||||||
** all occurences are identical. The current code logic won't
|
** all occurences are identical. The current code logic won't
|
||||||
** get here, but let's just do it.
|
** get here, but let's just do it.
|
||||||
*/
|
*/
|
||||||
Error ("Redeclaration of enumerator constant '%s'", Entry->Name);
|
Error ("Redeclaration of enumerator constant '%s'", Sym->Name);
|
||||||
Entry = 0;
|
Sym = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return if there are any errors */
|
/* Return if there are any errors */
|
||||||
return Entry == 0;
|
return Sym == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -832,38 +832,38 @@ static void AddSymEntry (SymTable* T, SymEntry* S)
|
|||||||
|
|
||||||
|
|
||||||
SymEntry* AddEnumSym (const char* Name, unsigned Flags, const Type* Type, SymTable* Tab, unsigned* DSFlags)
|
SymEntry* AddEnumSym (const char* Name, unsigned Flags, const Type* Type, SymTable* Tab, unsigned* DSFlags)
|
||||||
/* Add an enum entry and return it */
|
/* Add an enum tag entry and return it */
|
||||||
{
|
{
|
||||||
SymTable* CurTagTab = TagTab;
|
SymTable* CurTagTab = TagTab;
|
||||||
SymEntry* Entry;
|
SymEntry* TagEntry;
|
||||||
|
|
||||||
if ((Flags & SC_FICTITIOUS) == 0) {
|
if ((Flags & SC_FICTITIOUS) == 0) {
|
||||||
/* Do we have an entry with this name already? */
|
/* Do we have an entry with this name already? */
|
||||||
Entry = FindSymInTable (CurTagTab, Name, HashStr (Name));
|
TagEntry = FindSymInTable (CurTagTab, Name, HashStr (Name));
|
||||||
} else {
|
} else {
|
||||||
/* Add a fictitious symbol in the fail-safe table */
|
/* Add a fictitious symbol in the fail-safe table */
|
||||||
Entry = 0;
|
TagEntry = 0;
|
||||||
CurTagTab = FailSafeTab;
|
CurTagTab = FailSafeTab;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Entry) {
|
if (TagEntry) {
|
||||||
|
|
||||||
/* We do have an entry. This may be a forward, so check it. */
|
/* We do have an entry. This may be a forward, so check it. */
|
||||||
if ((Entry->Flags & SC_TYPEMASK) != SC_ENUM) {
|
if ((TagEntry->Flags & SC_TYPEMASK) != SC_ENUM) {
|
||||||
/* Existing symbol is not an enum */
|
/* Existing symbol is not an enum */
|
||||||
Error ("Symbol '%s' is already different kind", Name);
|
Error ("Symbol '%s' is already different kind", Name);
|
||||||
Entry = 0;
|
TagEntry = 0;
|
||||||
} else if (Type != 0) {
|
} else if (Type != 0) {
|
||||||
/* Define the struct size if the underlying type is given. */
|
/* Define the struct size if the underlying type is given. */
|
||||||
if (Entry->V.E.Type != 0) {
|
if (TagEntry->V.E.Type != 0) {
|
||||||
/* Both are definitions. */
|
/* Both are definitions. */
|
||||||
Error ("Multiple definition for 'enum %s'", Name);
|
Error ("Multiple definition for 'enum %s'", Name);
|
||||||
Entry = 0;
|
TagEntry = 0;
|
||||||
} else {
|
} else {
|
||||||
Entry->V.E.SymTab = Tab;
|
TagEntry->V.E.SymTab = Tab;
|
||||||
Entry->V.E.Type = Type;
|
TagEntry->V.E.Type = Type;
|
||||||
Entry->Flags &= ~SC_DECL;
|
TagEntry->Flags &= ~SC_DECL;
|
||||||
Entry->Flags |= SC_DEF;
|
TagEntry->Flags |= SC_DEF;
|
||||||
|
|
||||||
/* Remember this is the first definition of this type */
|
/* Remember this is the first definition of this type */
|
||||||
if (DSFlags != 0) {
|
if (DSFlags != 0) {
|
||||||
@ -872,83 +872,83 @@ SymEntry* AddEnumSym (const char* Name, unsigned Flags, const Type* Type, SymTab
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Entry == 0) {
|
if (TagEntry == 0) {
|
||||||
/* Use the fail-safe table for fictitious symbols */
|
/* Use the fail-safe table for fictitious symbols */
|
||||||
CurTagTab = FailSafeTab;
|
CurTagTab = FailSafeTab;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Entry == 0) {
|
if (TagEntry == 0) {
|
||||||
|
|
||||||
/* Create a new entry */
|
/* Create a new entry */
|
||||||
Entry = NewSymEntry (Name, SC_ENUM);
|
TagEntry = NewSymEntry (Name, SC_ENUM);
|
||||||
|
|
||||||
/* Set the enum type data */
|
/* Set the enum type data */
|
||||||
Entry->V.E.SymTab = Tab;
|
TagEntry->V.E.SymTab = Tab;
|
||||||
Entry->V.E.Type = Type;
|
TagEntry->V.E.Type = Type;
|
||||||
|
|
||||||
if (Type != 0) {
|
if (Type != 0) {
|
||||||
Entry->Flags |= SC_DEF;
|
TagEntry->Flags |= SC_DEF;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Remember this is the first definition of this type */
|
/* Remember this is the first definition of this type */
|
||||||
if (CurTagTab != FailSafeTab && DSFlags != 0) {
|
if (CurTagTab != FailSafeTab && DSFlags != 0) {
|
||||||
if ((Entry->Flags & SC_DEF) != 0) {
|
if ((TagEntry->Flags & SC_DEF) != 0) {
|
||||||
*DSFlags |= DS_NEW_TYPE_DEF;
|
*DSFlags |= DS_NEW_TYPE_DEF;
|
||||||
}
|
}
|
||||||
*DSFlags |= DS_NEW_TYPE_DECL;
|
*DSFlags |= DS_NEW_TYPE_DECL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Add it to the current table */
|
/* Add it to the current table */
|
||||||
AddSymEntry (CurTagTab, Entry);
|
AddSymEntry (CurTagTab, TagEntry);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return the entry */
|
/* Return the entry */
|
||||||
return Entry;
|
return TagEntry;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
SymEntry* AddStructSym (const char* Name, unsigned Flags, unsigned Size, SymTable* Tab, unsigned* DSFlags)
|
SymEntry* AddStructSym (const char* Name, unsigned Flags, unsigned Size, SymTable* Tab, unsigned* DSFlags)
|
||||||
/* Add a struct/union entry and return it */
|
/* Add a struct/union tag entry and return it */
|
||||||
{
|
{
|
||||||
SymTable* CurTagTab = TagTab;
|
SymTable* CurTagTab = TagTab;
|
||||||
SymEntry* Entry;
|
SymEntry* TagEntry;
|
||||||
unsigned Type = (Flags & SC_TYPEMASK);
|
unsigned SCType = (Flags & SC_TYPEMASK);
|
||||||
|
|
||||||
/* Type must be struct or union */
|
/* SCType must be struct or union */
|
||||||
PRECONDITION (Type == SC_STRUCT || Type == SC_UNION);
|
PRECONDITION (SCType == SC_STRUCT || SCType == SC_UNION);
|
||||||
|
|
||||||
if ((Flags & SC_FICTITIOUS) == 0) {
|
if ((Flags & SC_FICTITIOUS) == 0) {
|
||||||
/* Do we have an entry with this name already? */
|
/* Do we have an entry with this name already? */
|
||||||
Entry = FindSymInTable (CurTagTab, Name, HashStr (Name));
|
TagEntry = FindSymInTable (CurTagTab, Name, HashStr (Name));
|
||||||
} else {
|
} else {
|
||||||
/* Add a fictitious symbol in the fail-safe table */
|
/* Add a fictitious symbol in the fail-safe table */
|
||||||
Entry = 0;
|
TagEntry = 0;
|
||||||
CurTagTab = FailSafeTab;
|
CurTagTab = FailSafeTab;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Entry) {
|
if (TagEntry) {
|
||||||
|
|
||||||
/* We do have an entry. This may be a forward, so check it. */
|
/* We do have an entry. This may be a forward, so check it. */
|
||||||
if ((Entry->Flags & SC_TYPEMASK) != Type) {
|
if ((TagEntry->Flags & SC_TYPEMASK) != SCType) {
|
||||||
/* Existing symbol is not a struct */
|
/* Existing symbol is not a struct */
|
||||||
Error ("Symbol '%s' is already different kind", Name);
|
Error ("Symbol '%s' is already different kind", Name);
|
||||||
Entry = 0;
|
TagEntry = 0;
|
||||||
} else if ((Entry->Flags & Flags & SC_DEF) == SC_DEF) {
|
} else if ((TagEntry->Flags & Flags & SC_DEF) == SC_DEF) {
|
||||||
/* Both structs are definitions. */
|
/* Both structs are definitions. */
|
||||||
if (Type == SC_STRUCT) {
|
if (SCType == SC_STRUCT) {
|
||||||
Error ("Multiple definition for 'struct %s'", Name);
|
Error ("Multiple definition for 'struct %s'", Name);
|
||||||
} else {
|
} else {
|
||||||
Error ("Multiple definition for 'union %s'", Name);
|
Error ("Multiple definition for 'union %s'", Name);
|
||||||
}
|
}
|
||||||
Entry = 0;
|
TagEntry = 0;
|
||||||
} else {
|
} else {
|
||||||
/* Define the struct size if it is a definition */
|
/* Define the struct size if it is a definition */
|
||||||
if ((Flags & SC_DEF) == SC_DEF) {
|
if ((Flags & SC_DEF) == SC_DEF) {
|
||||||
Entry->Flags = Flags;
|
TagEntry->Flags = Flags;
|
||||||
Entry->V.S.SymTab = Tab;
|
TagEntry->V.S.SymTab = Tab;
|
||||||
Entry->V.S.Size = Size;
|
TagEntry->V.S.Size = Size;
|
||||||
|
|
||||||
/* Remember this is the first definition of this type */
|
/* Remember this is the first definition of this type */
|
||||||
if (DSFlags != 0) {
|
if (DSFlags != 0) {
|
||||||
@ -957,35 +957,35 @@ SymEntry* AddStructSym (const char* Name, unsigned Flags, unsigned Size, SymTabl
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Entry == 0) {
|
if (TagEntry == 0) {
|
||||||
/* Use the fail-safe table for fictitious symbols */
|
/* Use the fail-safe table for fictitious symbols */
|
||||||
CurTagTab = FailSafeTab;
|
CurTagTab = FailSafeTab;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Entry == 0) {
|
if (TagEntry == 0) {
|
||||||
|
|
||||||
/* Create a new entry */
|
/* Create a new entry */
|
||||||
Entry = NewSymEntry (Name, Flags);
|
TagEntry = NewSymEntry (Name, Flags);
|
||||||
|
|
||||||
/* Set the struct data */
|
/* Set the struct data */
|
||||||
Entry->V.S.SymTab = Tab;
|
TagEntry->V.S.SymTab = Tab;
|
||||||
Entry->V.S.Size = Size;
|
TagEntry->V.S.Size = Size;
|
||||||
|
|
||||||
/* Remember this is the first definition of this type */
|
/* Remember this is the first definition of this type */
|
||||||
if (CurTagTab != FailSafeTab && DSFlags != 0) {
|
if (CurTagTab != FailSafeTab && DSFlags != 0) {
|
||||||
if ((Entry->Flags & SC_DEF) != 0) {
|
if ((TagEntry->Flags & SC_DEF) != 0) {
|
||||||
*DSFlags |= DS_NEW_TYPE_DEF;
|
*DSFlags |= DS_NEW_TYPE_DEF;
|
||||||
}
|
}
|
||||||
*DSFlags |= DS_NEW_TYPE_DECL;
|
*DSFlags |= DS_NEW_TYPE_DECL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Add it to the current tag table */
|
/* Add it to the current tag table */
|
||||||
AddSymEntry (CurTagTab, Entry);
|
AddSymEntry (CurTagTab, TagEntry);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return the entry */
|
/* Return the entry */
|
||||||
return Entry;
|
return TagEntry;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -169,10 +169,10 @@ unsigned short FindSPAdjustment (const char* Name);
|
|||||||
|
|
||||||
|
|
||||||
SymEntry* AddEnumSym (const char* Name, unsigned Flags, const Type* Type, SymTable* Tab, unsigned* DSFlags);
|
SymEntry* AddEnumSym (const char* Name, unsigned Flags, const Type* Type, SymTable* Tab, unsigned* DSFlags);
|
||||||
/* Add an enum entry and return it */
|
/* Add an enum tag entry and return it */
|
||||||
|
|
||||||
SymEntry* AddStructSym (const char* Name, unsigned Flags, unsigned Size, SymTable* Tab, unsigned* DSFlags);
|
SymEntry* AddStructSym (const char* Name, unsigned Flags, unsigned Size, SymTable* Tab, unsigned* DSFlags);
|
||||||
/* Add a struct/union entry and return it */
|
/* Add a struct/union tag entry and return it */
|
||||||
|
|
||||||
SymEntry* AddBitField (const char* Name, const Type* Type, unsigned Offs,
|
SymEntry* AddBitField (const char* Name, const Type* Type, unsigned Offs,
|
||||||
unsigned BitOffs, unsigned BitWidth, int SignednessSpecified);
|
unsigned BitOffs, unsigned BitWidth, int SignednessSpecified);
|
||||||
|
@ -303,8 +303,8 @@ static void DoCompare (const Type* lhs, const Type* rhs, typecmp_t* Result)
|
|||||||
if ((IsTypeEnum (lhs) || IsTypeEnum (rhs))) {
|
if ((IsTypeEnum (lhs) || IsTypeEnum (rhs))) {
|
||||||
|
|
||||||
/* Compare the tag types */
|
/* Compare the tag types */
|
||||||
Sym1 = IsTypeEnum (lhs) ? GetESUSymEntry (lhs) : 0;
|
Sym1 = IsTypeEnum (lhs) ? GetESUTagSym (lhs) : 0;
|
||||||
Sym2 = IsTypeEnum (rhs) ? GetESUSymEntry (rhs) : 0;
|
Sym2 = IsTypeEnum (rhs) ? GetESUTagSym (rhs) : 0;
|
||||||
|
|
||||||
if (Sym1 != Sym2) {
|
if (Sym1 != Sym2) {
|
||||||
if (Sym1 == 0 || Sym2 == 0) {
|
if (Sym1 == 0 || Sym2 == 0) {
|
||||||
@ -420,8 +420,8 @@ static void DoCompare (const Type* lhs, const Type* rhs, typecmp_t* Result)
|
|||||||
case T_TYPE_STRUCT:
|
case T_TYPE_STRUCT:
|
||||||
case T_TYPE_UNION:
|
case T_TYPE_UNION:
|
||||||
/* Compare the tag types */
|
/* Compare the tag types */
|
||||||
Sym1 = GetESUSymEntry (lhs);
|
Sym1 = GetESUTagSym (lhs);
|
||||||
Sym2 = GetESUSymEntry (rhs);
|
Sym2 = GetESUTagSym (rhs);
|
||||||
|
|
||||||
CHECK (Sym1 != 0 || Sym2 != 0);
|
CHECK (Sym1 != 0 || Sym2 != 0);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user