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:
cuz 2000-10-10 20:40:36 +00:00
parent 72f0cd6368
commit 2bd62669ce
3 changed files with 73 additions and 22 deletions

View 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 */

View file

@ -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;
/* 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);
}
/* Do the actual cast. Special handling for void casts */
} 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, rflags);
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 */

View file

@ -43,8 +43,10 @@
# include <unistd.h>
#endif
#include "../common/xmalloc.h"
/* common */
#include "xmalloc.h"
/* cc65 */
#include "incpath.h"