xref: /llvm-project/clang/test/SemaCXX/lambda-capture-type-deduction.cpp (revision 154c7c0bf272adc67d3ffc541a01fe8025843fd2)
1 // RUN: %clang_cc1 -std=c++23 -verify -fsyntax-only %s
2 
3 template <typename T, typename U>
4 constexpr bool is_same = false;
5 
6 template <typename T>
7 constexpr bool is_same<T, T> = true;
8 
9 void f() {
10 
11   int y;
12 
13   static_assert(is_same<const int &,
14                         decltype([x = 1] -> decltype((x)) { return x; }())>);
15 
16   static_assert(is_same<int &,
17                         decltype([x = 1] mutable -> decltype((x)) { return x; }())>);
18 
19   static_assert(is_same<const int &,
20                         decltype([=] -> decltype((y)) { return y; }())>);
21 
22   static_assert(is_same<int &,
23                         decltype([=] mutable -> decltype((y)) { return y; }())>);
24 
25   static_assert(is_same<const int &,
26                         decltype([=] -> decltype((y)) { return y; }())>);
27 
28   static_assert(is_same<int &,
29                         decltype([=] mutable -> decltype((y)) { return y; }())>);
30 
31   auto ref = [&x = y](
32                  decltype([&](decltype(x)) { return 0; }) y) {
33     return x;
34   };
35 }
36 
37 void test_noexcept() {
38 
39   int y;
40 
41   static_assert(noexcept([x = 1] noexcept(is_same<const int &, decltype((x))>) {}()));
42   static_assert(noexcept([x = 1] mutable noexcept(is_same<int &, decltype((x))>) {}()));
43   static_assert(noexcept([y] noexcept(is_same<const int &, decltype((y))>) {}()));
44   static_assert(noexcept([y] mutable noexcept(is_same<int &, decltype((y))>) {}()));
45   static_assert(noexcept([=] noexcept(is_same<const int &, decltype((y))>) {}()));
46   static_assert(noexcept([=] mutable noexcept(is_same<int &, decltype((y))>) {}()));
47   static_assert(noexcept([&] noexcept(is_same<int &, decltype((y))>) {}()));
48   static_assert(noexcept([&] mutable noexcept(is_same<int &, decltype((y))>) {}()));
49 }
50 
51 template<typename T>
52 void test_requires() {
53 
54   int x;
55 
56   [x = 1]() requires is_same<const int &, decltype((x))> {}
57   ();
58   [x = 1]() mutable requires is_same<int &, decltype((x))> {}
59   ();
60   [x]() requires is_same<const int &, decltype((x))> {}
61   ();
62   [x]() mutable requires is_same<int &, decltype((x))> {}
63   ();
64   [=]() requires is_same<const int &, decltype((x))> {}
65   ();
66   [=]() mutable requires is_same<int &, decltype((x))> {}
67   ();
68   [&]() requires is_same<int &, decltype((x))> {}
69   ();
70   [&]() mutable requires is_same<int &, decltype((x))> {}
71   ();
72   [&x]() requires is_same<int &, decltype((x))> {}
73   ();
74   [&x]() mutable requires is_same<int &, decltype((x))> {}
75   ();
76 
77   [x = 1]() requires is_same<const int &, decltype((x))> {} ();
78   [x = 1]() mutable requires is_same<int &, decltype((x))> {} ();
79 }
80 
81 void use() {
82   test_requires<int>();
83 }
84 
85 void err() {
86   int y, z;
87   (void)[x = 1]<typename T>
88   requires(is_same<const int &, decltype((x))>) {};
89 
90   (void)[x = 1]<typename T = decltype((x))>{};
91 
92   (void)[=]<typename T = decltype((y))>{};
93 
94   (void)[z]<typename T = decltype((z))>{};
95 }
96 
97 void gnu_attributes() {
98   int y;
99   (void)[=]() __attribute__((diagnose_if(!is_same<decltype((y)), const int &>, "wrong type", "warning"))){}();
100   // expected-warning@-1 {{wrong type}} expected-note@-1{{'diagnose_if' attribute on 'operator()'}}
101   (void)[=]() __attribute__((diagnose_if(!is_same<decltype((y)), int &>, "wrong type", "warning"))){}();
102 
103   (void)[=]() __attribute__((diagnose_if(!is_same<decltype((y)), int &>, "wrong type", "warning"))) mutable {}();
104   (void)[=]() __attribute__((diagnose_if(!is_same<decltype((y)), const int &>, "wrong type", "warning"))) mutable {}();
105   // expected-warning@-1 {{wrong type}} expected-note@-1{{'diagnose_if' attribute on 'operator()'}}
106 
107 
108   (void)[x=1]() __attribute__((diagnose_if(!is_same<decltype((x)), const int &>, "wrong type", "warning"))){}();
109   // expected-warning@-1 {{wrong type}} expected-note@-1{{'diagnose_if' attribute on 'operator()'}}
110   (void)[x=1]() __attribute__((diagnose_if(!is_same<decltype((x)), int &>, "wrong type", "warning"))){}();
111 
112   (void)[x=1]() __attribute__((diagnose_if(!is_same<decltype((x)), int &>, "wrong type", "warning"))) mutable {}();
113   (void)[x=1]() __attribute__((diagnose_if(!is_same<decltype((x)), const int &>, "wrong type", "warning"))) mutable {}();
114   // expected-warning@-1 {{wrong type}} expected-note@-1{{'diagnose_if' attribute on 'operator()'}}
115 }
116 
117 void nested() {
118   int x, y, z;
119   (void)[&](
120       decltype([&](
121                    decltype([=](
122                                 decltype([&](
123                                              decltype([&](decltype(x)) {})) {})) {})) {})){};
124 
125   (void)[&](
126       decltype([&](
127                    decltype([&](
128                                 decltype([&](
129                                              decltype([&](decltype(y)) {})) {})) {})) {})){};
130 
131   (void)[=](
132       decltype([=](
133                    decltype([=](
134                                 decltype([=](
135                                              decltype([&]<decltype(z)> {})) {})) {})) {})){};
136 }
137 
138 template <typename T, typename U>
139 void dependent(U&& u) {
140   [&]() requires is_same<decltype(u), T> {}();
141 }
142 
143 template <typename T>
144 void dependent_init_capture(T x = 0) {
145   [ y = x + 1, x ]() mutable -> decltype(y + x)
146   requires(is_same<decltype((y)), int &>
147         && is_same<decltype((x)), int &>) {
148     return y;
149   }
150   ();
151   [ y = x + 1, x ]() -> decltype(y + x)
152   requires(is_same<decltype((y)), const int &>
153         && is_same<decltype((x)), const int &>) {
154     return y;
155   }
156   ();
157 }
158 
159 template <typename T, typename...>
160 struct extract_type {
161   using type = T;
162 };
163 
164 template <typename... T>
165 void dependent_variadic_capture(T... x) {
166   [... y = x, x... ](auto...) mutable -> typename extract_type<decltype(y)...>::type requires((is_same<decltype((y)), int &> && ...) && (is_same<decltype((x)), int &> && ...)) {
167     return 0;
168   }
169   (x...);
170   [... y = x, x... ](auto...) -> typename extract_type<decltype(y)...>::type requires((is_same<decltype((y)), const int &> && ...) && (is_same<decltype((x)), const int &> && ...)) {
171     return 0;
172   }
173   (x...);
174 }
175 
176 void test_dependent() {
177   int v   = 0;
178   int & r = v;
179   const int & cr = v;
180   dependent<int&>(v);
181   dependent<int&>(r);
182   dependent<const int&>(cr);
183   dependent_init_capture(0);
184   dependent_variadic_capture(1, 2, 3, 4);
185 }
186 
187 void check_params() {
188   int i = 0;
189   int &j = i;
190   (void)[=](decltype((j)) jp, decltype((i)) ip) {
191     static_assert(is_same<const int&, decltype((j))>);
192     static_assert(is_same<const int &, decltype((i))>);
193     static_assert(is_same<int &, decltype((jp))>);
194     static_assert(is_same<int &, decltype((ip))>);
195   };
196 
197   (void)[=](decltype((j)) jp, decltype((i)) ip) mutable {
198     static_assert(is_same<int &, decltype((j))>);
199     static_assert(is_same<int &, decltype((i))>);
200     static_assert(is_same<int &, decltype((jp))>);
201     static_assert(is_same<int &, decltype((ip))>);
202     static_assert(is_same<int &, decltype(jp)>);
203     static_assert(is_same<int &, decltype(ip)>);
204   };
205 
206   (void)[a = 0](decltype((a)) ap) mutable {
207     static_assert(is_same<int &, decltype((a))>);
208     static_assert(is_same<int, decltype(a)>);
209     static_assert(is_same<int &, decltype(ap)>);
210   };
211   (void)[a = 0](decltype((a)) ap) {
212     static_assert(is_same<const int &, decltype((a))>);
213     static_assert(is_same<int, decltype(a)>);
214     static_assert(is_same<int&, decltype((ap))>);
215   };
216 }
217 
218 template <typename T>
219 void check_params_tpl() {
220   T i = 0;
221   T &j = i;
222   (void)[=](decltype((j)) jp, decltype((i)) ip) {
223     static_assert(is_same<const int&, decltype((j))>);
224     static_assert(is_same<const int &, decltype((i))>);
225     static_assert(is_same<const int &, decltype((jp))>);
226     static_assert(is_same<const int &, decltype((ip))>);
227   };
228 
229   (void)[=](decltype((j)) jp, decltype((i)) ip) mutable {
230     static_assert(is_same<int &, decltype((j))>);
231     static_assert(is_same<int &, decltype((i))>);
232     static_assert(is_same<int &, decltype((jp))>);
233     static_assert(is_same<int &, decltype((ip))>);
234     static_assert(is_same<int &, decltype(jp)>);
235     static_assert(is_same<int &, decltype(ip)>);
236   };
237 
238   (void)[a = 0](decltype((a)) ap) mutable {
239     static_assert(is_same<int &, decltype((a))>);
240     static_assert(is_same<int, decltype(a)>);
241     static_assert(is_same<int &, decltype(ap)>);
242   };
243   (void)[a = 0](decltype((a)) ap) {
244     static_assert(is_same<const int &, decltype((a))>);
245     static_assert(is_same<int, decltype(a)>);
246     static_assert(is_same<int&, decltype((ap))>);
247   };
248 }
249 
250 namespace GH61267 {
251 template <typename> concept C = true;
252 
253 template<typename>
254 void f(int) {
255   int i;
256   [i]<C P>(P) {}(0);
257   i = 4;
258 }
259 
260 void test() { f<int>(0);  }
261 
262 }
263 
264 namespace GH65067 {
265 
266 template <typename> class a {
267 public:
268   template <typename b> void c(b f) { d<int>(f)(0); }
269   template <typename, typename b> auto d(b f) {
270     return [f = f](auto arg) -> a<decltype(f(arg))> { return {}; };
271   }
272 };
273 a<void> e;
274 auto fn1() {
275   e.c([](int) {});
276 }
277 
278 }
279 
280 namespace GH63675 {
281 
282 template <class _Tp> _Tp __declval();
283 struct __get_tag {
284   template <class _Tag> void operator()(_Tag);
285 };
286 template <class _ImplFn> struct __basic_sender {
287   using __tag_t = decltype(__declval<_ImplFn>()(__declval<__get_tag>()));
288   _ImplFn __impl_;
289 };
290 auto __make_basic_sender = []<class... _Children>(
291                                _Children... __children) {
292   return __basic_sender{[... __children = __children]<class _Fun>(
293                      _Fun __fun) -> decltype(__fun(__children...)) {}};
294 };
295 void __trans_tmp_1() {
296   __make_basic_sender(__trans_tmp_1);
297 }
298 
299 }
300 
301 namespace GH115931 {
302 
303 struct Range {};
304 
305 template <Range>
306 struct LengthPercentage {};
307 
308 void reflectSum() {
309   Range resultR;
310   [&] (auto) -> LengthPercentage<resultR> {
311     return {};
312   }(0);
313 }
314 
315 } // namespace GH115931
316 
317 namespace GH47400 {
318 
319 struct Foo {};
320 
321 template <int, Foo> struct Arr {};
322 
323 template <int> struct S {};
324 
325 constexpr void foo() {
326   constexpr Foo f;
327   [&]<int is>() {
328     [&](Arr<is, f>) {}({}); // f constitutes an ODR-use
329   }.template operator()<42>();
330 
331   constexpr int C = 1;
332   [] {
333     [](S<C>) { }({}); // ... while C doesn't
334   }();
335 }
336 
337 } // namespace GH47400
338 
339 namespace GH84961 {
340 
341 template <typename T> void g(const T &t) {}
342 
343 template <typename T> void f(const T &t) {
344   [t] { g(t); }();
345 }
346 
347 void h() {
348   f(h);
349 }
350 
351 } // namespace GH84961
352