Skip to content

Fix Visual Studio bit-field alignment #2329

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jun 12, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion appveyor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,6 @@ test_script:
rmdir /s /q ansi-c\arch_flags_mthumb_good
rmdir /s /q ansi-c\Forward_Declaration2
rmdir /s /q ansi-c\Incomplete_Type1
rmdir /s /q ansi-c\Union_Padding1
rmdir /s /q ansi-c\Universal_characters1
rmdir /s /q ansi-c\gcc_attributes7
rmdir /s /q ansi-c\gcc_version1
Expand Down
1 change: 0 additions & 1 deletion buildspec-windows.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ phases:
Remove-Item ansi-c\arch_flags_mthumb_good -Force -Recurse
Remove-Item ansi-c\Forward_Declaration2 -Force -Recurse
Remove-Item ansi-c\Incomplete_Type1 -Force -Recurse
Remove-Item ansi-c\Union_Padding1 -Force -Recurse
Remove-Item ansi-c\gcc_attributes7 -Force -Recurse
Remove-Item ansi-c\gcc_version1 -Force -Recurse
Remove-Item cbmc\Malloc23 -Force -Recurse
Expand Down
9 changes: 7 additions & 2 deletions regression/ansi-c/Struct_Padding3/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -99,8 +99,8 @@ struct my_struct3 {
char ch3;
long long i2; // this should be padded for 8-byte alignment
char ch4;
int bf1:1; // this should not be padded
int bf2:1; // this should not be padded
int bf1 : 1; // MSVC pads this, the gcc/clang do not
int bf2 : 1; // MSVC pads this, the gcc/clang do not
int i3; // this should be padded for 4-byte alignment
};

Expand All @@ -110,7 +110,12 @@ STATIC_ASSERT(__builtin_offsetof(struct my_struct3, i1)==4);
STATIC_ASSERT(__builtin_offsetof(struct my_struct3, ch3)==8);
STATIC_ASSERT(__builtin_offsetof(struct my_struct3, i2)==16);
STATIC_ASSERT(__builtin_offsetof(struct my_struct3, ch4)==24);

#ifdef _MSC_VER
STATIC_ASSERT(__builtin_offsetof(struct my_struct3, i3) == 32);
#else
STATIC_ASSERT(__builtin_offsetof(struct my_struct3, i3)==28);
#endif

int main()
{
Expand Down
132 changes: 119 additions & 13 deletions regression/ansi-c/Struct_Padding4/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,45 +7,151 @@ struct Z1
int i:3;
char ch2;
// there is end-of-struct padding because of the int
} z1;
};

STATIC_ASSERT(_Alignof(struct Z1) == _Alignof(int));

#ifdef _MSC_VER
STATIC_ASSERT(sizeof(struct Z1) == 4 + 4 + 4);
#else
STATIC_ASSERT(sizeof(struct Z1) == 1 + 1 + 1 + 1);
#ifdef __GNUC__
STATIC_ASSERT(__builtin_offsetof(struct Z1, ch2) == 2);
#endif
#endif

#pragma pack(push, 1)
struct Z1_packed
{
char ch;
int i : 3;
char ch2;
// there is no end-of-struct padding
};
#pragma pack(pop)

STATIC_ASSERT(_Alignof(struct Z1_packed) == 1);

#ifdef _MSC_VER
STATIC_ASSERT(sizeof(struct Z1_packed) == 1 + 4 + 1);
#else
STATIC_ASSERT(sizeof(struct Z1_packed) == 1 + 1 + 1);
#ifdef __GNUC__
STATIC_ASSERT(__builtin_offsetof(struct Z1_packed, ch2) == 2);
#endif
#endif

struct Z2
{
char ch;
char i:3;
char ch2;
// there is no end-of-struct padding
} z2;
};

STATIC_ASSERT(sizeof(struct Z2) == 1 + 1 + 1);

#pragma pack(push, 1)
struct Z2_packed
{
char ch;
char i : 3;
char ch2;
// there is no end-of-struct padding
};
#pragma pack(pop)

STATIC_ASSERT(sizeof(struct Z2_packed) == 1 + 1 + 1);

struct Z3
{
char ch;
int i:3; // bit-fields do not get padding!
} z3;
int i : 3; // padded by MSVC, not by gcc/clang
};

#ifdef _MSC_VER
STATIC_ASSERT(sizeof(struct Z3) == 4 + 4);
#else
STATIC_ASSERT(sizeof(struct Z3) == 1 + 1 + 2);
#endif

#pragma pack(push, 1)
struct Z3_packed
{
char ch;
int i : 3; // padded by MSVC, not by gcc/clang
};
#pragma pack(pop)

#ifdef _MSC_VER
STATIC_ASSERT(sizeof(struct Z3_packed) == 1 + 4);
#else
STATIC_ASSERT(sizeof(struct Z3_packed) == 1 + 1);
#endif

struct Z4
{
int i;
long long int x; // pads to 8
char ch; // 7 end-of-struct padding
} z4;
};

STATIC_ASSERT(sizeof(struct Z4) == 4 + 4 + 8 + 1 + 7);

#pragma pack(push, 1)
struct Z4_packed
{
int i;
long long int x; // no padding
char ch; // no end-of-struct padding
};
#pragma pack(pop)

STATIC_ASSERT(sizeof(struct Z4_packed) == 4 + 8 + 1);

struct Z5
{
char ch;
long long int x[]; // pads to 8, but has no size
} z5;
};

STATIC_ASSERT(sizeof(struct Z1)==1+1+1+1);
STATIC_ASSERT(sizeof(struct Z5) == 8);

#ifdef __GNUC__
STATIC_ASSERT(__builtin_offsetof(struct Z1, ch2)==2);
#pragma pack(push, 1)
struct Z5_packed
{
char ch;
long long int x[]; // pads to 8, but has no size
};
#pragma pack(pop)

STATIC_ASSERT(sizeof(struct Z5_packed) == 1);

struct Z6
{
char ch;
int i : 16; // padded to int by MSVC, to short by gcc/clang
};

#ifdef _MSC_VER
STATIC_ASSERT(sizeof(struct Z6) == 4 + 4);
#else
STATIC_ASSERT(sizeof(struct Z6) == 1 + 1 + 2);
#endif

STATIC_ASSERT(sizeof(struct Z2)==1+1+1);
STATIC_ASSERT(sizeof(struct Z3)==1+1+2);
STATIC_ASSERT(sizeof(struct Z4)==4+4+8+1+7);
STATIC_ASSERT(sizeof(struct Z5)==8);
#pragma pack(push, 1)
struct Z6_packed
{
char ch;
int i : 16; // padded to int by MSC, but not aligned
};
#pragma pack(pop)

#ifdef _MSC_VER
STATIC_ASSERT(sizeof(struct Z6_packed) == 1 + 4);
#else
STATIC_ASSERT(sizeof(struct Z6_packed) == 1 + 2);
#endif

int main()
{
Expand Down
40 changes: 40 additions & 0 deletions regression/ansi-c/Struct_Padding5/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,46 @@ STATIC_ASSERT(sizeof(struct flowi)==8);
STATIC_ASSERT(__builtin_offsetof(struct flowi, flexible)==1);
#endif

// bit-fields are very evil
#pragma pack(push, 1)
struct bit_field0
{
int i : 23;
};

struct bit_field1
{
int i : 1;
unsigned int j : 1;
// in MSC, it matters that the underlying type changes!
short c : 1;
};

struct bit_field2
{
int i : 23;
char ch;
};
#pragma pack(pop)

struct bit_field3
{
int i : 23;
char ch;
};

#ifdef _MSC_VER
STATIC_ASSERT(sizeof(struct bit_field0) == 4);
STATIC_ASSERT(sizeof(struct bit_field1) == 6);
STATIC_ASSERT(sizeof(struct bit_field2) == 5);
STATIC_ASSERT(sizeof(struct bit_field3) == 8);
#else
STATIC_ASSERT(sizeof(struct bit_field0) == 3);
STATIC_ASSERT(sizeof(struct bit_field1) == 1);
STATIC_ASSERT(sizeof(struct bit_field2) == 4);
STATIC_ASSERT(sizeof(struct bit_field3) == 4);
#endif

int main()
{
}
24 changes: 15 additions & 9 deletions regression/ansi-c/Union_Padding1/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,14 +41,16 @@ STATIC_ASSERT(sizeof(union some_union3)==sizeof(int));
#ifdef _MSC_VER

// bit-fields are evil
#pragma pack(1)
#pragma pack(push, 1)
union some_union4
{
int i:23;
};
#pragma pack(pop)

// Visual Studio ignores the 'packed'
STATIC_ASSERT(sizeof(union some_union4)==sizeof(int));
STATIC_ASSERT(__alignof(union some_union4) == 1);

#else

Expand All @@ -59,34 +61,38 @@ union some_union4
} __attribute__((__packed__));

STATIC_ASSERT(sizeof(union some_union4)==3);
STATIC_ASSERT(_Alignof(union some_union4) == 1);

#endif

#ifdef _MSC_VER

union some_union5
{
int i;
};

STATIC_ASSERT(__alignof(union some_union5)==1);

#ifdef _MSC_VER
STATIC_ASSERT(__alignof(union some_union5) == 4);
#else
STATIC_ASSERT(_Alignof(union some_union5) == 4);
#endif

union some_union5
{
#ifdef _MSC_VER
#pragma pack(push, 1)
union some_union6 {
int i;
};
#pragma pack(pop)

// Packing may affect alignment
STATIC_ASSERT(__alignof(union some_union6) == 1);
#else
union some_union6
{
int i;
} __attribute__((__packed__));

// Packing may affect alignment
STATIC_ASSERT(_Alignof(union some_union5)==4);
STATIC_ASSERT(_Alignof(union some_union6)==1);

#endif

int main()
Expand Down
Loading