}
} else {
+ /* Check function attributes */
+ if (Expr->Sym && SymHasAttr (Expr->Sym, atNoReturn)) {
+ /* For now, handle as if a return statement was encountered */
+ F_ReturnFound (CurrentFunc);
+ }
+
/* Check for known standard functions and inline them */
if (Expr->Name != 0) {
int StdFunc = FindStdFunc ((const char*) Expr->Name);
/* If we have a pointer on stack, remove it */
if (PtrOnStack) {
- g_space (- (int) sizeofarg (CF_PTR));
+ g_drop (SIZEOF_PTR);
pop (CF_PTR);
}
case TOK_SCONST:
case TOK_WCSCONST:
/* String literal */
- E->Type = GetCharArrayType (GetLiteralPoolOffs () - CurTok.IVal);
+ E->LVal = UseLiteral (CurTok.SVal);
+ E->Type = GetCharArrayType (GetLiteralSize (CurTok.SVal));
E->Flags = E_LOC_LITERAL | E_RTYPE_RVAL;
- E->IVal = CurTok.IVal;
- E->Name = LiteralPoolLabel;
+ E->IVal = 0;
+ E->Name = GetLiteralLabel (CurTok.SVal);
NextToken ();
break;
ExprDesc Subscript;
CodeMark Mark1;
CodeMark Mark2;
+ TypeCode Qualifiers;
Type* ElementType;
Type* tptr1;
* Since we do the necessary checking here, we can rely later on the
* correct types.
*/
+ Qualifiers = T_QUAL_NONE;
if (IsClassPtr (Expr->Type)) {
if (!IsClassInt (Subscript.Type)) {
Error ("Array subscript is not an integer");
/* To avoid any compiler errors, make the expression a valid int */
ED_MakeConstAbsInt (&Subscript, 0);
}
+ if (IsTypeArray (Expr->Type)) {
+ Qualifiers = GetQualifier (Expr->Type);
+ }
ElementType = Indirect (Expr->Type);
} else if (IsClassInt (Expr->Type)) {
if (!IsClassPtr (Subscript.Type)) {
* address 0.
*/
ED_MakeConstAbs (&Subscript, 0, GetCharArrayType (1));
+ } else if (IsTypeArray (Subscript.Type)) {
+ Qualifiers = GetQualifier (Subscript.Type);
}
ElementType = Indirect (Subscript.Type);
} else {
ElementType = Indirect (Expr->Type);
}
+ /* The element type has the combined qualifiers from itself and the array,
+ * it is a member of (if any).
+ */
+ if (GetQualifier (ElementType) != (GetQualifier (ElementType) | Qualifiers)) {
+ ElementType = TypeDup (ElementType);
+ ElementType->C |= Qualifiers;
+ }
+
/* If the subscript is a bit-field, load it and make it an rvalue */
if (ED_IsBitField (&Subscript)) {
LoadExpr (CF_NONE, &Subscript);
{
ident Ident;
SymEntry* Field;
+ TypeCode Q;
/* Skip the token and check for an identifier */
NextToken ();
if (CurTok.Tok != TOK_IDENT) {
Error ("Identifier expected");
- Expr->Type = type_int;
+ /* Make the expression an integer at address zero */
+ ED_MakeConstAbs (Expr, 0, type_int);
return;
}
Field = FindStructField (Expr->Type, Ident);
if (Field == 0) {
Error ("Struct/union has no field named `%s'", Ident);
- Expr->Type = type_int;
+ /* Make the expression an integer at address zero */
+ ED_MakeConstAbs (Expr, 0, type_int);
return;
}
/* 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 */
+ if (IsClassStruct (Expr->Type)) {
+ Q = GetQualifier (Expr->Type);
+ } else {
+ Q = GetQualifier (Indirect (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 {
-static void opeq (const GenDesc* Gen, ExprDesc* Expr)
+static void opeq (const GenDesc* Gen, ExprDesc* Expr, const char* Op)
/* Process "op=" operators. */
{
ExprDesc Expr2;
/* Evaluate the rhs */
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
-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: