brintos

brintos / llvm-project-archived public Read only

0
0
Text · 8.9 KiB · 980d71b Raw
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