Fixed type comparisons of ESU types with stricter rules.
This commit is contained in:
@@ -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)
|
static void DoCompare (const Type* lhs, const Type* rhs, typecmp_t* Result)
|
||||||
/* Recursively compare two types. */
|
/* Recursively compare two types. */
|
||||||
{
|
{
|
||||||
@@ -190,8 +155,6 @@ static void DoCompare (const Type* lhs, const Type* rhs, typecmp_t* Result)
|
|||||||
unsigned ElementCount;
|
unsigned ElementCount;
|
||||||
SymEntry* Sym1;
|
SymEntry* Sym1;
|
||||||
SymEntry* Sym2;
|
SymEntry* Sym2;
|
||||||
SymTable* Tab1;
|
|
||||||
SymTable* Tab2;
|
|
||||||
FuncDesc* F1;
|
FuncDesc* F1;
|
||||||
FuncDesc* F2;
|
FuncDesc* F2;
|
||||||
|
|
||||||
@@ -235,6 +198,40 @@ static void DoCompare (const Type* lhs, const Type* rhs, typecmp_t* Result)
|
|||||||
return;
|
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
|
/* On indirection level zero, a qualifier or sign difference is
|
||||||
** accepted. The types are no longer equal, but compatible.
|
** 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_STRUCT:
|
||||||
case T_TYPE_UNION:
|
case T_TYPE_UNION:
|
||||||
/* Compare the fields recursively. To do that, we fetch the
|
/* Compare the tag types */
|
||||||
** pointer to the struct definition from the type, and compare
|
|
||||||
** the fields.
|
|
||||||
*/
|
|
||||||
Sym1 = GetESUSymEntry (lhs);
|
Sym1 = GetESUSymEntry (lhs);
|
||||||
Sym2 = GetESUSymEntry (rhs);
|
Sym2 = GetESUSymEntry (rhs);
|
||||||
|
|
||||||
/* If one symbol has a name, the names must be identical */
|
CHECK (Sym1 != 0 || Sym2 != 0);
|
||||||
if (!HasAnonName (Sym1) || !HasAnonName (Sym2)) {
|
|
||||||
if (strcmp (Sym1->Name, Sym2->Name) != 0) {
|
if (Sym1 != Sym2) {
|
||||||
/* Names are not identical */
|
/* 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);
|
SetResult (Result, TC_INCOMPATIBLE);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get the field tables from the struct entry */
|
/* Both are identical */
|
||||||
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 */
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -410,7 +391,7 @@ static void DoCompare (const Type* lhs, const Type* rhs, typecmp_t* Result)
|
|||||||
|
|
||||||
/* Check if end of rhs reached */
|
/* Check if end of rhs reached */
|
||||||
if (rhs->C == T_END) {
|
if (rhs->C == T_END) {
|
||||||
SetResult (Result, TC_EQUAL);
|
SetResult (Result, TC_IDENTICAL);
|
||||||
} else {
|
} else {
|
||||||
SetResult (Result, TC_INCOMPATIBLE);
|
SetResult (Result, TC_INCOMPATIBLE);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user