Fix type of cond-op
the optimization of a ternary op with two boolean operands had the same problem (as in the last commit) of loosing the type.
This commit is contained in:
parent
96b31ba670
commit
ef3eb02ccb
2 changed files with 10 additions and 7 deletions
16
tccgen.c
16
tccgen.c
|
@ -6351,6 +6351,14 @@ static void expr_cond(void)
|
||||||
skip(':');
|
skip(':');
|
||||||
expr_cond();
|
expr_cond();
|
||||||
|
|
||||||
|
if ((vtop->type.t & VT_BTYPE) == VT_FUNC)
|
||||||
|
mk_pointer(&vtop->type);
|
||||||
|
|
||||||
|
/* cast operands to correct type according to ISOC rules */
|
||||||
|
if (!combine_types(&type, &sv, vtop, '?'))
|
||||||
|
type_incompatibility_error(&sv.type, &vtop->type,
|
||||||
|
"type mismatch in conditional expression (have '%s' and '%s')");
|
||||||
|
|
||||||
if (c < 0 && is_cond_bool(vtop) && is_cond_bool(&sv)) {
|
if (c < 0 && is_cond_bool(vtop) && is_cond_bool(&sv)) {
|
||||||
/* optimize "if (f ? a > b : c || d) ..." for example, where normally
|
/* optimize "if (f ? a > b : c || d) ..." for example, where normally
|
||||||
"a < b" and "c || d" would be forced to "(int)0/1" first, whereas
|
"a < b" and "c || d" would be forced to "(int)0/1" first, whereas
|
||||||
|
@ -6362,17 +6370,11 @@ static void expr_cond(void)
|
||||||
/* combine jump targets of 2nd op with VT_CMP of 1st op */
|
/* combine jump targets of 2nd op with VT_CMP of 1st op */
|
||||||
gvtst_set(0, t1);
|
gvtst_set(0, t1);
|
||||||
gvtst_set(1, t2);
|
gvtst_set(1, t2);
|
||||||
|
gen_cast(&type);
|
||||||
// tcc_warning("two conditions expr_cond");
|
// tcc_warning("two conditions expr_cond");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((vtop->type.t & VT_BTYPE) == VT_FUNC)
|
|
||||||
mk_pointer(&vtop->type);
|
|
||||||
|
|
||||||
/* cast operands to correct type according to ISOC rules */
|
|
||||||
if (!combine_types(&type, &sv, vtop, '?'))
|
|
||||||
type_incompatibility_error(&sv.type, &vtop->type,
|
|
||||||
"type mismatch in conditional expression (have '%s' and '%s')");
|
|
||||||
/* keep structs lvalue by transforming `(expr ? a : b)` to `*(expr ? &a : &b)` so
|
/* keep structs lvalue by transforming `(expr ? a : b)` to `*(expr ? &a : &b)` so
|
||||||
that `(expr ? a : b).mem` does not error with "lvalue expected" */
|
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 = (vtop->r & VT_LVAL) && (sv.r & VT_LVAL) && VT_STRUCT == (type.t & VT_BTYPE);
|
||||||
|
|
|
@ -1269,6 +1269,7 @@ void bool_test()
|
||||||
t = 1;
|
t = 1;
|
||||||
printf("type of bool: %d\n", (int) ( (~ ((unsigned int) (t && 1))) / 2) );
|
printf("type of bool: %d\n", (int) ( (~ ((unsigned int) (t && 1))) / 2) );
|
||||||
|
|
||||||
|
printf("type of cond: %d\n", (~(t ? 0U : (unsigned int)0)) / 2 );
|
||||||
/* test ? : cast */
|
/* test ? : cast */
|
||||||
{
|
{
|
||||||
int aspect_on;
|
int aspect_on;
|
||||||
|
|
Loading…
Add table
Reference in a new issue