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