]> granicus.if.org Git - clang/commitdiff
[ms-abi] Fixes improperly sized vfptrs with pragma pack
authorWarren Hunt <whunt@google.com>
Thu, 26 Dec 2013 22:09:12 +0000 (22:09 +0000)
committerWarren Hunt <whunt@google.com>
Thu, 26 Dec 2013 22:09:12 +0000 (22:09 +0000)
With pragma pack, the layout engine would produce vfptrs that were
packed width rather than pointer width.  This patch addresses the issue
and adds a test case.

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

lib/AST/RecordLayoutBuilder.cpp
test/Layout/ms-x86-pack-and-align.cpp

index 74010ce7aa0f6fe83859ca02e0281fd81a9d1e5b..832bfef90c950595057affc33585c8ffbdf1742a 100644 (file)
@@ -2316,15 +2316,14 @@ void MicrosoftRecordLayoutBuilder::layoutVFPtr(const CXXRecordDecl *RD) {
   if (!HasExtendableVFPtr)
     return;
 
+  updateAlignment(PointerAlignment);
+  Size = Size.RoundUpToAlignment(PointerAlignment) + PointerSize;
   // MSVC 32 (but not 64) potentially over-aligns the vf-table pointer by giving
   // it the max alignment of all the non-virtual data in the class.  The
   // resulting layout is essentially { vftbl, { nvdata } }.  This is completely
   // unnecessary, but we're not here to pass judgment.
-  updateAlignment(PointerAlignment);
-  if (Is64BitMode)
-    Size = Size.RoundUpToAlignment(PointerAlignment) + PointerSize;
-  else
-    Size = Size.RoundUpToAlignment(PointerAlignment) + Alignment;
+  if (!Is64BitMode && Alignment > PointerSize)
+    Size += Alignment - PointerSize;
 }
 
 void
index c7bf4d31579bc46add84e160fb7938987a43703b..d9bca99b1c12f5be2a6e210eb70f9fdbad8f068b 100644 (file)
@@ -119,6 +119,7 @@ struct A1 { long long a; };
 struct B1 : virtual A1 { char a; };
 #pragma pack(pop)
 struct C1 : B1 {};
+
 // CHECK: *** Dumping AST Record Layout
 // CHECK:    0 | struct C1
 // CHECK:    0 |   struct B1 (base)
@@ -138,8 +139,41 @@ struct C1 : B1 {};
 // CHECK-X64:      | [sizeof=24, align=8
 // CHECK-X64:      |  nvsize=9, nvalign=1]
 
+struct CA0 {
+       CA0() {}
+};
+struct CA1 : virtual CA0 {
+       CA1() {}
+};
+#pragma pack(push, 1)
+struct CA2 : public CA1, public CA0 {
+       virtual void CA2Method() {}
+       CA2() {}
+};
+#pragma pack(pop)
+
+// CHECK: *** Dumping AST Record Layout
+// CHECK:    0 | struct CA2
+// CHECK:    0 |   (CA2 vftable pointer)
+// CHECK:    4 |   struct CA1 (base)
+// CHECK:    4 |     (CA1 vbtable pointer)
+// CHECK:    9 |   struct CA0 (base) (empty)
+// CHECK:    9 |   struct CA0 (virtual base) (empty)
+// CHECK:      | [sizeof=9, align=1
+// CHECK:      |  nvsize=9, nvalign=1]
+// CHECK-C64: *** Dumping AST Record Layout
+// CHECK-C64:    0 | struct CA2
+// CHECK-C64:    0 |   (CA2 vftable pointer)
+// CHECK-C64:    8 |   struct CA1 (base)
+// CHECK-C64:    8 |     (CA1 vbtable pointer)
+// CHECK-C64:   17 |   struct CA0 (base) (empty)
+// CHECK-C64:   17 |   struct CA0 (virtual base) (empty)
+// CHECK-C64:      | [sizeof=17, align=1
+// CHECK-C64:      |  nvsize=17, nvalign=1]
+
 int a[
 sizeof(X)+
 sizeof(Y)+
 sizeof(Z)+
-sizeof(C1)];
+sizeof(C1)+
+sizeof(CA2)];