cproc

Unnamed repository; edit this file 'description' to name the repository.
git clone git://git.nihaljere.xyz/cproc
Log | Files | Refs | Submodules | README | LICENSE

commit 0d1969024c6fd7fa9aa729cf17860d0c172b56e0
parent e506961aabd683bfb54357c00f8150984bd0690f
Author: Michael Forney <mforney@mforney.org>
Date:   Mon, 12 Aug 2019 01:53:46 -0700

Revert "expr: Fix cast of same type"

This reverts commit 1a38a5fc4844a0de8729be694a62ba0afce3ff52.

This breaks comparisons bitfields in some cases, for instance

	extern struct {unsigned x:31;} s;
	int main(void) {
		return (unsigned)s.x - 1 < 0;
	}

If we discard the cast, then it is a signed comparison because of integer
promotion for bit-fields, otherwise it is an unsigned comparison.

Additionally, the test case this was meant to fix is not actually ISO C,
since casts must be to scalar types or `void`.

Diffstat:
Mexpr.c | 40+++++++++++++++++++---------------------
Dtest/cast-same-type.qbe | 12------------
2 files changed, 19 insertions(+), 33 deletions(-)

diff --git a/expr.c b/expr.c @@ -866,40 +866,38 @@ unaryexpr(struct scope *s) static struct expr * castexpr(struct scope *s) { - struct type *t, *prev = NULL; + struct type *t; enum typequal tq; - struct expr *result, *base = NULL, **end = &result; + struct expr *r, *e, **end; + end = &r; while (consume(TLPAREN)) { tq = QUALNONE; t = typename(s, &tq); if (!t) { - base = expr(s); + e = expr(s); expect(TRPAREN, "after expression to match '('"); - base = postfixexpr(s, base); - break; + *end = postfixexpr(s, e); + return r; } expect(TRPAREN, "after type name"); if (tok.kind == TLBRACE) { - base = mkexpr(EXPRCOMPOUND, t); - base->qual = tq; - base->lvalue = true; - base->compound.init = parseinit(s, t); - base = postfixexpr(s, decay(base)); - break; - } - if (prev && !typecompatible(prev, t)) { - *end = mkexpr(EXPRCAST, prev); - // XXX check types 6.5.4 - end = &(*end)->base; + e = mkexpr(EXPRCOMPOUND, t); + e->qual = tq; + e->lvalue = true; + e->compound.init = parseinit(s, t); + e = decay(e); + *end = postfixexpr(s, e); + return r; } - prev = t; + e = mkexpr(EXPRCAST, t); + // XXX check types 6.5.4 + *end = e; + end = &e->base; } - if (!base) - base = unaryexpr(s); - *end = prev ? exprconvert(base, prev) : base; + *end = unaryexpr(s); - return result; + return r; } static int diff --git a/test/cast-same-type.qbe b/test/cast-same-type.qbe @@ -1,12 +0,0 @@ -export -function w $main() { -@start.1 -@body.2 - %.1 =l copy $s - %.2 =l mul 0, 1 - %.3 =l add %.1, %.2 - %.4 =l copy %.3 - %.5 =w loadsw %.4 - ret %.5 -} -export data $s = align 4 { z 4 }