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
10 struct Foo {
11 int x;
12 float y;
~FooFoo13 ~Foo() {}
14 };
15
16 struct TestClass {
17 int x;
18
TestClassTestClass19 TestClass() : x(0) {};
MemberFuncTestClass20 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
test1()31 void 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
test2(int x)55 void 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
test3(int x)76 void 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
test4()90 void 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
105 template <typename T, int id>
touch(const T &)106 void touch(const T &) {}
107
108 template <typename T, unsigned id>
template_capture_var()109 void template_capture_var() {
110 T x;
111 #pragma clang __debug captured
112 {
113 touch<T, id>(x);
114 }
115 }
116
117 template <typename T, int id>
118 class Val {
119 T v;
120 public:
set()121 void set() {
122 #pragma clang __debug captured
123 {
124 touch<T, id>(v);
125 }
126 }
127
128 template <typename U, int id2>
foo(U u)129 void foo(U u) {
130 #pragma clang __debug captured
131 {
132 touch<U, id + id2>(u);
133 }
134 }
135 };
136
test_capture_var()137 void 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
162 template <typename T>
template_capture_lambda()163 void template_capture_lambda() {
164 T x, y;
165 [=, &y]() {
166 #pragma clang __debug captured
167 {
168 y += x;
169 }
170 }();
171 }
172
test_capture_lambda()173 void 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
test_captured_linkage()183 inline 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 }
call_test_captured_linkage()193 void call_test_captured_linkage() {
194 test_captured_linkage();
195 }
196