xref: /llvm-project/clang/test/SemaTemplate/concepts-lambda.cpp (revision f07e5162d0e67ec980e0ea282cf294f377407b10)
1 // RUN: %clang_cc1 -std=c++20 -verify %s
2 // RUN: %clang_cc1 -std=c++20 -verify %s -triple powerpc64-ibm-aix
3 
4 namespace GH57945 {
5   template<typename T>
6     concept c = true;
7 
8   template<typename>
9     auto f = []() requires c<void> {
10     };
11 
12   void g() {
13       f<int>();
14   };
15 }
16 
17 namespace GH57945_2 {
18   template<typename>
19     concept c = true;
20 
21   template<typename T>
22     auto f = [](auto... args) requires c<T>  {
23     };
24 
25   template <typename T>
26   auto f2 = [](auto... args)
27     requires (sizeof...(args) > 0)
28   {};
29 
30   void g() {
31       f<void>();
32       f2<void>(5.0);
33   }
34 }
35 
36 namespace GH57958 {
37   template<class> concept C = true;
38   template<int> constexpr bool v = [](C auto) { return true; }(0);
39   int _ = v<0>;
40 }
41 namespace GH57958_2 {
42   template<class> concept C = true;
43   template<int> constexpr bool v = [](C auto...) { return true; }(0);
44   int _ = v<0>;
45 }
46 
47 namespace GH57971 {
48   template<typename>
49     concept any = true;
50 
51   template<typename>
52     auto f = [](any auto) {
53     };
54 
55   using function_ptr = void(*)(int);
56   function_ptr ptr = f<void>;
57 }
58 
59 // GH58368: A lambda defined in a concept requires we store
60 // the concept as a part of the lambda context.
61 namespace LambdaInConcept {
62 using size_t = unsigned long;
63 
64 template<size_t...Ts>
65 struct IdxSeq{};
66 
67 template <class T, class... Ts>
68 concept NotLike = true;
69 
70 template <size_t, class... Ts>
71 struct AnyExcept {
72   template <NotLike<Ts...> T> operator T&() const;
73   template <NotLike<Ts...> T> operator T&&() const;
74 };
75 
76 template <class T>
77   concept ConstructibleWithN = (requires {
78                                 []<size_t I, size_t... Idxs>
79                                 (IdxSeq<I, Idxs...>)
80                                 requires requires { T{AnyExcept<I, T>{}}; }
81                                 { }
82                                 (IdxSeq<1,2,3>{});
83     });
84 
85 struct Foo {
86   int i;
87   double j;
88   char k;
89 };
90 
91 static_assert(ConstructibleWithN<Foo>);
92 
93 namespace GH56556 {
94 
95 template <typename It>
96 inline constexpr It declare ();
97 
98 template <typename It, template <typename> typename Template>
99 concept D = requires {
100 	{ [] <typename T1> (Template<T1> &) {}(declare<It &>()) };
101 };
102 
103 template <typename T>
104 struct B {};
105 
106 template <typename T>
107 struct Adapter;
108 
109 template <D<B> T>
110 struct Adapter<T> {};
111 
112 template struct Adapter<B<int>>;
113 
114 } // namespace GH56556
115 
116 namespace GH82849 {
117 
118 template <class T>
119 concept C = requires(T t) {
120   requires requires (T u) {
121     []<class V>(V) {
122       return requires(V v) {
123         [](V w) {}(v);
124       };
125     }(t);
126   };
127 };
128 
129 template <class From>
130 struct Widget;
131 
132 template <C F>
133 struct Widget<F> {
134   static F create(F from) {
135     return from;
136   }
137 };
138 
139 template <class>
140 bool foo() {
141   return C<int>;
142 }
143 
144 void bar() {
145   // https://github.com/llvm/llvm-project/issues/49570#issuecomment-1664966972
146   Widget<char>::create(0);
147 }
148 
149 } // namespace GH82849
150 
151 }
152 
153 // GH60642 reported an assert being hit, make sure we don't assert.
154 namespace GH60642 {
155 template<auto Q> concept C = requires { Q.template operator()<float>(); };
156 template<class> concept D = true;
157 static_assert(C<[]<D>{}>);  // ok
158 template<class> concept E = C<[]<D>{}>;
159 static_assert(E<int>);  // previously Asserted.
160 
161 // ensure we properly diagnose when "D" is false.
162 namespace DIsFalse {
163 template<auto Q> concept C = requires { Q.template operator()<float>(); };
164 template<class> concept D = false;
165 static_assert(C<[]<D>{}>);
166 // expected-error@-1{{static assertion failed}}
167 // expected-note@-2{{does not satisfy 'C'}}
168 // expected-note@-5{{because 'Q.template operator()<float>()' would be invalid: no matching member function for call to 'operator()'}}
169 template<class> concept E = C<[]<D>{}>;
170 static_assert(E<int>);
171 // expected-error@-1{{static assertion failed}}
172 // expected-note@-2{{because 'int' does not satisfy 'E'}}
173 // expected-note@-4{{does not satisfy 'C'}}
174 // expected-note@-11{{because 'Q.template operator()<float>()' would be invalid: no matching member function for call to 'operator()'}}
175 }
176 }
177 
178 namespace ReturnTypeRequirementInLambda {
179 template <typename T>
180 concept C1 = true;
181 
182 template <class T>
183 concept test = [] {
184   return requires(T t) {
185     { t } -> C1;
186   };
187 }();
188 
189 static_assert(test<int>);
190 
191 template <typename T>
192 concept C2 = true;
193 struct S1 {
194   int f1() { return 1; }
195 };
196 
197 void foo() {
198   auto make_caller = []<auto member> {
199     return [](S1 *ps) {
200       if constexpr (requires {
201                       { (ps->*member)() } -> C2;
202                     })
203         ;
204     };
205   };
206 
207   auto caller = make_caller.operator()<&S1::f1>();
208 }
209 } // namespace ReturnTypeRequirementInLambda
210 
211 namespace GH73418 {
212 void foo() {
213   int x;
214   [&x](auto) {
215     return [](auto y) {
216       return [](auto obj, auto... params)
217         requires requires {
218           sizeof...(params);
219           [](auto... pack) {
220             return sizeof...(pack);
221           }(params...);
222         }
223       { return false; }(y);
224     }(x);
225   }(x);
226 }
227 } // namespace GH73418
228 
229 namespace GH93821 {
230 
231 template <class>
232 concept C = true;
233 
234 template <class...>
235 concept D = []<C T = int>() { return true; }();
236 
237 D auto x = 0;
238 
239 } // namespace GH93821
240 
241 namespace dependent_param_concept {
242 template <typename... Ts> void sink(Ts...) {}
243 void dependent_param() {
244   auto L = [](auto... x) {
245     return [](decltype(x)... y) {
246       return [](int z)
247         requires requires { sink(y..., z); }
248       {};
249     };
250   };
251   L(0, 1)(1, 2)(1);
252 }
253 } // namespace dependent_param_concept
254 
255 namespace init_captures {
256 template <int N> struct V {};
257 
258 void sink(V<0>, V<1>, V<2>, V<3>, V<4>) {}
259 
260 void init_capture_pack() {
261   auto L = [](auto... z) {
262     return [=](auto... y) {
263       return [... w = z, y...](auto)
264         requires requires { sink(w..., y...); }
265       {};
266     };
267   };
268   L(V<0>{}, V<1>{}, V<2>{})(V<3>{}, V<4>{})(1);
269 }
270 
271 void dependent_capture_packs() {
272   auto L = [](auto... z) {
273     return [... w = z](auto... y) {
274       return [... c = w](auto)
275         requires requires { sink(c..., y...); }
276       {};
277     };
278   };
279   L(V<0>{}, V<1>{}, V<2>{})(V<3>{}, V<4>{})(1);
280 }
281 } // namespace init_captures
282 
283 namespace GH110721 {
284 
285 template <int N> void connect() {
286   int x = N, y = N;
287   [x, y = y]()
288     requires requires { x; }
289   {}();
290 }
291 
292 void foo() {
293   connect<42>();
294 }
295 
296 } // namespace GH110721
297 
298 namespace GH123441 {
299 
300 void test() {
301   auto L = [](auto... x) {
302     return [](decltype(x)... y)
303       requires true
304     {};
305   };
306   L(0, 1)(1, 2);
307 }
308 
309 }
310