Run DCE after a LoopFlatten test to reduce spurious output [nfc]
[llvm-project.git] / clang / test / SemaTemplate / concepts-out-of-line-def.cpp
blobf134394615fb2483cb4fca3433ea36592e61e7aa
1 // RUN: %clang_cc1 -std=c++20 -verify %s
3 static constexpr int PRIMARY = 0;
4 static constexpr int SPECIALIZATION_CONCEPT = 1;
5 static constexpr int SPECIALIZATION_REQUIRES = 2;
7 template <class T>
8 concept Concept = (sizeof(T) >= 2 * sizeof(int));
10 struct XY {
11 int x;
12 int y;
15 namespace members {
17 template <class T, class U> struct S {
18 static constexpr int primary();
21 template <class T, class U> constexpr int S<T, U>::primary() {
22 return PRIMARY;
25 template <Concept C, class U> struct S<C, U> {
26 static constexpr int specialization();
29 template <class T, class U>
30 requires(sizeof(T) == sizeof(int))
31 struct S<T, U> {
32 static constexpr int specialization();
35 template <Concept C, class U> constexpr int S<C, U>::specialization() {
36 return SPECIALIZATION_CONCEPT;
39 template <class T, class U>
40 requires(sizeof(T) == sizeof(int))
41 constexpr int S<T, U>::specialization() {
42 return SPECIALIZATION_REQUIRES;
45 static_assert(S<char, double>::primary() == PRIMARY);
46 static_assert(S<XY, double>::specialization() == SPECIALIZATION_CONCEPT);
47 static_assert(S<int, double>::specialization() == SPECIALIZATION_REQUIRES);
49 } // namespace members
51 namespace enumerations {
53 template <class T, class U> struct S {
54 enum class E : int;
57 template <class T, class U> enum class S<T, U>::E { Value = PRIMARY };
59 template <Concept C, class U> struct S<C, U> {
60 enum class E : int;
63 template <Concept C, class U>
64 enum class S<C, U>::E {
65 Value = SPECIALIZATION_CONCEPT
68 template <class T, class U>
69 requires(sizeof(T) == sizeof(int))
70 struct S<T, U> {
71 enum class E : int;
74 template <class T, class U>
75 requires(sizeof(T) == sizeof(int))
76 enum class S<T, U>::E {
77 Value = SPECIALIZATION_REQUIRES
80 static_assert(static_cast<int>(S<char, double>::E::Value) == PRIMARY);
81 static_assert(static_cast<int>(S<XY, double>::E::Value) ==
82 SPECIALIZATION_CONCEPT);
83 static_assert(static_cast<int>(S<int, double>::E::Value) ==
84 SPECIALIZATION_REQUIRES);
86 } // namespace enumerations
88 namespace multiple_template_parameter_lists {
90 template <class Outer>
91 struct S {
92 template <class Inner>
93 static constexpr int primary(Inner);
96 template <class Outer>
97 template <class Inner>
98 constexpr int S<Outer>::primary(Inner) {
99 return PRIMARY;
102 template <Concept Outer>
103 struct S<Outer> {
104 template <class Inner>
105 static constexpr int specialization(Inner);
108 template <Concept Outer>
109 template <class Inner>
110 constexpr int S<Outer>::specialization(Inner) { return SPECIALIZATION_CONCEPT; }
112 template <class Outer>
113 requires(sizeof(Outer) == sizeof(int))
114 struct S<Outer> {
115 template <class Inner>
116 static constexpr int specialization(Inner);
119 template <class Outer>
120 requires(sizeof(Outer) == sizeof(int))
121 template <class Inner>
122 constexpr int S<Outer>::specialization(Inner) { return SPECIALIZATION_REQUIRES; }
124 static_assert(S<char>::primary("str") == PRIMARY);
125 static_assert(S<XY>::specialization("str") == SPECIALIZATION_CONCEPT);
126 static_assert(S<int>::specialization("str") == SPECIALIZATION_REQUIRES);
128 } // namespace multiple_template_parameter_lists
130 static constexpr int CONSTRAINED_METHOD_1 = 1;
131 static constexpr int CONSTRAINED_METHOD_2 = 2;
133 namespace constrained_members {
135 template <int>
136 struct S {
137 template <Concept C>
138 static constexpr int constrained_method();
141 template <>
142 template <Concept C>
143 constexpr int S<1>::constrained_method() { return CONSTRAINED_METHOD_1; }
145 template <>
146 template <Concept C>
147 constexpr int S<2>::constrained_method() { return CONSTRAINED_METHOD_2; }
149 static_assert(S<1>::constrained_method<XY>() == CONSTRAINED_METHOD_1);
150 static_assert(S<2>::constrained_method<XY>() == CONSTRAINED_METHOD_2);
153 template <class T1, class T2>
154 concept ConceptT1T2 = true;
156 template<typename T3>
157 struct S12 {
158 template<ConceptT1T2<T3> T4>
159 static constexpr int constrained_method();
162 template<>
163 template<ConceptT1T2<int> T5>
164 constexpr int S12<int>::constrained_method() { return CONSTRAINED_METHOD_1; }
166 template<>
167 template<ConceptT1T2<double> T5>
168 constexpr int S12<double>::constrained_method() { return CONSTRAINED_METHOD_2; }
170 static_assert(S12<int>::constrained_method<XY>() == CONSTRAINED_METHOD_1);
171 static_assert(S12<double>::constrained_method<XY>() == CONSTRAINED_METHOD_2);
173 } // namespace constrained members
175 namespace constrained_members_of_nested_types {
177 template <int>
178 struct S {
179 struct Inner0 {
180 struct Inner1 {
181 template <Concept C>
182 static constexpr int constrained_method();
187 template <>
188 template <Concept C>
189 constexpr int S<1>::Inner0::Inner1::constrained_method() { return CONSTRAINED_METHOD_1; }
191 template <>
192 template <Concept C>
193 constexpr int S<2>::Inner0::Inner1::constrained_method() { return CONSTRAINED_METHOD_2; }
195 static_assert(S<1>::Inner0::Inner1::constrained_method<XY>() == CONSTRAINED_METHOD_1);
196 static_assert(S<2>::Inner0::Inner1::constrained_method<XY>() == CONSTRAINED_METHOD_2);
199 template <class T1, class T2>
200 concept ConceptT1T2 = true;
202 template<typename T3>
203 struct S12 {
204 struct Inner0 {
205 struct Inner1 {
206 template<ConceptT1T2<T3> T4>
207 static constexpr int constrained_method();
212 template<>
213 template<ConceptT1T2<int> T5>
214 constexpr int S12<int>::Inner0::Inner1::constrained_method() { return CONSTRAINED_METHOD_1; }
216 template<>
217 template<ConceptT1T2<double> T5>
218 constexpr int S12<double>::Inner0::Inner1::constrained_method() { return CONSTRAINED_METHOD_2; }
220 static_assert(S12<int>::Inner0::Inner1::constrained_method<XY>() == CONSTRAINED_METHOD_1);
221 static_assert(S12<double>::Inner0::Inner1::constrained_method<XY>() == CONSTRAINED_METHOD_2);
223 } // namespace constrained_members_of_nested_types
225 namespace constrained_member_sfinae {
227 template<int N> struct S {
228 template<class T>
229 static constexpr int constrained_method() requires (sizeof(int[N * 1073741824 + 4]) == 16) { // expected-warning {{variable length arrays in C++ are a Clang extension}} \
230 expected-note {{value 4294967296 is outside the range of representable values of type 'int'}} \
231 expected-note {{while calculating associated constraint of template 'constrained_method' here}}
232 return CONSTRAINED_METHOD_1;
235 template<class T>
236 static constexpr int constrained_method() requires (sizeof(int[N]) == 16);
239 template<>
240 template<typename T>
241 constexpr int S<4>::constrained_method() requires (sizeof(int[4]) == 16) {
242 return CONSTRAINED_METHOD_2;
245 // Verify that there is no amiguity in this case.
246 static_assert(S<4>::constrained_method<double>() == CONSTRAINED_METHOD_2);
248 } // namespace constrained_member_sfinae
250 namespace requires_expression_references_members {
252 void accept1(int x);
253 void accept2(XY xy);
255 template <class T> struct S {
256 T Field = T();
258 constexpr int constrained_method()
259 requires requires { accept1(Field); };
261 constexpr int constrained_method()
262 requires requires { accept2(Field); };
265 template <class T>
266 constexpr int S<T>::constrained_method()
267 requires requires { accept1(Field); } {
268 return CONSTRAINED_METHOD_1;
271 template <class T>
272 constexpr int S<T>::constrained_method()
273 requires requires { accept2(Field); } {
274 return CONSTRAINED_METHOD_2;
277 static_assert(S<int>().constrained_method() == CONSTRAINED_METHOD_1);
278 static_assert(S<XY>().constrained_method() == CONSTRAINED_METHOD_2);
280 } // namespace requires_expression_references_members
282 namespace GH60231 {
284 template<typename T0> concept C = true;
286 template <typename T1>
287 struct S {
288 template <typename F1> requires C<S<T1>>
289 void foo1(F1 f);
291 template <typename F2>
292 void foo2(F2 f) requires C<S<T1>>;
294 template <typename F3> requires C<F3>
295 void foo3(F3 f);
298 template <typename T2>
299 template <typename F4> requires C<S<T2>>
300 void S<T2>::foo1(F4 f) {}
302 template <typename T3>
303 template <typename F5>
304 void S<T3>::foo2(F5 f) requires C<S<T3>> {}
306 template <typename T4>
307 template <typename F6> requires C<F6>
308 void S<T4>::foo3(F6 f) {}
310 } // namespace GH60231
312 namespace GH62003 {
314 template <typename T0> concept Concept = true;
316 template <class T1>
317 struct S1 {
318 template <Concept C1>
319 static constexpr int foo();
321 template <class T2>
322 template <Concept C2>
323 constexpr int S1<T2>::foo() { return 1; }
325 template <Concept C3>
326 struct S2 {
327 template <class T3>
328 static constexpr int foo();
330 template <Concept C4>
331 template <class T4>
332 constexpr int S2<C4>::foo() { return 2; }
334 template <Concept C5>
335 struct S3 {
336 template <Concept C6>
337 static constexpr int foo();
339 template <Concept C7>
340 template <Concept C8>
341 constexpr int S3<C7>::foo() { return 3; }
343 static_assert(S1<int>::foo<int>() == 1);
344 static_assert(S2<int>::foo<int>() == 2);
345 static_assert(S3<int>::foo<int>() == 3);
347 } // namespace GH62003
349 namespace MultilevelTemplateWithPartialSpecialization {
350 template <typename>
351 concept Concept = true;
353 namespace two_level {
354 template <typename T1, int>
355 struct W0 {
356 template <typename T2>
357 requires (Concept<T2>)
358 void f(const T2 &);
361 template <typename T3>
362 struct W0<T3, 0> {
363 template <typename T4>
364 requires (Concept<T4>)
365 void f(const T4 &);
368 template <typename T3>
369 template <typename T4>
370 requires (Concept<T4>)
371 inline void W0<T3, 0>::f(const T4 &) {}
372 } // namespace two_level
374 namespace three_level {
375 template <typename T1, int>
376 struct W0 {
377 template <typename T2>
378 struct W1 {
379 template <typename T3>
380 requires (Concept<T3>)
381 void f(const T3 &);
385 template <typename T4>
386 struct W0<T4, 0> {
387 template <typename T5>
388 struct W1 {
389 template <typename T6>
390 requires (Concept<T6>)
391 void f(const T6 &);
395 template <typename T7>
396 template <typename T8>
397 template <typename T9>
398 requires (Concept<T9>)
399 inline void W0<T7, 0>::W1<T8>::f(const T9 &) {}
400 } // namespace three_level
402 } // namespace MultilevelTemplateWithPartialSpecialization
404 namespace PR62697 {
405 template<typename>
406 concept c = true;
408 template<typename T>
409 struct s {
410 void f() requires c<void(T)>;
413 template<typename T>
414 void s<T>::f() requires c<void(T)> { }
417 namespace GH62272 {
418 template<typename T> concept A = true;
419 template<typename T> struct X { A<T> auto f(); };
420 template<typename T> A<T> auto X<T>::f() {}
423 namespace GH65810 {
424 template<typename Param>
425 concept TrivialConcept =
426 requires(Param param) {
427 (void)param;
430 template <typename T>
431 struct Base {
432 class InnerClass;
435 template <typename T>
436 class Base<T>::InnerClass {
437 template <typename Param>
438 requires TrivialConcept<Param>
439 int func(Param param) const;
442 template <typename T>
443 template <typename Param>
444 requires TrivialConcept<Param>
445 int Base<T>::InnerClass::func(Param param) const {
446 return 0;
449 template<typename T>
450 struct Outermost {
451 struct Middle {
452 template<typename U>
453 struct Innermost {
454 template <typename Param>
455 requires TrivialConcept<Param>
456 int func(Param param) const;
461 template <typename T>
462 template <typename U>
463 template <typename Param>
464 requires TrivialConcept<Param>
465 int Outermost<T>::Middle::Innermost<U>::func(Param param) const {
466 return 0;
469 } // namespace GH65810
471 namespace GH61763 {
472 template<typename T, typename U>
473 concept same_as = true;
475 template <class = void>
476 struct Foo {
477 template <same_as<void> Param>
478 friend struct Bar;
481 template struct Foo<>;
483 template <same_as<void> Param>
484 struct Bar {
488 template<typename T>
489 concept ok = true;
491 struct outer {
492 template<typename T>
493 requires ok<T>
494 struct foo {};
497 template<typename U>
498 struct bar {
499 template<typename T>
500 requires ok<T>
501 friend struct outer::foo;
504 bar<int> x;
505 } // namespace GH61763