/* common */
#include "check.h"
+#include "debugflag.h"
#include "xmalloc.h"
/* cc65 */
-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;
* 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;
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 ();
* 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;
default:
if (istypeexpr ()) {
- /* A cast */
- return TypeCast (lval);
+ /* A cast */
+ return TypeCast (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;
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 `+'");