mirror of
https://github.com/cc65/cc65.git
synced 2025-03-01 11:29:27 +00:00
Fixed type comparisons of ESU types with stricter rules.
This commit is contained in:
parent
8b8561161c
commit
eb4464e828
@ -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);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user