aorlov updated this revision to Diff 311431. aorlov added reviewers: mibintc, hokein. aorlov added subscribers: mibintc, hokein. aorlov added a comment.
Updated. Disabled function parameters access checking in function templates. Hi, @broadwaylamb, @rsmith, @saar.raz, @doug.gregor, @mibintc, @hokein. Could you please look at this patch? Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D92024/new/ https://reviews.llvm.org/D92024 Files: clang/include/clang/Sema/DelayedDiagnostic.h clang/lib/Parse/ParseDecl.cpp clang/lib/Parse/ParseDeclCXX.cpp clang/lib/Parse/ParseTemplate.cpp clang/test/CXX/class.access/class.friend/p1.cpp clang/test/CXX/drs/dr1xx.cpp clang/test/CXX/temp/temp.spec/func.spec.cpp clang/test/CXX/temp/temp.spec/part.spec.cpp
Index: clang/test/CXX/temp/temp.spec/part.spec.cpp =================================================================== --- /dev/null +++ clang/test/CXX/temp/temp.spec/part.spec.cpp @@ -0,0 +1,640 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// C++20 [temp.class.spec] 17.6.5/10: +// The usual access checking rules do not apply to non-dependent names used +// to specify template arguments of the simple-template-id of the partial +// specialization. + +// TODO: add test cases for `enum` + +// class for tests +class TestClass { +public: + class PublicClass {}; + template <class T> class TemplatePublicClass {}; + + using AliasPublicClass = unsigned char; + + void publicFunc(); + void publicFuncOverloaded(); + void publicFuncOverloaded(int); + + static void publicStaticFunc(); + static void publicStaticFuncOverloaded(); + static void publicStaticFuncOverloaded(int); + + static constexpr int publicStaticInt = 42; + +protected: + // expected-note@+1 8{{declared protected here}} + class ProtectedClass {}; + template <class T> class TemplateProtectedClass {}; + + // expected-note@+1 2{{declared protected here}} + using AliasProtectedClass = const char; + + // expected-note@+1 3{{declared protected here}} + void protectedFunc(); + void protectedFuncOverloaded(); + void protectedFuncOverloaded(int); + + // expected-note@+1 2{{declared protected here}} + static void protectedStaticFunc(); + // expected-note@+1 2{{declared protected here}} + static void protectedStaticFuncOverloaded(); + static void protectedStaticFuncOverloaded(int); + + // expected-note@+1 2{{declared protected here}} + static constexpr int protectedStaticInt = 43; + +private: + // expected-note@+1 10{{declared private here}} + class PrivateClass {}; + // expected-note@+1 {{declared private here}} + template <class T> class TemplatePrivateClass {}; + + using AliasPrivateClass = char *; + + void privateFunc(); + void privateFuncOverloaded(); + void privateFuncOverloaded(int); + + static void privateStaticFunc(); + static void privateStaticFuncOverloaded(); + static void privateStaticFuncOverloaded(int); + + static constexpr int privateStaticInt = 44; +}; + +void globalFunction() {} + +//----------------------------------------------------------// + +// template declarations for explicit instantiations +template <typename T> class IT1 {}; +template <typename T1, typename T2> class IT2 {}; +template <int X> class IT3 {}; +template <void (TestClass::*)()> class IT4 {}; +template <void (*)()> class IT5 {}; +template <typename T> class IT6 { + template <typename NT> class NIT1 {}; +}; +template <typename T1, typename T2> class IT7 {}; +template <void (TestClass::*)(), int X> class IT8 {}; +template <typename T, void (*)()> class IT9 {}; + +// explicit instantiations + +// public +template class IT1<TestClass::PublicClass>; +template struct IT1<TestClass::TemplatePublicClass<int>>; +template class IT1<TestClass::AliasPublicClass>; +template struct IT2<TestClass::PublicClass, TestClass::PublicClass>; +template class IT3<TestClass::publicStaticInt>; +template struct IT4<&TestClass::publicFunc>; +template class IT4<&TestClass::publicFuncOverloaded>; +template class IT5<&TestClass::publicStaticFunc>; +template class IT5<&TestClass::publicStaticFuncOverloaded>; +template class IT5<&globalFunction>; +template class IT6<TestClass::PublicClass>::template NIT1<TestClass::PublicClass>; +template class IT7<TestClass::AliasPublicClass, TestClass::PublicClass>; +template struct IT7<TestClass::PublicClass, TestClass::TemplatePublicClass<TestClass::PublicClass>>; +template class IT8<&TestClass::publicFunc, TestClass::publicStaticInt>; +template class IT8<&TestClass::publicFuncOverloaded, TestClass::publicStaticInt>; +template class IT9<TestClass::PublicClass, &TestClass::publicStaticFunc>; +template class IT9<TestClass::PublicClass, &TestClass::publicStaticFuncOverloaded>; +template class IT9<TestClass::PublicClass, &globalFunction>; + +// protected +template class IT1<TestClass::ProtectedClass>; +template struct IT1<TestClass::TemplateProtectedClass<int>>; +template class IT1<TestClass::AliasProtectedClass>; +template struct IT2<TestClass::ProtectedClass, TestClass::ProtectedClass>; +template class IT3<TestClass::protectedStaticInt>; +template struct IT4<&TestClass::protectedFunc>; +template class IT4<&TestClass::protectedFuncOverloaded>; +template class IT5<&TestClass::protectedStaticFunc>; +template class IT5<&TestClass::protectedStaticFuncOverloaded>; +template class IT6<TestClass::ProtectedClass>::template NIT1<TestClass::ProtectedClass>; +template class IT7<TestClass::AliasProtectedClass, TestClass::ProtectedClass>; +template struct IT7<TestClass::ProtectedClass, TestClass::TemplateProtectedClass<TestClass::ProtectedClass>>; +template class IT8<&TestClass::protectedFunc, TestClass::protectedStaticInt>; +template class IT8<&TestClass::protectedFuncOverloaded, TestClass::protectedStaticInt>; +template class IT9<TestClass::ProtectedClass, &TestClass::protectedStaticFunc>; +template class IT9<TestClass::ProtectedClass, &TestClass::protectedStaticFuncOverloaded>; +template class IT9<TestClass::ProtectedClass, &globalFunction>; + +// private +template class IT1<TestClass::PrivateClass>; +template struct IT1<TestClass::TemplatePrivateClass<int>>; +template class IT1<TestClass::AliasPrivateClass>; +template struct IT2<TestClass::PrivateClass, TestClass::PrivateClass>; +template class IT3<TestClass::privateStaticInt>; +template struct IT4<&TestClass::privateFunc>; +template class IT4<&TestClass::privateFuncOverloaded>; +template class IT5<&TestClass::privateStaticFunc>; +template class IT5<&TestClass::privateStaticFuncOverloaded>; +template class IT6<TestClass::PrivateClass>::template NIT1<TestClass::PrivateClass>; +template class IT7<TestClass::AliasPrivateClass, TestClass::PrivateClass>; +template struct IT7<TestClass::PrivateClass, TestClass::TemplatePrivateClass<TestClass::PrivateClass>>; +template class IT8<&TestClass::privateFunc, TestClass::privateStaticInt>; +template class IT8<&TestClass::privateFuncOverloaded, TestClass::privateStaticInt>; +template class IT9<TestClass::PrivateClass, &TestClass::privateStaticFunc>; +template class IT9<TestClass::PrivateClass, &TestClass::privateStaticFuncOverloaded>; +template class IT9<TestClass::PrivateClass, &globalFunction>; + +//----------------------------------------------------------// + +// template declarations for full specializations +template <typename T> class CT1 {}; +template <typename T1, typename T2> class CT2 {}; +template <int X> class CT3 {}; +template <void (TestClass::*)()> class CT4 {}; +template <void (*)()> class CT5 {}; +template <typename T> class CT6 { + template <typename NT> class NCT1 {}; + template <typename NT> class NCT2; // forward declaration +}; + +// full specializations + +// public +template <> class CT1<TestClass::PublicClass>; +template <typename T> class CT1<TestClass::TemplatePublicClass<T>>; // not full but let it be here +template <> struct CT1<TestClass::TemplatePublicClass<int>>; +template <> class CT1<TestClass::AliasPublicClass>; +template <> struct CT2<TestClass::PublicClass, TestClass::PublicClass>; +template <> class CT3<TestClass::publicStaticInt>; +template <> struct CT4<&TestClass::publicFunc>; +template <> class CT4<&TestClass::publicFuncOverloaded>; +template <> struct CT5<&TestClass::publicStaticFunc>; +template <> class CT5<&TestClass::publicStaticFuncOverloaded>; +template <> class CT5<&globalFunction>; +template <> template <> class CT6<TestClass::PublicClass>::NCT1<TestClass::PublicClass>; + +template <> class CT1<TestClass::PublicClass> {}; +template <typename T> class CT1<TestClass::TemplatePublicClass<T>> {}; +template <> class CT1<TestClass::TemplatePublicClass<int>> {}; +template <> class CT1<TestClass::AliasPublicClass> {}; +template <> class CT2<TestClass::PublicClass, TestClass::PublicClass> {}; +template <> class CT3<TestClass::publicStaticInt> {}; +template <> class CT4<&TestClass::publicFunc> {}; +template <> class CT4<&TestClass::publicFuncOverloaded> {}; +template <> class CT5<&TestClass::publicStaticFunc> {}; +template <> class CT5<&TestClass::publicStaticFuncOverloaded> {}; +template <> class CT5<&globalFunction> {}; +template <> template <> class CT6<TestClass::PublicClass>::NCT1<TestClass::PublicClass> {}; +template <> template <typename NT> class CT6<TestClass::PublicClass>::NCT2 {}; // declaration + +// protected +template <> class CT1<TestClass::ProtectedClass>; +template <typename T> class CT1<TestClass::TemplateProtectedClass<T>>; // not full but let it be here +template <> class CT1<TestClass::TemplateProtectedClass<int>>; +template <> struct CT1<TestClass::AliasProtectedClass>; +template <> class CT2<TestClass::ProtectedClass, TestClass::ProtectedClass>; +template <> struct CT3<TestClass::protectedStaticInt>; +template <> class CT4<&TestClass::protectedFunc>; +template <> struct CT4<&TestClass::protectedFuncOverloaded>; +template <> class CT5<&TestClass::protectedStaticFunc>; +template <> class CT5<&TestClass::protectedStaticFuncOverloaded>; +template <> template <> class CT6<TestClass::ProtectedClass>::NCT1<TestClass::ProtectedClass>; + +template <> class CT1<TestClass::ProtectedClass> {}; +template <typename T> class CT1<TestClass::TemplateProtectedClass<T>> {}; // not full but let it be here +template <> class CT1<TestClass::TemplateProtectedClass<int>> {}; +template <> class CT1<TestClass::AliasProtectedClass> {}; +template <> class CT2<TestClass::ProtectedClass, TestClass::ProtectedClass> {}; +template <> class CT3<TestClass::protectedStaticInt> {}; +template <> class CT4<&TestClass::protectedFunc> {}; +template <> class CT4<&TestClass::protectedFuncOverloaded> {}; +template <> class CT5<&TestClass::protectedStaticFunc> {}; +template <> class CT5<&TestClass::protectedStaticFuncOverloaded> {}; +template <> template <> class CT6<TestClass::ProtectedClass>::NCT1<TestClass::ProtectedClass> {}; +template <> template <typename NT> class CT6<TestClass::ProtectedClass>::NCT2 {}; // declaration + +// private +template <> class CT1<TestClass::PrivateClass>; +template <typename T> class CT1<TestClass::TemplatePrivateClass<T>>; // not full but let it be here +template <> struct CT1<TestClass::TemplatePrivateClass<int>>; +template <> class CT1<TestClass::AliasPrivateClass>; +template <> struct CT2<TestClass::PrivateClass, TestClass::PrivateClass>; +template <> class CT3<TestClass::privateStaticInt>; +template <> struct CT4<&TestClass::privateFunc>; +template <> class CT4<&TestClass::privateFuncOverloaded>; +template <> class CT5<&TestClass::privateStaticFunc>; +template <> class CT5<&TestClass::privateStaticFuncOverloaded>; +template <> template <> class CT6<TestClass::PrivateClass>::NCT1<TestClass::PrivateClass>; + +template <> class CT1<TestClass::PrivateClass> {}; +template <typename T> class CT1<TestClass::TemplatePrivateClass<T>> {}; // not full but let it be here +template <> class CT1<TestClass::TemplatePrivateClass<int>> {}; +template <> class CT1<TestClass::AliasPrivateClass> {}; +template <> class CT2<TestClass::PrivateClass, TestClass::PrivateClass> {}; +template <> class CT3<TestClass::privateStaticInt> {}; +template <> class CT4<&TestClass::privateFunc> {}; // PR37424 +template <> class CT4<&TestClass::privateFuncOverloaded> {}; // PR37424 +template <> class CT5<&TestClass::privateStaticFunc> {}; +template <> class CT5<&TestClass::privateStaticFuncOverloaded> {}; +template <> template <> class CT6<TestClass::PrivateClass>::NCT1<TestClass::PrivateClass> {}; +template <> template <typename NT> class CT6<TestClass::PrivateClass>::NCT2 {}; // declaration + +//----------------------------------------------------------// + +// template declarations for full final specializations +template <typename T> class FCT1 {}; +template <typename T1, typename T2> class FCT2 {}; +template <int X> class FCT3 {}; +template <void (TestClass::*)()> class FCT4 {}; +template <void (*)()> class FCT5 {}; +template <typename T> class FCT6 { + template <typename NT> class NCT1 {}; + template <typename NT> class NCT2; // forward declaration +}; + +// full final specializations + +// public +template <> class FCT1<TestClass::PublicClass> final {}; +template <typename T> class FCT1<TestClass::TemplatePublicClass<T>> final {}; // not full but let it be here +template <> struct FCT1<TestClass::TemplatePublicClass<int>> final {}; +template <> class FCT1<TestClass::AliasPublicClass> final {}; +template <> struct FCT2<TestClass::PublicClass, TestClass::PublicClass> final {}; +template <> class FCT3<TestClass::publicStaticInt> final {}; +template <> struct FCT4<&TestClass::publicFunc> final {}; +template <> class FCT4<&TestClass::publicFuncOverloaded> final {}; +template <> class FCT5<&TestClass::publicStaticFunc> final {}; +template <> class FCT5<&TestClass::publicStaticFuncOverloaded> final {}; +template <> class FCT5<&globalFunction> final {}; +template <> template <> class FCT6<TestClass::PublicClass>::NCT1<TestClass::PublicClass> final {}; +template <> template <typename NT> class FCT6<TestClass::PublicClass>::NCT2 final {}; + +// protected +template <> class FCT1<TestClass::ProtectedClass> final {}; +template <typename T> class FCT1<TestClass::TemplateProtectedClass<T>> final {}; // not full but let it be here +template <> struct FCT1<TestClass::TemplateProtectedClass<int>> final {}; +template <> class FCT1<TestClass::AliasProtectedClass> final {}; +template <> struct FCT2<TestClass::ProtectedClass, TestClass::ProtectedClass> final {}; +template <> class FCT3<TestClass::protectedStaticInt> final {}; +template <> struct FCT4<&TestClass::protectedFunc> final {}; +template <> class FCT4<&TestClass::protectedFuncOverloaded> final {}; +template <> class FCT5<&TestClass::protectedStaticFunc> final {}; +template <> class FCT5<&TestClass::protectedStaticFuncOverloaded> final {}; +template <> template <> class FCT6<TestClass::ProtectedClass>::NCT1<TestClass::ProtectedClass> final {}; +template <> template <typename NT> class FCT6<TestClass::ProtectedClass>::NCT2 final {}; + +// private +template <> class FCT1<TestClass::PrivateClass> final {}; +template <typename T> class FCT1<TestClass::TemplatePrivateClass<T>> final {}; // not full but let it be here +template <> struct FCT1<TestClass::TemplatePrivateClass<int>> final {}; +template <> class FCT1<TestClass::AliasPrivateClass> final {}; +template <> struct FCT2<TestClass::PrivateClass, TestClass::PrivateClass> final {}; +template <> class FCT3<TestClass::privateStaticInt> final {}; +template <> struct FCT4<&TestClass::privateFunc> final {}; +template <> class FCT4<&TestClass::privateFuncOverloaded> final {}; +template <> class FCT5<&TestClass::privateStaticFunc> final {}; +template <> class FCT5<&TestClass::privateStaticFuncOverloaded> final {}; +template <> template <> class FCT6<TestClass::PrivateClass>::NCT1<TestClass::PrivateClass> final {}; +template <> template <typename NT> class FCT6<TestClass::PrivateClass>::NCT2 final {}; + +//----------------------------------------------------------// + +// template declarations for full specializations with parents +class P1 {}; +template <typename T> class PCT1 {}; +template <typename T1, typename T2> class PCT2 {}; +template <int X> class PCT3 {}; +template <void (TestClass::*)()> class PCT4 {}; +template <void (*)()> class PCT5 {}; +template <typename T> class PCT6 { + // expected-note@+1 3{{implicitly declared private here}} + template <typename NT> class NPCT1 {}; + // expected-note@+1 {{template is declared here}} + template <typename NT> class NPCT2; // forward declaration +}; + +// full specializations with parents + +// protected + public +template <> class PCT1<TestClass::PublicClass> : P1 {}; +template <typename T> class PCT1<TestClass::TemplatePublicClass<T>> : PCT2<TestClass::PublicClass, TestClass::PublicClass> {}; // not full but let it be here +template <> struct PCT1<TestClass::TemplatePublicClass<int>> : PCT1<TestClass::AliasPublicClass> {}; +template <> class PCT1<TestClass::AliasProtectedClass> : PCT2<TestClass::PublicClass, int> {}; +template <> struct PCT2<TestClass::ProtectedClass, TestClass::PublicClass> : PCT3<TestClass::publicStaticInt> {}; +template <> class PCT3<TestClass::protectedStaticInt> : PCT4<&TestClass::publicFunc> {}; +template <> struct PCT4<&TestClass::protectedFunc> : PCT5<&TestClass::publicStaticFunc> {}; +template <> class PCT4<&TestClass::publicFuncOverloaded> : PCT5<&TestClass::publicStaticFuncOverloaded> {}; +template <> class PCT5<&TestClass::protectedStaticFunc> : PCT5<&TestClass::publicStaticFuncOverloaded> {}; +// expected-error@+1 {{is a private member of}} +template <> class PCT5<&TestClass::protectedStaticFuncOverloaded> : PCT6<TestClass::PublicClass>::NPCT1<TestClass::PublicClass> {}; +// expected-error@+2 {{is a protected member of}} +// expected-error@+1 {{is a private member of}} +template <> class PCT5<&globalFunction> : PCT6<TestClass::ProtectedClass>::NPCT1<int> {}; +template <> template <typename NT> class PCT6<TestClass::PublicClass>::NPCT2 : P1 {}; // declaration +template <> template <> class PCT6<TestClass::PublicClass>::NPCT1<TestClass::ProtectedClass> : PCT6<TestClass::PublicClass>::template NPCT2<int> {}; + +// protected + private +template <> class PCT1<TestClass::PrivateClass> : P1 {}; +// expected-error@+2 {{is a protected member of}} +// expected-error@+1 {{is a private member of}} +template <typename T> class PCT1<TestClass::TemplatePrivateClass<T>> : PCT2<TestClass::PrivateClass, TestClass::ProtectedClass> {}; // not full but let it be here +// expected-error@+1 {{is a protected member of}} +template <> class PCT1<TestClass::TemplatePrivateClass<int>> : PCT1<TestClass::AliasProtectedClass> {}; +// expected-error@+2 {{is a protected member of}} +// expected-error@+1 {{is a private member of}} +template <> class PCT1<TestClass::AliasPrivateClass> : PCT2<TestClass::ProtectedClass, TestClass::PrivateClass> {}; +// expected-error@+1 {{is a protected member of}} +template <> class PCT2<TestClass::PrivateClass, TestClass::PrivateClass> : PCT3<TestClass::protectedStaticInt> {}; +// expected-error@+1 {{is a protected member of}} +template <> class PCT3<TestClass::privateStaticInt> : PCT4<&TestClass::protectedFunc> {}; +// expected-error@+1 {{is a protected member of}} +template <> class PCT4<&TestClass::privateFunc> : PCT5<&TestClass::protectedStaticFunc> {}; +// expected-error@+1 {{is a protected member of}} +template <> class PCT4<&TestClass::privateFuncOverloaded> : PCT5<&TestClass::protectedStaticFuncOverloaded> {}; +template <> class PCT5<&TestClass::privateStaticFunc> : P1 {}; +// expected-error@+2 {{implicit instantiation of undefined template}} +// expected-error@+1 {{is a private member of}} +template <> template <> class PCT6<TestClass::PrivateClass>::NPCT1<TestClass::PrivateClass> : PCT6<TestClass::PrivateClass>::NPCT2<int> {}; +// expected-error@+1 3{{is a private member of}} +template <> class PCT5<&TestClass::privateStaticFuncOverloaded> : PCT6<TestClass::PrivateClass>::NPCT1<TestClass::PrivateClass> {}; +template <> template <typename NT> class PCT6<TestClass::PrivateClass>::NPCT2 : P1 {}; // declaration + +//----------------------------------------------------------// + +// template declarations for partial specializations +template <typename T1, typename T2> class CTT1 {}; +template <typename T1, typename T2, typename T3> class CTT2 {}; +template <typename T, int X> class CTT3 {}; +template <typename T, void (TestClass::*)()> class CTT4 {}; +template <typename T, void (*)()> class CTT5 {}; +template <typename T1, typename T2> class CTT6 { + template <typename NT> class NCT1 {}; + template <typename NT> class NCT2; // forward declaration + template <typename NT1, typename NT2> class NCT3 {}; + template <typename NT1, typename NT2> class NCT4; // forward declaration +}; + +// partial specializations + +// public +template <typename T> class CTT1<T, TestClass::PublicClass> {}; +template <typename T> class CTT1<T, TestClass::TemplatePublicClass<T>> {}; +template <typename T> struct CTT1<T, TestClass::TemplatePublicClass<int>> {}; +template <typename T> class CTT1<T, TestClass::AliasPublicClass> {}; +template <typename T> struct CTT2<T, TestClass::PublicClass, TestClass::PublicClass> {}; +template <typename T> struct CTT2<TestClass::PublicClass, T, TestClass::PublicClass> {}; +template <typename T> class CTT2<TestClass::PublicClass, TestClass::PublicClass, T> {}; +template <typename T> class CTT3<T, TestClass::publicStaticInt> {}; +template <typename T> class CTT4<T, &TestClass::publicFunc> {}; +template <typename T> class CTT4<T, &TestClass::publicFuncOverloaded> {}; +template <typename T> class CTT5<T, &TestClass::publicStaticFunc> {}; +template <typename T> class CTT5<T, &TestClass::publicStaticFuncOverloaded> {}; +template <typename T> class CTT5<T, &globalFunction> {}; +// expected-error@+1 {{cannot specialize a dependent template}} +template <typename T1> template <typename T2> class CTT6<T1, TestClass::PublicClass>::template NCT1<T2 *> {}; +template <typename T1, typename T2> template <typename T3> class CTT6<T1, T2>::NCT1<T3 *> {}; +template <typename T1, typename T2> template <typename T3> class CTT6<T1, T2>::NCT2 {}; // declaration +template <typename T1, typename T2> template <typename T3> class CTT6<T1, T2>::NCT2<T3 *> {}; +template <typename T1, typename T2> template <typename T3> class CTT6<T1, T2>::NCT3<T3, TestClass::PublicClass> {}; +// expected-error@+1 {{cannot specialize a dependent template}} +template <typename T1> template <typename T2> class CTT6<T1, TestClass::PublicClass>::template NCT3<T2, TestClass::PublicClass> {}; +template <typename T1, typename T2> template <typename T3, typename T4> class CTT6<T1, T2>::NCT4 {}; // declaration +template <typename T1, typename T2> template <typename T3> class CTT6<T1, T2>::NCT4<T3, TestClass::PublicClass> {}; +template <typename T> class CTT6<TestClass::PublicClass, T> { + template <typename T1, typename T2> class NCT3 {}; + template <typename T1, typename T2> class NCT4; +}; +template <typename T1> template <typename T2> class CTT6<TestClass::PublicClass, T1>::NCT3<T2, TestClass::PublicClass> {}; +template <typename T1> template <typename, typename> class CTT6<TestClass::PublicClass, T1>::NCT4 {}; +template <typename T1> template <typename T2> class CTT6<TestClass::PublicClass, T1>::NCT4<T2, TestClass::PublicClass> {}; + +// protected + +template <typename T> class CTT1<T, TestClass::ProtectedClass> {}; +template <typename T> class CTT1<T, TestClass::TemplateProtectedClass<T>> {}; +template <typename T> struct CTT1<T, TestClass::TemplateProtectedClass<int>> {}; +template <typename T> class CTT1<T, TestClass::AliasProtectedClass> {}; +template <typename T> struct CTT2<T, TestClass::ProtectedClass, TestClass::ProtectedClass> {}; +template <typename T> class CTT2<TestClass::ProtectedClass, T, TestClass::ProtectedClass> {}; +template <typename T> struct CTT2<TestClass::ProtectedClass, TestClass::ProtectedClass, T> {}; +template <typename T> class CTT3<T, TestClass::protectedStaticInt> {}; +template <typename T> class CTT4<T, &TestClass::protectedFunc> {}; +template <typename T> class CTT4<T, &TestClass::protectedFuncOverloaded> {}; +template <typename T> class CTT5<T, &TestClass::protectedStaticFunc> {}; +template <typename T> class CTT5<T, &TestClass::protectedStaticFuncOverloaded> {}; +// expected-error@+1 {{cannot specialize a dependent template}} +template <typename T1> template <typename T2> class CTT6<T1, TestClass::ProtectedClass>::template NCT1<T2 *> {}; +template <typename T1, typename T2> template <typename T3> class CTT6<T1, T2>::NCT3<T3, TestClass::ProtectedClass> {}; +// expected-error@+1 {{cannot specialize a dependent template}} +template <typename T1> template <typename T2> class CTT6<T1, TestClass::ProtectedClass>::template NCT3<T2, TestClass::ProtectedClass> {}; +template <typename T1, typename T2> template <typename T3> class CTT6<T1, T2>::NCT4<T3, TestClass::ProtectedClass> {}; +template <typename T> class CTT6<TestClass::ProtectedClass, T> { + template <typename T1, typename T2> class NCT3 {}; + template <typename T1, typename T2> class NCT4; +}; +template <typename T1> template <typename T2> class CTT6<TestClass::ProtectedClass, T1>::NCT3<T2, TestClass::ProtectedClass> {}; +template <typename T1> template <typename, typename> class CTT6<TestClass::ProtectedClass, T1>::NCT4 {}; +template <typename T1> template <typename T2> class CTT6<TestClass::ProtectedClass, T1>::NCT4<T2, TestClass::ProtectedClass> {}; + +// private + +template <typename T> class CTT1<T, TestClass::PrivateClass> {}; +template <typename T> class CTT1<T, TestClass::TemplatePrivateClass<T>> {}; +template <typename T> struct CTT1<T, TestClass::TemplatePrivateClass<int>> {}; +template <typename T> class CTT1<T, TestClass::AliasPrivateClass> {}; +template <typename T> struct CTT2<T, TestClass::PrivateClass, TestClass::PrivateClass> {}; +template <typename T> class CTT2<TestClass::PrivateClass, T, TestClass::PrivateClass> {}; +template <typename T> struct CTT2<TestClass::PrivateClass, TestClass::PrivateClass, T> {}; +template <typename T> class CTT3<T, TestClass::privateStaticInt> {}; +template <typename T> class CTT4<T, &TestClass::privateFunc> {}; +template <typename T> class CTT4<T, &TestClass::privateFuncOverloaded> {}; +template <typename T> class CTT5<T, &TestClass::privateStaticFunc> {}; +template <typename T> class CTT5<T, &TestClass::privateStaticFuncOverloaded> {}; +// expected-error@+1 {{cannot specialize a dependent template}} +template <typename T1> template <typename T2> class CTT6<T1, TestClass::PrivateClass>::template NCT1<T2 *> {}; +template <typename T1, typename T2> template <typename T3> class CTT6<T1, T2>::NCT3<T3, TestClass::PrivateClass> {}; +// expected-error@+1 {{cannot specialize a dependent template}} +template <typename T1> template <typename T2> class CTT6<T1, TestClass::PrivateClass>::template NCT3<T2, TestClass::PrivateClass> {}; +template <typename T1, typename T2> template <typename T3> class CTT6<T1, T2>::NCT4<T3, TestClass::PrivateClass> {}; +template <typename T> class CTT6<TestClass::PrivateClass, T> { + template <typename T1, typename T2> class NCT3 {}; + template <typename T1, typename T2> class NCT4; +}; +template <typename T1> template <typename T2> class CTT6<TestClass::PrivateClass, T1>::NCT3<T2, TestClass::PrivateClass> {}; +template <typename T1> template <typename, typename> class CTT6<TestClass::PrivateClass, T1>::NCT4 {}; +template <typename T1> template <typename T2> class CTT6<TestClass::PrivateClass, T1>::NCT4<T2, TestClass::PrivateClass> {}; + +//----------------------------------------------------------// + +// template declarations for final partial specializations +template <typename T1, typename T2> class FCTT1 {}; +template <typename T1, typename T2, typename T3> class FCTT2 {}; +template <typename T, int X> class FCTT3 {}; +template <typename T, void (TestClass::*)()> class FCTT4 {}; +template <typename T, void (*)()> class FCTT5 {}; +template <typename T1, typename T2> class FCTT6 { + template <typename NT> class NCT1 {}; + template <typename NT> class NCT2; // forward declaration + template <typename NT1, typename NT2> class NCT3 {}; + template <typename NT1, typename NT2> class NCT4; // forward declaration +}; + +// partial final specializations + +// public +template <typename T> class FCTT1<T, TestClass::PublicClass> final {}; +template <typename T> class FCTT1<T, TestClass::TemplatePublicClass<T>> final {}; +template <typename T> struct FCTT1<T, TestClass::TemplatePublicClass<int>> final {}; +template <typename T> class FCTT1<T, TestClass::AliasPublicClass> final {}; +template <typename T> struct FCTT2<T, TestClass::PublicClass, TestClass::PublicClass> final {}; +template <typename T> class FCTT2<TestClass::PublicClass, T, TestClass::PublicClass> final {}; +template <typename T> struct FCTT2<TestClass::PublicClass, TestClass::PublicClass, T> final {}; +template <typename T> class FCTT3<T, TestClass::publicStaticInt> final {}; +template <typename T> class FCTT4<T, &TestClass::publicFunc> final {}; +template <typename T> class FCTT4<T, &TestClass::publicFuncOverloaded> final {}; +template <typename T> class FCTT5<T, &TestClass::publicStaticFunc> final {}; +template <typename T> class FCTT5<T, &TestClass::publicStaticFuncOverloaded> final {}; +template <typename T> class FCTT5<T, &globalFunction> final {}; +// expected-error@+1 {{cannot specialize a dependent template}} +template <typename T1> template <typename T2> class FCTT6<T1, TestClass::PublicClass>::template NCT1<T2 *> final {}; +template <typename T1, typename T2> template <typename T3> class FCTT6<T1, T2>::NCT1<T3 *> final {}; +template <typename T1, typename T2> template <typename T3> class FCTT6<T1, T2>::NCT2 final {}; // declaration +template <typename T1, typename T2> template <typename T3> class FCTT6<T1, T2>::NCT2<T3 *> final {}; +template <typename T1, typename T2> template <typename T3> class FCTT6<T1, T2>::NCT3<T3, TestClass::PublicClass> final {}; +// expected-error@+1 {{cannot specialize a dependent template}} +template <typename T1> template <typename T2> class FCTT6<T1, TestClass::PublicClass>::template NCT3<T2, TestClass::PublicClass> final {}; +template <typename T1, typename T2> template <typename T3, typename T4> class FCTT6<T1, T2>::NCT4 final {}; // declaration +template <typename T1, typename T2> template <typename T3> class FCTT6<T1, T2>::NCT4<T3, TestClass::PublicClass> final {}; +template <typename T> class FCTT6<TestClass::PublicClass, T> { + template <typename T1, typename T2> class NCT3 final {}; + template <typename T1, typename T2> class NCT4; +}; +template <typename T1> template <typename T2> class FCTT6<TestClass::PublicClass, T1>::NCT3<T2, TestClass::PublicClass> final {}; +template <typename T1> template <typename, typename> class FCTT6<TestClass::PublicClass, T1>::NCT4 final {}; +template <typename T1> template <typename T2> class FCTT6<TestClass::PublicClass, T1>::NCT4<T2, TestClass::PublicClass> final {}; + +// protected + +template <typename T> class FCTT1<T, TestClass::ProtectedClass> final {}; +template <typename T> class FCTT1<T, TestClass::TemplateProtectedClass<T>> final {}; +template <typename T> struct FCTT1<T, TestClass::TemplateProtectedClass<int>> final {}; +template <typename T> class FCTT1<T, TestClass::AliasProtectedClass> final {}; +template <typename T> struct FCTT2<T, TestClass::ProtectedClass, TestClass::ProtectedClass> final {}; +template <typename T> class FCTT2<TestClass::ProtectedClass, T, TestClass::ProtectedClass> final {}; +template <typename T> struct FCTT2<TestClass::ProtectedClass, TestClass::ProtectedClass, T> final {}; +template <typename T> class FCTT3<T, TestClass::protectedStaticInt> final {}; +template <typename T> class FCTT4<T, &TestClass::protectedFunc> final {}; +template <typename T> class FCTT4<T, &TestClass::protectedFuncOverloaded> final {}; +template <typename T> class FCTT5<T, &TestClass::protectedStaticFunc> final {}; +template <typename T> class FCTT5<T, &TestClass::protectedStaticFuncOverloaded> final {}; +// expected-error@+1 {{cannot specialize a dependent template}} +template <typename T1> template <typename T2> class FCTT6<T1, TestClass::ProtectedClass>::template NCT1<T2 *> final {}; +template <typename T1, typename T2> template <typename T3> class FCTT6<T1, T2>::NCT3<T3, TestClass::ProtectedClass> final {}; +// expected-error@+1 {{cannot specialize a dependent template}} +template <typename T1> template <typename T2> class FCTT6<T1, TestClass::ProtectedClass>::template NCT3<T2, TestClass::ProtectedClass> final {}; +template <typename T1, typename T2> template <typename T3> class FCTT6<T1, T2>::NCT4<T3, TestClass::ProtectedClass> final {}; +template <typename T> class FCTT6<TestClass::ProtectedClass, T> { + template <typename T1, typename T2> class NCT3 final {}; + template <typename T1, typename T2> class NCT4; +}; +template <typename T1> template <typename T2> class FCTT6<TestClass::ProtectedClass, T1>::NCT3<T2, TestClass::ProtectedClass> final {}; +template <typename T1> template <typename, typename> class FCTT6<TestClass::ProtectedClass, T1>::NCT4 final {}; +template <typename T1> template <typename T2> class FCTT6<TestClass::ProtectedClass, T1>::NCT4<T2, TestClass::ProtectedClass> final {}; + +// private + +template <typename T> class FCTT1<T, TestClass::PrivateClass> final {}; +template <typename T> class FCTT1<T, TestClass::TemplatePrivateClass<T>> final {}; +template <typename T> struct FCTT1<T, TestClass::TemplatePrivateClass<int>> final {}; +template <typename T> class FCTT1<T, TestClass::AliasPrivateClass> final {}; +template <typename T> struct FCTT2<T, TestClass::PrivateClass, TestClass::PrivateClass> final {}; +template <typename T> class FCTT2<TestClass::PrivateClass, T, TestClass::PrivateClass> final {}; +template <typename T> struct FCTT2<TestClass::PrivateClass, TestClass::PrivateClass, T> final {}; +template <typename T> class FCTT3<T, TestClass::privateStaticInt> final {}; +template <typename T> class FCTT4<T, &TestClass::privateFunc> final {}; +template <typename T> class FCTT4<T, &TestClass::privateFuncOverloaded> final {}; +template <typename T> class FCTT5<T, &TestClass::privateStaticFunc> final {}; +template <typename T> class FCTT5<T, &TestClass::privateStaticFuncOverloaded> final {}; +// expected-error@+1 {{cannot specialize a dependent template}} +template <typename T1> template <typename T2> class FCTT6<T1, TestClass::PrivateClass>::template NCT1<T2 *> final {}; +template <typename T1, typename T2> template <typename T3> class FCTT6<T1, T2>::NCT3<T3, TestClass::PrivateClass> final {}; +// expected-error@+1 {{cannot specialize a dependent template}} +template <typename T1> template <typename T2> class FCTT6<T1, TestClass::PrivateClass>::template NCT3<T2, TestClass::PrivateClass> final {}; +template <typename T1, typename T2> template <typename T3> class FCTT6<T1, T2>::NCT4<T3, TestClass::PrivateClass> final {}; +template <typename T> class FCTT6<TestClass::PrivateClass, T> { + template <typename T1, typename T2> class NCT3 final {}; + template <typename T1, typename T2> class NCT4; +}; +template <typename T1> template <typename T2> class FCTT6<TestClass::PrivateClass, T1>::NCT3<T2, TestClass::PrivateClass> final {}; +template <typename T1> template <typename, typename> class FCTT6<TestClass::PrivateClass, T1>::NCT4 final {}; +template <typename T1> template <typename T2> class FCTT6<TestClass::PrivateClass, T1>::NCT4<T2, TestClass::PrivateClass> final {}; + +//----------------------------------------------------------// + +// template declarations for partial specializations with parents +template <typename T1, typename T2> class PCTT1 {}; +template <typename T1, typename T2, typename T3> class PCTT2 {}; +template <typename T, int X> class PCTT3 {}; +template <typename T, void (TestClass::*)()> class PCTT4 {}; +template <typename T, void (*)()> class PCTT5 {}; +template <typename T1, typename T2> class PCTT6 { + template <typename NT> class NCT1 {}; + template <typename NT> class NCT2; // forward declaration + template <typename NT1, typename NT2> class NCT3 {}; + template <typename NT1, typename NT2> class NCT4; // forward declaration +}; + +// partial specializations with parents + +// protected + public +template <typename T> class PCTT1<T, TestClass::PublicClass> : P1 {}; +template <typename T> struct PCTT1<T, TestClass::TemplatePublicClass<T>> : PCTT2<T, TestClass::PublicClass, TestClass::PublicClass> {}; // not full but let it be here +template <typename T> class PCTT1<T, TestClass::TemplatePublicClass<int>> : PCTT1<T, TestClass::AliasPublicClass> {}; +// expected-error@+1 {{is a protected member of}} +template <typename T> class PCTT1<T, TestClass::TemplatePublicClass<TestClass::TemplateProtectedClass<T>>> : PCTT1<T, TestClass::ProtectedClass> {}; +template <typename T> struct PCTT1<T, TestClass::AliasProtectedClass> : PCTT2<T, TestClass::PublicClass, int> {}; +template <typename T> class PCTT2<T, TestClass::ProtectedClass, TestClass::PublicClass> : PCTT3<T, TestClass::publicStaticInt> {}; +template <typename T> class PCTT3<T, TestClass::protectedStaticInt> : PCTT4<T, &TestClass::publicFunc> {}; +template <typename T> struct PCTT4<T, &TestClass::protectedFunc> : PCTT5<T, &TestClass::publicStaticFunc> {}; +template <typename T> class PCTT4<T, &TestClass::publicFuncOverloaded> : PCTT5<T, &TestClass::publicStaticFuncOverloaded> {}; +template <typename T> class PCTT5<T, &TestClass::protectedStaticFunc> : PCTT5<T, &TestClass::publicStaticFuncOverloaded> {}; +template <typename T> class PCTT5<T, &TestClass::protectedStaticFuncOverloaded> : PCTT6<T, TestClass::PublicClass>::template NCT1<TestClass::PublicClass> {}; +// expected-error@+1 {{is a protected member of}} +template <typename T> class PCTT5<T, &globalFunction> : PCTT6<T, TestClass::ProtectedClass>::template NCT1<int> {}; +// expected-error@+1 {{is a protected member of}} +template <typename T1, typename T2> template <typename T3> class PCTT6<T1, T2>::NCT2 : PCTT4<T1, &TestClass::protectedFunc> {}; // declaration +template <typename T1, typename T2> template <typename T3> class PCTT6<T1, T2>::NCT2<T3 *> : P1 {}; +// expected-error@+2 {{cannot specialize a dependent template}} +// expected-error@+1 {{is a protected member of}} +template <typename T> template <typename NT> class PCTT6<T, TestClass::ProtectedClass>::template NCT1<NT *> : PCTT6<T, TestClass::ProtectedClass>::template NCT2<int> {}; + +// protected + private +template <typename T> class PCTT1<T, TestClass::PrivateClass> : P1 {}; +// expected-error@+2 {{is a protected member of}} +// expected-error@+1 {{is a private member of}} +template <typename T> struct PCTT1<T, TestClass::TemplatePrivateClass<T>> : PCTT2<T, TestClass::PrivateClass, TestClass::ProtectedClass> {}; // not full but let it be here +// expected-error@+1 {{is a protected member of}} +template <typename T> class PCTT1<T, TestClass::TemplatePrivateClass<int>> : PCTT1<T, TestClass::AliasProtectedClass> {}; +// expected-error@+2 {{is a protected member of}} +// expected-error@+1 {{is a private member of}} +template <typename T> struct PCTT1<T, TestClass::AliasPrivateClass> : PCTT2<T, TestClass::ProtectedClass, TestClass::PrivateClass> {}; +// expected-error@+1 {{is a protected member of}} +template <typename T> class PCTT2<T, TestClass::PrivateClass, TestClass::TemplatePrivateClass<T>> : PCTT3<T, TestClass::protectedStaticInt> {}; +// expected-error@+1 {{is a protected member of}} +template <typename T> class PCTT3<T, TestClass::privateStaticInt> : PCTT4<T, &TestClass::protectedFunc> {}; +// expected-error@+1 {{is a protected member of}} +template <typename T> struct PCTT4<T, &TestClass::privateFunc> : PCTT5<T, &TestClass::protectedStaticFunc> {}; +// expected-error@+1 {{is a protected member of}} +template <typename T> class PCTT4<T, &TestClass::privateFuncOverloaded> : PCTT5<T, &TestClass::protectedStaticFuncOverloaded> {}; +template <typename T> class PCTT5<T, &TestClass::privateStaticFunc> : P1 {}; +// expected-error@+2 {{cannot specialize a dependent template}} +// expected-error@+1 {{is a private member of}} +template <typename T> class PCTT6<T, TestClass::PrivateClass>::template PCTT1<TestClass::PrivateClass> : PCTT6<T, TestClass::PrivateClass>::template NCT2<int> {}; +// expected-error@+1 {{is a private member of}} +template <typename T> class PCTT5<T, &TestClass::privateStaticFuncOverloaded> : PCTT6<T, T>::template NCT1<TestClass::PrivateClass> {}; +template <typename T> class PCTT6<TestClass::PrivateClass, T> { + template <typename T1, typename T2> class NCT3 final {}; + template <typename T1, typename T2> class NCT4; +}; +template <typename T1> template <typename, typename> class PCTT6<TestClass::PrivateClass, T1>::NCT4 {}; +// expected-error@+1 2{{is a private member of}} +template <typename T1> template <typename T2> struct PCTT6<TestClass::PrivateClass, T1>::template NCT3<T2, TestClass::TemplatePrivateClass<TestClass::TemplateProtectedClass<TestClass::PublicClass>>> : PCTT6<TestClass::PrivateClass, T1>::NCT4<T2, TestClass::TemplatePrivateClass<int>> {}; Index: clang/test/CXX/temp/temp.spec/func.spec.cpp =================================================================== --- /dev/null +++ clang/test/CXX/temp/temp.spec/func.spec.cpp @@ -0,0 +1,142 @@ +// RUN: %clang_cc1 -std=c++17 -fsyntax-only -verify %s + +// C++20 [temp.explicit] 17.8/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. + +class A { + // expected-note@+1 14{{implicitly declared private here}} + template <typename T> class B {}; + // expected-note@+1 {{implicitly declared private here}} + static constexpr int num1 = 42; + +protected: + // expected-note@+1 9{{declared protected here}} + class C {}; + // expected-note@+1 {{declared protected here}} + static constexpr int num2 = 43; + static int num4; + +public: + template <typename T> class D {}; + static constexpr int num3 = 44; +}; +int A::num4 = 44; + +class E : public A { + template <typename T> A::C func1(); + // expected-error@+1 {{is a private member of}} + template <typename T> A::B<T> func2(); + template <typename T> A::D<T> func3(); + // expected-error@+1 {{is a private member of}} + template <typename T> class A::B<int> func4(); + template <typename T> void func5(); + + template <> A::C func1<A::C>(); + // expected-error@+1 {{is a private member of}} + template <> A::B<A::C> func2<A::C>(); + template <> A::D<A::C> func3<A::C>(); + // expected-error@+1 {{is a private member of}} + template <> class A::B<int> func4<A::C>(); + template <> void func5<A::C>(); + // expected-error@+1 {{is a private member of}} + template <> void func5<A::B<int>>(); + template <> void func5<A::D<A::C>>(); + template <> void func5<int>(); +}; + +template <int *x> class StealClass { + friend int stealFunc() { return *x; } +}; + +template class StealClass<&A::num4>; +int stealFunc(); + +int stealFunc2() { + return stealFunc(); +} + +//----------------------------------------------------------// + +// forward declarations + +// expected-error@+1 {{is a protected member of}} +template <typename T> A::C func1(); +// expected-error@+1 {{is a private member of}} +template <typename T> A::B<T> func2(); +template <typename T> A::D<T> func3(); +// expected-error@+1 {{is a private member of}} +template <typename T> class A::B<int> func4(); +template <typename T> void func5(); +// expected-error@+1 {{is a private member of}} +template <int x = A::num1> void func6(); +// expected-error@+1 {{is a protected member of}} +template <int x = A::num2> void func7(); +template <typename T> void func8(int x = sizeof(A::C)); +template <typename T> void func9(int x = A::num1); +template <typename T> void func10(A::B<T>, int x = A::num2); +template <typename T> void func11(A::C, A::D<T>, int = A::num3); + +//----------------------------------------------------------// + +// definitions + +// expected-error@+1 2{{is a protected member of}} +template <typename T> A::C func1() { A::C x; } +// expected-error@+2 {{is a private member of}} +// expected-error@+1 {{is a protected member of}} +template <typename T> A::B<T> func2() { A::D<A::C> x; } +template <typename T> A::D<T> func3() { A::D<int> x; } +// expected-error@+2 2{{is a private member of}} +// expected-error@+1 {{is a protected member of}} +template <typename T> class A::B<int> func4() { A::B<A::C> x; } template <typename T> void func5() { + // expected-error@+2 {{is a private member of}} + // expected-error@+1 {{is a protected member of}} + A::B<A::D<A::C>> x; + // expected-error@+1 {{is a private member of}} + A::B<int> x2; +} +template <typename T> void func8(int x) {} +template <typename T> void func9(int x) {} +template <typename T> void func10(A::B<T>, int x) {} +template <typename T> void func11(A::C, A::D<T>, int) {} +template <typename T> void func12() {} +template <int x> void func13() {} +template <typename T, int x> void func14() {} +template <template <typename> typename T> void func15() {} + +//----------------------------------------------------------// + +// explicit specializations + +// expected-error@+1 {{is a protected member of}} +template <> A::C func1<A::C>(); +// expected-error@+2 {{is a private member of}} +// expected-error@+1 {{is a protected member of}} +template <> A::B<A::C> func2<A::C>(); +// expected-error@+1 {{is a protected member of}} +template <> A::D<A::C> func3<A::C>(); +// expected-error@+1 {{is a private member of}} +template <> class A::B<int> func4<A::C>(); +template <> void func5<A::C>(); +template <> void func5<A::B<int>>(); +template <> void func5<A::D<A::C>>(); +template <> void func5<int>(); +template <> void func8<A::C>(int x); +template <> void func9<decltype(A::num1)>(int); +template <> void func10<A::D<int>>(A::B<A::D<int>>, int); +template <> void func11<A::C>(A::C, A::D<A::C>, int); + +//----------------------------------------------------------// + +// explicit instantiations + +template void func12<A::C>(); +template void func13<A::num1>(); +template void func13<A::num2>(); +template void func13<A::num3>(); +template void func14<A::C, A::num1>(); +template void func15<A::B>(); Index: clang/test/CXX/drs/dr1xx.cpp =================================================================== --- clang/test/CXX/drs/dr1xx.cpp +++ clang/test/CXX/drs/dr1xx.cpp @@ -934,12 +934,12 @@ template <class T> void C<T>::g() {} class A { - class B {}; // expected-note {{here}} + class B {}; void f(); }; template void C<A::B>::f(); - template <> void C<A::B>::g(); // expected-error {{private}} + template <> void C<A::B>::g(); void A::f() { C<B> cb; Index: clang/test/CXX/class.access/class.friend/p1.cpp =================================================================== --- clang/test/CXX/class.access/class.friend/p1.cpp +++ clang/test/CXX/class.access/class.friend/p1.cpp @@ -287,9 +287,10 @@ template A::I g<A::I>(A::I i); A::I f2(A::I i = A::x) {} // expected-error 3 {{is a private member of}} - template<typename T> A::I g2(A::I i) { // expected-error 2 {{is a private member of}} + template <typename T> A::I g2(A::I i) { // expected-error {{is a private member of}} T t; } + template <> A::I g2<char>(A::I i) { return 0; } // expected-error {{is a private member of}} template A::I g2<A::I>(A::I i); } Index: clang/lib/Parse/ParseTemplate.cpp =================================================================== --- clang/lib/Parse/ParseTemplate.cpp +++ clang/lib/Parse/ParseTemplate.cpp @@ -259,6 +259,18 @@ return nullptr; } + // Turn off usual access checking for templates. + // Remove them from the pool of delayed diagnostics. + // We don't use `SuppressAccessChecks` here because + // it supresses ALL the dignostics kinds, but we need to keep some of them. + // For instance marked as unavailable: + // `class __attribute((unavailable)) UnavailableClass;` + if (TemplateInfo.Kind != ParsedTemplateInfo::NonTemplate) { + if (sema::DelayedDiagnosticPool *Pool = + getActions().DelayedDiagnostics.getCurrentPool()) + Pool->removeAllOfKind(sema::DelayedDiagnostic::DDKind::Access); + } + llvm::TimeTraceScope TimeScope("ParseTemplate", [&]() { return std::string(DeclaratorInfo.getIdentifier() != nullptr ? DeclaratorInfo.getIdentifier()->getName() Index: clang/lib/Parse/ParseDeclCXX.cpp =================================================================== --- clang/lib/Parse/ParseDeclCXX.cpp +++ clang/lib/Parse/ParseDeclCXX.cpp @@ -1422,8 +1422,7 @@ // Note that we don't suppress if this turns out to be an elaborated // type specifier. bool shouldDelayDiagsInTag = - (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation || - TemplateInfo.Kind == ParsedTemplateInfo::ExplicitSpecialization); + (TemplateInfo.Kind != ParsedTemplateInfo::NonTemplate); SuppressAccessChecks diagsFromTag(*this, shouldDelayDiagsInTag); ParsedAttributesWithRange attrs(AttrFactory); @@ -1770,14 +1769,6 @@ } } - // If this is an elaborated type specifier, and we delayed - // diagnostics before, just merge them into the current pool. - if (shouldDelayDiagsInTag) { - diagsFromTag.done(); - if (TUK == Sema::TUK_Reference) - diagsFromTag.redelay(); - } - if (!Name && !TemplateId && (DS.getTypeSpecType() == DeclSpec::TST_error || TUK != Sema::TUK_Definition)) { if (DS.getTypeSpecType() != DeclSpec::TST_error) { @@ -1950,6 +1941,14 @@ } } + // If this is an elaborated type specifier, and we delayed + // diagnostics before, just merge them into the current pool. + if (shouldDelayDiagsInTag) { + diagsFromTag.done(); + if (TUK == Sema::TUK_Reference) + diagsFromTag.redelay(); + } + // If there is a body, parse it and inform the actions module. if (TUK == Sema::TUK_Definition) { assert(Tok.is(tok::l_brace) || Index: clang/lib/Parse/ParseDecl.cpp =================================================================== --- clang/lib/Parse/ParseDecl.cpp +++ clang/lib/Parse/ParseDecl.cpp @@ -2998,7 +2998,7 @@ // the token as an identifier. if (getLangOpts().MSVCCompat && Tok.is(tok::kw__Atomic) && DS.getStorageClassSpec() == clang::DeclSpec::SCS_typedef && - !DS.hasTypeSpecifier() && GetLookAheadToken(1).is(tok::less)) + !DS.hasTypeSpecifier() && NextToken().is(tok::less)) Tok.setKind(tok::identifier); SourceLocation Loc = Tok.getLocation(); Index: clang/include/clang/Sema/DelayedDiagnostic.h =================================================================== --- clang/include/clang/Sema/DelayedDiagnostic.h +++ clang/include/clang/Sema/DelayedDiagnostic.h @@ -312,6 +312,14 @@ pool.Diagnostics.clear(); } + void removeAllOfKind(DelayedDiagnostic::DDKind Kind) { + Diagnostics.erase(std::remove_if(Diagnostics.begin(), Diagnostics.end(), + [Kind](const DelayedDiagnostic &DD) { + return DD.Kind == Kind; + }), + Diagnostics.end()); + } + using pool_iterator = SmallVectorImpl<DelayedDiagnostic>::const_iterator; pool_iterator pool_begin() const { return Diagnostics.begin(); }
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits