/*****************************************************************************/
/* */
-/* typecmp.c */
+/* typecmp.c */
/* */
-/* Type compare function for the cc65 C compiler */
+/* Type compare function for the cc65 C compiler */
/* */
/* */
/* */
-/* (C) 1998-2000 Ullrich von Bassewitz */
-/* Wacholderweg 14 */
-/* D-70597 Stuttgart */
-/* EMail: uz@musoftware.de */
+/* (C) 1998-2008 Ullrich von Bassewitz */
+/* Roemerstrasse 52 */
+/* D-70794 Filderstadt */
+/* EMail: uz@cc65.org */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
+#include <string.h>
+
+/* cc65 */
#include "funcdesc.h"
#include "symtab.h"
#include "typecmp.h"
/* Set a new result value if it is less than the existing one */
{
if (Val < *Result) {
+ /* printf ("SetResult = %d\n", Val); */
*Result = Val;
}
}
-static int EqualFuncParams (SymTable* Tab1, SymTable* Tab2)
+static int ParamsHaveDefaultPromotions (const FuncDesc* F)
+/* Check if any of the parameters of function F has a default promotion. In
+ * this case, the function is not compatible with an empty parameter name list
+ * declaration.
+ */
+{
+ /* Get the symbol table */
+ const SymTable* Tab = F->SymTab;
+
+ /* Get the first parameter in the list */
+ const SymEntry* Sym = Tab->SymHead;
+
+ /* Walk over all parameters */
+ while (Sym && (Sym->Flags & SC_PARAM)) {
+
+ /* If this is an integer type, check if the promoted type is equal
+ * to the original type. If not, we have a default promotion.
+ */
+ if (IsClassInt (Sym->Type)) {
+ if (IntPromotion (Sym->Type) != Sym->Type) {
+ return 1;
+ }
+ }
+
+ /* Get the pointer to the next param */
+ Sym = Sym->NextSym;
+ }
+
+ /* No default promotions in the parameter list */
+ return 0;
+}
+
+
+
+static int EqualFuncParams (const FuncDesc* F1, const FuncDesc* F2)
/* Compare two function symbol tables regarding function parameters. Return 1
* if they are equal and 0 otherwise.
*/
{
+ /* Get the symbol tables */
+ const SymTable* Tab1 = F1->SymTab;
+ const SymTable* Tab2 = F2->SymTab;
+
/* Compare the parameter lists */
- SymEntry* Sym1 = Tab1->SymHead;
- SymEntry* Sym2 = Tab2->SymHead;
+ const SymEntry* Sym1 = Tab1->SymHead;
+ const SymEntry* Sym2 = Tab2->SymHead;
/* Compare the fields */
while (Sym1 && (Sym1->Flags & SC_PARAM) && Sym2 && (Sym2->Flags & SC_PARAM)) {
+ /* Get the symbol types */
+ Type* Type1 = Sym1->Type;
+ Type* Type2 = Sym2->Type;
+
+ /* If either of both functions is old style, apply the default
+ * promotions to the parameter type.
+ */
+ if (F1->Flags & FD_OLDSTYLE) {
+ if (IsClassInt (Type1)) {
+ Type1 = IntPromotion (Type1);
+ }
+ }
+ if (F2->Flags & FD_OLDSTYLE) {
+ if (IsClassInt (Type2)) {
+ Type2 = IntPromotion (Type2);
+ }
+ }
+
/* Compare this field */
- if (TypeCmp (Sym1->Type, Sym2->Type) < TC_EQUAL) {
+ if (TypeCmp (Type1, Type2) < TC_EQUAL) {
/* Field types not equal */
return 0;
}
Sym2 = Sym2->NextSym;
}
- /* Check both pointers against NULL or a non parameter to compare the
- * field count
+ /* Check both pointers against NULL or a non parameter to compare the
+ * field count
*/
return (Sym1 == 0 || (Sym1->Flags & SC_PARAM) == 0) &&
(Sym2 == 0 || (Sym2->Flags & SC_PARAM) == 0);
/* Compare the fields */
while (Sym1 && Sym2) {
- /* Compare this field */
+ /* 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;
-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. */
{
unsigned Indirections;
SymTable* Tab2;
FuncDesc* F1;
FuncDesc* F2;
- int Ok;
/* Initialize stuff */
ElementCount = 0;
/* Compare two types. Determine, where they differ */
- while (*lhs != T_END) {
+ while (lhs->C != T_END) {
- type LeftType, RightType;
- type LeftSign, RightSign;
- type LeftQual, RightQual;
- unsigned LeftCount, RightCount;
+ TypeCode LeftType, RightType;
+ TypeCode LeftSign, RightSign;
+ TypeCode LeftQual, RightQual;
+ long LeftCount, RightCount;
/* Check if the end of the type string is reached */
- if (*rhs == T_END) {
+ if (rhs->C == T_END) {
/* End of comparison reached */
return;
}
*/
if (LeftType == T_TYPE_PTR && RightType == T_TYPE_ARRAY) {
RightType = T_TYPE_PTR;
- rhs += DECODE_SIZE;
}
/* If the raw types are not identical, the types are incompatible */
if (LeftType != RightType) {
SetResult (Result, TC_INCOMPATIBLE);
- return;
+ return;
}
/* On indirection level zero, a qualifier or sign difference is
}
if (LeftQual != RightQual) {
/* On the first indirection level, different qualifiers mean
- * that the types are still compatible. On the second level,
- * this is a (maybe minor) error, so we create a special
- * return code, since a qualifier is dropped from a pointer.
- * Starting from the next level, the types are incompatible
- * if the qualifiers differ.
- */
- switch (Indirections) {
+ * that the types are still compatible. On the second level,
+ * this is a (maybe minor) error, so we create a special
+ * return code, since a qualifier is dropped from a pointer.
+ * Starting from the next level, the types are incompatible
+ * if the qualifiers differ.
+ */
+ /* printf ("Ind = %d %06X != %06X\n", Indirections, LeftQual, RightQual); */
+ switch (Indirections) {
case 0:
SetResult (Result, TC_STRICT_COMPATIBLE);
case T_TYPE_FUNC:
/* Compare the function descriptors */
- F1 = DecodePtr (lhs+1);
- F2 = DecodePtr (rhs+1);
-
- /* If one of the functions is implicitly declared, both
- * functions are considered equal. If one of the functions is
- * old style, and the other is empty, the functions are
- * considered equal.
- */
- if ((F1->Flags & FD_IMPLICIT) != 0 || (F2->Flags & FD_IMPLICIT) != 0) {
- Ok = 1;
- } else if ((F1->Flags & FD_OLDSTYLE) != 0 && (F2->Flags & FD_EMPTY) != 0) {
- Ok = 1;
- } else if ((F1->Flags & FD_EMPTY) != 0 && (F2->Flags & FD_OLDSTYLE) != 0) {
- Ok = 1;
- } else {
- Ok = 0;
- }
-
- if (!Ok) {
+ F1 = GetFuncDesc (lhs);
+ F2 = GetFuncDesc (rhs);
+
+ /* If one of both functions has an empty parameter list (which
+ * does also mean, it is not a function definition, because the
+ * flag is reset in this case), it is considered equal to any
+ * other definition, provided that the other has no default
+ * promotions in the parameter list. If none of both parameter
+ * lists is empty, we have to check the parameter lists and
+ * other attributes.
+ */
+ if (F1->Flags & FD_EMPTY) {
+ if ((F2->Flags & FD_EMPTY) == 0) {
+ if (ParamsHaveDefaultPromotions (F2)) {
+ /* Flags differ */
+ SetResult (Result, TC_INCOMPATIBLE);
+ return;
+ }
+ }
+ } else if (F2->Flags & FD_EMPTY) {
+ if (ParamsHaveDefaultPromotions (F1)) {
+ /* Flags differ */
+ SetResult (Result, TC_INCOMPATIBLE);
+ return;
+ }
+ } else {
/* Check the remaining flags */
if ((F1->Flags & ~FD_IGNORE) != (F2->Flags & ~FD_IGNORE)) {
}
/* Compare the parameter lists */
- if (EqualFuncParams (F1->SymTab, F2->SymTab) == 0 ||
- EqualSymTables (F1->TagTab, F2->TagTab) == 0) {
- /* One of the tables is not identical */
+ if (EqualFuncParams (F1, F2) == 0) {
+ /* Parameter list is not identical */
SetResult (Result, TC_INCOMPATIBLE);
return;
}
}
- /* Skip the FuncDesc pointers to compare the return type */
- lhs += DECODE_SIZE;
- rhs += DECODE_SIZE;
+ /* Keep on and compare the return type */
break;
case T_TYPE_ARRAY:
/* Check member count */
- LeftCount = Decode (lhs+1);
- RightCount = Decode (rhs+1);
- if (LeftCount != 0 && RightCount != 0 && LeftCount != RightCount) {
+ LeftCount = GetElementCount (lhs);
+ RightCount = GetElementCount (rhs);
+ if (LeftCount != UNSPECIFIED &&
+ RightCount != UNSPECIFIED &&
+ LeftCount != RightCount) {
/* Member count given but different */
SetResult (Result, TC_INCOMPATIBLE);
return;
}
- lhs += DECODE_SIZE;
- rhs += DECODE_SIZE;
break;
case T_TYPE_STRUCT:
* pointer to the struct definition from the type, and compare
* the fields.
*/
- Sym1 = DecodePtr (lhs+1);
- Sym2 = DecodePtr (rhs+1);
+ Sym1 = GetSymEntry (lhs);
+ Sym2 = GetSymEntry (rhs);
+
+ /* If one symbol has a name, the names must be identical */
+ if (!HasAnonName (Sym1) || !HasAnonName (Sym2)) {
+ if (strcmp (Sym1->Name, Sym2->Name) != 0) {
+ /* Names are not identical */
+ SetResult (Result, TC_INCOMPATIBLE);
+ return;
+ }
+ }
/* Get the field tables from the struct entry */
Tab1 = Sym1->V.S.SymTab;
}
/* Structs are equal */
- lhs += DECODE_SIZE;
- rhs += DECODE_SIZE;
break;
}
}
/* Check if end of rhs reached */
- if (*rhs == T_END) {
+ if (rhs->C == T_END) {
SetResult (Result, TC_EQUAL);
} else {
SetResult (Result, TC_INCOMPATIBLE);
-typecmp_t TypeCmp (const type* lhs, const type* rhs)
+typecmp_t TypeCmp (const Type* lhs, const Type* rhs)
/* Compare two types and return the result */
{
/* Assume the types are identical */
+