aboutsummaryrefslogtreecommitdiff
path: root/expr.c
diff options
context:
space:
mode:
authorMichael Forney <mforney@mforney.org>2019-02-18 23:25:36 -0800
committerMichael Forney <mforney@mforney.org>2019-02-18 23:25:36 -0800
commitf67a34503489f74fce416ce4447f291534c21f8f (patch)
tree72ef31ff443b08943eee8e36834f84bb05fde173 /expr.c
parent8c3315e5119452b48978abaf955deaabdfd015de (diff)
Pointer operands to + and - must be complete object types
Also clean up a little and give some better error messages.
Diffstat (limited to 'expr.c')
-rw-r--r--expr.c37
1 files 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: