Corrected and entailed comments and cleaned up code with type comparison.
This commit is contained in:
@@ -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;
|
||||||
|
|||||||
@@ -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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user