diff options
Diffstat (limited to 'lib/CodeGen')
-rw-r--r-- | lib/CodeGen/CGClass.cpp | 105 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenFunction.h | 10 |
2 files changed, 64 insertions, 51 deletions
diff --git a/lib/CodeGen/CGClass.cpp b/lib/CodeGen/CGClass.cpp index 2fa5837289..17802fc201 100644 --- a/lib/CodeGen/CGClass.cpp +++ b/lib/CodeGen/CGClass.cpp @@ -690,7 +690,7 @@ CodeGenFunction::SynthesizeCXXCopyConstructor(const FunctionArgList &Args) { } } - InitializeVtablePtrs(ClassDecl); + InitializeVTablePointers(ClassDecl); } /// SynthesizeCXXCopyAssignment - Implicitly define copy assignment operator. @@ -1010,7 +1010,7 @@ void CodeGenFunction::EmitCtorPrologue(const CXXConstructorDecl *CD, MemberInitializers.push_back(Member); } - InitializeVtablePtrs(ClassDecl); + InitializeVTablePointers(ClassDecl); for (unsigned I = 0, E = MemberInitializers.size(); I != E; ++I) { assert(LiveTemporaries.empty() && @@ -1060,7 +1060,7 @@ void CodeGenFunction::EmitDestructorBody(FunctionArgList &Args) { // Otherwise, we're in the base variant, so we need to ensure the // vtable ptrs are right before emitting the body. } else { - InitializeVtablePtrs(Dtor->getParent()); + InitializeVTablePointers(Dtor->getParent()); } // Emit the body of the statement. @@ -1561,7 +1561,6 @@ CodeGenFunction::InitializeVTablePointer(BaseSubobject Base, bool BaseIsMorallyVirtual, llvm::Constant *VTable, const CXXRecordDecl *VTableClass) { - // Compute the address point. const CodeGenVTables::AddrSubMap_t& AddressPoints = CGM.getVTables().getAddressPoints(VTableClass); @@ -1584,59 +1583,71 @@ CodeGenFunction::InitializeVTablePointer(BaseSubobject Base, Builder.CreateStore(VTableAddressPoint, VTableField); } -void CodeGenFunction::InitializeVtablePtrs(const CXXRecordDecl *RD) { - if (!RD->isDynamicClass()) - return; - - // Get the VTable. - llvm::Constant *VTable = CGM.getVTables().GetAddrOfVTable(RD); - - // Store address points for the current class and its non-virtual bases. - InitializeVtablePtrs(BaseSubobject(RD, 0), VTable, RD); +void +CodeGenFunction::InitializeVTablePointers(BaseSubobject Base, + bool BaseIsMorallyVirtual, + bool BaseIsNonVirtualPrimaryBase, + llvm::Constant *VTable, + const CXXRecordDecl *VTableClass, + VisitedVirtualBasesSetTy& VBases) { + // If this base is a non-virtual primary base the address point has already + // been set. + if (!BaseIsNonVirtualPrimaryBase) { + // Initialize the vtable pointer for this base. + InitializeVTablePointer(Base, BaseIsMorallyVirtual, VTable, VTableClass); + } - if (!RD->getNumVBases()) - return; - - const ASTRecordLayout &Layout = getContext().getASTRecordLayout(RD); + const CXXRecordDecl *RD = Base.getBase(); - // Store address points for virtual basess. - for (CXXRecordDecl::base_class_const_iterator I = RD->vbases_begin(), - E = RD->vbases_end(); I != E; ++I) { + // Traverse bases. + for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(), + E = RD->bases_end(); I != E; ++I) { CXXRecordDecl *BaseDecl = cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl()); + + // Ignore classes without a vtable. + if (!BaseDecl->isDynamicClass()) + continue; + + uint64_t BaseOffset; + + if (I->isVirtual()) { + // Check if we've visited this virtual base before. + if (!VBases.insert(BaseDecl)) + continue; + + const ASTRecordLayout &Layout = + getContext().getASTRecordLayout(VTableClass); + + BaseIsMorallyVirtual = true; + BaseIsNonVirtualPrimaryBase = false; + + BaseOffset = Layout.getVBaseClassOffset(BaseDecl); + } else { + const ASTRecordLayout &Layout = getContext().getASTRecordLayout(RD); + + BaseOffset = Base.getBaseOffset() + Layout.getBaseClassOffset(BaseDecl); + BaseIsNonVirtualPrimaryBase = Layout.getPrimaryBase() == BaseDecl; + } - uint64_t BaseOffset = Layout.getVBaseClassOffset(BaseDecl); - InitializeVtablePtrs(BaseSubobject(BaseDecl, BaseOffset), VTable, RD); + InitializeVTablePointers(BaseSubobject(BaseDecl, BaseOffset), + BaseIsMorallyVirtual, BaseIsNonVirtualPrimaryBase, + VTable, VTableClass, VBases); } } -void CodeGenFunction::InitializeVtablePtrs(BaseSubobject Base, - llvm::Constant *VTable, - const CXXRecordDecl *VTableClass) { - const CXXRecordDecl *RD = Base.getBase(); - - // Ignore classes without a vtable pointer. +void CodeGenFunction::InitializeVTablePointers(const CXXRecordDecl *RD) { + // Ignore classes without a vtable. if (!RD->isDynamicClass()) return; - - const ASTRecordLayout &Layout = getContext().getASTRecordLayout(RD); - // Store address points for non-virtual bases. - for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(), - E = RD->bases_end(); I != E; ++I) { - if (I->isVirtual()) - continue; - - CXXRecordDecl *BaseDecl - = cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl()); - uint64_t BaseOffset = Base.getBaseOffset() + - Layout.getBaseClassOffset(BaseDecl); - - InitializeVtablePtrs(BaseSubobject(BaseDecl, BaseOffset), - VTable, VTableClass); - } + // Get the VTable. + llvm::Constant *VTable = CGM.getVTables().GetAddrOfVTable(RD); - // FIXME: BaseIsMorallyVirtual is not correct here. - InitializeVTablePointer(Base, /*BaseIsMorallyVirtual=*/false, VTable, - VTableClass); + // Initialize the vtable pointers for this class and all of its bases. + VisitedVirtualBasesSetTy VBases; + InitializeVTablePointers(BaseSubobject(RD, 0), + /*BaseIsMorallyVirtual=*/false, + /*BaseIsNonVirtualPrimaryBase=*/false, + VTable, RD, VBases); } diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h index 3d7165b0a9..31ab1011b4 100644 --- a/lib/CodeGen/CodeGenFunction.h +++ b/lib/CodeGen/CodeGenFunction.h @@ -519,11 +519,13 @@ public: const CXXRecordDecl *VTableClass); typedef llvm::SmallPtrSet<const CXXRecordDecl *, 4> VisitedVirtualBasesSetTy; + void InitializeVTablePointers(BaseSubobject Base, bool BaseIsMorallyVirtual, + bool BaseIsNonVirtualPrimaryBase, + llvm::Constant *VTable, + const CXXRecordDecl *VTableClass, + VisitedVirtualBasesSetTy& VBases); - void InitializeVtablePtrs(BaseSubobject Base, llvm::Constant *VTable, - const CXXRecordDecl *VTableClass); - - void InitializeVtablePtrs(const CXXRecordDecl *ClassDecl); + void InitializeVTablePointers(const CXXRecordDecl *ClassDecl); void SynthesizeCXXCopyConstructor(const FunctionArgList &Args); |