summaryrefslogtreecommitdiffstats
path: root/clang/lib/CodeGen/CGVtable.cpp
diff options
context:
space:
mode:
authorAnders Carlsson <andersca@mac.com>2010-02-17 17:48:25 +0000
committerAnders Carlsson <andersca@mac.com>2010-02-17 17:48:25 +0000
commit231461f88f9fa2b3b1f1b5136d9810d16bffcbac (patch)
treed07b0710cf8ab69f9eecd1c9c51ee164b09b760b /clang/lib/CodeGen/CGVtable.cpp
parent80c430af8102ee729762675f46561d6ba5035035 (diff)
downloadbcm5719-llvm-231461f88f9fa2b3b1f1b5136d9810d16bffcbac.tar.gz
bcm5719-llvm-231461f88f9fa2b3b1f1b5136d9810d16bffcbac.zip
Make FinalOverriders handle virtual bases correctly. Unfortunately this can't be tested just yet.
llvm-svn: 96481
Diffstat (limited to 'clang/lib/CodeGen/CGVtable.cpp')
-rw-r--r--clang/lib/CodeGen/CGVtable.cpp36
1 files changed, 33 insertions, 3 deletions
diff --git a/clang/lib/CodeGen/CGVtable.cpp b/clang/lib/CodeGen/CGVtable.cpp
index 58989ede0bc..f5bd33e548f 100644
--- a/clang/lib/CodeGen/CGVtable.cpp
+++ b/clang/lib/CodeGen/CGVtable.cpp
@@ -120,6 +120,7 @@ private:
/// ComputeFinalOverriders - Compute the final overriders for a given base
/// subobject (and all its direct and indirect bases).
void ComputeFinalOverriders(BaseSubobject Base,
+ bool BaseSubobjectIsVisitedVBase,
SubobjectOffsetsMapTy &Offsets);
/// AddOverriders - Add the final overriders for this base subobject to the
@@ -197,7 +198,9 @@ FinalOverriders::FinalOverriders(const CXXRecordDecl *MostDerivedClass)
// Compute the final overriders.
SubobjectOffsetsMapTy Offsets;
- ComputeFinalOverriders(BaseSubobject(MostDerivedClass, 0), Offsets);
+ ComputeFinalOverriders(BaseSubobject(MostDerivedClass, 0),
+ /*BaseSubobjectIsVisitedVBase=*/false, Offsets);
+ VisitedVirtualBases.clear();
// And dump them (for now).
dump();
@@ -524,6 +527,7 @@ FinalOverriders::MergeSubobjectOffsets(const SubobjectOffsetsMapTy &NewOffsets,
}
void FinalOverriders::ComputeFinalOverriders(BaseSubobject Base,
+ bool BaseSubobjectIsVisitedVBase,
SubobjectOffsetsMapTy &Offsets) {
const CXXRecordDecl *RD = Base.getBase();
const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
@@ -539,19 +543,45 @@ void FinalOverriders::ComputeFinalOverriders(BaseSubobject Base,
if (!BaseDecl->isPolymorphic())
continue;
+ bool IsVisitedVirtualBase = false;
uint64_t BaseOffset;
if (I->isVirtual()) {
+ if (!VisitedVirtualBases.insert(BaseDecl))
+ IsVisitedVirtualBase = true;
BaseOffset = MostDerivedClassLayout.getVBaseClassOffset(BaseDecl);
} else {
BaseOffset = Layout.getBaseClassOffset(BaseDecl) + Base.getBaseOffset();
}
// Compute the final overriders for this base.
- ComputeFinalOverriders(BaseSubobject(BaseDecl, BaseOffset), NewOffsets);
+ // We always want to compute the final overriders, even if the base is a
+ // visited virtual base. Consider:
+ //
+ // struct A {
+ // virtual void f();
+ // virtual void g();
+ // };
+ //
+ // struct B : virtual A {
+ // void f();
+ // };
+ //
+ // struct C : virtual A {
+ // void g ();
+ // };
+ //
+ // struct D : B, C { };
+ //
+ // Here, we still want to compute the overriders for A as a base of C,
+ // because otherwise we'll miss that C::g overrides A::f.
+ ComputeFinalOverriders(BaseSubobject(BaseDecl, BaseOffset),
+ IsVisitedVirtualBase, NewOffsets);
}
/// Now add the overriders for this particular subobject.
- AddOverriders(Base, NewOffsets);
+ /// (We don't want to do this more than once for a virtual base).
+ if (!BaseSubobjectIsVisitedVBase)
+ AddOverriders(Base, NewOffsets);
// And merge the newly discovered subobject offsets.
MergeSubobjectOffsets(NewOffsets, Offsets);
OpenPOWER on IntegriCloud