From f7779efe58520fa735f550651d003f09dce9b684 Mon Sep 17 00:00:00 2001 From: Petr Skocik Date: Thu, 29 Nov 2018 13:40:48 +0100 Subject: [PATCH] Fix incorrect one-sided void handling in ?: Also make the case when one side in ?: is a ptr and the other is neither a ptr nor a null-ptr constant fail cleanly instead of segfaulting. --- tccgen.c | 14 ++++++++------ tests/tests2/33_ternary_op.c | 32 ++++++++++++++++++-------------- 2 files changed, 26 insertions(+), 20 deletions(-) diff --git a/tccgen.c b/tccgen.c index e70c843a..dda46a7c 100644 --- a/tccgen.c +++ b/tccgen.c @@ -5598,7 +5598,9 @@ static void expr_cond(void) /* cast operands to correct type according to ISOC rules */ - if (is_float(bt1) || is_float(bt2)) { + if (bt1 == VT_VOID || bt2 == VT_VOID) { + type.t = VT_VOID; /* NOTE: as an extension, we accept void on only one side */ + }else if (is_float(bt1) || is_float(bt2)) { if (bt1 == VT_LDOUBLE || bt2 == VT_LDOUBLE) { type.t = VT_LDOUBLE; @@ -5625,8 +5627,11 @@ static void expr_cond(void) if (is_null_pointer (vtop)) type = type1; else if (is_null_pointer (&sv)) type = type2; else{ - int pbt1 = (pointed_type(&type1)->t&VT_BTYPE); - int pbt2 = (pointed_type(&type2)->t&VT_BTYPE); + int pbt1, pbt2; + if (bt1!=bt2) + tcc_error("incompatible types in conditional expressions"); + pbt1 = (pointed_type(&type1)->t&VT_BTYPE); + pbt2 = (pointed_type(&type2)->t&VT_BTYPE); /*pointers to void get preferred, otherwise the pointed to types minus qualifs should be compatible*/ type = (pbt1==VT_VOID) ? type1 : type2; if (pbt1!=VT_VOID && pbt2!=VT_VOID){ @@ -5652,9 +5657,6 @@ static void expr_cond(void) } else if (bt1 == VT_STRUCT || bt2 == VT_STRUCT) { /* XXX: test structure compatibility */ 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; } else { /* integer operations */ type.t = VT_INT | (VT_LONG & (t1 | t2)); diff --git a/tests/tests2/33_ternary_op.c b/tests/tests2/33_ternary_op.c index bf637d49..a79a62c1 100644 --- a/tests/tests2/33_ternary_op.c +++ b/tests/tests2/33_ternary_op.c @@ -6,20 +6,24 @@ static void f (void){} void (*fp)(void) = f; void call_fp() { - (fp?f:f)(); - (fp?fp:fp)(); - (fp?fp:&f)(); - (fp?&f:fp)(); - (fp?&f:&f)(); - _Generic(0?arr:arr, char*: (void)0); - _Generic(0?&arr[0]:arr, char*: (void)0); - _Generic(0?arr:&arr[0], char*: (void)0); - _Generic(1?arr:arr, char*: (void)0); - _Generic(1?&arr[0]:arr, char*: (void)0); - _Generic(1?arr:&arr[0], char*: (void)0); - _Generic((__typeof(1?f:f)*){0}, void (**)(void): (void)0); - (fp?&f:f)(); - (fp?f:&f)(); + (fp?f:f)(); + (fp?fp:fp)(); + (fp?fp:&f)(); + (fp?&f:fp)(); + (fp?&f:&f)(); + _Generic(0?arr:arr, char*: (void)0); + _Generic(0?&arr[0]:arr, char*: (void)0); + _Generic(0?arr:&arr[0], char*: (void)0); + _Generic(1?arr:arr, char*: (void)0); + _Generic(1?&arr[0]:arr, char*: (void)0); + _Generic(1?arr:&arr[0], char*: (void)0); + _Generic((__typeof(1?f:f)*){0}, void (**)(void): (void)0); + (fp?&f:f)(); + (fp?f:&f)(); + _Generic((__typeof(fp?0L:(void)0)*){0}, void*: (void)0); + + //Should cleanly fail, not segfault: + /*(fp?f:1);*/ } int main()