Hello,
We are using Clang for generating reflection data and ran into an issue with how Microsoft lays out bitfields. Here's the structure we were having a problem with:
struct reflected woof
{
bool m_b1 : 1 reflected; // Clang bit offset: 0, MS bit offset: 0
bool m_b2 : 1 reflected; // Clang bit offset: 1, MS bit offset: 1
bool m_b3 : 1 reflected; // Clang bit offset: 2, MS bit offset: 2
bool m_b4 : 1 reflected; // Clang bit offset: 3, MS bit offset: 3
uint m_i1 reflected; // Clang bit offset: 32, MS bit offset: 32
uint m_i2 : 5 reflected; // Clang bit offset: 64, MS bit offset: 64
uint m_i3 : 8 reflected; // Clang bit offset: 69, MS bit offset: 69
uint16 m_i5 : 2 reflected; // Clang bit offset: 77, MS bit offset: 96
uint8 m_i4 : 2 reflected;
uint8 m_ix1 : 2;
uint16 m_i6 : 6 reflected;
};
When compiling with Clang the bit offset of "m_i5" is 77, while when compiling with VS 2010 the bit offset is 96. We tried compiling with the "-mms-bitfields" command-line parameter but it didn't change the results. We stepped through Clang code and discovered that the "RecordLayoutBuilder::LayoutFields" function is looking for the "IsMsStruct" attribute. So we tried adding __attribute__((ms_struct)) to the structure and that fixed the problem. Adding "#pragma ms_struct on" also worked. We were wondering if the code inside "RecordLayoutBuilder::LayoutFields" should be checking "Context.getLangOpts().MSBitfields" along with "IsMsStruct":
for (RecordDecl::field_iterator Field = D->field_begin(),
FieldEnd = D->field_end(); Field != FieldEnd; ++Field) {
if (IsMsStruct) { // <-- Should this check Context.getLangOpts().MSBitfields?
FieldDecl *FD = *Field;
if (Context.ZeroBitfieldFollowsBitfield(FD, LastFD))
ZeroLengthBitfield = FD;
...
if (IsMsStruct && RemainingInAlignment && // <-- Should this check Context.getLangOpts().MSBitfields?
LastFD && LastFD->isBitField() && LastFD->getBitWidthValue(Context)) {
Thanks for your help!
Jeremiah Zanin