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