X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=src%2Fcc65%2Fexpr.c;h=343ecdfed4eb048acab1813cef404fc9205623d1;hb=77bfcc1ff0a88e0430f077d22b6fad07c7d0c86b;hp=6bf80782698638992f6a96289fe43c9fde3c28e5;hpb=b5db4cd5fa4f1cf648baf2b58dea67ec5560c5bb;p=cc65 diff --git a/src/cc65/expr.c b/src/cc65/expr.c index 6bf807826..343ecdfed 100644 --- a/src/cc65/expr.c +++ b/src/cc65/expr.c @@ -486,6 +486,12 @@ static void FunctionCall (ExprDesc* Expr) } } 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); @@ -547,7 +553,7 @@ static void FunctionCall (ExprDesc* Expr) /* If we have a pointer on stack, remove it */ if (PtrOnStack) { - g_space (- (int) sizeofarg (CF_PTR)); + g_drop (SIZEOF_PTR); pop (CF_PTR); } @@ -742,10 +748,11 @@ static void Primary (ExprDesc* E) 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; @@ -797,6 +804,7 @@ static void ArrayRef (ExprDesc* Expr) ExprDesc Subscript; CodeMark Mark1; CodeMark Mark2; + TypeCode Qualifiers; Type* ElementType; Type* tptr1; @@ -838,12 +846,16 @@ static void ArrayRef (ExprDesc* Expr) * 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)) { @@ -852,6 +864,8 @@ static void ArrayRef (ExprDesc* Expr) * address 0. */ ED_MakeConstAbs (&Subscript, 0, GetCharArrayType (1)); + } else if (IsTypeArray (Subscript.Type)) { + Qualifiers = GetQualifier (Subscript.Type); } ElementType = Indirect (Subscript.Type); } else { @@ -864,6 +878,14 @@ static void ArrayRef (ExprDesc* Expr) 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); @@ -1070,12 +1092,14 @@ static void StructRef (ExprDesc* Expr) { 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; } @@ -1085,7 +1109,8 @@ static void StructRef (ExprDesc* Expr) 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; } @@ -1104,8 +1129,18 @@ static void StructRef (ExprDesc* Expr) /* 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 @@ -1592,9 +1627,12 @@ void hie10 (ExprDesc* Expr) 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 { @@ -2843,7 +2881,7 @@ static void hieQuest (ExprDesc* Expr) -static void opeq (const GenDesc* Gen, ExprDesc* Expr) +static void opeq (const GenDesc* Gen, ExprDesc* Expr, const char* Op) /* Process "op=" operators. */ { ExprDesc Expr2; @@ -2890,6 +2928,14 @@ static void opeq (const GenDesc* Gen, ExprDesc* Expr) /* 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 @@ -2951,7 +2997,7 @@ static void opeq (const GenDesc* Gen, ExprDesc* Expr) -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; @@ -2963,7 +3009,7 @@ static void addsubeq (const GenDesc* Gen, ExprDesc *Expr) /* 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; } @@ -2996,8 +3042,16 @@ static void addsubeq (const GenDesc* Gen, ExprDesc *Expr) 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) { @@ -3091,43 +3145,43 @@ void hie1 (ExprDesc* Expr) 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: