diff options
author | Anders Carlsson <andersca@mac.com> | 2010-02-13 20:41:15 +0000 |
---|---|---|
committer | Anders Carlsson <andersca@mac.com> | 2010-02-13 20:41:15 +0000 |
commit | a4a541708a65184466b97fe562a293891fa7e811 (patch) | |
tree | a055f7b9f235a5998d690fd2570cb4eab44aec10 /lib/CodeGen/CGVtable.cpp | |
parent | af667588d53de22795c5304f1496ccaac2a71402 (diff) |
Handle virtual bases in ComputeBaseOffset.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@96117 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/CGVtable.cpp')
-rw-r--r-- | lib/CodeGen/CGVtable.cpp | 37 |
1 files changed, 27 insertions, 10 deletions
diff --git a/lib/CodeGen/CGVtable.cpp b/lib/CodeGen/CGVtable.cpp index 7d3f35f077..f7b8c53d02 100644 --- a/lib/CodeGen/CGVtable.cpp +++ b/lib/CodeGen/CGVtable.cpp @@ -288,7 +288,7 @@ ComputeBaseOffset(ASTContext &Context, const CXXRecordDecl *DerivedRD, const CXXRecordDecl *BaseRD) { CXXBasePaths Paths(/*FindAmbiguities=*/false, - /*RecordPaths=*/true, /*DetectVirtual=*/true); + /*RecordPaths=*/true, /*DetectVirtual=*/false); if (!const_cast<CXXRecordDecl *>(DerivedRD)-> isDerivedFrom(const_cast<CXXRecordDecl *>(BaseRD), Paths)) { @@ -296,15 +296,30 @@ ComputeBaseOffset(ASTContext &Context, return FinalOverriders::BaseOffset(); } - assert(!Paths.getDetectedVirtual() && - "FIXME: Handle virtual bases!"); - uint64_t NonVirtualOffset = 0; const CXXBasePath &Path = Paths.front(); - for (size_t Start = 0, End = Path.size(); Start != End; ++Start) { - const CXXBasePathElement &Element = Path[Start]; + unsigned NonVirtualStart = 0; + const CXXRecordDecl *VirtualBase = 0; + + // First, look for the virtual base class. + for (unsigned I = 0, E = Path.size(); I != E; ++I) { + const CXXBasePathElement &Element = Path[I]; + + if (Element.Base->isVirtual()) { + // FIXME: Can we break when we find the first virtual base? + // (If we can't, can't we just iterate over the path in reverse order?) + NonVirtualStart = I + 1; + QualType VBaseType = Element.Base->getType(); + VirtualBase = + cast<CXXRecordDecl>(VBaseType->getAs<RecordType>()->getDecl()); + } + } + + // Now compute the non-virtual offset. + for (unsigned I = NonVirtualStart, E = Path.size(); I != E; ++I) { + const CXXBasePathElement &Element = Path[I]; // Check the base class offset. const ASTRecordLayout &Layout = Context.getASTRecordLayout(Element.Class); @@ -318,7 +333,7 @@ ComputeBaseOffset(ASTContext &Context, // FIXME: This should probably use CharUnits or something. Maybe we should // even change the base offsets in ASTRecordLayout to be specified in // CharUnits. - return FinalOverriders::BaseOffset(0, NonVirtualOffset / 8); + return FinalOverriders::BaseOffset(VirtualBase, NonVirtualOffset / 8); } static FinalOverriders::BaseOffset @@ -510,10 +525,12 @@ void FinalOverriders::dump(llvm::raw_ostream &Out, BaseSubobject Base) const { ReturnAdjustments.find(std::make_pair(Base, MD)); if (AI != ReturnAdjustments.end()) { const BaseOffset &Offset = AI->second; - - assert(!Offset.VirtualBase && "FIXME: Handle vbases!"); + + Out << " [ret-adj: "; + if (Offset.VirtualBase) + Out << Offset.VirtualBase->getQualifiedNameAsString() << " vbase, "; - Out << " [ret-adj: " << Offset.NonVirtualOffset << " nv]"; + Out << Offset.NonVirtualOffset << " nv]"; } Out << "\n"; } |