the optimization of a ternary op with two boolean operands had the same problem (as in the last commit) of loosing the type.
Showing the changes to tccgen.c (1 of 2 files). Show all
Unified · Split
| @@ -6351,6 +6351,14 @@ static void expr_cond(void) · 6350 unmodified lines | |||
| 6351 | skip(':'); | 6351 | skip(':'); |
| 6352 | expr_cond(); | 6352 | expr_cond(); |
| 6353 | 6353 | ||
| 6354 | if ((vtop->type.t & VT_BTYPE) == VT_FUNC) | ||
| 6355 | mk_pointer(&vtop->type); | ||
| 6356 | |||
| 6357 | /* cast operands to correct type according to ISOC rules */ | ||
| 6358 | if (!combine_types(&type, &sv, vtop, '?')) | ||
| 6359 | type_incompatibility_error(&sv.type, &vtop->type, | ||
| 6360 | "type mismatch in conditional expression (have '%s' and '%s')"); | ||
| 6361 | |||
| 6354 | if (c < 0 && is_cond_bool(vtop) && is_cond_bool(&sv)) { | 6362 | if (c < 0 && is_cond_bool(vtop) && is_cond_bool(&sv)) { |
| 6355 | /* optimize "if (f ? a > b : c || d) ..." for example, where normally | 6363 | /* optimize "if (f ? a > b : c || d) ..." for example, where normally |
| 6356 | "a < b" and "c || d" would be forced to "(int)0/1" first, whereas | 6364 | "a < b" and "c || d" would be forced to "(int)0/1" first, whereas |
| @@ -6362,17 +6370,11 @@ static void expr_cond(void) · 5 unmodified lines | |||
| 6362 | /* combine jump targets of 2nd op with VT_CMP of 1st op */ | 6370 | /* combine jump targets of 2nd op with VT_CMP of 1st op */ |
| 6363 | gvtst_set(0, t1); | 6371 | gvtst_set(0, t1); |
| 6364 | gvtst_set(1, t2); | 6372 | gvtst_set(1, t2); |
| 6373 | gen_cast(&type); | ||
| 6365 | // tcc_warning("two conditions expr_cond"); | 6374 | // tcc_warning("two conditions expr_cond"); |
| 6366 | return; | 6375 | return; |
| 6367 | } | 6376 | } |
| 6368 | 6377 | ||
| 6369 | if ((vtop->type.t & VT_BTYPE) == VT_FUNC) | ||
| 6370 | mk_pointer(&vtop->type); | ||
| 6371 | |||
| 6372 | /* cast operands to correct type according to ISOC rules */ | ||
| 6373 | if (!combine_types(&type, &sv, vtop, '?')) | ||
| 6374 | type_incompatibility_error(&sv.type, &vtop->type, | ||
| 6375 | "type mismatch in conditional expression (have '%s' and '%s')"); | ||
| 6376 | /* keep structs lvalue by transforming `(expr ? a : b)` to `*(expr ? &a : &b)` so | 6378 | /* keep structs lvalue by transforming `(expr ? a : b)` to `*(expr ? &a : &b)` so |
| 6377 | that `(expr ? a : b).mem` does not error with "lvalue expected" */ | 6379 | that `(expr ? a : b).mem` does not error with "lvalue expected" */ |
| 6378 | islv = (vtop->r & VT_LVAL) && (sv.r & VT_LVAL) && VT_STRUCT == (type.t & VT_BTYPE); | 6380 | islv = (vtop->r & VT_LVAL) && (sv.r & VT_LVAL) && VT_STRUCT == (type.t & VT_BTYPE); |