summaryrefslogtreecommitdiffstats
path: root/clang/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist.cpp
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2013-06-12 22:31:48 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2013-06-12 22:31:48 +0000
commitcc1b96d356a0bd85c033309b8cfa965f36ae8aa6 (patch)
tree0494bcbc5d7f1e890c1c814a70b4ee0dd0a8352e /clang/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist.cpp
parent6a0c9ae4f93fd29b7bae48513674ab18dda73f9e (diff)
downloadbcm5719-llvm-cc1b96d356a0bd85c033309b8cfa965f36ae8aa6.tar.gz
bcm5719-llvm-cc1b96d356a0bd85c033309b8cfa965f36ae8aa6.zip
PR12086, PR15117
Introduce CXXStdInitializerListExpr node, representing the implicit construction of a std::initializer_list<T> object from its underlying array. The AST representation of such an expression goes from an InitListExpr with a flag set, to a CXXStdInitializerListExpr containing a MaterializeTemporaryExpr containing an InitListExpr (possibly wrapped in a CXXBindTemporaryExpr). This more detailed representation has several advantages, the most important of which is that the new MaterializeTemporaryExpr allows us to directly model lifetime extension of the underlying temporary array. Using that, this patch *drastically* simplifies the IR generation of this construct, provides IR generation support for nested global initializer_list objects, fixes several bugs where the destructors for the underlying array would accidentally not get invoked, and provides constant expression evaluation support for std::initializer_list objects. llvm-svn: 183872
Diffstat (limited to 'clang/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist.cpp')
-rw-r--r--clang/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist.cpp82
1 files changed, 74 insertions, 8 deletions
diff --git a/clang/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist.cpp b/clang/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist.cpp
index 54d88f565ee..593367c8f13 100644
--- a/clang/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist.cpp
+++ b/clang/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist.cpp
@@ -47,23 +47,43 @@ 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 global [4 x i32]
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: appending global
+
+
+// thread_local initializer:
+// CHECK: define internal void
+// CHECK: store i32 1, i32* getelementptr inbounds ([4 x i32]* @_ZGRN25thread_local_global_array1xE, i64 0, i64 0)
+// CHECK: store i32 2, i32* getelementptr inbounds ([4 x i32]* @_ZGRN25thread_local_global_array1xE, i64 0, i64 1)
+// CHECK: store i32 3, i32* getelementptr inbounds ([4 x i32]* @_ZGRN25thread_local_global_array1xE, i64 0, i64 2)
+// CHECK: store i32 4, i32* getelementptr inbounds ([4 x i32]* @_ZGRN25thread_local_global_array1xE, i64 0, i64 3)
+// 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: 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
+// 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 = {
@@ -281,10 +301,56 @@ namespace dtors {
S();
~S();
};
+ void z();
+
+ // CHECK: define void @_ZN5dtors1fEv(
void f() {
+ // CHECK: call void @_ZN5dtors1SC1Ev(%"struct.dtors::S"* %arrayinit.begin)
+ // CHECK: call void @_ZN5dtors1SC1Ev(%"struct.dtors::S"* %arrayinit.element)
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: define void @_ZN5dtors1gEv(
void g() {
+ // CHECK: call void @_ZN5dtors1SC1Ev(%"struct.dtors::S"* %arrayinit.begin)
+ // CHECK: call void @_ZN5dtors1SC1Ev(%"struct.dtors::S"* %arrayinit.element)
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: define void @_ZN5dtors1hEv(
+ void h() {
+ // CHECK: call void @_ZN5dtors1SC1Ev(%"struct.dtors::S"* %arrayinit.begin)
+ // CHECK: call void @_ZN5dtors1SC1Ev(%"struct.dtors::S"* %arrayinit.element)
+ 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
}
}
OpenPOWER on IntegriCloud