1
0
mirror of https://github.com/cc65/cc65.git synced 2024-06-07 07:29:33 +00:00

Fixed type comparisons of ESU types with stricter rules.

This commit is contained in:
acqn 2020-08-03 01:38:54 +08:00 committed by Oliver Schmidt
parent 8b8561161c
commit eb4464e828

View File

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