aboutsummaryrefslogtreecommitdiff
path: root/lib/CodeGen/CGVtable.cpp
diff options
context:
space:
mode:
authorAnders Carlsson <andersca@mac.com>2010-02-27 04:05:52 +0000
committerAnders Carlsson <andersca@mac.com>2010-02-27 04:05:52 +0000
commit08c26752efa51fb5dc47bd3382ea21814bd0c5b8 (patch)
treefa3b46a7ccb252f5fa7af83b894fe9db32c70c21 /lib/CodeGen/CGVtable.cpp
parent06079d1d1eb04e8d3d874311aafd605c8ec3cafc (diff)
Fix a bug where we were generating an unnecessary vtable for a virtual base that's already a primary virtual base.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@97303 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/CGVtable.cpp')
-rw-r--r--lib/CodeGen/CGVtable.cpp46
1 files changed, 37 insertions, 9 deletions
diff --git a/lib/CodeGen/CGVtable.cpp b/lib/CodeGen/CGVtable.cpp
index 3dc29ad9ca..3c8ddfaed5 100644
--- a/lib/CodeGen/CGVtable.cpp
+++ b/lib/CodeGen/CGVtable.cpp
@@ -1220,7 +1220,12 @@ private:
/// LayoutSecondaryVtables - Layout the secondary vtables for the given base
/// subobject.
void LayoutSecondaryVtables(BaseSubobject Base);
-
+
+ /// DeterminePrimaryVirtualBases - Determine the primary virtual bases in this
+ /// class hierarchy.
+ void DeterminePrimaryVirtualBases(const CXXRecordDecl *RD,
+ VisitedVirtualBasesSetTy &VBases);
+
/// LayoutVtablesForVirtualBases - Layout vtables for all virtual bases of the
/// given base (excluding any primary bases).
void LayoutVtablesForVirtualBases(const CXXRecordDecl *RD,
@@ -1418,9 +1423,6 @@ VtableBuilder::AddMethods(BaseSubobject Base,
Context.getASTRecordLayout(MostDerivedClass);
BaseOffset = MostDerivedClassLayout.getVBaseClassOffset(PrimaryBase);
-
- // Keep track of this primary virtual base.
- PrimaryVirtualBases.insert(PrimaryBase);
} else {
assert(Layout.getBaseClassOffset(PrimaryBase) == 0 &&
"Primary base should have a zero offset!");
@@ -1498,6 +1500,11 @@ void VtableBuilder::LayoutVtable() {
/*BaseIsVirtual=*/false);
VisitedVirtualBasesSetTy VBases;
+
+ // Determine the primary virtual bases.
+ DeterminePrimaryVirtualBases(MostDerivedClass, VBases);
+ VBases.clear();
+
LayoutVtablesForVirtualBases(MostDerivedClass, VBases);
}
@@ -1592,15 +1599,37 @@ void VtableBuilder::LayoutSecondaryVtables(BaseSubobject Base) {
}
void
+VtableBuilder::DeterminePrimaryVirtualBases(const CXXRecordDecl *RD,
+ VisitedVirtualBasesSetTy &VBases) {
+ const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
+
+ // Check if this base has a primary base.
+ if (const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase()) {
+ // Check if it's virtual
+ if (Layout.getPrimaryBaseWasVirtual())
+ PrimaryVirtualBases.insert(PrimaryBase);
+ }
+
+ // Traverse bases, looking for more primary virtual bases.
+ for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
+ E = RD->bases_end(); I != E; ++I) {
+ const CXXRecordDecl *BaseDecl =
+ cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
+
+ if (I->isVirtual() && !VBases.insert(BaseDecl))
+ continue;
+
+ DeterminePrimaryVirtualBases(BaseDecl, VBases);
+ }
+}
+
+void
VtableBuilder::LayoutVtablesForVirtualBases(const CXXRecordDecl *RD,
VisitedVirtualBasesSetTy &VBases) {
// Itanium C++ ABI 2.5.2:
// Then come the virtual base virtual tables, also in inheritance graph
// order, and again excluding primary bases (which share virtual tables with
// the classes for which they are primary).
- const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
- const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase();
-
for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
E = RD->bases_end(); I != E; ++I) {
const CXXRecordDecl *BaseDecl =
@@ -1609,8 +1638,7 @@ VtableBuilder::LayoutVtablesForVirtualBases(const CXXRecordDecl *RD,
// Check if this base needs a vtable. (If it's virtual, not a primary base
// of some other class, and we haven't visited it before).
if (I->isVirtual() && BaseDecl->isDynamicClass() &&
- BaseDecl != PrimaryBase && !PrimaryVirtualBases.count(BaseDecl) &&
- VBases.insert(BaseDecl)) {
+ !PrimaryVirtualBases.count(BaseDecl) && VBases.insert(BaseDecl)) {
const ASTRecordLayout &MostDerivedClassLayout =
Context.getASTRecordLayout(MostDerivedClass);
uint64_t BaseOffset =