Corrected and entailed comments and cleaned up code with type comparison.

This commit is contained in:
acqn
2022-10-13 13:45:22 +08:00
parent 01d2b809a1
commit cf3a0c4a30
2 changed files with 49 additions and 56 deletions

View File

@@ -141,7 +141,7 @@ static void SetResult (typecmp_t* Result, typecmpcode_t Val)
static typecmp_t* CmpQuals (const Type* lhst, const Type* rhst, typecmp_t* Result) static typecmp_t* CmpQuals (const Type* lhst, const Type* rhst, typecmp_t* Result)
/* Copare the types regarding thier qualifiers. Return the Result */ /* Compare the types regarding their qualifiers. Return via pointer *Result */
{ {
TypeCode LeftQual, RightQual; TypeCode LeftQual, RightQual;
@@ -249,16 +249,10 @@ static void DoCompare (const Type* lhs, const Type* rhs, typecmp_t* Result)
/* Compare two types. Determine, where they differ */ /* Compare two types. Determine, where they differ */
while (lhs->C != T_END) { while (lhs->C != T_END && rhs->C != T_END) {
/* Check if the end of the type string is reached */
if (rhs->C == T_END) {
/* End of comparison reached */
break;
}
/* Compare qualifiers */ /* Compare qualifiers */
if (CmpQuals (lhs, rhs, Result)->C == TC_INCOMPATIBLE) { if (CmpQuals (lhs, rhs, Result)->C == TC_INCOMPATIBLE) {
/* No need to compare further */
return; return;
} }
@@ -266,6 +260,22 @@ static void DoCompare (const Type* lhs, const Type* rhs, typecmp_t* Result)
LeftRank = (GetUnqualTypeCode (lhs) & T_MASK_RANK); LeftRank = (GetUnqualTypeCode (lhs) & T_MASK_RANK);
RightRank = (GetUnqualTypeCode (rhs) & T_MASK_RANK); RightRank = (GetUnqualTypeCode (rhs) & T_MASK_RANK);
/* Bit-fields are considered compatible if they have the same
** signedness, bit-offset and bit-width.
*/
if (IsTypeBitField (lhs) || IsTypeBitField (rhs)) {
if (!IsTypeBitField (lhs) ||
!IsTypeBitField (rhs) ||
lhs->A.B.Offs != rhs->A.B.Offs ||
lhs->A.B.Width != rhs->A.B.Width) {
/* Incompatible */
goto Incompatible;
}
if (LeftRank != RightRank) {
SetResult (Result, TC_STRICT_COMPATIBLE);
}
}
/* If one side is a pointer and the other side is an array, both are /* If one side is a pointer and the other side is an array, both are
** compatible. ** compatible.
*/ */
@@ -280,56 +290,35 @@ static void DoCompare (const Type* lhs, const Type* rhs, typecmp_t* Result)
} }
} }
/* Bit-fields are considered compatible if they have the same
** signedness, bit-offset and bit-width.
*/
if (IsTypeBitField (lhs) || IsTypeBitField (rhs)) {
if (!IsTypeBitField (lhs) ||
!IsTypeBitField (rhs) ||
lhs->A.B.Offs != rhs->A.B.Offs ||
lhs->A.B.Width != rhs->A.B.Width) {
SetResult (Result, TC_INCOMPATIBLE);
}
if (LeftRank != RightRank) {
SetResult (Result, TC_STRICT_COMPATIBLE);
}
}
/* If the ranks are different, the types are incompatible */ /* If the ranks are different, the types are incompatible */
if (LeftRank != RightRank) { if (LeftRank != RightRank) {
SetResult (Result, TC_INCOMPATIBLE); goto Incompatible;
return;
} }
/* Enums must be handled specially */ /* Enums must be handled specially */
if ((IsTypeEnum (lhs) || IsTypeEnum (rhs))) { if ((IsTypeEnum (lhs) || IsTypeEnum (rhs))) {
/* Compare the tag types */ /* Compare the tag types */
Sym1 = IsTypeEnum (lhs) ? GetESUTagSym (lhs) : 0; Sym1 = GetESUTagSym (lhs);
Sym2 = IsTypeEnum (rhs) ? GetESUTagSym (rhs) : 0; Sym2 = GetESUTagSym (rhs);
/* For the two to be identical, they must be declared in the same
** scope and have the same name.
*/
if (Sym1 != Sym2) { if (Sym1 != Sym2) {
if (Sym1 == 0 || Sym2 == 0) { if (Sym1 == 0 || Sym2 == 0) {
/* Only one is an enum. So they can't be identical */ /* Only one is an enum. So they can't be identical */
SetResult (Result, TC_STRICT_COMPATIBLE); SetResult (Result, TC_STRICT_COMPATIBLE);
} else if (Sym1->Owner != Sym2->Owner ||
} else { strcmp (Sym1->Name, Sym2->Name) != 0) {
/* For the two to be identical, they must be in the same /* If any one of the two is incomplete, we can't guess
** scope and have the same name. ** their underlying types and have to assume that they
** be incompatible.
*/ */
if (Sym1->Owner != Sym2->Owner || if (SizeOf (lhs) == 0 || SizeOf (rhs) == 0) {
strcmp (Sym1->Name, Sym2->Name) != 0) { goto Incompatible;
/* 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;
}
} }
SetResult (Result, TC_STRICT_COMPATIBLE);
} }
} }
@@ -383,15 +372,13 @@ static void DoCompare (const Type* lhs, const Type* rhs, typecmp_t* Result)
/* Check the remaining flags */ /* Check the remaining flags */
if ((F1->Flags & ~FD_IGNORE) != (F2->Flags & ~FD_IGNORE)) { if ((F1->Flags & ~FD_IGNORE) != (F2->Flags & ~FD_IGNORE)) {
/* Flags differ */ /* Flags differ */
SetResult (Result, TC_INCOMPATIBLE); goto Incompatible;
return;
} }
/* Compare the parameter lists */ /* Compare the parameter lists */
if (EqualFuncParams (F1, F2) == 0) { if (EqualFuncParams (F1, F2) == 0) {
/* Parameter list is not identical */ /* Parameter list is not identical */
SetResult (Result, TC_INCOMPATIBLE); goto Incompatible;
return;
} }
} }
@@ -406,8 +393,7 @@ static void DoCompare (const Type* lhs, const Type* rhs, typecmp_t* Result)
if (LeftCount != UNSPECIFIED && if (LeftCount != UNSPECIFIED &&
RightCount != UNSPECIFIED) { RightCount != UNSPECIFIED) {
/* Member count given but different */ /* Member count given but different */
SetResult (Result, TC_INCOMPATIBLE); goto Incompatible;
return;
} }
/* We take into account which side is more specified */ /* We take into account which side is more specified */
@@ -436,8 +422,7 @@ static void DoCompare (const Type* lhs, const Type* rhs, typecmp_t* Result)
/* This shouldn't happen in the current code base, but /* This shouldn't happen in the current code base, but
** we still handle this case to be future-proof. ** we still handle this case to be future-proof.
*/ */
SetResult (Result, TC_INCOMPATIBLE); goto Incompatible;
return;
} }
} }
@@ -453,9 +438,11 @@ static void DoCompare (const Type* lhs, const Type* rhs, typecmp_t* Result)
/* Check if lhs and rhs both reached ends */ /* Check if lhs and rhs both reached ends */
if (lhs->C == T_END && rhs->C == T_END) { if (lhs->C == T_END && rhs->C == T_END) {
SetResult (Result, TC_IDENTICAL); SetResult (Result, TC_IDENTICAL);
} else { return;
SetResult (Result, TC_INCOMPATIBLE);
} }
Incompatible:
SetResult (Result, TC_INCOMPATIBLE);
} }
@@ -483,7 +470,10 @@ typecmp_t TypeCmp (const Type* lhs, const Type* rhs)
void TypeCompatibilityDiagnostic (const Type* NewType, const Type* OldType, int IsError, const char* Msg) void TypeCompatibilityDiagnostic (const Type* NewType, const Type* OldType, int IsError, const char* Msg)
/* Print error or warning message about type compatibility with proper type names */ /* Print error or warning message about type compatibility with proper type
** names. The format string shall contain two '%s' specifiers for the names of
** the two types.
*/
{ {
StrBuf NewTypeName = STATIC_STRBUF_INITIALIZER; StrBuf NewTypeName = STATIC_STRBUF_INITIALIZER;
StrBuf OldTypeName = STATIC_STRBUF_INITIALIZER; StrBuf OldTypeName = STATIC_STRBUF_INITIALIZER;

View File

@@ -97,7 +97,10 @@ typecmp_t TypeCmp (const Type* lhs, const Type* rhs);
/* Compare two types and return the result */ /* Compare two types and return the result */
void TypeCompatibilityDiagnostic (const Type* NewType, const Type* OldType, int IsError, const char* Msg); void TypeCompatibilityDiagnostic (const Type* NewType, const Type* OldType, int IsError, const char* Msg);
/* Print error or warning message about type compatibility with proper type names */ /* Print error or warning message about type compatibility with proper type
** names. The format string shall contain two '%s' specifiers for the names of
** the two types.
*/