summaryrefslogtreecommitdiffstats
path: root/test/CodeGenCXX/captured-statements.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'test/CodeGenCXX/captured-statements.cpp')
-rw-r--r--test/CodeGenCXX/captured-statements.cpp189
1 files changed, 189 insertions, 0 deletions
diff --git a/test/CodeGenCXX/captured-statements.cpp b/test/CodeGenCXX/captured-statements.cpp
new file mode 100644
index 0000000..2843c2b
--- /dev/null
+++ b/test/CodeGenCXX/captured-statements.cpp
@@ -0,0 +1,189 @@
+// RUN: %clang_cc1 -std=c++11 -emit-llvm %s -o %t
+// RUN: FileCheck %s -input-file=%t -check-prefix=CHECK-1
+// RUN: FileCheck %s -input-file=%t -check-prefix=CHECK-2
+// RUN: FileCheck %s -input-file=%t -check-prefix=CHECK-3
+// RUN: FileCheck %s -input-file=%t -check-prefix=CHECK-4
+// RUN: FileCheck %s -input-file=%t -check-prefix=CHECK-5
+// RUN: FileCheck %s -input-file=%t -check-prefix=CHECK-6
+// RUN: FileCheck %s -input-file=%t -check-prefix=CHECK-7
+
+struct Foo {
+ int x;
+ float y;
+ ~Foo() {}
+};
+
+struct TestClass {
+ int x;
+
+ TestClass() : x(0) {};
+ void MemberFunc() {
+ Foo f;
+ #pragma clang __debug captured
+ {
+ f.y = x;
+ }
+ }
+};
+
+void test1() {
+ TestClass c;
+ c.MemberFunc();
+ // CHECK-1: %[[Capture:struct\.anon[\.0-9]*]] = type { %struct.Foo*, %struct.TestClass* }
+
+ // CHECK-1: define {{.*}} void @_ZN9TestClass10MemberFuncEv
+ // CHECK-1: alloca %struct.anon
+ // CHECK-1: getelementptr inbounds %[[Capture]]* %{{[^,]*}}, i32 0, i32 0
+ // CHECK-1: store %struct.Foo* %f, %struct.Foo**
+ // CHECK-1: getelementptr inbounds %[[Capture]]* %{{[^,]*}}, i32 0, i32 1
+ // CHECK-1: call void @[[HelperName:[A-Za-z0-9_]+]](%[[Capture]]*
+ // CHECK-1: call {{.*}}FooD1Ev
+ // CHECK-1: ret
+}
+
+// CHECK-1: define internal void @[[HelperName]]
+// CHECK-1: getelementptr inbounds %[[Capture]]* {{[^,]*}}, i32 0, i32 1
+// CHECK-1: getelementptr inbounds %struct.TestClass* {{[^,]*}}, i32 0, i32 0
+// CHECK-1: getelementptr inbounds %[[Capture]]* {{[^,]*}}, i32 0, i32 0
+
+void test2(int x) {
+ int y = [&]() {
+ #pragma clang __debug captured
+ {
+ x++;
+ }
+ return x;
+ }();
+
+ // CHECK-2-LABEL: define void @_Z5test2i
+ // CHECK-2: call {{.*}} @[[Lambda:["$\w]+]]
+ //
+ // CHECK-2: define internal {{.*}} @[[Lambda]]
+ // CHECK-2: call void @[[HelperName:["$_A-Za-z0-9]+]](%[[Capture:.*]]*
+ //
+ // CHECK-2: define internal void @[[HelperName]]
+ // CHECK-2: getelementptr inbounds %[[Capture]]*
+ // CHECK-2: load i32**
+ // CHECK-2: load i32*
+}
+
+void test3(int x) {
+ #pragma clang __debug captured
+ {
+ x = [=]() { return x + 1; } ();
+ }
+
+ // CHECK-3: %[[Capture:struct\.anon[\.0-9]*]] = type { i32* }
+
+ // CHECK-3-LABEL: define void @_Z5test3i
+ // CHECK-3: store i32*
+ // CHECK-3: call void @{{.*}}__captured_stmt
+ // CHECK-3: ret void
+}
+
+void test4() {
+ #pragma clang __debug captured
+ {
+ Foo f;
+ f.x = 5;
+ }
+ // CHECK-4-LABEL: define void @_Z5test4v
+ // CHECK-4: call void @[[HelperName:["$_A-Za-z0-9]+]](%[[Capture:.*]]*
+ // CHECK-4: ret void
+ //
+ // CHECK-4: define internal void @[[HelperName]]
+ // CHECK-4: store i32 5, i32*
+ // CHECK-4: call {{.*}}FooD1Ev
+}
+
+template <typename T, int id>
+void touch(const T &) {}
+
+template <typename T, unsigned id>
+void template_capture_var() {
+ T x;
+ #pragma clang __debug captured
+ {
+ touch<T, id>(x);
+ }
+}
+
+template <typename T, int id>
+class Val {
+ T v;
+public:
+ void set() {
+ #pragma clang __debug captured
+ {
+ touch<T, id>(v);
+ }
+ }
+
+ template <typename U, int id2>
+ void foo(U u) {
+ #pragma clang __debug captured
+ {
+ touch<U, id + id2>(u);
+ }
+ }
+};
+
+void test_capture_var() {
+ // CHECK-5: define {{.*}} void @_Z20template_capture_varIiLj201EEvv
+ // CHECK-5-NOT: }
+ // CHECK-5: store i32*
+ // CHECK-5: call void @__captured_stmt
+ // CHECK-5-NEXT: ret void
+ template_capture_var<int, 201>();
+
+ // CHECK-5: define {{.*}} void @_ZN3ValIfLi202EE3setEv
+ // CHECK-5-NOT: }
+ // CHECK-5: store %class.Val*
+ // CHECK-5: call void @__captured_stmt
+ // CHECK-5-NEXT: ret void
+ Val<float, 202> Obj;
+ Obj.set();
+
+ // CHECK-5: define {{.*}} void @_ZN3ValIfLi202EE3fooIdLi203EEEvT_
+ // CHECK-5-NOT: }
+ // CHECK-5: store %class.Val*
+ // CHECK-5: store double
+ // CHECK-5: call void @__captured_stmt
+ // CHECK-5-NEXT: ret void
+ Obj.foo<double, 203>(1.0);
+}
+
+template <typename T>
+void template_capture_lambda() {
+ T x, y;
+ [=, &y]() {
+ #pragma clang __debug captured
+ {
+ y += x;
+ }
+ }();
+}
+
+void test_capture_lambda() {
+ // CHECK-6: define {{.*}} void @_ZZ23template_capture_lambdaIiEvvENKUlvE_clEv
+ // CHECK-6-NOT: }
+ // CHECK-6: store i32*
+ // CHECK-6: store i32*
+ // CHECK-6: call void @__captured_stmt
+ // CHECK-6-NEXT: ret void
+ template_capture_lambda<int>();
+}
+
+inline int test_captured_linkage() {
+ // CHECK-7: @_ZZ21test_captured_linkagevE1i = linkonce_odr global i32 0
+ int j;
+ #pragma clang __debug captured
+ {
+ static int i = 0;
+ j = ++i;
+ }
+ return j;
+}
+void call_test_captured_linkage() {
+ test_captured_linkage();
+}
OpenPOWER on IntegriCloud