// RUN: %clang_cc1 -std=c++17 -fsyntax-only -verify %s // C++20 [temp.spec] 13.9/6: // The usual access checking rules do not apply to names in a declaration // of an explicit instantiation or explicit specialization, with the // exception of names appearing in a function body, default argument, // base-clause, member-specification, enumerator-list, or static data member // or variable template initializer. // [Note : In particular, the template arguments and names used in the // function declarator(including parameter types, return types and exception // specifications) may be private types or objects that would normally not be // accessible. — end note] class A { // expected-note@+1 17{{implicitly declared private here}} template class B {}; // expected-note@+1 3{{implicitly declared private here}} static constexpr int num1 = 42; protected: // expected-note@+1 13{{declared protected here}} class C {}; // expected-note@+1 2{{declared protected here}} static constexpr int num2 = 43; static int num4; public: template class D {}; static constexpr int num3 = 44; }; int A::num4 = 44; class E : public A { // Declarations // expected-error@+1 {{is a private member of}} template > void func1(); template void func2(); template > void func3(); // expected-error@+1 {{is a private member of}} template A::B func4(); // expected-error@+1 {{is a private member of}} template A::B func5(); template class A::C func6(); template class A::D func7(); // expected-error@+1 2{{is a private member of}} template void func8(class A::B, int x = A::num1); template void func9(A::C, A::D, int = A::num3); // Specializations inside class declaration template <> void func1>() {} template <> void func2>() { } template <> void func3() { } template <> class A::B func4>() { return {}; } template <> A::B> func5>() { return {}; } template <> class A::C func6() { return {}; } template <> A::D func7() { return {}; } template <> void func8(class A::B, int) {} template <> void func9>(A::C, A::D>, int) {} // FIXME: Instantiations inside class declaration. // don't work correctly. }; // Definitions template void E::func1() {} template void E::func2() {} template void E::func3() {} // expected-error@+1 {{is a private member of}} template A::B E::func4() { return {}; } // expected-error@+1 {{is a private member of}} template A::B E::func5() { return {}; } template A::C E::func6() { return {}; } template A::D E::func7() { return {}; } // expected-error@+1 {{is a private member of}} template void E::func8(A::B, int) {} template void E::func9(A::C, A::D, int) {} // Specializations template <> void E::func1>() {} template <> void E::func2() {} template <> void E::func3>() { } template <> class A::B E::func4>() { return {}; } template <> A::B E::func5() { return {}; } template <> class A::C E::func6>() { return {}; } template <> A::D E::func7() { return {}; } template <> void E::func8(class A::B, int) {} template <> void E::func9(A::C, A::D, int) {} // Instantiations template <> void E::func1>(); template <> void E::func2(); template <> void E::func3>(); template <> class A::B E::func4>(); template <> A::B E::func5(); template <> class A::C E::func6>(); template <> A::D E::func7(); template <> void E::func8(class A::B, int); template <> void E::func9(A::C, A::D, int); //----------------------------------------------------------// // forward declarations // expected-error@+1 {{is a protected member of}} template class A::C func1(); // expected-error@+1 {{is a private member of}} template A::B func2(); template A::D func3(); // expected-error@+1 {{is a private member of}} template class A::B func4(); template void func5(); // expected-error@+1 {{is a private member of}} template void func6(); // expected-error@+1 {{is a protected member of}} template void func7(); // expected-error@+1 {{is a protected member of}} template void func8(int x = sizeof(A::C)); // expected-error@+1 {{is a private member of}} template void func9(int x = A::num1); // expected-error@+2 {{is a private member of}} // expected-error@+1 {{is a protected member of}} template void func10(class A::B, int x = A::num2); // expected-error@+1 {{is a protected member of}} template void func11(class A::C, A::D, int = A::num3); template void func12(); template void func13(); template void func14(); template