/* common */
#include "check.h"
+#include "debugflag.h"
#include "xmalloc.h"
/* cc65 */
#include "scanner.h"
#include "stdfunc.h"
#include "symtab.h"
-#include "typecast.h"
#include "typecmp.h"
+#include "typeconv.h"
#include "expr.h"
-static int hie0 (ExprDesc *lval);
+int hie0 (ExprDesc *lval);
/* Parse comma operator. */
static int expr (int (*func) (ExprDesc*), ExprDesc *lval);
-unsigned assignadjust (type* lhst, ExprDesc* rhs)
-/* Adjust the type of the right hand expression so that it can be assigned to
- * the type on the left hand side. This function is used for assignment and
- * for converting parameters in a function call. It returns the code generator
- * flags for the operation. The type string of the right hand side will be
- * set to the type of the left hand side.
- */
-{
- /* Get the type of the right hand side. Treat function types as
- * pointer-to-function
- */
- type* rhst = rhs->Type;
- if (IsTypeFunc (rhst)) {
- rhst = PointerTo (rhst);
- }
-
- /* After calling this function, rhs will have the type of the lhs */
- rhs->Type = lhst;
-
- /* First, do some type checking */
- if (IsTypeVoid (lhst) || IsTypeVoid (rhst)) {
- /* If one of the sides are of type void, output a more apropriate
- * error message.
- */
- Error ("Illegal type");
- } else if (IsClassInt (lhst)) {
- if (IsClassPtr (rhst)) {
- /* Pointer -> int conversion */
- Warning ("Converting pointer to integer without a cast");
- } else if (!IsClassInt (rhst)) {
- Error ("Incompatible types");
- } else {
- /* Convert the rhs to the type of the lhs. */
- unsigned flags = TypeOf (rhst);
- if (rhs->Flags == E_MCONST) {
- flags |= CF_CONST;
- }
- return g_typecast (TypeOf (lhst), flags);
- }
- } else if (IsClassPtr (lhst)) {
- if (IsClassPtr (rhst)) {
- /* 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.
- */
- if (!IsTypeVoid (Indirect (lhst)) && !IsTypeVoid (Indirect (rhst))) {
- /* Compare the types */
- switch (TypeCmp (lhst, rhst)) {
-
- 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 (rhst)) {
- /* Int to pointer assignment is valid only for constant zero */
- if (rhs->Flags != E_MCONST || rhs->ConstVal != 0) {
- Warning ("Converting integer to pointer without a cast");
- }
- } else if (IsTypeFuncPtr (lhst) && IsTypeFunc(rhst)) {
- /* Assignment of function to function pointer is allowed, provided
- * that both functions have the same parameter list.
- */
- if (TypeCmp (Indirect (lhst), rhst) < TC_EQUAL) {
- Error ("Incompatible types");
- }
- } else {
- Error ("Incompatible types");
- }
- } else {
- Error ("Incompatible types");
- }
-
- /* Return an int value in all cases where the operands are not both ints */
- return CF_INT;
-}
-
-
-
void DefineData (ExprDesc* Expr)
/* Output a data definition for the given expression */
{
-static int kcalc (int tok, long val1, long val2)
+static int kcalc (token_t tok, long val1, long val2)
/* Calculate an operation with left and right operand constant. */
{
switch (tok) {
-void exprhs (unsigned flags, int k, ExprDesc *lval)
+void exprhs (unsigned flags, int k, ExprDesc* lval)
/* Put the result of an expression into the primary register */
{
int f;
FrameSize = Func->ParamSize;
if (FrameParams > 0 && (Func->Flags & FD_FASTCALL) != 0) {
/* Last parameter is not pushed */
- const SymEntry* LastParam = Func->SymTab->SymTail;
- FrameSize -= CheckedSizeOf (LastParam->Type);
+ FrameSize -= CheckedSizeOf (Func->LastParam->Type);
--FrameParams;
}
* convert the actual argument to the type needed.
*/
if (!Ellipsis) {
- /* Promote the argument if needed */
- assignadjust (Param->Type, &lval);
+ /* Convert the argument to the parameter type if needed */
+ TypeConversion (&lval, 0, Param->Type);
/* If we have a prototype, chars may be pushed as chars */
Flags |= CF_FORCECHAR;
RemoveCode (Mark1);
/* Handle constant base array on stack. Be sure NOT to
- * handle pointers the same way, this won't work.
+ * handle pointers the same way, and check for character literals
+ * (both won't work).
*/
- if (IsTypeArray (tptr1) &&
+ if (IsTypeArray (tptr1) && lval->Flags != (E_MCONST | E_TLIT) &&
((lval->Flags & ~E_MCTYPE) == E_MCONST ||
(lval->Flags & ~E_MCTYPE) == E_MLOCAL ||
(lval->Flags & E_MGLOBAL) != 0 ||
/* If the expression is already a pointer to function, the
* additional dereferencing operator must be ignored.
*/
- if (IsTypeFuncPtr (lval->Type)) {
+ if (IsTypeFuncPtr (lval->Type)) {
/* Expression not storable */
return 0;
} else {
- if (IsClassPtr (lval->Type)) {
+ if (IsClassPtr (lval->Type)) {
lval->Type = Indirect (lval->Type);
} else {
Error ("Illegal indirection");
g_scale (CF_INT, CheckedPSizeOf (lhst));
/* Operate on pointers, result type is a pointer */
flags |= CF_PTR;
- /* Generate the code for the add */
- if (lval->Flags == E_MCONST) {
- /* Numeric constant */
- g_inc (flags, lval->ConstVal);
- } else {
- /* Constant address */
- g_addaddr_static (flags, lval->Name, lval->ConstVal);
- }
+ /* Generate the code for the add */
+ if (lval->Flags == E_MCONST) {
+ /* Numeric constant */
+ g_inc (flags, lval->ConstVal);
+ } else {
+ /* Constant address */
+ g_addaddr_static (flags, lval->Name, lval->ConstVal);
+ }
} else if (IsClassInt (lhst) && IsClassPtr (rhst)) {
/* Left is int, right is pointer, must scale lhs. */
- unsigned ScaleFactor = CheckedPSizeOf (rhst);
+ unsigned ScaleFactor = CheckedPSizeOf (rhst);
/* Operate on pointers, result type is a pointer */
- flags |= CF_PTR;
- lval->Type = lval2.Type;
-
- /* Since we do already have rhs in the primary, if lhs is
- * not a numeric constant, and the scale factor is not one
- * (no scaling), we must take the long way over the stack.
- */
- if (lval->Flags == E_MCONST) {
- /* Numeric constant, scale lhs */
- lval->ConstVal *= ScaleFactor;
- /* Generate the code for the add */
- g_inc (flags, lval->ConstVal);
- } else if (ScaleFactor == 1) {
- /* Constant address but no need to scale */
- g_addaddr_static (flags, lval->Name, lval->ConstVal);
- } else {
- /* Constant address that must be scaled */
+ flags |= CF_PTR;
+ lval->Type = lval2.Type;
+
+ /* Since we do already have rhs in the primary, if lhs is
+ * not a numeric constant, and the scale factor is not one
+ * (no scaling), we must take the long way over the stack.
+ */
+ if (lval->Flags == E_MCONST) {
+ /* Numeric constant, scale lhs */
+ lval->ConstVal *= ScaleFactor;
+ /* Generate the code for the add */
+ g_inc (flags, lval->ConstVal);
+ } else if (ScaleFactor == 1) {
+ /* Constant address but no need to scale */
+ g_addaddr_static (flags, lval->Name, lval->ConstVal);
+ } else {
+ /* Constant address that must be scaled */
g_push (TypeOf (lval2.Type), 0); /* rhs --> stack */
- g_getimmed (flags, lval->Name, lval->ConstVal);
- g_scale (CF_PTR, ScaleFactor);
- g_add (CF_PTR, 0);
- }
+ g_getimmed (flags, lval->Name, lval->ConstVal);
+ g_scale (CF_PTR, ScaleFactor);
+ g_add (CF_PTR, 0);
+ }
} else if (IsClassInt (lhst) && IsClassInt (rhst)) {
/* Integer addition */
flags |= typeadjust (lval, &lval2, 1);
- /* Generate the code for the add */
- if (lval->Flags == E_MCONST) {
- /* Numeric constant */
- g_inc (flags, lval->ConstVal);
- } else {
- /* Constant address */
- g_addaddr_static (flags, lval->Name, lval->ConstVal);
- }
+ /* Generate the code for the add */
+ if (lval->Flags == E_MCONST) {
+ /* Numeric constant */
+ g_inc (flags, lval->ConstVal);
+ } else {
+ /* Constant address */
+ g_addaddr_static (flags, lval->Name, lval->ConstVal);
+ }
} else {
/* OOPS */
Error ("Invalid operands for binary operator `+'");
flags = CF_PTR;
lval->Type = lval2.Type;
} else if (IsClassInt (lhst) && IsClassInt (rhst)) {
- /* Integer addition */
- flags = typeadjust (lval, &lval2, 0);
+ /* Integer addition. Note: Result is never constant.
+ * Problem here is that typeadjust does not know if the
+ * variable is an rvalue or lvalue, so if both operands
+ * are dereferenced constant numeric addresses, typeadjust
+ * thinks the operation works on constants. Removing
+ * CF_CONST here means handling the symptoms, however, the
+ * whole parser is such a mess that I fear to break anything
+ * when trying to apply another solution.
+ */
+ flags = typeadjust (lval, &lval2, 0) & ~CF_CONST;
} else {
/* OOPS */
Error ("Invalid operands for binary operator `+'");
-static int hie0 (ExprDesc *lval)
+int hie0 (ExprDesc *lval)
/* Parse comma operator. */
{
- int k;
-
- k = hie1 (lval);
+ int k = hie1 (lval);
while (CurTok.Tok == TOK_COMMA) {
NextToken ();
k = hie1 (lval);