diff --git a/src/cc65/typecmp.c b/src/cc65/typecmp.c index 0eddf2988..39f13b79e 100644 --- a/src/cc65/typecmp.c +++ b/src/cc65/typecmp.c @@ -148,41 +148,6 @@ static int EqualFuncParams (const FuncDesc* F1, const FuncDesc* F2) -static int EqualSymTables (SymTable* Tab1, SymTable* Tab2) -/* Compare two symbol tables. Return 1 if they are equal and 0 otherwise */ -{ - /* Compare the parameter lists */ - SymEntry* Sym1 = Tab1->SymHead; - SymEntry* Sym2 = Tab2->SymHead; - - /* Compare the fields */ - while (Sym1 && Sym2) { - - /* Compare the names of this field */ - if (!HasAnonName (Sym1) || !HasAnonName (Sym2)) { - if (strcmp (Sym1->Name, Sym2->Name) != 0) { - /* Names are not identical */ - return 0; - } - } - - /* Compare the types of this field */ - if (TypeCmp (Sym1->Type, Sym2->Type) < TC_EQUAL) { - /* Field types not equal */ - return 0; - } - - /* Get the pointers to the next fields */ - Sym1 = Sym1->NextSym; - Sym2 = Sym2->NextSym; - } - - /* Check both pointers against NULL to compare the field count */ - return (Sym1 == 0 && Sym2 == 0); -} - - - static void DoCompare (const Type* lhs, const Type* rhs, typecmp_t* Result) /* Recursively compare two types. */ { @@ -190,8 +155,6 @@ static void DoCompare (const Type* lhs, const Type* rhs, typecmp_t* Result) unsigned ElementCount; SymEntry* Sym1; SymEntry* Sym2; - SymTable* Tab1; - SymTable* Tab2; FuncDesc* F1; FuncDesc* F2; @@ -235,6 +198,40 @@ static void DoCompare (const Type* lhs, const Type* rhs, typecmp_t* Result) return; } + /* Enums must be handled specially */ + if ((IsTypeEnum (lhs) || IsTypeEnum (rhs))) { + + /* Compare the tag types */ + Sym1 = GetESUSymEntry (lhs); + Sym2 = GetESUSymEntry (rhs); + + if (Sym1 != Sym2) { + if (Sym1 == 0 || Sym2 == 0) { + + /* Only one is an enum. So they can't be identical */ + SetResult (Result, TC_STRICT_COMPATIBLE); + + } else { + /* For the two to be identical, they must be in the same + ** scope and have the same name. + */ + if (Sym1->Owner != Sym2->Owner || + strcmp (Sym1->Name, Sym2->Name) != 0) { + + /* If any one of the two is incomplete, we can't guess + ** their underlying types and have to assume that they + ** be incompatible. + */ + if (SizeOf (lhs) == 0 || SizeOf (rhs) == 0) { + SetResult (Result, TC_INCOMPATIBLE); + return; + } + } + } + } + + } + /* On indirection level zero, a qualifier or sign difference is ** accepted. The types are no longer equal, but compatible. */ @@ -364,41 +361,25 @@ static void DoCompare (const Type* lhs, const Type* rhs, typecmp_t* Result) case T_TYPE_STRUCT: case T_TYPE_UNION: - /* Compare the fields recursively. To do that, we fetch the - ** pointer to the struct definition from the type, and compare - ** the fields. - */ + /* Compare the tag types */ Sym1 = GetESUSymEntry (lhs); Sym2 = GetESUSymEntry (rhs); - /* If one symbol has a name, the names must be identical */ - if (!HasAnonName (Sym1) || !HasAnonName (Sym2)) { - if (strcmp (Sym1->Name, Sym2->Name) != 0) { - /* Names are not identical */ + CHECK (Sym1 != 0 || Sym2 != 0); + + if (Sym1 != Sym2) { + /* Both must be in the same scope and have the same name to + ** be identical. This shouldn't happen in the current code + ** base, but we still do this to be future-proof. + */ + if (Sym1->Owner != Sym2->Owner || + strcmp (Sym1->Name, Sym2->Name) != 0) { SetResult (Result, TC_INCOMPATIBLE); return; } } - /* Get the field tables from the struct entry */ - Tab1 = Sym1->V.S.SymTab; - Tab2 = Sym2->V.S.SymTab; - - /* One or both structs may be forward definitions. In this case, - ** the symbol tables are both non existant. Assume that the - ** structs are equal in this case. - */ - if (Tab1 != 0 && Tab2 != 0) { - - if (EqualSymTables (Tab1, Tab2) == 0) { - /* Field lists are not equal */ - SetResult (Result, TC_INCOMPATIBLE); - return; - } - - } - - /* Structs are equal */ + /* Both are identical */ break; } @@ -410,7 +391,7 @@ static void DoCompare (const Type* lhs, const Type* rhs, typecmp_t* Result) /* Check if end of rhs reached */ if (rhs->C == T_END) { - SetResult (Result, TC_EQUAL); + SetResult (Result, TC_IDENTICAL); } else { SetResult (Result, TC_INCOMPATIBLE); }