// RUN: %clang_cc1 -std=c++20 -verify %s static constexpr int PRIMARY = 0; static constexpr int SPECIALIZATION_CONCEPT = 1; static constexpr int SPECIALIZATION_REQUIRES = 2; template concept Concept = (sizeof(T) >= 2 * sizeof(int)); struct XY { int x; int y; }; namespace members { template struct S { static constexpr int primary(); }; template constexpr int S::primary() { return PRIMARY; }; template struct S { static constexpr int specialization(); }; template requires(sizeof(T) == sizeof(int)) struct S { static constexpr int specialization(); }; template constexpr int S::specialization() { return SPECIALIZATION_CONCEPT; } template requires(sizeof(T) == sizeof(int)) constexpr int S::specialization() { return SPECIALIZATION_REQUIRES; } static_assert(S::primary() == PRIMARY); static_assert(S::specialization() == SPECIALIZATION_CONCEPT); static_assert(S::specialization() == SPECIALIZATION_REQUIRES); } // namespace members namespace enumerations { template struct S { enum class E : int; }; template enum class S::E { Value = PRIMARY }; template struct S { enum class E : int; }; template enum class S::E { Value = SPECIALIZATION_CONCEPT }; template requires(sizeof(T) == sizeof(int)) struct S { enum class E : int; }; template requires(sizeof(T) == sizeof(int)) enum class S::E { Value = SPECIALIZATION_REQUIRES }; static_assert(static_cast(S::E::Value) == PRIMARY); static_assert(static_cast(S::E::Value) == SPECIALIZATION_CONCEPT); static_assert(static_cast(S::E::Value) == SPECIALIZATION_REQUIRES); } // namespace enumerations namespace multiple_template_parameter_lists { template struct S { template static constexpr int primary(Inner); }; template template constexpr int S::primary(Inner) { return PRIMARY; }; template struct S { template static constexpr int specialization(Inner); }; template template constexpr int S::specialization(Inner) { return SPECIALIZATION_CONCEPT; } template requires(sizeof(Outer) == sizeof(int)) struct S { template static constexpr int specialization(Inner); }; template requires(sizeof(Outer) == sizeof(int)) template constexpr int S::specialization(Inner) { return SPECIALIZATION_REQUIRES; } static_assert(S::primary("str") == PRIMARY); static_assert(S::specialization("str") == SPECIALIZATION_CONCEPT); static_assert(S::specialization("str") == SPECIALIZATION_REQUIRES); } // namespace multiple_template_parameter_lists static constexpr int CONSTRAINED_METHOD_1 = 1; static constexpr int CONSTRAINED_METHOD_2 = 2; namespace constrained_members { template struct S { template static constexpr int constrained_method(); }; template <> template constexpr int S<1>::constrained_method() { return CONSTRAINED_METHOD_1; } template <> template constexpr int S<2>::constrained_method() { return CONSTRAINED_METHOD_2; } static_assert(S<1>::constrained_method() == CONSTRAINED_METHOD_1); static_assert(S<2>::constrained_method() == CONSTRAINED_METHOD_2); template concept ConceptT1T2 = true; template struct S12 { template T4> static constexpr int constrained_method(); }; template<> template T5> constexpr int S12::constrained_method() { return CONSTRAINED_METHOD_1; } template<> template T5> constexpr int S12::constrained_method() { return CONSTRAINED_METHOD_2; } static_assert(S12::constrained_method() == CONSTRAINED_METHOD_1); static_assert(S12::constrained_method() == CONSTRAINED_METHOD_2); } // namespace constrained members namespace constrained_members_of_nested_types { template struct S { struct Inner0 { struct Inner1 { template static constexpr int constrained_method(); }; }; }; template <> template constexpr int S<1>::Inner0::Inner1::constrained_method() { return CONSTRAINED_METHOD_1; } template <> template constexpr int S<2>::Inner0::Inner1::constrained_method() { return CONSTRAINED_METHOD_2; } static_assert(S<1>::Inner0::Inner1::constrained_method() == CONSTRAINED_METHOD_1); static_assert(S<2>::Inner0::Inner1::constrained_method() == CONSTRAINED_METHOD_2); template concept ConceptT1T2 = true; template struct S12 { struct Inner0 { struct Inner1 { template T4> static constexpr int constrained_method(); }; }; }; template<> template T5> constexpr int S12::Inner0::Inner1::constrained_method() { return CONSTRAINED_METHOD_1; } template<> template T5> constexpr int S12::Inner0::Inner1::constrained_method() { return CONSTRAINED_METHOD_2; } static_assert(S12::Inner0::Inner1::constrained_method() == CONSTRAINED_METHOD_1); static_assert(S12::Inner0::Inner1::constrained_method() == CONSTRAINED_METHOD_2); } // namespace constrained_members_of_nested_types namespace constrained_member_sfinae { template struct S { template static constexpr int constrained_method() requires (sizeof(int[N * 1073741824 + 4]) == 16) { // expected-warning {{variable length arrays in C++ are a Clang extension}} \ expected-note {{value 4294967296 is outside the range of representable values of type 'int'}} \ expected-note {{while calculating associated constraint of template 'constrained_method' here}} return CONSTRAINED_METHOD_1; } template static constexpr int constrained_method() requires (sizeof(int[N]) == 16); }; template<> template constexpr int S<4>::constrained_method() requires (sizeof(int[4]) == 16) { return CONSTRAINED_METHOD_2; } // Verify that there is no amiguity in this case. static_assert(S<4>::constrained_method() == CONSTRAINED_METHOD_2); } // namespace constrained_member_sfinae namespace requires_expression_references_members { void accept1(int x); void accept2(XY xy); template struct S { T Field = T(); constexpr int constrained_method() requires requires { accept1(Field); }; constexpr int constrained_method() requires requires { accept2(Field); }; }; template constexpr int S::constrained_method() requires requires { accept1(Field); } { return CONSTRAINED_METHOD_1; } template constexpr int S::constrained_method() requires requires { accept2(Field); } { return CONSTRAINED_METHOD_2; } static_assert(S().constrained_method() == CONSTRAINED_METHOD_1); static_assert(S().constrained_method() == CONSTRAINED_METHOD_2); } // namespace requires_expression_references_members namespace GH60231 { template concept C = true; template struct S { template requires C> void foo1(F1 f); template void foo2(F2 f) requires C>; template requires C void foo3(F3 f); }; template template requires C> void S::foo1(F4 f) {} template template void S::foo2(F5 f) requires C> {} template template requires C void S::foo3(F6 f) {} } // namespace GH60231 namespace GH62003 { template concept Concept = true; template struct S1 { template static constexpr int foo(); }; template template constexpr int S1::foo() { return 1; } template struct S2 { template static constexpr int foo(); }; template template constexpr int S2::foo() { return 2; } template struct S3 { template static constexpr int foo(); }; template template constexpr int S3::foo() { return 3; } static_assert(S1::foo() == 1); static_assert(S2::foo() == 2); static_assert(S3::foo() == 3); } // namespace GH62003 namespace MultilevelTemplateWithPartialSpecialization { template concept Concept = true; namespace two_level { template struct W0 { template requires (Concept) void f(const T2 &); }; template struct W0 { template requires (Concept) void f(const T4 &); }; template template requires (Concept) inline void W0::f(const T4 &) {} } // namespace two_level namespace three_level { template struct W0 { template struct W1 { template requires (Concept) void f(const T3 &); }; }; template struct W0 { template struct W1 { template requires (Concept) void f(const T6 &); }; }; template template template requires (Concept) inline void W0::W1::f(const T9 &) {} } // namespace three_level } // namespace MultilevelTemplateWithPartialSpecialization namespace PR62697 { template concept c = true; template struct s { void f() requires c; }; template void s::f() requires c { } } namespace GH62272 { template concept A = true; template struct X { A auto f(); }; template A auto X::f() {} } namespace GH65810 { template concept TrivialConcept = requires(Param param) { (void)param; }; template struct Base { class InnerClass; }; template class Base::InnerClass { template requires TrivialConcept int func(Param param) const; }; template template requires TrivialConcept int Base::InnerClass::func(Param param) const { return 0; } template struct Outermost { struct Middle { template struct Innermost { template requires TrivialConcept int func(Param param) const; }; }; }; template template template requires TrivialConcept int Outermost::Middle::Innermost::func(Param param) const { return 0; } } // namespace GH65810 namespace GH61763 { template concept same_as = true; template struct Foo { template Param> friend struct Bar; }; template struct Foo<>; template Param> struct Bar { }; template concept ok = true; struct outer { template requires ok struct foo {}; }; template struct bar { template requires ok friend struct outer::foo; }; bar x; } // namespace GH61763 namespace GH74314 { template constexpr bool is_same_v = __is_same(T, U); template constexpr bool is_not_same_v = !__is_same(T, U); template concept something_interesting = requires { true; requires is_same_v; }; template struct X { void foo() requires requires { requires is_not_same_v; }; void bar(decltype(requires { requires is_not_same_v; })); }; template void X::foo() requires requires { requires something_interesting; } {} // expected-error@-1{{definition of 'foo' does not match any declaration}} // expected-note@*{{}} template void X::foo() requires requires { requires is_not_same_v; } {} // ok template void X::bar(decltype(requires { requires something_interesting; })) {} // expected-error@-1{{definition of 'bar' does not match any declaration}} template void X::bar(decltype(requires { requires is_not_same_v; })) {} } // namespace GH74314