aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Forney <mforney@mforney.org>2020-04-04 19:21:32 -0700
committerMichael Forney <mforney@mforney.org>2020-04-04 21:31:52 -0700
commit65290cc659feafddf5881ec34a3b5e7987dfb07f (patch)
tree0006939ec9933867bf38b9c5b97739e9a767da83
parent0bb7273d42117585aeeda4610267158fcea494a6 (diff)
downloadcproc-65290cc659feafddf5881ec34a3b5e7987dfb07f.tar.xz
expr: Add type checking for equality and relational expressions
-rw-r--r--expr.c55
1 files changed, 42 insertions, 13 deletions
diff --git a/expr.c b/expr.c
index 2508879..7d13b44 100644
--- a/expr.c
+++ b/expr.c
@@ -183,6 +183,16 @@ commonreal(struct expr **e1, struct expr **e2)
return t;
}
+static bool
+nullpointer(struct expr *e)
+{
+ if (e->kind != EXPRCONST)
+ return false;
+ if (!(e->type->prop & PROPINT) && (e->type->kind != TYPEPOINTER || e->type->base != &typevoid))
+ return false;
+ return e->constant.i == 0;
+}
+
static struct expr *
mkbinaryexpr(struct location *loc, enum tokenkind op, struct expr *l, struct expr *r)
{
@@ -205,16 +215,45 @@ mkbinaryexpr(struct location *loc, enum tokenkind op, struct expr *l, struct exp
break;
case TEQL:
case TNEQ:
+ t = &typeint;
+ if (lp & PROPARITH && rp & PROPARITH) {
+ commonreal(&l, &r);
+ break;
+ }
+ if (l->type->kind != TYPEPOINTER)
+ e = l, l = r, r = e;
+ if (l->type->kind != TYPEPOINTER)
+ error(loc, "invalid operands to '%s' operator", tokstr[op]);
+ if (nullpointer(eval(r, EVALARITH))) {
+ r = exprconvert(r, l->type);
+ break;
+ }
+ if (nullpointer(eval(l, EVALARITH))) {
+ l = exprconvert(l, r->type);
+ break;
+ }
+ if (r->type->kind != TYPEPOINTER)
+ error(loc, "invalid operands to '%s' operator", tokstr[op]);
+ if (l->type->base->kind == TYPEVOID)
+ e = l, l = r, r = e;
+ if (r->type->base->kind == TYPEVOID && l->type->base->kind != TYPEFUNC)
+ r = exprconvert(r, l->type);
+ else if (!typecompatible(l->type->base, r->type->base))
+ error(loc, "pointer operands to '%s' operator are to incompatible types", tokstr[op]);
+ break;
case TLESS:
case TGREATER:
case TLEQ:
case TGEQ:
- if (lp & PROPARITH && rp & PROPARITH) {
+ t = &typeint;
+ if (lp & PROPREAL && rp & PROPREAL) {
commonreal(&l, &r);
+ } else if (l->type->kind == TYPEPOINTER && r->type->kind == TYPEPOINTER) {
+ if (!typecompatible(l->type->base, r->type->base) || l->type->base->kind == TYPEFUNC)
+ error(loc, "pointer operands to '%s' operator must be to compatible object types", tokstr[op]);
} else {
- // XXX: check pointer types
+ error(loc, "invalid operands to '%s' operator", tokstr[op]);
}
- t = &typeint;
break;
case TBOR:
case TXOR:
@@ -959,16 +998,6 @@ binaryexpr(struct scope *s, struct expr *l, int i)
return l;
}
-static bool
-nullpointer(struct expr *e)
-{
- if (e->kind != EXPRCONST)
- return false;
- if (!(e->type->prop & PROPINT) && (e->type->kind != TYPEPOINTER || e->type->base != &typevoid))
- return false;
- return e->constant.i == 0;
-}
-
static struct expr *
condexpr(struct scope *s)
{