
This just adds a warning for bitfields placed next to other bitfields where the underlying type has different storage. Under the MS struct bitfield packing ABI such bitfields are not packed.
197 lines
5.3 KiB
C++
197 lines
5.3 KiB
C++
|
|
// RUN: %clang_cc1 -fsyntax-only -Wms-bitfield-padding -verify -triple armv8 -std=c++23 %s
|
|
// RUN: %clang_cc1 -fsyntax-only -DMS_BITFIELDS -mms-bitfields -verify=msbitfields -triple armv8-apple-macos10.15 -std=c++23 %s
|
|
|
|
// msbitfields-no-diagnostics
|
|
|
|
enum Enum1 { Enum1_A, Enum1_B };
|
|
enum Enum2 { Enum2_A, Enum2_B };
|
|
|
|
enum class EnumU32_1 : unsigned { A, B };
|
|
enum class EnumU32_2 : unsigned { A, B };
|
|
enum class EnumU64 : unsigned long long { A, B };
|
|
enum class EnumI32 : int { A, B };
|
|
enum class EnumU8 : unsigned char { A, B };
|
|
enum class EnumI8 : char { A, B };
|
|
enum class EnumU16 : unsigned short { A, B };
|
|
enum class EnumI16 : short { A, B };
|
|
|
|
struct A {
|
|
unsigned int a : 15;
|
|
unsigned int b : 15;
|
|
};
|
|
static_assert(sizeof(A) == 4);
|
|
|
|
struct B {
|
|
unsigned int a : 15;
|
|
int b : 15;
|
|
};
|
|
static_assert(sizeof(B) == 4);
|
|
|
|
struct C {
|
|
unsigned int a : 15;
|
|
int b : 15;
|
|
};
|
|
static_assert(sizeof(C) == 4);
|
|
|
|
struct D {
|
|
Enum1 a : 15;
|
|
Enum1 b : 15;
|
|
};
|
|
static_assert(sizeof(D) == 4);
|
|
|
|
struct E {
|
|
Enum1 a : 15;
|
|
Enum2 b : 15;
|
|
};
|
|
static_assert(sizeof(E) == 4);
|
|
|
|
struct F {
|
|
EnumU32_1 a : 15;
|
|
EnumU32_2 b : 15;
|
|
};
|
|
static_assert(sizeof(F) == 4);
|
|
|
|
struct G {
|
|
EnumU32_1 a : 15;
|
|
EnumU64 b : 15;
|
|
// expected-warning@-1 {{bit-field 'b' of type 'EnumU64' has a different storage size than the preceding bit-field (8 vs 4 bytes) and will not be packed under the Microsoft ABI}}
|
|
// expected-note@-3 {{preceding bit-field 'a' declared here with type 'EnumU32_1'}}
|
|
};
|
|
|
|
#ifdef MS_BITFIELDS
|
|
static_assert(sizeof(G) == 16);
|
|
#else
|
|
static_assert(sizeof(G) == 8);
|
|
#endif
|
|
|
|
struct H {
|
|
EnumU32_1 a : 10;
|
|
EnumI32 b : 10;
|
|
EnumU32_1 c : 10;
|
|
};
|
|
static_assert(sizeof(H) == 4);
|
|
|
|
struct I {
|
|
EnumU8 a : 3;
|
|
EnumI8 b : 5;
|
|
EnumU32_1 c : 10;
|
|
// expected-warning@-1 {{bit-field 'c' of type 'EnumU32_1' has a different storage size than the preceding bit-field (4 vs 1 bytes) and will not be packed under the Microsoft ABI}}
|
|
// expected-note@-3 {{preceding bit-field 'b' declared here with type 'EnumI8'}}
|
|
};
|
|
#ifdef MS_BITFIELDS
|
|
static_assert(sizeof(I) == 8);
|
|
#else
|
|
static_assert(sizeof(I) == 4);
|
|
#endif
|
|
|
|
struct J {
|
|
EnumU8 : 0;
|
|
EnumU8 b : 4;
|
|
};
|
|
static_assert(sizeof(J) == 1);
|
|
|
|
struct K {
|
|
EnumU8 a : 4;
|
|
EnumU8 : 0;
|
|
};
|
|
static_assert(sizeof(K) == 1);
|
|
|
|
struct L {
|
|
EnumU32_1 a : 10;
|
|
EnumU32_2 b : 10;
|
|
EnumU32_1 c : 10;
|
|
};
|
|
|
|
static_assert(sizeof(L) == 4);
|
|
|
|
struct M {
|
|
EnumU32_1 a : 10;
|
|
EnumI32 b : 10;
|
|
EnumU32_1 c : 10;
|
|
};
|
|
|
|
static_assert(sizeof(M) == 4);
|
|
|
|
struct N {
|
|
EnumU32_1 a : 10;
|
|
EnumU64 b : 10;
|
|
// expected-warning@-1 {{bit-field 'b' of type 'EnumU64' has a different storage size than the preceding bit-field (8 vs 4 bytes) and will not be packed under the Microsoft ABI}}
|
|
// expected-note@-3 {{preceding bit-field 'a' declared here with type 'EnumU32_1'}}
|
|
EnumU32_1 c : 10;
|
|
// expected-warning@-1 {{bit-field 'c' of type 'EnumU32_1' has a different storage size than the preceding bit-field (4 vs 8 bytes) and will not be packed under the Microsoft ABI}}
|
|
// expected-note@-5 {{preceding bit-field 'b' declared here with type 'EnumU64'}}
|
|
};
|
|
|
|
#ifdef MS_BITFIELDS
|
|
static_assert(sizeof(N) == 24);
|
|
#else
|
|
static_assert(sizeof(N) == 8);
|
|
#endif
|
|
|
|
struct O {
|
|
EnumU16 a : 10;
|
|
EnumU32_1 b : 10;
|
|
// expected-warning@-1 {{bit-field 'b' of type 'EnumU32_1' has a different storage size than the preceding bit-field (4 vs 2 bytes) and will not be packed under the Microsoft ABI}}
|
|
// expected-note@-3 {{preceding bit-field 'a' declared here with type 'EnumU16'}}
|
|
};
|
|
#ifdef MS_BITFIELDS
|
|
static_assert(sizeof(O) == 8);
|
|
#else
|
|
static_assert(sizeof(O) == 4);
|
|
#endif
|
|
|
|
struct P {
|
|
EnumU32_1 a : 10;
|
|
EnumU16 b : 10;
|
|
// expected-warning@-1 {{bit-field 'b' of type 'EnumU16' has a different storage size than the preceding bit-field (2 vs 4 bytes) and will not be packed under the Microsoft ABI}}
|
|
// expected-note@-3 {{preceding bit-field 'a' declared here with type 'EnumU32_1'}}
|
|
};
|
|
#ifdef MS_BITFIELDS
|
|
static_assert(sizeof(P) == 8);
|
|
#else
|
|
static_assert(sizeof(P) == 4);
|
|
#endif
|
|
|
|
struct Q {
|
|
EnumU8 a : 6;
|
|
EnumU16 b : 6;
|
|
// expected-warning@-1 {{bit-field 'b' of type 'EnumU16' has a different storage size than the preceding bit-field (2 vs 1 bytes) and will not be packed under the Microsoft ABI}}
|
|
// expected-note@-3 {{preceding bit-field 'a' declared here with type 'EnumU8'}}
|
|
};
|
|
#ifdef MS_BITFIELDS
|
|
static_assert(sizeof(Q) == 4);
|
|
#else
|
|
static_assert(sizeof(Q) == 2);
|
|
#endif
|
|
|
|
struct R {
|
|
EnumU16 a : 9;
|
|
EnumU16 b : 9;
|
|
EnumU8 c : 6;
|
|
// expected-warning@-1 {{bit-field 'c' of type 'EnumU8' has a different storage size than the preceding bit-field (1 vs 2 bytes) and will not be packed under the Microsoft ABI}}
|
|
// expected-note@-3 {{preceding bit-field 'b' declared here with type 'EnumU16'}}
|
|
};
|
|
|
|
#ifdef MS_BITFIELDS
|
|
static_assert(sizeof(R) == 6);
|
|
#else
|
|
static_assert(sizeof(R) == 4);
|
|
#endif
|
|
|
|
struct S {
|
|
char a : 4;
|
|
char b : 4;
|
|
char c : 4;
|
|
char d : 4;
|
|
short x : 7;
|
|
// expected-warning@-1 {{bit-field 'x' of type 'short' has a different storage size than the preceding bit-field (2 vs 1 bytes) and will not be packed under the Microsoft ABI}}
|
|
// expected-note@-3 {{preceding bit-field 'd' declared here with type 'char'}}
|
|
// This is a false positive. Reporting this correctly requires duplicating the record layout process
|
|
// in target and MS layout modes, and it's also unclear if that's the correct choice for users of
|
|
// this diagnostic.
|
|
short y : 9;
|
|
};
|
|
|
|
static_assert(sizeof(S) == 4);
|