1 | // RUN: %clang_cc1 -std=c++1z -verify -fsyntax-only -fblocks -emit-llvm-only %s |
2 | // RUN: %clang_cc1 -std=c++1z -verify -fsyntax-only -fblocks -fdelayed-template-parsing %s -DDELAYED_TEMPLATE_PARSING |
3 | // RUN: %clang_cc1 -std=c++1z -verify -fsyntax-only -fblocks -fms-extensions %s -DMS_EXTENSIONS |
4 | // RUN: %clang_cc1 -std=c++1z -verify -fsyntax-only -fblocks -fdelayed-template-parsing -fms-extensions %s -DMS_EXTENSIONS -DDELAYED_TEMPLATE_PARSING |
5 | |
6 | template <class, class> |
7 | constexpr bool is_same = false; |
8 | template <class T> |
9 | constexpr bool is_same<T, T> = true; |
10 | |
11 | namespace test_star_this { |
12 | namespace ns1 { |
13 | class A { |
14 | int x = 345; |
15 | auto foo() { |
16 | (void)[ *this, this ]{}; //expected-error{{'this' can appear only once}} |
17 | (void)[this] { ++x; }; |
18 | (void)[*this] { ++x; }; //expected-error{{read-only variable}} |
19 | (void)[*this]() mutable { ++x; }; |
20 | (void)[=] { return x; }; |
21 | (void)[&, this ] { return x; }; |
22 | (void)[ =, *this ] { return x; }; |
23 | (void)[&, *this ] { return x; }; |
24 | } |
25 | }; |
26 | } // namespace ns1 |
27 | |
28 | namespace ns2 { |
29 | class B { |
30 | B(const B &) = delete; //expected-note{{deleted here}} |
31 | int *x = (int *)456; |
32 | void foo() { |
33 | (void)[this] { return x; }; |
34 | (void)[*this] { return x; }; //expected-error{{call to deleted}} |
35 | } |
36 | }; |
37 | } // namespace ns2 |
38 | |
39 | namespace ns3 { |
40 | class B { |
41 | B(const B &) = delete; //expected-note2{{deleted here}} |
42 | |
43 | int *x = (int *)456; |
44 | |
45 | public: |
46 | template <class T = int> |
47 | void foo() { |
48 | (void)[this] { return x; }; |
49 | (void)[*this] { return x; }; //expected-error2{{call to deleted}} |
50 | } |
51 | |
52 | B() = default; |
53 | } b; |
54 | B *c = (b.foo(), nullptr); //expected-note{{in instantiation}} |
55 | } // namespace ns3 |
56 | |
57 | namespace ns4 { |
58 | template <class U> |
59 | class B { |
60 | B(const B &) = delete; //expected-note{{deleted here}} |
61 | double d = 3.14; |
62 | |
63 | public: |
64 | template <class T = int> |
65 | auto foo() { |
66 | const auto &L = [*this](auto a) mutable { //expected-error{{call to deleted}} |
67 | d += a; |
68 | return [this](auto b) { return d += b; }; |
69 | }; |
70 | } |
71 | |
72 | B() = default; |
73 | }; |
74 | void main() { |
75 | B<int *> b; |
76 | b.foo(); //expected-note{{in instantiation}} |
77 | } // end main |
78 | } // namespace ns4 |
79 | |
80 | namespace ns5 { |
81 | |
82 | struct X { |
83 | double d = 3.14; |
84 | X(const volatile X &); |
85 | void foo() { |
86 | } |
87 | |
88 | void foo() const { //expected-note{{const}} |
89 | |
90 | auto L = [*this]() mutable { |
91 | static_assert(is_same<decltype(this), X *>); |
92 | ++d; |
93 | auto M = [this] { |
94 | static_assert(is_same<decltype(this), X *>); |
95 | ++d; |
96 | auto N = [] { |
97 | static_assert(is_same<decltype(this), X *>); |
98 | }; |
99 | }; |
100 | }; |
101 | |
102 | auto L1 = [*this] { |
103 | static_assert(is_same<decltype(this), const X *>); |
104 | auto M = [this]() mutable { |
105 | static_assert(is_same<decltype(this), const X *>); |
106 | auto N = [] { |
107 | static_assert(is_same<decltype(this), const X *>); |
108 | }; |
109 | }; |
110 | auto M2 = [*this]() mutable { |
111 | static_assert(is_same<decltype(this), X *>); |
112 | auto N = [] { |
113 | static_assert(is_same<decltype(this), X *>); |
114 | }; |
115 | }; |
116 | }; |
117 | |
118 | auto GL1 = [*this](auto a) { |
119 | static_assert(is_same<decltype(this), const X *>); |
120 | auto M = [this](auto b) mutable { |
121 | static_assert(is_same<decltype(this), const X *>); |
122 | auto N = [](auto c) { |
123 | static_assert(is_same<decltype(this), const X *>); |
124 | }; |
125 | return N; |
126 | }; |
127 | |
128 | auto M2 = [*this](auto a) mutable { |
129 | static_assert(is_same<decltype(this), X *>); |
130 | auto N = [](auto b) { |
131 | static_assert(is_same<decltype(this), X *>); |
132 | }; |
133 | return N; |
134 | }; |
135 | return [=](auto a) mutable { M(a)(a); M2(a)(a); }; |
136 | }; |
137 | |
138 | GL1("abc") |
139 | ("abc"); |
140 | |
141 | auto L2 = [this]() mutable { |
142 | static_assert(is_same<decltype(this), const X *>); |
143 | ++d; //expected-error{{cannot assign}} |
144 | }; |
145 | auto GL = [*this](auto a) mutable { |
146 | static_assert(is_same<decltype(this), X *>); |
147 | ++d; |
148 | auto M = [this](auto b) { |
149 | static_assert(is_same<decltype(this), X *>); |
150 | ++d; |
151 | auto N = [](auto c) { |
152 | static_assert(is_same<decltype(this), X *>); |
153 | }; |
154 | N(3.14); |
155 | }; |
156 | M("abc"); |
157 | }; |
158 | GL(3.14); |
159 | } |
160 | void foo() volatile const { |
161 | auto L = [this]() { |
162 | static_assert(is_same<decltype(this), const volatile X *>); |
163 | auto M = [*this]() mutable { |
164 | static_assert(is_same<decltype(this), X *>); |
165 | auto N = [this] { |
166 | static_assert(is_same<decltype(this), X *>); |
167 | auto M = [] { |
168 | static_assert(is_same<decltype(this), X *>); |
169 | }; |
170 | }; |
171 | auto N2 = [*this] { |
172 | static_assert(is_same<decltype(this), const X *>); |
173 | }; |
174 | }; |
175 | auto M2 = [*this]() { |
176 | static_assert(is_same<decltype(this), const X *>); |
177 | auto N = [this] { |
178 | static_assert(is_same<decltype(this), const X *>); |
179 | }; |
180 | }; |
181 | }; |
182 | } |
183 | }; |
184 | |
185 | } // namespace ns5 |
186 | namespace ns6 { |
187 | struct X { |
188 | double d; |
189 | auto foo() const { |
190 | auto L = [*this]() mutable { |
191 | auto M = [=](auto a) { |
192 | auto N = [this] { |
193 | ++d; |
194 | static_assert(is_same<decltype(this), X *>); |
195 | auto O = [*this] { |
196 | static_assert(is_same<decltype(this), const X *>); |
197 | }; |
198 | }; |
199 | N(); |
200 | static_assert(is_same<decltype(this), X *>); |
201 | }; |
202 | return M; |
203 | }; |
204 | return L; |
205 | } |
206 | }; |
207 | |
208 | int main() { |
209 | auto L = X{}.foo(); |
210 | auto M = L(); |
211 | M(3.14); |
212 | } |
213 | } // namespace ns6 |
214 | namespace ns7 { |
215 | |
216 | struct X { |
217 | double d; |
218 | X(); |
219 | X(const X &); |
220 | X(X &) = delete; |
221 | auto foo() const { |
222 | //OK - the object used to initialize our capture is a const object and so prefers the non-deleted ctor. |
223 | const auto &&L = [*this]{}; |
224 | } |
225 | }; |
226 | int main() { |
227 | X x; |
228 | x.foo(); |
229 | } |
230 | } // namespace ns7 |
231 | |
232 | } // namespace test_star_this |
233 | |
234 | namespace PR32831 { |
235 | // https://bugs.llvm.org/show_bug.cgi?id=32831 |
236 | namespace ns1 { |
237 | template <typename Func> |
238 | void fun_template(Func func) { |
239 | (void)[&]() { |
240 | func(0); |
241 | }; |
242 | } |
243 | |
244 | class A { |
245 | void member_foo() { |
246 | (void)[this] { |
247 | (void)[this] { |
248 | fun_template( |
249 | [this](auto X) { |
250 | auto L = [this](auto Y) { member_foo(); }; |
251 | L(5); |
252 | }); |
253 | fun_template( |
254 | [this](auto) { member_foo(); }); |
255 | }; |
256 | }; |
257 | } |
258 | }; |
259 | } // namespace ns1 |
260 | |
261 | namespace ns2 { |
262 | |
263 | struct B { |
264 | int data = 0; |
265 | template <class F> |
266 | void mem2(F f) { |
267 | (void)[&](auto f) { |
268 | (void)[&] { f(this->data); }; |
269 | } |
270 | (f); |
271 | } |
272 | }; |
273 | |
274 | class A { |
275 | void member_foo() { |
276 | (void)[this] { |
277 | (void)[this] { |
278 | B{}.mem2( |
279 | [this](auto X) { |
280 | auto L = [this](auto Y) { member_foo(); }; |
281 | L(5); |
282 | }); |
283 | B{}.mem2( |
284 | [this](auto) { member_foo(); }); |
285 | }; |
286 | }; |
287 | } |
288 | int data = 0; |
289 | auto m2() { |
290 | return [this] { return [] () -> decltype(data){ return 0; }; }; |
291 | } |
292 | auto m3() { |
293 | return [] { return [] () -> decltype(data){ return 0; }; }; |
294 | } |
295 | }; |
296 | |
297 | } // namespace ns2 |
298 | |
299 | } // namespace PR32831 |
300 | |
301 | |