Author: Erich Keane Date: 2023-05-11T06:11:43-07:00 New Revision: 9dd2af0b4caeaa3d19d9f48891e59bc5e0877544
URL: https://github.com/llvm/llvm-project/commit/9dd2af0b4caeaa3d19d9f48891e59bc5e0877544 DIFF: https://github.com/llvm/llvm-project/commit/9dd2af0b4caeaa3d19d9f48891e59bc5e0877544.diff LOG: Fix CRTP partial specialization instantiation crash. Fixes #60778. When instantiating the body of a class template specialization that was instantiated from a partial specialization, we were incorrectly collecting template arguments from the primary template, which resulted in the template arguments list being inaccurate. In the example from the issue, we were trying to substitute the boolean 'false' into the type on Nested, which caused an assertion. Differential Revision: https://reviews.llvm.org/D150285 Added: Modified: clang/docs/ReleaseNotes.rst clang/lib/Sema/SemaTemplateInstantiate.cpp clang/test/SemaTemplate/partial-spec-instantiate.cpp Removed: ################################################################################ diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 8b6232a6b9e6f..7086d337304b1 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -391,6 +391,10 @@ Bug Fixes in This Version at the point where it is required. This fixes: (`#62224 <https://github.com/llvm/llvm-project/issues/62224>`_) and (`#62596 <https://github.com/llvm/llvm-project/issues/62596>`_) +- Fix an assertion when instantiating the body of a Class Template Specialization + when it had been instantiated from a partial template specialization with diff erent + template arguments on the containing class. This fixes: + (`#60778 <https://github.com/llvm/llvm-project/issues/60778>`_). Bug Fixes to Compiler Builtins ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp index 3d5da5f8d8284..32a8ba1a5c46d 100644 --- a/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -163,6 +163,14 @@ HandleClassTemplateSpec(const ClassTemplateSpecializationDecl *ClassTemplSpec, 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<ClassTemplatePartialSpecializationDecl *>()) + 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 index 369ff69aa3756..c457c03baba0f 100644 --- a/clang/test/SemaTemplate/partial-spec-instantiate.cpp +++ b/clang/test/SemaTemplate/partial-spec-instantiate.cpp @@ -134,3 +134,23 @@ namespace IgnorePartialSubstitution { _Static_assert(S::value, ""); } + +namespace GH60778 { + template <bool B = false> class ClassTemplate { + public: + template <typename T, typename = void> class Nested {}; + }; + + template <typename DerivedType> class Base {}; + + template <> + template <typename T> + class ClassTemplate<>::Nested<T> : public Base<ClassTemplate<>::Nested<T> > {}; + + 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<int> instantiation; + } +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits