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) {
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()) {
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
// 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)+
sizeof(pragma_test3::C)+
sizeof(pragma_test4::C)+
sizeof(GD)+
+sizeof(HC)+
0];