[clang] [Clang] Fix a crash when using ctad with a template template parameter. (PR #161488)

Corentin Jabot via cfe-commits cfe-commits at lists.llvm.org
Thu Oct 2 03:14:15 PDT 2025


https://github.com/cor3ntin updated https://github.com/llvm/llvm-project/pull/161488

>From 6d84b97524b0565846a69b0e56c05234c8311d0f Mon Sep 17 00:00:00 2001
From: Corentin Jabot <corentinjabot at gmail.com>
Date: Wed, 1 Oct 2025 10:02:28 +0200
Subject: [PATCH 1/2] [Clang] Fix a crash when using ctad with a template
 template parameter.

This fixes the crash reported in #130604.
It does not try to improve diagnostics or resolve CWG3003
(this will be explored separately).

Fixes #130604
---
 clang/docs/ReleaseNotes.rst                   |  1 +
 clang/lib/Sema/SemaTemplateDeductionGuide.cpp |  7 +++++--
 clang/test/SemaCXX/cxx20-ctad-type-alias.cpp  | 15 +++++++++++++++
 3 files changed, 21 insertions(+), 2 deletions(-)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index b1ddfa070318b..c6ee1e282a008 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -437,6 +437,7 @@ Bug Fixes to C++ Support
 - Fix the result of `__builtin_is_implicit_lifetime` for types with a user-provided constructor. (#GH160610)
 - Correctly deduce return types in ``decltype`` expressions. (#GH160497) (#GH56652) (#GH116319) (#GH161196)
 - Fixed a crash in the pre-C++23 warning for attributes before a lambda declarator (#GH161070).
+- Fix a crash when attempting to deduce a deduction guide from a non deducible template template parameter. (#130604)
 
 Bug Fixes to AST Handling
 ^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/clang/lib/Sema/SemaTemplateDeductionGuide.cpp b/clang/lib/Sema/SemaTemplateDeductionGuide.cpp
index 3d54d1eb4373a..4cad4a02c190f 100644
--- a/clang/lib/Sema/SemaTemplateDeductionGuide.cpp
+++ b/clang/lib/Sema/SemaTemplateDeductionGuide.cpp
@@ -1428,8 +1428,11 @@ void Sema::DeclareImplicitDeductionGuides(TemplateDecl *Template,
     DeclareImplicitDeductionGuidesForTypeAlias(*this, AliasTemplate, Loc);
     return;
   }
-  if (CXXRecordDecl *DefRecord =
-          cast<CXXRecordDecl>(Template->getTemplatedDecl())->getDefinition()) {
+  CXXRecordDecl *DefRecord =
+      llvm::dyn_cast_or_null<CXXRecordDecl>(Template->getTemplatedDecl());
+  if (!DefRecord)
+    return;
+  if (DefRecord->getDefinition()) {
     if (TemplateDecl *DescribedTemplate =
             DefRecord->getDescribedClassTemplate())
       Template = DescribedTemplate;
diff --git a/clang/test/SemaCXX/cxx20-ctad-type-alias.cpp b/clang/test/SemaCXX/cxx20-ctad-type-alias.cpp
index 2f1817d0ca7eb..fd1a5c01233d5 100644
--- a/clang/test/SemaCXX/cxx20-ctad-type-alias.cpp
+++ b/clang/test/SemaCXX/cxx20-ctad-type-alias.cpp
@@ -586,3 +586,18 @@ Baz a{};
 static_assert(__is_same(decltype(a), A<A<int>>));
 
 } // namespace GH133132
+
+namespace GH130604 {
+template <typename T> struct A {
+    A(T);
+};
+
+template <typename T, template <typename> class TT = A> using Alias = TT<T>; // #gh130604-alias
+template <typename T> using Alias2 = Alias<T>;
+
+Alias2 a(42);
+// expected-error at -1 {{no viable constructor or deduction guide for deduction of template arguments of 'Alias2'}}
+Alias  b(42);
+// expected-error at -1 {{alias template 'Alias' requires template arguments; argument deduction only allowed for class templates or alias template}}
+// expected-note@#gh130604-alias {{template is declared here}}
+}

>From 1dcc02cd98f3b1e5767139251e18e210dc8bd956 Mon Sep 17 00:00:00 2001
From: Corentin Jabot <corentinjabot at gmail.com>
Date: Thu, 2 Oct 2025 12:09:50 +0200
Subject: [PATCH 2/2] fix tests

---
 clang/lib/Sema/SemaTemplateDeductionGuide.cpp | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/clang/lib/Sema/SemaTemplateDeductionGuide.cpp b/clang/lib/Sema/SemaTemplateDeductionGuide.cpp
index 4cad4a02c190f..fe673eac8fcfa 100644
--- a/clang/lib/Sema/SemaTemplateDeductionGuide.cpp
+++ b/clang/lib/Sema/SemaTemplateDeductionGuide.cpp
@@ -1429,12 +1429,12 @@ void Sema::DeclareImplicitDeductionGuides(TemplateDecl *Template,
     return;
   }
   CXXRecordDecl *DefRecord =
-      llvm::dyn_cast_or_null<CXXRecordDecl>(Template->getTemplatedDecl());
+      dyn_cast_or_null<CXXRecordDecl>(Template->getTemplatedDecl());
   if (!DefRecord)
     return;
-  if (DefRecord->getDefinition()) {
+  if (const CXXRecordDecl *Definition = DefRecord->getDefinition()) {
     if (TemplateDecl *DescribedTemplate =
-            DefRecord->getDescribedClassTemplate())
+            Definition->getDescribedClassTemplate())
       Template = DescribedTemplate;
   }
 



More information about the cfe-commits mailing list