298 lines · cpp
1// RUN: %clang_cc1 -fsyntax-only -std=c++20 -verify %s2 3namespace GH85667 {4 5template <class T>6struct identity {7 using type = T;8};9 10template <class> using ElementType = int;11 12template <class = void> void f() {13 14 static_assert([]<class... Is>(Is... x) {15 return ([I(x)] {16 return I;17 }() + ...);18 }(1, 2) == 3);19 20 []<class... Is>(Is... x) {21 return ([](auto y = Is()) { return y + 1; }() + ...); // expected-error {{no matching function}} \22 // expected-note {{couldn't infer template argument 'y:auto'}} \23 // expected-note@-1 {{requested here}}24 // expected-note@#instantiate-f {{requested here}}25 }(1);26 27 []<class... Is>() {28 ([]<class = Is>(Is)29 noexcept(bool(Is()))30 {}(Is()),31 ...);32 }.template operator()<char, int, float>();33 34 static_assert(__is_same(decltype([]<class... Is>() {35 return ([]() -> decltype(Is()) { return {}; }(),36 ...);37 }.template operator()<int, char>()),38 char));39 40 []<class... Is>() {41 return ([]<class... Ts>() -> decltype(Is()) { return Ts(); }() + ...);42 // expected-error@-1 {{unexpanded parameter pack 'Ts'}}43 }.template operator()<int, int>();44 45 // https://github.com/llvm/llvm-project/issues/5685246 []<class... Is>(Is...) {47 ([] {48 using T = identity<Is>::type;49 }(), ...);50 }(1, 2);51 52 []<class... Is>(Is...) {53 ([] { using T = ElementType<Is>; }(), ...);54 }(1);55 56 [](auto ...y) {57 ([y] { }(), ...);58 }();59 60 [](auto ...x) {61 ([&](auto ...y) {62 ([x..., y] { }(), ...);63 })(1);64 }(2, 'b');65 66#if 067 // FIXME: https://github.com/llvm/llvm-project/issues/1887368 [](auto ...x) { // #169 ([&](auto ...y) { // #270 ([x, y] { }(), ...); // #371 })(1, 'a'); // #472 }(2, 'b'); // #573 74 // We run into another crash for the above lambda because of the absence of a75 // mechanism that rebuilds an unexpanded pack from an expanded Decls.76 //77 // Basically, this happens after `x` at #1 being expanded when the template78 // arguments at #5, deduced as <int, char>, are ready. When we want to79 // instantiate the body of #1, we first instantiate the CallExpr at #4, which80 // boils down to the lambda's instantiation at #2. To that end, we have to81 // instantiate the body of it, which turns out to be #3. #3 is a CXXFoldExpr,82 // and we immediately have to hold off on the expansion because we don't have83 // corresponding template arguments (arguments at #4 are not transformed yet) for it.84 // Therefore, we want to rebuild a CXXFoldExpr, which requires another pattern85 // transformation of the lambda inside #3. Then we need to find an unexpanded form86 // of such a Decl of x at the time of transforming the capture, which is impossible87 // because the instantiated form has been expanded at #1!88 89 [](auto ...x) { // #outer90 ([&](auto ...y) { // #inner91 ([x, y] { }(), ...);92 // expected-error@-1 {{parameter pack 'y' that has a different length (4 vs. 3) from outer parameter packs}}93 // expected-note-re@#inner {{function template specialization {{.*}} requested here}}94 // expected-note-re@#outer {{function template specialization {{.*}} requested here}}95 // expected-note-re@#instantiate-f {{function template specialization {{.*}} requested here}}96 })('a', 'b', 'c');97 }(0, 1, 2, 3);98#endif99}100 101template void f(); // #instantiate-f102 103} // namespace GH85667104 105namespace GH99877 {106 107struct tuple {108 int x[3];109};110 111template <class F> int apply(F f, tuple v) { return f(v.x[0], v.x[1], v.x[2]); }112 113int Cartesian1(auto x, auto y) {114 return apply(115 [&](auto... xs) {116 return (apply([xs](auto... ys) { return (ys + ...); }, y) + ...);117 },118 x);119}120 121int Cartesian2(auto x, auto y) {122 return apply(123 [&](auto... xs) {124 return (apply([zs = xs](auto... ys) { return (ys + ...); }, y) + ...);125 },126 x);127}128 129template <int...> struct Ints {};130template <int> struct Choose {131 template <class> struct Templ;132};133template <int... x> int Cartesian3(auto y) {134 return [&]<int... xs>(Ints<xs...>) {135 // check in default template arguments for136 // - type template parameters,137 (void)(apply([]<class = decltype(xs)>(auto... ys) { return (ys + ...); },138 y) +139 ...);140 // - template template parameters.141 (void)(apply([]<template <class> class = Choose<xs>::template Templ>(142 auto... ys) { return (ys + ...); },143 y) +144 ...);145 // - non-type template parameters,146 return (apply([]<int = xs>(auto... ys) { return (ys + ...); }, y) + ...);147 }(Ints<x...>());148}149 150template <int... x> int Cartesian4(auto y) {151 return [&]<int... xs>(Ints<xs...>) {152 return (153 apply([]<decltype(xs) xx = 1>(auto... ys) { return (ys + ...); }, y) +154 ...);155 }(Ints<x...>());156}157 158// FIXME: Attributes should preserve the ContainsUnexpandedPack flag.159#if 0160 161int Cartesian5(auto x, auto y) {162 return apply(163 [&](auto... xs) {164 return (apply([](auto... ys) __attribute__((165 diagnose_if(!__is_same(decltype(xs), int), "message",166 "error"))) { return (ys + ...); },167 y) +168 ...);169 },170 x);171}172 173#endif174 175void foo() {176 auto x = tuple({1, 2, 3});177 auto y = tuple({4, 5, 6});178 Cartesian1(x, y);179 Cartesian2(x, y);180 Cartesian3<1, 2, 3>(y);181 Cartesian4<1, 2, 3>(y);182#if 0183 Cartesian5(x, y);184#endif185}186 187} // namespace GH99877188 189namespace GH101754 {190 191template <typename... Ts> struct Overloaded : Ts... {192 using Ts::operator()...;193};194 195template <typename... Ts> Overloaded(Ts...) -> Overloaded<Ts...>;196 197template <class T, class U>198concept same_as = __is_same(T, U); // #same_as199 200template <typename... Ts> constexpr auto foo() {201 return Overloaded{[](same_as<Ts> auto value) { return value; }...}; // #lambda202}203 204static_assert(foo<int, double>()(123) == 123);205static_assert(foo<int, double>()(2.718) == 2.718);206 207static_assert(foo<int, double>()('c'));208// expected-error@-1 {{no matching function}}209 210// expected-note@#lambda {{constraints not satisfied}}211// expected-note@#lambda {{'same_as<char, int>' evaluated to false}}212// expected-note@#same_as {{evaluated to false}}213 214// expected-note@#lambda {{constraints not satisfied}}215// expected-note@#lambda {{'same_as<char, double>' evaluated to false}}216// expected-note@#same_as {{evaluated to false}}217 218template <class T, class U, class V>219concept C = same_as<T, U> && same_as<U, V>; // #C220 221template <typename... Ts> constexpr auto bar() {222 return ([]<class Up>() {223 return Overloaded{[](C<Up, Ts> auto value) { // #bar224 return value;225 }...};226 }.template operator()<Ts>(), ...);227}228static_assert(bar<int, float>()(3.14f)); // OK, bar() returns the last overload i.e. <float>.229 230static_assert(bar<int, float>()(123));231// expected-error@-1 {{no matching function}}232// expected-note@#bar {{constraints not satisfied}}233// expected-note@#bar {{'C<int, float, int>' evaluated to false}}234// expected-note@#C {{evaluated to false}}235 236// expected-note@#bar {{constraints not satisfied}}237// expected-note@#bar {{'C<int, float, float>' evaluated to false}}238// expected-note@#C {{evaluated to false}}239// expected-note@#same_as 2{{evaluated to false}}240 241template <class T, auto U>242concept same_as_v = __is_same(T, decltype(U)); // #same_as_v243 244template <auto... Vs> constexpr auto baz() {245 return Overloaded{[](same_as_v<Vs> auto value) { return value; }...}; // #baz246}247 248static_assert(baz<1, 1.>()(123) == 123);249static_assert(baz<1, 1.>()(2.718) == 2.718);250 251static_assert(baz<1, 1.>()('c'));252// expected-error@-1 {{no matching function}}253 254// expected-note@#baz {{constraints not satisfied}}255// expected-note@#baz {{'same_as_v<char, 1>' evaluated to false}}256// expected-note@#same_as_v {{evaluated to false}}257 258// expected-note@#baz {{constraints not satisfied}}259// expected-note@#baz {{'same_as_v<char, 1.>' evaluated to false}}260// expected-note@#same_as_v {{evaluated to false}}261 262template <auto... Ts> constexpr auto bazz() {263 return Overloaded{[](same_as_v<Ts> auto value) { return Ts; }...}; // #bazz264}265 266static_assert(bazz<1, 2>()(1));267// expected-error@-1 {{is ambiguous}}268// expected-note@#bazz 2{{candidate function [with value:auto = int]}}269 270template <class T> concept C2 = sizeof(T) >= sizeof(int);271template <class... Ts> static constexpr auto trailing() {272 return Overloaded{[](auto) requires (C2<Ts> && C2<int>) { return 0; }...}; // #trailing273}274static_assert(trailing<int, long>()(0));275// expected-error@-1 {{is ambiguous}}276// expected-note@#trailing 2{{candidate function [with auto:1 = int]}}277 278 279} // namespace GH101754280 281namespace GH131798 {282 template <class T0>283 struct tuple { T0 elem0; };284 285 template <class, class>286 concept C = true;287 288 template <int>289 struct Foo {};290 291 template <int... Vals>292 constexpr tuple fs{[] (C<Foo<Vals>> auto) {}...};293 294 int main() {295 fs<0>.elem0(1);296 }297} // namspace GH131798298