diff options
-rw-r--r-- | cc.h | 7 | ||||
-rw-r--r-- | expr.c | 42 | ||||
-rw-r--r-- | init.c | 2 |
3 files changed, 23 insertions, 28 deletions
@@ -294,14 +294,9 @@ enum exprkind { EXPRTEMP, }; -enum exprflags { - EXPRFLAG_LVAL = 1<<0, - EXPRFLAG_DECAYED = 1<<1, -}; - struct expr { enum exprkind kind; - enum exprflags flags; + _Bool lvalue, decayed; struct type *type; struct expr *next; union { @@ -11,13 +11,14 @@ #include "cc.h" static struct expr * -mkexpr(enum exprkind k, struct type *t, enum exprflags flags) +mkexpr(enum exprkind k, struct type *t, bool lvalue) { struct expr *e; e = xmalloc(sizeof(*e)); - e->type = flags & EXPRFLAG_LVAL || !t ? t : typeunqual(t, NULL); - e->flags = flags; + e->type = lvalue || !t ? t : typeunqual(t, NULL); + e->lvalue = lvalue; + e->decayed = false; e->kind = k; e->next = NULL; @@ -56,11 +57,11 @@ decay(struct expr *e) case TYPEARRAY: e = mkunaryexpr(TBAND, e); e->type = mkqualifiedtype(mkpointertype(t->base), tq); - e->flags |= EXPRFLAG_DECAYED; + e->decayed = true; break; case TYPEFUNC: e = mkunaryexpr(TBAND, e); - e->flags |= EXPRFLAG_DECAYED; + e->decayed = true; break; } @@ -71,7 +72,7 @@ static void lvalueconvert(struct expr *e) { e->type = typeunqual(e->type, NULL); - e->flags &= ~EXPRFLAG_LVAL; + e->lvalue = false; } static struct expr * @@ -81,8 +82,8 @@ mkunaryexpr(enum tokenkind op, struct expr *base) switch (op) { case TBAND: - if (base->flags & EXPRFLAG_DECAYED) { - base->flags &= ~EXPRFLAG_DECAYED; + if (base->decayed) { + base->decayed = false; return base; } expr = mkexpr(EXPRUNARY, mkpointertype(base->type), 0); @@ -93,7 +94,7 @@ mkunaryexpr(enum tokenkind op, struct expr *base) lvalueconvert(base); if (base->type->kind != TYPEPOINTER) error(&tok.loc, "cannot dereference non-pointer"); - expr = mkexpr(EXPRUNARY, base->type->base, EXPRFLAG_LVAL); + expr = mkexpr(EXPRUNARY, base->type->base, true); expr->unary.op = op; expr->unary.base = base; return decay(expr); @@ -316,14 +317,14 @@ primaryexpr(struct scope *s) d = scopegetdecl(s, tok.lit, 1); if (!d) error(&tok.loc, "undeclared identifier: %s", tok.lit); - e = mkexpr(EXPRIDENT, d->type, d->kind == DECLOBJECT ? EXPRFLAG_LVAL : 0); + e = mkexpr(EXPRIDENT, d->type, d->kind == DECLOBJECT); e->ident.decl = d; if (d->kind != DECLBUILTIN) e = decay(e); next(); break; case TSTRINGLIT: - e = mkexpr(EXPRSTRING, mkarraytype(&typechar, 0), EXPRFLAG_LVAL); + e = mkexpr(EXPRSTRING, mkarraytype(&typechar, 0), true); e->string.size = 0; e->string.data = NULL; do { @@ -418,7 +419,7 @@ builtinfunc(struct scope *s, enum builtinkind kind) break; case BUILTINNANF: e = assignexpr(s); - if (!(e->flags & EXPRFLAG_DECAYED) || e->unary.base->kind != EXPRSTRING || e->unary.base->string.size > 0) + if (!e->decayed || e->unary.base->kind != EXPRSTRING || e->unary.base->string.size > 0) error(&tok.loc, "__builtin_nanf currently only supports empty string literals"); e = mkexpr(EXPRCONST, &typefloat, 0); /* TODO: use NAN here when we can handle musl's math.h */ @@ -560,7 +561,7 @@ postfixexpr(struct scope *s, struct expr *r) next(); if (tok.kind != TIDENT) error(&tok.loc, "expected identifier after '->' operator"); - lvalue = op == TARROW || r->unary.base->flags & EXPRFLAG_LVAL; + lvalue = op == TARROW || r->unary.base->lvalue; r = exprconvert(r, mkpointertype(&typechar)); offset = 0; m = typemember(t, tok.lit, &offset); @@ -571,8 +572,7 @@ postfixexpr(struct scope *s, struct expr *r) r = mkbinaryexpr(&tok.loc, TADD, r, mkconstexpr(&typeulong, offset)); r = exprconvert(r, mkpointertype(mkqualifiedtype(m->type, tq))); e = mkunaryexpr(TMUL, r); - if (!lvalue) - e->flags &= ~EXPRFLAG_LVAL; + e->lvalue = lvalue; next(); break; case TINC: @@ -605,7 +605,7 @@ unaryexpr(struct scope *s) case TDEC: next(); l = unaryexpr(s); - if (!(l->flags & EXPRFLAG_LVAL)) + if (!l->lvalue) error(&tok.loc, "operand of %srement operator must be an lvalue", op == TINC ? "inc" : "dec"); /* if (l->qualifiers & QUALCONST) @@ -663,13 +663,13 @@ unaryexpr(struct scope *s) expect(TRPAREN, "after expression"); if (op == TSIZEOF) e = postfixexpr(s, e); - if (e->flags & EXPRFLAG_DECAYED) + if (e->decayed) e = e->unary.base; t = e->type; } } else if (op == TSIZEOF) { e = unaryexpr(s); - if (e->flags & EXPRFLAG_DECAYED) + if (e->decayed) e = e->unary.base; t = e->type; } else { @@ -701,7 +701,7 @@ castexpr(struct scope *s) } expect(TRPAREN, "after type name"); if (tok.kind == TLBRACE) { - e = mkexpr(EXPRCOMPOUND, t, EXPRFLAG_LVAL); + e = mkexpr(EXPRCOMPOUND, t, true); e->compound.init = parseinit(s, t); e = decay(e); *end = postfixexpr(s, e); @@ -864,14 +864,14 @@ assignexpr(struct scope *s) default: return l; } - if (!(l->flags & EXPRFLAG_LVAL)) + if (!l->lvalue) 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), EXPRFLAG_LVAL); + tmp = mkexpr(EXPRTEMP, mkpointertype(l->type), true); tmp->temp = NULL; e = mkexpr(EXPRCOMMA, l->type, 0); e->comma.exprs = mkexpr(EXPRASSIGN, tmp->type, 0); @@ -236,7 +236,7 @@ parseinit(struct scope *s, struct type *t) t = p.sub->type; switch (t->kind) { case TYPEARRAY: - if (expr->flags & EXPRFLAG_DECAYED && expr->unary.base->kind == EXPRSTRING) { + if (expr->decayed && expr->unary.base->kind == EXPRSTRING) { expr = expr->unary.base; base = typeunqual(t->base, NULL); /* XXX: wide string literals */ |