1 // RUN: %clang_cc1 -std=c++2a -x c++ %s -verify -Wno-unused-value
2 
3 template<typename T, typename U>
4 constexpr bool is_same_v = false;
5 
6 template<typename T>
7 constexpr bool is_same_v<T, T> = true;
8 
9 // We use a hack in this file to make the compiler print out the requires
10 // expression after it has been instantiated - we put false_v<requires {...}> as
11 // the requires clause of a class template, then instantiate the template.
12 // The requirement will not be satisfied, and the explaining diagnostic will
13 // print out false_v<requires {...}> in its raw form (the false_v serves to
14 // prevent the diagnostic from elaborating on why the requires expr wasn't
15 // satisfied).
16 
17 template<bool v>
18 constexpr bool false_v = false;
19 
20 template<typename... Ts>
21 using void_t = void;
22 
23 // Check that requires parameters are instantiated correctly.
24 
25 template<typename T> requires
26 false_v<requires (T t) { requires is_same_v<decltype(t), int>; }>
27 // expected-note@-1 {{because 'false_v<requires (int t) { requires is_same_v<decltype(t), int>; }>' evaluated to false}}
28 // expected-note@-2 {{because 'false_v<requires (char t) { requires is_same_v<decltype(t), int>; }>' evaluated to false}}
29 struct r1 {};
30 
31 using r1i1 = r1<int>; // expected-error {{constraints not satisfied for class template 'r1' [with T = int]}}
32 using r1i2 = r1<char>; // expected-error {{constraints not satisfied for class template 'r1' [with T = char]}}
33 
34 // Check that parameter packs work.
35 
36 template<typename... Ts> requires
37 false_v<requires (Ts... ts) {requires ((sizeof(ts) == 2) && ...);}>
38 // expected-note@-1 {{because 'false_v<requires (short ts, unsigned short ts) { requires (sizeof (ts) == 2) && (sizeof (ts) == 2); }>'}}
39 // expected-note@-2 {{because 'false_v<requires (short ts) { requires (sizeof (ts) == 2); }>' evaluated to false}}
40 struct r2 {};
41 
42 using r2i1 = r2<short, unsigned short>; // expected-error {{constraints not satisfied for class template 'r2' [with Ts = <short, unsigned short>]}}
43 using r2i2 = r2<short>; // expected-error {{constraints not satisfied for class template 'r2' [with Ts = <short>]}}
44 
45 template<typename... Ts> requires
46 false_v<(requires (Ts ts) {requires sizeof(ts) != 0;} && ...)>
47 // expected-note@-1 {{because 'false_v<requires (short ts) { requires sizeof (ts) != 0; } && requires (unsigned short ts) { requires sizeof (ts) != 0; }>' evaluated to false}}
48 // expected-note@-2 {{because 'false_v<requires (short ts) { requires sizeof (ts) != 0; }>' evaluated to false}}
49 struct r3 {};
50 
51 using r3i1 = r3<short, unsigned short>; // expected-error {{constraints not satisfied for class template 'r3' [with Ts = <short, unsigned short>]}}
52 using r3i2 = r3<short>; // expected-error {{constraints not satisfied for class template 'r3' [with Ts = <short>]}}
53 
54 template<typename T>
55 struct identity { using type = T; };
56 
57 namespace type_requirement {
58   struct A {};
59 
60   // check that nested name specifier is instantiated correctly.
61   template<typename T> requires false_v<requires { typename T::type; }> // expected-note{{because 'false_v<requires { typename identity<int>::type; }>' evaluated to false}}
62   struct r1 {};
63 
64   using r1i = r1<identity<int>>; // expected-error{{constraints not satisfied for class template 'r1' [with T = identity<int>]}}
65 
66   // check that template argument list is instantiated correctly.
67   template<typename T>
68   struct contains_template {
69       template<typename U> requires is_same_v<contains_template<T>, U>
70       using temp = int;
71   };
72 
73   template<typename T> requires
74   false_v<requires { typename T::template temp<T>; }>
75   // expected-note@-1 {{because 'false_v<requires { typename contains_template<int>::temp<contains_template<int> >; }>' evaluated to false}}
76   // expected-note@-2 {{because 'false_v<requires { typename contains_template<short>::temp<contains_template<short> >; }>' evaluated to false}}
77   struct r2 {};
78 
79   using r2i1 = r2<contains_template<int>>; // expected-error{{constraints not satisfied for class template 'r2' [with T = type_requirement::contains_template<int>]}}
80   using r2i2 = r2<contains_template<short>>; // expected-error{{constraints not satisfied for class template 'r2' [with T = type_requirement::contains_template<short>]}}
81 
82   // substitution error occurs, then requires expr is instantiated again
83 
84   template<typename T>
85   struct a {
86       template<typename U> requires (requires { typename T::a::a; }, false)
87       // expected-note@-1{{because 'requires { <<error-type>>; } , false' evaluated to false}}
88       struct r {};
89   };
90 
91   using ari = a<int>::r<short>; // expected-error{{constraints not satisfied for class template 'r' [with U = short]}}
92 
93   // Parameter pack inside expr
94   template<typename... Ts> requires
95   false_v<(requires { typename Ts::type; } && ...)>
96   // expected-note@-1 {{because 'false_v<requires { typename identity<short>::type; } && requires { typename identity<int>::type; } && requires { <<error-type>>; }>' evaluated to false}}
97   struct r5 {};
98 
99   using r5i = r5<identity<short>, identity<int>, short>; // expected-error{{constraints not satisfied for class template 'r5' [with Ts = <identity<short>, identity<int>, short>]}}
100   template<typename... Ts> requires
101   false_v<(requires { typename void_t<Ts>; } && ...)> // expected-note{{because 'false_v<requires { typename void_t<int>; } && requires { typename void_t<short>; }>' evaluated to false}}
102   struct r6 {};
103 
104   using r6i = r6<int, short>; // expected-error{{constraints not satisfied for class template 'r6' [with Ts = <int, short>]}}
105 
106   template<typename... Ts> requires
107   false_v<(requires { typename Ts::template aaa<Ts>; } && ...)>
108   // expected-note@-1 {{because 'false_v<requires { <<error-type>>; } && requires { <<error-type>>; }>' evaluated to false}}
109   struct r7 {};
110 
111   using r7i = r7<int, A>; // expected-error{{constraints not satisfied for class template 'r7' [with Ts = <int, type_requirement::A>]}}
112 }
113 
114 namespace expr_requirement {
115   // check that compound/simple requirements are instantiated correctly.
116 
117   template<typename T> requires false_v<requires { sizeof(T); { sizeof(T) }; }>
118   // expected-note@-1 {{because 'false_v<requires { sizeof(int); { sizeof(int) }; }>' evaluated to false}}
119   // expected-note@-2 {{because 'false_v<requires { <<error-expression>>; { sizeof(T) }; }>' evaluated to false}}
120   struct r1 {};
121 
122   using r1i1 = r1<int>; // expected-error{{constraints not satisfied for class template 'r1' [with T = int]}}
123   using r1i2 = r1<void>; // expected-error{{constraints not satisfied for class template 'r1' [with T = void]}}
124 
125   // substitution error occurs in expr, then expr is instantiated again.
126 
127   template<typename T>
128   struct a {
129       template<typename U> requires (requires { sizeof(T::a); }, false) // expected-note{{because 'requires { <<error-expression>>; } , false' evaluated to false}}
130       struct r {};
131   };
132 
133   using ari = a<int>::r<short>; // expected-error{{constraints not satisfied for class template 'r' [with U = short]}}
134 
135   // check that the return-type-requirement is instantiated correctly.
136 
137   template<typename T, typename U = int>
138   concept C1 = is_same_v<T, U>;
139 
140   template<typename T> requires false_v<requires(T t) { { t } -> C1<T>; }>
141   // expected-note@-1 {{because 'false_v<requires (int t) { { t } -> C1<int>; }>' evaluated to false}}
142   // expected-note@-2 {{because 'false_v<requires (double t) { { t } -> C1<double>; }>' evaluated to false}}
143   struct r2 {};
144 
145   using r2i1 = r2<int>; // expected-error{{constraints not satisfied for class template 'r2' [with T = int]}}
146   using r2i2 = r2<double>; // expected-error{{constraints not satisfied for class template 'r2' [with T = double]}}
147 
148 
149   // substitution error occurs in return type requirement, then requires expr is
150   // instantiated again.
151 
152   template<typename T>
153   struct b {
154       template<typename U> requires (requires { { 0 } -> C1<typename T::a>; }, false) // expected-note{{because 'requires { { 0 } -> <<error-type>>; } , false' evaluated to false}}
155       struct r {};
156   };
157 
158   using bri = b<int>::r<short>; // expected-error{{constraints not satisfied for class template 'r' [with U = short]}}
159 
160 
161   template<typename... Ts> requires
162   false_v<(requires { { 0 } noexcept -> C1<Ts>; } && ...)>
163   // expected-note@-1 {{because 'false_v<requires { { 0 } noexcept -> C1<int>; } && requires { { 0 } noexcept -> C1<unsigned int>; }>' evaluated to false}}
164   struct r3 {};
165 
166   using r3i = r3<int, unsigned int>; // expected-error{{constraints not satisfied for class template 'r3' [with Ts = <int, unsigned int>]}}
167 
168   template<typename T>
169   struct r4 {
fooexpr_requirement::r4170       constexpr int foo() {
171         if constexpr (requires { this->invalid(); })
172           return 1;
173         else
174           return 0;
175       }
176 
invalidexpr_requirement::r4177       constexpr void invalid() requires false { }
178   };
179   static_assert(r4<int>{}.foo() == 0);
180 }
181 
182 namespace nested_requirement {
183   // check that constraint expression is instantiated correctly
184   template<typename T> requires false_v<requires { requires sizeof(T) == 2; }> // expected-note{{because 'false_v<requires { requires sizeof(int) == 2; }>' evaluated to false}}
185   struct r1 {};
186 
187   using r1i = r1<int>; // expected-error{{constraints not satisfied for class template 'r1' [with T = int]}}
188 
189   // substitution error occurs in expr, then expr is instantiated again.
190   template<typename T>
191   struct a {
192       template<typename U> requires
193       (requires { requires sizeof(T::a) == 0; }, false) // expected-note{{because 'requires { requires <<error-expression>>; } , false' evaluated to false}}
194       struct r {};
195   };
196 
197   using ari = a<int>::r<short>; // expected-error{{constraints not satisfied for class template 'r' [with U = short]}}
198 
199   // Parameter pack inside expr
200   template<typename... Ts> requires
201   false_v<(requires { requires sizeof(Ts) == 0; } && ...)>
202   // expected-note@-1 {{because 'false_v<requires { requires sizeof(int) == 0; } && requires { requires sizeof(short) == 0; }>' evaluated to false}}
203   struct r2 {};
204 
205   using r2i = r2<int, short>; // expected-error{{constraints not satisfied for class template 'r2' [with Ts = <int, short>]}}
206 }
207 
208 // Parameter pack inside multiple requirements
209 template<typename... Ts> requires
210 false_v<(requires { requires sizeof(Ts) == 0; sizeof(Ts); } && ...)>
211 // expected-note@-1 {{because 'false_v<requires { requires sizeof(int) == 0; sizeof(Ts); } && requires { requires sizeof(short) == 0; sizeof(Ts); }>' evaluated to false}}
212 struct r4 {};
213 
214 using r4i = r4<int, short>; // expected-error{{constraints not satisfied for class template 'r4' [with Ts = <int, short>]}}
215 
216 template<typename... Ts> requires
217 false_v<(requires(Ts t) { requires sizeof(t) == 0; t++; } && ...)>
218 // expected-note@-1 {{because 'false_v<requires (int t) { requires sizeof (t) == 0; t++; } && requires (short t) { requires sizeof (t) == 0; t++; }>' evaluated to false}}
219 struct r5 {};
220 
221 using r5i = r5<int, short>; // expected-error{{constraints not satisfied for class template 'r5' [with Ts = <int, short>]}}
222 
223 template<typename T> requires
224 false_v<(requires(T t) { T{t}; })> // T{t} creates an "UnevaluatedList" context.
225 // expected-note@-1 {{because 'false_v<(requires (int t) { int{t}; })>' evaluated to false}}
226 struct r6 {};
227 
228 using r6i = r6<int>;
229 // expected-error@-1 {{constraints not satisfied for class template 'r6' [with T = int]}}
230