diff options
-rw-r--r-- | cc.h | 7 | ||||
-rw-r--r-- | eval.c | 20 | ||||
-rw-r--r-- | expr.c | 8 | ||||
-rw-r--r-- | qbe.c | 2 | ||||
-rw-r--r-- | test/conditional-compound-literal.c | 4 | ||||
-rw-r--r-- | test/conditional-compound-literal.qbe | 25 |
6 files changed, 52 insertions, 14 deletions
@@ -442,7 +442,12 @@ struct expr *exprpromote(struct expr *); /* eval */ -struct expr *eval(struct expr *); +enum evalkind { + EVALARITH, /* arithmetic constant expression */ + EVALINIT, /* initializer constant expression */ +}; + +struct expr *eval(struct expr *, enum evalkind); /* init */ @@ -87,7 +87,7 @@ binary(struct expr *expr, enum tokenkind op, struct expr *l, struct expr *r) #undef S struct expr * -eval(struct expr *expr) +eval(struct expr *expr, enum evalkind kind) { struct expr *l, *r, *c; struct decl *d; @@ -100,6 +100,8 @@ eval(struct expr *expr) expr->constant.i = intconstvalue(expr->ident.decl->value); break; case EXPRCOMPOUND: + if (kind != EVALINIT) + break; d = mkdecl(DECLOBJECT, expr->type, expr->qual, LINKNONE); d->value = mkglobal(NULL, true); emitdata(d, expr->compound.init); @@ -107,13 +109,15 @@ eval(struct expr *expr) expr->ident.decl = d; break; case EXPRUNARY: - l = eval(expr->base); + if (kind != EVALINIT) + break; + l = eval(expr->base, kind); if (expr->op != TBAND) break; switch (l->kind) { case EXPRUNARY: if (l->op == TMUL) - expr = eval(l->base); + expr = eval(l->base, kind); break; case EXPRSTRING: l->ident.decl = stringdecl(l); @@ -123,7 +127,7 @@ eval(struct expr *expr) } break; case EXPRCAST: - l = eval(expr->base); + l = eval(expr->base, kind); if (l->kind == EXPRCONST) { expr->kind = EXPRCONST; if (l->type->prop & PROPINT && expr->type->prop & PROPFLOAT) @@ -138,8 +142,8 @@ eval(struct expr *expr) } break; case EXPRBINARY: - l = eval(expr->binary.l); - r = eval(expr->binary.r); + l = eval(expr->binary.l, kind); + r = eval(expr->binary.r, kind); expr->binary.l = l; expr->binary.r = r; switch (expr->op) { @@ -176,10 +180,10 @@ eval(struct expr *expr) case EXPRCOND: l = expr->cond.t; r = expr->cond.f; - c = eval(expr->base); + c = eval(expr->base, kind); if (c->kind != EXPRCONST) break; - return eval(c->constant.i ? l : r); + return eval(c->constant.i ? l : r, kind); } return expr; @@ -557,7 +557,7 @@ builtinfunc(struct scope *s, enum builtinkind kind) e->base = exprconvert(assignexpr(s), &typeulong); break; case BUILTINCONSTANTP: - e = mkconstexpr(&typeint, eval(condexpr(s))->kind == EXPRCONST); + e = mkconstexpr(&typeint, eval(condexpr(s), EVALARITH)->kind == EXPRCONST); break; case BUILTININFF: e = mkexpr(EXPRCONST, &typefloat); @@ -969,8 +969,8 @@ condexpr(struct scope *s) } else if (t == &typevoid && f == &typevoid) { e->type = &typevoid; } else { - e->cond.t = eval(e->cond.t); - e->cond.f = eval(e->cond.f); + e->cond.t = eval(e->cond.t, EVALARITH); + e->cond.f = eval(e->cond.f, EVALARITH); if (nullpointer(e->cond.t) && f->kind == TYPEPOINTER) { e->type = f; } else if (nullpointer(e->cond.f) && t->kind == TYPEPOINTER) { @@ -998,7 +998,7 @@ condexpr(struct scope *s) struct expr * constexpr(struct scope *s) { - return eval(condexpr(s)); + return eval(condexpr(s), EVALARITH); } uint64_t @@ -1269,7 +1269,7 @@ emitdata(struct decl *d, struct init *init) else if (d->align < d->type->align) error(&tok.loc, "object requires alignment %d, which is stricter than %d", d->type->align, d->align); for (cur = init; cur; cur = cur->next) - cur->expr = eval(cur->expr); + cur->expr = eval(cur->expr, EVALINIT); if (d->linkage == LINKEXTERN) fputs("export ", stdout); fputs("data ", stdout); diff --git a/test/conditional-compound-literal.c b/test/conditional-compound-literal.c new file mode 100644 index 0000000..33a5416 --- /dev/null +++ b/test/conditional-compound-literal.c @@ -0,0 +1,4 @@ +int main(void) { + int x = 0, *p = 0 ? 0 : &(int){x}; + return *p; +} diff --git a/test/conditional-compound-literal.qbe b/test/conditional-compound-literal.qbe new file mode 100644 index 0000000..9e9c5f7 --- /dev/null +++ b/test/conditional-compound-literal.qbe @@ -0,0 +1,25 @@ +export +function w $main() { +@start.1 + %.1 =l alloc4 4 + %.3 =l alloc8 8 + %.6 =l alloc4 4 +@body.2 + %.2 =l add %.1, 0 + storew 0, %.2 + %.4 =l add %.3, 0 + %.5 =w cnew 0, 0 + jnz %.5, @cond_true.3, @cond_false.4 +@cond_true.3 + jmp @cond_join.5 +@cond_false.4 + %.7 =l add %.6, 0 + %.8 =w loadsw %.1 + storew %.8, %.7 +@cond_join.5 + %.9 =l phi @cond_true.3 0, @cond_false.4 %.6 + storel %.9, %.4 + %.10 =l loadl %.3 + %.11 =w loadsw %.10 + ret %.11 +} |