summaryrefslogtreecommitdiffstats
path: root/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'test/CodeGenCXX/cxx0x-initializer-stdinitializerlist.cpp')
-rw-r--r--test/CodeGenCXX/cxx0x-initializer-stdinitializerlist.cpp202
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: }
+ }
+}
OpenPOWER on IntegriCloud