Make signed/unsigned bitfields the same as gcc/clang

This commit is contained in:
herman ten brugge
2025-08-18 16:22:00 +02:00
parent 199e135142
commit 8845b6cd45
3 changed files with 151 additions and 73 deletions

View File

@@ -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 */
;

View File

@@ -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;
}

View File

@@ -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