Re: [cc65] cc65 function pointer bugs

From: Ullrich von Bassewitz <uz1musoftware.de>
Date: 2015-03-14 18:53:24
On Wed, Mar 11, 2015 at 01:21:47PM -0400, Greg King wrote:
> cc65 version 2.13.9, Subversion revision 5990, fails to handle some
> operations on function pointers.

Here is a patch that might fix the problems:

------------------------------------------------------------------------------
Index: datatype.c
===================================================================
--- datatype.c	(revision 5990)
+++ datatype.c	(working copy)
@@ -391,6 +391,9 @@
     	case T_VOID:
        	    return 0;   /* Assume voids have size zero */

+	case T_FUNC:
+            return 0;   /* Size of function is unknown */
+
 	case T_SCHAR:
 	case T_UCHAR:
 	    return SIZEOF_CHAR;
@@ -404,7 +407,6 @@
             return SIZEOF_INT;

 	case T_PTR:
-	case T_FUNC:	/* Maybe pointer to function */
 	    return SIZEOF_PTR;

         case T_LONG:
@@ -659,7 +661,7 @@
  * will return. Otherwise it will return the base element type, which means
  * the element type that is not an array.
  */
-{
+{
     while (IsTypeArray (T)) {
         ++T;
     }
Index: expr.c
===================================================================
--- expr.c	(revision 5990)
+++ expr.c	(working copy)
@@ -47,8 +47,9 @@


 /* Generator attributes */
-#define GEN_NOPUSH	0x01  		/* Don't push lhs */
+#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 {
@@ -2030,6 +2031,11 @@
        	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);
@@ -2047,6 +2053,11 @@
 	/* 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) {
@@ -2054,6 +2065,22 @@
             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))) {
@@ -2588,6 +2615,13 @@
     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 ();

@@ -2604,6 +2638,13 @@
     /* 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)) {

@@ -2763,11 +2804,11 @@
 /* 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);
 }
------------------------------------------------------------------------------

Beware: There's a chance that the change in datatype.c triggers problems in
other parts of the compiler. The solution is to fix the callers, because
calling SizeOf() with a function type as argument is bad.

Regards


        Uz


-- 
Ullrich von Bassewitz                                  uz@musoftware.de
Encrypted email preferred                          PGP Key-Id: 29D93B10
----------------------------------------------------------------------
To unsubscribe from the list send mail to majordomo@musoftware.de with
the string "unsubscribe cc65" in the body(!) of the mail.
Received on Sat Mar 14 18:53:28 2015

This archive was generated by hypermail 2.1.8 : 2015-03-14 18:53:31 CET