From 6471ec0a2bd523edd4bbc79277a33d0b853940fa Mon Sep 17 00:00:00 2001 From: Michael Matz Date: Sat, 14 Apr 2012 23:50:21 +0200 Subject: [PATCH 1/9] Fix conversion in a?0:ptr. (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. --- tccgen.c | 19 ++++++++++++++----- tests/tcctest.c | 13 +++++++++++++ 2 files changed, 27 insertions(+), 5 deletions(-) diff --git a/tccgen.c b/tccgen.c index 5aa21c6..b0cec4a 100644 --- a/tccgen.c +++ b/tccgen.c @@ -1489,7 +1489,8 @@ static inline int is_null_pointer(SValue *p) if ((p->r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST) return 0; return ((p->type.t & VT_BTYPE) == VT_INT && p->c.i == 0) || - ((p->type.t & VT_BTYPE) == VT_LLONG && p->c.ll == 0); + ((p->type.t & VT_BTYPE) == VT_LLONG && p->c.ll == 0) || + ((p->type.t & VT_BTYPE) == VT_PTR && p->c.ptr == 0); } static inline int is_integer_btype(int bt) @@ -4116,14 +4117,22 @@ static void expr_cond(void) (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED)) type.t |= VT_UNSIGNED; } else if (bt1 == VT_PTR || bt2 == VT_PTR) { - /* XXX: test pointer compatibility */ - type = type1; + /* If one is a null ptr constant the result type + is the other. */ + if (is_null_pointer (vtop)) + type = type1; + else if (is_null_pointer (&sv)) + type = type2; + /* XXX: test pointer compatibility, C99 has more elaborate + rules here. */ + else + type = type1; } else if (bt1 == VT_FUNC || bt2 == VT_FUNC) { /* XXX: test function pointer compatibility */ - type = type1; + type = bt1 == VT_FUNC ? type1 : type2; } else if (bt1 == VT_STRUCT || bt2 == VT_STRUCT) { /* XXX: test structure compatibility */ - type = type1; + type = bt1 == VT_STRUCT ? type1 : type2; } else if (bt1 == VT_VOID || bt2 == VT_VOID) { /* NOTE: as an extension, we accept void on only one side */ type.t = VT_VOID; diff --git a/tests/tcctest.c b/tests/tcctest.c index f0d82cf..723adc1 100644 --- a/tests/tcctest.c +++ b/tests/tcctest.c @@ -2486,3 +2486,16 @@ void const_warn_test(void) { const_func(1); } + +struct condstruct { + int i; +}; + +int getme (struct condstruct *s, int i) +{ + int i1 = (i == 0 ? 0 : s)->i; + int i2 = (i == 0 ? s : 0)->i; + int i3 = (i == 0 ? (void*)0 : s)->i; + int i4 = (i == 0 ? s : (void*)0)->i; + return i1 + i2 + i3 + i4; +} -- 1.7.3.4