Convert the EH cleanups for base and member destructors in a constructor into

lazy cleanups.

llvm-svn: 108978
This commit is contained in:
John McCall 2010-07-21 01:23:41 +00:00
parent 05fc5be32f
commit 1d9875654f
2 changed files with 47 additions and 23 deletions

View File

@ -310,6 +310,22 @@ static llvm::Value *GetVTTParameter(CodeGenFunction &CGF, GlobalDecl GD,
return VTT;
}
namespace {
struct CallBaseDtor : EHScopeStack::LazyCleanup {
CXXDestructorDecl *Dtor;
bool isBaseVirtual;
llvm::Value *Addr;
CallBaseDtor(CXXDestructorDecl *DD, bool isVirtual, llvm::Value *Addr)
: Dtor(DD), isBaseVirtual(isVirtual), Addr(Addr) {}
void Emit(CodeGenFunction &CGF, bool IsForEH) {
// FIXME: Is this OK for C++0x delegating constructors?
CGF.EmitCXXDestructorCall(Dtor, Dtor_Base, isBaseVirtual, Addr);
}
};
}
static void EmitBaseInitializer(CodeGenFunction &CGF,
const CXXRecordDecl *ClassDecl,
CXXBaseOrMemberInitializer *BaseInit,
@ -338,13 +354,10 @@ static void EmitBaseInitializer(CodeGenFunction &CGF,
CGF.EmitAggExpr(BaseInit->getInit(), V, false, false, true);
if (CGF.Exceptions && !BaseClassDecl->hasTrivialDestructor()) {
// FIXME: Is this OK for C++0x delegating constructors?
CodeGenFunction::CleanupBlock Cleanup(CGF, EHCleanup);
CXXDestructorDecl *DD = BaseClassDecl->getDestructor();
CGF.EmitCXXDestructorCall(DD, Dtor_Base, isBaseVirtual, V);
}
if (CGF.Exceptions && !BaseClassDecl->hasTrivialDestructor())
CGF.EHStack.pushLazyCleanup<CallBaseDtor>(EHCleanup,
BaseClassDecl->getDestructor(),
isBaseVirtual, V);
}
static void EmitAggMemberInitializer(CodeGenFunction &CGF,
@ -432,6 +445,25 @@ static void EmitAggMemberInitializer(CodeGenFunction &CGF,
// Emit the fall-through block.
CGF.EmitBlock(AfterFor, true);
}
namespace {
struct CallMemberDtor : EHScopeStack::LazyCleanup {
FieldDecl *Field;
CXXDestructorDecl *Dtor;
CallMemberDtor(FieldDecl *Field, CXXDestructorDecl *Dtor)
: Field(Field), Dtor(Dtor) {}
void Emit(CodeGenFunction &CGF, bool IsForEH) {
// FIXME: Is this OK for C++0x delegating constructors?
llvm::Value *ThisPtr = CGF.LoadCXXThis();
LValue LHS = CGF.EmitLValueForField(ThisPtr, Field, 0);
CGF.EmitCXXDestructorCall(Dtor, Dtor_Complete, /*ForVirtualBase=*/false,
LHS.getAddress());
}
};
}
static void EmitMemberInitializer(CodeGenFunction &CGF,
const CXXRecordDecl *ClassDecl,
@ -532,17 +564,9 @@ static void EmitMemberInitializer(CodeGenFunction &CGF,
return;
CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
if (!RD->hasTrivialDestructor()) {
// FIXME: Is this OK for C++0x delegating constructors?
CodeGenFunction::CleanupBlock Cleanup(CGF, EHCleanup);
llvm::Value *ThisPtr = CGF.LoadCXXThis();
LValue LHS = CGF.EmitLValueForField(ThisPtr, Field, 0);
CXXDestructorDecl *DD = RD->getDestructor();
CGF.EmitCXXDestructorCall(DD, Dtor_Complete, /*ForVirtualBase=*/false,
LHS.getAddress());
}
if (!RD->hasTrivialDestructor())
CGF.EHStack.pushLazyCleanup<CallMemberDtor>(EHCleanup, Field,
RD->getDestructor());
}
}

View File

@ -262,11 +262,6 @@ namespace test5 {
// Checks from test3:
// CHECK: define internal void @_ZN5test312_GLOBAL__N_11CD2Ev(
// CHECK: call void @_ZN5test31BD2Ev(
// CHECK: call void @_ZN5test31AD2Ev(
// CHECK: ret void
// CHECK: define internal void @_ZN5test312_GLOBAL__N_11DD0Ev(
// CHECK: invoke void @_ZN5test312_GLOBAL__N_11DD1Ev(
// CHECK: call void @_ZdlPv({{.*}}) nounwind
@ -289,6 +284,11 @@ namespace test5 {
// CHECK: call void @_ZN5test312_GLOBAL__N_11DD0Ev(
// CHECK: ret void
// CHECK: define internal void @_ZN5test312_GLOBAL__N_11CD2Ev(
// CHECK: call void @_ZN5test31BD2Ev(
// CHECK: call void @_ZN5test31AD2Ev(
// CHECK: ret void
// CHECK: declare void @_ZN5test31BD2Ev(
// CHECK: declare void @_ZN5test31AD2Ev(