aorlov updated this revision to Diff 310416.
aorlov added a comment.

Simplify the patch.
@Quuxplusone,
Actually you've pushed me to some thinking of what more syntactic cases it 
could be. And I came to that we can get rid of this hack and simplify the patch 
pretty much. Hope, this fix will be more admissible.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D92024/new/

https://reviews.llvm.org/D92024

Files:
  clang/include/clang/Parse/Parser.h
  clang/lib/Parse/ParseDecl.cpp
  clang/lib/Parse/ParseDeclCXX.cpp
  clang/lib/Parse/ParseTemplate.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,121 @@
+// 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 num3;
+
+public:
+  template <typename T> class D {};
+};
+int A::num3 = 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::num3>;
+int stealFunc();
+
+int stealFunc2() {
+  return stealFunc();
+}
+
+//----------------------------------------------------------//
+
+// explicit specializations
+
+// 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();
+
+// 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;
+}
+
+// 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>();
+
+//----------------------------------------------------------//
+
+// explicit instantiations
+
+template <typename T> void func8() {}
+template <int x> void func9() {}
+template <typename T, int x> void func10() {}
+template <template <typename> typename T> void func11() {}
+
+template void func8<A::C>();
+template void func9<A::num1>();
+template void func9<A::num2>();
+template void func10<A::C, A::num1>();
+template void func11<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/lib/Parse/ParseTemplate.cpp
===================================================================
--- clang/lib/Parse/ParseTemplate.cpp
+++ clang/lib/Parse/ParseTemplate.cpp
@@ -245,6 +245,11 @@
   else
     DS.takeAttributesFrom(prefixAttrs);
 
+  const bool NeedSuppressAccessChecks =
+      (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation ||
+       TemplateInfo.Kind == ParsedTemplateInfo::ExplicitSpecialization);
+  SuppressAccessChecks SuppressAccessGuard(*this, NeedSuppressAccessChecks);
+
   // Parse the declarator.
   ParsingDeclarator DeclaratorInfo(*this, DS, (DeclaratorContext)Context);
   if (TemplateInfo.TemplateParams)
@@ -259,6 +264,9 @@
     return nullptr;
   }
 
+  if (NeedSuppressAccessChecks)
+    SuppressAccessGuard.done();
+
   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) ||
@@ -2292,8 +2291,8 @@
 
 /// isCXX11FinalKeyword - Determine whether the next token is a C++11
 /// 'final' or Microsoft 'sealed' contextual keyword.
-bool Parser::isCXX11FinalKeyword() const {
-  VirtSpecifiers::Specifier Specifier = isCXX11VirtSpecifier();
+bool Parser::isCXX11FinalKeyword(const Token &Tok) const {
+  VirtSpecifiers::Specifier Specifier = isCXX11VirtSpecifier(Tok);
   return Specifier == VirtSpecifiers::VS_Final ||
          Specifier == VirtSpecifiers::VS_GNU_Final ||
          Specifier == VirtSpecifiers::VS_Sealed;
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/Parse/Parser.h
===================================================================
--- clang/include/clang/Parse/Parser.h
+++ clang/include/clang/Parse/Parser.h
@@ -2846,7 +2846,8 @@
   void ParseOptionalCXX11VirtSpecifierSeq(VirtSpecifiers &VS, bool IsInterface,
                                           SourceLocation FriendLoc);
 
-  bool isCXX11FinalKeyword() const;
+  bool isCXX11FinalKeyword(const Token &Tok) const;
+  bool isCXX11FinalKeyword() const { return isCXX11FinalKeyword(Tok); }
 
   /// DeclaratorScopeObj - RAII object used in Parser::ParseDirectDeclarator to
   /// enter a new C++ declarator scope and exit it when the function is
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to