diff options
| author | Michael Forney <mforney@mforney.org> | 2019-04-05 14:13:29 -0700 | 
|---|---|---|
| committer | Michael Forney <mforney@mforney.org> | 2019-04-06 12:01:37 -0700 | 
| commit | 7e5a07cfff793e5656d9868cae9cc5281f92e0d0 (patch) | |
| tree | 762a99ff7cb5a8c5b52dc33af7ced2005955370d | |
| parent | 2f19124e5a36e4cd796841238dadfb8750789f78 (diff) | |
| download | cproc-7e5a07cfff793e5656d9868cae9cc5281f92e0d0.tar.xz | |
Separate unqualified type and qualifiers in struct expr
| -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"); | 
