From aef8789873bd008d42aa50330ca98488fad91b31 Mon Sep 17 00:00:00 2001
From: cuz <cuz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Date: Wed, 20 Aug 2003 08:32:07 +0000
Subject: [PATCH] Fixed several type conversion issues

git-svn-id: svn://svn.cc65.org/cc65/trunk@2380 b7a2c559-68d2-44c3-8de9-860c34a00d81
---
 src/cc65/expr.c | 138 +++++++++++++++++++++++++-----------------------
 1 file changed, 73 insertions(+), 65 deletions(-)

diff --git a/src/cc65/expr.c b/src/cc65/expr.c
index bf9ccb5b0..02b5d78e2 100644
--- a/src/cc65/expr.c
+++ b/src/cc65/expr.c
@@ -413,54 +413,54 @@ void CheckBoolExpr (ExprDesc* lval)
 
 
 
-void exprhs (unsigned flags, int k, ExprDesc* lval)
+void exprhs (unsigned Flags, int k, ExprDesc* Expr)
 /* Put the result of an expression into the primary register */
 {
     int f;
 
-    f = lval->Flags;
+    f = Expr->Flags;
     if (k) {
        	/* Dereferenced lvalue */
-       	flags |= TypeOf (lval->Type);
-     	if (lval->Test & E_FORCETEST) {
-     	    flags |= CF_TEST;
-     	    lval->Test &= ~E_FORCETEST;
+       	Flags |= TypeOf (Expr->Type);
+     	if (Expr->Test & E_FORCETEST) {
+     	    Flags |= CF_TEST;
+     	    Expr->Test &= ~E_FORCETEST;
      	}
-       	if (f & E_MGLOBAL) {	
-	    /* Reference to a global variable */
-     	    flags |= GlobalModeFlags (f);
-       	    g_getstatic (flags, lval->Name, lval->ConstVal);
+       	if (f & E_MGLOBAL) {
+     	    /* Reference to a global variable */
+     	    Flags |= GlobalModeFlags (f);
+       	    g_getstatic (Flags, Expr->Name, Expr->ConstVal);
        	} else if (f & E_MLOCAL) {
      	    /* Reference to a local variable */
-       	    g_getlocal (flags, lval->ConstVal);
+       	    g_getlocal (Flags, Expr->ConstVal);
      	} else if (f & E_MCONST) {
      	    /* Reference to an absolute address */
-     	    g_getstatic (flags | CF_ABSOLUTE, lval->ConstVal, 0);
+     	    g_getstatic (Flags | CF_ABSOLUTE, Expr->ConstVal, 0);
      	} else if (f == E_MEOFFS) {
-	    /* Reference to address in primary with offset in lval */
-     	    g_getind (flags, lval->ConstVal);
+     	    /* Reference to address in primary with offset in Expr */
+     	    g_getind (Flags, Expr->ConstVal);
      	} else if (f != E_MREG) {
-	    /* Reference with address in primary */
-     	    g_getind (flags, 0);
+     	    /* Reference with address in primary */
+     	    g_getind (Flags, 0);
      	}
     } else {
-	/* An rvalue */
-	if (f == E_MEOFFS) {
-	    /* reference not storable */
-	    flags |= TypeOf (lval->Type);
-	    g_inc (flags | CF_CONST, lval->ConstVal);
-	} else if ((f & E_MEXPR) == 0) {
-	    /* Constant of some sort, load it into the primary */
-	    LoadConstant (flags, lval);
-	}
+     	/* An rvalue */
+     	if (f == E_MEOFFS) {
+     	    /* reference not storable */
+     	    Flags |= TypeOf (Expr->Type);
+     	    g_inc (Flags | CF_CONST, Expr->ConstVal);
+     	} else if ((f & E_MEXPR) == 0) {
+     	    /* Constant of some sort, load it into the primary */
+     	    LoadConstant (Flags, Expr);
+     	}
     }
 
     /* Are we testing this value? */
-    if (lval->Test & E_FORCETEST) {
+    if (Expr->Test & E_FORCETEST) {
         /* Yes, force a test */
-     	flags |= TypeOf (lval->Type);
-       	g_test (flags);
-       	lval->Test &= ~E_FORCETEST;
+     	Flags |= TypeOf (Expr->Type);
+       	g_test (Flags);
+       	Expr->Test &= ~E_FORCETEST;
     }
 }
 
@@ -2582,15 +2582,17 @@ static int hieOr (ExprDesc *lval)
 
 
 
-static int hieQuest (ExprDesc *lval)
-/* Parse "lvalue ? exp : exp" */
+static int hieQuest (ExprDesc* lval)
+/* Parse the ternary operator */
 {
-    int k1, k2, k3;
-    int labf;
-    int labt;
-    ExprDesc lval2;            	/* Expression 2 */
-    ExprDesc lval3;            	/* Expression 3 */
-    type* rtype;   	       	/* Type of result */
+    int         k1, k2, k3;
+    int         labf;
+    int         labt;
+    ExprDesc 	Expr2;          /* Expression 2 */
+    ExprDesc 	Expr3;          /* Expression 3 */
+    int         Expr2IsNULL;    /* Expression 2 is a NULL pointer */
+    int         Expr3IsNULL;    /* Expression 3 is a NULL pointer */
+    type* 	ResultType;     /* Type of result */
 
 
     k1 = Preprocessing? hieOrPP (lval) : hieOr (lval);
@@ -2604,25 +2606,33 @@ static int hieQuest (ExprDesc *lval)
     	labf = GetLocalLabel ();
     	g_falsejump (CF_NONE, labf);
 
-    	/* Parse second expression */
-        k2 = expr (hie1, &lval2);
-        if (!IsTypeVoid (lval2.Type)) {
+    	/* Parse second expression. Remember for later if it is a NULL pointer
+         * expression, then load it into the primary.
+         */
+        k2 = expr (hie1, &Expr2);
+        Expr2IsNULL = IsNullPtr (&Expr2);
+        if (!IsTypeVoid (Expr2.Type)) {
             /* Load it into the primary */
-            exprhs (CF_NONE, k2, &lval2);
-	    lval2.Flags = E_MEXPR;
+            exprhs (CF_NONE, k2, &Expr2);
+	    Expr2.Flags = E_MEXPR;
 	    k2 = 0;
         }
     	labt = GetLocalLabel ();
     	ConsumeColon ();
     	g_jump (labt);
 
-        /* Parse the third expression */
+        /* Jump here if the first expression was false */
     	g_defcodelabel (labf);
-        k3 = expr (hie1, &lval3);
-        if (!IsTypeVoid (lval3.Type)) {
+
+    	/* Parse second expression. Remember for later if it is a NULL pointer
+         * expression, then load it into the primary.
+         */
+        k3 = expr (hie1, &Expr3);
+        Expr3IsNULL = IsNullPtr (&Expr3);
+        if (!IsTypeVoid (Expr3.Type)) {
             /* Load it into the primary */
-            exprhs (CF_NONE, k3, &lval3);
-	    lval3.Flags = E_MEXPR;
+            exprhs (CF_NONE, k3, &Expr3);
+	    Expr3.Flags = E_MEXPR;
 	    k3 = 0;
         }
 
@@ -2639,13 +2649,13 @@ static int hieQuest (ExprDesc *lval)
          *     type void.
 	 *   - all other cases are flagged by an error.
 	 */
-	if (IsClassInt (lval2.Type) && IsClassInt (lval3.Type)) {
+	if (IsClassInt (Expr2.Type) && IsClassInt (Expr3.Type)) {
 
 	    /* Get common type */
-	    rtype = promoteint (lval2.Type, lval3.Type);
+	    ResultType = promoteint (Expr2.Type, Expr3.Type);
 
 	    /* Convert the third expression to this type if needed */
-	    TypeConversion (&lval3, k3, rtype);
+	    TypeConversion (&Expr3, k3, ResultType);
 
 	    /* Setup a new label so that the expr3 code will jump around
 	     * the type cast code for expr2.
@@ -2657,31 +2667,31 @@ static int hieQuest (ExprDesc *lval)
     	    g_defcodelabel (labt);
 
 	    /* Create the typecast code for expr2 */
-    	    TypeConversion (&lval2, k2, rtype);
+    	    TypeConversion (&Expr2, k2, ResultType);
 
 	    /* Jump here around the typecase code. */
 	    g_defcodelabel (labf);
 	    labt = 0;	       	/* Mark other label as invalid */
 
-	} else if (IsClassPtr (lval2.Type) && IsClassPtr (lval3.Type)) {
+	} else if (IsClassPtr (Expr2.Type) && IsClassPtr (Expr3.Type)) {
 	    /* Must point to same type */
-	    if (TypeCmp (Indirect (lval2.Type), Indirect (lval3.Type)) < TC_EQUAL) {
+	    if (TypeCmp (Indirect (Expr2.Type), Indirect (Expr3.Type)) < TC_EQUAL) {
 	      	Error ("Incompatible pointer types");
 	    }
 	    /* Result has the common type */
-	    rtype = lval2.Type;
-	} else if (IsClassPtr (lval2.Type) && IsNullPtr (&lval3)) {
+	    ResultType = Expr2.Type;
+	} else if (IsClassPtr (Expr2.Type) && Expr3IsNULL) {
 	    /* Result type is pointer, no cast needed */
-	    rtype = lval2.Type;
-	} else if (IsNullPtr (&lval2) && IsClassPtr (lval3.Type)) {
+	    ResultType = Expr2.Type;
+	} else if (Expr2IsNULL && IsClassPtr (Expr3.Type)) {
 	    /* Result type is pointer, no cast needed */
-	    rtype = lval3.Type;
-        } else if (IsTypeVoid (lval2.Type) && IsTypeVoid (lval3.Type)) {
+	    ResultType = Expr3.Type;
+        } else if (IsTypeVoid (Expr2.Type) && IsTypeVoid (Expr3.Type)) {
             /* Result type is void */
-            rtype = lval3.Type;
+            ResultType = Expr3.Type;
       	} else {
       	    Error ("Incompatible types");
-      	    rtype = lval2.Type;	 	/* Doesn't matter here */
+      	    ResultType = Expr2.Type;		/* Doesn't matter here */
       	}
 
       	/* If we don't have the label defined until now, do it */
@@ -2691,7 +2701,7 @@ static int hieQuest (ExprDesc *lval)
 
       	/* Setup the target expression */
        	lval->Flags = E_MEXPR;
-      	lval->Type = rtype;
+      	lval->Type  = ResultType;
       	k1 = 0;
     }
     return k1;
@@ -2827,8 +2837,6 @@ static void addsubeq (const GenDesc* Gen, ExprDesc *lval, int k)
     } else {
      	/* Not constant, load into the primary */
         exprhs (CF_NONE, k, &lval2);
-	lval2.Flags = E_MEXPR;
-	k = 0;
        	if (MustScale) {
      	    /* lhs is a pointer, scale rhs */
        	    g_scale (TypeOf (lval2.Type), CheckedSizeOf (lval->Type+1));
@@ -2840,7 +2848,7 @@ static void addsubeq (const GenDesc* Gen, ExprDesc *lval, int k)
     rflags |= TypeOf (lval2.Type);
 
     /* Convert the type of the lhs to that of the rhs */
-    TypeConversion (&lval2, k, lval->Type);
+    g_typecast (lflags, rflags);
 
     /* Output apropriate code */
     if (lval->Flags & E_MGLOBAL) {