]> git.sur5r.net Git - cc65/blobdiff - src/cc65/typeconv.c
Added dummy classification macros for the remaining targets - even for those that...
[cc65] / src / cc65 / typeconv.c
index 34498259a21d8458257d0a53cd8e8dd17c13923f..ecde7349fbaac217d810ac5094d9f50f434dbb99 100644 (file)
@@ -6,8 +6,8 @@
 /*                                                                           */
 /*                                                                           */
 /*                                                                           */
-/* (C) 2002-2004 Ullrich von Bassewitz                                       */
-/*               Römerstrasse 52                                             */
+/* (C) 2002-2008 Ullrich von Bassewitz                                       */
+/*               Roemerstrasse 52                                            */
 /*               D-70794 Filderstadt                                         */
 /* EMail:        uz@cc65.org                                                 */
 /*                                                                           */
@@ -42,6 +42,7 @@
 #include "declare.h"
 #include "error.h"
 #include "expr.h"
+#include "loadexpr.h"
 #include "scanner.h"
 #include "typecmp.h"
 #include "typeconv.h"
 
 
 
-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 void DoConversion (ExprDesc* Expr, type* NewType)
+static void DoConversion (ExprDesc* Expr, const Type* NewType)
 /* Emit code to convert the given expression to a new type. */
 {
-    type*    OldType;
+    Type*    OldType;
     unsigned OldSize;
     unsigned NewSize;
 
@@ -112,63 +99,59 @@ static void DoConversion (ExprDesc* Expr, type* NewType)
          */
         if (NewSize > OldSize) {
             /* Load the value into the primary */
-            ExprLoad (CF_NONE, Expr);
+            LoadExpr (CF_NONE, Expr);
 
             /* Emit typecast code */
-            g_typecast (TypeOf (NewType), TypeOf (OldType));
+            g_typecast (TypeOf (NewType), TypeOf (OldType) | CF_FORCECHAR);
 
             /* Value is now in primary and an rvalue */
             ED_MakeRValExpr (Expr);
         }
 
-    } else {
-
-        /* We have an rvalue. Check for a constant. */
-        if (ED_IsLocAbs (Expr)) {
+    } else if (ED_IsLocAbs (Expr)) {
 
-            /* A cast of a constant to an integer. Be sure to handle sign
-             * extension correctly.
-             */
+        /* A cast of a constant numeric value to another type. Be sure
+         * to handle sign extension correctly.
+         */
 
-            /* Get the current and new size of the value */
-            unsigned OldBits = OldSize * 8;
-            unsigned NewBits = NewSize * 8;
+        /* 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) {
+        /* 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->Val &= (0xFFFFFFFFUL >> (32 - NewBits));
+            /* Cut the value to the new size */
+            Expr->IVal &= (0xFFFFFFFFUL >> (32 - NewBits));
 
-                /* If the new type is signed, sign extend the value */
-                if (!IsSignUnsigned (NewType)) {
-                    if (Expr->Val & (0x01UL << (NewBits-1))) {
-                        /* Beware: Use the safe shift routine here. */
-                        Expr->Val |= shl_l (~0UL, NewBits);
-                    }
+            /* If the new type is signed, sign extend the value */
+            if (IsSignSigned (NewType)) {
+                if (Expr->IVal & (0x01UL << (NewBits-1))) {
+                    /* Beware: Use the safe shift routine here. */
+                    Expr->IVal |= shl_l (~0UL, NewBits);
                 }
             }
+        }
 
-        } else {
+    } 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) {
+        /* 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 */
-                ExprLoad (CF_NONE, Expr);
+            /* Load the value into the primary */
+            LoadExpr (CF_NONE, Expr);
 
-                /* Emit typecast code. */
-                g_typecast (TypeOf (NewType) | CF_FORCECHAR, TypeOf (OldType));
+            /* Emit typecast code. */
+            g_typecast (TypeOf (NewType), TypeOf (OldType) | CF_FORCECHAR);
 
-                /* Value is now a rvalue in the primary */
-                ED_MakeRValExpr (Expr);
-            }
+            /* Value is now a rvalue in the primary */
+            ED_MakeRValExpr (Expr);
         }
     }
 
@@ -179,16 +162,21 @@ ExitPoint:
 
 
 
-void TypeConversion (ExprDesc* Expr, type* NewType)
+void TypeConversion (ExprDesc* Expr, 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);
+#if 0
+    /* Debugging */
+    printf ("Expr:\n=======================================\n");
+    PrintExprDesc (stdout, Expr);
+    printf ("Type:\n=======================================\n");
+    PrintType (stdout, NewType);
+    printf ("\n");
+    PrintRawType (stdout, NewType);
+#endif
 
     /* First, do some type checking */
     if (IsTypeVoid (NewType) || IsTypeVoid (Expr->Type)) {
@@ -198,58 +186,78 @@ void TypeConversion (ExprDesc* Expr, type* NewType)
                Error ("Illegal type");
     }
 
+    /* If Expr is a function, convert it to pointer to function */
+    if (IsTypeFunc(Expr->Type)) {
+        Expr->Type = PointerTo (Expr->Type);
+    }
+
+    /* If both types are equal, no conversion is needed */
+    if (TypeCmp (Expr->Type, NewType) >= TC_EQUAL) {
+        /* We're already done */
+        return;
+    }
+
     /* Check for conversion problems */
     if (IsClassInt (NewType)) {
 
         /* Handle conversions to int type */
                if (IsClassPtr (Expr->Type)) {
-           /* Pointer -> int conversion */
+           /* Pointer -> int conversion. Convert array to pointer */
+            if (IsTypeArray (Expr->Type)) {
+                Expr->Type = ArrayToPtr (Expr->Type);
+            }
            Warning ("Converting pointer to integer without a cast");
-               } else if (!IsClassInt (Expr->Type)) {
+               } else if (!IsClassInt (Expr->Type) && !IsClassFloat (Expr->Type)) {
            Error ("Incompatible types");
                }
 
+    } else if (IsClassFloat (NewType)) {
+
+        if (!IsClassFloat (Expr->Type) && !IsClassInt (Expr->Type)) {
+            Error ("Incompatible types");
+        }
+
     } else if (IsClassPtr (NewType)) {
 
         /* Handle conversions to pointer type */
-       if (IsClassPtr (Expr->Type)) {
+               if (IsClassPtr (Expr->Type)) {
+
+            /* Convert array to pointer */
+            if (IsTypeArray (Expr->Type)) {
+                Expr->Type = ArrayToPtr (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.
+            *   - 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");
-                       break;
-
-                   case TC_QUAL_DIFF:
-                       Error ("Pointer types differ in type qualifiers");
-                       break;
-
-                   default:
-                       /* Ok */
-                       break;
-               }
-           }
+           if (!IsTypeVoid (Indirect (NewType)) && !IsTypeVoid (Indirect (Expr->Type))) {
+               /* Compare the types */
+                switch (TypeCmp (NewType, Expr->Type)) {
+
+                   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 (Expr->Type)) {
            /* Int to pointer assignment is valid only for constant zero */
-           if (!ED_IsConstAbsInt (Expr) || Expr->Val != 0) {
+           if (!ED_IsConstAbsInt (Expr) || Expr->IVal != 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");
-           }
        } else {
-           Error ("Incompatible types");
-       }
+           Error ("Incompatible types");
+       }
 
     } else {
 
@@ -265,11 +273,9 @@ void TypeConversion (ExprDesc* Expr, type* NewType)
 
 
 void TypeCast (ExprDesc* Expr)
-/* Handle an explicit cast. The function returns true if the resulting
- * expression is an lvalue and false if not.
- */
+/* Handle an explicit cast. */
 {
-    type    NewType[MAXTYPELEN];
+    Type    NewType[MAXTYPELEN];
 
     /* Skip the left paren */
     NextToken ();
@@ -284,7 +290,7 @@ void TypeCast (ExprDesc* Expr)
     hie10 (Expr);
 
     /* Convert functions and arrays to "pointer to" object */
-    DoPtrConversions (Expr);
+    Expr->Type = PtrConversion (Expr->Type);
 
     /* Convert the value. */
     DoConversion (Expr, NewType);
@@ -293,3 +299,4 @@ void TypeCast (ExprDesc* Expr)
 
 
 
+