[clang] 9dd2af0 - Fix CRTP partial specialization instantiation crash.

Erich Keane via cfe-commits cfe-commits at lists.llvm.org
Thu May 11 06:11:50 PDT 2023


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;
+  }
+}


        


More information about the cfe-commits mailing list