1 // RUN: %clang_cc1 -std=c++20 -verify %s 2 3 static constexpr int PRIMARY = 0; 4 static constexpr int SPECIALIZATION_CONCEPT = 1; 5 static constexpr int SPECIALIZATION_REQUIRES = 2; 6 7 template <class T> 8 concept Concept = (sizeof(T) >= 2 * sizeof(int)); 9 10 struct XY { 11 int x; 12 int y; 13 }; 14 15 namespace members { 16 17 template <class T, class U> struct S { 18 static constexpr int primary(); 19 }; 20 21 template <class T, class U> constexpr int S<T, U>::primary() { 22 return PRIMARY; 23 }; 24 25 template <Concept C, class U> struct S<C, U> { 26 static constexpr int specialization(); 27 }; 28 29 template <class T, class U> 30 requires(sizeof(T) == sizeof(int)) 31 struct S<T, U> { 32 static constexpr int specialization(); 33 }; 34 35 template <Concept C, class U> constexpr int S<C, U>::specialization() { 36 return SPECIALIZATION_CONCEPT; 37 } 38 39 template <class T, class U> 40 requires(sizeof(T) == sizeof(int)) 41 constexpr int S<T, U>::specialization() { 42 return SPECIALIZATION_REQUIRES; 43 } 44 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); 48 49 } // namespace members 50 51 namespace enumerations { 52 53 template <class T, class U> struct S { 54 enum class E : int; 55 }; 56 57 template <class T, class U> enum class S<T, U>::E { Value = PRIMARY }; 58 59 template <Concept C, class U> struct S<C, U> { 60 enum class E : int; 61 }; 62 63 template <Concept C, class U> 64 enum class S<C, U>::E { 65 Value = SPECIALIZATION_CONCEPT 66 }; 67 68 template <class T, class U> 69 requires(sizeof(T) == sizeof(int)) 70 struct S<T, U> { 71 enum class E : int; 72 }; 73 74 template <class T, class U> 75 requires(sizeof(T) == sizeof(int)) 76 enum class S<T, U>::E { 77 Value = SPECIALIZATION_REQUIRES 78 }; 79 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); 85 86 } // namespace enumerations 87 88 namespace multiple_template_parameter_lists { 89 90 template <class Outer> 91 struct S { 92 template <class Inner> 93 static constexpr int primary(Inner); 94 }; 95 96 template <class Outer> 97 template <class Inner> 98 constexpr int S<Outer>::primary(Inner) { 99 return PRIMARY; 100 }; 101 102 template <Concept Outer> 103 struct S<Outer> { 104 template <class Inner> 105 static constexpr int specialization(Inner); 106 }; 107 108 template <Concept Outer> 109 template <class Inner> 110 constexpr int S<Outer>::specialization(Inner) { return SPECIALIZATION_CONCEPT; } 111 112 template <class Outer> 113 requires(sizeof(Outer) == sizeof(int)) 114 struct S<Outer> { 115 template <class Inner> 116 static constexpr int specialization(Inner); 117 }; 118 119 template <class Outer> 120 requires(sizeof(Outer) == sizeof(int)) 121 template <class Inner> 122 constexpr int S<Outer>::specialization(Inner) { return SPECIALIZATION_REQUIRES; } 123 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); 127 128 } // namespace multiple_template_parameter_lists 129 130 static constexpr int CONSTRAINED_METHOD_1 = 1; 131 static constexpr int CONSTRAINED_METHOD_2 = 2; 132 133 namespace constrained_members { 134 135 template <int> 136 struct S { 137 template <Concept C> 138 static constexpr int constrained_method(); 139 }; 140 141 template <> 142 template <Concept C> 143 constexpr int S<1>::constrained_method() { return CONSTRAINED_METHOD_1; } 144 145 template <> 146 template <Concept C> 147 constexpr int S<2>::constrained_method() { return CONSTRAINED_METHOD_2; } 148 149 static_assert(S<1>::constrained_method<XY>() == CONSTRAINED_METHOD_1); 150 static_assert(S<2>::constrained_method<XY>() == CONSTRAINED_METHOD_2); 151 152 153 template <class T1, class T2> 154 concept ConceptT1T2 = true; 155 156 template<typename T3> 157 struct S12 { 158 template<ConceptT1T2<T3> T4> 159 static constexpr int constrained_method(); 160 }; 161 162 template<> 163 template<ConceptT1T2<int> T5> 164 constexpr int S12<int>::constrained_method() { return CONSTRAINED_METHOD_1; } 165 166 template<> 167 template<ConceptT1T2<double> T5> 168 constexpr int S12<double>::constrained_method() { return CONSTRAINED_METHOD_2; } 169 170 static_assert(S12<int>::constrained_method<XY>() == CONSTRAINED_METHOD_1); 171 static_assert(S12<double>::constrained_method<XY>() == CONSTRAINED_METHOD_2); 172 173 } // namespace constrained members 174 175 namespace constrained_members_of_nested_types { 176 177 template <int> 178 struct S { 179 struct Inner0 { 180 struct Inner1 { 181 template <Concept C> 182 static constexpr int constrained_method(); 183 }; 184 }; 185 }; 186 187 template <> 188 template <Concept C> 189 constexpr int S<1>::Inner0::Inner1::constrained_method() { return CONSTRAINED_METHOD_1; } 190 191 template <> 192 template <Concept C> 193 constexpr int S<2>::Inner0::Inner1::constrained_method() { return CONSTRAINED_METHOD_2; } 194 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); 197 198 199 template <class T1, class T2> 200 concept ConceptT1T2 = true; 201 202 template<typename T3> 203 struct S12 { 204 struct Inner0 { 205 struct Inner1 { 206 template<ConceptT1T2<T3> T4> 207 static constexpr int constrained_method(); 208 }; 209 }; 210 }; 211 212 template<> 213 template<ConceptT1T2<int> T5> 214 constexpr int S12<int>::Inner0::Inner1::constrained_method() { return CONSTRAINED_METHOD_1; } 215 216 template<> 217 template<ConceptT1T2<double> T5> 218 constexpr int S12<double>::Inner0::Inner1::constrained_method() { return CONSTRAINED_METHOD_2; } 219 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); 222 223 } // namespace constrained_members_of_nested_types 224 225 namespace constrained_member_sfinae { 226 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; 233 } 234 235 template<class T> 236 static constexpr int constrained_method() requires (sizeof(int[N]) == 16); 237 }; 238 239 template<> 240 template<typename T> 241 constexpr int S<4>::constrained_method() requires (sizeof(int[4]) == 16) { 242 return CONSTRAINED_METHOD_2; 243 } 244 245 // Verify that there is no amiguity in this case. 246 static_assert(S<4>::constrained_method<double>() == CONSTRAINED_METHOD_2); 247 248 } // namespace constrained_member_sfinae 249 250 namespace requires_expression_references_members { 251 252 void accept1(int x); 253 void accept2(XY xy); 254 255 template <class T> struct S { 256 T Field = T(); 257 258 constexpr int constrained_method() 259 requires requires { accept1(Field); }; 260 261 constexpr int constrained_method() 262 requires requires { accept2(Field); }; 263 }; 264 265 template <class T> 266 constexpr int S<T>::constrained_method() 267 requires requires { accept1(Field); } { 268 return CONSTRAINED_METHOD_1; 269 } 270 271 template <class T> 272 constexpr int S<T>::constrained_method() 273 requires requires { accept2(Field); } { 274 return CONSTRAINED_METHOD_2; 275 } 276 277 static_assert(S<int>().constrained_method() == CONSTRAINED_METHOD_1); 278 static_assert(S<XY>().constrained_method() == CONSTRAINED_METHOD_2); 279 280 } // namespace requires_expression_references_members 281 282 namespace GH60231 { 283 284 template<typename T0> concept C = true; 285 286 template <typename T1> 287 struct S { 288 template <typename F1> requires C<S<T1>> 289 void foo1(F1 f); 290 291 template <typename F2> 292 void foo2(F2 f) requires C<S<T1>>; 293 294 template <typename F3> requires C<F3> 295 void foo3(F3 f); 296 }; 297 298 template <typename T2> 299 template <typename F4> requires C<S<T2>> 300 void S<T2>::foo1(F4 f) {} 301 302 template <typename T3> 303 template <typename F5> 304 void S<T3>::foo2(F5 f) requires C<S<T3>> {} 305 306 template <typename T4> 307 template <typename F6> requires C<F6> 308 void S<T4>::foo3(F6 f) {} 309 310 } // namespace GH60231 311 312 namespace GH62003 { 313 314 template <typename T0> concept Concept = true; 315 316 template <class T1> 317 struct S1 { 318 template <Concept C1> 319 static constexpr int foo(); 320 }; 321 template <class T2> 322 template <Concept C2> 323 constexpr int S1<T2>::foo() { return 1; } 324 325 template <Concept C3> 326 struct S2 { 327 template <class T3> 328 static constexpr int foo(); 329 }; 330 template <Concept C4> 331 template <class T4> 332 constexpr int S2<C4>::foo() { return 2; } 333 334 template <Concept C5> 335 struct S3 { 336 template <Concept C6> 337 static constexpr int foo(); 338 }; 339 template <Concept C7> 340 template <Concept C8> 341 constexpr int S3<C7>::foo() { return 3; } 342 343 static_assert(S1<int>::foo<int>() == 1); 344 static_assert(S2<int>::foo<int>() == 2); 345 static_assert(S3<int>::foo<int>() == 3); 346 347 } // namespace GH62003 348 349 namespace MultilevelTemplateWithPartialSpecialization { 350 template <typename> 351 concept Concept = true; 352 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 &); 359 }; 360 361 template <typename T3> 362 struct W0<T3, 0> { 363 template <typename T4> 364 requires (Concept<T4>) 365 void f(const T4 &); 366 }; 367 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 373 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 &); 382 }; 383 }; 384 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 &); 392 }; 393 }; 394 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 401 402 } // namespace MultilevelTemplateWithPartialSpecialization 403 404 namespace PR62697 { 405 template<typename> 406 concept c = true; 407 408 template<typename T> 409 struct s { 410 void f() requires c<void(T)>; 411 }; 412 413 template<typename T> 414 void s<T>::f() requires c<void(T)> { } 415 } 416 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() {} 421 } 422 423 namespace GH65810 { 424 template<typename Param> 425 concept TrivialConcept = 426 requires(Param param) { 427 (void)param; 428 }; 429 430 template <typename T> 431 struct Base { 432 class InnerClass; 433 }; 434 435 template <typename T> 436 class Base<T>::InnerClass { 437 template <typename Param> 438 requires TrivialConcept<Param> 439 int func(Param param) const; 440 }; 441 442 template <typename T> 443 template <typename Param> 444 requires TrivialConcept<Param> 445 int Base<T>::InnerClass::func(Param param) const { 446 return 0; 447 } 448 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; 457 }; 458 }; 459 }; 460 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; 467 } 468 469 } // namespace GH65810 470 471 namespace GH61763 { 472 template<typename T, typename U> 473 concept same_as = true; 474 475 template <class = void> 476 struct Foo { 477 template <same_as<void> Param> 478 friend struct Bar; 479 }; 480 481 template struct Foo<>; 482 483 template <same_as<void> Param> 484 struct Bar { 485 }; 486 487 488 template<typename T> 489 concept ok = true; 490 491 struct outer { 492 template<typename T> 493 requires ok<T> 494 struct foo {}; 495 }; 496 497 template<typename U> 498 struct bar { 499 template<typename T> 500 requires ok<T> 501 friend struct outer::foo; 502 }; 503 504 bar<int> x; 505 } // namespace GH61763 506 507 508 namespace GH74314 { 509 template <class T, class U> constexpr bool is_same_v = __is_same(T, U); 510 template <class T, class U> constexpr bool is_not_same_v = !__is_same(T, U); 511 512 template <class Result> 513 concept something_interesting = requires { 514 true; 515 requires is_same_v<int, Result>; 516 }; 517 518 template <class T> 519 struct X { // #defined-here 520 void foo() requires requires { requires is_not_same_v<T, int>; }; 521 void bar(decltype(requires { requires is_not_same_v<T, int>; })); 522 }; 523 524 template <class T> 525 void X<T>::foo() requires requires { requires something_interesting<T>; } {} 526 // expected-error@-1{{definition of 'foo' does not match any declaration}} 527 // expected-note@#defined-here{{defined here}} 528 // expected-note@-8{{member declaration nearly matches}} 529 530 template <class T> 531 void X<T>::foo() requires requires { requires is_not_same_v<T, int>; } {} // ok 532 533 template <class T> 534 void X<T>::bar(decltype(requires { requires something_interesting<T>; })) {} 535 // expected-error@-1{{definition of 'bar' does not match any declaration}} 536 // expected-note@#defined-here{{defined here}} 537 538 template <class T> 539 void X<T>::bar(decltype(requires { requires is_not_same_v<T, int>; })) {} 540 } // namespace GH74314 541 542 namespace GH56482 { 543 template <typename SlotMap> 544 concept slot_map_has_reserve = true; 545 546 template <typename T> struct Slot_map { 547 constexpr void reserve() const noexcept 548 requires slot_map_has_reserve<Slot_map>; 549 550 constexpr void reserve(int) const noexcept 551 requires slot_map_has_reserve<Slot_map<T>>; 552 }; 553 554 template <typename T> 555 constexpr void Slot_map<T>::reserve() const noexcept 556 requires slot_map_has_reserve<Slot_map<T>> 557 {} 558 559 template <typename T> 560 constexpr void Slot_map<T>::reserve(int) const noexcept 561 requires slot_map_has_reserve<Slot_map> 562 {} 563 } // namespace GH56482 564 565 namespace GH74447 { 566 template <typename T> struct S { 567 template <typename... U, int V> 568 void test(T target, U... value) 569 requires requires { 570 target; 571 sizeof...(value) == 1; 572 V == 2; 573 }; 574 }; 575 576 template <typename T> 577 template <typename... U, int V> 578 void S<T>::test(T target, U... value) 579 requires requires { 580 target; 581 sizeof...(value) == 1; 582 V == 2; 583 } 584 {} 585 } // namespace GH74447 586 587 namespace GH72557 { 588 589 template <typename...> 590 concept IsAnyOf = true; 591 592 template <class... DerTs> struct DerivedCollection { 593 template <class DerT> 594 requires IsAnyOf<DerTs...> 595 unsigned long index(); 596 }; 597 598 template <class... DerTs> 599 template <class DerT> 600 requires IsAnyOf<DerTs...> 601 unsigned long DerivedCollection<DerTs...>::index() {} 602 603 } // namespace GH72557 604 605 namespace GH101735 { 606 607 template <class, class> 608 concept True = true; 609 610 template <typename T> 611 class A { 612 template <typename... Ts> 613 void method(Ts&... ts) 614 requires requires (T t) { 615 { t.method(static_cast<Ts &&>(ts)...) } -> True<void>; 616 }; 617 }; 618 619 template <typename T> 620 template <typename... Ts> 621 void A<T>::method(Ts&... ts) 622 requires requires (T t) { 623 { t.method(static_cast<Ts &&>(ts)...) } -> True<void>; 624 } {} 625 626 } 627 628 namespace GH63782 { 629 // GH63782 was also fixed by PR #80594, so let's add a test for it. 630 631 template<bool... Vals> 632 constexpr bool All = (Vals && ...); 633 634 template<bool... Bs> 635 class Class { 636 template<typename> 637 requires All<Bs...> 638 void Foo(); 639 }; 640 641 template<bool... Bs> 642 template<typename> 643 requires All<Bs...> 644 void Class<Bs...>::Foo() { 645 }; 646 647 } // namespace GH63782 648 649 namespace eve { 650 // Reduced from the "eve" project 651 652 template <typename... Ts> 653 struct tuple { 654 template <int I0> requires(I0 <= sizeof...(Ts)) 655 constexpr auto split(); 656 }; 657 658 template <typename... Ts> 659 template <int I0> 660 requires(I0 <= sizeof...(Ts)) 661 constexpr auto tuple<Ts...>::split(){ 662 return 0; 663 } 664 665 int foo() { 666 tuple<int, float> x; 667 return x.split<0>(); 668 } 669 670 } // namespace eve 671 672 namespace GH93099 { 673 674 // Issues with sizeof...(expr) 675 676 template <typename T = int> struct C { 677 template <int... N> 678 requires(sizeof...(N) > 0) 679 friend class NTTP; 680 681 template <class... Tp> 682 requires(sizeof...(Tp) > 0) 683 friend class TP; 684 685 template <template <typename> class... TTp> 686 requires(sizeof...(TTp) > 0) 687 friend class TTP; 688 }; 689 690 template <int... N> 691 requires(sizeof...(N) > 0) 692 class NTTP; 693 694 template <class... Tp> 695 requires(sizeof...(Tp) > 0) 696 class TP; 697 698 template <template <typename> class... TTp> 699 requires(sizeof...(TTp) > 0) 700 class TTP; 701 702 C v; 703 704 } // namespace GH93099 705 706 namespace GH115098 { 707 708 template <typename... Ts> struct c { 709 template <typename T> 710 requires(sizeof...(Ts) > 0) 711 friend bool operator==(c, c); 712 }; 713 714 template <typename... Ts> struct d { 715 template <typename T> 716 requires(sizeof...(Ts) > 0) 717 friend bool operator==(d, d); 718 }; 719 720 template struct c<int>; 721 template struct d<int, int>; 722 723 } // namespace GH115098 724 725 namespace GH123441 { 726 727 struct buf { 728 constexpr buf(auto&&... initList) requires (sizeof...(initList) <= 8); 729 }; 730 731 constexpr buf::buf(auto&&... initList) requires (sizeof...(initList) <= 8) {} 732 733 template <class> 734 struct buffer { 735 constexpr buffer(auto&&... initList) requires (sizeof...(initList) <= 8); 736 }; 737 738 template <class T> 739 constexpr buffer<T>::buffer(auto&&... initList) requires (sizeof...(initList) <= 8) {} 740 741 template <class...> 742 struct foo { // expected-note {{foo defined here}} 743 constexpr foo(auto&&... initList) 744 requires (sizeof...(initList) <= 8); 745 }; 746 747 template <class... T> 748 constexpr foo<T...>::foo(auto&&... initList) // expected-error {{does not match any declaration}} 749 requires (sizeof...(T) <= 8) {} 750 751 } // namespace GH123441 752 753 namespace GH114685 { 754 755 template <typename T> struct ptr { 756 template <typename U> 757 friend ptr<U> make_item(auto &&args) 758 requires(sizeof(args) > 1); 759 }; 760 761 template <typename U> 762 ptr<U> make_item(auto &&args) 763 requires(sizeof(args) > 1) {} 764 765 ptr<char> p; 766 767 } // namespace GH114685 768 769 namespace GH123472 { 770 771 consteval bool fn() { return true; } 772 773 struct S { 774 template <typename T> 775 static consteval void mfn() requires (bool(&fn)); 776 }; 777 778 template <typename T> 779 consteval void S::mfn() requires (bool(&fn)) {} 780 781 } 782