[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