From bac5cf4110c1c9ba0992fad4fd9f66cedc27f3da Mon Sep 17 00:00:00 2001 From: Sebastian Redl Date: Sun, 19 Feb 2012 12:27:56 +0000 Subject: [PATCH] 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 --- lib/Sema/SemaInit.cpp | 22 ++++++++++---- .../cxx0x-initializer-stdinitializerlist.cpp | 30 ++++++++++++++++++- 2 files changed, 46 insertions(+), 6 deletions(-) diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp index 28b99f9e4c..1a62d246e4 100644 --- a/lib/Sema/SemaInit.cpp +++ b/lib/Sema/SemaInit.cpp @@ -5109,8 +5109,9 @@ InitializationSequence::Perform(Sema &S, // 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 @@ InitializationSequence::Perform(Sema &S, 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 a1c4167261..79d2073759 100644 --- a/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist.cpp +++ b/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist.cpp @@ -62,7 +62,10 @@ struct witharg1 { witharg1(const destroyme1&); ~witharg1(); }; - +struct wantslist1 { + wantslist1(std::initializer_list); + ~wantslist1(); +}; void fn2() { // CHECK: define void @_Z3fn2v @@ -108,3 +111,28 @@ void fn5() { // 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 +} -- 2.40.0