diff options
Diffstat (limited to 'test/CodeGenCXX/captured-statements.cpp')
-rw-r--r-- | test/CodeGenCXX/captured-statements.cpp | 189 |
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(); +} |