From f67a34503489f74fce416ce4447f291534c21f8f Mon Sep 17 00:00:00 2001 From: Michael Forney Date: Mon, 18 Feb 2019 23:25:36 -0800 Subject: Pointer operands to + and - must be complete object types Also clean up a little and give some better error messages. --- expr.c | 37 +++++++++++++++++++++++-------------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/expr.c b/expr.c index 1c0f4ff..11d6fbe 100644 --- a/expr.c +++ b/expr.c @@ -310,28 +310,37 @@ mkbinaryexpr(struct location *loc, enum tokenkind op, struct expression *l, stru case TADD: if (lp & PROPARITH && rp & PROPARITH) { t = commonreal(&l, &r); - } else if (l->type->kind == TYPEPOINTER && rp & PROPINT) { - t = l->type; - r = mkbinaryexpr(loc, TMUL, exprconvert(r, &typeulong), mkconstexpr(&typeulong, t->base->size)); - } else if (lp & PROPINT && r->type->kind == TYPEPOINTER) { - t = r->type; - l = mkbinaryexpr(loc, TMUL, exprconvert(l, &typeulong), mkconstexpr(&typeulong, t->base->size)); - } else { - error(loc, "invalid operands to '+' operator"); + break; } + if (r->type->kind == TYPEPOINTER) + e = l, l = r, r = e; + if (l->type->kind != TYPEPOINTER || !(rp & PROPINT)) + error(loc, "invalid operands to '+' operator"); + t = l->type; + if (t->base->incomplete) + error(loc, "pointer operand to '+' must be to complete object type"); + r = mkbinaryexpr(loc, TMUL, exprconvert(r, &typeulong), mkconstexpr(&typeulong, t->base->size)); break; case TSUB: if (lp & PROPARITH && rp & PROPARITH) { t = commonreal(&l, &r); - } else if (l->type->kind == TYPEPOINTER && rp & PROPINT) { + break; + } + if (l->type->kind != TYPEPOINTER || !(rp & PROPINT) && r->type->kind != TYPEPOINTER) + error(loc, "invalid operands to '-' operator"); + if (l->type->base->incomplete) + error(loc, "pointer operand to '-' must be to complete object type"); + if (rp & PROPINT) { t = l->type; r = mkbinaryexpr(loc, TMUL, exprconvert(r, &typeulong), mkconstexpr(&typeulong, t->base->size)); - } else if (l->type->kind == TYPEPOINTER && r->type->kind == TYPEPOINTER && typecompatible(typeunqual(l->type->base, NULL), typeunqual(r->type->base, NULL))) { - /* XXX: when is the appropriate place to convert to signed integer */ - e = mkbinaryexpr(loc, TSUB, exprconvert(l, &typelong), exprconvert(r, &typelong)); - return mkbinaryexpr(loc, TDIV, e, mkconstexpr(&typelong, l->type->base->size)); } else { - error(loc, "invalid operands to '-' operator"); + if (!typecompatible(typeunqual(l->type->base, NULL), typeunqual(r->type->base, NULL))) + error(&tok.loc, "pointer operands to '-' are to incompatible types"); + op = TDIV; + t = &typelong; + e = mkbinaryexpr(loc, TSUB, exprconvert(l, &typelong), exprconvert(r, &typelong)); + r = mkconstexpr(&typelong, l->type->base->size); + l = e; } break; case TMOD: -- cgit v1.2.3