diff options
author | Anders Carlsson <andersca@mac.com> | 2010-02-27 06:38:03 +0000 |
---|---|---|
committer | Anders Carlsson <andersca@mac.com> | 2010-02-27 06:38:03 +0000 |
commit | c784ba21ba14f4cf65fc6fa2e3548c4775819921 (patch) | |
tree | 508995b5ffb94de71ae06b153f3f530b63c28e15 /lib/CodeGen/CGVtable.cpp | |
parent | 5560969d73e3e72747972d0f0f37ca4e3b042186 (diff) |
Fix another vtable layout bug; we weren't looking hard enough for overriden functions when determining if an overrider will ever be used.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@97306 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/CGVtable.cpp')
-rw-r--r-- | lib/CodeGen/CGVtable.cpp | 48 |
1 files changed, 40 insertions, 8 deletions
diff --git a/lib/CodeGen/CGVtable.cpp b/lib/CodeGen/CGVtable.cpp index 89676d4343..a12e80cc47 100644 --- a/lib/CodeGen/CGVtable.cpp +++ b/lib/CodeGen/CGVtable.cpp @@ -1247,12 +1247,12 @@ public: void dumpLayout(llvm::raw_ostream&); }; -/// OverridesMethodInPrimaryBase - Checks whether whether this virtual member -/// function overrides a member function in a direct or indirect primary base. +/// OverridesMethodInBases - Checks whether whether this virtual member +/// function overrides a member function in any of the given bases. /// Returns the overridden member function, or null if none was found. static const CXXMethodDecl * -OverridesMethodInPrimaryBase(const CXXMethodDecl *MD, - VtableBuilder::PrimaryBasesSetTy &PrimaryBases) { +OverridesMethodInBases(const CXXMethodDecl *MD, + VtableBuilder::PrimaryBasesSetTy &Bases) { for (CXXMethodDecl::method_iterator I = MD->begin_overridden_methods(), E = MD->end_overridden_methods(); I != E; ++I) { const CXXMethodDecl *OverriddenMD = *I; @@ -1260,7 +1260,7 @@ OverridesMethodInPrimaryBase(const CXXMethodDecl *MD, assert(OverriddenMD->isCanonicalDecl() && "Should have the canonical decl of the overridden RD!"); - if (PrimaryBases.count(OverriddenRD)) + if (Bases.count(OverriddenRD)) return OverriddenMD; } @@ -1352,6 +1352,38 @@ VtableBuilder::AddMethod(const CXXMethodDecl *MD, } } +/// OverridesIndirectMethodInBase - Return whether the given member function +/// overrides any methods in the set of given bases. +/// Unlike OverridesMethodInBase, this checks "overriders of overriders". +/// For example, if we have: +/// +/// struct A { virtual void f(); } +/// struct B : A { virtual void f(); } +/// struct C : B { virtual void f(); } +/// +/// OverridesIndirectMethodInBase will return true if given C::f as the method +/// and { A } as the set of bases. +static bool +OverridesIndirectMethodInBases(const CXXMethodDecl *MD, + VtableBuilder::PrimaryBasesSetTy &Bases) { + for (CXXMethodDecl::method_iterator I = MD->begin_overridden_methods(), + E = MD->end_overridden_methods(); I != E; ++I) { + const CXXMethodDecl *OverriddenMD = *I; + const CXXRecordDecl *OverriddenRD = OverriddenMD->getParent(); + assert(OverriddenMD->isCanonicalDecl() && + "Should have the canonical decl of the overridden RD!"); + + if (Bases.count(OverriddenRD)) + return true; + + // Check "indirect overriders". + if (OverridesIndirectMethodInBases(OverriddenMD, Bases)) + return true; + } + + return false; +} + bool VtableBuilder::IsOverriderUsed(BaseSubobject Base, BaseSubobject FirstBaseInPrimaryBaseChain, @@ -1406,7 +1438,7 @@ VtableBuilder::IsOverriderUsed(BaseSubobject Base, // If the final overrider is an override of one of the primary bases, // then we know that it will be used. - return OverridesMethodInPrimaryBase(Overrider.Method, PrimaryBases); + return OverridesIndirectMethodInBases(Overrider.Method, PrimaryBases); } void @@ -1457,7 +1489,7 @@ VtableBuilder::AddMethods(BaseSubobject Base, // base. If this is the case, and the return type doesn't require adjustment // then we can just use the member function from the primary base. if (const CXXMethodDecl *OverriddenMD = - OverridesMethodInPrimaryBase(MD, PrimaryBases)) { + OverridesMethodInBases(MD, PrimaryBases)) { if (ComputeReturnAdjustmentBaseOffset(Context, MD, OverriddenMD).isEmpty()) continue; @@ -2959,7 +2991,7 @@ void CGVtableInfo::ComputeMethodVtableIndices(const CXXRecordDecl *RD) { // Check if this method overrides a method in the primary base. if (const CXXMethodDecl *OverriddenMD = - OverridesMethodInPrimaryBase(MD, PrimaryBases)) { + OverridesMethodInBases(MD, PrimaryBases)) { // Check if converting from the return type of the method to the // return type of the overridden method requires conversion. if (ComputeReturnAdjustmentBaseOffset(CGM.getContext(), MD, |