Fixed type conversion problems

git-svn-id: svn://svn.cc65.org/cc65/trunk@2371 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
cuz
2003-08-19 20:31:10 +00:00
parent 7596da75f0
commit e20bda21b3
2 changed files with 68 additions and 58 deletions

View File

@@ -426,29 +426,35 @@ void exprhs (unsigned flags, int k, ExprDesc* lval)
flags |= CF_TEST; flags |= CF_TEST;
lval->Test &= ~E_FORCETEST; lval->Test &= ~E_FORCETEST;
} }
if (f & E_MGLOBAL) { /* ref to globalvar */ if (f & E_MGLOBAL) {
/* Generate code */ /* Reference to a global variable */
flags |= GlobalModeFlags (f); flags |= GlobalModeFlags (f);
g_getstatic (flags, lval->Name, lval->ConstVal); g_getstatic (flags, lval->Name, lval->ConstVal);
} else if (f & E_MLOCAL) { } else if (f & E_MLOCAL) {
/* ref to localvar */ /* Reference to a local variable */
g_getlocal (flags, lval->ConstVal); g_getlocal (flags, lval->ConstVal);
} else if (f & E_MCONST) { } else if (f & E_MCONST) {
/* ref to absolute address */ /* Reference to an absolute address */
g_getstatic (flags | CF_ABSOLUTE, lval->ConstVal, 0); g_getstatic (flags | CF_ABSOLUTE, lval->ConstVal, 0);
} else if (f == E_MEOFFS) { } else if (f == E_MEOFFS) {
/* Reference to address in primary with offset in lval */
g_getind (flags, lval->ConstVal); g_getind (flags, lval->ConstVal);
} else if (f != E_MREG) { } else if (f != E_MREG) {
/* Reference with address in primary */
g_getind (flags, 0); g_getind (flags, 0);
} }
} else if (f == E_MEOFFS) { } else {
/* reference not storable */ /* An rvalue */
flags |= TypeOf (lval->Type); if (f == E_MEOFFS) {
g_inc (flags | CF_CONST, lval->ConstVal); /* reference not storable */
} else if ((f & E_MEXPR) == 0) { flags |= TypeOf (lval->Type);
/* Constant of some sort, load it into the primary */ g_inc (flags | CF_CONST, lval->ConstVal);
LoadConstant (flags, lval); } else if ((f & E_MEXPR) == 0) {
/* Constant of some sort, load it into the primary */
LoadConstant (flags, lval);
}
} }
/* Are we testing this value? */ /* Are we testing this value? */
if (lval->Test & E_FORCETEST) { if (lval->Test & E_FORCETEST) {
/* Yes, force a test */ /* Yes, force a test */
@@ -2579,33 +2585,32 @@ static int hieOr (ExprDesc *lval)
static int hieQuest (ExprDesc *lval) static int hieQuest (ExprDesc *lval)
/* Parse "lvalue ? exp : exp" */ /* Parse "lvalue ? exp : exp" */
{ {
int k; int k1, k2, k3;
int labf; int labf;
int labt; int labt;
ExprDesc lval2; /* Expression 2 */ ExprDesc lval2; /* Expression 2 */
ExprDesc lval3; /* Expression 3 */ ExprDesc lval3; /* Expression 3 */
type* type2; /* Type of expression 2 */ type* rtype; /* Type of result */
type* type3; /* Type of expression 3 */
type* rtype; /* Type of result */
k = Preprocessing? hieOrPP (lval) : hieOr (lval); k1 = Preprocessing? hieOrPP (lval) : hieOr (lval);
if (CurTok.Tok == TOK_QUEST) { if (CurTok.Tok == TOK_QUEST) {
NextToken (); NextToken ();
if ((lval->Test & E_CC) == 0) { if ((lval->Test & E_CC) == 0) {
/* Condition codes not set, force a test */ /* Condition codes not set, force a test */
lval->Test |= E_FORCETEST; lval->Test |= E_FORCETEST;
} }
exprhs (CF_NONE, k, lval); exprhs (CF_NONE, k1, lval);
labf = GetLocalLabel (); labf = GetLocalLabel ();
g_falsejump (CF_NONE, labf); g_falsejump (CF_NONE, labf);
/* Parse second expression */ /* Parse second expression */
k = expr (hie1, &lval2); k2 = expr (hie1, &lval2);
type2 = lval2.Type;
if (!IsTypeVoid (lval2.Type)) { if (!IsTypeVoid (lval2.Type)) {
/* Load it into the primary */ /* Load it into the primary */
exprhs (CF_NONE, k, &lval2); exprhs (CF_NONE, k2, &lval2);
lval2.Flags = E_MEXPR;
k2 = 0;
} }
labt = GetLocalLabel (); labt = GetLocalLabel ();
ConsumeColon (); ConsumeColon ();
@@ -2613,11 +2618,12 @@ static int hieQuest (ExprDesc *lval)
/* Parse the third expression */ /* Parse the third expression */
g_defcodelabel (labf); g_defcodelabel (labf);
k = expr (hie1, &lval3); k3 = expr (hie1, &lval3);
type3 = lval3.Type;
if (!IsTypeVoid (lval3.Type)) { if (!IsTypeVoid (lval3.Type)) {
/* Load it into the primary */ /* Load it into the primary */
exprhs (CF_NONE, k, &lval3); exprhs (CF_NONE, k3, &lval3);
lval3.Flags = E_MEXPR;
k3 = 0;
} }
/* Check if any conversions are needed, if so, do them. /* Check if any conversions are needed, if so, do them.
@@ -2633,62 +2639,62 @@ static int hieQuest (ExprDesc *lval)
* type void. * type void.
* - all other cases are flagged by an error. * - all other cases are flagged by an error.
*/ */
if (IsClassInt (type2) && IsClassInt (type3)) { if (IsClassInt (lval2.Type) && IsClassInt (lval3.Type)) {
/* Get common type */ /* Get common type */
rtype = promoteint (type2, type3); rtype = promoteint (lval2.Type, lval3.Type);
/* Convert the third expression to this type if needed */ /* Convert the third expression to this type if needed */
g_typecast (TypeOf (rtype), TypeOf (type3)); TypeConversion (&lval3, k3, rtype);
/* Setup a new label so that the expr3 code will jump around /* Setup a new label so that the expr3 code will jump around
* the type cast code for expr2. * the type cast code for expr2.
*/ */
labf = GetLocalLabel (); /* Get new label */ labf = GetLocalLabel (); /* Get new label */
g_jump (labf); /* Jump around code */ g_jump (labf); /* Jump around code */
/* The jump for expr2 goes here */ /* The jump for expr2 goes here */
g_defcodelabel (labt); g_defcodelabel (labt);
/* Create the typecast code for expr2 */ /* Create the typecast code for expr2 */
g_typecast (TypeOf (rtype), TypeOf (type2)); TypeConversion (&lval2, k2, rtype);
/* Jump here around the typecase code. */ /* Jump here around the typecase code. */
g_defcodelabel (labf); g_defcodelabel (labf);
labt = 0; /* Mark other label as invalid */ labt = 0; /* Mark other label as invalid */
} else if (IsClassPtr (type2) && IsClassPtr (type3)) { } else if (IsClassPtr (lval2.Type) && IsClassPtr (lval3.Type)) {
/* Must point to same type */ /* Must point to same type */
if (TypeCmp (Indirect (type2), Indirect (type3)) < TC_EQUAL) { if (TypeCmp (Indirect (lval2.Type), Indirect (lval3.Type)) < TC_EQUAL) {
Error ("Incompatible pointer types"); Error ("Incompatible pointer types");
} }
/* Result has the common type */ /* Result has the common type */
rtype = lval2.Type; rtype = lval2.Type;
} else if (IsClassPtr (type2) && IsNullPtr (&lval3)) { } else if (IsClassPtr (lval2.Type) && IsNullPtr (&lval3)) {
/* Result type is pointer, no cast needed */ /* Result type is pointer, no cast needed */
rtype = lval2.Type; rtype = lval2.Type;
} else if (IsNullPtr (&lval2) && IsClassPtr (type3)) { } else if (IsNullPtr (&lval2) && IsClassPtr (lval3.Type)) {
/* Result type is pointer, no cast needed */ /* Result type is pointer, no cast needed */
rtype = lval3.Type; rtype = lval3.Type;
} else if (IsTypeVoid (type2) && IsTypeVoid (type3)) { } else if (IsTypeVoid (lval2.Type) && IsTypeVoid (lval3.Type)) {
/* Result type is void */ /* Result type is void */
rtype = lval3.Type; rtype = lval3.Type;
} else { } else {
Error ("Incompatible types"); Error ("Incompatible types");
rtype = lval2.Type; /* Doesn't matter here */ rtype = lval2.Type; /* Doesn't matter here */
} }
/* If we don't have the label defined until now, do it */ /* If we don't have the label defined until now, do it */
if (labt) { if (labt) {
g_defcodelabel (labt); g_defcodelabel (labt);
} }
/* Setup the target expression */ /* Setup the target expression */
lval->Flags = E_MEXPR; lval->Flags = E_MEXPR;
lval->Type = rtype; lval->Type = rtype;
k = 0; k1 = 0;
} }
return k; return k1;
} }
@@ -2780,7 +2786,7 @@ static void addsubeq (const GenDesc* Gen, ExprDesc *lval, int k)
ExprDesc lval2; ExprDesc lval2;
unsigned lflags; unsigned lflags;
unsigned rflags; unsigned rflags;
int MustScale; int MustScale;
/* We must have an lvalue */ /* We must have an lvalue */
@@ -2809,16 +2815,20 @@ static void addsubeq (const GenDesc* Gen, ExprDesc *lval, int k)
rflags = 0; rflags = 0;
/* Evaluate the rhs */ /* Evaluate the rhs */
if (evalexpr (CF_NONE, hie1, &lval2) == 0) { k = hie1 (&lval2);
if (k == 0 && lval2.Flags == E_MCONST) {
/* The resulting value is a constant. */ /* The resulting value is a constant. */
if (MustScale) { if (MustScale) {
/* lhs is a pointer, scale rhs */ /* lhs is a pointer, scale rhs */
lval2.ConstVal *= CheckedSizeOf (lval->Type+1); lval2.ConstVal *= CheckedSizeOf (lval->Type+1);
} }
rflags |= CF_CONST; rflags |= CF_CONST;
lflags |= CF_CONST; lflags |= CF_CONST;
} else { } else {
/* rhs is not constant and already in the primary register */ /* Not constant, load into the primary */
exprhs (CF_NONE, k, &lval2);
lval2.Flags = E_MEXPR;
k = 0;
if (MustScale) { if (MustScale) {
/* lhs is a pointer, scale rhs */ /* lhs is a pointer, scale rhs */
g_scale (TypeOf (lval2.Type), CheckedSizeOf (lval->Type+1)); g_scale (TypeOf (lval2.Type), CheckedSizeOf (lval->Type+1));
@@ -2829,8 +2839,8 @@ static void addsubeq (const GenDesc* Gen, ExprDesc *lval, int k)
lflags |= TypeOf (lval->Type) | CF_FORCECHAR; lflags |= TypeOf (lval->Type) | CF_FORCECHAR;
rflags |= TypeOf (lval2.Type); rflags |= TypeOf (lval2.Type);
/* Cast the rhs to the type of the lhs */ /* Convert the type of the lhs to that of the rhs */
g_typecast (lflags, rflags); TypeConversion (&lval2, k, lval->Type);
/* Output apropriate code */ /* Output apropriate code */
if (lval->Flags & E_MGLOBAL) { if (lval->Flags & E_MGLOBAL) {

View File

@@ -112,7 +112,7 @@ static int DoConversion (ExprDesc* Expr, int k, type* NewType)
exprhs (CF_NONE, k, Expr); exprhs (CF_NONE, k, Expr);
/* Emit typecast code */ /* Emit typecast code */
g_typecast (TypeOf (OldType), TypeOf (NewType)); g_typecast (TypeOf (NewType), TypeOf (OldType));
/* Value is now in primary */ /* Value is now in primary */
Expr->Flags = E_MEXPR; Expr->Flags = E_MEXPR;
@@ -161,7 +161,7 @@ static int DoConversion (ExprDesc* Expr, int k, type* NewType)
exprhs (CF_NONE, k, Expr); exprhs (CF_NONE, k, Expr);
/* Emit typecast code. */ /* Emit typecast code. */
g_typecast (TypeOf (OldType), TypeOf (NewType) | CF_FORCECHAR); g_typecast (TypeOf (NewType) | CF_FORCECHAR, TypeOf (OldType));
/* Value is now in primary */ /* Value is now in primary */
Expr->Flags = E_MEXPR; Expr->Flags = E_MEXPR;