// RUN: %clang_cc1 -std=c++2a -x c++ -verify %s // RUN: %clang_cc1 -std=c++2c -x c++ -verify %s template concept True = true; template concept Foo = True; // #Foo template concept Bar = Foo; // #Bar template requires Bar struct S { }; // #S template requires Bar && true struct S { }; // #SpecS // expected-error@-1 {{class template partial specialization is not more specialized than the primary template}} // expected-error@#Foo 2{{'type name' declared as a pointer to a reference of type 'T &'}} // expected-note@#SpecS {{while substituting into concept arguments here}} // expected-note@#S {{while substituting into concept arguments here}} // expected-note@#Bar 2{{while substituting into concept arguments here}} // expected-note@#S {{template is declared here}} template concept True2 = sizeof(T) >= 0; template concept Foo2 = True2; // #Foo2 template concept Bar2 = Foo2; // #Bar2 // expected-note@-1 3{{while substituting into concept arguments here; substitution failures not allowed in concept arguments}} template requires Bar2 struct S2 { }; // #SpecS2_1 // expected-note@-1{{template is declared here}} template requires Bar2 && true struct S2 { }; // #SpecS2_2 // expected-error@-1{{class template partial specialization is not more specialized than the primary template}} // expected-error@#Foo2{{'type name' declared as a pointer to a reference of type 'T &'}} namespace type_pack { template concept C1 = ((sizeof(Args) >= 0) && ...); template concept C2 = C1; template constexpr void foo() requires C2 { } template constexpr void foo() requires C1 && true { } static_assert((foo(), true)); } namespace template_pack { template struct S1 {}; template struct S2 {}; template typename... Args> concept C1 = ((sizeof(Args) >= 0) && ...); template typename A, template typename... B> concept C2 = C1; template typename T> constexpr void foo() requires C2 { } template typename T> constexpr void foo() requires C1 && true { } static_assert((foo(), true)); } namespace non_type_pack { template concept C1 = ((Args >= 0) && ...); template concept C2 = C1; template constexpr void foo() requires C2 { } template constexpr void foo() requires C1 && true { } static_assert((foo<1>(), true)); } namespace PR47174 { // This checks that we don't crash with a failed substitution on the first constrained argument when // performing normalization. template // #S3_Header requires true struct S3; // expected-note {{template is declared here}} template requires true struct S3; // expected-error@-1 {{class template partial specialization is not more specialized than the primary template}} // expected-error@#Foo2 2{{'type name' declared as a pointer to a reference of type 'T &'}} // expected-note@#SpecS2_1 {{while substituting into concept arguments here}} // expected-note@#SpecS2_2 {{while substituting into concept arguments here}} // expected-note@#S3_Header {{while substituting into concept arguments here}} // expected-note@#Bar2 {{while substituting into concept arguments here}} // Same as above, for the second position (but this was already working). template // #S4_Header requires true struct S4; // #S4 template requires true struct S4; // #S4-spec // expected-error@-1 {{class template partial specialization is not more specialized than the primary template}} // expected-error@#Foo2 {{'type name' declared as a pointer to a reference of type 'U &'}} // expected-note@#S4_Header {{while substituting into concept arguments here}} // expected-note@#S4 {{template is declared here}} // expected-note@#S4 {{similar constraint expressions not considered equivalent}} // expected-note@#S4-spec {{similar constraint expression here}} struct X { template struct Y { using type = int; }; }; template concept C1 = sizeof(T) != 0; template concept C2 = C1::type>; template requires C1 void t1() {}; // expected-note {{candidate function}} template requires C1 && C2 void t1() = delete; // expected-note {{candidate function}} template void t1(); void t1() { t1(); } // expected-error {{call to deleted function 't1'}} template requires C1 void t2() {}; // expected-note 2 {{candidate function}} template requires C2 void t2() {}; // expected-note 2 {{candidate function}} template void t2(); // expected-error {{partial ordering for explicit instantiation of 't2' is ambiguous}} void t2() { t2(); } // expected-error {{call to 't2' is ambiguous}} } // namespace PR47174