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

Reply via email to