/// __declspec(align) into account. It also updates RequiredAlignment as a
/// side effect because it is most convenient to do so here.
ElementInfo getAdjustedElementInfo(const FieldDecl *FD);
- /// \brief Updates the alignment of the record.
- void updateAlignment(CharUnits MemberAlignment) {
- Alignment = std::max(Alignment, MemberAlignment);
- }
/// \brief Places a field at an offset in CharUnits.
void placeFieldAtOffset(CharUnits FieldOffset) {
FieldOffsets.push_back(Context.toBits(FieldOffset));
if (Layout.hasZeroSizedSubObject())
HasZeroSizedSubObject = true;
// Respect required alignment, this is necessary because we may have adjusted
- // the alignment in the case of pragam pack.
+ // the alignment in the case of pragam pack. Note that the required alignment
+ // doesn't actually apply to the struct alignment at this point.
+ Alignment = std::max(Alignment, Info.Alignment);
Info.Alignment = std::max(Info.Alignment, Layout.getRequiredAlignment());
Info.Size = Layout.getDataSize();
return Info;
// Capture required alignment as a side-effect.
RequiredAlignment = std::max(RequiredAlignment, FieldRequiredAlignment);
}
+ // TODO: Add a Sema warning that MS ignores bitfield alignment in unions.
+ if (!(FD->isBitField() && IsUnion))
+ Alignment = std::max(Alignment, Info.Alignment);
return Info;
}
CharUnits BaseOffset = Size.RoundUpToAlignment(Info.Alignment);
Bases.insert(std::make_pair(BaseDecl, BaseOffset));
Size = BaseOffset + BaseLayout.getDataSize();
- updateAlignment(Info.Alignment);
PreviousBaseLayout = &BaseLayout;
VBPtrOffset = Size;
}
placeFieldAtOffset(FieldOffset);
Size = FieldOffset + Info.Size;
}
- updateAlignment(Info.Alignment);
}
void MicrosoftRecordLayoutBuilder::layoutBitField(const FieldDecl *FD) {
if (IsUnion) {
placeFieldAtOffset(CharUnits::Zero());
Size = std::max(Size, Info.Size);
- // TODO: Add a Sema warning that MS ignores bitfield alignment in unions.
} else {
// Allocate a new block of memory and place the bitfield in it.
CharUnits FieldOffset = Size.RoundUpToAlignment(Info.Alignment);
placeFieldAtOffset(FieldOffset);
Size = FieldOffset + Info.Size;
- updateAlignment(Info.Alignment);
RemainingBitsInField = Context.toBits(Info.Size) - Width;
}
}
CharUnits FieldOffset = Size.RoundUpToAlignment(Info.Alignment);
placeFieldAtOffset(FieldOffset);
Size = FieldOffset;
- updateAlignment(Info.Alignment);
}
}
i != e; ++i)
if (i->second >= InjectionSite)
i->second += Offset;
- // Update the object alignment.
- updateAlignment(PointerInfo.Alignment);
// The presence of a vbptr suppresses zero sized objects that are not in
// virtual bases.
HasZeroSizedSubObject = false;
for (BaseOffsetsMapTy::iterator i = Bases.begin(), e = Bases.end();
i != e; ++i)
i->second += Offset;
- updateAlignment(PointerInfo.Alignment);
}
void MicrosoftRecordLayoutBuilder::injectVPtrs(const CXXRecordDecl *RD) {
// the record.
injectVBPtr(RD);
injectVFPtr(RD);
+ Alignment = std::max(Alignment, PointerInfo.Alignment);
return;
}
// In 64-bit mode, structs with RequiredAlignment greater than 8 get special
FieldOffsets.clear();
Bases.clear();
Size = CharUnits::Zero();
- updateAlignment(PointerInfo.Alignment);
+ Alignment = std::max(Alignment, PointerInfo.Alignment);
if (HasOwnVFPtr)
Size = PointerInfo.Size;
layoutNonVirtualBases(RD);
VBases.insert(std::make_pair(BaseDecl,
ASTRecordLayout::VBaseInfo(BaseOffset, HasVtordisp)));
Size = BaseOffset + BaseLayout.getDataSize();
- updateAlignment(Info.Alignment);
PreviousBaseLayout = &BaseLayout;
}
}
// CHECK-NEXT: 12 | char a
// CHECK-NEXT: 14 | int b
// CHECK-NEXT: | [sizeof=20, align=4
-// CHECK-NEXT: | nvsize=20, nvalign=4]
+// CHECK-NEXT: | nvsize=18, nvalign=4]
// CHECK-X64: *** Dumping AST Record Layout
// CHECK-X64: *** Dumping AST Record Layout
// CHECK-X64-NEXT: 0 | struct Y
// CHECK-X64-NEXT: 12 | char a
// CHECK-X64-NEXT: 14 | int b
// CHECK-X64-NEXT: | [sizeof=20, align=4
-// CHECK-X64-NEXT: | nvsize=20, nvalign=4]
+// CHECK-X64-NEXT: | nvsize=18, nvalign=4]
struct Z : virtual B {
char a;
// CHECK-X64: | [sizeof=5, align=1
// CHECK-X64-NEXT: | nvsize=5, nvalign=1]
+#pragma pack(16)
+struct __declspec(align(16)) D0 { char a; };
+#pragma pack(1)
+struct D1 : public D0 { char a; };
+#pragma pack(16)
+struct D2 : D1 { char a; };
+
+// CHECK: *** Dumping AST Record Layout
+// CHECK: *** Dumping AST Record Layout
+// CHECK: *** Dumping AST Record Layout
+// CHECK-NEXT: 0 | struct D2
+// CHECK-NEXT: 0 | struct D1 (base)
+// CHECK-NEXT: 0 | struct D0 (base)
+// CHECK-NEXT: 0 | char a
+// CHECK-NEXT: 1 | char a
+// CHECK-NEXT: 2 | char a
+// CHECK-NEXT: | [sizeof=16, align=16
+// CHECK-NEXT: | nvsize=16, nvalign=16]
+// CHECK-X64: *** Dumping AST Record Layout
+// CHECK-X64: *** Dumping AST Record Layout
+// CHECK-X64: *** Dumping AST Record Layout
+// CHECK-X64-NEXT: 0 | struct D2
+// CHECK-X64-NEXT: 0 | struct D1 (base)
+// CHECK-X64-NEXT: 0 | struct D0 (base)
+// CHECK-X64-NEXT: 0 | char a
+// CHECK-X64-NEXT: 1 | char a
+// CHECK-X64-NEXT: 2 | char a
+// CHECK-X64-NEXT: | [sizeof=16, align=16
+// CHECK-X64-NEXT: | nvsize=16, nvalign=16]
+
int a[
sizeof(X)+
sizeof(Y)+
sizeof(YD)+
sizeof(YE)+
sizeof(YF)+
+sizeof(YF)+
+sizeof(D2)+
0];