r206124 - MS ABI: #pragma vtordisp(0) only disables new vtordisps

David Majnemer david.majnemer at gmail.com
Sat Apr 12 19:27:33 PDT 2014


Author: majnemer
Date: Sat Apr 12 21:27:32 2014
New Revision: 206124

URL: http://llvm.org/viewvc/llvm-project?rev=206124&view=rev
Log:
MS ABI: #pragma vtordisp(0) only disables new vtordisps

Previously, it was believed that #pragma vtordisp(0) would prohibit the
generation of any and all vtordisps.

In actuality, it only disables the generation of additional vtordisps.

This fixes PR19413.

Modified:
    cfe/trunk/lib/AST/RecordLayoutBuilder.cpp
    cfe/trunk/test/Layout/ms-x86-vtordisp.cpp

Modified: cfe/trunk/lib/AST/RecordLayoutBuilder.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/RecordLayoutBuilder.cpp?rev=206124&r1=206123&r2=206124&view=diff
==============================================================================
--- cfe/trunk/lib/AST/RecordLayoutBuilder.cpp (original)
+++ cfe/trunk/lib/AST/RecordLayoutBuilder.cpp Sat Apr 12 21:27:32 2014
@@ -2674,10 +2674,6 @@ llvm::SmallPtrSet<const CXXRecordDecl *,
 MicrosoftRecordLayoutBuilder::computeVtorDispSet(const CXXRecordDecl *RD) {
   llvm::SmallPtrSet<const CXXRecordDecl *, 2> HasVtordispSet;
 
-  // /vd0 or #pragma vtordisp(0): Never use vtordisps when used as a vbase.
-  if (RD->getMSVtorDispMode() == MSVtorDispAttr::Never)
-    return HasVtordispSet;
-
   // /vd2 or #pragma vtordisp(2): Always use vtordisps for virtual bases with
   // vftables.
   if (RD->getMSVtorDispMode() == MSVtorDispAttr::ForVFTable) {
@@ -2690,11 +2686,6 @@ MicrosoftRecordLayoutBuilder::computeVto
     return HasVtordispSet;
   }
 
-  // /vd1 or #pragma vtordisp(1): Try to guess based on whether we think it's
-  // possible for a partially constructed object with virtual base overrides to
-  // escape a non-trivial constructor.
-  assert(RD->getMSVtorDispMode() == MSVtorDispAttr::ForVBaseOverride);
-
   // If any of our bases need a vtordisp for this type, so do we.  Check our
   // direct bases for vtordisp requirements.
   for (const auto &I : RD->bases()) {
@@ -2704,10 +2695,16 @@ MicrosoftRecordLayoutBuilder::computeVto
       if (bi.second.hasVtorDisp())
         HasVtordispSet.insert(bi.first);
   }
-  // If we do not have a user declared constructor or destructor then we don't
-  // introduce any additional vtordisps.
-  if (!RD->hasUserDeclaredConstructor() && !RD->hasUserDeclaredDestructor())
+  // We don't introduce any additional vtordisps if either:
+  // * A user declared constructor or destructor aren't declared.
+  // * #pragma vtordisp(0) or the /vd0 flag are in use.
+  if ((!RD->hasUserDeclaredConstructor() && !RD->hasUserDeclaredDestructor()) ||
+      RD->getMSVtorDispMode() == MSVtorDispAttr::Never)
     return HasVtordispSet;
+  // /vd1 or #pragma vtordisp(1): Try to guess based on whether we think it's
+  // possible for a partially constructed object with virtual base overrides to
+  // escape a non-trivial constructor.
+  assert(RD->getMSVtorDispMode() == MSVtorDispAttr::ForVBaseOverride);
   // Compute a set of base classes which define methods we override.  A virtual
   // base in this set will require a vtordisp.  A virtual base that transitively
   // contains one of these bases as a non-virtual base will also require a

Modified: cfe/trunk/test/Layout/ms-x86-vtordisp.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Layout/ms-x86-vtordisp.cpp?rev=206124&r1=206123&r2=206124&view=diff
==============================================================================
--- cfe/trunk/test/Layout/ms-x86-vtordisp.cpp (original)
+++ cfe/trunk/test/Layout/ms-x86-vtordisp.cpp Sat Apr 12 21:27:32 2014
@@ -381,6 +381,41 @@ struct GD: public virtual GC, public vir
 // CHECK-X64-NEXT:      | [sizeof=40, align=8
 // CHECK-X64-NEXT:      |  nvsize=8, nvalign=8]
 
+struct HA {
+  virtual void fun() {}
+};
+#pragma vtordisp(push, 2)
+struct HB : virtual HA {};
+#pragma vtordisp(pop, 2)
+#pragma vtordisp(push, 0)
+struct HC : virtual HB {};
+#pragma vtordisp(pop, 0)
+
+// CHECK: *** Dumping AST Record Layout
+// CHECK: *** Dumping AST Record Layout
+// CHECK: *** Dumping AST Record Layout
+// CHECK-NEXT:    0 | struct HC
+// CHECK-NEXT:    0 |   (HC vbtable pointer)
+// CHECK-NEXT:    4 |   (vtordisp for vbase HA)
+// CHECK-NEXT:    8 |   struct HA (virtual base)
+// CHECK-NEXT:    8 |     (HA vftable pointer)
+// CHECK-NEXT:   12 |   struct HB (virtual base)
+// CHECK-NEXT:   12 |     (HB vbtable pointer)
+// CHECK-NEXT:      | [sizeof=16, align=4
+// CHECK-NEXT:      |  nvsize=4, nvalign=4]
+// CHECK-X64: *** Dumping AST Record Layout
+// CHECK-X64: *** Dumping AST Record Layout
+// CHECK-X64: *** Dumping AST Record Layout
+// CHECK-X64-NEXT:    0 | struct HC
+// CHECK-X64-NEXT:    0 |   (HC vbtable pointer)
+// CHECK-X64-NEXT:   12 |   (vtordisp for vbase HA)
+// CHECK-X64-NEXT:   16 |   struct HA (virtual base)
+// CHECK-X64-NEXT:   16 |     (HA vftable pointer)
+// CHECK-X64-NEXT:   24 |   struct HB (virtual base)
+// CHECK-X64-NEXT:   24 |     (HB vbtable pointer)
+// CHECK-X64-NEXT:      | [sizeof=32, align=8
+// CHECK-X64-NEXT:      |  nvsize=8, nvalign=8]
+
 int a[
 sizeof(A)+
 sizeof(C)+
@@ -392,4 +427,5 @@ sizeof(pragma_test2::C)+
 sizeof(pragma_test3::C)+
 sizeof(pragma_test4::C)+
 sizeof(GD)+
+sizeof(HC)+
 0];





More information about the cfe-commits mailing list