aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--expr.c4
-rw-r--r--tests/lvalue-conversion.c6
-rw-r--r--tests/lvalue-conversion.qbe14
-rw-r--r--type.c2
4 files changed, 26 insertions, 0 deletions
diff --git a/expr.c b/expr.c
index aad7cbc..46d81e8 100644
--- a/expr.c
+++ b/expr.c
@@ -473,6 +473,7 @@ postfixexpr(struct scope *s, struct expression *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
@@ -585,17 +586,20 @@ 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;
diff --git a/tests/lvalue-conversion.c b/tests/lvalue-conversion.c
new file mode 100644
index 0000000..6bbc326
--- /dev/null
+++ b/tests/lvalue-conversion.c
@@ -0,0 +1,6 @@
+void g();
+void f(void) {
+ static const unsigned char c = 0;
+ g(c);
+ g(~c);
+}
diff --git a/tests/lvalue-conversion.qbe b/tests/lvalue-conversion.qbe
new file mode 100644
index 0000000..ac5fbc3
--- /dev/null
+++ b/tests/lvalue-conversion.qbe
@@ -0,0 +1,14 @@
+data $.Lc.2 = align 1 { b 0, }
+export
+function $f() {
+@start.1
+@body.2
+ %.1 =w loadub $.Lc.2
+ %.2 =w extub %.1
+ call $g(w %.2)
+ %.3 =w loadub $.Lc.2
+ %.4 =w extub %.3
+ %.5 =w xor %.4, 18446744073709551615
+ call $g(w %.5)
+ ret
+}
diff --git a/type.c b/type.c
index 97def21..d5550d3 100644
--- a/type.c
+++ b/type.c
@@ -237,6 +237,7 @@ typeunqual(struct type *t, enum typequalifier *tq)
struct type *
typeintpromote(struct type *t)
{
+ assert(t->kind != TYPEQUALIFIED);
if (typeprop(t) & PROPINT && typerank(t) <= typerank(&typeint))
return t->size < typeint.size || t->basic.issigned ? &typeint : &typeuint;
return t;
@@ -245,6 +246,7 @@ typeintpromote(struct type *t)
struct type *
typeargpromote(struct type *t)
{
+ assert(t->kind != TYPEQUALIFIED);
if (t == &typefloat)
return &typedouble;
return typeintpromote(t);