// RUN: %clang_cc1 -fsyntax-only -verify -std=c++20 %s template constexpr bool True = true; template concept C = True; template concept D = C && sizeof(T) > 2; template concept E = D && alignof(T) > 1; struct A {}; template struct S {}; template struct S2 {}; template struct X {}; namespace p6 { struct B; void f(C auto &, auto &) = delete; template void f(Q &, C auto &); void g(struct A *ap, struct B *bp) { f(*ap, *bp); } #if 0 // FIXME: [temp.func.order]p6.2.1 is not implemented, matching GCC. template bool operator==(X, V) = delete; template bool operator==(T, X); bool h() { return X{} == 0; } #endif template class U, typename... Z> void foo(T, U) = delete; template class U, typename... Z> void foo(T, U) = delete; template class U, typename... Z> void foo(T, U); void bar(S s, S2 s2) { foo(0, s); } template void bar2(); template void bar2() = delete; } // namespace p6 namespace TestConversionFunction { struct Y { template operator X(); // expected-note {{candidate function [with T = int, U = int]}} template operator X(); // expected-note {{candidate function [with T = int, U = int]}} }; X f() { return Y{}; // expected-error {{conversion from 'Y' to 'X' is ambiguous}} } } namespace ClassPartialSpecPartialOrdering { template struct Y { Y()=delete; }; // expected-note {{template is declared here}} template struct Y {}; // expected-error {{class template partial specialization is not more specialized than the primary template}} template struct Y1 { Y1()=delete; }; template struct Y1 { Y1()=delete; }; template struct Y1 {}; template struct Y2 {}; template struct Y2 {}; // expected-note {{partial specialization matches}} template struct Y2 {}; // expected-note {{partial specialization matches}} template class U, typename... Z> struct Y3 { Y3()=delete; }; template class U, typename... Z> struct Y3 { Y3()=delete; }; template class U, typename... Z> struct Y3 {}; void f() { Y1 a; Y2 b; // expected-error {{ambiguous partial specializations}} Y3 c; } // Per [temp.func.order]p6.2.2, specifically "if the function parameters that // positionally correspond between the two templates are not of the same type", // this partial specialization does not work. // See https://github.com/llvm/llvm-project/issues/58896 template struct Y4; // expected-note {{template is declared here}} template struct Y4; // expected-error {{class template partial specialization is not more specialized than the primary template}} template struct W1; template struct W1 {}; // See http://cplusplus.github.io/concepts-ts/ts-active.html#28 // template struct W2; // template struct W2 {}; template concept C1 = C && C; template concept D1 = D && C; template auto T> struct W3; template auto T> struct W3 {}; // See http://cplusplus.github.io/concepts-ts/ts-active.html#28 // template auto... T> struct W4; // template auto... T> struct W4 {}; // FIXME: enable once Clang support non-trivial auto on NTTP. // template struct W5; // template struct W5 {}; // FIXME: enable once Clang support non-trivial auto on NTTP. // template struct W6; // template struct W6 {}; struct W1<0> w1; // struct W2<0> w2; struct W3<0> w3; // struct W4<0> w4; // FIXME: enable once Clang support non-trivial auto on NTTP. // struct W5<(int*)nullptr> w5; // struct W6 w6; } namespace PR53640 { template concept C = true; template void f(T t) {} // expected-note {{candidate function [with T = int]}} template void f(const T &t) {} // expected-note {{candidate function [with T = int]}} int g() { f(0); // expected-error {{call to 'f' is ambiguous}} } struct S { template explicit S(T) noexcept requires C {} // expected-note {{candidate constructor}} template explicit S(const T &) noexcept {} // expected-note {{candidate constructor}} }; int h() { S s(4); // expected-error-re {{call to constructor of {{.*}} is ambiguous}} } } namespace NestedConstraintsDiffer { template concept A = true; template concept B = A && true; // This is valid: we can compare the constraints of the two overloads of `f` // because the template-parameters are equivalent, despite having different // constraints. template struct Z {}; template typename> struct X {}; template typename TT> void f(U, X) {} template typename TT> void f(U, X) {} void g(X x) { f(0, x); } // Same thing with a constrained non-type parameter. template struct W {}; template typename> struct Y {}; template typename TT> void h(U, Y) {} template typename TT> void h(U, Y) {} void i(Y x) { h(0, x); } }