]> git.sur5r.net Git - cc65/commitdiff
Fixed a bug in explicit type casts
authorcuz <cuz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Tue, 10 Oct 2000 20:40:36 +0000 (20:40 +0000)
committercuz <cuz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Tue, 10 Oct 2000 20:40:36 +0000 (20:40 +0000)
git-svn-id: svn://svn.cc65.org/cc65/trunk@354 b7a2c559-68d2-44c3-8de9-860c34a00d81

src/cc65/declare.c
src/cc65/expr.c
src/cc65/incpath.c

index 0a365db2cf1996434c41366c71cf89128ed6695c..c2b4c5313795158d4ab32ce13363f6c42b665a99 100644 (file)
@@ -659,7 +659,7 @@ static void ParseAnsiParamList (FuncDesc* F)
            Spec.StorageClass &= ~SC_DEF;
        }
 
-       /* Parse an attribute */
+       /* Parse an attribute ### */
        ParseAttribute (&Decl, &Attr);
 
        /* Create a symbol table entry */
index dc2252c7dd53466cd869e8c599b2e05e53a45743..a971ee322614115a4b18cdadebfa06acd8d027d6 100644 (file)
@@ -1010,7 +1010,7 @@ static int arrayref (int k, struct expent* lval)
                     * if necessary and the second one is a pointer).
             * Note: If ConstBaseAddr is true, we don't have a value on
             * stack, so to "swap" both, just push the subscript.
-            */
+            */
            if (ConstBaseAddr) {
                g_push (CF_INT, 0);
                exprhs (CF_NONE, k, lval);
@@ -1047,7 +1047,7 @@ static int arrayref (int k, struct expent* lval)
            rflags = lval2.e_flags & ~E_MCTYPE;
            ConstSubAddr = (rflags == E_MCONST)       || /* Constant numeric address */
                                    (rflags & E_MGLOBAL) != 0 || /* Static array, or ... */
-                           rflags == E_MLOCAL;          /* Local array */
+                           rflags == E_MLOCAL;          /* Local array */
 
                    if (ConstSubAddr && SizeOf (lval->e_tptr) == 1) {
 
@@ -1055,7 +1055,7 @@ static int arrayref (int k, struct expent* lval)
 
                /* Reverse the order of evaluation */
                unsigned flags = (SizeOf (lval2.e_tptr) == 1)? CF_CHAR : CF_INT;
-               RemoveCode (Mark2);
+               RemoveCode (Mark2);
 
                /* Get a pointer to the array into the primary. We have changed
                 * e_tptr above but we need the original type to load the
@@ -1411,7 +1411,6 @@ static int typecast (struct expent* lval)
 {
     int k;
     type Type[MAXTYPELEN];
-    unsigned rflags;
 
     /* Skip the left paren */
     NextToken ();
@@ -1425,19 +1424,69 @@ static int typecast (struct expent* lval)
     /* Read the expression we have to cast */
     k = hie10 (lval);
 
-    /* Get the type of the expression and honor constant values */
-    rflags = TypeOf (lval->e_tptr);
-    if (lval->e_flags & E_MCONST) {
-       rflags |= CF_CONST;
-    }
+    /* Check for a const expression */
+    if (k == 0 && lval->e_flags == E_MCONST) {
+
+       /* A cast of a constant to something else. If the new type is an int,
+        * be sure to handle the size extension correctly. If the new type is
+        * not an int, the cast is implementation specific anyway, so leave
+        * the value alone.
+        */
+       if (IsClassInt (Type)) {
+
+           /* Get the current and new size of the value */
+           unsigned OldSize = SizeOf (lval->e_tptr);
+           unsigned NewSize = SizeOf (Type);
+           unsigned OldBits = OldSize * 8;
+           unsigned NewBits = NewSize * 8;
 
-    /* Do the actual cast. Special handling for void casts */
-    if (!IsTypeVoid (Type)) {
-       /* Mark the lhs as const to avoid a manipulation of TOS */
-        g_typecast (TypeOf (Type) | CF_CONST, rflags);
+           /* Check if the new datatype will have a smaller range */
+           if (NewSize < OldSize) {
+
+               /* Cut the value to the new size */
+               lval->e_const &= (0xFFFFFFFFUL >> (32 - NewBits));
+
+               /* If the new value is signed, sign extend the value */
+               if (!IsSignUnsigned (Type)) {
+                   lval->e_const |= ((~0L) << NewBits);
+               }
+
+           } else if (NewSize > OldSize) {
+
+               /* Sign extend the value if needed */
+               if (!IsSignUnsigned (Type) && !IsSignUnsigned (lval->e_tptr)) {
+                   if (lval->e_const & (0x01UL << (OldBits-1))) {
+                       lval->e_const |= ((~0L) << OldBits);
+                   }
+               }
+           }
+       }
+
+    } else {
+
+       /* Not a constant. Be sure to ignore casts to void */
+       if (!IsTypeVoid (Type)) {
+
+           /* If the size does not change, leave the value alone. Otherwise,
+            * we have to load the value into the primary and generate code to
+            * cast teh value in the primary register.
+            */
+           if (SizeOf (Type) != SizeOf (lval->e_tptr)) {
+
+               /* Load the value into the primary */
+               exprhs (CF_NONE, k, lval);
+
+               /* Mark the lhs as const to avoid a manipulation of TOS */
+               g_typecast (TypeOf (Type) | CF_CONST, TypeOf (lval->e_tptr));
+
+               /* Value is now in primary */
+               lval->e_flags = E_MEXPR;
+                       k = 0;
+           }
+       }
     }
 
-    /* Use the new type */
+    /* In any case, use the new type */
     lval->e_tptr = TypeDup (Type);
 
     /* Done */
@@ -2816,7 +2865,7 @@ int hie0 (struct expent *lval)
     k = hie1 (lval);
     while (curtok == TOK_COMMA) {
        NextToken ();
-       k = hie1 (lval);
+       k = hie1 (lval);
     }
     return k;
 }
@@ -2835,10 +2884,10 @@ int evalexpr (unsigned flags, int (*f) (struct expent*), struct expent* lval)
     /* Evaluate */
     k = f (lval);
     if (k == 0 && lval->e_flags == E_MCONST) {
-       /* Constant expression */
-       return 0;
+       /* Constant expression */
+       return 0;
     } else {
-       /* Not constant, load into the primary */
+       /* Not constant, load into the primary */
         exprhs (flags, k, lval);
        return 1;
     }
index d0ba1f073cd04664703d3902a4eca64bfe7c0a90..35e6656db50de78a6e8979a4dce5571d83508513 100644 (file)
 #  include <unistd.h>
 #endif
 
-#include "../common/xmalloc.h"
-
+/* common */
+#include "xmalloc.h"
+         
+/* cc65 */
 #include "incpath.h"