1 | // RUN: %clang_cc1 -std=c++11 -triple %itanium_abi_triple -emit-llvm %s -o %t -debug-info-kind=limited |
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 | x = [=]() { return x + 1; }(); |
82 | |
83 | // CHECK-3: %[[Capture:struct\.anon[\.0-9]*]] = type { i32* } |
84 | |
85 | // CHECK-3-LABEL: define {{.*}}void @_Z5test3i |
86 | // CHECK-3: store i32* |
87 | // CHECK-3: call void @{{.*}}__captured_stmt |
88 | // CHECK-3: ret void |
89 | } |
90 | |
91 | void test4() { |
92 | #pragma clang __debug captured |
93 | { |
94 | Foo f; |
95 | f.x = 5; |
96 | } |
97 | // CHECK-4-LABEL: define {{.*}}void @_Z5test4v |
98 | // CHECK-4: call void @[[HelperName:[\."$_A-Za-z0-9]+]](%[[Capture:.*]]* |
99 | // CHECK-4: ret void |
100 | // |
101 | // CHECK-4: define internal {{.*}}void @[[HelperName]] |
102 | // CHECK-4: store i32 5, i32* |
103 | // CHECK-4: call {{.*}}FooD1Ev |
104 | } |
105 | |
106 | template <typename T, int id> |
107 | void touch(const T &) {} |
108 | |
109 | template <typename T, unsigned id> |
110 | void template_capture_var() { |
111 | T x; |
112 | #pragma clang __debug captured |
113 | { |
114 | touch<T, id>(x); |
115 | } |
116 | } |
117 | |
118 | template <typename T, int id> |
119 | class Val { |
120 | T v; |
121 | public: |
122 | void set() { |
123 | #pragma clang __debug captured |
124 | { |
125 | touch<T, id>(v); |
126 | } |
127 | } |
128 | |
129 | template <typename U, int id2> |
130 | void foo(U u) { |
131 | #pragma clang __debug captured |
132 | { |
133 | touch<U, id + id2>(u); |
134 | } |
135 | } |
136 | }; |
137 | |
138 | void test_capture_var() { |
139 | // CHECK-5: define {{.*}} void @_Z20template_capture_varIiLj201EEvv |
140 | // CHECK-5-NOT: } |
141 | // CHECK-5: store i32* |
142 | // CHECK-5: call void @__captured_stmt |
143 | // CHECK-5-NEXT: ret void |
144 | template_capture_var<int, 201>(); |
145 | |
146 | // CHECK-5: define {{.*}} void @_ZN3ValIfLi202EE3setEv |
147 | // CHECK-5-NOT: } |
148 | // CHECK-5: store %class.Val* |
149 | // CHECK-5: call void @__captured_stmt |
150 | // CHECK-5-NEXT: ret void |
151 | Val<float, 202> Obj; |
152 | Obj.set(); |
153 | |
154 | // CHECK-5: define {{.*}} void @_ZN3ValIfLi202EE3fooIdLi203EEEvT_ |
155 | // CHECK-5-NOT: } |
156 | // CHECK-5: store %class.Val* |
157 | // CHECK-5: store double |
158 | // CHECK-5: call void @__captured_stmt |
159 | // CHECK-5-NEXT: ret void |
160 | Obj.foo<double, 203>(1.0); |
161 | } |
162 | |
163 | template <typename T> |
164 | void template_capture_lambda() { |
165 | T x, y; |
166 | [=, &y]() { |
167 | #pragma clang __debug captured |
168 | { |
169 | y += x; |
170 | } |
171 | }(); |
172 | } |
173 | |
174 | void test_capture_lambda() { |
175 | // CHECK-6: define {{.*}} void @_ZZ23template_capture_lambdaIiEvvENKUlvE_clEv |
176 | // CHECK-6-NOT: } |
177 | // CHECK-6: store i32* |
178 | // CHECK-6: store i32* |
179 | // CHECK-6: call void @__captured_stmt |
180 | // CHECK-6-NEXT: ret void |
181 | template_capture_lambda<int>(); |
182 | } |
183 | |
184 | inline int test_captured_linkage() { |
185 | // CHECK-7: @_ZZ21test_captured_linkagevE1i = linkonce_odr {{(dso_local )?}}global i32 0 |
186 | int j; |
187 | #pragma clang __debug captured |
188 | { |
189 | static int i = 0; |
190 | j = ++i; |
191 | } |
192 | return j; |
193 | } |
194 | void call_test_captured_linkage() { |
195 | test_captured_linkage(); |
196 | } |
197 | |
198 | // CHECK-1-DAG: !DILocalVariable(name: "this", {{.*}}, flags: DIFlagArtificial | DIFlagObjectPointer) |
199 | // CHECK-1-DAG: !DILocalVariable(name: "__context", {{.*}}, flags: DIFlagArtificial) |
200 | // CHECK-2-DAG: !DILocalVariable(name: "this", {{.*}}, flags: DIFlagArtificial | DIFlagObjectPointer) |
201 | // CHECK-2-DAG: !DILocalVariable(name: "__context", {{.*}}, flags: DIFlagArtificial) |
202 | // CHECK-3-DAG: !DILocalVariable(name: "this", {{.*}}, flags: DIFlagArtificial | DIFlagObjectPointer) |
203 | // CHECK-3-DAG: !DILocalVariable(name: "__context", {{.*}}, flags: DIFlagArtificial) |
204 | // CHECK-4-DAG: !DILocalVariable(name: "this", {{.*}}, flags: DIFlagArtificial | DIFlagObjectPointer) |
205 | // CHECK-4-DAG: !DILocalVariable(name: "__context", {{.*}}, flags: DIFlagArtificial) |
206 | // CHECK-5-DAG: !DILocalVariable(name: "this", {{.*}}, flags: DIFlagArtificial | DIFlagObjectPointer) |
207 | // CHECK-5-DAG: !DILocalVariable(name: "__context", {{.*}}, flags: DIFlagArtificial) |
208 | // CHECK-6-DAG: !DILocalVariable(name: "this", {{.*}}, flags: DIFlagArtificial | DIFlagObjectPointer) |
209 | // CHECK-6-DAG: !DILocalVariable(name: "__context", {{.*}}, flags: DIFlagArtificial) |
210 | // CHECK-7-DAG: !DILocalVariable(name: "this", {{.*}}, flags: DIFlagArtificial | DIFlagObjectPointer) |
211 | // CHECK-7-DAG: !DILocalVariable(name: "__context", {{.*}}, flags: DIFlagArtificial) |
212 | |