зеркало из https://github.com/microsoft/clang-1.git
Reapply r99775 with a fix for a silly bug - we were setting the vtable pointer for all bases, even those without a vtable pointer :)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@99777 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
4658990ac1
Коммит
603d6d12cc
|
@ -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) {
|
||||
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);
|
||||
}
|
||||
|
||||
const CXXRecordDecl *RD = Base.getBase();
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
InitializeVTablePointers(BaseSubobject(BaseDecl, BaseOffset),
|
||||
BaseIsMorallyVirtual, BaseIsNonVirtualPrimaryBase,
|
||||
VTable, VTableClass, VBases);
|
||||
}
|
||||
}
|
||||
|
||||
void CodeGenFunction::InitializeVTablePointers(const CXXRecordDecl *RD) {
|
||||
// Ignore classes without a vtable.
|
||||
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);
|
||||
|
||||
if (!RD->getNumVBases())
|
||||
return;
|
||||
|
||||
const ASTRecordLayout &Layout = getContext().getASTRecordLayout(RD);
|
||||
|
||||
// Store address points for virtual basess.
|
||||
for (CXXRecordDecl::base_class_const_iterator I = RD->vbases_begin(),
|
||||
E = RD->vbases_end(); I != E; ++I) {
|
||||
CXXRecordDecl *BaseDecl
|
||||
= cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
|
||||
|
||||
uint64_t BaseOffset = Layout.getVBaseClassOffset(BaseDecl);
|
||||
InitializeVtablePtrs(BaseSubobject(BaseDecl, BaseOffset), VTable, RD);
|
||||
}
|
||||
}
|
||||
|
||||
void CodeGenFunction::InitializeVtablePtrs(BaseSubobject Base,
|
||||
llvm::Constant *VTable,
|
||||
const CXXRecordDecl *VTableClass) {
|
||||
const CXXRecordDecl *RD = Base.getBase();
|
||||
|
||||
// Ignore classes without a vtable pointer.
|
||||
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);
|
||||
}
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
Загрузка…
Ссылка в новой задаче