aboutsummaryrefslogtreecommitdiff
path: root/lib/CodeGen/CGClass.cpp
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2013-01-31 05:50:40 +0000
committerDouglas Gregor <dgregor@apple.com>2013-01-31 05:50:40 +0000
commit378e1e739aed97e9b278beeb20e9f5bbe34c0232 (patch)
tree14aa2f4f0b3613854ca561578aec63a8a6bba457 /lib/CodeGen/CGClass.cpp
parent29805ca6d278b4d9563adfee67f2478f0fecdcfc (diff)
When we're emitting a constructor or destructor call from a delegating
constructor, retrieve our VTT parameter directly. Fixes PR14588 / <rdar://problem/12867962>. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@174042 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/CGClass.cpp')
-rw-r--r--lib/CodeGen/CGClass.cpp40
1 files changed, 25 insertions, 15 deletions
diff --git a/lib/CodeGen/CGClass.cpp b/lib/CodeGen/CGClass.cpp
index 5d1e30fef6..0611ed7834 100644
--- a/lib/CodeGen/CGClass.cpp
+++ b/lib/CodeGen/CGClass.cpp
@@ -282,7 +282,8 @@ CodeGenFunction::GetAddressOfDerivedClass(llvm::Value *Value,
/// GetVTTParameter - Return the VTT parameter that should be passed to a
/// base constructor/destructor with virtual bases.
static llvm::Value *GetVTTParameter(CodeGenFunction &CGF, GlobalDecl GD,
- bool ForVirtualBase) {
+ bool ForVirtualBase,
+ bool Delegating) {
if (!CodeGenVTables::needsVTTParameter(GD)) {
// This constructor/destructor does not need a VTT parameter.
return 0;
@@ -295,9 +296,12 @@ static llvm::Value *GetVTTParameter(CodeGenFunction &CGF, GlobalDecl GD,
uint64_t SubVTTIndex;
- // If the record matches the base, this is the complete ctor/dtor
- // variant calling the base variant in a class with virtual bases.
- if (RD == Base) {
+ if (Delegating) {
+ // If this is a delegating constructor call, just load the VTT.
+ return CGF.LoadCXXVTT();
+ } else if (RD == Base) {
+ // If the record matches the base, this is the complete ctor/dtor
+ // variant calling the base variant in a class with virtual bases.
assert(!CodeGenVTables::needsVTTParameter(CGF.CurGD) &&
"doing no-op VTT offset in base dtor/ctor?");
assert(!ForVirtualBase && "Can't have same class as virtual base!");
@@ -344,7 +348,8 @@ namespace {
CGF.GetAddressOfDirectBaseInCompleteClass(CGF.LoadCXXThis(),
DerivedClass, BaseClass,
BaseIsVirtual);
- CGF.EmitCXXDestructorCall(D, Dtor_Base, BaseIsVirtual, Addr);
+ CGF.EmitCXXDestructorCall(D, Dtor_Base, BaseIsVirtual,
+ /*Delegating=*/false, Addr);
}
};
@@ -537,7 +542,7 @@ namespace {
void Emit(CodeGenFunction &CGF, Flags flags) {
CGF.EmitCXXDestructorCall(Dtor, Dtor_Complete, /*ForVirtualBase=*/false,
- V);
+ /*Delegating=*/false, V);
}
};
}
@@ -893,7 +898,7 @@ void CodeGenFunction::EmitDestructorBody(FunctionArgList &Args) {
if (DtorType == Dtor_Deleting) {
EnterDtorCleanups(Dtor, Dtor_Deleting);
EmitCXXDestructorCall(Dtor, Dtor_Complete, /*ForVirtualBase=*/false,
- LoadCXXThis());
+ /*Delegating=*/false, LoadCXXThis());
PopCleanupBlock();
return;
}
@@ -923,7 +928,7 @@ void CodeGenFunction::EmitDestructorBody(FunctionArgList &Args) {
if (!isTryBody &&
CGM.getContext().getTargetInfo().getCXXABI().hasDestructorVariants()) {
EmitCXXDestructorCall(Dtor, Dtor_Base, /*ForVirtualBase=*/false,
- LoadCXXThis());
+ /*Delegating=*/false, LoadCXXThis());
break;
}
// Fallthrough: act like we're in the base variant.
@@ -1188,7 +1193,7 @@ CodeGenFunction::EmitCXXAggrConstructorCall(const CXXConstructorDecl *ctor,
}
EmitCXXConstructorCall(ctor, Ctor_Complete, /*ForVirtualBase=*/ false,
- cur, argBegin, argEnd);
+ /*Delegating=*/false, cur, argBegin, argEnd);
}
// Go to the next element.
@@ -1216,12 +1221,13 @@ void CodeGenFunction::destroyCXXObject(CodeGenFunction &CGF,
const CXXDestructorDecl *dtor = record->getDestructor();
assert(!dtor->isTrivial());
CGF.EmitCXXDestructorCall(dtor, Dtor_Complete, /*for vbase*/ false,
- addr);
+ /*Delegating=*/false, addr);
}
void
CodeGenFunction::EmitCXXConstructorCall(const CXXConstructorDecl *D,
CXXCtorType Type, bool ForVirtualBase,
+ bool Delegating,
llvm::Value *This,
CallExpr::const_arg_iterator ArgBeg,
CallExpr::const_arg_iterator ArgEnd) {
@@ -1255,7 +1261,8 @@ CodeGenFunction::EmitCXXConstructorCall(const CXXConstructorDecl *D,
return;
}
- llvm::Value *VTT = GetVTTParameter(*this, GlobalDecl(D, Type), ForVirtualBase);
+ llvm::Value *VTT = GetVTTParameter(*this, GlobalDecl(D, Type), ForVirtualBase,
+ Delegating);
llvm::Value *Callee = CGM.GetAddrOfCXXConstructor(D, Type);
// FIXME: Provide a source location here.
@@ -1331,7 +1338,8 @@ CodeGenFunction::EmitDelegateCXXConstructorCall(const CXXConstructorDecl *Ctor,
// vtt
if (llvm::Value *VTT = GetVTTParameter(*this, GlobalDecl(Ctor, CtorType),
- /*ForVirtualBase=*/false)) {
+ /*ForVirtualBase=*/false,
+ /*Delegating=*/true)) {
QualType VoidPP = getContext().getPointerType(getContext().VoidPtrTy);
DelegateArgs.add(RValue::get(VTT), VoidPP);
@@ -1365,7 +1373,7 @@ namespace {
void Emit(CodeGenFunction &CGF, Flags flags) {
CGF.EmitCXXDestructorCall(Dtor, Type, /*ForVirtualBase=*/false,
- Addr);
+ /*Delegating=*/true, Addr);
}
};
}
@@ -1401,9 +1409,10 @@ CodeGenFunction::EmitDelegatingCXXConstructorCall(const CXXConstructorDecl *Ctor
void CodeGenFunction::EmitCXXDestructorCall(const CXXDestructorDecl *DD,
CXXDtorType Type,
bool ForVirtualBase,
+ bool Delegating,
llvm::Value *This) {
llvm::Value *VTT = GetVTTParameter(*this, GlobalDecl(DD, Type),
- ForVirtualBase);
+ ForVirtualBase, Delegating);
llvm::Value *Callee = 0;
if (getLangOpts().AppleKext)
Callee = BuildAppleKextVirtualDestructorCall(DD, Type,
@@ -1427,7 +1436,8 @@ namespace {
void Emit(CodeGenFunction &CGF, Flags flags) {
CGF.EmitCXXDestructorCall(Dtor, Dtor_Complete,
- /*ForVirtualBase=*/false, Addr);
+ /*ForVirtualBase=*/false,
+ /*Delegating=*/false, Addr);
}
};
}