diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -391,6 +391,10 @@ at the point where it is required. This fixes: (`#62224 `_) and (`#62596 `_) +- Fix an assertion when instantiating the body of a Class Template Specialization + when it had been instantiated from a partial template specialization with different + template arguments on the containing class. This fixes: + (`#60778 `_). Bug Fixes to Compiler Builtins ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp --- a/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -163,6 +163,14 @@ assert(ClassTemplSpec->getSpecializedTemplate() && "No class template?"); if (ClassTemplSpec->getSpecializedTemplate()->isMemberSpecialization()) return Response::Done(); + + // If this was instantiated from a partial template specialization, we need + // to get the next level of declaration context from the partial + // specialization, as the ClassTemplateSpecializationDecl's + // DeclContext/LexicalDeclContext will be for the primary template. + if (auto *InstFromPartialTempl = ClassTemplSpec->getSpecializedTemplateOrPartial() + .dyn_cast()) + return Response::ChangeDecl(InstFromPartialTempl->getLexicalDeclContext()); } return Response::UseNextDecl(ClassTemplSpec); } diff --git a/clang/test/SemaTemplate/partial-spec-instantiate.cpp b/clang/test/SemaTemplate/partial-spec-instantiate.cpp --- a/clang/test/SemaTemplate/partial-spec-instantiate.cpp +++ b/clang/test/SemaTemplate/partial-spec-instantiate.cpp @@ -134,3 +134,23 @@ _Static_assert(S::value, ""); } + +namespace GH60778 { + template class ClassTemplate { + public: + template class Nested {}; + }; + + template class Base {}; + + template <> + template + class ClassTemplate<>::Nested : public Base::Nested > {}; + + void use() { + // This should instantiate the body of Nested with the template arguments + // from the Partial Specialization. This would previously get confused and + // get the template arguments from the primary template instead. + ClassTemplate<>::Nested instantiation; + } +}