[PATCH] Fix vbtable indices if a class shares the vbptr with a non-virtual base
Timur Iskhodzhanov
timurrrr at google.com
Fri Nov 1 07:19:25 PDT 2013
Hi rnk,
http://llvm-reviews.chandlerc.com/D2089
Files:
lib/AST/VTableBuilder.cpp
lib/CodeGen/MicrosoftVBTables.cpp
test/CodeGenCXX/microsoft-abi-vbtables.cpp
Index: lib/AST/VTableBuilder.cpp
===================================================================
--- lib/AST/VTableBuilder.cpp
+++ lib/AST/VTableBuilder.cpp
@@ -2397,16 +2397,57 @@
return CreateVTableLayout(Builder);
}
-unsigned clang::GetVBTableIndex(const CXXRecordDecl *Derived,
- const CXXRecordDecl *VBase) {
- unsigned VBTableIndex = 1; // Start with one to skip the self entry.
+static unsigned GetVBTableIndexOrZero(const CXXRecordDecl *Derived,
+ const CXXRecordDecl *VBase,
+ BasesSetVectorTy &VisitedBases) {
+ const ASTContext &Context = Derived->getASTContext();
+ const ASTRecordLayout &Layout = Context.getASTRecordLayout(Derived);
+
+ // First, see if the Derived class shared the vbptr with a non-virtual base.
+ for (CXXRecordDecl::base_class_const_iterator I = Derived->bases_begin(),
+ E = Derived->bases_end(); I != E; ++I) {
+ if (I->isVirtual())
+ continue;
+
+ const CXXRecordDecl *CurBase = I->getType()->getAsCXXRecordDecl();
+ CharUnits DerivedVBPtrOffset = Layout.getVBPtrOffset(),
+ BaseOffset = Layout.getBaseClassOffset(CurBase);
+ if (DerivedVBPtrOffset < BaseOffset)
+ continue;
+ const ASTRecordLayout &BaseLayout = Context.getASTRecordLayout(CurBase);
+ if (!BaseLayout.hasVBPtr() ||
+ DerivedVBPtrOffset != BaseOffset + BaseLayout.getVBPtrOffset())
+ continue;
+
+ // If the Derived class shares the vbptr with a non-virtual base,
+ // it inherits its vbase indices.
+ unsigned VBIndexInNVBase =
+ GetVBTableIndexOrZero(CurBase, VBase, VisitedBases);
+ if (VBIndexInNVBase)
+ return VBIndexInNVBase;
+ assert(VisitedBases.count(VBase) == 0);
+ }
+
+ // New vbases are added to the end of the vbtable.
+ // Skip the self entry and vbases visited in the non-virtual base, if any.
+ unsigned VBTableIndex = 1 + VisitedBases.size();
for (CXXRecordDecl::base_class_const_iterator I = Derived->vbases_begin(),
E = Derived->vbases_end(); I != E; ++I) {
- if (I->getType()->getAsCXXRecordDecl() == VBase)
+ const CXXRecordDecl *CurVBase = I->getType()->getAsCXXRecordDecl();
+ if (CurVBase == VBase)
return VBTableIndex;
- ++VBTableIndex;
+ if (VisitedBases.insert(CurVBase))
+ ++VBTableIndex;
}
- llvm_unreachable("VBase must be a vbase of Derived");
+ return 0;
+}
+
+unsigned clang::GetVBTableIndex(const CXXRecordDecl *Derived,
+ const CXXRecordDecl *VBase) {
+ BasesSetVectorTy VisitedBases;
+ unsigned ret = GetVBTableIndexOrZero(Derived, VBase, VisitedBases);
+ assert(ret > 0 && "VBase must be a vbase of Derived");
+ return ret;
}
namespace {
Index: lib/CodeGen/MicrosoftVBTables.cpp
===================================================================
--- lib/CodeGen/MicrosoftVBTables.cpp
+++ lib/CodeGen/MicrosoftVBTables.cpp
@@ -195,12 +195,11 @@
const ASTRecordLayout &DerivedLayout =
CGM.getContext().getASTRecordLayout(RD);
- SmallVector<llvm::Constant *, 4> Offsets;
+ SmallVector<llvm::Constant *, 4> Offsets(1 + ReusingBase->getNumVBases(), 0);
// The offset from ReusingBase's vbptr to itself always leads.
CharUnits VBPtrOffset = BaseLayout.getVBPtrOffset();
- Offsets.push_back(
- llvm::ConstantInt::get(CGM.IntTy, -VBPtrOffset.getQuantity()));
+ Offsets[0] = llvm::ConstantInt::get(CGM.IntTy, -VBPtrOffset.getQuantity());
// These are laid out in the same order as in Itanium, which is the same as
// the order of the vbase iterator.
@@ -211,7 +210,9 @@
assert(!Offset.isNegative());
// Make it relative to the subobject vbptr.
Offset -= VBPtrSubobject.getBaseOffset() + VBPtrOffset;
- Offsets.push_back(llvm::ConstantInt::get(CGM.IntTy, Offset.getQuantity()));
+ llvm::Constant *&VBOffset = Offsets[GetVBTableIndex(ReusingBase, VBase)];
+ assert(VBOffset == 0 && "The same vbindex seen twice?");
+ VBOffset = llvm::ConstantInt::get(CGM.IntTy, Offset.getQuantity());
}
assert(Offsets.size() ==
Index: test/CodeGenCXX/microsoft-abi-vbtables.cpp
===================================================================
--- test/CodeGenCXX/microsoft-abi-vbtables.cpp
+++ test/CodeGenCXX/microsoft-abi-vbtables.cpp
@@ -410,3 +410,54 @@
// CHECK-DAG: @"\01??_8B at Test21@@7B@" =
// CHECK-DAG: @"\01??_8C at Test21@@7B@" =
}
+
+namespace Test22 {
+struct A { int a; };
+struct B : virtual A { int b; };
+struct C { int c; };
+struct D : B, virtual C { int d; };
+D d;
+
+// CHECK-DAG: @"\01??_8D at Test22@@7B@" = linkonce_odr unnamed_addr constant [3 x i32] [i32 0, i32 12, i32 16]
+// CHECK-DAG: @"\01??_8B at Test22@@7B@" = linkonce_odr unnamed_addr constant [2 x i32] [i32 0, i32 8]
+}
+
+namespace Test23 {
+struct A { int a; };
+struct B : virtual A { int b; };
+struct C { int c; };
+// Note the unusual order of bases. It forces C to be laid out before A.
+struct D : virtual C, B { int d; };
+D d;
+
+// CHECK-DAG: @"\01??_8D at Test23@@7B@" = linkonce_odr unnamed_addr constant [3 x i32] [i32 0, i32 16, i32 12]
+// CHECK-DAG: @"\01??_8B at Test23@@7B@" = linkonce_odr unnamed_addr constant [2 x i32] [i32 0, i32 8]
+}
+
+namespace Test24 {
+struct A { int a; };
+struct B : virtual A { int b; };
+struct C { int c; };
+struct D : virtual C, B {
+ virtual void f(); // Issues a vfptr, but the vbptr is still shared with B.
+ int d;
+};
+D d;
+
+// CHECK-DAG: @"\01??_8D at Test24@@7B@" = linkonce_odr unnamed_addr constant [3 x i32] [i32 0, i32 16, i32 12]
+// CHECK-DAG: @"\01??_8B at Test24@@7B@" = linkonce_odr unnamed_addr constant [2 x i32] [i32 0, i32 8]
+}
+
+namespace Test25 {
+struct A { int a; };
+struct B : virtual A {
+ virtual void f(); // Issues a vfptr.
+ int b;
+};
+struct C { int c; };
+struct D : virtual C, B { int d; };
+D d;
+
+// CHECK-DAG: @"\01??_8D at Test25@@7B@" = linkonce_odr unnamed_addr constant [3 x i32] [i32 -4, i32 16, i32 12]
+// CHECK-DAG: @"\01??_8B at Test25@@7B@" = linkonce_odr unnamed_addr constant [2 x i32] [i32 -4, i32 8]
+}
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D2089.1.patch
Type: text/x-patch
Size: 6064 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20131101/2f677aa8/attachment.bin>
More information about the cfe-commits
mailing list