]> git.sur5r.net Git - cc65/commitdiff
Rewrote type conversions
authorcuz <cuz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Mon, 11 Aug 2003 20:18:30 +0000 (20:18 +0000)
committercuz <cuz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Mon, 11 Aug 2003 20:18:30 +0000 (20:18 +0000)
git-svn-id: svn://svn.cc65.org/cc65/trunk@2262 b7a2c559-68d2-44c3-8de9-860c34a00d81

17 files changed:
src/cc65/asmcode.c
src/cc65/assignment.c
src/cc65/assignment.h
src/cc65/declare.c
src/cc65/expr.c
src/cc65/expr.h
src/cc65/locals.c
src/cc65/make/gcc.mak
src/cc65/make/watcom.mak
src/cc65/segments.c
src/cc65/segments.h
src/cc65/stdfunc.c
src/cc65/stmt.c
src/cc65/typecast.c [deleted file]
src/cc65/typecast.h [deleted file]
src/cc65/typeconv.c [new file with mode: 0644]
src/cc65/typeconv.h [new file with mode: 0644]

index 788dd5bece3f9fd0d7c0f339baa6d1d65ab5478a..776e36f674e2b4efcf12693030eeac5bc5488f98 100644 (file)
@@ -85,7 +85,7 @@ void WriteOutput (FILE* F)
     SymEntry* Entry;
 
     /* Output the global data segment */
-    CHECK (CS_GetEntryCount (CS->Code) == 0);
+    CHECK (!HaveGlobalCode ());
     OutputSegments (CS, F);
 
     /* Output all global or referenced functions */
index 3427468eac5057567d4fb88bbe97012d6fdc19f0..a6f00ac13e7d7b7b752f9c7aa5a3470da3e264b8 100644 (file)
@@ -6,9 +6,9 @@
 /*                                                                           */
 /*                                                                           */
 /*                                                                           */
-/* (C) 2002      Ullrich von Bassewitz                                       */
-/*               Wacholderweg 14                                             */
-/*               D-70597 Stuttgart                                           */
+/* (C) 2002-2003 Ullrich von Bassewitz                                       */
+/*               Römerstrasse 52                                             */
+/*               D-70794 Filderstadt                                         */
 /* EMail:        uz@cc65.org                                                 */
 /*                                                                           */
 /*                                                                           */
@@ -39,6 +39,7 @@
 #include "error.h"
 #include "expr.h"
 #include "typecmp.h"
+#include "typeconv.h"
 #include "assignment.h"
 
 
@@ -49,7 +50,7 @@
 
 
 
-void Assignment (ExprDesc* lval)
+int Assignment (ExprDesc* lval)
 /* Parse an assignment */
 {
     int k;
@@ -86,7 +87,7 @@ void Assignment (ExprDesc* lval)
         if (UseReg) {
             PushAddr (lval);
         } else {
-           exprhs (0, 0, lval);
+           exprhs (0, 0, lval);
             g_push (CF_PTR | CF_UNSIGNED, 0);
         }
 
@@ -147,27 +148,26 @@ void Assignment (ExprDesc* lval)
 
     } else {
 
-       /* Get the address on stack if needed */
-       PushAddr (lval);
+       /* Get the address on stack if needed */
+       PushAddr (lval);
 
-       /* Get the expression on the right of the '=' into the primary */
-       if (evalexpr (CF_NONE, hie1, &lval2) == 0) {
-           /* Constant expression. Adjust the types */
-           assignadjust (ltype, &lval2);
-           /* Put the value into the primary register */
-           exprhs (CF_NONE, 0, &lval2);
-       } else {
-           /* Expression is not constant and already in the primary */
-           assignadjust (ltype, &lval2);
-       }
+       /* Read the expression on the right side of the '=' */
+       k = hie1 (&lval2);
+
+       /* Do type conversion if necessary */
+       k = TypeConversion (&lval2, k, ltype);
+
+       /* If necessary, load the value into the primary register */
+       exprhs (CF_NONE, k, &lval2);
 
        /* Generate a store instruction */
        Store (lval, 0);
 
     }
 
-    /* Value is still in primary */
+    /* Value is still in primary and not an lvalue */
     lval->Flags = E_MEXPR;
+    return 0;
 }
 
 
index dee5f7f1775c55362a4abc15d0574e3bb23caf0f..68c17bffd84f92bbe2dfaaef0ed8a195fde8894a 100644 (file)
@@ -6,9 +6,9 @@
 /*                                                                           */
 /*                                                                           */
 /*                                                                           */
-/* (C) 2002      Ullrich von Bassewitz                                       */
-/*               Wacholderweg 14                                             */
-/*               D-70597 Stuttgart                                           */
+/* (C) 2002-2003 Ullrich von Bassewitz                                       */
+/*               Römerstrasse 52                                             */
+/*               D-70794 Filderstadt                                         */
 /* EMail:        uz@cc65.org                                                 */
 /*                                                                           */
 /*                                                                           */
@@ -49,7 +49,7 @@
 
 
 
-void Assignment (ExprDesc* lval);
+int Assignment (ExprDesc* lval);
 /* Parse an assignment */
 
 
index 93760bc820401ffde66e67fa25ece85d40aabebb..59a618dac423253696cfedd9b3b688d0cad1b416 100644 (file)
@@ -44,6 +44,7 @@
 #include "anonname.h"
 #include "codegen.h"
 #include "datatype.h"
+#include "declare.h"
 #include "declattr.h"
 #include "error.h"
 #include "expr.h"
@@ -54,7 +55,7 @@
 #include "pragma.h"
 #include "scanner.h"
 #include "symtab.h"
-#include "declare.h"
+#include "typeconv.h"
 
 
 
@@ -1076,18 +1077,10 @@ static void ClosingCurlyBraces (unsigned BracesExpected)
 static unsigned ParseScalarInit (type* T)
 /* Parse initializaton for scalar data types. Return the number of data bytes. */
 {
-    static const unsigned long Masks[] = {
-        0x000000FFUL, 0x0000FFFFUL, 0x00FFFFFFUL, 0xFFFFFFFFUL
-    };
-    unsigned BraceCount;
     ExprDesc ED;
 
-    /* Get the size of the expected type */
-    unsigned Size = SizeOf (T);
-    CHECK (Size > 0 && Size <= sizeof(Masks)/sizeof(Masks[0]));
-
     /* Optional opening brace */
-    BraceCount = OpeningCurlyBraces (0);
+    unsigned BraceCount = OpeningCurlyBraces (0);
 
     /* We warn if an initializer for a scalar contains braces, because this is
      * quite unusual and often a sign for some problem in the input.
@@ -1096,13 +1089,9 @@ static unsigned ParseScalarInit (type* T)
         Warning ("Braces around scalar initializer");
     }
 
-    /* Expression */
+    /* Get the expression and convert it to the target type */
     ConstExpr (&ED);
-    if ((ED.Flags & E_MCTYPE) == E_TCONST) {
-        /* Make the const value the correct size */
-        ED.ConstVal &= Masks[Size-1];
-    }
-    assignadjust (T, &ED);
+    TypeConversion (&ED, 0, T);
 
     /* Output the data */
     DefineData (&ED);
@@ -1111,7 +1100,7 @@ static unsigned ParseScalarInit (type* T)
     ClosingCurlyBraces (BraceCount);
 
     /* Done */
-    return Size;
+    return SizeOf (T);
 }
 
 
@@ -1129,7 +1118,7 @@ static unsigned ParsePointerInit (type* T)
         /* Make the const value the correct size */
         ED.ConstVal &= 0xFFFF;
     }
-    assignadjust (T, &ED);
+    TypeConversion (&ED, 0, T);
 
     /* Output the data */
     DefineData (&ED);
@@ -1406,7 +1395,19 @@ static unsigned ParseInitInternal (type* T, int AllowFlexibleMembers)
 unsigned ParseInit (type* T)
 /* Parse initialization of variables. Return the number of data bytes. */
 {
-    return ParseInitInternal (T, !ANSI);
+    /* Parse the initialization */
+    unsigned Size = ParseInitInternal (T, !ANSI);
+
+    /* The initialization may not generate code on global level, because code
+     * outside function scope will never get executed.
+     */
+    if (HaveGlobalCode ()) {
+        Error ("Non constant initializers");
+        RemoveGlobalCode ();
+    }
+
+    /* Return the size needed for the initialization */
+    return Size;
 }
 
 
index b71d2d6709d06d16b9926210dc42141496ef933e..89e708e0d091539ff3b2e1c10c01314f737fb630 100644 (file)
@@ -31,8 +31,8 @@
 #include "scanner.h"
 #include "stdfunc.h"
 #include "symtab.h"
-#include "typecast.h"
 #include "typecmp.h"
+#include "typeconv.h"
 #include "expr.h"
 
 
@@ -87,7 +87,7 @@ static GenDesc GenOASGN  = { TOK_OR_ASSIGN,   GEN_NOPUSH,     g_or  };
 
 
 
-static int hie0 (ExprDesc *lval);
+int hie0 (ExprDesc *lval);
 /* Parse comma operator. */
 
 static int expr (int (*func) (ExprDesc*), ExprDesc *lval);
@@ -195,94 +195,6 @@ static unsigned typeadjust (ExprDesc* lhs, ExprDesc* rhs, int NoPush)
 
 
 
-unsigned assignadjust (type* lhst, ExprDesc* rhs)
-/* Adjust the type of the right hand expression so that it can be assigned to
- * the type on the left hand side. This function is used for assignment and
- * for converting parameters in a function call. It returns the code generator
- * flags for the operation. The type string of the right hand side will be
- * set to the type of the left hand side.
- */
-{
-    /* Get the type of the right hand side. Treat function types as
-     * pointer-to-function
-     */
-    type* rhst = rhs->Type;
-    if (IsTypeFunc (rhst)) {
-       rhst = PointerTo (rhst);
-    }
-
-    /* After calling this function, rhs will have the type of the lhs */
-    rhs->Type = lhst;
-
-    /* First, do some type checking */
-    if (IsTypeVoid (lhst) || IsTypeVoid (rhst)) {
-       /* If one of the sides are of type void, output a more apropriate
-        * error message.
-        */
-               Error ("Illegal type");
-    } else if (IsClassInt (lhst)) {
-               if (IsClassPtr (rhst)) {
-           /* Pointer -> int conversion */
-           Warning ("Converting pointer to integer without a cast");
-               } else if (IsClassInt (rhst)) {
-           /* Convert the rhs to the type of the lhs. */
-           unsigned flags = TypeOf (rhst);
-                   if (rhs->Flags == E_MCONST) {
-               flags |= CF_CONST;
-           }
-                   return g_typecast (TypeOf (lhst), flags);
-       } else {
-           Error ("Incompatible types");
-        }
-    } else if (IsClassPtr (lhst)) {
-       if (IsClassPtr (rhst)) {
-           /* Pointer to pointer assignment is valid, if:
-            *   - both point to the same types, or
-            *   - the rhs pointer is a void pointer, or
-            *   - the lhs pointer is a void pointer.
-            */
-           if (!IsTypeVoid (Indirect (lhst)) && !IsTypeVoid (Indirect (rhst))) {
-               /* Compare the types */
-               switch (TypeCmp (lhst, rhst)) {
-
-                   case TC_INCOMPATIBLE:
-                       Error ("Incompatible pointer types");
-                       break;
-
-                   case TC_QUAL_DIFF:
-                       Error ("Pointer types differ in type qualifiers");
-                       break;
-
-                   default:
-                       /* Ok */
-                       break;
-               }
-           }
-       } else if (IsClassInt (rhst)) {
-           /* Int to pointer assignment is valid only for constant zero */
-           if (rhs->Flags != E_MCONST || rhs->ConstVal != 0) {
-               Warning ("Converting integer to pointer without a cast");
-           }
-       } else if (IsTypeFuncPtr (lhst) && IsTypeFunc(rhst)) {
-           /* Assignment of function to function pointer is allowed, provided
-            * that both functions have the same parameter list.
-            */
-           if (TypeCmp (Indirect (lhst), rhst) < TC_EQUAL) {
-               Error ("Incompatible types");
-           }
-       } else {
-           Error ("Incompatible types");
-       }
-    } else {
-       Error ("Incompatible types");
-    }
-
-    /* Return an int value in all cases where the operands are not both ints */
-    return CF_INT;
-}
-
-
-
 void DefineData (ExprDesc* Expr)
 /* Output a data definition for the given expression */
 {
@@ -655,8 +567,8 @@ static unsigned FunctionParamList (FuncDesc* Func)
         * convert the actual argument to the type needed.
         */
                if (!Ellipsis) {
-           /* Promote the argument if needed */
-                   assignadjust (Param->Type, &lval);
+           /* Convert the argument to the parameter type if needed */
+            TypeConversion (&lval, 0, Param->Type);
 
            /* If we have a prototype, chars may be pushed as chars */
            Flags |= CF_FORCECHAR;
@@ -3022,12 +2934,10 @@ int hie1 (ExprDesc* lval)
 
 
 
-static int hie0 (ExprDesc *lval)
+int hie0 (ExprDesc *lval)
 /* Parse comma operator. */
 {
-    int k;
-
-    k = hie1 (lval);
+    int k = hie1 (lval);
     while (CurTok.Tok == TOK_COMMA) {
        NextToken ();
        k = hie1 (lval);
index efd1777e66bf2a2be7161ebd67dd20ed72956aa8..3398e7c278cc55732134740ff2abdbba21fc0891 100644 (file)
@@ -42,13 +42,6 @@ void CheckBoolExpr (ExprDesc* lval);
  * if not.
  */
 
-unsigned assignadjust (type* lhst, ExprDesc* rhs);
-/* Adjust the type of the right hand expression so that it can be assigned to
- * the type on the left hand side. This function is used for assignment and
- * for converting parameters in a function call. It returns the code generator
- * flags for the operation.
- */
-
 void exprhs (unsigned flags, int k, ExprDesc *lval);
 /* Put the result of an expression into the primary register */
 
@@ -58,13 +51,8 @@ void Store (ExprDesc* lval, const type* StoreType);
  * is NULL, use lval->Type instead.
  */
 
-void expression1 (ExprDesc* lval);
-/* Evaluate an expression on level 1 (no comma operator) and put it into
- * the primary register
- */
-
-void expression (ExprDesc* lval);
-/* Evaluate an expression and put it into the primary register */
+int hie0 (ExprDesc *lval);
+/* Parse comma operator. */
 
 int evalexpr (unsigned flags, int (*f) (ExprDesc*), ExprDesc* lval);
 /* Will evaluate an expression via the given function. If the result is a
@@ -73,6 +61,14 @@ int evalexpr (unsigned flags, int (*f) (ExprDesc*), ExprDesc* lval);
  * primary register and 1 is returned.
  */
 
+void expression1 (ExprDesc* lval);
+/* Evaluate an expression on level 1 (no comma operator) and put it into
+ * the primary register
+ */
+
+void expression (ExprDesc* lval);
+/* Evaluate an expression and put it into the primary register */
+
 void ConstExpr (ExprDesc* lval);
 /* Get a constant value */
 
index 9f4c05088740af5ca6dc55dc8d7d1909b58ea1c6..00d15d1bcefeb4d6d6c0c3d1b87783903332c36a 100644 (file)
@@ -46,8 +46,9 @@
 #include "expr.h"
 #include "function.h"
 #include "global.h"
-#include "symtab.h"
 #include "locals.h"
+#include "symtab.h"
+#include "typeconv.h"
 
 
 
@@ -62,7 +63,6 @@ static unsigned ParseRegisterDecl (Declaration* Decl, unsigned* SC, int Reg)
  * symbol data, which is the offset of the variable in the register bank.
  */
 {
-    unsigned Flags;
     unsigned InitLabel;
 
     /* Determine if this is a compound variable */
@@ -95,8 +95,8 @@ static unsigned ParseRegisterDecl (Declaration* Decl, unsigned* SC, int Reg)
 
             /* Parse the initialization generating a memory image of the
              * data in the RODATA segment. The function does return the size
-             * of the initialization data, which may be greater than the 
-             * actual size of the type, if the type is a structure with a 
+             * of the initialization data, which may be greater than the
+             * actual size of the type, if the type is a structure with a
              * flexible array member that has been initialized. Since we must
              * know the size of the data in advance for register variables,
              * we cannot allow that here.
@@ -110,27 +110,17 @@ static unsigned ParseRegisterDecl (Declaration* Decl, unsigned* SC, int Reg)
 
         } else {
 
-            /* Setup the type flags for the assignment */
-            Flags = CF_NONE;
-            if (Size == SIZEOF_CHAR) {
-                Flags |= CF_FORCECHAR;
-            }
+            /* Parse the expression */
+            int k = hie1 (InitExprDesc (&lval));
 
-            /* Get the expression into the primary */
-            if (evalexpr (Flags, hie1, &lval) == 0) {
-                /* Constant expression. Adjust the types */
-                assignadjust (Decl->Type, &lval);
-                Flags |= CF_CONST;
-                /* Load it into the primary */
-                exprhs (Flags, 0, &lval);
-            } else {
-                /* Expression is not constant and in the primary */
-                assignadjust (Decl->Type, &lval);
-            }
+            /* Convert it to the target type */
+            k = TypeConversion (&lval, k, Decl->Type);
+
+            /* Load the value into the primary */
+            exprhs (CF_NONE, k, &lval);
 
             /* Store the value into the variable */
-            Flags |= CF_REGVAR;
-            g_putstatic (Flags | TypeOf (Decl->Type), Reg, 0);
+            g_putstatic (CF_REGVAR | TypeOf (Decl->Type), Reg, 0);
 
         }
 
@@ -210,20 +200,28 @@ static unsigned ParseAutoDecl (Declaration* Decl, unsigned* SC)
 
             } else {
 
+                int k;
+
                 /* Allocate previously reserved local space */
                 F_AllocLocalSpace (CurrentFunc);
 
                 /* Setup the type flags for the assignment */
                 Flags = (Size == SIZEOF_CHAR)? CF_FORCECHAR : CF_NONE;
 
-                /* Get the expression into the primary */
-                if (evalexpr (Flags, hie1, &lval) == 0) {
-                    /* Constant expression. Adjust the types */
-                    assignadjust (Decl->Type, &lval);
-                    Flags |= CF_CONST;
+                /* Parse the expression */
+                k = hie1 (InitExprDesc (&lval));
+
+                /* Convert it to the target type */
+                k = TypeConversion (&lval, k, Decl->Type);
+
+                /* If the value is not const, load it into the primary.
+                 * Otherwise pass the information to the code generator.
+                 */
+                if (k != 0 || lval.Flags != E_MCONST) {
+                    exprhs (CF_NONE, k, &lval);
+                    k = 0;
                 } else {
-                    /* Expression is not constant and in the primary */
-                    assignadjust (Decl->Type, &lval);
+                    Flags |= CF_CONST;
                 }
 
                 /* Push the value */
@@ -286,24 +284,17 @@ static unsigned ParseAutoDecl (Declaration* Decl, unsigned* SC)
 
             } else {
 
-                /* Setup the type flags for the assignment */
-                Flags = (Size == SIZEOF_CHAR)? CF_FORCECHAR : CF_NONE;
+                /* Parse the expression */
+                int k = hie1 (InitExprDesc (&lval));
 
-                /* Get the expression into the primary */
-                if (evalexpr (Flags, hie1, &lval) == 0) {
-                    /* Constant expression. Adjust the types */
-                    assignadjust (Decl->Type, &lval);
-                    Flags |= CF_CONST;
-                    /* Load it into the primary */
-                    exprhs (Flags, 0, &lval);
-                } else {
-                    /* Expression is not constant and in the primary */
-                    assignadjust (Decl->Type, &lval);
-                }
+                /* Convert it to the target type */
+                k = TypeConversion (&lval, k, Decl->Type);
 
-                /* Store the value into the variable */
-                g_putstatic (Flags | TypeOf (Decl->Type), SymData, 0);
+                /* Load the value into the primary */
+                exprhs (CF_NONE, k, &lval);
 
+                /* Store the value into the variable */
+                g_putstatic (TypeOf (Decl->Type), SymData, 0);
             }
 
             /* Mark the variable as referenced */
index 968a20b236c1c0b011b2a6c281173825a564079b..b87785b0b7409ad81525760aa4c6aab9edd526d1 100644 (file)
@@ -82,8 +82,8 @@ OBJS =        anonname.o      \
        symentry.o      \
        symtab.o        \
        textseg.o       \
-        typecast.o      \
        typecmp.o       \
+        typeconv.o      \
        util.o
 
 LIBS = $(COMMON)/common.a
index fceb1963c156597e5fe3af85209c4f7304327dea..20c6bb737fe7eb690ec79e5cb9fd971f048b57b7 100644 (file)
@@ -103,8 +103,8 @@ OBJS =      anonname.obj    \
        symentry.obj    \
        symtab.obj      \
        textseg.obj     \
-        typecast.obj    \
        typecmp.obj     \
+        typeconv.obj    \
        util.obj
 
 LIBS = ..\common\common.lib
index dd7817b8887149d68ead2401edad3c0b0c411653..dabb4a4a601e59ad5ae62aeff86b9ba73918db7a 100644 (file)
@@ -224,6 +224,22 @@ void AddDataLine (const char* Format, ...)
 
 
 
+int HaveGlobalCode (void)
+/* Return true if the global code segment contains entries (which is an error) */
+{
+    return (CS_GetEntryCount (GS->Code) > 0);
+}
+
+
+
+void RemoveGlobalCode (void)
+/* Remove all code from the global code segment. Used for error recovery. */
+{
+    CS_DelEntries (GS->Code, 0, CS_GetEntryCount (GS->Code));
+}
+
+
+
 void OutputSegments (const Segments* S, FILE* F)
 /* Output the given segments to the file */
 {
index e7590ee14a672e02e975ba1aea653294fb8c553a..81496ed1fbed664fd936a44e61579545fa4998dd 100644 (file)
@@ -132,6 +132,12 @@ void AddCode (opc_t OPC, am_t AM, const char* Arg, struct CodeLabel* JumpTo);
 void AddDataLine (const char* Format, ...) attribute ((format (printf, 1, 2)));
 /* Add a line of data to the current data segment */
 
+int HaveGlobalCode (void);
+/* Return true if the global code segment contains entries (which is an error) */
+
+void RemoveGlobalCode (void);
+/* Remove all code from the global code segment. Used for error recovery. */
+
 void OutputSegments (const Segments* S, FILE* F);
 /* Output the given segments to the file */
 
index 219ad470676da2404e15c010d87da75a8f04371c..40d74f692695bb5c49d81411287e0681a35bc27a 100644 (file)
@@ -48,6 +48,7 @@
 #include "litpool.h"
 #include "scanner.h"
 #include "stdfunc.h"
+#include "typeconv.h"
 
 
 
@@ -106,35 +107,36 @@ static struct StdFuncDesc* FindFunc (const char* Name)
 
 
 
-static unsigned ParseArg (type* Type, ExprDesc* pval)
+static unsigned ParseArg (type* Type, ExprDesc* Arg)
 /* Parse one argument but do not push it onto the stack. Return the code
  * generator flags needed to do the actual push.
  */
 {
-    unsigned CFlags;
-    unsigned Flags;
+    /* We have a prototype, so chars may be pushed as chars */
+    unsigned Flags = CF_FORCECHAR;
 
-    /* Do some optimization: If we have a constant value to push,
-     * use a special function that may optimize.
-     */
-    CFlags = CF_NONE;
-    if (CheckedSizeOf (Type) == 1) {
-        CFlags = CF_FORCECHAR;
-    }
-    Flags = CF_NONE;
-    if (evalexpr (CFlags, hie1, pval) == 0) {
-        /* A constant value */
-        Flags |= CF_CONST;
-    }
+    /* Read the expression we're going to pass to the function */
+    int k = hie1 (InitExprDesc (Arg));
 
-    /* Promote the argument if needed */
-    assignadjust (Type, pval);
+    /* Convert this expression to the expected type */
+    k = TypeConversion (Arg, k, Type);
 
-    /* We have a prototype, so chars may be pushed as chars */
-    Flags |= CF_FORCECHAR;
+    /* If the value is not a constant, load it into the primary */
+    if (k != 0 || Arg->Flags != E_MCONST) {
+
+        /* Load into the primary */
+        exprhs (CF_NONE, k, Arg);
+        k = 0;
+
+    } else {
+
+        /* Remember that we have a constant value */
+        Flags |= CF_CONST;
+
+    }
 
     /* Use the type of the argument for the push */
-    return (Flags | TypeOf (pval->Type));
+    return (Flags | TypeOf (Arg->Type));
 }
 
 
@@ -208,20 +210,17 @@ static void StdFunc_strlen (FuncDesc* F attribute ((unused)),
                             ExprDesc* lval attribute ((unused)))
 /* Handle the strlen function */
 {
-    static type ParamType[] = { T_PTR, T_SCHAR, T_END };
-
-    ExprDesc Param;
-    unsigned CodeFlags;
+    static type   ParamType[] = { T_PTR, T_SCHAR, T_END };
+    int           k;
+    ExprDesc      Param;
+    unsigned      CodeFlags;
     unsigned long ParamName;
 
-    /* Fetch the parameter */
-    int k = hie1 (InitExprDesc (&Param));
-
     /* Setup the argument type string */
     ParamType[1] = GetDefaultChar () | T_QUAL_CONST;
 
-    /* Convert the parameter type to the type needed, check for mismatches */
-    assignadjust (ParamType, &Param);
+    /* Fetch the parameter and convert it to the type needed */
+    k = TypeConversion (&Param, hie1 (InitExprDesc (&Param)), ParamType);
 
     /* Check if the parameter is a constant array of some type, or a numeric
      * address cast to a pointer.
index 408297a184d7051b0191082fba2624d661dc3fc9..6a18b43b36862c19538f5494e10000e318911997 100644 (file)
@@ -58,6 +58,7 @@
 #include "swstmt.h"
 #include "symtab.h"
 #include "stmt.h"
+#include "typeconv.h"
 
 
 
@@ -89,13 +90,13 @@ static void CheckSemi (int* PendingToken)
  * error message if not found (plus some error recovery). If PendingToken is
  * NULL, it will the skip the token, otherwise it will store one to
  * PendingToken.
- * This function is a special version of CheckTok with the addition of the 
+ * This function is a special version of CheckTok with the addition of the
  * error recovery.
  */
 {
     int HaveToken = (CurTok.Tok == TOK_SEMI);
     if (!HaveToken) {
-       Error ("`;' expected");                                  
+       Error ("`;' expected");
         /* Try to be smart about errors */
         if (CurTok.Tok == TOK_COLON || CurTok.Tok == TOK_COMMA) {
             HaveToken = 1;
@@ -256,7 +257,8 @@ static void WhileStatement (void)
 static void ReturnStatement (void)
 /* Handle the 'return' statement */
 {
-    ExprDesc lval;
+    ExprDesc Expr;
+    int k;
 
     NextToken ();
     if (CurTok.Tok != TOK_SEMI) {
@@ -266,12 +268,17 @@ static void ReturnStatement (void)
                    Error ("Returning a value in function with return type void");
                }
 
-       /* Evaluate the return expression. Result will be in primary */
-       expression (&lval);
+       /* Evaluate the return expression */
+       k = hie0 (InitExprDesc (&Expr));
 
-       /* Convert the return value to the type of the function result */
+       /* Ignore the return expression if the function returns void */
        if (!F_HasVoidReturn (CurrentFunc)) {
-                   assignadjust (F_GetReturnType (CurrentFunc), &lval);
+
+           /* Convert the return value to the type of the function result */
+           TypeConversion (&Expr, k, F_GetReturnType (CurrentFunc));
+
+           /* Load the value into the primary */
+           exprhs (CF_NONE, k, &Expr);
        }
 
     } else if (!F_HasVoidReturn (CurrentFunc) && !F_HasOldStyleIntRet (CurrentFunc)) {
diff --git a/src/cc65/typecast.c b/src/cc65/typecast.c
deleted file mode 100644 (file)
index 7e0c36d..0000000
+++ /dev/null
@@ -1,213 +0,0 @@
-/*****************************************************************************/
-/*                                                                           */
-/*                                typecast.c                                 */
-/*                                                                           */
-/*                             Handle type casts                             */
-/*                                                                           */
-/*                                                                           */
-/*                                                                           */
-/* (C) 2002      Ullrich von Bassewitz                                       */
-/*               Römerstrasse 52                                             */
-/*               D-70794 Filderstadt                                         */
-/* EMail:        uz@cc65.org                                                 */
-/*                                                                           */
-/*                                                                           */
-/* This software is provided 'as-is', without any expressed or implied       */
-/* warranty.  In no event will the authors be held liable for any damages    */
-/* arising from the use of this software.                                    */
-/*                                                                           */
-/* Permission is granted to anyone to use this software for any purpose,     */
-/* including commercial applications, and to alter it and redistribute it    */
-/* freely, subject to the following restrictions:                            */
-/*                                                                           */
-/* 1. The origin of this software must not be misrepresented; you must not   */
-/*    claim that you wrote the original software. If you use this software   */
-/*    in a product, an acknowledgment in the product documentation would be  */
-/*    appreciated but is not required.                                       */
-/* 2. Altered source versions must be plainly marked as such, and must not   */
-/*    be misrepresented as being the original software.                      */
-/* 3. This notice may not be removed or altered from any source              */
-/*    distribution.                                                          */
-/*                                                                           */
-/*****************************************************************************/
-
-
-
-/* cc65 */
-#include "codegen.h"
-#include "datatype.h"
-#include "declare.h"
-#include "error.h"
-#include "expr.h"
-#include "scanner.h"
-#include "typecast.h"
-
-
-
-/*****************************************************************************/
-/*                                  Code                                    */
-/*****************************************************************************/
-
-
-
-int TypeCast (ExprDesc* lval)
-/* Handle an explicit cast. The function returns true if the resulting
- * expression is an lvalue and false if not.
- */
-{
-    int      k;
-    type*    OldType;
-    type     NewType[MAXTYPELEN];
-    unsigned OldSize;
-    unsigned NewSize;
-
-    /* Skip the left paren */
-    NextToken ();
-
-    /* Read the type */
-    ParseType (NewType);
-
-    /* Closing paren */
-    ConsumeRParen ();
-
-    /* Read the expression we have to cast */
-    k = hie10 (lval);
-
-    /* If the expression is a function, treat it as pointer to function.
-     * If the expression is an array, treat it as pointer to first element.
-     */
-    if (IsTypeFunc (lval->Type)) {
-       lval->Type = PointerTo (lval->Type);
-    } else if (IsTypeArray (lval->Type)) {
-        lval->Type = ArrayToPtr (lval->Type);
-    }
-
-    /* Remember the old type */
-    OldType = lval->Type;
-
-    /* If we're casting to void, we're done. Note: This does also cover a cast
-     * void -> void.
-     */
-    if (IsTypeVoid (NewType)) {
-        k = 0;          /* Never an lvalue */
-        goto ExitPoint;
-    }
-
-    /* Don't allow casts from void to something else. */
-    if (IsTypeVoid (OldType)) {
-        Error ("Cannot cast from `void' to something else");
-        goto ExitPoint;
-    }
-
-    /* Get the sizes of the types. Since we've excluded void types, checking
-     * for known sizes makes sense here.
-     */
-    OldSize = CheckedSizeOf (OldType);
-    NewSize = CheckedSizeOf (NewType);
-
-    /* Is this a cast of something into an integer? */
-    if (IsClassInt (NewType)) {
-
-        /* lvalue? */
-        if (k != 0) {
-
-            /* We have an lvalue. If the new size is smaller than the new one,
-             * we don't need to do anything. The compiler will generate code
-             * to load only the portion of the value that is actually needed.
-             * This works only on a little endian architecture, but that's
-             * what we support.
-             * If both sizes are equal, do also leave the value alone.
-             * If the new size is larger, we must convert the value.
-             */
-            if (NewSize > OldSize) {
-                /* Load the value into the primary */
-                exprhs (CF_NONE, k, lval);
-
-                /* Emit typecast code */
-                g_typecast (TypeOf (OldType), TypeOf (NewType));
-
-                /* Value is now in primary */
-                lval->Flags = E_MEXPR;
-                k = 0;
-            }
-
-        } else {
-
-            /* We have an rvalue. Check for a constant. */
-            if (lval->Flags == E_MCONST) {
-
-                /* A cast of a constant to an integer. Be sure to handle sign
-                 * extension correctly.
-                 */
-
-                /* Get the current and new size of the value */
-                unsigned OldBits = OldSize * 8;
-                unsigned NewBits = NewSize * 8;
-
-                /* Check if the new datatype will have a smaller range. If it
-                 * has a larger range, things are ok, since the value is 
-                 * internally already represented by a long.
-                 */
-                if (NewBits <= OldBits) {
-
-                    /* Cut the value to the new size */
-                    lval->ConstVal &= (0xFFFFFFFFUL >> (32 - NewBits));
-
-                    /* If the new type is signed, sign extend the value */
-                    if (!IsSignUnsigned (NewType)) {
-                        if (lval->ConstVal & (0x01UL << (NewBits-1))) {
-                            lval->ConstVal |= ((~0L) << NewBits);
-                        }
-                    }
-                }
-
-            } else {
-
-                /* The value is not a constant. If the sizes of the types are
-                 * not equal, add conversion code. Be sure to convert chars
-                 * correctly.
-                 */
-                if (OldSize != NewSize) {
-
-                    /* Load the value into the primary */
-                    exprhs (CF_NONE, k, lval);
-
-                    /* Emit typecast code. */
-                    g_typecast (TypeOf (OldType), TypeOf (NewType) | CF_FORCECHAR);
-
-                    /* Value is now in primary */
-                    lval->Flags = E_MEXPR;
-                    k = 0;
-                }
-            }
-        }
-
-    } else {
-
-        /* All other stuff is handled equally */
-        if (NewSize != OldSize) {
-            /* Load the value into the primary */
-            exprhs (CF_NONE, k, lval);
-
-            /* Emit typecast code */
-            g_typecast (TypeOf (OldType), TypeOf (NewType) | CF_FORCECHAR);
-
-            /* Value is now in primary */
-            lval->Flags = E_MEXPR;
-            k = 0;
-        }
-    }
-
-ExitPoint:
-    /* The expression has always the new type */
-    ReplaceType (lval, NewType);
-
-    /* Done */
-    return k;
-}
-
-
-
-
-
-
diff --git a/src/cc65/typecast.h b/src/cc65/typecast.h
deleted file mode 100644 (file)
index bca3b1a..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-/*****************************************************************************/
-/*                                                                           */
-/*                                typecast.h                                 */
-/*                                                                           */
-/*                             Handle type casts                             */
-/*                                                                           */
-/*                                                                           */
-/*                                                                           */
-/* (C) 2002      Ullrich von Bassewitz                                       */
-/*               Wacholderweg 14                                             */
-/*               D-70597 Stuttgart                                           */
-/* EMail:        uz@cc65.org                                                 */
-/*                                                                           */
-/*                                                                           */
-/* This software is provided 'as-is', without any expressed or implied       */
-/* warranty.  In no event will the authors be held liable for any damages    */
-/* arising from the use of this software.                                    */
-/*                                                                           */
-/* Permission is granted to anyone to use this software for any purpose,     */
-/* including commercial applications, and to alter it and redistribute it    */
-/* freely, subject to the following restrictions:                            */
-/*                                                                           */
-/* 1. The origin of this software must not be misrepresented; you must not   */
-/*    claim that you wrote the original software. If you use this software   */
-/*    in a product, an acknowledgment in the product documentation would be  */
-/*    appreciated but is not required.                                       */
-/* 2. Altered source versions must be plainly marked as such, and must not   */
-/*    be misrepresented as being the original software.                      */
-/* 3. This notice may not be removed or altered from any source              */
-/*    distribution.                                                          */
-/*                                                                           */
-/*****************************************************************************/
-
-
-
-#ifndef TYPECAST_H
-#define TYPECAST_H
-
-
-                     
-/* cc65 */
-#include "exprdesc.h"
-
-
-
-/*****************************************************************************/
-/*                                  Code                                    */
-/*****************************************************************************/
-
-
-
-int TypeCast (ExprDesc* lval);
-/* Handle an explicit cast. The function returns true if the resulting
- * expression is an lvalue and false if not.
- */
-
-
-
-/* End of typecast.h */
-#endif
-
-
-
diff --git a/src/cc65/typeconv.c b/src/cc65/typeconv.c
new file mode 100644 (file)
index 0000000..38ac201
--- /dev/null
@@ -0,0 +1,300 @@
+/*****************************************************************************/
+/*                                                                           */
+/*                                typeconv.c                                 */
+/*                                                                           */
+/*                          Handle type conversions                          */
+/*                                                                           */
+/*                                                                           */
+/*                                                                           */
+/* (C) 2002-2003 Ullrich von Bassewitz                                       */
+/*               Römerstrasse 52                                             */
+/*               D-70794 Filderstadt                                         */
+/* EMail:        uz@cc65.org                                                 */
+/*                                                                           */
+/*                                                                           */
+/* This software is provided 'as-is', without any expressed or implied       */
+/* warranty.  In no event will the authors be held liable for any damages    */
+/* arising from the use of this software.                                    */
+/*                                                                           */
+/* Permission is granted to anyone to use this software for any purpose,     */
+/* including commercial applications, and to alter it and redistribute it    */
+/* freely, subject to the following restrictions:                            */
+/*                                                                           */
+/* 1. The origin of this software must not be misrepresented; you must not   */
+/*    claim that you wrote the original software. If you use this software   */
+/*    in a product, an acknowledgment in the product documentation would be  */
+/*    appreciated but is not required.                                       */
+/* 2. Altered source versions must be plainly marked as such, and must not   */
+/*    be misrepresented as being the original software.                      */
+/* 3. This notice may not be removed or altered from any source              */
+/*    distribution.                                                          */
+/*                                                                           */
+/*****************************************************************************/
+
+
+
+/* cc65 */
+#include "codegen.h"
+#include "datatype.h"
+#include "declare.h"
+#include "error.h"
+#include "expr.h"
+#include "scanner.h"
+#include "typecmp.h"
+#include "typeconv.h"
+
+
+
+/*****************************************************************************/
+/*                                  Code                                    */
+/*****************************************************************************/
+
+
+
+static void DoPtrConversions (ExprDesc* Expr)
+/* If the expression is a function, convert it to pointer to function.
+ * If the expression is an array, convert it to pointer to first element.
+ */
+{
+    if (IsTypeFunc (Expr->Type)) {
+       Expr->Type = PointerTo (Expr->Type);
+    } else if (IsTypeArray (Expr->Type)) {
+        Expr->Type = ArrayToPtr (Expr->Type);
+    }
+}
+
+
+
+static int DoConversion (ExprDesc* Expr, int k, type* NewType)
+/* Emit code to convert the given expression to a new type. */
+{
+    type*    OldType;
+    unsigned OldSize;
+    unsigned NewSize;
+
+
+    /* Remember the old type */
+    OldType = Expr->Type;
+
+    /* If we're converting to void, we're done. Note: This does also cover a
+     * conversion void -> void.
+     */
+    if (IsTypeVoid (NewType)) {
+        k = 0;          /* Never an lvalue */
+        goto ExitPoint;
+    }
+
+    /* Don't allow casts from void to something else. */
+    if (IsTypeVoid (OldType)) {
+        Error ("Cannot convert from `void' to something else");
+        goto ExitPoint;
+    }
+
+    /* Get the sizes of the types. Since we've excluded void types, checking
+     * for known sizes makes sense here.
+     */
+    OldSize = CheckedSizeOf (OldType);
+    NewSize = CheckedSizeOf (NewType);
+
+    /* lvalue? */
+    if (k != 0) {
+
+        /* We have an lvalue. If the new size is smaller than the new one,
+         * we don't need to do anything. The compiler will generate code
+         * to load only the portion of the value that is actually needed.
+         * This works only on a little endian architecture, but that's
+         * what we support.
+         * If both sizes are equal, do also leave the value alone.
+         * If the new size is larger, we must convert the value.
+         */
+        if (NewSize > OldSize) {
+            /* Load the value into the primary */
+            exprhs (CF_NONE, k, Expr);
+
+            /* Emit typecast code */
+            g_typecast (TypeOf (OldType), TypeOf (NewType));
+
+            /* Value is now in primary */
+            Expr->Flags = E_MEXPR;
+            k = 0;
+        }
+
+    } else {
+
+        /* We have an rvalue. Check for a constant. */
+        if (Expr->Flags == E_MCONST) {
+
+            /* A cast of a constant to an integer. Be sure to handle sign
+             * extension correctly.
+             */
+
+            /* Get the current and new size of the value */
+            unsigned OldBits = OldSize * 8;
+            unsigned NewBits = NewSize * 8;
+
+            /* Check if the new datatype will have a smaller range. If it
+             * has a larger range, things are ok, since the value is
+             * internally already represented by a long.
+             */
+            if (NewBits <= OldBits) {
+
+                /* Cut the value to the new size */
+                Expr->ConstVal &= (0xFFFFFFFFUL >> (32 - NewBits));
+
+                /* If the new type is signed, sign extend the value */
+                if (!IsSignUnsigned (NewType)) {
+                    if (Expr->ConstVal & (0x01UL << (NewBits-1))) {
+                        Expr->ConstVal |= ((~0L) << NewBits);
+                    }
+                }
+            }
+
+        } else {
+
+            /* The value is not a constant. If the sizes of the types are
+             * not equal, add conversion code. Be sure to convert chars
+             * correctly.
+             */
+            if (OldSize != NewSize) {
+
+                /* Load the value into the primary */
+                exprhs (CF_NONE, k, Expr);
+
+                /* Emit typecast code. */
+                g_typecast (TypeOf (OldType), TypeOf (NewType) | CF_FORCECHAR);
+
+                /* Value is now in primary */
+                Expr->Flags = E_MEXPR;
+                k = 0;
+            }
+        }
+    }
+
+ExitPoint:
+    /* The expression has always the new type */
+    ReplaceType (Expr, NewType);
+
+    /* Done */
+    return k;
+}
+
+
+
+int TypeConversion (ExprDesc* Expr, int k, type* NewType)
+/* Do an automatic conversion of the given expression to the new type. Output
+ * warnings or errors where this automatic conversion is suspicious or
+ * impossible.
+ */
+{
+    /* Get the type of the right hand side. Treat function types as
+     * pointer-to-function
+     */
+    DoPtrConversions (Expr);
+
+    /* First, do some type checking */
+    if (IsTypeVoid (NewType) || IsTypeVoid (Expr->Type)) {
+       /* If one of the sides are of type void, output a more apropriate
+        * error message.
+        */
+               Error ("Illegal type");
+       return k;
+    }
+
+    /* Handle conversions to int type */
+    if (IsClassInt (NewType)) {
+               if (IsClassPtr (Expr->Type)) {
+           /* Pointer -> int conversion */
+           Warning ("Converting pointer to integer without a cast");
+               } else if (!IsClassInt (Expr->Type)) {
+           Error ("Incompatible types");
+       } else {
+           /* Convert the rhs to the type of the lhs. */
+           k = DoConversion (Expr, k, NewType);
+        }
+       return k;
+    }
+
+    /* Handle conversions to pointer type */
+    if (IsClassPtr (NewType)) {
+       if (IsClassPtr (Expr->Type)) {
+           /* Pointer to pointer assignment is valid, if:
+            *   - both point to the same types, or
+            *   - the rhs pointer is a void pointer, or
+            *   - the lhs pointer is a void pointer.
+            */
+           if (!IsTypeVoid (Indirect (NewType)) && !IsTypeVoid (Indirect (Expr->Type))) {
+               /* Compare the types */
+               switch (TypeCmp (NewType, Expr->Type)) {
+
+                   case TC_INCOMPATIBLE:
+                       Error ("Incompatible pointer types");
+                       return k;
+
+                   case TC_QUAL_DIFF:
+                       Error ("Pointer types differ in type qualifiers");
+                       return k;
+
+                   default:
+                       /* Ok */
+                       break;
+               }
+           }
+       } else if (IsClassInt (Expr->Type)) {
+           /* Int to pointer assignment is valid only for constant zero */
+           if (Expr->Flags != E_MCONST || Expr->ConstVal != 0) {
+               Warning ("Converting integer to pointer without a cast");
+           }
+       } else if (IsTypeFuncPtr (NewType) && IsTypeFunc(Expr->Type)) {
+           /* Assignment of function to function pointer is allowed, provided
+            * that both functions have the same parameter list.
+            */
+           if (TypeCmp (Indirect (NewType), Expr->Type) < TC_EQUAL) {
+               Error ("Incompatible types");
+               return k;
+           }
+       } else {
+           Error ("Incompatible types");
+           return k;
+       }
+
+       /* If we come here, the conversion is ok, convert and return the result */
+       return DoConversion (Expr, k, NewType);
+
+    }
+
+    /* Invalid automatic conversion */
+    Error ("Incompatible types");
+    return k;
+}
+
+
+
+int TypeCast (ExprDesc* Expr)
+/* Handle an explicit cast. The function returns true if the resulting
+ * expression is an lvalue and false if not.
+ */
+{
+    int            k;
+    type    NewType[MAXTYPELEN];
+
+    /* Skip the left paren */
+    NextToken ();
+
+    /* Read the type */
+    ParseType (NewType);
+
+    /* Closing paren */
+    ConsumeRParen ();
+
+    /* Read the expression we have to cast */
+    k = hie10 (Expr);
+
+    /* Convert functions and arrays to "pointer to" object */
+    DoPtrConversions (Expr);
+
+    /* Convert the value and return the result. */
+    return DoConversion (Expr, k, NewType);
+}
+
+
+
diff --git a/src/cc65/typeconv.h b/src/cc65/typeconv.h
new file mode 100644 (file)
index 0000000..51d4a76
--- /dev/null
@@ -0,0 +1,69 @@
+/*****************************************************************************/
+/*                                                                           */
+/*                                typeconv.h                                 */
+/*                                                                           */
+/*                          Handle type conversions                          */
+/*                                                                           */
+/*                                                                           */
+/*                                                                           */
+/* (C) 2002-2003 Ullrich von Bassewitz                                       */
+/*               Römerstrasse 52                                             */
+/*               D-70794 Filderstadt                                         */
+/* EMail:        uz@cc65.org                                                 */
+/*                                                                           */
+/*                                                                           */
+/* This software is provided 'as-is', without any expressed or implied       */
+/* warranty.  In no event will the authors be held liable for any damages    */
+/* arising from the use of this software.                                    */
+/*                                                                           */
+/* Permission is granted to anyone to use this software for any purpose,     */
+/* including commercial applications, and to alter it and redistribute it    */
+/* freely, subject to the following restrictions:                            */
+/*                                                                           */
+/* 1. The origin of this software must not be misrepresented; you must not   */
+/*    claim that you wrote the original software. If you use this software   */
+/*    in a product, an acknowledgment in the product documentation would be  */
+/*    appreciated but is not required.                                       */
+/* 2. Altered source versions must be plainly marked as such, and must not   */
+/*    be misrepresented as being the original software.                      */
+/* 3. This notice may not be removed or altered from any source              */
+/*    distribution.                                                          */
+/*                                                                           */
+/*****************************************************************************/
+
+
+
+#ifndef TYPECONV_H
+#define TYPECONV_H
+
+
+
+/* cc65 */
+#include "exprdesc.h"
+
+
+
+/*****************************************************************************/
+/*                                  Code                                    */
+/*****************************************************************************/
+
+
+
+int TypeConversion (ExprDesc* Expr, int k, type* NewType);
+/* Do an automatic conversion of the given expression to the new type. Output
+ * warnings or errors where this automatic conversion is suspicious or
+ * impossible.
+ */
+
+int TypeCast (ExprDesc* Expr);
+/* Handle an explicit cast. The function returns true if the resulting
+ * expression is an lvalue and false if not.
+ */
+
+
+
+/* End of typeconv.h */
+#endif
+
+
+