cproc

Unnamed repository; edit this file 'description' to name the repository.
git clone git://git.nihaljere.xyz/cproc
Log | Files | Refs | Submodules | README | LICENSE

commit 65290cc659feafddf5881ec34a3b5e7987dfb07f
parent 0bb7273d42117585aeeda4610267158fcea494a6
Author: Michael Forney <mforney@mforney.org>
Date:   Sat,  4 Apr 2020 19:21:32 -0700

expr: Add type checking for equality and relational expressions

Diffstat:
Mexpr.c | 55++++++++++++++++++++++++++++++++++++++++++-------------
1 file changed, 42 insertions(+), 13 deletions(-)

diff --git 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) {