X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=src%2Fcc65%2Ftypeconv.c;h=ecde7349fbaac217d810ac5094d9f50f434dbb99;hb=c6ee5a841878ccdbf9ab85d3dafdd088648b93ba;hp=916afbfd69bfc28a32169d48e4f47cb0a5dc0b98;hpb=e20bda21b3425310edc24ae8fc7815d3fd1e3db2;p=cc65 diff --git a/src/cc65/typeconv.c b/src/cc65/typeconv.c index 916afbfd6..ecde7349f 100644 --- a/src/cc65/typeconv.c +++ b/src/cc65/typeconv.c @@ -6,8 +6,8 @@ /* */ /* */ /* */ -/* (C) 2002-2003 Ullrich von Bassewitz */ -/* Römerstrasse 52 */ +/* (C) 2002-2008 Ullrich von Bassewitz */ +/* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ @@ -33,12 +33,16 @@ +/* common */ +#include "shift.h" + /* cc65 */ #include "codegen.h" #include "datatype.h" #include "declare.h" #include "error.h" #include "expr.h" +#include "loadexpr.h" #include "scanner.h" #include "typecmp.h" #include "typeconv.h" @@ -51,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 int DoConversion (ExprDesc* Expr, int k, 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; @@ -80,7 +70,7 @@ static int DoConversion (ExprDesc* Expr, int k, type* NewType) * conversion void -> void. */ if (IsTypeVoid (NewType)) { - k = 0; /* Never an lvalue */ + ED_MakeRVal (Expr); /* Never an lvalue */ goto ExitPoint; } @@ -97,7 +87,7 @@ static int DoConversion (ExprDesc* Expr, int k, type* NewType) NewSize = CheckedSizeOf (NewType); /* lvalue? */ - if (k != 0) { + if (ED_IsLVal (Expr)) { /* We have an lvalue. If the new size is smaller than the new one, * we don't need to do anything. The compiler will generate code @@ -109,170 +99,183 @@ static int DoConversion (ExprDesc* Expr, int k, type* NewType) */ if (NewSize > OldSize) { /* Load the value into the primary */ - exprhs (CF_NONE, k, 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 */ - Expr->Flags = E_MEXPR; - k = 0; + /* Value is now in primary and an rvalue */ + ED_MakeRValExpr (Expr); } - } else { + } else if (ED_IsLocAbs (Expr)) { - /* We have an rvalue. Check for a constant. */ - if (Expr->Flags == E_MCONST) { - - /* 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))) { - Expr->ConstVal |= ((~0L) << 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 */ - exprhs (CF_NONE, k, 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 in primary */ - Expr->Flags = E_MEXPR; - k = 0; - } + /* Value is now a rvalue in the primary */ + ED_MakeRValExpr (Expr); } } ExitPoint: /* The expression has always the new type */ ReplaceType (Expr, NewType); - - /* Done */ - return k; } -int TypeConversion (ExprDesc* Expr, int k, 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)) { - /* If one of the sides are of type void, output a more apropriate - * error message. - */ + /* If one of the sides are of type void, output a more apropriate + * error message. + */ Error ("Illegal type"); - return k; } - /* Handle conversions to int 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"); } - /* Do a conversion regardless of errors and return the result. */ - return DoConversion (Expr, k, NewType); - } + } 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)) { + + /* Convert array to pointer */ + if (IsTypeArray (Expr->Type)) { + Expr->Type = ArrayToPtr (Expr->Type); + } - /* Handle conversions to pointer type */ - if (IsClassPtr (NewType)) { - if (IsClassPtr (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"); + } - /* Do the conversion even in case of errors */ - return DoConversion (Expr, k, NewType); + } else { + + /* Invalid automatic conversion */ + Error ("Incompatible types"); } - /* Invalid automatic conversion */ - Error ("Incompatible types"); - return DoConversion (Expr, k, NewType); + /* Do the actual conversion */ + DoConversion (Expr, NewType); } -int TypeCast (ExprDesc* Expr) -/* Handle an explicit cast. The function returns true if the resulting - * expression is an lvalue and false if not. - */ +void TypeCast (ExprDesc* Expr) +/* Handle an explicit cast. */ { - int k; - type NewType[MAXTYPELEN]; + Type NewType[MAXTYPELEN]; /* Skip the left paren */ NextToken (); @@ -284,14 +287,16 @@ int TypeCast (ExprDesc* Expr) ConsumeRParen (); /* Read the expression we have to cast */ - k = hie10 (Expr); + hie10 (Expr); /* Convert functions and arrays to "pointer to" object */ - DoPtrConversions (Expr); + Expr->Type = PtrConversion (Expr->Type); - /* Convert the value and return the result. */ - return DoConversion (Expr, k, NewType); + /* Convert the value. */ + DoConversion (Expr, NewType); } + +