xref: /llvm-project/clang/test/CXX/temp/temp.constr/temp.constr.normal/p1.cpp (revision 358165ded3c45115ce587d56ef792a9e7c0214ea)
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