[clang] Implement lifetime analysis for lifetime_capture_by(X) (#115921)
[llvm-project.git] / clang / test / SemaCXX / fold_lambda_with_variadics.cpp
blob2257a4c2d975a8df4cc35057ffb03b979fa3aebd
1 // RUN: %clang_cc1 -fsyntax-only -std=c++20 -verify %s
3 namespace GH85667 {
5 template <class T>
6 struct identity {
7 using type = T;
8 };
10 template <class = void> void f() {
12 static_assert([]<class... Is>(Is... x) {
13 return ([I(x)] {
14 return I;
15 }() + ...);
16 }(1, 2) == 3);
18 []<class... Is>(Is... x) {
19 return ([](auto y = Is()) { return y + 1; }() + ...); // expected-error {{no matching function}} \
20 // expected-note {{couldn't infer template argument 'y:auto'}} \
21 // expected-note@-1 {{requested here}}
22 // expected-note@#instantiate-f {{requested here}}
23 }(1);
25 []<class... Is>() {
26 ([]<class = Is>(Is)
27 noexcept(bool(Is()))
28 {}(Is()),
29 ...);
30 }.template operator()<char, int, float>();
32 static_assert(__is_same(decltype([]<class... Is>() {
33 return ([]() -> decltype(Is()) { return {}; }(),
34 ...);
35 }.template operator()<int, char>()),
36 char));
38 []<class... Is>() {
39 return ([]<class... Ts>() -> decltype(Is()) { return Ts(); }() + ...);
40 // expected-error@-1 {{unexpanded parameter pack 'Ts'}}
41 }.template operator()<int, int>();
43 // https://github.com/llvm/llvm-project/issues/56852
44 []<class... Is>(Is...) {
45 ([] {
46 using T = identity<Is>::type;
47 }(), ...);
48 }(1, 2);
50 [](auto ...y) {
51 ([y] { }(), ...);
52 }();
54 [](auto ...x) {
55 ([&](auto ...y) {
56 ([x..., y] { }(), ...);
57 })(1);
58 }(2, 'b');
60 #if 0
61 // FIXME: https://github.com/llvm/llvm-project/issues/18873
62 [](auto ...x) { // #1
63 ([&](auto ...y) { // #2
64 ([x, y] { }(), ...); // #3
65 })(1, 'a'); // #4
66 }(2, 'b'); // #5
68 // We run into another crash for the above lambda because of the absence of a
69 // mechanism that rebuilds an unexpanded pack from an expanded Decls.
71 // Basically, this happens after `x` at #1 being expanded when the template
72 // arguments at #5, deduced as <int, char>, are ready. When we want to
73 // instantiate the body of #1, we first instantiate the CallExpr at #4, which
74 // boils down to the lambda's instantiation at #2. To that end, we have to
75 // instantiate the body of it, which turns out to be #3. #3 is a CXXFoldExpr,
76 // and we immediately have to hold off on the expansion because we don't have
77 // corresponding template arguments (arguments at #4 are not transformed yet) for it.
78 // Therefore, we want to rebuild a CXXFoldExpr, which requires another pattern
79 // transformation of the lambda inside #3. Then we need to find an unexpanded form
80 // of such a Decl of x at the time of transforming the capture, which is impossible
81 // because the instantiated form has been expanded at #1!
83 [](auto ...x) { // #outer
84 ([&](auto ...y) { // #inner
85 ([x, y] { }(), ...);
86 // expected-error@-1 {{parameter pack 'y' that has a different length (4 vs. 3) from outer parameter packs}}
87 // expected-note-re@#inner {{function template specialization {{.*}} requested here}}
88 // expected-note-re@#outer {{function template specialization {{.*}} requested here}}
89 // expected-note-re@#instantiate-f {{function template specialization {{.*}} requested here}}
90 })('a', 'b', 'c');
91 }(0, 1, 2, 3);
92 #endif
95 template void f(); // #instantiate-f
97 } // namespace GH85667
99 namespace GH99877 {
101 struct tuple {
102 int x[3];
105 template <class F> int apply(F f, tuple v) { return f(v.x[0], v.x[1], v.x[2]); }
107 int Cartesian1(auto x, auto y) {
108 return apply(
109 [&](auto... xs) {
110 return (apply([xs](auto... ys) { return (ys + ...); }, y) + ...);
115 int Cartesian2(auto x, auto y) {
116 return apply(
117 [&](auto... xs) {
118 return (apply([zs = xs](auto... ys) { return (ys + ...); }, y) + ...);
123 template <int...> struct Ints {};
124 template <int> struct Choose {
125 template <class> struct Templ;
127 template <int... x> int Cartesian3(auto y) {
128 return [&]<int... xs>(Ints<xs...>) {
129 // check in default template arguments for
130 // - type template parameters,
131 (void)(apply([]<class = decltype(xs)>(auto... ys) { return (ys + ...); },
132 y) +
133 ...);
134 // - template template parameters.
135 (void)(apply([]<template <class> class = Choose<xs>::template Templ>(
136 auto... ys) { return (ys + ...); },
137 y) +
138 ...);
139 // - non-type template parameters,
140 return (apply([]<int = xs>(auto... ys) { return (ys + ...); }, y) + ...);
141 }(Ints<x...>());
144 template <int... x> int Cartesian4(auto y) {
145 return [&]<int... xs>(Ints<xs...>) {
146 return (
147 apply([]<decltype(xs) xx = 1>(auto... ys) { return (ys + ...); }, y) +
148 ...);
149 }(Ints<x...>());
152 // FIXME: Attributes should preserve the ContainsUnexpandedPack flag.
153 #if 0
155 int Cartesian5(auto x, auto y) {
156 return apply(
157 [&](auto... xs) {
158 return (apply([](auto... ys) __attribute__((
159 diagnose_if(!__is_same(decltype(xs), int), "message",
160 "error"))) { return (ys + ...); },
161 y) +
162 ...);
167 #endif
169 void foo() {
170 auto x = tuple({1, 2, 3});
171 auto y = tuple({4, 5, 6});
172 Cartesian1(x, y);
173 Cartesian2(x, y);
174 Cartesian3<1, 2, 3>(y);
175 Cartesian4<1, 2, 3>(y);
176 #if 0
177 Cartesian5(x, y);
178 #endif
181 } // namespace GH99877
183 namespace GH101754 {
185 template <typename... Ts> struct Overloaded : Ts... {
186 using Ts::operator()...;
189 template <typename... Ts> Overloaded(Ts...) -> Overloaded<Ts...>;
191 template <class T, class U>
192 concept same_as = __is_same(T, U); // #same_as
194 template <typename... Ts> constexpr auto foo() {
195 return Overloaded{[](same_as<Ts> auto value) { return value; }...}; // #lambda
198 static_assert(foo<int, double>()(123) == 123);
199 static_assert(foo<int, double>()(2.718) == 2.718);
201 static_assert(foo<int, double>()('c'));
202 // expected-error@-1 {{no matching function}}
204 // expected-note@#lambda {{constraints not satisfied}}
205 // expected-note@#lambda {{'same_as<char, int>' evaluated to false}}
206 // expected-note@#same_as {{evaluated to false}}
208 // expected-note@#lambda {{constraints not satisfied}}
209 // expected-note@#lambda {{'same_as<char, double>' evaluated to false}}
210 // expected-note@#same_as {{evaluated to false}}
212 template <class T, class U, class V>
213 concept C = same_as<T, U> && same_as<U, V>; // #C
215 template <typename... Ts> constexpr auto bar() {
216 return ([]<class Up>() {
217 return Overloaded{[](C<Up, Ts> auto value) { // #bar
218 return value;
219 }...};
220 }.template operator()<Ts>(), ...);
222 static_assert(bar<int, float>()(3.14f)); // OK, bar() returns the last overload i.e. <float>.
224 static_assert(bar<int, float>()(123));
225 // expected-error@-1 {{no matching function}}
226 // expected-note@#bar {{constraints not satisfied}}
227 // expected-note@#bar {{'C<int, float, int>' evaluated to false}}
228 // expected-note@#C {{evaluated to false}}
230 // expected-note@#bar {{constraints not satisfied}}
231 // expected-note@#bar {{'C<int, float, float>' evaluated to false}}
232 // expected-note@#C {{evaluated to false}}
233 // expected-note@#same_as 2{{evaluated to false}}
235 } // namespace GH101754