]> git.sur5r.net Git - cc65/blobdiff - src/cc65/typecmp.c
Fix the check for constant static local data, which was wrong when the data
[cc65] / src / cc65 / typecmp.c
index 3a101011c5a8272663ee87a9d87f4bc44e350799..6afc6698f3a7255457f6803c51ff189f241ad4f2 100644 (file)
@@ -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       */
@@ -52,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;
        }
@@ -107,7 +164,7 @@ static int EqualSymTables (SymTable* Tab1, SymTable* Tab2)
                 return 0;
             }
         }
-                                
+
         /* Compare the types of this field */
                if (TypeCmp (Sym1->Type, Sym2->Type) < TC_EQUAL) {
            /* Field types not equal */
@@ -125,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;
@@ -136,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 */
@@ -144,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;
                }
@@ -170,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
@@ -192,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);
@@ -231,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)) {
@@ -259,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:
@@ -291,8 +351,8 @@ 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)) {
@@ -322,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;
        }
 
@@ -334,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);
@@ -343,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 */
@@ -365,3 +423,4 @@ typecmp_t TypeCmp (const type* lhs, const type* rhs)
 
 
 
+