// RUN: %clang_cc1 -std=c++2a -verify %s template constexpr bool is_same_v = false; template constexpr bool is_same_v = true; template struct type_list; namespace unconstrained { decltype(auto) f1(auto x) { return x; } static_assert(is_same_v); static_assert(is_same_v); decltype(auto) f2(auto &x) { return x; } // expected-note@-1{{candidate function [with x:auto = int] not viable: expects an lvalue for 1st argument}} // expected-note@-2{{candidate function [with x:auto = char] not viable: expects an lvalue for 1st argument}} static_assert(is_same_v); // expected-error{{no matching}} static_assert(is_same_v); // expected-error{{no matching}} decltype(auto) f3(const auto &x) { return x; } static_assert(is_same_v); static_assert(is_same_v); decltype(auto) f4(auto (*x)(auto y)) { return x; } // expected-error{{'auto' not allowed in function prototype}} decltype(auto) f5(void (*x)(decltype(auto) y)) { return x; } // expected-error{{'decltype(auto)' not allowed in function prototype}} int return_int(); void return_void(); int foo(int); decltype(auto) f6(auto (*x)()) { return x; } // expected-note@-1{{candidate template ignored: failed template argument deduction}} static_assert(is_same_v); static_assert(is_same_v); using f6c1 = decltype(f6(foo)); // expected-error{{no matching}} decltype(auto) f7(auto (*x)() -> int) { return x; } // expected-note@-1{{candidate function not viable: no known conversion from 'void ()' to 'auto (*)() -> int' for 1st argument}} // expected-note@-2{{candidate function not viable: no known conversion from 'int (int)' to 'auto (*)() -> int' for 1st argument}} static_assert(is_same_v); using f7c1 = decltype(f7(return_void)); // expected-error{{no matching}} using f7c2 = decltype(f7(foo)); // expected-error{{no matching}} static_assert(is_same_v); decltype(auto) f8(auto... x) { return (x + ...); } static_assert(is_same_v); static_assert(is_same_v); static_assert(is_same_v); decltype(auto) f9(auto &... x) { return (x, ...); } // expected-note@-1{{candidate function [with x:auto = ] not viable: expects an lvalue for 2nd argument}} using f9c1 = decltype(f9(return_int, 1)); // expected-error{{no matching}} decltype(auto) f11(decltype(auto) x) { return x; } // expected-error{{'decltype(auto)' not allowed in function prototype}} template auto f12(auto x, T y) -> type_list; static_assert(is_same_v>); static_assert(is_same_v(1, 'c')), type_list>); template auto f13(T x, auto y) -> type_list; static_assert(is_same_v>); static_assert(is_same_v(1, 'c')), type_list>); template auto f14(auto y) -> type_list; static_assert(is_same_v('c')), type_list>); static_assert(is_same_v('c')), type_list>); template auto f15(auto y, U u) -> type_list; static_assert(is_same_v('c', nullptr)), type_list>); static_assert(is_same_v('c', nullptr)), type_list>); auto f16(auto x, auto y) -> type_list; static_assert(is_same_v>); static_assert(is_same_v('c', 1)), type_list>); static_assert(is_same_v('c', 1)), type_list>); void f17(auto x, auto y) requires (sizeof(x) > 1); // expected-note@-1{{candidate template ignored: constraints not satisfied [with x:auto = char, y:auto = int]}} // expected-note@-2{{because 'sizeof (x) > 1' (1 > 1) evaluated to false}} static_assert(is_same_v); // expected-error@-1{{no matching}} static_assert(is_same_v('c', 1)), void>); static_assert(is_same_v('c', 1)), void>); void f18(auto... x) requires (sizeof...(x) == 2); // expected-note@-1{{candidate template ignored: constraints not satisfied [with x:auto = ]}} // expected-note@-2{{candidate template ignored: constraints not satisfied [with x:auto = ]}} // expected-note@-3{{because 'sizeof...(x) == 2' (1 == 2) evaluated to false}} // expected-note@-4{{because 'sizeof...(x) == 2' (3 == 2) evaluated to false}} static_assert(is_same_v); // expected-error@-1{{no matching}} static_assert(is_same_v); static_assert(is_same_v); // expected-error@-1{{no matching}} template struct S { constexpr auto f1(auto x, T t) -> decltype(x + t); template constexpr auto f2(U u, auto x, T t) -> decltype(x + u + t); }; template constexpr auto S::f1(auto x, T t) -> decltype(x + t) { return x + t; } template template constexpr auto S::f2(auto x, U u, T t) -> decltype(x + u + t) { return x + u + t; } // expected-error@-1 {{out-of-line definition of 'f2' does not match any declaration in 'S'}} template template constexpr auto S::f2(U u, auto x, T t) -> decltype(x + u + t) { return x + u + t; } template<> template<> constexpr auto S::f2(double u, char x, int t) -> double { return 42; } static_assert(S{}.f1(1, 2) == 3); static_assert(S{}.f2(1, 2, '\x00') == 3); static_assert(S{}.f2(1, 2, '\x00') == 3.); static_assert(S{}.f2(1, '2', '\x00') == 42); } namespace constrained { template concept C = is_same_v; // expected-note@-1 12{{because}} template concept C2 = is_same_v; // expected-note@-1 12{{because}} int i; const int ci = 1; char c; const char cc = 'a'; int g(int); char h(int); void f1(C auto x); // expected-note@-1 {{candidate template ignored: constraints not satisfied [with x:auto = }} // expected-note@-2{{because}} static_assert(is_same_v); static_assert(is_same_v); // expected-error@-1{{no matching}} void f2(C auto &x); // expected-note@-1 2{{candidate template ignored}} expected-note@-1 2{{because}} static_assert(is_same_v); static_assert(is_same_v); // expected-error@-1{{no matching}} static_assert(is_same_v); // expected-error@-1{{no matching}} void f3(const C auto &x); // expected-note@-1{{candidate template ignored}} expected-note@-1{{because}} static_assert(is_same_v); static_assert(is_same_v); static_assert(is_same_v); // expected-error@-1{{no matching}} void f4(C auto (*x)(C auto y)); // expected-error{{'auto' not allowed}} void f5(C auto (*x)(int y)); // expected-note@-1{{candidate template ignored}} expected-note@-1{{because}} static_assert(is_same_v); static_assert(is_same_v); // expected-error@-1{{no matching}} void f6(C auto (*x)() -> int); // expected-error{{function with trailing return type must specify return type 'auto', not 'C auto'}} void f7(C auto... x); // expected-note@-1 2{{candidate template ignored}} expected-note@-1 2{{because}} static_assert(is_same_v); static_assert(is_same_v); // expected-error@-1{{no matching}} static_assert(is_same_v); // expected-error@-1{{no matching}} void f8(C auto &... x); // expected-note@-1 2{{candidate template ignored}} expected-note@-1 2{{because}} static_assert(is_same_v); static_assert(is_same_v); // expected-error@-1{{no matching}} static_assert(is_same_v); // expected-error@-1{{no matching}} void f9(const C auto &... x); // expected-note@-1{{candidate template ignored}} expected-note@-1{{because}} static_assert(is_same_v); static_assert(is_same_v); // expected-error@-1{{no matching}} static_assert(is_same_v); void f10(C decltype(auto) x); auto f11 = [] (C auto x) { }; // expected-note@-1{{candidate template ignored}} expected-note@-1{{because}} static_assert(is_same_v); static_assert(is_same_v); // expected-error@-1{{no matching}} void f12(C2 auto x); // expected-note@-1{{candidate template ignored}} expected-note@-1{{because}} static_assert(is_same_v); // expected-error@-1{{no matching}} static_assert(is_same_v); void f13(C2 auto &x); // expected-note@-1 2{{candidate template ignored}} expected-note@-1 2{{because}} static_assert(is_same_v); // expected-error@-1{{no matching}} static_assert(is_same_v); // expected-error@-1{{no matching}} static_assert(is_same_v); void f14(const C2 auto &x); // expected-note@-1{{candidate template ignored}} expected-note@-1{{because}} static_assert(is_same_v); // expected-error@-1{{no matching}} static_assert(is_same_v); static_assert(is_same_v); void f15(C2 auto (*x)(C2 auto y)); // expected-error{{'auto' not allowed}} void f16(C2 auto (*x)(int y)); // expected-note@-1{{candidate template ignored}} expected-note@-1{{because}} static_assert(is_same_v); // expected-error@-1{{no matching}} static_assert(is_same_v); void f17(C2 auto (*x)() -> int); // expected-error{{function with trailing return type must specify return type 'auto', not 'C2 auto'}} void f18(C2 auto... x); // expected-note@-1 2{{candidate template ignored}} expected-note@-1 2{{because}} static_assert(is_same_v); static_assert(is_same_v); // expected-error@-1{{no matching}} static_assert(is_same_v); // expected-error@-1{{no matching}} void f19(C2 auto &... x); // expected-note@-1 2{{candidate template ignored}} expected-note@-1 2{{because}} static_assert(is_same_v); static_assert(is_same_v); // expected-error@-1{{no matching}} static_assert(is_same_v); // expected-error@-1{{no matching}} void f20(const C2 auto &... x); // expected-note@-1{{candidate template ignored}} expected-note@-1{{because}} static_assert(is_same_v); static_assert(is_same_v); // expected-error@-1{{no matching}} static_assert(is_same_v); void f21(C2 decltype(auto) x); auto f22 = [] (C2 auto x) { }; // expected-note@-1{{candidate template ignored}} expected-note@-1{{because}} static_assert(is_same_v); // expected-error@-1{{no matching}} static_assert(is_same_v); struct S1 { S1(C auto); }; // expected-note@-1{{candidate template ignored}} expected-note@-1{{because}} // expected-note@-2 2{{candidate constructor}} static_assert(is_same_v); static_assert(is_same_v); // expected-error@-1{{no matching}} struct S2 { S2(C2 auto); }; // expected-note@-1{{candidate template ignored}} expected-note@-1{{because}} // expected-note@-2 2{{candidate constructor}} static_assert(is_same_v); // expected-error@-1{{no matching}} static_assert(is_same_v); }