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