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;
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       static double inner = x;
25       (void)inner;
26       f.y = x;
27     }
28   }
29 };
30 
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 
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 
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 
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>
106 void touch(const T &) {}
107 
108 template <typename T, unsigned id>
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:
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 
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>
163 void template_capture_lambda() {
164   T x, y;
165   [=, &y]() {
166     #pragma clang __debug captured
167     {
168       y += x;
169     }
170   }();
171 }
172 
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 
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 }
193 void call_test_captured_linkage() {
194   test_captured_linkage();
195 }
196