aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--expr.c40
-rw-r--r--test/cast-same-type.c4
-rw-r--r--test/cast-same-type.qbe12
3 files changed, 37 insertions, 19 deletions
diff --git a/expr.c b/expr.c
index 171c239..2879efe 100644
--- a/expr.c
+++ b/expr.c
@@ -866,38 +866,40 @@ unaryexpr(struct scope *s)
static struct expr *
castexpr(struct scope *s)
{
- struct type *t;
+ struct type *t, *prev = NULL;
enum typequal tq;
- struct expr *r, *e, **end;
+ struct expr *result, *base = NULL, **end = &result;
- end = &r;
while (consume(TLPAREN)) {
tq = QUALNONE;
t = typename(s, &tq);
if (!t) {
- e = expr(s);
+ base = expr(s);
expect(TRPAREN, "after expression to match '('");
- *end = postfixexpr(s, e);
- return r;
+ base = postfixexpr(s, base);
+ break;
}
expect(TRPAREN, "after type name");
if (tok.kind == TLBRACE) {
- 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;
+ base = mkexpr(EXPRCOMPOUND, t);
+ base->qual = tq;
+ base->lvalue = true;
+ base->compound.init = parseinit(s, t);
+ base = postfixexpr(s, decay(base));
+ break;
}
- e = mkexpr(EXPRCAST, t);
- // XXX check types 6.5.4
- *end = e;
- end = &e->base;
+ if (prev && !typecompatible(prev, t)) {
+ *end = mkexpr(EXPRCAST, prev);
+ // XXX check types 6.5.4
+ end = &(*end)->base;
+ }
+ prev = t;
}
- *end = unaryexpr(s);
+ if (!base)
+ base = unaryexpr(s);
+ *end = prev ? exprconvert(base, prev) : base;
- return r;
+ return result;
}
static int
diff --git a/test/cast-same-type.c b/test/cast-same-type.c
new file mode 100644
index 0000000..5602057
--- /dev/null
+++ b/test/cast-same-type.c
@@ -0,0 +1,4 @@
+struct S {int x;} s;
+int main(void) {
+ return ((struct S)s).x;
+}
diff --git a/test/cast-same-type.qbe b/test/cast-same-type.qbe
new file mode 100644
index 0000000..625f937
--- /dev/null
+++ b/test/cast-same-type.qbe
@@ -0,0 +1,12 @@
+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 }