xref: /llvm-project/clang/test/CXX/temp/temp.deduct/p9.cpp (revision 3eeed79946124a8f67a89bb950a1e510369dcdf9)
1629170feSIlya Biryukov // RUN:  %clang_cc1 -std=c++20 -verify %s
2629170feSIlya Biryukov // [temp.deduct.p9]
3629170feSIlya Biryukov // A lambda-expression appearing in a function type or a template parameter is
4629170feSIlya Biryukov // not considered part of the immediate context for the purposes of template
5629170feSIlya Biryukov // argument deduction.
6629170feSIlya Biryukov // [Note: The intent is to avoid requiring implementations to deal with
7629170feSIlya Biryukov // substitution failure involving arbitrary statements.]
8629170feSIlya Biryukov template <class T>
__anonc5a543d20102() 9629170feSIlya Biryukov auto f(T) -> decltype([]() { T::invalid; } ());
10629170feSIlya Biryukov void f(...);
test_f()11629170feSIlya Biryukov void test_f() {
12629170feSIlya Biryukov   f(0); // expected-error@-3 {{type 'int' cannot be used prior to '::'}}
13629170feSIlya Biryukov         // expected-note@-1 {{while substituting deduced template arguments}}
14629170feSIlya Biryukov         // expected-note@-5 {{while substituting into a lambda expression here}}
15629170feSIlya Biryukov }
16629170feSIlya Biryukov 
17629170feSIlya Biryukov template <class T, unsigned = sizeof([]() { T::invalid; })>
18629170feSIlya Biryukov void g(T);
19629170feSIlya Biryukov void g(...);
test_g()20629170feSIlya Biryukov void test_g() {
21629170feSIlya Biryukov   g(0); // expected-error@-4 {{type 'int' cannot be used prior to '::'}}
22629170feSIlya Biryukov         // expected-note@-4 {{in instantiation of default argument}}
23629170feSIlya Biryukov         // expected-note@-2 {{while substituting deduced template arguments}}
24629170feSIlya Biryukov         // expected-note@-7 {{while substituting into a lambda expression here}}
25629170feSIlya Biryukov }
26629170feSIlya Biryukov 
27629170feSIlya Biryukov template <class T>
__anonc5a543d20202() 28629170feSIlya Biryukov auto h(T) -> decltype([x = T::invalid]() { });
29629170feSIlya Biryukov void h(...);
test_h()30629170feSIlya Biryukov void test_h() {
31*3eeed799SYounan Zhang   h(0);
32629170feSIlya Biryukov }
33629170feSIlya Biryukov 
34629170feSIlya Biryukov template <class T>
__anonc5a543d20302() 35629170feSIlya Biryukov auto i(T) -> decltype([]() -> typename T::invalid { });
36629170feSIlya Biryukov void i(...);
test_i()37629170feSIlya Biryukov void test_i() {
38*3eeed799SYounan Zhang   i(0);
39629170feSIlya Biryukov }
40629170feSIlya Biryukov 
41629170feSIlya Biryukov 
42629170feSIlya Biryukov // In this example, the lambda itself is not part of an immediate context, but
43629170feSIlya Biryukov // substitution to the lambda expression succeeds, producing dependent
44629170feSIlya Biryukov // `decltype(x.invalid)`. The call to the lambda, however, is in the immediate context
45629170feSIlya Biryukov // and it produces a SFINAE failure. Hence, we pick the second overload
46629170feSIlya Biryukov // and don't produce any errors.
47629170feSIlya Biryukov template <class T>
48629170feSIlya Biryukov auto j(T t) -> decltype([](auto x) -> decltype(x.invalid) { } (t));   // #1
49629170feSIlya Biryukov void j(...);                                                          // #2
test_j()50629170feSIlya Biryukov void test_j() {
51629170feSIlya Biryukov   j(0); // deduction fails on #1, calls #2.
52629170feSIlya Biryukov }
53