aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cc.h8
-rw-r--r--eval.c2
-rw-r--r--expr.c36
-rw-r--r--qbe.c22
-rw-r--r--stmt.c5
5 files changed, 28 insertions, 45 deletions
diff --git a/cc.h b/cc.h
index 511ad41..85b50b5 100644
--- a/cc.h
+++ b/cc.h
@@ -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 {
diff --git a/eval.c b/eval.c
index 209441d..46dfd5c 100644
--- a/eval.c
+++ b/eval.c
@@ -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;
diff --git a/expr.c b/expr.c
index 7f850c8..c973666 100644
--- a/expr.c
+++ b/expr.c
@@ -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));
diff --git a/qbe.c b/qbe.c
index bb223c2..4f6b7a1 100644
--- a/qbe.c
+++ b/qbe.c
@@ -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)
diff --git a/stmt.c b/stmt.c
index 73e391c..f10bfb2 100644
--- a/stmt.c
+++ b/stmt.c
@@ -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");