]> git.sur5r.net Git - cc65/blobdiff - src/cc65/expr.c
Change the OptStackOps function so that it adjusts the instruction pointer
[cc65] / src / cc65 / expr.c
index 6bf80782698638992f6a96289fe43c9fde3c28e5..343ecdfed4eb048acab1813cef404fc9205623d1 100644 (file)
@@ -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: