summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Majnemer <david.majnemer@gmail.com>2014-09-30 06:45:43 +0000
committerDavid Majnemer <david.majnemer@gmail.com>2014-09-30 06:45:43 +0000
commit00a061dccc6671c96412d7b28ab2012963208579 (patch)
treeb8de3d4202a7fd311d0b424a6e167eaee41e5de2
parent09184fedc0491328ff287d7049578c6ca1443b9b (diff)
downloadbcm5719-llvm-00a061dccc6671c96412d7b28ab2012963208579.tar.gz
bcm5719-llvm-00a061dccc6671c96412d7b28ab2012963208579.zip
MS ABI: Correct layout for empty records
Empty records do not always have size equivalent to their alignment. They only do so when their alignment is at least as large as the minimum empty struct size: 1 byte in C++ and 4 bytes in C. llvm-svn: 218661
-rw-r--r--clang/lib/AST/RecordLayoutBuilder.cpp16
-rw-r--r--clang/test/Layout/ms-x86-basic-layout.cpp32
-rw-r--r--clang/test/Layout/ms-x86-pack-and-align.cpp34
3 files changed, 79 insertions, 3 deletions
diff --git a/clang/lib/AST/RecordLayoutBuilder.cpp b/clang/lib/AST/RecordLayoutBuilder.cpp
index 6c7f6806116..798f9f39c3f 100644
--- a/clang/lib/AST/RecordLayoutBuilder.cpp
+++ b/clang/lib/AST/RecordLayoutBuilder.cpp
@@ -2204,6 +2204,8 @@ public:
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).
@@ -2299,6 +2301,8 @@ MicrosoftRecordLayoutBuilder::getAdjustedElementInfo(
}
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);
@@ -2308,6 +2312,8 @@ void MicrosoftRecordLayoutBuilder::layout(const RecordDecl *RD) {
}
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);
@@ -2636,7 +2642,7 @@ void MicrosoftRecordLayoutBuilder::layoutVirtualBases(const CXXRecordDecl *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);
@@ -2646,11 +2652,15 @@ void MicrosoftRecordLayoutBuilder::finalizeLayout(const RecordDecl *RD) {
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;
}
}
diff --git a/clang/test/Layout/ms-x86-basic-layout.cpp b/clang/test/Layout/ms-x86-basic-layout.cpp
index b6ffeee7114..aac7aed0601 100644
--- a/clang/test/Layout/ms-x86-basic-layout.cpp
+++ b/clang/test/Layout/ms-x86-basic-layout.cpp
@@ -816,6 +816,36 @@ struct RecordArrayTypedef {
// 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)+
@@ -840,4 +870,6 @@ sizeof(F6)+
sizeof(ArrayFieldOfRecords)+
sizeof(ArrayOfArrayFieldOfRecords)+
sizeof(RecordArrayTypedef)+
+sizeof(EmptyIntMemb)+
+sizeof(EmptyLongLongMemb)+
0];
diff --git a/clang/test/Layout/ms-x86-pack-and-align.cpp b/clang/test/Layout/ms-x86-pack-and-align.cpp
index e2f03d782e5..9783233d66a 100644
--- a/clang/test/Layout/ms-x86-pack-and-align.cpp
+++ b/clang/test/Layout/ms-x86-pack-and-align.cpp
@@ -769,6 +769,38 @@ struct QD {
// 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)+
@@ -800,4 +832,6 @@ sizeof(PE)+
sizeof(QB)+
sizeof(QC)+
sizeof(QD)+
+sizeof(EmptyAlignedLongLongMemb)+
+sizeof(EmptyPackedAlignedLongLongMemb)+
0];
OpenPOWER on IntegriCloud