From: Anders Carlsson Date: Sun, 14 Feb 2010 00:37:35 +0000 (+0000) Subject: Baby steps towards teaching FinalOverriders about virtual bases. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=9d6f0d551bbd08036baef2b892e31b87fc7e4322;p=clang Baby steps towards teaching FinalOverriders about virtual bases. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@96139 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/CodeGen/CGVtable.cpp b/lib/CodeGen/CGVtable.cpp index 9c3f1df5a5..3fc7135b8b 100644 --- a/lib/CodeGen/CGVtable.cpp +++ b/lib/CodeGen/CGVtable.cpp @@ -83,6 +83,10 @@ private: /// all the base subobjects of the most derived class. OverridersMapTy OverridersMap; + /// VisitedVirtualBases - A set of all the visited virtual bases, used to + /// avoid visiting virtual bases more than once. + llvm::SmallPtrSet VisitedVirtualBases; + typedef llvm::DenseMap AdjustmentOffsetsMapTy; @@ -173,13 +177,16 @@ public: } /// dump - dump the final overriders. - void dump() const { - dump(llvm::errs(), BaseSubobject(MostDerivedClass, 0)); + void dump() { + assert(VisitedVirtualBases.empty() && + "Visited virtual bases aren't empty!"); + dump(llvm::errs(), BaseSubobject(MostDerivedClass, 0)); + VisitedVirtualBases.clear(); } /// dump - dump the final overriders for a base subobject, and all its direct /// and indirect base subobjects. - void dump(llvm::raw_ostream &Out, BaseSubobject Base) const; + void dump(llvm::raw_ostream &Out, BaseSubobject Base); }; FinalOverriders::FinalOverriders(const CXXRecordDecl *MostDerivedClass) @@ -491,11 +498,13 @@ void FinalOverriders::ComputeFinalOverriders(BaseSubobject Base, const CXXRecordDecl *BaseDecl = cast(I->getType()->getAs()->getDecl()); - assert(!I->isVirtual() && "FIXME: Handle virtual bases!"); - - uint64_t BaseOffset = Layout.getBaseClassOffset(BaseDecl) + - Base.getBaseOffset(); - + uint64_t BaseOffset; + if (I->isVirtual()) { + BaseOffset = MostDerivedClassLayout.getVBaseClassOffset(BaseDecl); + } else { + BaseOffset = Layout.getBaseClassOffset(BaseDecl) + Base.getBaseOffset(); + } + // Compute the final overriders for this base. ComputeFinalOverriders(BaseSubobject(BaseDecl, BaseOffset), NewOffsets); } @@ -510,20 +519,28 @@ void FinalOverriders::ComputeFinalOverriders(BaseSubobject Base, Offsets[RD].push_back(Base.getBaseOffset()); } -void FinalOverriders::dump(llvm::raw_ostream &Out, BaseSubobject Base) const { +void FinalOverriders::dump(llvm::raw_ostream &Out, BaseSubobject Base) { const CXXRecordDecl *RD = Base.getBase(); const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD); for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(), E = RD->bases_end(); I != E; ++I) { - assert(!I->isVirtual() && "FIXME: Handle virtual bases!"); - const CXXRecordDecl *BaseDecl = cast(I->getType()->getAs()->getDecl()); - uint64_t BaseOffset = Layout.getBaseClassOffset(BaseDecl) + - Base.getBaseOffset(); - + uint64_t BaseOffset; + if (I->isVirtual()) { + if (!VisitedVirtualBases.insert(BaseDecl)) { + // We've visited this base before. + continue; + } + + BaseOffset = MostDerivedClassLayout.getVBaseClassOffset(BaseDecl); + } else { + BaseOffset = Layout.getBaseClassOffset(BaseDecl) + + Base.getBaseOffset(); + } + dump(Out, BaseSubobject(BaseDecl, BaseOffset)); }