/* expr.c
**
** 1998-06-21, Ullrich von Bassewitz
-** 2015-04-19, Greg King
+** 2015-06-26, Greg King
*/
/* Generator attributes */
#define GEN_NOPUSH 0x01 /* Don't push lhs */
#define GEN_COMM 0x02 /* Operator is commutative */
+#define GEN_NOFUNC 0x04 /* Not allowed for function pointers */
/* Map a generator function and its attributes to a token */
typedef struct {
/* Get the data type */
Flags = TypeOf (Expr->Type);
- /* Push the address if needed */
- PushAddr (Expr);
+ /* Fast path: char */
+ if ((Flags & CF_CHAR) == CF_CHAR && ED_GetLoc(Expr) & (E_LOC_GLOBAL | E_LOC_STATIC)) {
- /* Fetch the value and save it (since it's the result of the expression) */
- LoadExpr (CF_NONE, Expr);
- g_save (Flags | CF_FORCECHAR);
+ LoadExpr (CF_NONE, Expr);
+ AddCodeLine ("inc %s", ED_GetLabelName(Expr, 0));
- /* If we have a pointer expression, increment by the size of the type */
- if (IsTypePtr (Expr->Type)) {
- g_inc (Flags | CF_CONST | CF_FORCECHAR, CheckedSizeOf (Expr->Type + 1));
} else {
- g_inc (Flags | CF_CONST | CF_FORCECHAR, 1);
- }
- /* Store the result back */
- Store (Expr, 0);
+ /* Push the address if needed */
+ PushAddr (Expr);
+
+ /* Fetch the value and save it (since it's the result of the expression) */
+ LoadExpr (CF_NONE, Expr);
+ g_save (Flags | CF_FORCECHAR);
+
+ /* If we have a pointer expression, increment by the size of the type */
+ if (IsTypePtr (Expr->Type)) {
+ g_inc (Flags | CF_CONST | CF_FORCECHAR, CheckedSizeOf (Expr->Type + 1));
+ } else {
+ g_inc (Flags | CF_CONST | CF_FORCECHAR, 1);
+ }
- /* Restore the original value in the primary register */
- g_restore (Flags | CF_FORCECHAR);
+ /* Store the result back */
+ Store (Expr, 0);
+
+ /* Restore the original value in the primary register */
+ g_restore (Flags | CF_FORCECHAR);
+ }
/* The result is always an expression, no reference */
ED_MakeRValExpr (Expr);
/* Get the data type */
Flags = TypeOf (Expr->Type);
- /* Push the address if needed */
- PushAddr (Expr);
+ /* Fast path: char */
+ if ((Flags & CF_CHAR) == CF_CHAR && ED_GetLoc(Expr) & (E_LOC_GLOBAL | E_LOC_STATIC)) {
- /* Fetch the value and save it (since it's the result of the expression) */
- LoadExpr (CF_NONE, Expr);
- g_save (Flags | CF_FORCECHAR);
+ LoadExpr (CF_NONE, Expr);
+ AddCodeLine ("dec %s", ED_GetLabelName(Expr, 0));
- /* If we have a pointer expression, increment by the size of the type */
- if (IsTypePtr (Expr->Type)) {
- g_dec (Flags | CF_CONST | CF_FORCECHAR, CheckedSizeOf (Expr->Type + 1));
} else {
- g_dec (Flags | CF_CONST | CF_FORCECHAR, 1);
- }
- /* Store the result back */
- Store (Expr, 0);
+ /* Push the address if needed */
+ PushAddr (Expr);
+
+ /* Fetch the value and save it (since it's the result of the expression) */
+ LoadExpr (CF_NONE, Expr);
+ g_save (Flags | CF_FORCECHAR);
+
+ /* If we have a pointer expression, increment by the size of the type */
+ if (IsTypePtr (Expr->Type)) {
+ g_dec (Flags | CF_CONST | CF_FORCECHAR, CheckedSizeOf (Expr->Type + 1));
+ } else {
+ g_dec (Flags | CF_CONST | CF_FORCECHAR, 1);
+ }
- /* Restore the original value in the primary register */
- g_restore (Flags | CF_FORCECHAR);
+ /* Store the result back */
+ Store (Expr, 0);
+
+ /* Restore the original value in the primary register */
+ g_restore (Flags | CF_FORCECHAR);
+ }
/* The result is always an expression, no reference */
ED_MakeRValExpr (Expr);
} else {
Error ("Illegal indirection");
}
- /* The * operator yields an lvalue */
- ED_MakeLVal (Expr);
+ /* If the expression points to an array, then don't convert the
+ ** address -- it already is the location of the first element.
+ */
+ if (!IsTypeArray (Expr->Type)) {
+ /* The * operator yields an lvalue */
+ ED_MakeLVal (Expr);
+ }
}
break;
Tok = CurTok.Tok;
NextToken ();
+ /* If lhs is a function, convert it to pointer to function */
+ if (IsTypeFunc (Expr->Type)) {
+ Expr->Type = PointerTo (Expr->Type);
+ }
+
/* Get the lhs on stack */
GetCodePos (&Mark1);
ltype = TypeOf (Expr->Type);
/* Get the right hand side */
MarkedExprWithCheck (hienext, &Expr2);
+ /* If rhs is a function, convert it to pointer to function */
+ if (IsTypeFunc (Expr2.Type)) {
+ Expr2.Type = PointerTo (Expr2.Type);
+ }
+
/* Check for a constant expression */
rconst = (ED_IsConstAbs (&Expr2) && ED_CodeRangeIsEmpty (&Expr2));
if (!rconst) {
LoadExpr (CF_NONE, &Expr2);
}
+ /* Some operations aren't allowed on function pointers */
+ if ((Gen->Flags & GEN_NOFUNC) != 0) {
+ /* Output only one message even if both sides are wrong */
+ if (IsTypeFuncPtr (Expr->Type)) {
+ Error ("Invalid left operand for relational operator");
+ /* Avoid further errors */
+ ED_MakeConstAbsInt (Expr, 0);
+ ED_MakeConstAbsInt (&Expr2, 0);
+ } else if (IsTypeFuncPtr (Expr2.Type)) {
+ Error ("Invalid right operand for relational operator");
+ /* Avoid further errors */
+ ED_MakeConstAbsInt (Expr, 0);
+ ED_MakeConstAbsInt (&Expr2, 0);
+ }
+ }
+
/* Make sure, the types are compatible */
if (IsClassInt (Expr->Type)) {
if (!IsClassInt (Expr2.Type) && !(IsClassPtr(Expr2.Type) && ED_IsNullPtr(Expr))) {
*/
Type* left = Indirect (Expr->Type);
Type* right = Indirect (Expr2.Type);
- if (TypeCmp (left, right) < TC_EQUAL && left->C != T_VOID && right->C != T_VOID) {
- /* Incomatible pointers */
+ if (TypeCmp (left, right) < TC_QUAL_DIFF && left->C != T_VOID && right->C != T_VOID) {
+ /* Incompatible pointers */
Error ("Incompatible types");
}
} else if (!ED_IsNullPtr (&Expr2)) {
Type* lhst; /* Type of left hand side */
Type* rhst; /* Type of right hand side */
-
/* Skip the PLUS token */
NextToken ();
flags = CF_PTR;
} else if (IsClassInt (lhst) && IsClassPtr (rhst)) {
/* Left is int, right is pointer, must scale lhs */
- g_tosint (TypeOf (rhst)); /* Make sure, TOS is int */
+ g_tosint (TypeOf (lhst)); /* Make sure TOS is int */
g_swap (CF_INT); /* Swap TOS and primary */
g_scale (CF_INT, CheckedPSizeOf (rhst));
/* Operate on pointers, result type is a pointer */
/* Condition codes not set */
ED_MarkAsUntested (Expr);
-
}
int rscale; /* Scale factor for the result */
+ /* lhs cannot be function or pointer to function */
+ if (IsTypeFunc (Expr->Type) || IsTypeFuncPtr (Expr->Type)) {
+ Error ("Invalid left operand for binary operator `-'");
+ /* Make it pointer to char to avoid further errors */
+ Expr->Type = type_uchar;
+ }
+
/* Skip the MINUS token */
NextToken ();
/* Parse the right hand side */
MarkedExprWithCheck (hie9, &Expr2);
+ /* rhs cannot be function or pointer to function */
+ if (IsTypeFunc (Expr2.Type) || IsTypeFuncPtr (Expr2.Type)) {
+ Error ("Invalid right operand for binary operator `-'");
+ /* Make it pointer to char to avoid further errors */
+ Expr2.Type = type_uchar;
+ }
+
/* Check for a constant rhs expression */
if (ED_IsConstAbs (&Expr2) && ED_CodeRangeIsEmpty (&Expr2)) {
/* Handle greater-than type comparators */
{
static const GenDesc hie6_ops [] = {
- { TOK_LT, GEN_NOPUSH, g_lt },
- { TOK_LE, GEN_NOPUSH, g_le },
- { TOK_GE, GEN_NOPUSH, g_ge },
- { TOK_GT, GEN_NOPUSH, g_gt },
- { TOK_INVALID, 0, 0 }
+ { TOK_LT, GEN_NOPUSH | GEN_NOFUNC, g_lt },
+ { TOK_LE, GEN_NOPUSH | GEN_NOFUNC, g_le },
+ { TOK_GE, GEN_NOPUSH | GEN_NOFUNC, g_ge },
+ { TOK_GT, GEN_NOPUSH | GEN_NOFUNC, g_gt },
+ { TOK_INVALID, 0, 0 }
};
hie_compare (hie6_ops, Expr, ShiftExpr);
}