CharUnits CurrentBitfieldSize;
/// \brief Offset to the virtual base table pointer (if one exists).
CharUnits VBPtrOffset;
+ /// \brief Minimum record size possible.
+ CharUnits MinEmptyStructSize;
/// \brief The size and alignment info of a pointer.
ElementInfo PointerInfo;
/// \brief The primary base class (if one exists).
}
void MicrosoftRecordLayoutBuilder::layout(const RecordDecl *RD) {
+ // For C record layout, zero-sized records always have size 4.
+ MinEmptyStructSize = CharUnits::fromQuantity(4);
initializeLayout(RD);
layoutFields(RD);
DataSize = Size = Size.RoundUpToAlignment(Alignment);
}
void MicrosoftRecordLayoutBuilder::cxxLayout(const CXXRecordDecl *RD) {
+ // The C++ standard says that empty structs have size 1.
+ MinEmptyStructSize = CharUnits::One();
initializeLayout(RD);
initializeCXXLayout(RD);
layoutNonVirtualBases(RD);
void MicrosoftRecordLayoutBuilder::finalizeLayout(const RecordDecl *RD) {
// Respect required alignment. Note that in 32-bit mode Required alignment
- // may be 0 nad cause size not to be updated.
+ // may be 0 and cause size not to be updated.
DataSize = Size;
if (!RequiredAlignment.isZero()) {
Alignment = std::max(Alignment, RequiredAlignment);
RoundingAlignment = std::max(RoundingAlignment, RequiredAlignment);
Size = Size.RoundUpToAlignment(RoundingAlignment);
}
- // Zero-sized structures have size equal to their alignment.
if (Size.isZero()) {
EndsWithZeroSizedObject = true;
LeadsWithZeroSizedBase = true;
- Size = Alignment;
+ // Zero-sized structures have size equal to their alignment if a
+ // __declspec(align) came into play.
+ if (RequiredAlignment >= MinEmptyStructSize)
+ Size = Alignment;
+ else
+ Size = MinEmptyStructSize;
}
}
// CHECK-X64-NEXT: | [sizeof=16, align=4
// CHECK-X64-NEXT: | nvsize=16, nvalign=4]
+struct EmptyIntMemb {
+ int FlexArrayMemb[0];
+};
+
+// CHECK: *** Dumping AST Record Layout
+// CHECK-NEXT: 0 | struct EmptyIntMemb
+// CHECK-NEXT: 0 | int [0] FlexArrayMemb
+// CHECK-NEXT: | [sizeof=1, align=4
+// CHECK-NEXT: | nvsize=0, nvalign=4]
+// CHECK-X64: *** Dumping AST Record Layout
+// CHECK-X64-NEXT: 0 | struct EmptyIntMemb
+// CHECK-X64-NEXT: 0 | int [0] FlexArrayMemb
+// CHECK-X64-NEXT: | [sizeof=4, align=4
+// CHECK-X64-NEXT: | nvsize=0, nvalign=4]
+
+struct EmptyLongLongMemb {
+ long long FlexArrayMemb[0];
+};
+
+// CHECK: *** Dumping AST Record Layout
+// CHECK-NEXT: 0 | struct EmptyLongLongMemb
+// CHECK-NEXT: 0 | long long [0] FlexArrayMemb
+// CHECK-NEXT: | [sizeof=1, align=8
+// CHECK-NEXT: | nvsize=0, nvalign=8]
+// CHECK-X64: *** Dumping AST Record Layout
+// CHECK-X64-NEXT: 0 | struct EmptyLongLongMemb
+// CHECK-X64-NEXT: 0 | long long [0] FlexArrayMemb
+// CHECK-X64-NEXT: | [sizeof=8, align=8
+// CHECK-X64-NEXT: | nvsize=0, nvalign=8]
+
int a[
sizeof(TestF0)+
sizeof(TestF1)+
sizeof(ArrayFieldOfRecords)+
sizeof(ArrayOfArrayFieldOfRecords)+
sizeof(RecordArrayTypedef)+
+sizeof(EmptyIntMemb)+
+sizeof(EmptyLongLongMemb)+
0];
// CHECK-X64-NEXT: | [sizeof=8, align=4
// CHECK-X64-NEXT: | nvsize=8, nvalign=4]
+struct __declspec(align(4)) EmptyAlignedLongLongMemb {
+ long long FlexArrayMemb[0];
+};
+
+// CHECK: *** Dumping AST Record Layout
+// CHECK-NEXT: 0 | struct EmptyAlignedLongLongMemb
+// CHECK-NEXT: 0 | long long [0] FlexArrayMemb
+// CHECK-NEXT: | [sizeof=8, align=8
+// CHECK-NEXT: | nvsize=0, nvalign=8]
+// CHECK-X64: *** Dumping AST Record Layout
+// CHECK-X64-NEXT: 0 | struct EmptyAlignedLongLongMemb
+// CHECK-X64-NEXT: 0 | long long [0] FlexArrayMemb
+// CHECK-X64-NEXT: | [sizeof=8, align=8
+// CHECK-X64-NEXT: | nvsize=0, nvalign=8]
+
+#pragma pack(1)
+struct __declspec(align(4)) EmptyPackedAlignedLongLongMemb {
+ long long FlexArrayMemb[0];
+};
+#pragma pack()
+
+// CHECK: *** Dumping AST Record Layout
+// CHECK-NEXT: 0 | struct EmptyPackedAlignedLongLongMemb
+// CHECK-NEXT: 0 | long long [0] FlexArrayMemb
+// CHECK-NEXT: | [sizeof=4, align=4
+// CHECK-NEXT: | nvsize=0, nvalign=4]
+// CHECK-X64: *** Dumping AST Record Layout
+// CHECK-X64-NEXT: 0 | struct EmptyPackedAlignedLongLongMemb
+// CHECK-X64-NEXT: 0 | long long [0] FlexArrayMemb
+// CHECK-X64-NEXT: | [sizeof=4, align=4
+// CHECK-X64-NEXT: | nvsize=0, nvalign=4]
+
int a[
sizeof(X)+
sizeof(Y)+
sizeof(QB)+
sizeof(QC)+
sizeof(QD)+
+sizeof(EmptyAlignedLongLongMemb)+
+sizeof(EmptyPackedAlignedLongLongMemb)+
0];