Fix nested lifetime extension when a std::initializer_list member is

initialized during aggregate initialization of the surrounding structure.

llvm-svn: 185117
This commit is contained in:
Richard Smith 2013-06-27 22:54:33 +00:00
parent 5c5e6179a0
commit 8d7f11da50
2 changed files with 41 additions and 3 deletions

View File

@ -5348,13 +5348,15 @@ static void performLifetimeExtension(Expr *Init, const ValueDecl *ExtendingD) {
I != E; ++I) {
if (I->isUnnamedBitfield())
continue;
Expr *SubInit = ILE->getInit(Index);
if (I->getType()->isReferenceType())
performReferenceExtension(ILE->getInit(Index), ExtendingD);
else if (isa<InitListExpr>(ILE->getInit(Index)))
performReferenceExtension(SubInit, ExtendingD);
else if (isa<InitListExpr>(SubInit) ||
isa<CXXStdInitializerListExpr>(SubInit))
// This may be either aggregate-initialization of a member or
// initialization of a std::initializer_list object. Either way,
// we should recursively lifetime-extend that initializer.
performLifetimeExtension(ILE->getInit(Index), ExtendingD);
performLifetimeExtension(SubInit, ExtendingD);
++Index;
}
}

View File

@ -395,3 +395,39 @@ namespace partly_constant {
// 'il' reference.
// CHECK: store {{.*}}* @[[PARTLY_CONSTANT_OUTER]], {{.*}}** @_ZN15partly_constant2ilE, align 8
}
namespace nested {
struct A { A(); ~A(); };
struct B { const A &a; ~B(); };
struct C { std::initializer_list<B> b; ~C(); };
void f();
// CHECK: define void @_ZN6nested1gEv(
void g() {
// CHECK: call void @_ZN6nested1AC1Ev(
// CHECK-NOT: call
// CHECK: call void @_ZN6nested1AC1Ev(
// CHECK-NOT: call
const C &c { { { A() }, { A() } } };
// CHECK: call void @_ZN6nested1fEv(
// CHECK-NOT: call
f();
// CHECK: call void @_ZN6nested1CD1Ev(
// CHECK-NOT: call
// Destroy B[2] array.
// FIXME: This isn't technically correct: reverse construction order would
// destroy the second B then the second A then the first B then the first A.
// CHECK: call void @_ZN6nested1BD1Ev(
// CHECK-NOT: call
// CHECK: br
// CHECK-NOT: call
// CHECK: call void @_ZN6nested1AD1Ev(
// CHECK-NOT: call
// CHECK: call void @_ZN6nested1AD1Ev(
// CHECK-NOT: call
// CHECK: }
}
}