1 // RUN: %clang_cc1 -std=c++11 -emit-llvm %s -o %t 2 // RUN: FileCheck %s -input-file=%t -check-prefix=CHECK-1 3 // RUN: FileCheck %s -input-file=%t -check-prefix=CHECK-2 4 // RUN: FileCheck %s -input-file=%t -check-prefix=CHECK-3 5 // RUN: FileCheck %s -input-file=%t -check-prefix=CHECK-4 6 // RUN: FileCheck %s -input-file=%t -check-prefix=CHECK-5 7 // RUN: FileCheck %s -input-file=%t -check-prefix=CHECK-6 8 9 struct Foo { 10 int x; 11 float y; 12 ~Foo() {} 13 }; 14 15 struct TestClass { 16 int x; 17 18 TestClass() : x(0) {}; 19 void MemberFunc() { 20 Foo f; 21 #pragma clang __debug captured 22 { 23 f.y = x; 24 } 25 } 26 }; 27 28 void test1() { 29 TestClass c; 30 c.MemberFunc(); 31 // CHECK-1: %[[Capture:struct\.anon[\.0-9]*]] = type { %struct.Foo*, %struct.TestClass* } 32 33 // CHECK-1: define {{.*}} void @_ZN9TestClass10MemberFuncEv 34 // CHECK-1: alloca %struct.anon 35 // CHECK-1: getelementptr inbounds %[[Capture]]* %{{[^,]*}}, i32 0, i32 0 36 // CHECK-1: store %struct.Foo* %f, %struct.Foo** 37 // CHECK-1: getelementptr inbounds %[[Capture]]* %{{[^,]*}}, i32 0, i32 1 38 // CHECK-1: call void @[[HelperName:[A-Za-z0-9_]+]](%[[Capture]]* 39 // CHECK-1: call {{.*}}FooD1Ev 40 // CHECK-1: ret 41 } 42 43 // CHECK-1: define internal void @[[HelperName]] 44 // CHECK-1: getelementptr inbounds %[[Capture]]* {{[^,]*}}, i32 0, i32 1 45 // CHECK-1: getelementptr inbounds %struct.TestClass* {{[^,]*}}, i32 0, i32 0 46 // CHECK-1: getelementptr inbounds %[[Capture]]* {{[^,]*}}, i32 0, i32 0 47 48 void test2(int x) { 49 int y = [&]() { 50 #pragma clang __debug captured 51 { 52 x++; 53 } 54 return x; 55 }(); 56 57 // CHECK-2: define void @_Z5test2i 58 // CHECK-2: call i32 @[[Lambda:["$\w]+]] 59 // 60 // CHECK-2: define internal i32 @[[Lambda]] 61 // CHECK-2: call void @[[HelperName:["$_A-Za-z0-9]+]](%[[Capture:.*]]* 62 // 63 // CHECK-2: define internal void @[[HelperName]] 64 // CHECK-2: getelementptr inbounds %[[Capture]]* 65 // CHECK-2: load i32** 66 // CHECK-2: load i32* 67 } 68 69 void test3(int x) { 70 #pragma clang __debug captured 71 { 72 x = [=]() { return x + 1; } (); 73 } 74 75 // CHECK-3: %[[Capture:struct\.anon[\.0-9]*]] = type { i32* } 76 77 // CHECK-3: define void @_Z5test3i(i32 %x) 78 // CHECK-3: store i32* 79 // CHECK-3: call void @{{.*}}__captured_stmt 80 // CHECK-3: ret void 81 } 82 83 void test4() { 84 #pragma clang __debug captured 85 { 86 Foo f; 87 f.x = 5; 88 } 89 // CHECK-4: %[[Capture:struct\.anon[\.0-9]*]] = type { i32* } 90 91 // CHECK-4: define void @_Z5test3i(i32 %x) 92 // CHECK-4: store i32* 93 // CHECK-4: call void @[[HelperName:["$_A-Za-z0-9]+]](%[[Capture:.*]]* 94 // CHECK-4: ret void 95 // 96 // CHECK-4: define internal void @[[HelperName]] 97 // CHECK-4: store i32 5, i32* 98 // CHECK-4: call {{.*}}FooD1Ev 99 } 100 101 template <typename T, int id> 102 void touch(const T &) {} 103 104 template <typename T, unsigned id> 105 void template_capture_var() { 106 T x; 107 #pragma clang __debug captured 108 { 109 touch<T, id>(x); 110 } 111 } 112 113 template <typename T, int id> 114 class Val { 115 T v; 116 public: 117 void set() { 118 #pragma clang __debug captured 119 { 120 touch<T, id>(v); 121 } 122 } 123 124 template <typename U, int id2> 125 void foo(U u) { 126 #pragma clang __debug captured 127 { 128 touch<U, id + id2>(u); 129 } 130 } 131 }; 132 133 void test_capture_var() { 134 // CHECK-5: define {{.*}} void @_Z20template_capture_varIiLj201EEvv 135 // CHECK-5-NOT: } 136 // CHECK-5: store i32* 137 // CHECK-5: call void @__captured_stmt 138 // CHECK-5-NEXT: ret void 139 template_capture_var<int, 201>(); 140 141 // CHECK-5: define {{.*}} void @_ZN3ValIfLi202EE3setEv 142 // CHECK-5-NOT: } 143 // CHECK-5: store %class.Val* 144 // CHECK-5: call void @__captured_stmt 145 // CHECK-5-NEXT: ret void 146 Val<float, 202> Obj; 147 Obj.set(); 148 149 // CHECK-5: define {{.*}} void @_ZN3ValIfLi202EE3fooIdLi203EEEvT_ 150 // CHECK-5-NOT: } 151 // CHECK-5: store %class.Val* 152 // CHECK-5: store double 153 // CHECK-5: call void @__captured_stmt 154 // CHECK-5-NEXT: ret void 155 Obj.foo<double, 203>(1.0); 156 } 157 158 template <typename T> 159 void template_capture_lambda() { 160 T x, y; 161 [=, &y]() { 162 #pragma clang __debug captured 163 { 164 y += x; 165 } 166 }(); 167 } 168 169 void test_capture_lambda() { 170 // CHECK-6: define {{.*}} void @_ZZ23template_capture_lambdaIiEvvENKS_IiEUlvE_clEv 171 // CHECK-6-NOT: } 172 // CHECK-6: store i32* 173 // CHECK-6: store i32* 174 // CHECK-6: call void @__captured_stmt 175 // CHECK-6-NEXT: ret void 176 template_capture_lambda<int>(); 177 } 178