// RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify %s namespace Undefined { template struct A { template static constexpr int f(); // expected-note {{declared here}} template static const int x; // expected-note {{declared here}} template static const int x; // expected-note {{declared here}} template struct B; // expected-note {{template is declared here}} template struct B; // expected-note {{template is declared here}} }; template<> template constexpr int A::f() { return A::f(); } template<> template constexpr int A::x = A::x; template<> template constexpr int A::x = A::x; template<> template struct A::B { static constexpr int y = A::B::y; }; template<> template struct A::B { static constexpr int y = A::B::y; }; template<> template constexpr int A::f() { return 1; } template<> template constexpr int A::x = 1; template<> template constexpr int A::x = 2; template<> template struct A::B { static constexpr int y = 1; }; template<> template struct A::B { static constexpr int y = 2; }; static_assert(A::f() == 0); // expected-error {{static assertion expression is not an integral constant expression}} // expected-note@-1 {{undefined function 'f' cannot be used in a constant expression}} static_assert(A::x == 0); // expected-error {{static assertion expression is not an integral constant expression}} // expected-note@-1 {{initializer of 'x' is unknown}} static_assert(A::x == 0); // expected-error {{static assertion expression is not an integral constant expression}} // expected-note@-1 {{initializer of 'x' is unknown}} static_assert(A::B::y == 0); // expected-error {{implicit instantiation of undefined template 'Undefined::A::B'}} static_assert(A::B::y == 0); // expected-error {{implicit instantiation of undefined template 'Undefined::A::B'}} static_assert(A::f() == 1); static_assert(A::x == 1); static_assert(A::x == 2); static_assert(A::B::y == 1); static_assert(A::B::y == 2); } // namespace Undefined namespace Defined { template struct A { template static constexpr int f() { return 0; }; template static const int x = 0; template static const int x = 0; template struct B { static constexpr int y = 0; }; template struct B { static constexpr int y = 0; }; }; template<> template constexpr int A::f() { return A::f(); } template<> template constexpr int A::x = A::x; template<> template constexpr int A::x = A::x; template<> template struct A::B { static constexpr int y = A::B::y; }; template<> template struct A::B { static constexpr int y = A::B::y; }; template<> template constexpr int A::f() { return 1; } template<> template constexpr int A::x = 1; template<> template constexpr int A::x = 2; template<> template struct A::B { static constexpr int y = 1; }; template<> template struct A::B { static constexpr int y = 2; }; static_assert(A::f() == 0); static_assert(A::x == 0); static_assert(A::x == 0); static_assert(A::B::y == 0); static_assert(A::B::y == 0); static_assert(A::f() == 1); static_assert(A::x == 1); static_assert(A::x == 2); static_assert(A::B::y == 1); static_assert(A::B::y == 2); } // namespace Defined namespace Constrained { template struct A { // FIXME expected-note@-1 2{{defined here}} template requires V static constexpr int f(); // expected-note {{declared here}} // FIXME expected-note@-1 {{declared here}} template requires V static const int x; // expected-note {{declared here}} // FIXME expected-note@-2 2{{previous template declaration is here}} // FIXME expected-note@-2 {{declared here}} template requires V static const int x; // expected-note {{declared here}} // FIXME expected-note@-1 {{partial specialization matches}} template requires V struct B; // expected-note {{template is declared here}} // FIXME expected-note@-2 2{{previous template declaration is here}} // FIXME expected-note@-2 {{template is declared here}} template requires V struct B; // expected-note {{template is declared here}} // FIXME expected-note@-1 {{partial specialization matches}} }; template<> template requires V constexpr int A::f() { return A::f(); } // FIXME expected-error@-3 {{out-of-line definition of 'f' does not match any declaration in 'Constrained::A'}} template<> template requires V constexpr int A::x = A::x; // FIXME expected-error@-2 {{requires clause differs in template redeclaration}} template<> template requires V constexpr int A::x = A::x; // FIXME expected-note@-1 {{partial specialization matches}} template<> template requires V struct A::B { static constexpr int y = A::B::y; }; // FIXME expected-note@-3 {{partial specialization matches}} template<> template requires V struct A::B { static constexpr int y = A::B::y; }; // FIXME expected-error@-4 {{requires clause differs in template redeclaration}} template<> template requires V constexpr int A::f() { return 1; } // FIXME expected-error@-3 {{out-of-line definition of 'f' does not match any declaration in 'Constrained::A'}} template<> template requires V constexpr int A::x = 1; // FIXME expected-error@-2 {{requires clause differs in template redeclaration}} template<> template requires V constexpr int A::x = 2; template<> template requires V struct A::B { static constexpr int y = 1; }; // FIXME expected-error@-4 {{requires clause differs in template redeclaration}} template<> template requires V struct A::B { static constexpr int y = 2; }; static_assert(A::f() == 0); // expected-error {{static assertion expression is not an integral constant expression}} // expected-note@-1 {{undefined function 'f' cannot be used in a constant expression}} static_assert(A::x == 0); // expected-error {{static assertion expression is not an integral constant expression}} // expected-note@-1 {{initializer of 'x' is unknown}} static_assert(A::x == 0); // expected-error {{static assertion expression is not an integral constant expression}} // expected-note@-1 {{initializer of 'x' is unknown}} static_assert(A::B::y == 0); // expected-error {{implicit instantiation of undefined template 'Constrained::A::B'}} static_assert(A::B::y == 0); // expected-error {{implicit instantiation of undefined template 'Constrained::A::B'}} static_assert(A::f() == 1); // FIXME expected-error@-1 {{static assertion expression is not an integral constant expression}} // FIXME expected-note@-2 {{undefined function 'f' cannot be used in a constant expression}} static_assert(A::x == 1); // FIXME expected-error@-1 {{static assertion expression is not an integral constant expression}} // FIXME expected-note@-2 {{initializer of 'x' is unknown}} static_assert(A::x == 2); // FIXME expected-error@-1 {{ambiguous partial specializations of 'x'}} static_assert(A::B::y == 1); // FIXME expected-error@-1 {{implicit instantiation of undefined template 'Constrained::A::B'}} static_assert(A::B::y == 2); // FIXME expected-error@-1 {{ambiguous partial specializations of 'B'}} } // namespace Constrained namespace Dependent { template struct A { template static constexpr int f(); template static const int x; template struct B; }; template<> template constexpr int A<0>::f() { return A<1>::f(); } template<> template constexpr int A<1>::f() { return J; } template<> template constexpr int A<0>::x = A<1>::x; template<> template constexpr int A<1>::x = J; template<> template struct A<0>::B { static constexpr int y = A<1>::B::y; }; template<> template struct A<1>::B { static constexpr int y = J; }; static_assert(A<0>::f<2>() == 2); static_assert(A<0>::x<2> == 2); static_assert(A<0>::B<2>::y == 2); } // namespace Dependent