diff options
Diffstat (limited to 'test/CodeGenCXX/cxx0x-initializer-stdinitializerlist.cpp')
-rw-r--r-- | test/CodeGenCXX/cxx0x-initializer-stdinitializerlist.cpp | 202 |
1 files changed, 179 insertions, 23 deletions
diff --git a/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist.cpp b/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist.cpp index d683493..164cbce 100644 --- a/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist.cpp +++ b/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist.cpp @@ -47,23 +47,48 @@ struct wantslist1 { ~wantslist1(); }; -// CHECK: @_ZL25globalInitList1__initlist = internal global [3 x i32] [i32 1, i32 2, i32 3] -// CHECK: @globalInitList1 = global %{{[^ ]+}} { i32* getelementptr inbounds ([3 x i32]* @_ZL25globalInitList1__initlist, i32 0, i32 0), i{{32|64}} 3 } +// CHECK: @_ZGR15globalInitList1 = private constant [3 x i32] [i32 1, i32 2, i32 3] +// CHECK: @globalInitList1 = global %{{[^ ]+}} { i32* getelementptr inbounds ([3 x i32]* @_ZGR15globalInitList1, i32 0, i32 0), i{{32|64}} 3 } std::initializer_list<int> globalInitList1 = {1, 2, 3}; namespace thread_local_global_array { - // CHECK: @_ZN25thread_local_global_arrayL11x__initlistE = internal thread_local global [4 x i32] [i32 1, i32 2, i32 3, i32 4] - // CHECK: @_ZN25thread_local_global_array1xE = thread_local global {{.*}} @_ZN25thread_local_global_arrayL11x__initlistE, {{.*}} i64 4 + // FIXME: We should be able to constant-evaluate this even though the + // initializer is not a constant expression (pointers to thread_local + // objects aren't really a problem). + // + // CHECK: @_ZN25thread_local_global_array1xE = thread_local global + // CHECK: @_ZGRN25thread_local_global_array1xE = private thread_local constant [4 x i32] [i32 1, i32 2, i32 3, i32 4] std::initializer_list<int> thread_local x = { 1, 2, 3, 4 }; } -// CHECK: @_ZL25globalInitList2__initlist = internal global [2 x %{{[^ ]*}}] zeroinitializer -// CHECK: @globalInitList2 = global %{{[^ ]+}} { %[[WITHARG:[^ *]+]]* getelementptr inbounds ([2 x +// CHECK: @globalInitList2 = global %{{[^ ]+}} zeroinitializer +// CHECK: @_ZGR15globalInitList2 = private global [2 x %[[WITHARG:[^ ]*]]] zeroinitializer + +// CHECK: @_ZN15partly_constant1kE = global i32 0, align 4 +// CHECK: @_ZN15partly_constant2ilE = global {{.*}} null, align 8 +// CHECK: @[[PARTLY_CONSTANT_OUTER:_ZGRN15partly_constant2ilE.*]] = private global {{.*}} zeroinitializer, align 8 +// CHECK: @[[PARTLY_CONSTANT_INNER:_ZGRN15partly_constant2ilE.*]] = private global [3 x {{.*}}] zeroinitializer, align 8 +// CHECK: @[[PARTLY_CONSTANT_FIRST:_ZGRN15partly_constant2ilE.*]] = private constant [3 x i32] [i32 1, i32 2, i32 3], align 4 +// CHECK: @[[PARTLY_CONSTANT_SECOND:_ZGRN15partly_constant2ilE.*]] = private global [2 x i32] zeroinitializer, align 4 +// CHECK: @[[PARTLY_CONSTANT_THIRD:_ZGRN15partly_constant2ilE.*]] = private constant [4 x i32] [i32 5, i32 6, i32 7, i32 8], align 4 + // CHECK: appending global -// CHECK: define internal void -// CHECK: call void @_ZN8witharg1C1ERK10destroyme1(%[[WITHARG]]* getelementptr inbounds ([2 x %[[WITHARG]]]* @_ZL25globalInitList2__initlist, i{{32|64}} 0, i{{32|64}} 0 -// CHECK: call void @_ZN8witharg1C1ERK10destroyme1(%[[WITHARG]]* getelementptr inbounds ([2 x %[[WITHARG]]]* @_ZL25globalInitList2__initlist, i{{32|64}} 0, i{{32|64}} 1 + + +// thread_local initializer: +// CHECK-LABEL: define internal void +// CHECK: store i32* getelementptr inbounds ([4 x i32]* @_ZGRN25thread_local_global_array1xE, i64 0, i64 0), +// CHECK: i32** getelementptr inbounds ({{.*}}* @_ZN25thread_local_global_array1xE, i32 0, i32 0), align 8 +// CHECK: store i64 4, i64* getelementptr inbounds ({{.*}}* @_ZN25thread_local_global_array1xE, i32 0, i32 1), align 8 + + +// CHECK-LABEL: define internal void +// CHECK: call void @_ZN8witharg1C1ERK10destroyme1(%[[WITHARG]]* getelementptr inbounds ([2 x %[[WITHARG]]]* @_ZGR15globalInitList2, i{{32|64}} 0, i{{32|64}} 0 +// CHECK: call void @_ZN8witharg1C1ERK10destroyme1(%[[WITHARG]]* getelementptr inbounds ([2 x %[[WITHARG]]]* @_ZGR15globalInitList2, i{{32|64}} 0, i{{32|64}} 1 // CHECK: __cxa_atexit +// CHECK: store %[[WITHARG]]* getelementptr inbounds ([2 x %[[WITHARG]]]* @_ZGR15globalInitList2, i64 0, i64 0), +// CHECK: %[[WITHARG]]** getelementptr inbounds (%{{.*}}* @globalInitList2, i32 0, i32 0), align 8 +// CHECK: store i64 2, i64* getelementptr inbounds (%{{.*}}* @globalInitList2, i32 0, i32 1), align 8 // CHECK: call void @_ZN10destroyme1D1Ev // CHECK: call void @_ZN10destroyme1D1Ev std::initializer_list<witharg1> globalInitList2 = { @@ -71,7 +96,7 @@ std::initializer_list<witharg1> globalInitList2 = { }; void fn1(int i) { - // CHECK: define void @_Z3fn1i + // CHECK-LABEL: define void @_Z3fn1i // temporary array // CHECK: [[array:%[^ ]+]] = alloca [3 x i32] // CHECK: getelementptr inbounds [3 x i32]* [[array]], i{{32|64}} 0 @@ -91,7 +116,7 @@ void fn1(int i) { } void fn2() { - // CHECK: define void @_Z3fn2v + // CHECK-LABEL: define void @_Z3fn2v void target(std::initializer_list<destroyme1>); // objects should be destroyed before dm2, after call returns // CHECK: call void @_Z6targetSt16initializer_listI10destroyme1E @@ -102,7 +127,7 @@ void fn2() { } void fn3() { - // CHECK: define void @_Z3fn3v + // CHECK-LABEL: define void @_Z3fn3v // objects should be destroyed after dm2 auto list = { destroyme1(), destroyme1() }; destroyme2 dm2; @@ -111,7 +136,7 @@ void fn3() { } void fn4() { - // CHECK: define void @_Z3fn4v + // CHECK-LABEL: define void @_Z3fn4v void target(std::initializer_list<witharg1>); // objects should be destroyed before dm2, after call returns // CHECK: call void @_ZN8witharg1C1ERK10destroyme1 @@ -124,7 +149,7 @@ void fn4() { } void fn5() { - // CHECK: define void @_Z3fn5v + // CHECK-LABEL: define void @_Z3fn5v // temps should be destroyed before dm2 // objects should be destroyed after dm2 // CHECK: call void @_ZN8witharg1C1ERK10destroyme1 @@ -136,7 +161,7 @@ void fn5() { } void fn6() { - // CHECK: define void @_Z3fn6v + // CHECK-LABEL: define void @_Z3fn6v void target(const wantslist1&); // objects should be destroyed before dm2, after call returns // CHECK: call void @_ZN10wantslist1C1ESt16initializer_listI10destroyme1E @@ -149,7 +174,7 @@ void fn6() { } void fn7() { - // CHECK: define void @_Z3fn7v + // CHECK-LABEL: define void @_Z3fn7v // temps should be destroyed before dm2 // object should be destroyed after dm2 // CHECK: call void @_ZN10wantslist1C1ESt16initializer_listI10destroyme1E @@ -161,7 +186,7 @@ void fn7() { } void fn8() { - // CHECK: define void @_Z3fn8v + // CHECK-LABEL: define void @_Z3fn8v void target(std::initializer_list<std::initializer_list<destroyme1>>); // objects should be destroyed before dm2, after call returns // CHECK: call void @_Z6targetSt16initializer_listIS_I10destroyme1EE @@ -175,7 +200,7 @@ void fn8() { } void fn9() { - // CHECK: define void @_Z3fn9v + // CHECK-LABEL: define void @_Z3fn9v // objects should be destroyed after dm2 std::initializer_list<destroyme1> inner; std::initializer_list<std::initializer_list<destroyme1>> list = @@ -193,7 +218,7 @@ struct haslist1 { haslist1(); }; -// CHECK: define void @_ZN8haslist1C2Ev +// CHECK-LABEL: define void @_ZN8haslist1C2Ev haslist1::haslist1() // CHECK: alloca [3 x i32] // CHECK: store i32 1 @@ -210,7 +235,7 @@ struct haslist2 { haslist2(); }; -// CHECK: define void @_ZN8haslist2C2Ev +// CHECK-LABEL: define void @_ZN8haslist2C2Ev haslist2::haslist2() : il{destroyme1(), destroyme1()} { @@ -220,7 +245,7 @@ haslist2::haslist2() } void fn10() { - // CHECK: define void @_Z4fn10v + // CHECK-LABEL: define void @_Z4fn10v // CHECK: alloca [3 x i32] // CHECK: call noalias i8* @_Znw{{[jm]}} // CHECK: store i32 1 @@ -232,7 +257,7 @@ void fn10() { } void fn11() { - // CHECK: define void @_Z4fn11v + // CHECK-LABEL: define void @_Z4fn11v (void) new std::initializer_list<destroyme1> {destroyme1(), destroyme1()}; // CHECK: call void @_ZN10destroyme1D1Ev destroyme2 dm2; @@ -260,7 +285,7 @@ namespace PR12178 { namespace rdar13325066 { struct X { ~X(); }; - // CHECK: define void @_ZN12rdar133250664loopERNS_1XES1_ + // CHECK-LABEL: define void @_ZN12rdar133250664loopERNS_1XES1_ void loop(X &x1, X &x2) { // CHECK: br label // CHECK: br i1 @@ -275,3 +300,134 @@ namespace rdar13325066 { for (X x : { x1, x2 }) { } } } + +namespace dtors { + struct S { + S(); + ~S(); + }; + void z(); + + // CHECK-LABEL: define void @_ZN5dtors1fEv( + void f() { + // CHECK: call void @_ZN5dtors1SC1Ev( + // CHECK: call void @_ZN5dtors1SC1Ev( + std::initializer_list<S>{ S(), S() }; + + // Destruction loop for underlying array. + // CHECK: br label + // CHECK: call void @_ZN5dtors1SD1Ev( + // CHECK: br i1 + + // CHECK: call void @_ZN5dtors1zEv( + z(); + + // CHECK-NOT: call void @_ZN5dtors1SD1Ev( + } + + // CHECK-LABEL: define void @_ZN5dtors1gEv( + void g() { + // CHECK: call void @_ZN5dtors1SC1Ev( + // CHECK: call void @_ZN5dtors1SC1Ev( + auto x = std::initializer_list<S>{ S(), S() }; + + // Destruction loop for underlying array. + // CHECK: br label + // CHECK: call void @_ZN5dtors1SD1Ev( + // CHECK: br i1 + + // CHECK: call void @_ZN5dtors1zEv( + z(); + + // CHECK-NOT: call void @_ZN5dtors1SD1Ev( + } + + // CHECK-LABEL: define void @_ZN5dtors1hEv( + void h() { + // CHECK: call void @_ZN5dtors1SC1Ev( + // CHECK: call void @_ZN5dtors1SC1Ev( + std::initializer_list<S> x = { S(), S() }; + + // CHECK-NOT: call void @_ZN5dtors1SD1Ev( + + // CHECK: call void @_ZN5dtors1zEv( + z(); + + // Destruction loop for underlying array. + // CHECK: br label + // CHECK: call void @_ZN5dtors1SD1Ev( + // CHECK: br i1 + } +} + +namespace partly_constant { + int k; + std::initializer_list<std::initializer_list<int>> &&il = { { 1, 2, 3 }, { 4, k }, { 5, 6, 7, 8 } }; + // First init list. + // CHECK-NOT: @[[PARTLY_CONSTANT_FIRST]], + // CHECK: store i32* getelementptr inbounds ({{.*}}* @[[PARTLY_CONSTANT_FIRST]], i64 0, i64 0), + // CHECK: i32** getelementptr inbounds ({{.*}}* @[[PARTLY_CONSTANT_INNER]], i64 0, i64 0, i32 0) + // CHECK: store i64 3, i64* getelementptr inbounds ({{.*}}* @[[PARTLY_CONSTANT_INNER]], i64 0, i64 0, i32 1) + // CHECK-NOT: @[[PARTLY_CONSTANT_FIRST]], + // + // Second init list array (non-constant). + // CHECK: store i32 4, i32* getelementptr inbounds ({{.*}}* @[[PARTLY_CONSTANT_SECOND]], i64 0, i64 0) + // CHECK: load i32* @_ZN15partly_constant1kE + // CHECK: store i32 {{.*}}, i32* getelementptr inbounds ({{.*}}* @[[PARTLY_CONSTANT_SECOND]], i64 0, i64 1) + // + // Second init list. + // CHECK: store i32* getelementptr inbounds ({{.*}}* @[[PARTLY_CONSTANT_SECOND]], i64 0, i64 0), + // CHECK: i32** getelementptr inbounds ({{.*}}* @[[PARTLY_CONSTANT_INNER]], i64 0, i64 1, i32 0) + // CHECK: store i64 2, i64* getelementptr inbounds ({{.*}}* @[[PARTLY_CONSTANT_INNER]], i64 0, i64 1, i32 1) + // + // Third init list. + // CHECK-NOT: @[[PARTLY_CONSTANT_THIRD]], + // CHECK: store i32* getelementptr inbounds ({{.*}}* @[[PARTLY_CONSTANT_THIRD]], i64 0, i64 0), + // CHECK: i32** getelementptr inbounds ({{.*}}* @[[PARTLY_CONSTANT_INNER]], i64 0, i64 2, i32 0) + // CHECK: store i64 4, i64* getelementptr inbounds ({{.*}}* @_ZGRN15partly_constant2ilE4, i64 0, i64 2, i32 1) + // CHECK-NOT: @[[PARTLY_CONSTANT_THIRD]], + // + // Outer init list. + // CHECK: store {{.*}}* getelementptr inbounds ({{.*}}* @[[PARTLY_CONSTANT_INNER]], i64 0, i64 0), + // CHECK: {{.*}}** getelementptr inbounds ({{.*}}* @[[PARTLY_CONSTANT_OUTER]], i32 0, i32 0) + // CHECK: store i64 3, i64* getelementptr inbounds ({{.*}}* @[[PARTLY_CONSTANT_OUTER]], i32 0, i32 1) + // + // '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-LABEL: 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: } + } +} |