(cond ? 0 : ptr)->member wasn't handled correctly. If one arm is a null pointer constant (which also can be a pointer) the result type is that of the other arm.
Unified · Split
| @@ -1489,7 +1489,8 @@ static inline int is_null_pointer(SValue *p) · 1488 unmodified lines | ||
| 1489 | 1489 | if ((p->r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST) |
| 1490 | 1490 | return 0; |
| 1491 | 1491 | return ((p->type.t & VT_BTYPE) == VT_INT && p->c.i == 0) || |
| 1492 | − ((p->type.t & VT_BTYPE) == VT_LLONG && p->c.ll == 0); | |
| 1492 | + ((p->type.t & VT_BTYPE) == VT_LLONG && p->c.ll == 0) || | |
| 1493 | + ((p->type.t & VT_BTYPE) == VT_PTR && p->c.ptr == 0); | |
| 1493 | 1494 | } |
| 1494 | 1495 | |
| 1495 | 1496 | static inline int is_integer_btype(int bt) |
| @@ -4116,14 +4117,22 @@ static void expr_cond(void) · 2620 unmodified lines | ||
| 4116 | 4117 | (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED)) |
| 4117 | 4118 | type.t |= VT_UNSIGNED; |
| 4118 | 4119 | } else if (bt1 == VT_PTR || bt2 == VT_PTR) { |
| 4119 | − /* XXX: test pointer compatibility */ | |
| 4120 | − type = type1; | |
| 4120 | + /* If one is a null ptr constant the result type | |
| 4121 | + is the other. */ | |
| 4122 | + if (is_null_pointer (vtop)) | |
| 4123 | + type = type1; | |
| 4124 | + else if (is_null_pointer (&sv)) | |
| 4125 | + type = type2; | |
| 4126 | + /* XXX: test pointer compatibility, C99 has more elaborate | |
| 4127 | + rules here. */ | |
| 4128 | + else | |
| 4129 | + type = type1; | |
| 4121 | 4130 | } else if (bt1 == VT_FUNC || bt2 == VT_FUNC) { |
| 4122 | 4131 | /* XXX: test function pointer compatibility */ |
| 4123 | − type = type1; | |
| 4132 | + type = bt1 == VT_FUNC ? type1 : type2; | |
| 4124 | 4133 | } else if (bt1 == VT_STRUCT || bt2 == VT_STRUCT) { |
| 4125 | 4134 | /* XXX: test structure compatibility */ |
| 4126 | − type = type1; | |
| 4135 | + type = bt1 == VT_STRUCT ? type1 : type2; | |
| 4127 | 4136 | } else if (bt1 == VT_VOID || bt2 == VT_VOID) { |
| 4128 | 4137 | /* NOTE: as an extension, we accept void on only one side */ |
| 4129 | 4138 | type.t = VT_VOID; |
| @@ -2486,3 +2486,16 @@ void const_warn_test(void) · 2485 unmodified lines | ||
| 2486 | 2486 | { |
| 2487 | 2487 | const_func(1); |
| 2488 | 2488 | } |
| 2489 | + | |
| 2490 | +struct condstruct { | |
| 2491 | + int i; | |
| 2492 | +}; | |
| 2493 | + | |
| 2494 | +int getme (struct condstruct *s, int i) | |
| 2495 | +{ | |
| 2496 | + int i1 = (i == 0 ? 0 : s)->i; | |
| 2497 | + int i2 = (i == 0 ? s : 0)->i; | |
| 2498 | + int i3 = (i == 0 ? (void*)0 : s)->i; | |
| 2499 | + int i4 = (i == 0 ? s : (void*)0)->i; | |
| 2500 | + return i1 + i2 + i3 + i4; | |
| 2501 | +} | |