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