diff --git a/tccgen.c b/tccgen.c index b6dbad2d..1f853b50 100644 --- a/tccgen.c +++ b/tccgen.c @@ -2959,15 +2959,17 @@ static int combine_types(CType *dest, SValue *op1, SValue *op2, int op) if (bt2 == VT_LLONG) type.t &= t2; /* convert to unsigned if it does not fit in a long long */ - if ((t1 & (VT_BTYPE | VT_UNSIGNED | VT_BITFIELD)) == (VT_LLONG | VT_UNSIGNED) || - (t2 & (VT_BTYPE | VT_UNSIGNED | VT_BITFIELD)) == (VT_LLONG | VT_UNSIGNED)) + if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED) || + (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED)) type.t |= VT_UNSIGNED; } else { + int t1_bit = BIT_SIZE(t1) <= 31 ? VT_BITFIELD : 0; + int t2_bit = BIT_SIZE(t2) <= 31 ? VT_BITFIELD : 0; /* integer operations */ type.t = VT_INT | (VT_LONG & (t1 | t2)); /* convert to unsigned if it does not fit in an integer */ - if ((t1 & (VT_BTYPE | VT_UNSIGNED | VT_BITFIELD)) == (VT_INT | VT_UNSIGNED) || - (t2 & (VT_BTYPE | VT_UNSIGNED | VT_BITFIELD)) == (VT_INT | VT_UNSIGNED)) + if ((t1 & (VT_BTYPE | VT_UNSIGNED | t1_bit)) == (VT_INT | VT_UNSIGNED) || + (t2 & (VT_BTYPE | VT_UNSIGNED | t2_bit)) == (VT_INT | VT_UNSIGNED)) type.t |= VT_UNSIGNED; } if (dest) @@ -4554,6 +4556,7 @@ do_decl: tcc_error("width of '%s' exceeds its type", get_tok_str(v, NULL)); } else if (bit_size == bsize + && !*tcc_state->pack_stack_ptr && !ad.a.packed && !ad1.a.packed) { /* no need for bit fields */ ; diff --git a/tests/tests2/93_integer_promotion.c b/tests/tests2/93_integer_promotion.c index a1176fc6..2c47ec1a 100644 --- a/tests/tests2/93_integer_promotion.c +++ b/tests/tests2/93_integer_promotion.c @@ -6,66 +6,106 @@ int printf(const char*, ...); int main (void) { struct { - unsigned ub:3; - unsigned u:32; - unsigned long long ullb:35; - unsigned long long ull:64; + unsigned u3:3; + unsigned u31:31; + unsigned u32:32; + unsigned long ul31:31; + unsigned long ul32:32; + unsigned long long ull31:31; + unsigned long long ull32:32; + unsigned long long ull33:33; + unsigned long long ull64:64; unsigned char c; - } s = { 1, 1, 1 }; + } s = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; - promote(s.ub); - promote(s.u); - promote(s.ullb); - promote(s.ull); + promote(s.u3); + promote(s.u31); + promote(s.u32); + promote(s.ul31); + promote(s.ul32); + promote(s.ull31); + promote(s.ull32); + promote(s.ull33); + promote(s.ull64); promote(s.c); printf("\n"); - promote((1 ? s.ub : 1)); - promote((1 ? s.u : 1)); - promote((1 ? s.ullb : 1)); - promote((1 ? s.ull : 1)); + promote((1 ? s.u3 : 1)); + promote((1 ? s.u31 : 1)); + promote((1 ? s.u32 : 1)); + promote((1 ? s.ul31 : 1)); + promote((1 ? s.ul32 : 1)); + promote((1 ? s.ull31 : 1)); + promote((1 ? s.ull32 : 1)); + promote((1 ? s.ull33 : 1)); + promote((1 ? s.ull64 : 1)); promote((1 ? s.c : 1)); printf("\n"); - promote(s.ub << 1); - promote(s.u << 1); - promote(s.ullb << 1); - promote(s.ull << 1); + promote(s.u3 << 1); + promote(s.u31 << 1); + promote(s.u32 << 1); + promote(s.ul31 << 1); + promote(s.ul32 << 1); + promote(s.ull31 << 1); + promote(s.ull32 << 1); + promote(s.ull33 << 1); + promote(s.ull64 << 1); promote(s.c << 1); printf("\n"); - promote(+s.ub); - promote(+s.u); - promote(+s.ullb); - promote(+s.ull); + promote(+s.u3); + promote(+s.u31); + promote(+s.u32); + promote(+s.ul31); + promote(+s.ul32); + promote(+s.ull31); + promote(+s.ull32); + promote(+s.ull33); + promote(+s.ull64); promote(+s.c); printf("\n"); - promote(-s.ub); - promote(-s.u); - promote(-s.ullb); - promote(-s.ull); + promote(-s.u3); + promote(-s.u31); + promote(-s.u32); + promote(-s.ul31); + promote(-s.ul32); + promote(-s.ull31); + promote(-s.ull32); + promote(-s.ull33); + promote(-s.ull64); promote(-s.c); printf("\n"); - promote(~s.ub); - promote(~s.u); - promote(~s.ullb); - promote(~s.ull); + promote(~s.u3); + promote(~s.u31); + promote(~s.u32); + promote(~s.ul31); + promote(~s.ul32); + promote(~s.ull31); + promote(~s.ull32); + promote(~s.ull33); + promote(~s.ull64); promote(~s.c); printf("\n"); - promote(!s.ub); - promote(!s.u); - promote(!s.ullb); - promote(!s.ull); + promote(!s.u3); + promote(!s.u31); + promote(!s.u32); + promote(!s.ul31); + promote(!s.ul32); + promote(!s.ull31); + promote(!s.ull32); + promote(!s.ull33); + promote(!s.ull64); promote(!s.c); printf("\n"); - promote(+(unsigned)s.ub); - promote(-(unsigned)s.ub); - promote(~(unsigned)s.ub); - promote(!(unsigned)s.ub); + promote(+(unsigned)s.u3); + promote(-(unsigned)s.u3); + promote(~(unsigned)s.u3); + promote(!(unsigned)s.u3); return 0; } diff --git a/tests/tests2/93_integer_promotion.expect b/tests/tests2/93_integer_promotion.expect index 34b9c145..f3f55625 100644 --- a/tests/tests2/93_integer_promotion.expect +++ b/tests/tests2/93_integer_promotion.expect @@ -1,46 +1,81 @@ - signed : s.ub - unsigned : s.u - signed : s.ullb - unsigned : s.ull + signed : s.u3 + signed : s.u31 + unsigned : s.u32 + signed : s.ul31 + unsigned : s.ul32 + signed : s.ull31 + unsigned : s.ull32 + unsigned : s.ull33 + unsigned : s.ull64 signed : s.c - signed : (1 ? s.ub : 1) - unsigned : (1 ? s.u : 1) - signed : (1 ? s.ullb : 1) - unsigned : (1 ? s.ull : 1) + signed : (1 ? s.u3 : 1) + signed : (1 ? s.u31 : 1) + unsigned : (1 ? s.u32 : 1) + signed : (1 ? s.ul31 : 1) + unsigned : (1 ? s.ul32 : 1) + signed : (1 ? s.ull31 : 1) + unsigned : (1 ? s.ull32 : 1) + unsigned : (1 ? s.ull33 : 1) + unsigned : (1 ? s.ull64 : 1) signed : (1 ? s.c : 1) - signed : s.ub << 1 - unsigned : s.u << 1 - signed : s.ullb << 1 - unsigned : s.ull << 1 + signed : s.u3 << 1 + signed : s.u31 << 1 + unsigned : s.u32 << 1 + signed : s.ul31 << 1 + unsigned : s.ul32 << 1 + signed : s.ull31 << 1 + unsigned : s.ull32 << 1 + unsigned : s.ull33 << 1 + unsigned : s.ull64 << 1 signed : s.c << 1 - signed : +s.ub - unsigned : +s.u - signed : +s.ullb - unsigned : +s.ull + signed : +s.u3 + signed : +s.u31 + unsigned : +s.u32 + signed : +s.ul31 + unsigned : +s.ul32 + signed : +s.ull31 + unsigned : +s.ull32 + unsigned : +s.ull33 + unsigned : +s.ull64 signed : +s.c - signed : -s.ub - unsigned : -s.u - signed : -s.ullb - unsigned : -s.ull + signed : -s.u3 + signed : -s.u31 + unsigned : -s.u32 + signed : -s.ul31 + unsigned : -s.ul32 + signed : -s.ull31 + unsigned : -s.ull32 + unsigned : -s.ull33 + unsigned : -s.ull64 signed : -s.c - signed : ~s.ub - unsigned : ~s.u - signed : ~s.ullb - unsigned : ~s.ull + signed : ~s.u3 + signed : ~s.u31 + unsigned : ~s.u32 + signed : ~s.ul31 + unsigned : ~s.ul32 + signed : ~s.ull31 + unsigned : ~s.ull32 + unsigned : ~s.ull33 + unsigned : ~s.ull64 signed : ~s.c - signed : !s.ub - signed : !s.u - signed : !s.ullb - signed : !s.ull + signed : !s.u3 + signed : !s.u31 + signed : !s.u32 + signed : !s.ul31 + signed : !s.ul32 + signed : !s.ull31 + signed : !s.ull32 + signed : !s.ull33 + signed : !s.ull64 signed : !s.c - unsigned : +(unsigned)s.ub - unsigned : -(unsigned)s.ub - unsigned : ~(unsigned)s.ub - signed : !(unsigned)s.ub + unsigned : +(unsigned)s.u3 + unsigned : -(unsigned)s.u3 + unsigned : ~(unsigned)s.u3 + signed : !(unsigned)s.u3