Fixed a bug in explicit type casts
git-svn-id: svn://svn.cc65.org/cc65/trunk@354 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
parent
72f0cd6368
commit
2bd62669ce
3 changed files with 73 additions and 22 deletions
|
@ -659,7 +659,7 @@ static void ParseAnsiParamList (FuncDesc* F)
|
||||||
Spec.StorageClass &= ~SC_DEF;
|
Spec.StorageClass &= ~SC_DEF;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Parse an attribute */
|
/* Parse an attribute ### */
|
||||||
ParseAttribute (&Decl, &Attr);
|
ParseAttribute (&Decl, &Attr);
|
||||||
|
|
||||||
/* Create a symbol table entry */
|
/* Create a symbol table entry */
|
||||||
|
|
|
@ -1010,7 +1010,7 @@ static int arrayref (int k, struct expent* lval)
|
||||||
* if necessary and the second one is a pointer).
|
* if necessary and the second one is a pointer).
|
||||||
* Note: If ConstBaseAddr is true, we don't have a value on
|
* Note: If ConstBaseAddr is true, we don't have a value on
|
||||||
* stack, so to "swap" both, just push the subscript.
|
* stack, so to "swap" both, just push the subscript.
|
||||||
*/
|
*/
|
||||||
if (ConstBaseAddr) {
|
if (ConstBaseAddr) {
|
||||||
g_push (CF_INT, 0);
|
g_push (CF_INT, 0);
|
||||||
exprhs (CF_NONE, k, lval);
|
exprhs (CF_NONE, k, lval);
|
||||||
|
@ -1047,7 +1047,7 @@ static int arrayref (int k, struct expent* lval)
|
||||||
rflags = lval2.e_flags & ~E_MCTYPE;
|
rflags = lval2.e_flags & ~E_MCTYPE;
|
||||||
ConstSubAddr = (rflags == E_MCONST) || /* Constant numeric address */
|
ConstSubAddr = (rflags == E_MCONST) || /* Constant numeric address */
|
||||||
(rflags & E_MGLOBAL) != 0 || /* Static array, or ... */
|
(rflags & E_MGLOBAL) != 0 || /* Static array, or ... */
|
||||||
rflags == E_MLOCAL; /* Local array */
|
rflags == E_MLOCAL; /* Local array */
|
||||||
|
|
||||||
if (ConstSubAddr && SizeOf (lval->e_tptr) == 1) {
|
if (ConstSubAddr && SizeOf (lval->e_tptr) == 1) {
|
||||||
|
|
||||||
|
@ -1055,7 +1055,7 @@ static int arrayref (int k, struct expent* lval)
|
||||||
|
|
||||||
/* Reverse the order of evaluation */
|
/* Reverse the order of evaluation */
|
||||||
unsigned flags = (SizeOf (lval2.e_tptr) == 1)? CF_CHAR : CF_INT;
|
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
|
/* Get a pointer to the array into the primary. We have changed
|
||||||
* e_tptr above but we need the original type to load the
|
* e_tptr above but we need the original type to load the
|
||||||
|
@ -1411,7 +1411,6 @@ static int typecast (struct expent* lval)
|
||||||
{
|
{
|
||||||
int k;
|
int k;
|
||||||
type Type[MAXTYPELEN];
|
type Type[MAXTYPELEN];
|
||||||
unsigned rflags;
|
|
||||||
|
|
||||||
/* Skip the left paren */
|
/* Skip the left paren */
|
||||||
NextToken ();
|
NextToken ();
|
||||||
|
@ -1425,19 +1424,69 @@ static int typecast (struct expent* lval)
|
||||||
/* Read the expression we have to cast */
|
/* Read the expression we have to cast */
|
||||||
k = hie10 (lval);
|
k = hie10 (lval);
|
||||||
|
|
||||||
/* Get the type of the expression and honor constant values */
|
/* Check for a const expression */
|
||||||
rflags = TypeOf (lval->e_tptr);
|
if (k == 0 && lval->e_flags == E_MCONST) {
|
||||||
if (lval->e_flags & E_MCONST) {
|
|
||||||
rflags |= CF_CONST;
|
/* 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;
|
||||||
|
|
||||||
|
/* 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Do the actual cast. Special handling for void casts */
|
/* In any case, use the new type */
|
||||||
if (!IsTypeVoid (Type)) {
|
|
||||||
/* Mark the lhs as const to avoid a manipulation of TOS */
|
|
||||||
g_typecast (TypeOf (Type) | CF_CONST, rflags);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Use the new type */
|
|
||||||
lval->e_tptr = TypeDup (Type);
|
lval->e_tptr = TypeDup (Type);
|
||||||
|
|
||||||
/* Done */
|
/* Done */
|
||||||
|
@ -2816,7 +2865,7 @@ int hie0 (struct expent *lval)
|
||||||
k = hie1 (lval);
|
k = hie1 (lval);
|
||||||
while (curtok == TOK_COMMA) {
|
while (curtok == TOK_COMMA) {
|
||||||
NextToken ();
|
NextToken ();
|
||||||
k = hie1 (lval);
|
k = hie1 (lval);
|
||||||
}
|
}
|
||||||
return k;
|
return k;
|
||||||
}
|
}
|
||||||
|
@ -2835,10 +2884,10 @@ int evalexpr (unsigned flags, int (*f) (struct expent*), struct expent* lval)
|
||||||
/* Evaluate */
|
/* Evaluate */
|
||||||
k = f (lval);
|
k = f (lval);
|
||||||
if (k == 0 && lval->e_flags == E_MCONST) {
|
if (k == 0 && lval->e_flags == E_MCONST) {
|
||||||
/* Constant expression */
|
/* Constant expression */
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
/* Not constant, load into the primary */
|
/* Not constant, load into the primary */
|
||||||
exprhs (flags, k, lval);
|
exprhs (flags, k, lval);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,8 +43,10 @@
|
||||||
# include <unistd.h>
|
# include <unistd.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "../common/xmalloc.h"
|
/* common */
|
||||||
|
#include "xmalloc.h"
|
||||||
|
|
||||||
|
/* cc65 */
|
||||||
#include "incpath.h"
|
#include "incpath.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue