xref: /llvm-project/clang/test/SemaTemplate/generic-lambda.cpp (revision f4c781174b4b8fd958d9074c25eb06b6e276cb1c)
1af10d6f3SMatheus Izvekov // RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify %s
2af10d6f3SMatheus Izvekov 
3af10d6f3SMatheus Izvekov // expected-no-diagnostics
4af10d6f3SMatheus Izvekov 
5af10d6f3SMatheus Izvekov template <class T, class U> constexpr bool is_same_v = false;
6af10d6f3SMatheus Izvekov template <class T> constexpr bool is_same_v<T, T> = true;
7af10d6f3SMatheus Izvekov template <class T, class U>
8af10d6f3SMatheus Izvekov concept is_same = is_same_v<T, U>;
9af10d6f3SMatheus Izvekov 
10af10d6f3SMatheus Izvekov template <class T> struct X {};
11af10d6f3SMatheus Izvekov template <class T, class U>
12af10d6f3SMatheus Izvekov concept C1 = is_same<T, X<U>>;
13af10d6f3SMatheus Izvekov 
t1()14af10d6f3SMatheus Izvekov template <class T1> X<X<X<T1>>> t1() {
15af10d6f3SMatheus Izvekov   return []<class T2>(T2) -> X<X<T2>> {
16af10d6f3SMatheus Izvekov     struct S {
17af10d6f3SMatheus Izvekov       static X<X<T2>> f() {
18af10d6f3SMatheus Izvekov         return []<class T3>(T3) -> X<T3> {
19af10d6f3SMatheus Izvekov           static_assert(is_same<T2, X<T1>>);
20af10d6f3SMatheus Izvekov           static_assert(is_same<T3, X<T2>>);
21af10d6f3SMatheus Izvekov           return X<T3>();
22af10d6f3SMatheus Izvekov         }(X<T2>());
23af10d6f3SMatheus Izvekov       }
24af10d6f3SMatheus Izvekov     };
25af10d6f3SMatheus Izvekov     return S::f();
26af10d6f3SMatheus Izvekov   }(X<T1>());
27af10d6f3SMatheus Izvekov };
28af10d6f3SMatheus Izvekov template X<X<X<int>>> t1<int>();
29af10d6f3SMatheus Izvekov 
30af10d6f3SMatheus Izvekov #if 0 // FIXME: crashes
31af10d6f3SMatheus Izvekov template<class T1> auto t2() {
32af10d6f3SMatheus Izvekov   return []<class T2>(T2) {
33af10d6f3SMatheus Izvekov     struct S {
34af10d6f3SMatheus Izvekov       static auto f() {
35af10d6f3SMatheus Izvekov         return []<class T3>(T3) {
36af10d6f3SMatheus Izvekov           static_assert(is_same<T2, X<T1>>);
37af10d6f3SMatheus Izvekov           static_assert(is_same<T3, X<T2>>);
38af10d6f3SMatheus Izvekov           return X<T3>();
39af10d6f3SMatheus Izvekov         }(X<T2>());
40af10d6f3SMatheus Izvekov       }
41af10d6f3SMatheus Izvekov     };
42af10d6f3SMatheus Izvekov     return S::f();
43af10d6f3SMatheus Izvekov   }(X<T1>());
44af10d6f3SMatheus Izvekov };
45af10d6f3SMatheus Izvekov template auto t2<int>();
46af10d6f3SMatheus Izvekov static_assert(is_same<decltype(t2<int>()), X<X<X<int>>>>);
47af10d6f3SMatheus Izvekov 
48af10d6f3SMatheus Izvekov template<class T1> C1<X<X<T1>>> auto t3() {
49af10d6f3SMatheus Izvekov   return []<C1<T1> T2>(T2) -> C1<X<T2>> auto {
50af10d6f3SMatheus Izvekov     struct S {
51af10d6f3SMatheus Izvekov       static auto f() {
52af10d6f3SMatheus Izvekov         return []<C1<T2> T3>(T3) -> C1<T3> auto {
53af10d6f3SMatheus Izvekov           return X<T3>();
54af10d6f3SMatheus Izvekov         }(X<T2>());
55af10d6f3SMatheus Izvekov       }
56af10d6f3SMatheus Izvekov     };
57af10d6f3SMatheus Izvekov     return S::f();
58af10d6f3SMatheus Izvekov   }(X<T1>());
59af10d6f3SMatheus Izvekov };
60af10d6f3SMatheus Izvekov template C1<X<X<int>>> auto t3<int>();
61af10d6f3SMatheus Izvekov static_assert(is_same<decltype(t3<int>()), X<X<X<int>>>>);
62af10d6f3SMatheus Izvekov #endif
63*f4c78117SYounan Zhang 
64*f4c78117SYounan Zhang namespace GH95735 {
65*f4c78117SYounan Zhang 
g(int fn)66*f4c78117SYounan Zhang int g(int fn) {
67*f4c78117SYounan Zhang   return [f = fn](auto tpl) noexcept(noexcept(f)) { return f; }(0);
68*f4c78117SYounan Zhang }
69*f4c78117SYounan Zhang 
foo(auto...fn)70*f4c78117SYounan Zhang int foo(auto... fn) {
71*f4c78117SYounan Zhang   // FIXME: This one hits the assertion "if the exception specification is dependent,
72*f4c78117SYounan Zhang   // then the noexcept expression should be value-dependent" in the constructor of
73*f4c78117SYounan Zhang   // FunctionProtoType.
74*f4c78117SYounan Zhang   // One possible solution is to update Sema::canThrow() to consider expressions
75*f4c78117SYounan Zhang   // (e.g. DeclRefExpr/FunctionParmPackExpr) involving unexpanded parameters as Dependent.
76*f4c78117SYounan Zhang   // This would effectively add an extra value-dependent flag to the noexcept expression.
77*f4c78117SYounan Zhang   // However, I'm afraid that would also cause ABI breakage.
78*f4c78117SYounan Zhang   // [...f = fn](auto tpl) noexcept(noexcept(f)) { return 0; }(0);
79*f4c78117SYounan Zhang   [...f = fn](auto tpl) noexcept(noexcept(g(fn...))) { return 0; }(0);
80*f4c78117SYounan Zhang   return [...f = fn](auto tpl) noexcept(noexcept(g(f...))) { return 0; }(0);
81*f4c78117SYounan Zhang }
82*f4c78117SYounan Zhang 
83*f4c78117SYounan Zhang int v = foo(42);
84*f4c78117SYounan Zhang 
85*f4c78117SYounan Zhang } // namespace GH95735
86