]> git.sur5r.net Git - cc65/blobdiff - src/cc65/expr.c
Merge branch 'pointer' of https://github.com/mrdudz/cc65 into mrdudz-pointer
[cc65] / src / cc65 / expr.c
index 7563645ff0e9bf6e28da7a8c12bcd6fb049ff06e..64fc17e3f2833018b1c1b9d12a340bb0f956986b 100644 (file)
@@ -50,6 +50,7 @@
 /* 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 {
@@ -2042,6 +2043,11 @@ static void hie_compare (const GenDesc* Ops,    /* List of generators */
         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);
@@ -2059,6 +2065,11 @@ static void hie_compare (const GenDesc* Ops,    /* List of generators */
         /* 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) {
@@ -2066,6 +2077,22 @@ static void hie_compare (const GenDesc* Ops,    /* List of generators */
             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))) {
@@ -2600,6 +2627,13 @@ static void parsesub (ExprDesc* 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 ();
 
@@ -2616,6 +2650,13 @@ static void parsesub (ExprDesc* Expr)
     /* 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)) {
 
@@ -2775,11 +2816,11 @@ static void hie6 (ExprDesc* Expr)
 /* 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);
 }