Skip to content

Commit

Permalink
Visual Studio packs bit-fields differently
Browse files Browse the repository at this point in the history
  • Loading branch information
Daniel Kroening committed Jun 12, 2018
1 parent 19cfa50 commit 1d93fa1
Show file tree
Hide file tree
Showing 7 changed files with 394 additions and 88 deletions.
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

0 comments on commit 1d93fa1

Please sign in to comment.