]> granicus.if.org Git - clang/commitdiff
We were mistakenly marking morally virtual bases as being uninteresting. Fix this.
authorAnders Carlsson <andersca@mac.com>
Wed, 10 Mar 2010 19:39:11 +0000 (19:39 +0000)
committerAnders Carlsson <andersca@mac.com>
Wed, 10 Mar 2010 19:39:11 +0000 (19:39 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@98180 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/CGVtable.cpp
test/CodeGenCXX/vtable-layout.cpp

index caf1e1f93e4823c7c702d37fe28cb629c3775fcc..37dd23c0b513b766286b399ec4410e67047b8017 100644 (file)
@@ -1235,7 +1235,11 @@ private:
   
   /// LayoutSecondaryVtables - Layout the secondary vtables for the given base
   /// subobject.
-  void LayoutSecondaryVtables(BaseSubobject Base, uint64_t OffsetInLayoutClass);
+  ///
+  /// \param BaseIsMorallyVirtual whether the base subobject is a virtual base
+  /// or a direct or indirect base of a virtual base.
+  void LayoutSecondaryVtables(BaseSubobject Base, bool BaseIsMorallyVirtual,
+                              uint64_t OffsetInLayoutClass);
 
   /// DeterminePrimaryVirtualBases - Determine the primary virtual bases in this
   /// class hierarchy.
@@ -1772,11 +1776,16 @@ VtableBuilder::LayoutPrimaryAndSecondaryVtables(BaseSubobject Base,
     AddressPoints.insert(std::make_pair(PrimaryBase, AddressPoint));
   }
 
+  bool BaseIsMorallyVirtual = BaseIsVirtual;
+  if (isBuildingConstructorVtable() && Base.getBase() == MostDerivedClass)
+    BaseIsMorallyVirtual = false;
+  
   // Layout secondary vtables.
-  LayoutSecondaryVtables(Base, OffsetInLayoutClass);
+  LayoutSecondaryVtables(Base, BaseIsMorallyVirtual, OffsetInLayoutClass);
 }
 
 void VtableBuilder::LayoutSecondaryVtables(BaseSubobject Base,
+                                           bool BaseIsMorallyVirtual,
                                            uint64_t OffsetInLayoutClass) {
   // Itanium C++ ABI 2.5.2:
   //   Following the primary virtual table of a derived class are secondary 
@@ -1806,9 +1815,8 @@ void VtableBuilder::LayoutSecondaryVtables(BaseSubobject Base,
       //   tables, which will therefore not be present in the construction
       //   virtual table group, even though the subobject virtual tables are
       //   present in the main virtual table group for the complete object.
-      if (!BaseDecl->getNumVBases()) {
+      if (!BaseIsMorallyVirtual && !BaseDecl->getNumVBases())
         continue;
-      }
     }
 
     // Get the base offset of this base.
@@ -1821,7 +1829,7 @@ void VtableBuilder::LayoutSecondaryVtables(BaseSubobject Base,
     // to emit secondary vtables for other bases of this base.
     if (BaseDecl == PrimaryBase) {
       LayoutSecondaryVtables(BaseSubobject(BaseDecl, BaseOffset),
-                             BaseOffsetInLayoutClass);
+                             BaseIsMorallyVirtual, BaseOffsetInLayoutClass);
       continue;
     }
 
index 19619d0f2b8e4ce3965af264bad87ac139433d93..2e08df9ed91af49ffe31161e1a11bbd5a2fe2bd3 100644 (file)
@@ -1150,4 +1150,71 @@ struct E : D {
   virtual void e();
 };
 void E::e() { }
+
+}
+
+namespace Test28 {
+
+// Check that we do include the vtable for B in the D-in-E construction vtable, since
+// B is a base class of a virtual base (C).
+
+struct A {
+  virtual void a();
+};
+
+struct B {
+  virtual void b();
+};
+
+struct C : A, B {
+  virtual void c();
+};
+
+struct D : virtual C {
+};
+
+// CHECK:      Vtable for 'Test28::E' (14 entries).
+// CHECK-NEXT:    0 | vbase_offset (8)
+// CHECK-NEXT:    1 | offset_to_top (0)
+// CHECK-NEXT:    2 | Test28::E RTTI
+// CHECK-NEXT:        -- (Test28::D, 0) vtable address --
+// CHECK-NEXT:        -- (Test28::E, 0) vtable address --
+// CHECK-NEXT:    3 | void Test28::E::e()
+// CHECK-NEXT:    4 | vcall_offset (8)
+// CHECK-NEXT:    5 | vcall_offset (0)
+// CHECK-NEXT:    6 | vcall_offset (0)
+// CHECK-NEXT:    7 | offset_to_top (-8)
+// CHECK-NEXT:    8 | Test28::E RTTI
+// CHECK-NEXT:        -- (Test28::A, 8) vtable address --
+// CHECK-NEXT:        -- (Test28::C, 8) vtable address --
+// CHECK-NEXT:    9 | void Test28::A::a()
+// CHECK-NEXT:   10 | void Test28::C::c()
+// CHECK-NEXT:   11 | offset_to_top (-16)
+// CHECK-NEXT:   12 | Test28::E RTTI
+// CHECK-NEXT:        -- (Test28::B, 16) vtable address --
+// CHECK-NEXT:   13 | void Test28::B::b()
+
+// CHECK:      Construction vtable for ('Test28::D', 0) in 'Test28::E' (13 entries).
+// CHECK-NEXT:    0 | vbase_offset (8)
+// CHECK-NEXT:    1 | offset_to_top (0)
+// CHECK-NEXT:    2 | Test28::D RTTI
+// CHECK-NEXT:        -- (Test28::D, 0) vtable address --
+// CHECK-NEXT:    3 | vcall_offset (8)
+// CHECK-NEXT:    4 | vcall_offset (0)
+// CHECK-NEXT:    5 | vcall_offset (0)
+// CHECK-NEXT:    6 | offset_to_top (-8)
+// CHECK-NEXT:    7 | Test28::D RTTI
+// CHECK-NEXT:        -- (Test28::A, 8) vtable address --
+// CHECK-NEXT:        -- (Test28::C, 8) vtable address --
+// CHECK-NEXT:    8 | void Test28::A::a()
+// CHECK-NEXT:    9 | void Test28::C::c()
+// CHECK-NEXT:   10 | offset_to_top (-16)
+// CHECK-NEXT:   11 | Test28::D RTTI
+// CHECK-NEXT:        -- (Test28::B, 16) vtable address --
+// CHECK-NEXT:   12 | void Test28::B::b()
+struct E : D {
+  virtual void e();
+};
+void E::e() { }
+
 }