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