diff --git a/src/cc65/symtab.c b/src/cc65/symtab.c index 30fab0593..316963ee9 100644 --- a/src/cc65/symtab.c +++ b/src/cc65/symtab.c @@ -558,34 +558,46 @@ static int HandleSymRedefinition (SymEntry* Entry, const Type* T, unsigned Flags unsigned E_SCType = Entry->Flags & SC_TYPEMASK; unsigned SCType = Flags & SC_TYPEMASK; - /* Some symbols may be redeclared if certain requirements are met */ - if (IsTypeArray (T) && IsTypeArray (E_Type)) { + /* Existing typedefs cannot be redeclared as anything different */ + if (E_SCType == SC_TYPEDEF) { - /* 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) { - /* 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); + if (SCType == SC_TYPEDEF) { + if (TypeCmp (E_Type, T) < TC_IDENTICAL) { + 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 { - /* We have a symbol with this name already */ - if ((Entry->Flags & SC_FUNC) == SC_FUNC) { + /* Some symbols may be redeclared if certain requirements are met */ + 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 ** 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; } - } 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 { - /* New type must be identical */ + /* New type must be equivalent */ if (SCType != E_SCType) { Error ("Redefinition of '%s' as different kind of symbol", Entry->Name); Entry = 0; diff --git a/src/cc65/typecmp.c b/src/cc65/typecmp.c index 39f13b79e..e14ace6b9 100644 --- a/src/cc65/typecmp.c +++ b/src/cc65/typecmp.c @@ -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) { RightType = T_TYPE_PTR; + SetResult (Result, TC_STRICT_COMPATIBLE); } /* 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 */ LeftCount = GetElementCount (lhs); RightCount = GetElementCount (rhs); - if (LeftCount != UNSPECIFIED && - RightCount != UNSPECIFIED && - LeftCount != RightCount) { - /* Member count given but different */ - SetResult (Result, TC_INCOMPATIBLE); - return; + if (LeftCount != RightCount) { + if (LeftCount != UNSPECIFIED && + RightCount != UNSPECIFIED) { + /* Member count given but different */ + SetResult (Result, TC_INCOMPATIBLE); + return; + } + SetResult (Result, TC_EQUAL); } break; diff --git a/src/cc65/typecmp.h b/src/cc65/typecmp.h index 5f95e42a1..3e95adb3f 100644 --- a/src/cc65/typecmp.h +++ b/src/cc65/typecmp.h @@ -55,7 +55,7 @@ typedef enum { TC_COMPATIBLE = TC_SIGN_DIFF, /* Compatible types */ TC_QUAL_DIFF, /* Types differ in qualifier of pointer */ TC_STRICT_COMPATIBLE, /* Strict compatibility */ - TC_EQUAL, /* Types are equal */ + TC_EQUAL, /* Types are equivalent */ TC_IDENTICAL /* Types are identical */ } typecmp_t;