https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92684
Bug ID: 92684
Summary: bitfield behavior not matching the declared type
Product: gcc
Version: 9.2.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: c
Assignee: unassigned at gcc dot gnu.org
Reporter: wuxb45 at gmail dot com
Target Milestone: ---
found wrong data when compiled by gcc 9.2.0 (x86_64, -std=gnu11). Have not
tried other gcc versions. The results are correct on clang 8.0.1.
Long story short: some bits are missing when using bitfields with uint64_t as
the declared type. Maybe I should use a (u64) cast on every dereference to
those fields. But the results are not always wrong. Maybe I should read some
C11 specs. But consider the different behaviors between gcc and clang, I decide
to report a bug here in hope to get some better help. Thanks.
This reproduces the results: gcc/clang -std=gnu11 main.c
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
typedef uint64_t u64;
struct st {
union {
struct {
u64 v1:19;
u64 v2:45;
};
void * ptr;
};
};
struct bits {
u64 bit1:1;
u64 bitx:63;
};
int
main(void)
{
char * val = "0xffff0000fff8";
// x has 48 valid bits, the three low bits are 0s
volatile u64 x = strtoull(val, NULL, 16);
printf("%lx\n", x);
// st stores that 45 bits
struct st st = {.v1 = 0, .v2 = (x >> 3)};
printf("%p\n", st.ptr);
// y should get the original bits; but the three high bits are gone.
u64 y = st.v2 << 3;
printf("%lx\n", y);
// this is another (minor) related case.
// some are correct and some are wrong.
struct bits b = {.bit1 = 1, .bitx = 0};
// this is more interesting. gcc shows "80000000", clang shows "1"
printf("%lx %lx %lx\n", b.bit1, b.bit1 << 1, b.bit1 << 63);
return 0;
}