1 // RUN: %clang_cc1 -std=c++2a -x c++ -verify %s 2 3 template<typename T> concept True = true; 4 template<typename T> concept Foo = True<T*>; 5 template<typename T> concept Bar = Foo<T&>; 6 template<typename T> requires Bar<T> struct S { }; 7 template<typename T> requires Bar<T> && true struct S<T> { }; 8 9 template<typename T> concept True2 = sizeof(T) >= 0; 10 template<typename T> concept Foo2 = True2<T*>; 11 // expected-error@-1{{'type name' declared as a pointer to a reference of type 'type-parameter-0-0 &'}} 12 template<typename T> concept Bar2 = Foo2<T&>; 13 // expected-note@-1{{while substituting into concept arguments here; substitution failures not allowed in concept arguments}} 14 template<typename T> requires Bar2<T> struct S2 { }; 15 // expected-note@-1{{template is declared here}} 16 template<typename T> requires Bar2<T> && true struct S2<T> { }; 17 // expected-error@-1{{class template partial specialization is not more specialized than the primary template}} 18 // expected-note@-2{{while calculating associated constraint of template 'S2<T>' here}} 19 20 namespace type_pack { 21 template<typename... Args> 22 concept C1 = ((sizeof(Args) >= 0) && ...); 23 24 template<typename A, typename... B> 25 concept C2 = C1<A, B...>; 26 27 template<typename T> 28 constexpr void foo() requires C2<T, char, T> { } 29 30 template<typename T> 31 constexpr void foo() requires C1<T, char, T> && true { } 32 33 static_assert((foo<int>(), true)); 34 } 35 36 namespace template_pack { 37 template<typename T> struct S1 {}; 38 template<typename T> struct S2 {}; 39 40 template<template<typename> typename... Args> 41 concept C1 = ((sizeof(Args<int>) >= 0) && ...); 42 43 template<template<typename> typename A, template<typename> typename... B> 44 concept C2 = C1<A, B...>; 45 46 template<template<typename> typename T> 47 constexpr void foo() requires C2<T, S1, T> { } 48 49 template<template<typename> typename T> 50 constexpr void foo() requires C1<T, S1, T> && true { } 51 52 static_assert((foo<S2>(), true)); 53 } 54 55 namespace non_type_pack { 56 template<int... Args> 57 concept C1 = ((Args >= 0) && ...); 58 59 template<int A, int... B> 60 concept C2 = C1<A, B...>; 61 62 template<int T> 63 constexpr void foo() requires C2<T, 2, T> { } 64 65 template<int T> 66 constexpr void foo() requires C1<T, 2, T> && true { } 67 68 static_assert((foo<1>(), true)); 69 } 70 71 namespace PR47174 { 72 // This checks that we don't crash with a failed substitution on the first constrained argument when 73 // performing normalization. 74 template <Bar2 T, True U> 75 requires true struct S3; // expected-note {{template is declared here}} 76 template <True T, True U> 77 requires true struct S3<T, U>; // expected-error {{class template partial specialization is not more specialized than the primary template}} 78 79 // Same as above, for the second position (but this was already working). 80 template <True T, Bar2 U> 81 requires true struct S4; // expected-note {{template is declared here}} 82 template <True T, True U> 83 requires true struct S4<T, U>; // expected-error {{class template partial specialization is not more specialized than the primary template}} 84 85 struct X { 86 template<int> struct Y { 87 using type = int; 88 }; 89 }; 90 91 template<class T> concept C1 = sizeof(T) != 0; 92 template<class T> concept C2 = C1<typename T::template Y<1>::type>; 93 94 template<class T> requires C1<T> void t1() {}; // expected-note {{candidate function}} 95 template<class T> requires C1<T> && C2<T> void t1() = delete; // expected-note {{candidate function}} 96 template void t1<X>(); 97 void t1() { t1<X>(); } // expected-error {{call to deleted function 't1'}} 98 99 template<class T> requires C1<T> void t2() {}; // expected-note 2 {{candidate function}} 100 template<class T> requires C2<T> void t2() {}; // expected-note 2 {{candidate function}} 101 template void t2<X>(); // expected-error {{partial ordering for explicit instantiation of 't2' is ambiguous}} 102 void t2() { t2<X>(); } // expected-error {{call to 't2' is ambiguous}} 103 } // namespace PR47174 104