X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=src%2Fcc65%2Ftypecmp.c;h=6afc6698f3a7255457f6803c51ff189f241ad4f2;hb=77bfcc1ff0a88e0430f077d22b6fad07c7d0c86b;hp=d9677fb1574e13388c3fa0e8e9e67663e6e770a5;hpb=38f076a59ee81effc67ca5126bb4fd2974f6ce9a;p=cc65 diff --git a/src/cc65/typecmp.c b/src/cc65/typecmp.c index d9677fb15..6afc6698f 100644 --- a/src/cc65/typecmp.c +++ b/src/cc65/typecmp.c @@ -1,15 +1,15 @@ /*****************************************************************************/ /* */ -/* 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 */ @@ -33,6 +33,9 @@ +#include + +/* cc65 */ #include "funcdesc.h" #include "symtab.h" #include "typecmp.h" @@ -49,26 +52,83 @@ static void SetResult (typecmp_t* Result, typecmp_t Val) /* 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; } @@ -78,8 +138,8 @@ static int EqualFuncParams (SymTable* Tab1, SymTable* Tab2) 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); @@ -97,7 +157,15 @@ static int EqualSymTables (SymTable* Tab1, SymTable* Tab2) /* 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; @@ -114,7 +182,7 @@ static int EqualSymTables (SymTable* Tab1, SymTable* Tab2) -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; @@ -125,7 +193,6 @@ static void DoCompare (const type* lhs, const type* rhs, typecmp_t* Result) SymTable* Tab2; FuncDesc* F1; FuncDesc* F2; - int Ok; /* Initialize stuff */ @@ -133,15 +200,15 @@ static void DoCompare (const type* lhs, const type* rhs, typecmp_t* Result) 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; } @@ -159,13 +226,12 @@ 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; - 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 @@ -181,13 +247,14 @@ static void DoCompare (const type* lhs, const type* rhs, typecmp_t* Result) } 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); @@ -220,25 +287,32 @@ static void DoCompare (const type* lhs, const type* rhs, typecmp_t* Result) 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)) { @@ -248,30 +322,27 @@ static void DoCompare (const type* lhs, const type* rhs, typecmp_t* Result) } /* 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: @@ -280,8 +351,17 @@ static void DoCompare (const type* lhs, const type* rhs, typecmp_t* Result) * 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; @@ -302,8 +382,6 @@ static void DoCompare (const type* lhs, const type* rhs, typecmp_t* Result) } /* Structs are equal */ - lhs += DECODE_SIZE; - rhs += DECODE_SIZE; break; } @@ -314,7 +392,7 @@ static void DoCompare (const type* lhs, const type* rhs, typecmp_t* Result) } /* Check if end of rhs reached */ - if (*rhs == T_END) { + if (rhs->C == T_END) { SetResult (Result, TC_EQUAL); } else { SetResult (Result, TC_INCOMPATIBLE); @@ -323,7 +401,7 @@ static void DoCompare (const type* lhs, const type* rhs, typecmp_t* Result) -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 */ @@ -345,3 +423,4 @@ typecmp_t TypeCmp (const type* lhs, const type* rhs) +