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-LABEL: 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-LABEL: 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-LABEL: 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