]> git.sur5r.net Git - cc65/commitdiff
Fixed several problems with old style (K&R) declarations and a mix of old and
authoruz <uz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Sun, 3 Aug 2008 20:55:36 +0000 (20:55 +0000)
committeruz <uz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Sun, 3 Aug 2008 20:55:36 +0000 (20:55 +0000)
new style decls.

git-svn-id: svn://svn.cc65.org/cc65/trunk@3869 b7a2c559-68d2-44c3-8de9-860c34a00d81

src/cc65/compile.c
src/cc65/datatype.c
src/cc65/funcdesc.h
src/cc65/symtab.c
src/cc65/typecmp.c

index 2157a748e83bf56baf6b6e92e594c1b28d58cdfb..8475657a4f0df470223202f35e10c8ee9c52a2cd 100644 (file)
@@ -149,6 +149,21 @@ static void Parse (void)
                Decl.StorageClass |= SC_STORAGE | SC_DEF;
            }
 
+            /* If this is a function declarator that is not followed by a comma
+             * or semicolon, it must be followed by a function body. If this is
+             * the case, convert an empty parameter list into one accepting no
+             * parameters (same as void) as required by the standard.
+             */
+            if ((Decl.StorageClass & SC_FUNC) != 0 &&
+                (CurTok.Tok != TOK_COMMA)          &&
+                (CurTok.Tok != TOK_SEMI)) {
+
+                FuncDesc* D = GetFuncDesc (Decl.Type);
+                if (D->Flags & FD_EMPTY) {
+                    D->Flags = (D->Flags & ~(FD_EMPTY | FD_VARIADIC)) | FD_VOID_PARAM;
+                }
+            }
+
            /* Add an entry to the symbol table */
            Entry = AddGlobalSym (Decl.Ident, Decl.Type, Decl.StorageClass);
 
@@ -240,25 +255,12 @@ static void Parse (void)
                    NextToken ();
                } else {
 
-                    FuncDesc* D;
-
                     /* Function body. Check for duplicate function definitions */
                     if (SymIsDef (Entry)) {
                         Error ("Body for function `%s' has already been defined",
                                Entry->Name);
                     }
 
-                    /* An empty parameter list in a function definition means
-                     * that the function doesn't take any parameters. The same
-                     * in a declarator means that the function can take any
-                     * number of parameters. This seems weird but is necessary
-                     * to support old K&R style programs.
-                     */
-                    D = Entry->V.F.Func;
-                    if (D->Flags & FD_EMPTY) {
-                        D->Flags = (D->Flags & ~(FD_EMPTY | FD_VARIADIC)) | FD_VOID_PARAM;
-                    }
-
                     /* Parse the function body */
                     NewFunc (Entry);
                }
index 9c4bb2c70c4a6be3b501e2e314eaa29000a29550..4c7e23ff0890c047260237c2e3adefb3f80f5502 100644 (file)
@@ -179,7 +179,7 @@ Type* GetImplicitFuncType (void)
     Type* T = TypeAlloc (3);    /* func/returns int/terminator */
 
     /* Prepare the function descriptor */
-    F->Flags  = FD_IMPLICIT | FD_EMPTY | FD_VARIADIC;
+    F->Flags  = FD_EMPTY | FD_VARIADIC;
     F->SymTab = &EmptySymTab;
     F->TagTab = &EmptySymTab;
 
index 9cb4500463c3d84a8c2b67769e1cb63df1a08b80..56da848a14629292d0f4e8b7b6790d4b68b69c4d 100644 (file)
@@ -6,8 +6,8 @@
 /*                                                                           */
 /*                                                                           */
 /*                                                                           */
-/* (C) 2000-2003 Ullrich von Bassewitz                                       */
-/*               Römerstraße 52                                              */
+/* (C) 2000-2008 Ullrich von Bassewitz                                       */
+/*               Roemerstrasse 52                                            */
 /*               D-70794 Filderstadt                                         */
 /* EMail:        uz@cc65.org                                                 */
 /*                                                                           */
 
 
 
-/* Masks for the Flags field in FuncDesc */                                   
+/* Masks for the Flags field in FuncDesc */
 #define FD_NONE                        0x0000U /* No flags                          */
-#define FD_IMPLICIT            0x0001U /* Implicitly declared function      */
-#define FD_EMPTY               0x0002U /* Function with empty param list    */
-#define FD_VOID_PARAM          0x0004U /* Function with a void param list   */
-#define FD_VARIADIC            0x0008U /* Function with variable param list */
+#define FD_EMPTY                       0x0001U /* Function with empty param list    */
+#define FD_VOID_PARAM          0x0002U /* Function with a void param list   */
+#define FD_VARIADIC            0x0004U /* Function with variable param list */
 #define FD_FASTCALL            0x0010U /* __fastcall__ function             */
 #define FD_FAR                 0x0020U /* __far__ function                  */
 #define FD_NEAR                        0x0040U /* __near__ function                 */
@@ -58,7 +57,7 @@
 #define FD_UNNAMED_PARAMS              0x0400U /* Function has unnamed params       */
 
 /* Bits that must be ignored when comparing funcs */
-#define FD_IGNORE      (FD_IMPLICIT | FD_UNNAMED_PARAMS)
+#define FD_IGNORE       (FD_OLDSTYLE | FD_OLDSTYLE_INTRET | FD_UNNAMED_PARAMS)
 
 
 
index 8990f48c872e3b6c97ee3af6f6e73da689ee5e1c..d10a7ad0a4e5496e5f8aaa3aacb6b85fb24f8e53 100644 (file)
@@ -753,14 +753,20 @@ SymEntry* AddGlobalSym (const char* Name, const Type* T, unsigned Flags)
 
            /* In case of a function, use the new type descriptor, since it
             * contains pointers to the new symbol tables that are needed if
-            * an actual function definition follows.
+            * an actual function definition follows. Be sure not to use the
+             * new descriptor if it contains a function declaration with an
+             * empty parameter list.
             */
            if (IsFunc) {
                /* Get the function descriptor from the new type */
                FuncDesc* F = GetFuncDesc (T);
-               /* Use this new function descriptor */
-               Entry->V.F.Func = F;
-               SetFuncDesc (EType, F);
+               /* Use this new function descriptor if it doesn't contain
+                 * an empty parameter list.
+                 */
+                if ((F->Flags & FD_EMPTY) == 0) {
+                    Entry->V.F.Func = F;
+                    SetFuncDesc (EType, F);
+                }
            }
        }
 
index 1ff49e159702655f0dbf82781bdbea8379330d26..0752d60bac96c3c809a5393f1488c3d671d0fa0f 100644 (file)
@@ -1,13 +1,13 @@
 /*****************************************************************************/
 /*                                                                           */
-/*                                typecmp.c                                 */
+/*                                typecmp.c                                 */
 /*                                                                           */
-/*              Type compare function for the cc65 C compiler               */
+/*              Type compare function for the cc65 C compiler               */
 /*                                                                           */
 /*                                                                           */
 /*                                                                           */
-/* (C) 1998-2003 Ullrich von Bassewitz                                       */
-/*               Römerstrasse 52                                             */
+/* (C) 1998-2008 Ullrich von Bassewitz                                       */
+/*               Roemerstrasse 52                                            */
 /*               D-70794 Filderstadt                                         */
 /* EMail:        uz@cc65.org                                                 */
 /*                                                                           */
@@ -58,20 +58,76 @@ static void SetResult (typecmp_t* Result, typecmp_t 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;
        }
@@ -136,7 +192,6 @@ static void DoCompare (const Type* lhs, const Type* rhs, typecmp_t* Result)
     SymTable*  Tab2;
     FuncDesc*  F1;
     FuncDesc*  F2;
-    int                Ok;
 
 
     /* Initialize stuff */
@@ -175,7 +230,7 @@ static void DoCompare (const Type* lhs, const Type* rhs, typecmp_t* Result)
        /* 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
@@ -233,22 +288,29 @@ static void DoCompare (const Type* lhs, const Type* rhs, typecmp_t* Result)
                        F1 = GetFuncDesc (lhs);
                        F2 = GetFuncDesc (rhs);
 
-                       /* 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) {
+                /* 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)) {
@@ -258,7 +320,7 @@ static void DoCompare (const Type* lhs, const Type* rhs, typecmp_t* Result)
                            }
 
                            /* Compare the parameter lists */
-                           if (EqualFuncParams (F1->SymTab, F2->SymTab) == 0) {
+                           if (EqualFuncParams (F1, F2) == 0) {
                                /* Parameter list is not identical */
                        SetResult (Result, TC_INCOMPATIBLE);
                                return;