Add a testcase for using objects with list-constructors, and fix a Sema crash by repeating an old hack.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@150925 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp
index 28b99f9..1a62d24 100644
--- a/lib/Sema/SemaInit.cpp
+++ b/lib/Sema/SemaInit.cpp
@@ -5109,8 +5109,9 @@
// When an initializer list is passed for a parameter of type "reference
// to object", we don't get an EK_Temporary entity, but instead an
// EK_Parameter entity with reference type.
- // FIXME: This is a hack. Why is this necessary here, but not in other
- // places where implicit temporaries are created?
+ // FIXME: This is a hack. What we really should do is create a user
+ // conversion step for this case, but this makes it considerably more
+ // complicated. For now, this will do.
InitializedEntity TempEntity = InitializedEntity::InitializeTemporary(
Entity.getType().getNonReferenceType());
bool UseTemporary = Entity.getType()->isReferenceType();
@@ -5139,11 +5140,22 @@
break;
}
- case SK_ConstructorInitialization:
- CurInit = PerformConstructorInitialization(S, Entity, Kind, move(Args),
- *Step,
+ case SK_ConstructorInitialization: {
+ // When an initializer list is passed for a parameter of type "reference
+ // to object", we don't get an EK_Temporary entity, but instead an
+ // EK_Parameter entity with reference type.
+ // FIXME: This is a hack. What we really should do is create a user
+ // conversion step for this case, but this makes it considerably more
+ // complicated. For now, this will do.
+ InitializedEntity TempEntity = InitializedEntity::InitializeTemporary(
+ Entity.getType().getNonReferenceType());
+ bool UseTemporary = Entity.getType()->isReferenceType();
+ CurInit = PerformConstructorInitialization(S, UseTemporary ? TempEntity
+ : Entity,
+ Kind, move(Args), *Step,
ConstructorInitRequiresZeroInit);
break;
+ }
case SK_ZeroInitialization: {
step_iterator NextStep = Step;
diff --git a/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist.cpp b/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist.cpp
index a1c4167..79d2073 100644
--- a/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist.cpp
+++ b/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist.cpp
@@ -62,7 +62,10 @@
witharg1(const destroyme1&);
~witharg1();
};
-
+struct wantslist1 {
+ wantslist1(std::initializer_list<destroyme1>);
+ ~wantslist1();
+};
void fn2() {
// CHECK: define void @_Z3fn2v
@@ -108,3 +111,28 @@
// CHECK: call void @_ZN10destroyme2D1Ev
// CHECK: call void @_ZN8witharg1D1Ev
}
+
+void fn6() {
+ // CHECK: define void @_Z3fn6v
+ void target(const wantslist1&);
+ // objects should be destroyed before dm2, after call returns
+ // CHECK: call void @_ZN10wantslist1C1ESt16initializer_listI10destroyme1E
+ // CHECK: call void @_Z6targetRK10wantslist1
+ target({ destroyme1(), destroyme1() });
+ // CHECK: call void @_ZN10wantslist1D1Ev
+ // CHECK: call void @_ZN10destroyme1D1Ev
+ destroyme2 dm2;
+ // CHECK: call void @_ZN10destroyme2D1Ev
+}
+
+void fn7() {
+ // CHECK: define void @_Z3fn7v
+ // temps should be destroyed before dm2
+ // object should be destroyed after dm2
+ // CHECK: call void @_ZN10wantslist1C1ESt16initializer_listI10destroyme1E
+ wantslist1 wl = { destroyme1(), destroyme1() };
+ // CHECK: call void @_ZN10destroyme1D1Ev
+ destroyme2 dm2;
+ // CHECK: call void @_ZN10destroyme2D1Ev
+ // CHECK: call void @_ZN10wantslist1D1Ev
+}