This is the mail archive of the gcc-bugs@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Bug target/52991] [6/7/8 Regression] attribute packed broken on mingw32?


https://gcc.gnu.org/bugzilla/show_bug.cgi?id=52991

--- Comment #31 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
Thanks for the hint.

So:
#include <stdio.h>

struct S {
  int a : 2;
  __declspec(align(8)) int b : 2;
  int c : 28;
  __declspec(align(16)) int d : 2;
  int e : 30;
} s;
int a = sizeof (struct S);
void f1 (int x) { s.a = x; }
void f2 (int x) { s.b = x; }
void f3 (int x) { s.c = x; }
void f4 (int x) { s.d = x; }
void f5 (int x) { s.e = x; }

void
printme (void)
{
    int i;
    for (i = 0; i < sizeof (s); ++i)
        printf ("%02x, ", ((unsigned char *) &s)[i]);
    printf ("\n");
}

int
main ()
{
    printf ("%d\n", (int) sizeof (s));
    s.a = -1; printme ();
    s.a = 0; s.b = -1; printme ();
    s.b = 0; s.c = -1; printme ();
    s.c = 0; s.d = -1; printme ();
    s.d = 0; s.e = -1; printme ();
    return 0;
}

matches what GCC with the patch emits (that is the bf-ms-layout-5.c test),
and so does:
#include <stddef.h>

#ifdef _WIN32
# ifdef _MSC_VER
#  define PACK(typeDec) __pragma( pack(push, 1) ) typeDec __pragma( pack(pop) )
# else
#  define PACK(typeDec) typeDec __attribute__((__packed__,ms_struct))
# endif
#else
# define PACK(typeDec) typeDec __attribute__((__packed__))
#endif

#ifdef _MSC_VER
# define ALIGN(typeDec, n) __declspec(align(n)) typeDec
#else
# define ALIGN(typeDec, n) typeDec __attribute__((aligned(n)))
#endif

#define assert_cc(expr) extern char c[(expr) ? 1 : -1]

PACK(struct test_sp1 {
    int a;
    short b;
    int c;
    char d;
});

assert_cc(sizeof(struct test_sp1) == 11);
assert_cc(offsetof(struct test_sp1, a) == 0);
assert_cc(offsetof(struct test_sp1, b) == 4);
assert_cc(offsetof(struct test_sp1, c) == 6);
assert_cc(offsetof(struct test_sp1, d) == 10);

PACK(struct test_sp3 {
    int a;
    ALIGN(short b, 8);
    int c;
    char d;
});

assert_cc(sizeof(struct test_sp3) == 16);
assert_cc(offsetof(struct test_sp3, a) == 0);
assert_cc(offsetof(struct test_sp3, b) == 8);
assert_cc(offsetof(struct test_sp3, c) == 10);
assert_cc(offsetof(struct test_sp3, d) == 14);

struct test_s4 {
    int a;
    short b;
    int c:15;
    char d;
};

#ifdef _WIN32
assert_cc(sizeof(struct test_s4) == 16);
assert_cc(offsetof(struct test_s4, a) == 0);
assert_cc(offsetof(struct test_s4, b) == 4);
assert_cc(offsetof(struct test_s4, d) == 12);
#else
assert_cc(sizeof(struct test_s4) == 12);
assert_cc(offsetof(struct test_s4, a) == 0);
assert_cc(offsetof(struct test_s4, b) == 4);
assert_cc(offsetof(struct test_s4, d) == 8);
#endif

int main () { return 0; }

(bf-ms-layout-4.c).
So does:
#define _TEST_MS_LAYOUT
#include <stddef.h>
#include <string.h>

extern void abort();

#pragma pack(8)

struct one {
  int d;
  unsigned char a;
  unsigned short b:7;
  char c;
} ;

struct two {
  int d;
  unsigned char a;
  unsigned int b:7;
  char c;
} ;

struct three {
  short d;
  unsigned short a:3;
  unsigned short b:9;
  unsigned char c:7;
} ;


/* Bitfields of size 0 have some truly odd behaviors. */

struct four {
  unsigned short a:3;
  unsigned short b:9;
  unsigned int :0;  /* forces struct alignment to int */
  unsigned char c:7;
} ;

struct five {
  char a;
  int :0;        /* ignored; prior field is not a bitfield. */
  char b;
  char c;
} ;

struct six {
  char a :8;
  int :0;       /* not ignored; prior field IS a bitfield, causes
                   struct alignment as well. */
  char b;
  char c;
} ;

struct seven {
  char a:8;
  char :0;
  int  :0;      /* Ignored; prior field is zero size bitfield. */
  char b;
  char c;
} ;

struct eight { /* ms size 4 */
  short b:3;
  char  c;
} ;

#ifdef _MSC_VER
#define LONGLONG __int64
#else
#define LONGLONG long long
#endif

union nine {   /* ms size 8 */
  LONGLONG a:3;
  char  c;
} ;

struct ten {   /* ms size 16 */
  LONGLONG a:3;
  LONGLONG b:3;
  char  c;
} ;


#define val(s,f) (s.f)

#define check_struct(_X) \
{ \
  if (sizeof (struct _X) != exp_sizeof_##_X )   \
    abort();                                    \
  memcpy(&test_##_X, filler, sizeof(test_##_X));\
  if (val(test_##_X,c) != exp_##_X##_c)         \
     abort();                                   \
}

#define check_union(_X) \
{ \
  if (sizeof (union _X) != exp_sizeof_##_X )    \
    abort();                                    \
  memcpy(&test_##_X, filler, sizeof(test_##_X));\
  if (val(test_##_X,c) != exp_##_X##_c)         \
     abort();                                   \
}

#define check_struct_size(_X) \
{ \
  if (sizeof (struct _X) != exp_sizeof_##_X )   \
    abort();                                    \
}

#define check_struct_off(_X) \
{ \
  memcpy(&test_##_X, filler, sizeof(test_##_X));\
  if (val(test_##_X,c) != exp_##_X##_c)         \
    abort();                                    \
}

#define check_union_size(_X) \
{ \
  if (sizeof (union _X) != exp_sizeof_##_X )    \
    abort();                                    \
}

#define check_union_off(_X) \
{ \
  memcpy(&test_##_X, filler, sizeof(test_##_X));\
  if (val(test_##_X,c) != exp_##_X##_c)         \
    abort();                                    \
}

int main(){

  unsigned char filler[16];
  struct one test_one;
  struct two test_two;
  struct three test_three;
  struct four test_four;
  struct five test_five;
  struct six test_six;
  struct seven test_seven;
  struct eight test_eight;
  union nine test_nine;
  struct ten test_ten;

#if defined (_TEST_MS_LAYOUT) || defined (_MSC_VER)
  size_t exp_sizeof_one = 12;
  size_t exp_sizeof_two = 16;
  size_t exp_sizeof_three =6;
  size_t exp_sizeof_four = 8;
  size_t exp_sizeof_five = 3;
  size_t exp_sizeof_six = 8;
  size_t exp_sizeof_seven = 3;
  size_t exp_sizeof_eight = 4;
  size_t exp_sizeof_nine = 8;
  size_t exp_sizeof_ten = 16;

  unsigned char exp_one_c = 8;
  unsigned char exp_two_c  = 12;
  unsigned char exp_three_c = 4;
  unsigned char exp_four_c = 4;
  char exp_five_c = 2;
  char exp_six_c = 5;
  char exp_seven_c = 2;
  char exp_eight_c = 2;
  char exp_nine_c = 0;
  char exp_ten_c = 8;

#else /* testing -mno-ms-bitfields */

  size_t exp_sizeof_one = 8;
  size_t exp_sizeof_two = 8;
  size_t exp_sizeof_three = 6;
  size_t exp_sizeof_four = 6;
  size_t exp_sizeof_five = 6;
  size_t exp_sizeof_six = 6;
  size_t exp_sizeof_seven = 6;
  size_t exp_sizeof_eight = 2;
  size_t exp_sizeof_nine = 8;
  size_t exp_sizeof_ten = 8;

  unsigned short exp_one_c = 6;
  unsigned int exp_two_c  = 6;
  unsigned char exp_three_c = 64;
  unsigned char exp_four_c = 4;
  char exp_five_c = 5;
  char exp_six_c = 5;
  char exp_seven_c = 5;
  char exp_eight_c = 1;
  char exp_nine_c = 0;
  char exp_ten_c = 1;

#endif

  unsigned char i;
  for ( i = 0; i < 16; i++ )
    filler[i] = i;

  check_struct_off (one);
  check_struct_off (two);
  check_struct_off (three);
  check_struct_off (four);
  check_struct_off (five);
  check_struct_off (six);
  check_struct_off (seven);
  check_struct_off (eight);
  check_union_off (nine);
  check_struct_off (ten);

  check_struct_size (one);
  check_struct_size (two);
  check_struct_size (three);
  check_struct_size (four);
  check_struct_size (five);
  check_struct_size (six);
  check_struct_size (seven);
  check_struct_size (eight);
  check_union_size (nine);
  check_struct_size (ten);
  return 0;
}

which is the patched version of bf-ms-layout.c, and so does:
#define _TEST_MS_LAYOUT
#include <stddef.h>
#include <string.h>

extern void abort();

#pragma pack(8)

#ifdef __GNUC__
#define ATTR __attribute__ ((ms_struct))
#else
#define ATTR
#endif

struct one {
  int d;
  unsigned char a;
  unsigned short b:7;
  char c;
} ATTR;

struct two {
  int d;
  unsigned char a;
  unsigned int b:7;
  char c;
} ATTR;

struct three {
  short d;
  unsigned short a:3;
  unsigned short b:9;
  unsigned char c:7;
} ATTR;


/* Bitfields of size 0 have some truly odd behaviors. */

struct four {
  unsigned short a:3;
  unsigned short b:9;
  unsigned int :0;  /* forces struct alignment to int */
  unsigned char c:7;
} ATTR;

struct five {
  char a;
  int :0;        /* ignored; prior field is not a bitfield. */
  char b;
  char c;
} ATTR;

struct six {
  char a :8;
  int :0;       /* not ignored; prior field IS a bitfield, causes
                   struct alignment as well. */
  char b;
  char c;
} ATTR;

struct seven {
  char a:8;
  char :0;
  int  :0;      /* Ignored; prior field is zero size bitfield. */
  char b;
  char c;
} ATTR;

struct eight { /* ms size 4 */
  short b:3;
  char  c;
} ATTR;

#ifdef _MSC_VER
#define LONGLONG __int64
#else
#define LONGLONG long long
#endif

union nine {   /* ms size 8 */
  LONGLONG a:3;
  char  c;
} ATTR;

struct ten {   /* ms size 16 */
  LONGLONG a:3;
  LONGLONG b:3;
  char  c;
} ATTR;


#define val(s,f) (s.f)

#define check_struct(_X) \
{ \
  if (sizeof (struct _X) != exp_sizeof_##_X )   \
    abort();                                    \
  memcpy(&test_##_X, filler, sizeof(test_##_X));\
  if (val(test_##_X,c) != exp_##_X##_c)         \
     abort();                                   \
}

#define check_union(_X) \
{ \
  if (sizeof (union _X) != exp_sizeof_##_X )    \
    abort();                                    \
  memcpy(&test_##_X, filler, sizeof(test_##_X));\
  if (val(test_##_X,c) != exp_##_X##_c)         \
     abort();                                   \
}

#define check_struct_size(_X) \
{ \
  if (sizeof (struct _X) != exp_sizeof_##_X )   \
    abort();                                    \
}

#define check_struct_off(_X) \
{ \
  memcpy(&test_##_X, filler, sizeof(test_##_X));\
  if (val(test_##_X,c) != exp_##_X##_c)         \
    abort();                                    \
}

#define check_union_size(_X) \
{ \
  if (sizeof (union _X) != exp_sizeof_##_X )    \
    abort();                                    \
}

#define check_union_off(_X) \
{ \
  memcpy(&test_##_X, filler, sizeof(test_##_X));\
  if (val(test_##_X,c) != exp_##_X##_c)         \
    abort();                                    \
}

int main(){

  unsigned char filler[16];
  struct one test_one;
  struct two test_two;
  struct three test_three;
  struct four test_four;
  struct five test_five;
  struct six test_six;
  struct seven test_seven;
  struct eight test_eight;
  union nine test_nine;
  struct ten test_ten;

#if defined (_TEST_MS_LAYOUT) || defined (_MSC_VER)
  size_t exp_sizeof_one = 12;
  size_t exp_sizeof_two = 16;
  size_t exp_sizeof_three =6;
  size_t exp_sizeof_four = 8;
  size_t exp_sizeof_five = 3;
  size_t exp_sizeof_six = 8;
  size_t exp_sizeof_seven = 3;
  size_t exp_sizeof_eight = 4;
  size_t exp_sizeof_nine = 8;
  size_t exp_sizeof_ten = 16;

  unsigned char exp_one_c = 8;
  unsigned char exp_two_c  = 12;
  unsigned char exp_three_c = 4;
  unsigned char exp_four_c = 4;
  char exp_five_c = 2;
  char exp_six_c = 5;
  char exp_seven_c = 2;
  char exp_eight_c = 2;
  char exp_nine_c = 0;
  char exp_ten_c = 8;

#else /* testing -mno-ms-bitfields */

  size_t exp_sizeof_one = 8;
  size_t exp_sizeof_two = 8;
  size_t exp_sizeof_three = 6;
  size_t exp_sizeof_four = 6;
  size_t exp_sizeof_five = 6;
  size_t exp_sizeof_six = 6;
  size_t exp_sizeof_seven = 6;
  size_t exp_sizeof_eight = 2;
  size_t exp_sizeof_nine = 8;
  size_t exp_sizeof_ten = 8;

  unsigned short exp_one_c = 6;
  unsigned int exp_two_c  = 6;
  unsigned char exp_three_c = 64;
  unsigned char exp_four_c = 4;
  char exp_five_c = 5;
  char exp_six_c = 5;
  char exp_seven_c = 5;
  char exp_eight_c = 1;
  char exp_nine_c = 0;
  char exp_ten_c = 1;

#endif

  unsigned char i;
  for ( i = 0; i < 16; i++ )
    filler[i] = i;

  check_struct_off (one);
  check_struct_off (two);
  check_struct_off (three);
  check_struct_off (four);
  check_struct_off (five);
  check_struct_off (six);
  check_struct_off (seven);
  check_struct_off (eight);
  check_union_off (nine);
  check_struct_off (ten);

  check_struct_size (one);
  check_struct_size (two);
  check_struct_size (three);
  check_struct_size (four);
  check_struct_size (five);
  check_struct_size (six);
  check_struct_size (seven);
  check_struct_size (eight);
  check_union_size (nine);
  check_struct_size (ten);

  return 0;
};

which is the patched version of bf-ms-layout-2.c (with ATTR defined to nothing
for non-__GNUC__), again the unpatched version fails.

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]