From 3058d4116e73062ee2029ad20ecc6f3c3f736915 Mon Sep 17 00:00:00 2001 From: Petr Skocik Date: Wed, 28 Nov 2018 21:12:38 +0100 Subject: [PATCH] Fix (Cexpr?struct1:struct2).member Tcc used to fail this with `lvalue expected` if the expression was a compile-time constant. --- tccgen.c | 3 +-- tests/tests2/33_ternary_op.c | 14 ++++++++++++++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/tccgen.c b/tccgen.c index cccd88b..0077769 100644 --- a/tccgen.c +++ b/tccgen.c @@ -5663,7 +5663,6 @@ static void expr_cond(void) /* keep structs lvalue by transforming `(expr ? a : b)` to `*(expr ? &a : &b)` so that `(expr ? a : b).mem` does not error with "lvalue expected" */ islv = (vtop->r & VT_LVAL) && (sv.r & VT_LVAL) && VT_STRUCT == (type.t & VT_BTYPE); - islv &= c < 0; /* now we convert second operand */ if (c != 1) { @@ -5708,7 +5707,7 @@ static void expr_cond(void) gaddrof(); } - if (c < 0) { + if (c < 0 || islv) { r1 = gv(rc); move_reg(r2, r1, type.t); vtop->r = r2; diff --git a/tests/tests2/33_ternary_op.c b/tests/tests2/33_ternary_op.c index 8579b50..33cda44 100644 --- a/tests/tests2/33_ternary_op.c +++ b/tests/tests2/33_ternary_op.c @@ -1,4 +1,5 @@ #include +#include int main() { @@ -9,6 +10,19 @@ int main() printf("%d\n", (Count < 5) ? (Count*Count) : (Count * 3)); } + { + int c = 0; + #define ASSERT(X) assert(X) + static struct stru { int x; } a={'A'},b={'B'}; + ASSERT('A'==(*(1?&a:&b)).x); + ASSERT('A'==(1?a:b).x); + ASSERT('A'==(c?b:a).x); + ASSERT('A'==(0?b:a).x); + c=1; + ASSERT('A'==(c?a:b).x); + } + + return 0; }