X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=src%2Fcc65%2Fexpr.c;h=e5e21e3ce796c9831b388aaf05413a54e6b864bc;hb=b28cf4cfd855ddf3e69eadc1a48d7582fc901e12;hp=48675d99bf548a42847aa5da8da79d872da426aa;hpb=4e2110a7a9ab0d054acb784b8585e9c7c6f4f399;p=cc65 diff --git a/src/cc65/expr.c b/src/cc65/expr.c index 48675d99b..e5e21e3ce 100644 --- a/src/cc65/expr.c +++ b/src/cc65/expr.c @@ -11,6 +11,7 @@ /* common */ #include "check.h" +#include "debugflag.h" #include "xmalloc.h" /* cc65 */ @@ -500,7 +501,7 @@ void CheckBoolExpr (ExprDesc* lval) -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; @@ -553,7 +554,7 @@ static unsigned FunctionParamList (FuncDesc* Func) * each parameter separately, or creating the parameter frame once and then * storing into this frame. * The function returns the size of the parameters pushed. - */ + */ { ExprDesc lval; @@ -1609,29 +1610,37 @@ int hie10 (ExprDesc* lval) case TOK_BOOL_NOT: NextToken (); if (evalexpr (CF_NONE, hie10, lval) == 0) { - /* Constant expression */ - lval->ConstVal = !lval->ConstVal; + /* Constant expression */ + lval->ConstVal = !lval->ConstVal; } else { - g_bneg (TypeOf (lval->Type)); - lval->Test |= E_CC; /* bneg will set cc */ - lval->Flags = E_MEXPR; /* say it's an expr */ + g_bneg (TypeOf (lval->Type)); + lval->Test |= E_CC; /* bneg will set cc */ + lval->Flags = E_MEXPR; /* say it's an expr */ } return 0; /* expr not storable */ case TOK_STAR: NextToken (); if (evalexpr (CF_NONE, hie10, lval) != 0) { - /* Expression is not const, indirect value loaded into primary */ - lval->Flags = E_MEXPR; - lval->ConstVal = 0; /* Offset is zero now */ + /* Expression is not const, indirect value loaded into primary */ + lval->Flags = E_MEXPR; + lval->ConstVal = 0; /* Offset is zero now */ } - t = lval->Type; - if (IsClassPtr (t)) { - lval->Type = Indirect (t); - } else { - Error ("Illegal indirection"); - } - return 1; + /* If the expression is already a pointer to function, the + * additional dereferencing operator must be ignored. + */ + if (IsTypeFuncPtr (lval->Type)) { + /* Expression not storable */ + return 0; + } else { + if (IsClassPtr (lval->Type)) { + lval->Type = Indirect (lval->Type); + } else { + Error ("Illegal indirection"); + } + return 1; + } + break; case TOK_AND: NextToken (); @@ -1640,32 +1649,32 @@ int hie10 (ExprDesc* lval) * applied to functions, even if they're no lvalues. */ if (k == 0 && !IsTypeFunc (lval->Type)) { - /* Allow the & operator with an array */ - if (!IsTypeArray (lval->Type)) { - Error ("Illegal address"); - } + /* Allow the & operator with an array */ + if (!IsTypeArray (lval->Type)) { + Error ("Illegal address"); + } } else { - t = TypeAlloc (TypeLen (lval->Type) + 2); - t [0] = T_PTR; - TypeCpy (t + 1, lval->Type); - lval->Type = t; + t = TypeAlloc (TypeLen (lval->Type) + 2); + t [0] = T_PTR; + TypeCpy (t + 1, lval->Type); + lval->Type = t; } return 0; case TOK_SIZEOF: NextToken (); if (istypeexpr ()) { - type Type[MAXTYPELEN]; - NextToken (); - lval->ConstVal = CheckedSizeOf (ParseType (Type)); - ConsumeRParen (); + type Type[MAXTYPELEN]; + NextToken (); + lval->ConstVal = CheckedSizeOf (ParseType (Type)); + ConsumeRParen (); } else { - /* Remember the output queue pointer */ - CodeMark Mark = GetCodePos (); - hie10 (lval); + /* Remember the output queue pointer */ + CodeMark Mark = GetCodePos (); + hie10 (lval); lval->ConstVal = CheckedSizeOf (lval->Type); - /* Remove any generated code */ - RemoveCode (Mark); + /* Remove any generated code */ + RemoveCode (Mark); } lval->Flags = E_MCONST | E_TCONST; lval->Type = type_uint; @@ -1674,8 +1683,8 @@ int hie10 (ExprDesc* lval) default: if (istypeexpr ()) { - /* A cast */ - return TypeCast (lval); + /* A cast */ + return TypeCast (lval); } } @@ -1699,7 +1708,7 @@ int hie10 (ExprDesc* lval) static int hie_internal (const GenDesc** ops, /* List of generators */ ExprDesc* lval, /* parent expr's lval */ int (*hienext) (ExprDesc*), - int* UsedGen) /* next higher level */ + int* UsedGen) /* next higher level */ /* Helper function */ { int k; @@ -2025,53 +2034,53 @@ static void parseadd (int k, ExprDesc* lval) 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 `+'"); @@ -2147,8 +2156,16 @@ static void parseadd (int k, ExprDesc* lval) 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 `+'");