diff options
-rw-r--r-- | cc.h | 8 | ||||
-rw-r--r-- | eval.c | 2 | ||||
-rw-r--r-- | expr.c | 36 | ||||
-rw-r--r-- | qbe.c | 22 | ||||
-rw-r--r-- | stmt.c | 5 |
5 files changed, 28 insertions, 45 deletions
@@ -296,8 +296,14 @@ enum exprkind { struct expr { enum exprkind kind; - _Bool lvalue, decayed; + /* whether this expression is an lvalue */ + _Bool lvalue; + /* whether this expression is a pointer decayed from an array or function designator */ + _Bool decayed; + /* the unqualified type of the expression */ struct type *type; + /* the type qualifiers of the object this expression refers to (ignored for non-lvalues) */ + enum typequal qual; struct expr *next; union { struct { @@ -78,7 +78,7 @@ eval(struct expr *expr) expr->constant.i = intconstvalue(expr->ident.decl->value); break; case EXPRCOMPOUND: - d = mkdecl(DECLOBJECT, expr->type, LINKNONE); + d = mkdecl(DECLOBJECT, mkqualifiedtype(expr->type, expr->qual), LINKNONE); d->value = mkglobal(NULL, true); emitdata(d, expr->compound.init); expr->kind = EXPRIDENT; @@ -16,7 +16,8 @@ mkexpr(enum exprkind k, struct type *t) struct expr *e; e = xmalloc(sizeof(*e)); - e->type = t; + e->qual = QUALNONE; + e->type = t ? typeunqual(t, &e->qual) : NULL; e->lvalue = false; e->decayed = false; e->kind = k; @@ -49,14 +50,16 @@ static struct expr * decay(struct expr *e) { struct type *t; - enum typequal tq = QUALNONE; + enum typequal tq; // XXX: combine with decl.c:adjust in some way? - t = typeunqual(e->type, &tq); + t = e->type; + tq = e->qual; switch (t->kind) { case TYPEARRAY: e = mkunaryexpr(TBAND, e); - e->type = mkqualifiedtype(mkpointertype(t->base), tq); + e->type = mkpointertype(t->base); + e->qual = tq; e->decayed = true; break; case TYPEFUNC: @@ -68,13 +71,6 @@ decay(struct expr *e) return e; } -static void -lvalueconvert(struct expr *e) -{ - e->type = typeunqual(e->type, NULL); - e->lvalue = false; -} - static struct expr * mkunaryexpr(enum tokenkind op, struct expr *base) { @@ -86,12 +82,11 @@ mkunaryexpr(enum tokenkind op, struct expr *base) base->decayed = false; return base; } - expr = mkexpr(EXPRUNARY, mkpointertype(base->type)); + expr = mkexpr(EXPRUNARY, mkpointertype(mkqualifiedtype(base->type, base->qual))); expr->unary.op = op; expr->unary.base = base; return expr; case TMUL: - lvalueconvert(base); if (base->type->kind != TYPEPOINTER) error(&tok.loc, "cannot dereference non-pointer"); expr = mkexpr(EXPRUNARY, base->type->base); @@ -123,8 +118,6 @@ mkbinaryexpr(struct location *loc, enum tokenkind op, struct expr *l, struct exp struct type *t = NULL; enum typeprop lp, rp; - lvalueconvert(l); - lvalueconvert(r); lp = typeprop(l->type); rp = typeprop(r->type); switch (op) { @@ -446,6 +439,7 @@ builtinfunc(struct scope *s, enum builtinkind kind) e->builtin.arg = exprconvert(assignexpr(s), &typevalistptr); expect(TCOMMA, "after va_list"); e->type = typename(s); + typeunqual(e->type, &e->qual); break; case BUILTINVACOPY: e = mkexpr(EXPRASSIGN, typevalist.base); @@ -493,8 +487,6 @@ postfixexpr(struct scope *s, struct expr *r) next(); arr = r; idx = expr(s); - lvalueconvert(arr); - lvalueconvert(idx); if (arr->type->kind != TYPEPOINTER) { if (idx->type->kind != TYPEPOINTER) error(&tok.loc, "either array or index must be pointer type"); @@ -516,7 +508,6 @@ postfixexpr(struct scope *s, struct expr *r) expect(TRPAREN, "after builtin parameters"); break; } - lvalueconvert(r); if (r->type->kind != TYPEPOINTER || r->type->base->kind != TYPEFUNC) error(&tok.loc, "called object is not a function"); t = r->type->base; @@ -534,7 +525,6 @@ postfixexpr(struct scope *s, struct expr *r) if (!p && !t->func.isvararg && t->func.paraminfo) error(&tok.loc, "too many arguments for function call"); *end = assignexpr(s); - lvalueconvert(*end); if (!t->func.isprototype || (t->func.isvararg && !p)) *end = exprconvert(*end, typeargpromote((*end)->type)); else @@ -554,7 +544,6 @@ postfixexpr(struct scope *s, struct expr *r) /* fallthrough */ case TARROW: op = tok.kind; - lvalueconvert(r); if (r->type->kind != TYPEPOINTER) error(&tok.loc, "arrow operator must be applied to pointer to struct/union"); tq = QUALNONE; @@ -626,27 +615,23 @@ unaryexpr(struct scope *s) case TADD: next(); e = castexpr(s); - lvalueconvert(e); e = exprconvert(e, typeintpromote(e->type)); break; case TSUB: next(); e = castexpr(s); - lvalueconvert(e); e = exprconvert(e, typeintpromote(e->type)); e = mkbinaryexpr(&tok.loc, TSUB, mkconstexpr(&typeint, 0), e); break; case TBNOT: next(); e = castexpr(s); - lvalueconvert(e); e = exprconvert(e, typeintpromote(e->type)); e = mkbinaryexpr(&tok.loc, TXOR, e, mkconstexpr(e->type, -1)); break; case TLNOT: next(); e = castexpr(s); - lvalueconvert(e); if (!(typeprop(e->type) & PROPSCALAR)) error(&tok.loc, "operator '!' must have scalar operand"); e = mkbinaryexpr(&tok.loc, TEQL, e, mkconstexpr(&typeint, 0)); @@ -794,8 +779,6 @@ condexpr(struct scope *s) e->cond.t = expr(s); expect(TCOLON, "in conditional expression"); e->cond.f = condexpr(s); - lvalueconvert(e->cond.t); - lvalueconvert(e->cond.f); t = e->cond.t->type; f = e->cond.f->type; if (t == f) { @@ -872,7 +855,6 @@ assignexpr(struct scope *s) error(&tok.loc, "left side of assignment expression is not an lvalue"); next(); r = assignexpr(s); - lvalueconvert(r); if (op) { /* rewrite `E1 OP= E2` as `T = &E1, *T = *T OP E2`, where T is a temporary slot */ tmp = mkexpr(EXPRTEMP, mkpointertype(l->type)); @@ -234,12 +234,10 @@ funcalloc(struct func *f, struct decl *d) } static void -funcstore(struct func *f, struct type *t, struct value *addr, struct value *v) +funcstore(struct func *f, struct type *t, enum typequal tq, struct value *addr, struct value *v) { enum instkind op; - enum typequal tq = QUALNONE; - t = typeunqual(t, &tq); if (tq & QUALVOLATILE) error(&tok.loc, "volatile store is not yet supported"); if (tq & QUALCONST) @@ -295,9 +293,7 @@ funcload(struct func *f, struct type *t, struct value *addr) { struct value *v; enum instkind op; - enum typequal tq; - t = typeunqual(t, &tq); switch (t->kind) { case TYPEBASIC: switch (t->size) { @@ -377,7 +373,7 @@ mkfunc(char *name, struct type *t, struct scope *s) d->value->repr = &iptr; } else { funcinit(f, d, NULL); - funcstore(f, typeunqual(p->type, NULL), d->value, p->value); + funcstore(f, typeunqual(p->type, NULL), QUALNONE, d->value, p->value); } scopeputdecl(s, p->name, d); } @@ -473,7 +469,7 @@ objectaddr(struct func *f, struct expr *e) d = stringdecl(e); return d->value; case EXPRCOMPOUND: - d = mkdecl(DECLOBJECT, e->type, LINKNONE); + d = mkdecl(DECLOBJECT, mkqualifiedtype(e->type, e->qual), LINKNONE); funcinit(f, d, e->compound.init); return d->value; case EXPRUNARY: @@ -582,7 +578,7 @@ funcexpr(struct func *f, struct expr *e) case EXPRIDENT: d = e->ident.decl; switch (d->kind) { - case DECLOBJECT: return funcload(f, d->type, d->value); + case DECLOBJECT: return funcload(f, typeunqual(d->type, NULL), d->value); case DECLCONST: return d->value; default: fatal("unimplemented declaration kind %d", d->kind); @@ -607,7 +603,7 @@ funcexpr(struct func *f, struct expr *e) else fatal("not a scalar"); v = funcinst(f, e->incdec.op == TINC ? IADD : ISUB, e->type->repr, l, r); - funcstore(f, e->type, addr, v); + funcstore(f, e->type, e->qual, addr, v); return e->incdec.post ? l : v; case EXPRCALL: argvals = xreallocarray(NULL, e->call.nargs + 3, sizeof(argvals[0])); @@ -639,10 +635,10 @@ funcexpr(struct func *f, struct expr *e) l = funcexpr(f, e->cast.e); r = NULL; - src = typeunqual(e->cast.e->type, NULL); + src = e->cast.e->type; if (src->kind == TYPEPOINTER) src = &typeulong; - dst = typeunqual(e->type, NULL); + dst = e->type; if (dst->kind == TYPEPOINTER) dst = &typeulong; if (dst->kind == TYPEVOID) @@ -823,7 +819,7 @@ funcexpr(struct func *f, struct expr *e) e->assign.l->temp = r; } else { l = objectaddr(f, e->assign.l); - funcstore(f, e->assign.l->type, l, r); + funcstore(f, e->assign.l->type, e->assign.l->qual, l, r); } return r; case EXPRCOMMA: @@ -902,7 +898,7 @@ funcinit(struct func *func, struct decl *d, struct init *init) } else { dst = funcinst(func, IADD, &iptr, d->value, mkintconst(&iptr, init->start)); src = funcexpr(func, init->expr); - funcstore(func, init->expr->type, dst, src); + funcstore(func, init->expr->type, QUALNONE, dst, src); offset = init->end; } if (max < offset) @@ -125,10 +125,9 @@ stmt(struct func *f, struct scope *s) e = expr(s); expect(TRPAREN, "after expression"); - t = typeunqual(e->type, NULL); - if (!(typeprop(t) & PROPINT)) + if (!(typeprop(e->type) & PROPINT)) error(&tok.loc, "controlling expression of switch statement must have integer type"); - e = exprconvert(e, typeintpromote(t)); + e = exprconvert(e, typeintpromote(e->type)); label[0] = mkblock("switch_cond"); label[1] = mkblock("switch_join"); |