[cfe-commits] r97039 - in /cfe/trunk: lib/CodeGen/CGVtable.cpp test/CodeGenCXX/vtable-layout-abi-examples.cpp
Anders Carlsson
andersca at mac.com
Wed Feb 24 08:43:12 PST 2010
Author: andersca
Date: Wed Feb 24 10:43:12 2010
New Revision: 97039
URL: http://llvm.org/viewvc/llvm-project?rev=97039&view=rev
Log:
Generate correct vcall offsets when we have a primary virtual base that is not a primary base in the complete class hierarchy.
Modified:
cfe/trunk/lib/CodeGen/CGVtable.cpp
cfe/trunk/test/CodeGenCXX/vtable-layout-abi-examples.cpp
Modified: cfe/trunk/lib/CodeGen/CGVtable.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGVtable.cpp?rev=97039&r1=97038&r2=97039&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGVtable.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGVtable.cpp Wed Feb 24 10:43:12 2010
@@ -968,6 +968,7 @@
/// AddVCallAndVBaseOffsets - Add vcall offsets and vbase offsets for the
/// given base subobject.
void AddVCallAndVBaseOffsets(BaseSubobject Base, bool BaseIsVirtual,
+ uint64_t RealBaseOffset,
VisitedVirtualBasesSetTy &VBases);
/// AddVCallOffsets - Add vcall offsets for the given base subobject.
@@ -1112,6 +1113,7 @@
void
VtableBuilder::AddVCallAndVBaseOffsets(BaseSubobject Base,
bool BaseIsVirtual,
+ uint64_t RealBaseOffset,
VisitedVirtualBasesSetTy &VBases) {
const ASTRecordLayout &Layout = Context.getASTRecordLayout(Base.getBase());
@@ -1126,8 +1128,28 @@
// emit them for the primary base first).
if (const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase()) {
bool PrimaryBaseIsVirtual = Layout.getPrimaryBaseWasVirtual();
- AddVCallAndVBaseOffsets(BaseSubobject(PrimaryBase, Base.getBaseOffset()),
- PrimaryBaseIsVirtual, VBases);
+
+ uint64_t PrimaryBaseOffset;
+
+ // Get the base offset of the primary base.
+ if (PrimaryBaseIsVirtual) {
+ assert(Layout.getVBaseClassOffset(PrimaryBase) == 0 &&
+ "Primary vbase should have a zero offset!");
+
+ const ASTRecordLayout &MostDerivedClassLayout =
+ Context.getASTRecordLayout(MostDerivedClass);
+
+ PrimaryBaseOffset =
+ MostDerivedClassLayout.getVBaseClassOffset(PrimaryBase);
+ } else {
+ assert(Layout.getBaseClassOffset(PrimaryBase) == 0 &&
+ "Primary base should have a zero offset!");
+
+ PrimaryBaseOffset = Base.getBaseOffset();
+ }
+
+ AddVCallAndVBaseOffsets(BaseSubobject(PrimaryBase, PrimaryBaseOffset),
+ PrimaryBaseIsVirtual, RealBaseOffset, VBases);
}
// FIXME: Don't use /8 here.
@@ -1136,7 +1158,7 @@
// We only want to add vcall offsets for virtual bases.
if (BaseIsVirtual)
- AddVCallOffsets(Base, Base.getBaseOffset());
+ AddVCallOffsets(Base, RealBaseOffset);
}
void VtableBuilder::AddVCallOffsets(BaseSubobject Base, uint64_t VBaseOffset) {
@@ -1434,7 +1456,7 @@
// Add vcall and vbase offsets for this vtable.
VisitedVirtualBasesSetTy VBases;
- AddVCallAndVBaseOffsets(Base, BaseIsVirtual, VBases);
+ AddVCallAndVBaseOffsets(Base, BaseIsVirtual, Base.getBaseOffset(), VBases);
// Reverse them and add them to the vtable components.
std::reverse(VCallAndVBaseOffsets.begin(), VCallAndVBaseOffsets.end());
@@ -1470,11 +1492,11 @@
AddressPoints.insert(std::make_pair(PrimaryBase, AddressPoint));
}
- // Layout secondary vtables.
- LayoutSecondaryVtables(Base);
-
// Clear the vcall offsets.
VCallOffsets.clear();
+
+ // Layout secondary vtables.
+ LayoutSecondaryVtables(Base);
}
void VtableBuilder::LayoutSecondaryVtables(BaseSubobject Base) {
Modified: cfe/trunk/test/CodeGenCXX/vtable-layout-abi-examples.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/vtable-layout-abi-examples.cpp?rev=97039&r1=97038&r2=97039&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/vtable-layout-abi-examples.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/vtable-layout-abi-examples.cpp Wed Feb 24 10:43:12 2010
@@ -155,3 +155,35 @@
void E::f() { }
}
+
+namespace Test2 {
+
+// From http://www.codesourcery.com/public/cxx-abi/abi.html#class-types.
+
+struct A { virtual void f(); };
+struct B : virtual public A { int i; };
+struct C : virtual public A { int j; };
+
+// CHECK: Vtable for 'Test2::D' (11 entries).
+// CHECK-NEXT: 0 | vbase_offset (0)
+// CHECK-NEXT: 1 | vcall_offset (0)
+// CHECK-NEXT: 2 | offset_to_top (0)
+// CHECK-NEXT: 3 | Test2::D RTTI
+// CHECK-NEXT: -- (Test2::A, 0) vtable address --
+// CHECK-NEXT: -- (Test2::B, 0) vtable address --
+// CHECK-NEXT: -- (Test2::D, 0) vtable address --
+// CHECK-NEXT: 4 | void Test2::A::f()
+// CHECK-NEXT: 5 | void Test2::D::d()
+// CHECK-NEXT: 6 | vbase_offset (-16)
+// CHECK-NEXT: 7 | vcall_offset (-16)
+// CHECK-NEXT: 8 | offset_to_top (-16)
+// CHECK-NEXT: 9 | Test2::D RTTI
+// CHECK-NEXT: -- (Test2::A, 16) vtable address --
+// CHECK-NEXT: -- (Test2::C, 16) vtable address --
+// CHECK-NEXT: 10 | [unused] void Test2::A::f()
+struct D : public B, public C {
+ virtual void d();
+};
+void D::d() { }
+
+}
More information about the cfe-commits
mailing list