Fixed type comparisons of typedefs and arrays.

This commit is contained in:
acqn
2020-08-08 06:46:55 +08:00
committed by Oliver Schmidt
parent eb4464e828
commit 03b37cf712
3 changed files with 45 additions and 43 deletions

View File

@@ -558,34 +558,46 @@ static int HandleSymRedefinition (SymEntry* Entry, const Type* T, unsigned Flags
unsigned E_SCType = Entry->Flags & SC_TYPEMASK; unsigned E_SCType = Entry->Flags & SC_TYPEMASK;
unsigned SCType = Flags & SC_TYPEMASK; unsigned SCType = Flags & SC_TYPEMASK;
/* Some symbols may be redeclared if certain requirements are met */ /* Existing typedefs cannot be redeclared as anything different */
if (IsTypeArray (T) && IsTypeArray (E_Type)) { if (E_SCType == SC_TYPEDEF) {
/* Get the array sizes */ if (SCType == SC_TYPEDEF) {
long Size = GetElementCount (T); if (TypeCmp (E_Type, T) < TC_IDENTICAL) {
long ESize = GetElementCount (E_Type); Error ("Conflicting types for typedef '%s'", Entry->Name);
Entry = 0;
/* If we are handling arrays, the old entry or the new entry may be
** an incomplete declaration. Accept this, and if the exsting entry
** is incomplete, complete it.
*/
if ((Size != UNSPECIFIED && ESize != UNSPECIFIED && Size != ESize) ||
TypeCmp (T + 1, E_Type + 1) < TC_EQUAL) {
/* Types not identical: Conflicting types */
Error ("Conflicting array types for '%s[]'", Entry->Name);
Entry = 0;
} else {
/* Check if we have a size in the existing definition */
if (ESize == UNSPECIFIED) {
/* Existing, size not given, use size from new def */
SetElementCount (E_Type, Size);
} }
} else {
Error ("Redefinition of typedef '%s' as different kind of symbol", Entry->Name);
Entry = 0;
} }
} else { } else {
/* We have a symbol with this name already */ /* Some symbols may be redeclared if certain requirements are met */
if ((Entry->Flags & SC_FUNC) == SC_FUNC) { if (IsTypeArray (T) && IsTypeArray (E_Type)) {
/* Get the array sizes */
long Size = GetElementCount (T);
long ESize = GetElementCount (E_Type);
/* If we are handling arrays, the old entry or the new entry may be
** an incomplete declaration. Accept this, and if the exsting entry
** is incomplete, complete it.
*/
if ((Size != UNSPECIFIED && ESize != UNSPECIFIED && Size != ESize) ||
TypeCmp (T + 1, E_Type + 1) < TC_EQUAL) {
/* Conflicting element types */
Error ("Conflicting array types for '%s[]'", Entry->Name);
Entry = 0;
} else {
/* Check if we have a size in the existing definition */
if (ESize == UNSPECIFIED) {
/* Existing, size not given, use size from new def */
SetElementCount (E_Type, Size);
}
}
} else if ((Entry->Flags & SC_FUNC) == SC_FUNC) {
/* In case of a function, use the new type descriptor, since it /* In case of a function, use the new type descriptor, since it
** contains pointers to the new symbol tables that are needed if ** contains pointers to the new symbol tables that are needed if
@@ -616,22 +628,9 @@ static int HandleSymRedefinition (SymEntry* Entry, const Type* T, unsigned Flags
Entry = 0; Entry = 0;
} }
} else if (E_SCType == SC_TYPEDEF) {
if (SCType == SC_TYPEDEF) {
/* New typedef must be identical */
if (TypeCmp (E_Type, T) < TC_EQUAL) {
Error ("Conflicting types for typedef '%s'", Entry->Name);
Entry = 0;
}
} else {
Error ("Redefinition of typedef '%s' as different kind of symbol", Entry->Name);
Entry = 0;
}
} else { } else {
/* New type must be identical */ /* New type must be equivalent */
if (SCType != E_SCType) { if (SCType != E_SCType) {
Error ("Redefinition of '%s' as different kind of symbol", Entry->Name); Error ("Redefinition of '%s' as different kind of symbol", Entry->Name);
Entry = 0; Entry = 0;

View File

@@ -190,6 +190,7 @@ static void DoCompare (const Type* lhs, const Type* rhs, typecmp_t* Result)
*/ */
if (LeftType == T_TYPE_PTR && RightType == T_TYPE_ARRAY) { if (LeftType == T_TYPE_PTR && RightType == T_TYPE_ARRAY) {
RightType = T_TYPE_PTR; RightType = T_TYPE_PTR;
SetResult (Result, TC_STRICT_COMPATIBLE);
} }
/* If the underlying types are not identical, the types are incompatible */ /* If the underlying types are not identical, the types are incompatible */
@@ -350,12 +351,14 @@ static void DoCompare (const Type* lhs, const Type* rhs, typecmp_t* Result)
/* Check member count */ /* Check member count */
LeftCount = GetElementCount (lhs); LeftCount = GetElementCount (lhs);
RightCount = GetElementCount (rhs); RightCount = GetElementCount (rhs);
if (LeftCount != UNSPECIFIED && if (LeftCount != RightCount) {
RightCount != UNSPECIFIED && if (LeftCount != UNSPECIFIED &&
LeftCount != RightCount) { RightCount != UNSPECIFIED) {
/* Member count given but different */ /* Member count given but different */
SetResult (Result, TC_INCOMPATIBLE); SetResult (Result, TC_INCOMPATIBLE);
return; return;
}
SetResult (Result, TC_EQUAL);
} }
break; break;

View File

@@ -55,7 +55,7 @@ typedef enum {
TC_COMPATIBLE = TC_SIGN_DIFF, /* Compatible types */ TC_COMPATIBLE = TC_SIGN_DIFF, /* Compatible types */
TC_QUAL_DIFF, /* Types differ in qualifier of pointer */ TC_QUAL_DIFF, /* Types differ in qualifier of pointer */
TC_STRICT_COMPATIBLE, /* Strict compatibility */ TC_STRICT_COMPATIBLE, /* Strict compatibility */
TC_EQUAL, /* Types are equal */ TC_EQUAL, /* Types are equivalent */
TC_IDENTICAL /* Types are identical */ TC_IDENTICAL /* Types are identical */
} typecmp_t; } typecmp_t;