Files
codeql/cpp/ql/test/library-tests/padding/bitfields.c
2018-08-02 17:53:23 +01:00

215 lines
5.2 KiB
C

#include "size_asserts.h"
// Bitfield packing:
// (1) A struct containing a bitfield with declared type T (e.g. T bf : 7) will be aligned as if it
// contained an actual member variable of type T. Thus, a struct containing a bitfield 'unsigned int bf : 8'
// will have an alignment of at least alignof(unsigned int), even though the bitfield was only 8 bits.
// (2) If a bitfield with declared type T would straddle a sizeof(T) boundary, padding is inserted
// before the bitfield to align it on an alignof(T) boundary. Note the subtle distinction between alignof
// and sizeof. This matters for 32-bit Linux, where sizeof(long long) == 8, but alignof(long long) == 4.
// (3) [MSVC only!] If a bitfield with declared type T immediately follows another bitfield with declared type P,
// and sizeof(P) != sizeof(T), padding will be inserted to align the new bitfield to a boundary of
// max(alignof(P), alignof(T)).
struct Bitfield_Straddle {
// 0
unsigned int bf0 : 24;
// 3
// Pad 1
// 4
unsigned int bf1 : 24;
// 7
// Pad 1
// 8
unsigned int bf2 : 16;
// 10
// Pad 2
// 12
};
CASSERT(sizeof(struct Bitfield_Straddle) == 12);
struct Bitfield_longlong_25 {
// 0
char c;
// 1
// Pad 7(MSVC); 0(GCC)
// 8(MSVC); 1(GCC)
unsigned long long bf : 25;
// 11.1(MSVC); 4.1(GCC)
// Pad 4.7(MSVC); 3.7(GCC)
// 16(MSVC); 8(GCC)
};
CASSERT_MSVC(sizeof(struct Bitfield_longlong_25) == 16);
CASSERT_GCC(sizeof(struct Bitfield_longlong_25) == 8);
struct Bitfield_longlong_57 {
// 0
char c;
// 1
// Pad 7(MSVC, GCC64); 3(GCC32)
// 8(MSVC, GCC64); 4(GCC32)
unsigned long long bf : 57;
// 15.1(MSVC, GCC64); 11.1(GCC32)
// Padd 0.7
// 16(MSVC, GCC64); 12(GCC32)
};
CASSERT_MSVC(sizeof(struct Bitfield_longlong_57) == 16);
CASSERT_GCC64(sizeof(struct Bitfield_longlong_57) == 16);
CASSERT_GCC32(sizeof(struct Bitfield_longlong_57) == 12);
struct Bitfield_Int7 {
// 0
char c;
// 1
// Pad 3(MSVC); 0(GCC)
// 4(MSVC); 1(GCC)
unsigned int bf : 7;
// 4.7(MSVC); 1.7(GCC)
// Pad 3.1(MSVC); 2.1(GCC)
// 8(MSVC); 4(GCC)
};
CASSERT_MSVC(sizeof(struct Bitfield_Int7) == 8);
CASSERT_GCC(sizeof(struct Bitfield_Int7) == 4);
struct Bitfield_Int8 {
// 0
char c;
// 1
// Pad 3(MSVC); 0(GCC)
// 4(MSVC); 1(GCC)
unsigned int bf : 8;
// 5(MSVC); 2(GCC)
// Pad 3(MSVC); 2(GCC)
// 8(MSVC); 4(GCC)
};
CASSERT_MSVC(sizeof(struct Bitfield_Int8) == 8);
CASSERT_GCC(sizeof(struct Bitfield_Int8) == 4);
struct Bitfield_Int9 {
// 0
char c;
// 1
// Pad 3(MSVC); 0(GCC)
// 4(MSVC); 1(GCC)
unsigned int bf : 9;
// 5.1(MSVC); 2.1(GCC)
// Pad 2.7(MSVC); 1.7(GCC)
// 8(MSVC); 4(GCC)
};
CASSERT_MSVC(sizeof(struct Bitfield_Int9) == 8);
CASSERT_GCC(sizeof(struct Bitfield_Int9) == 4);
struct Bitfield_Short7 {
// 0
char c;
// 1
// Pad 1(MSVC); 0(GCC)
// 2(MSVC); 1(GCC)
unsigned short bf : 7;
// 2.7(MSVC); 1.7(GCC)
// Pad 1.1(MSVC); 0.1(GCC)
// 4(MSVC); 2(GCC)
};
CASSERT_MSVC(sizeof(struct Bitfield_Short7) == 4);
CASSERT_GCC(sizeof(struct Bitfield_Short7) == 2);
struct Bitfield_Short8 {
// 0
char c;
// 1
// Pad 1(MSVC); 0(GCC)
// 2(MSVC); 1(GCC)
unsigned short bf : 8;
// 3(MSVC); 2(GCC)
// Pad 1(MSVC); 0(GCC)
// 4(MSVC); 2(GCC)
};
CASSERT_MSVC(sizeof(struct Bitfield_Short8) == 4);
CASSERT_GCC(sizeof(struct Bitfield_Short8) == 2);
struct Bitfield_Short9 {
// 0
char c;
// 1
// Pad 1
// 2
unsigned short bf : 9;
// 3.1
// Pad 0.7(MSVC)
// 4
};
CASSERT_MSVC(sizeof(struct Bitfield_Short9) == 4);
CASSERT_GCC(sizeof(struct Bitfield_Short9) == 4);
struct Bitfield_Mixed {
// 0
unsigned char bfc : 2;
// 0.2
// Pad 3.6(MSVC); 0(GCC)
// 4(MSVC); 0.2(GCC)
unsigned int bfi : 7;
// 4.7(MSVC); 1.1(GCC)
// Pad 3.1(MSVC); 0(GCC)
// 8(MSVC); 1.1(GCC)
unsigned short bfs : 7;
// 8.7(MSVC); 2(GCC)
// Pad 3.1(MSVC); 0(GCC)
};
CASSERT_MSVC(sizeof(struct Bitfield_Mixed) == 12);
CASSERT_GCC(sizeof(struct Bitfield_Mixed) == 4);
typedef char CHAR;
typedef short SHORT;
struct Bitfield_TypeEquality_char {
char x : 2;
const char y : 2;
};
CASSERT(sizeof(struct Bitfield_TypeEquality_char) == 1);
struct Bitfield_TypeEquality_char_uchar {
char x : 2;
unsigned char y : 2;
};
CASSERT(sizeof(struct Bitfield_TypeEquality_char_uchar) == 1);
struct Bitfield_TypeEquality_char_schar {
char x : 2;
signed char y : 2;
};
CASSERT(sizeof(struct Bitfield_TypeEquality_char_schar) == 1);
struct Bitfield_TypeEquality_char_CHAR {
char x : 2;
CHAR y : 2;
};
CASSERT(sizeof(struct Bitfield_TypeEquality_char_CHAR) == 1);
struct Bitfield_TypeEquality_short {
short x : 2;
short y : 2;
};
CASSERT(sizeof(struct Bitfield_TypeEquality_short) == 2);
struct Bitfield_TypeEquality_short_ushort {
short x : 2;
unsigned short y : 2;
};
CASSERT(sizeof(struct Bitfield_TypeEquality_short_ushort) == 2);
struct Bitfield_TypeEquality_int_long {
int x : 2;
long y : 2;
};
CASSERT_MSVC(sizeof(struct Bitfield_TypeEquality_int_long) == 4);
CASSERT_GCC32(sizeof(struct Bitfield_TypeEquality_int_long) == 4);
CASSERT_GCC64(sizeof(struct Bitfield_TypeEquality_int_long) == 8);
struct Bitfield_TypeEquality_int_ulong {
int x : 2;
unsigned long y : 2;
};
CASSERT_MSVC(sizeof(struct Bitfield_TypeEquality_int_long) == 4);
CASSERT_GCC32(sizeof(struct Bitfield_TypeEquality_int_long) == 4);
CASSERT_GCC64(sizeof(struct Bitfield_TypeEquality_int_long) == 8);