]> granicus.if.org Git - clang/commitdiff
[ms-abi] 64-bit fixes for r196549
authorWarren Hunt <whunt@google.com>
Tue, 10 Dec 2013 01:44:39 +0000 (01:44 +0000)
committerWarren Hunt <whunt@google.com>
Tue, 10 Dec 2013 01:44:39 +0000 (01:44 +0000)
In order to address latent bugs that were easier to expose in 64-bit
mode, we move the application of __declspec(align) to before the layout
of vbases rather than after.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@196861 91177308-0d34-0410-b5e6-96231b3b80d8

lib/AST/RecordLayoutBuilder.cpp
test/Layout/ms-x86-alias-avoidance-padding.cpp
test/Layout/ms-x86-empty-virtual-base.cpp

index a3ea6b9f3861ab7d7c799caa6502e893d4674a22..a5b07384dc8d45c8b9f279a87e63dcb5963dc4c8 100644 (file)
@@ -2060,12 +2060,13 @@ public:
   /// \brief Lays out a single zero-width bit-field in the record and handles
   /// special cases associated with zero-width bit-fields.
   void layoutZeroWidthBitField(const FieldDecl *FD);
+  void fixSizeAndAlignment(const RecordDecl *FD);
   void layoutVirtualBases(const CXXRecordDecl *RD);
   void layoutVirtualBase(const CXXRecordDecl *RD, bool HasVtordisp);
   /// \brief Flushes the lazy virtual base and conditionally rounds up to
   /// alignment.
   void finalizeCXXLayout(const CXXRecordDecl *RD);
-  void honorDeclspecAlign(const RecordDecl *RD);
+  void finalizeLayout(const RecordDecl *RD);
 
   /// \brief Updates the alignment of the type.  This function doesn't take any
   /// properties (such as packedness) into account.  getAdjustedFieldInfo()
@@ -2233,7 +2234,8 @@ void MicrosoftRecordLayoutBuilder::initializeLayout(const RecordDecl *RD) {
 void MicrosoftRecordLayoutBuilder::layout(const RecordDecl *RD) {
   initializeLayout(RD);
   layoutFields(RD);
-  honorDeclspecAlign(RD);
+  fixSizeAndAlignment(RD);
+  finalizeLayout(RD);
 }
 
 void MicrosoftRecordLayoutBuilder::cxxLayout(const CXXRecordDecl *RD) {
@@ -2243,11 +2245,10 @@ void MicrosoftRecordLayoutBuilder::cxxLayout(const CXXRecordDecl *RD) {
   layoutNonVirtualBases(RD);
   layoutVBPtr(RD);
   layoutFields(RD);
-  DataSize = Size;
-  NonVirtualAlignment = Alignment;
+  fixSizeAndAlignment(RD);
   layoutVirtualBases(RD);
   finalizeCXXLayout(RD);
-  honorDeclspecAlign(RD);
+  finalizeLayout(RD);
 }
 
 void
@@ -2543,6 +2544,13 @@ MicrosoftRecordLayoutBuilder::layoutZeroWidthBitField(const FieldDecl *FD) {
   }
 }
 
+void MicrosoftRecordLayoutBuilder::fixSizeAndAlignment(const RecordDecl *RD) {
+  DataSize = Size;
+  NonVirtualAlignment = Alignment;
+  RequiredAlignment = std::max(RequiredAlignment,
+      Context.toCharUnitsFromBits(RD->getMaxAlignment()));
+}
+
 void MicrosoftRecordLayoutBuilder::layoutVirtualBases(const CXXRecordDecl *RD) {
   if (!HasVBPtr)
     return;
@@ -2581,8 +2589,9 @@ void MicrosoftRecordLayoutBuilder::layoutVirtualBase(const CXXRecordDecl *RD,
   // bytes (in both 32 and 64 bits modes), we don't know why.
   if (PreviousBaseLayout && PreviousBaseLayout->hasZeroSizedSubObject() &&
       Layout.leadsWithZeroSizedBase())
-    Size = Size.RoundUpToAlignment(Alignment) +
-        std::max(CharUnits::fromQuantity(4), Layout.getAlignment());
+    Size = Size.RoundUpToAlignment(std::max(CharUnits::fromQuantity(4),
+                                            RequiredAlignment)) +
+        CharUnits::fromQuantity(4);
 
   CharUnits BaseNVSize = Layout.getNonVirtualSize();
   CharUnits BaseAlign = getBaseAlignment(Layout);
@@ -2612,9 +2621,7 @@ void MicrosoftRecordLayoutBuilder::finalizeCXXLayout(const CXXRecordDecl *RD) {
   }
 }
 
-void MicrosoftRecordLayoutBuilder::honorDeclspecAlign(const RecordDecl *RD) {
-  RequiredAlignment = std::max(RequiredAlignment,
-      Context.toCharUnitsFromBits(RD->getMaxAlignment()));
+void MicrosoftRecordLayoutBuilder::finalizeLayout(const RecordDecl *RD) {
   if (!RequiredAlignment.isZero()) {
     updateAlignment(RequiredAlignment);
     Size = Size.RoundUpToAlignment(Alignment);
index 86b3cebe2414bbd5c2f0b71c37b03c50b7992fe8..78957cf747e5940b8896c5788eef3a09482622ba 100644 (file)
@@ -166,9 +166,9 @@ struct __declspec(align(1)) T3 : virtual T1, virtual T2 {
 // CHECK-X64:    8 |     struct T0 (base) (empty)
 // CHECK-X64:    8 |       struct AT (base) (empty)
 // CHECK-X64:    8 |     char a
-// CHECK-X64:   20 |   struct T2 (virtual base)
-// CHECK-X64:   20 |     struct AT (base) (empty)
-// CHECK-X64:   20 |     char a
+// CHECK-X64:   16 |   struct T2 (virtual base)
+// CHECK-X64:   16 |     struct AT (base) (empty)
+// CHECK-X64:   16 |     char a
 // CHECK-X64:      | [sizeof=24, align=8
 // CHECK-X64:      |  nvsize=8, nvalign=8]
 
index ef6f08175e7a1344be18fc0ad84fc71245512da7..8377969aa9ba4f936d584da0790f51c0031ace20 100644 (file)
@@ -679,6 +679,31 @@ struct __declspec(align(32)) V : virtual D1 {
 // CHECK-X64:      | [sizeof=32, align=32
 // CHECK-X64:      |  nvsize=16, nvalign=8]
 
+struct T0 {};
+struct T1 : T0 { char a; };
+struct T3 : virtual T1, virtual T0 { long long a; };
+
+// CHECK: *** Dumping AST Record Layout
+// CHECK:    0 | struct T3
+// CHECK:    0 |   (T3 vbtable pointer)
+// CHECK:    8 |   long long a
+// CHECK:   16 |   struct T1 (virtual base)
+// CHECK:   16 |     struct T0 (base) (empty)
+// CHECK:   16 |     char a
+// CHECK:   24 |   struct T0 (virtual base) (empty)
+// CHECK:      | [sizeof=24, align=8
+// CHECK:      |  nvsize=16, nvalign=8]
+// CHECK-X64: *** Dumping AST Record Layout
+// CHECK-X64:    0 | struct T3
+// CHECK-X64:    0 |   (T3 vbtable pointer)
+// CHECK-X64:    8 |   long long a
+// CHECK-X64:   16 |   struct T1 (virtual base)
+// CHECK-X64:   16 |     struct T0 (base) (empty)
+// CHECK-X64:   16 |     char a
+// CHECK-X64:   24 |   struct T0 (virtual base) (empty)
+// CHECK-X64:      | [sizeof=24, align=8
+// CHECK-X64:      |  nvsize=16, nvalign=8]
+
 int a[
 sizeof(A)+
 sizeof(B)+
@@ -701,4 +726,5 @@ sizeof(R)+
 sizeof(S)+
 sizeof(T)+
 sizeof(U)+
-sizeof(V)];
\ No newline at end of file
+sizeof(V)+
+sizeof(T3)];
\ No newline at end of file