diff options
Diffstat (limited to 'stmt.c')
-rw-r--r-- | stmt.c | 29 |
1 files changed, 25 insertions, 4 deletions
@@ -24,6 +24,27 @@ gotolabel(struct func *f) return true; } +/* controlling expression of loops and if-statements */ +static struct expr * +ctrlexpr(struct scope *s) +{ + struct expr *e; + struct type *t; + + e = expr(s); + t = e->type; + if (!(t->prop & PROPSCALAR)) + error(&tok.loc, "controlling expression must have scalar type"); + /* + Ideally we would just do this conversion unconditionally, + but QBE is not currently able to optimize the conversion + away for int. + */ + if (t->prop & PROPFLOAT || t->size > 4) + e = exprconvert(e, &typebool); + return e; +} + /* 6.8 Statements and blocks */ void stmt(struct func *f, struct scope *s) @@ -91,7 +112,7 @@ stmt(struct func *f, struct scope *s) next(); s = mkscope(s); expect(TLPAREN, "after 'if'"); - e = exprconvert(expr(s), &typebool); + e = ctrlexpr(s); v = funcexpr(f, e); delexpr(e); expect(TRPAREN, "after expression"); @@ -154,7 +175,7 @@ stmt(struct func *f, struct scope *s) next(); s = mkscope(s); expect(TLPAREN, "after 'while'"); - e = exprconvert(expr(s), &typebool); + e = ctrlexpr(s); expect(TRPAREN, "after expression"); label[0] = mkblock("while_cond"); @@ -192,7 +213,7 @@ stmt(struct func *f, struct scope *s) expect(TWHILE, "after 'do' statement"); expect(TLPAREN, "after 'while'"); funclabel(f, label[1]); - e = exprconvert(expr(s), &typebool); + e = ctrlexpr(s); expect(TRPAREN, "after expression"); v = funcexpr(f, e); @@ -221,7 +242,7 @@ stmt(struct func *f, struct scope *s) funclabel(f, label[0]); if (tok.kind != TSEMICOLON) { - e = exprconvert(expr(s), &typebool); + e = ctrlexpr(s); v = funcexpr(f, e); funcjnz(f, v, label[1], label[3]); delexpr(e); |