break;
case TOK_SCONST:
+ case TOK_WCSCONST:
/* String literal */
E->Type = GetCharArrayType (GetLiteralPoolOffs () - CurTok.IVal);
E->Flags = E_LOC_LITERAL | E_RTYPE_RVAL;
}
/* TOS now contains ptr to array elements. Get the subscript. */
- ExprWithCheck (hie0, &Subscript);
+ MarkedExprWithCheck (hie0, &Subscript);
/* Check the types of array and subscript. We can either have a
* pointer/array to the left, in which case the subscript must be of an
}
/* Check if the subscript is constant absolute value */
- if (ED_IsConstAbs (&Subscript)) {
+ if (ED_IsConstAbs (&Subscript) && ED_CodeRangeIsEmpty (&Subscript)) {
/* The array subscript is a numeric constant. If we had pushed the
* array base address onto the stack before, we can remove this value,
{
ident Ident;
SymEntry* Field;
+ TypeCode Q;
/* Skip the token and check for an identifier */
NextToken ();
/* Set the struct field offset */
Expr->IVal += Field->V.Offs;
- /* The type is now the type of the field */
- Expr->Type = Field->Type;
+ /* The type is the type of the field plus any qualifiers from the struct */
+ Q = GetQualifier (Expr->Type);
+ if (GetQualifier (Field->Type) == (GetQualifier (Field->Type) | Q)) {
+ Expr->Type = Field->Type;
+ } else {
+ Expr->Type = TypeDup (Field->Type);
+ Expr->Type->C |= Q;
+ }
/* An struct member is actually a variable. So the rules for variables
* with respect to the reference type apply: If it's an array, it is
ED_MakeRValExpr (Expr);
}
/* If the expression is already a pointer to function, the
- * additional dereferencing operator must be ignored.
+ * additional dereferencing operator must be ignored. A function
+ * itself is represented as "pointer to function", so any number
+ * of dereference operators is legal, since the result will
+ * always be converted to "pointer to function".
*/
- if (IsTypeFuncPtr (Expr->Type)) {
+ if (IsTypeFuncPtr (Expr->Type) || IsTypeFunc (Expr->Type)) {
/* Expression not storable */
ED_MakeRVal (Expr);
} else {
}
/* Get the right hand side */
- rconst = (evalexpr (CF_NONE, hienext, &Expr2) == 0);
+ MarkedExprWithCheck (hienext, &Expr2);
+
+ /* Check for a constant expression */
+ rconst = (ED_IsConstAbs (&Expr2) && ED_CodeRangeIsEmpty (&Expr2));
+ if (!rconst) {
+ /* Not constant, load into the primary */
+ LoadExpr (CF_NONE, &Expr2);
+ }
/* Make sure, the types are compatible */
if (IsClassInt (Expr->Type)) {
/* Both expressions are constants. Check for pointer arithmetic */
if (IsClassPtr (lhst) && IsClassInt (rhst)) {
- /* Left is pointer, right is int, must scale rhs */
+ /* Left is pointer, right is int, must scale rhs */
Expr->IVal += Expr2.IVal * CheckedPSizeOf (lhst);
- /* Result type is a pointer */
+ /* Result type is a pointer */
} else if (IsClassInt (lhst) && IsClassPtr (rhst)) {
- /* Left is int, right is pointer, must scale lhs */
+ /* Left is int, right is pointer, must scale lhs */
Expr->IVal = Expr->IVal * CheckedPSizeOf (rhst) + Expr2.IVal;
- /* Result type is a pointer */
- Expr->Type = Expr2.Type;
+ /* Result type is a pointer */
+ Expr->Type = Expr2.Type;
} else if (IsClassInt (lhst) && IsClassInt (rhst)) {
- /* Integer addition */
- Expr->IVal += Expr2.IVal;
- typeadjust (Expr, &Expr2, 1);
+ /* Integer addition */
+ Expr->IVal += Expr2.IVal;
+ typeadjust (Expr, &Expr2, 1);
} else {
/* OOPS */
- Error ("Invalid operands for binary operator `+'");
+ Error ("Invalid operands for binary operator `+'");
}
} else {
g_push (TypeOf (Expr->Type), 0); /* --> stack */
/* Evaluate the rhs */
- if (evalexpr (CF_NONE, hie9, &Expr2) == 0) {
+ MarkedExprWithCheck (hie9, &Expr2);
+
+ /* Check for a constant rhs expression */
+ if (ED_IsConstAbs (&Expr2) && ED_CodeRangeIsEmpty (&Expr2)) {
/* Right hand side is a constant. Get the rhs type */
rhst = Expr2.Type;
} else {
+ /* Not constant, load into the primary */
+ LoadExpr (CF_NONE, &Expr2);
+
/* lhs and rhs are not constant. Get the rhs type. */
rhst = Expr2.Type;
g_push (TypeOf (lhst), 0); /* --> stack */
/* Parse the right hand side */
- if (evalexpr (CF_NONE, hie9, &Expr2) == 0) {
+ MarkedExprWithCheck (hie9, &Expr2);
+
+ /* Check for a constant rhs expression */
+ if (ED_IsConstAbs (&Expr2) && ED_CodeRangeIsEmpty (&Expr2)) {
/* The right hand side is constant. Get the rhs type. */
rhst = Expr2.Type;
/* Do the subtraction */
g_dec (flags | CF_CONST, Expr2.IVal);
- /* If this was a pointer subtraction, we must scale the result */
- if (rscale != 1) {
- g_scale (flags, -rscale);
- }
+ /* If this was a pointer subtraction, we must scale the result */
+ if (rscale != 1) {
+ g_scale (flags, -rscale);
+ }
- /* Result is a rvalue in the primary register */
- ED_MakeRValExpr (Expr);
- ED_MarkAsUntested (Expr);
+ /* Result is a rvalue in the primary register */
+ ED_MakeRValExpr (Expr);
+ ED_MarkAsUntested (Expr);
- }
+ }
} else {
- /* Right hand side is not constant. Get the rhs type. */
- rhst = Expr2.Type;
+ /* Not constant, load into the primary */
+ LoadExpr (CF_NONE, &Expr2);
+
+ /* Right hand side is not constant. Get the rhs type. */
+ rhst = Expr2.Type;
/* Check for pointer arithmetic */
- if (IsClassPtr (lhst) && IsClassInt (rhst)) {
+ if (IsClassPtr (lhst) && IsClassInt (rhst)) {
/* Left is pointer, right is int, must scale rhs */
- g_scale (CF_INT, CheckedPSizeOf (lhst));
- /* Operate on pointers, result type is a pointer */
- flags = CF_PTR;
- } else if (IsClassPtr (lhst) && IsClassPtr (rhst)) {
- /* Left is pointer, right is pointer, must scale result */
- if (TypeCmp (Indirect (lhst), Indirect (rhst)) < TC_QUAL_DIFF) {
- Error ("Incompatible pointer types");
- } else {
- rscale = CheckedPSizeOf (lhst);
- }
- /* Operate on pointers, result type is an integer */
- flags = CF_PTR;
- Expr->Type = type_int;
+ g_scale (CF_INT, CheckedPSizeOf (lhst));
+ /* Operate on pointers, result type is a pointer */
+ flags = CF_PTR;
+ } else if (IsClassPtr (lhst) && IsClassPtr (rhst)) {
+ /* Left is pointer, right is pointer, must scale result */
+ if (TypeCmp (Indirect (lhst), Indirect (rhst)) < TC_QUAL_DIFF) {
+ Error ("Incompatible pointer types");
+ } else {
+ rscale = CheckedPSizeOf (lhst);
+ }
+ /* Operate on pointers, result type is an integer */
+ flags = CF_PTR;
+ Expr->Type = type_int;
} else if (IsClassInt (lhst) && IsClassInt (rhst)) {
/* Integer subtraction. If the left hand side descriptor says that
* the lhs is const, we have to remove this mark, since this is no
-static void opeq (const GenDesc* Gen, ExprDesc* Expr)
+static void opeq (const GenDesc* Gen, ExprDesc* Expr, const char* Op)
/* Process "op=" operators. */
{
ExprDesc Expr2;
g_push (flags, 0);
/* Evaluate the rhs */
- if (evalexpr (CF_NONE, hie1, &Expr2) == 0) {
+ MarkedExprWithCheck (hie1, &Expr2);
+
+ /* The rhs must be an integer (or a float, but we don't support that yet */
+ if (!IsClassInt (Expr2.Type)) {
+ Error ("Invalid right operand for binary operator `%s'", Op);
+ /* Continue. Wrong code will be generated, but the compiler won't
+ * break, so this is the best error recovery.
+ */
+ }
+
+ /* Check for a constant expression */
+ if (ED_IsConstAbs (&Expr2) && ED_CodeRangeIsEmpty (&Expr2)) {
/* The resulting value is a constant. If the generator has the NOPUSH
* flag set, don't push the lhs.
*/
Gen->Func (flags | CF_CONST, Expr2.IVal);
}
} else {
- /* rhs is not constant and already in the primary register */
+
+ /* rhs is not constant. Load into the primary */
+ LoadExpr (CF_NONE, &Expr2);
if (MustScale) {
/* lhs is a pointer, scale rhs */
g_scale (TypeOf (Expr2.Type), CheckedSizeOf (Expr->Type+1));
-static void addsubeq (const GenDesc* Gen, ExprDesc *Expr)
+static void addsubeq (const GenDesc* Gen, ExprDesc *Expr, const char* Op)
/* Process the += and -= operators */
{
ExprDesc Expr2;
/* We're currently only able to handle some adressing modes */
if (ED_GetLoc (Expr) == E_LOC_EXPR || ED_GetLoc (Expr) == E_LOC_PRIMARY) {
/* Use generic routine */
- opeq (Gen, Expr);
+ opeq (Gen, Expr, Op);
return;
}
lflags = 0;
rflags = 0;
- /* Evaluate the rhs */
+ /* Evaluate the rhs. We expect an integer here, since float is not
+ * supported
+ */
hie1 (&Expr2);
+ if (!IsClassInt (Expr2.Type)) {
+ Error ("Invalid right operand for binary operator `%s'", Op);
+ /* Continue. Wrong code will be generated, but the compiler won't
+ * break, so this is the best error recovery.
+ */
+ }
if (ED_IsConstAbs (&Expr2)) {
/* The resulting value is a constant. Scale it. */
if (MustScale) {
break;
case TOK_PLUS_ASSIGN:
- addsubeq (&GenPASGN, Expr);
+ addsubeq (&GenPASGN, Expr, "+=");
break;
case TOK_MINUS_ASSIGN:
- addsubeq (&GenSASGN, Expr);
+ addsubeq (&GenSASGN, Expr, "-=");
break;
case TOK_MUL_ASSIGN:
- opeq (&GenMASGN, Expr);
+ opeq (&GenMASGN, Expr, "*=");
break;
case TOK_DIV_ASSIGN:
- opeq (&GenDASGN, Expr);
+ opeq (&GenDASGN, Expr, "/=");
break;
case TOK_MOD_ASSIGN:
- opeq (&GenMOASGN, Expr);
+ opeq (&GenMOASGN, Expr, "%=");
break;
case TOK_SHL_ASSIGN:
- opeq (&GenSLASGN, Expr);
+ opeq (&GenSLASGN, Expr, "<<=");
break;
case TOK_SHR_ASSIGN:
- opeq (&GenSRASGN, Expr);
+ opeq (&GenSRASGN, Expr, ">>=");
break;
case TOK_AND_ASSIGN:
- opeq (&GenAASGN, Expr);
+ opeq (&GenAASGN, Expr, "&=");
break;
case TOK_XOR_ASSIGN:
- opeq (&GenXOASGN, Expr);
+ opeq (&GenXOASGN, Expr, "^=");
break;
case TOK_OR_ASSIGN:
- opeq (&GenOASGN, Expr);
+ opeq (&GenOASGN, Expr, "|=");
break;
default: