From 11a3195c4951d9ee635407999c174afe8df19497 Mon Sep 17 00:00:00 2001 From: Stephen Heumann Date: Mon, 4 Jul 2022 22:30:25 -0500 Subject: [PATCH] Use properly result type for statically evaluated ternary operators. Also, update the tests to include statically-evaluated cases. --- Expression.pas | 37 ++++++++++++++- Tests/Conformance/c11ternary.c | 85 +++++++++++++++++++++------------- 2 files changed, 89 insertions(+), 33 deletions(-) diff --git a/Expression.pas b/Expression.pas index 57373e4..986ad7a 100644 --- a/Expression.pas +++ b/Expression.pas @@ -1201,11 +1201,44 @@ var if op^.middle^.token.kind in [intconst,uintconst,ushortconst, longconst,ulongconst,longlongconst,ulonglongconst, charconst,scharconst,ucharconst] then begin + + kindLeft := op^.middle^.token.kind; + kindRight := op^.right^.token.kind; + + {do the usual binary conversions} + if (kindRight = ulonglongconst) or (kindLeft = ulonglongconst) then + ekind := ulonglongconst + else if (kindRight = longlongconst) or (kindLeft = longlongconst) then + ekind := longlongconst + else if (kindRight = ulongconst) or (kindLeft = ulongconst) then + ekind := ulongconst + else if (kindRight = longconst) or (kindLeft = longconst) then + ekind := longconst + else if (kindRight = uintconst) or (kindLeft = uintconst) + or (kindRight = ushortconst) or (kindLeft = ushortconst) then + ekind := uintconst + else + ekind := intconst; + GetLongLongVal(llop1, op^.left^.token); if (llop1.lo <> 0) or (llop1.hi <> 0) then - op^.token := op^.middle^.token + GetLongLongVal(llop2, op^.middle^.token) else - op^.token := op^.right^.token; + GetLongLongVal(llop2, op^.right^.token); + op^.token.kind := ekind; + if ekind in [longlongconst,ulonglongconst] then begin + op^.token.qval := llop2; + op^.token.class := longlongConstant; + end {if} + else if ekind in [longconst,ulongconst] then begin + op^.token.lval := llop2.lo; + op^.token.class := longConstant; + end {if} + else begin + op^.token.ival := long(llop2.lo).lsw; + op^.token.class := intConstant; + end; {else} + dispose(op^.left); dispose(op^.right); dispose(op^.middle); diff --git a/Tests/Conformance/c11ternary.c b/Tests/Conformance/c11ternary.c index 7aa4e47..3b2ecad 100644 --- a/Tests/Conformance/c11ternary.c +++ b/Tests/Conformance/c11ternary.c @@ -5,7 +5,10 @@ * but a C11 feature (_Generic) is used to test them. */ +#include + #define assert_type(e,t) (void)_Generic((e), t:(e)) +#define assert_type_val(e,t,v) if (_Generic((e), t:(e)) != (v)) goto Fail int main(void) { int i = 1; @@ -13,8 +16,8 @@ int main(void) { double d = 3; struct S {int i;} s = {4}; const struct S t = {5}; - const void *cvp = &i; - void *vp = &i; + const void *cvp = &s; + void *vp = &d; const int *cip = &i; volatile int *vip = 0; int *ip = &i; @@ -23,35 +26,55 @@ int main(void) { int (*fp2)(int (*)[40]) = 0; int (*fp3)(int (*)[]) = 0; - assert_type(1?i:l, long); - assert_type(1?d:i, double); + assert_type_val(1?i:l, long, 1); + assert_type_val(1?d:i, double, 3.0); assert_type(1?s:t, struct S); 1?(void)2:(void)3; - assert_type(1?ip:ip, int *); - assert_type(1?ip:cip, const int *); - assert_type(1?cip:ip, const int *); - assert_type(1?0:ip, int *); - assert_type(0?0LL:ip, int *); - assert_type(1?(void*)0:ip, int *); - assert_type(1?cip:0, const int *); - assert_type(1?cip:0LL, const int *); - assert_type(1?cip:(char)0.0, const int *); - assert_type(1?cip:(void*)0, const int *); - assert_type(1?(void*)(void*)0:ip, void *); - assert_type(1?(void*)ip:ip, void *); - assert_type(1?cip:(void*)(void*)0, const void *); - assert_type(1?(void*)ip:cip, const void *); - assert_type(1?main:main, int(*)(void)); - assert_type(1?main:0, int(*)(void)); - assert_type(1?(const void*)cip:(void*)ip, const void *); - assert_type(1?cvp:cip, const void *); - assert_type(1?vip:0, volatile int *); - assert_type(1?cip:vip, const volatile int *); - assert_type(1?vp:ccp, const void *); - assert_type(1?ip:cip, const int *); - assert_type(1?vp:ip, void *); - assert_type(1?fp1:fp2, int (*)(int (*)[40])); - assert_type(1?fp2:fp3, int (*)(int (*)[40])); - assert_type(1?fp2:0, int (*)(int (*)[40])); - assert_type(1?fp2:(void*)0, int (*)(int (*)[40])); + assert_type_val(1?ip:ip, int *, &i); + assert_type_val(1?ip:cip, const int *, &i); + assert_type_val(1?cip:ip, const int *, &i); + assert_type_val(1?0:ip, int *, (void*)0); + assert_type_val(0?0LL:ip, int *, &i); + assert_type_val(1?(void*)0:ip, int *, (void*)0); + assert_type_val(1?cip:0, const int *, &i); + assert_type_val(1?cip:0LL, const int *, &i); + assert_type_val(1?cip:(char)0.0, const int *, &i); + assert_type_val(1?cip:(void*)0, const int *, &i); + assert_type_val(1?(void*)(void*)0:ip, void *, (void*)0); + assert_type_val(1?(void*)ip:ip, void *, &i); + assert_type_val(1?cip:(void*)(void*)0, const void *, &i); + assert_type_val(1?(void*)ip:cip, const void *, &i); + assert_type_val(1?main:main, int(*)(void), main); + assert_type_val(1?main:0, int(*)(void), main); + assert_type_val(1?(const void*)cip:(void*)ip, const void *, &i); + assert_type_val(1?cvp:cip, const void *, &s); + assert_type_val(1?vip:0, volatile int *, (int*)0); + assert_type_val(1?cip:vip, const volatile int *, &i); + assert_type_val(1?vp:ccp, const void *, &d); + assert_type_val(1?ip:cip, const int *, &i); + assert_type_val(1?vp:ip, void *, &d); + assert_type_val(1?fp1:fp2, int (*)(int (*)[40]), (void*)0); + assert_type_val(1?fp2:fp3, int (*)(int (*)[40]), (void*)0); + assert_type_val(1?fp2:0, int (*)(int (*)[40]), (void*)0); + assert_type_val(1?fp2:(void*)0, int (*)(int (*)[40]), (void*)0); + assert_type_val(1?2:3, int, 2); + assert_type_val(1?2:3U, unsigned int, 2); + assert_type_val(1?2:3L, long, 2); + assert_type_val(1?2:3UL, unsigned long, 2); + assert_type_val(1?2:3LL, long long, 2); + assert_type_val(1?2:3ULL, unsigned long long, 2); + assert_type_val(0?2:3, int, 3); + assert_type_val(0?2U:3, unsigned int, 3); + assert_type_val(0?2L:3, long, 3); + assert_type_val(0?2UL:3, unsigned long, 3); + assert_type_val(0?2LL:3, long long, 3); + assert_type_val(0?2ULL:3, unsigned long long, 3); + assert_type_val(1?50000U:3LL, long long, 50000); + assert_type_val(1?5000000L:3LL, long long, 5000000); + + printf ("Passed Conformance Test c11ternary\n"); + return 0; + +Fail: + printf ("Failed Conformance Test c11ternary\n"); }