X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;ds=sidebyside;f=src%2Fcc65%2Ftypeconv.c;h=ecde7349fbaac217d810ac5094d9f50f434dbb99;hb=c6ee5a841878ccdbf9ab85d3dafdd088648b93ba;hp=b3fbedb48e98bdbd9421314ff5394d4dd045887a;hpb=878e4f13524e91fbcdc8c97cc461724231339483;p=cc65 diff --git a/src/cc65/typeconv.c b/src/cc65/typeconv.c index b3fbedb48..ecde7349f 100644 --- a/src/cc65/typeconv.c +++ b/src/cc65/typeconv.c @@ -6,8 +6,8 @@ /* */ /* */ /* */ -/* (C) 2002-2004 Ullrich von Bassewitz */ -/* Römerstrasse 52 */ +/* (C) 2002-2008 Ullrich von Bassewitz */ +/* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ @@ -42,6 +42,7 @@ #include "declare.h" #include "error.h" #include "expr.h" +#include "loadexpr.h" #include "scanner.h" #include "typecmp.h" #include "typeconv.h" @@ -54,24 +55,10 @@ -static void DoPtrConversions (ExprDesc* Expr) -/* If the expression is a function, convert it to pointer to function. - * If the expression is an array, convert it to pointer to first element. - */ -{ - if (IsTypeFunc (Expr->Type)) { - Expr->Type = PointerTo (Expr->Type); - } else if (IsTypeArray (Expr->Type)) { - Expr->Type = ArrayToPtr (Expr->Type); - } -} - - - -static void DoConversion (ExprDesc* Expr, type* NewType) +static void DoConversion (ExprDesc* Expr, const Type* NewType) /* Emit code to convert the given expression to a new type. */ { - type* OldType; + Type* OldType; unsigned OldSize; unsigned NewSize; @@ -112,63 +99,59 @@ static void DoConversion (ExprDesc* Expr, type* NewType) */ if (NewSize > OldSize) { /* Load the value into the primary */ - ExprLoad (CF_NONE, Expr); + LoadExpr (CF_NONE, Expr); /* Emit typecast code */ - g_typecast (TypeOf (NewType), TypeOf (OldType)); + g_typecast (TypeOf (NewType), TypeOf (OldType) | CF_FORCECHAR); /* Value is now in primary and an rvalue */ - Expr->Flags = E_MEXPR | E_RVAL; + ED_MakeRValExpr (Expr); } - } else { - - /* We have an rvalue. Check for a constant. */ - if (Expr->Flags == E_MCONST) { + } else if (ED_IsLocAbs (Expr)) { - /* A cast of a constant to an integer. Be sure to handle sign - * extension correctly. - */ + /* A cast of a constant numeric value to another type. Be sure + * to handle sign extension correctly. + */ - /* Get the current and new size of the value */ - unsigned OldBits = OldSize * 8; - unsigned NewBits = NewSize * 8; + /* Get the current and new size of the value */ + unsigned OldBits = OldSize * 8; + unsigned NewBits = NewSize * 8; - /* Check if the new datatype will have a smaller range. If it - * has a larger range, things are ok, since the value is - * internally already represented by a long. - */ - if (NewBits <= OldBits) { + /* Check if the new datatype will have a smaller range. If it + * has a larger range, things are ok, since the value is + * internally already represented by a long. + */ + if (NewBits <= OldBits) { - /* Cut the value to the new size */ - Expr->ConstVal &= (0xFFFFFFFFUL >> (32 - NewBits)); + /* Cut the value to the new size */ + Expr->IVal &= (0xFFFFFFFFUL >> (32 - NewBits)); - /* If the new type is signed, sign extend the value */ - if (!IsSignUnsigned (NewType)) { - if (Expr->ConstVal & (0x01UL << (NewBits-1))) { - /* Beware: Use the safe shift routine here. */ - Expr->ConstVal |= shl_l (~0UL, NewBits); - } + /* If the new type is signed, sign extend the value */ + if (IsSignSigned (NewType)) { + if (Expr->IVal & (0x01UL << (NewBits-1))) { + /* Beware: Use the safe shift routine here. */ + Expr->IVal |= shl_l (~0UL, NewBits); } } + } - } else { + } else { - /* The value is not a constant. If the sizes of the types are - * not equal, add conversion code. Be sure to convert chars - * correctly. - */ - if (OldSize != NewSize) { + /* The value is not a constant. If the sizes of the types are + * not equal, add conversion code. Be sure to convert chars + * correctly. + */ + if (OldSize != NewSize) { - /* Load the value into the primary */ - ExprLoad (CF_NONE, Expr); + /* Load the value into the primary */ + LoadExpr (CF_NONE, Expr); - /* Emit typecast code. */ - g_typecast (TypeOf (NewType) | CF_FORCECHAR, TypeOf (OldType)); + /* Emit typecast code. */ + g_typecast (TypeOf (NewType), TypeOf (OldType) | CF_FORCECHAR); - /* Value is now a rvalie in the primary */ - Expr->Flags = E_MEXPR | E_RVAL; - } + /* Value is now a rvalue in the primary */ + ED_MakeRValExpr (Expr); } } @@ -179,16 +162,21 @@ ExitPoint: -void TypeConversion (ExprDesc* Expr, type* NewType) +void TypeConversion (ExprDesc* Expr, Type* NewType) /* Do an automatic conversion of the given expression to the new type. Output * warnings or errors where this automatic conversion is suspicious or * impossible. */ { - /* Get the type of the right hand side. Treat function types as - * pointer-to-function - */ - DoPtrConversions (Expr); +#if 0 + /* Debugging */ + printf ("Expr:\n=======================================\n"); + PrintExprDesc (stdout, Expr); + printf ("Type:\n=======================================\n"); + PrintType (stdout, NewType); + printf ("\n"); + PrintRawType (stdout, NewType); +#endif /* First, do some type checking */ if (IsTypeVoid (NewType) || IsTypeVoid (Expr->Type)) { @@ -198,58 +186,78 @@ void TypeConversion (ExprDesc* Expr, type* NewType) Error ("Illegal type"); } + /* If Expr is a function, convert it to pointer to function */ + if (IsTypeFunc(Expr->Type)) { + Expr->Type = PointerTo (Expr->Type); + } + + /* If both types are equal, no conversion is needed */ + if (TypeCmp (Expr->Type, NewType) >= TC_EQUAL) { + /* We're already done */ + return; + } + /* Check for conversion problems */ if (IsClassInt (NewType)) { /* Handle conversions to int type */ if (IsClassPtr (Expr->Type)) { - /* Pointer -> int conversion */ + /* Pointer -> int conversion. Convert array to pointer */ + if (IsTypeArray (Expr->Type)) { + Expr->Type = ArrayToPtr (Expr->Type); + } Warning ("Converting pointer to integer without a cast"); - } else if (!IsClassInt (Expr->Type)) { + } else if (!IsClassInt (Expr->Type) && !IsClassFloat (Expr->Type)) { Error ("Incompatible types"); } + } else if (IsClassFloat (NewType)) { + + if (!IsClassFloat (Expr->Type) && !IsClassInt (Expr->Type)) { + Error ("Incompatible types"); + } + } else if (IsClassPtr (NewType)) { /* Handle conversions to pointer type */ - if (IsClassPtr (Expr->Type)) { + if (IsClassPtr (Expr->Type)) { + + /* Convert array to pointer */ + if (IsTypeArray (Expr->Type)) { + Expr->Type = ArrayToPtr (Expr->Type); + } + /* Pointer to pointer assignment is valid, if: * - both point to the same types, or * - the rhs pointer is a void pointer, or - * - the lhs pointer is a void pointer. + * - the lhs pointer is a void pointer. */ - if (!IsTypeVoid (Indirect (NewType)) && !IsTypeVoid (Indirect (Expr->Type))) { - /* Compare the types */ - switch (TypeCmp (NewType, Expr->Type)) { - - case TC_INCOMPATIBLE: - Error ("Incompatible pointer types"); - break; - - case TC_QUAL_DIFF: - Error ("Pointer types differ in type qualifiers"); - break; - - default: - /* Ok */ - break; - } - } + if (!IsTypeVoid (Indirect (NewType)) && !IsTypeVoid (Indirect (Expr->Type))) { + /* Compare the types */ + switch (TypeCmp (NewType, Expr->Type)) { + + case TC_INCOMPATIBLE: + Error ("Incompatible pointer types"); + break; + + case TC_QUAL_DIFF: + Error ("Pointer types differ in type qualifiers"); + break; + + default: + /* Ok */ + break; + } + } + } else if (IsClassInt (Expr->Type)) { /* Int to pointer assignment is valid only for constant zero */ - if (Expr->Flags != E_MCONST || Expr->ConstVal != 0) { + if (!ED_IsConstAbsInt (Expr) || Expr->IVal != 0) { Warning ("Converting integer to pointer without a cast"); } - } else if (IsTypeFuncPtr (NewType) && IsTypeFunc(Expr->Type)) { - /* Assignment of function to function pointer is allowed, provided - * that both functions have the same parameter list. - */ - if (TypeCmp (Indirect (NewType), Expr->Type) < TC_EQUAL) { - Error ("Incompatible types"); - } } else { - Error ("Incompatible types"); - } + Error ("Incompatible types"); + } } else { @@ -265,11 +273,9 @@ void TypeConversion (ExprDesc* Expr, type* NewType) void TypeCast (ExprDesc* Expr) -/* Handle an explicit cast. The function returns true if the resulting - * expression is an lvalue and false if not. - */ +/* Handle an explicit cast. */ { - type NewType[MAXTYPELEN]; + Type NewType[MAXTYPELEN]; /* Skip the left paren */ NextToken (); @@ -284,7 +290,7 @@ void TypeCast (ExprDesc* Expr) hie10 (Expr); /* Convert functions and arrays to "pointer to" object */ - DoPtrConversions (Expr); + Expr->Type = PtrConversion (Expr->Type); /* Convert the value. */ DoConversion (Expr, NewType); @@ -293,3 +299,4 @@ void TypeCast (ExprDesc* Expr) +