[clang] [Clang] Handle default template arguments for alias CTAD guides (PR #134807)
Younan Zhang via cfe-commits
cfe-commits at lists.llvm.org
Tue Apr 15 00:15:53 PDT 2025
https://github.com/zyn0217 updated https://github.com/llvm/llvm-project/pull/134807
>From 3f09d114d6c4c51bd879a19caaf1c73c531cfedd Mon Sep 17 00:00:00 2001
From: Younan Zhang <zyn7109 at gmail.com>
Date: Tue, 8 Apr 2025 16:16:53 +0800
Subject: [PATCH 1/2] [Clang] Handle default template arguments for alias CTAD
guides
It's possible that some deduced template arguments come from default
arguments, not just from the return type. So we need to recursively
visit the default arguments if the parameter is referenced, thereby the
template parameter referenced by the defualt arguments could come along
to the synthesized deduction guide.
---
clang/docs/ReleaseNotes.rst | 1 +
clang/lib/Sema/SemaTemplateDeductionGuide.cpp | 17 ++++++++
clang/test/SemaTemplate/deduction-guide.cpp | 39 +++++++++++++++++++
3 files changed, 57 insertions(+)
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 5217e04b5e83f..d9b1cd16a85d3 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -384,6 +384,7 @@ Bug Fixes to C++ Support
- Clang no longer crashes when trying to unify the types of arrays with
certain differences in qualifiers (this could happen during template argument
deduction or when building a ternary operator). (#GH97005)
+- Fixed type alias CTAD issues involving default template arguments. (#GH134471)
- The initialization kind of elements of structured bindings
direct-list-initialized from an array is corrected to direct-initialization.
- Clang no longer crashes when a coroutine is declared ``[[noreturn]]``. (#GH127327)
diff --git a/clang/lib/Sema/SemaTemplateDeductionGuide.cpp b/clang/lib/Sema/SemaTemplateDeductionGuide.cpp
index b4863cefc3fb4..30376ca774384 100644
--- a/clang/lib/Sema/SemaTemplateDeductionGuide.cpp
+++ b/clang/lib/Sema/SemaTemplateDeductionGuide.cpp
@@ -690,6 +690,23 @@ SmallVector<unsigned> TemplateParamsReferencedInTemplateArgumentList(
SemaRef.MarkUsedTemplateParameters(
DeducedArgs, TemplateParamsList->getDepth(), ReferencedTemplateParams);
+ auto MarkDefaultArgs = [&](auto *Param) {
+ if (!Param || !Param->hasDefaultArgument())
+ return;
+ SemaRef.MarkUsedTemplateParameters(
+ Param->getDefaultArgument().getArgument(),
+ TemplateParamsList->getDepth(), ReferencedTemplateParams);
+ };
+
+ for (unsigned Index = 0; Index < TemplateParamsList->size(); ++Index) {
+ if (!ReferencedTemplateParams[Index])
+ continue;
+ auto *Param = TemplateParamsList->getParam(Index);
+ MarkDefaultArgs(dyn_cast<TemplateTypeParmDecl>(Param));
+ MarkDefaultArgs(dyn_cast<NonTypeTemplateParmDecl>(Param));
+ MarkDefaultArgs(dyn_cast<TemplateTemplateParmDecl>(Param));
+ }
+
SmallVector<unsigned> Results;
for (unsigned Index = 0; Index < TemplateParamsList->size(); ++Index) {
if (ReferencedTemplateParams[Index])
diff --git a/clang/test/SemaTemplate/deduction-guide.cpp b/clang/test/SemaTemplate/deduction-guide.cpp
index 6db132ca37c7e..76b6cb051b7dd 100644
--- a/clang/test/SemaTemplate/deduction-guide.cpp
+++ b/clang/test/SemaTemplate/deduction-guide.cpp
@@ -771,3 +771,42 @@ D d(24);
// CHECK-NEXT: `-ParmVarDecl {{.+}} 'U'
} // namespace GH132616_DeductionGuide
+
+namespace GH133132 {
+
+template <class _Ty>
+struct A {};
+
+template <class T = int, class U = T>
+using AA = A<U>;
+
+AA a{};
+
+// CHECK-LABEL: Dumping GH133132::<deduction guide for AA>:
+// CHECK-NEXT: FunctionTemplateDecl {{.+}} implicit <deduction guide for AA>
+// CHECK-NEXT: |-TemplateTypeParmDecl {{.+}} class depth 0 index 0 T
+// CHECK-NEXT: | `-TemplateArgument type 'int'
+// CHECK-NEXT: | `-BuiltinType {{.+}} 'int'
+// CHECK-NEXT: |-TemplateTypeParmDecl {{.+}} class depth 0 index 1 U
+// CHECK-NEXT: | `-TemplateArgument type 'T':'type-parameter-0-0'
+// CHECK-NEXT: | `-TemplateTypeParmType {{.+}} 'T' dependent depth 0 index 0
+// CHECK-NEXT: | `-TemplateTypeParm {{.+}} 'T'
+// CHECK-NEXT: |-TypeTraitExpr {{.+}} 'bool' __is_deducible
+// CHECK-NEXT: | |-DeducedTemplateSpecializationType {{.+}} 'GH133132::AA' dependent
+// CHECK-NEXT: | | `-name: 'GH133132::AA'
+// CHECK-NEXT: | | `-TypeAliasTemplateDecl {{.+}} AA
+// CHECK-NEXT: | `-TemplateSpecializationType {{.+}} 'A<U>' dependent
+// CHECK-NEXT: | |-name: 'A':'GH133132::A' qualified
+// CHECK-NEXT: | | `-ClassTemplateDecl {{.+}} A
+// CHECK-NEXT: | `-TemplateArgument type 'U':'type-parameter-0-1'
+// CHECK-NEXT: | `-SubstTemplateTypeParmType {{.+}} 'U' sugar dependent class depth 0 index 0 _Ty
+// CHECK-NEXT: | |-FunctionTemplate {{.+}} '<deduction guide for A>'
+// CHECK-NEXT: | `-TemplateTypeParmType {{.+}} 'U' dependent depth 0 index 1
+// CHECK-NEXT: | `-TemplateTypeParm {{.+}} 'U'
+// CHECK-NEXT: |-CXXDeductionGuideDecl {{.+}} implicit <deduction guide for AA> 'auto () -> A<U>'
+// CHECK-NEXT: `-CXXDeductionGuideDecl {{.+}} implicit used <deduction guide for AA> 'auto () -> A<int>' implicit_instantiation
+// CHECK-NEXT: |-TemplateArgument type 'int'
+// CHECK-NEXT: | `-BuiltinType {{.+}} 'int'
+// CHECK-NEXT: `-TemplateArgument type 'int'
+// CHECK-NEXT: `-BuiltinType {{.+}} 'int'
+}
>From 0587264d403b26bbdb44bcb72ae6df2ec663a1a9 Mon Sep 17 00:00:00 2001
From: Younan Zhang <zyn7109 at gmail.com>
Date: Tue, 15 Apr 2025 15:14:10 +0800
Subject: [PATCH 2/2] Add tests for template/non-template parameters
---
clang/test/SemaTemplate/deduction-guide.cpp | 78 ++++++++++++++++++++-
1 file changed, 77 insertions(+), 1 deletion(-)
diff --git a/clang/test/SemaTemplate/deduction-guide.cpp b/clang/test/SemaTemplate/deduction-guide.cpp
index 76b6cb051b7dd..066c917537947 100644
--- a/clang/test/SemaTemplate/deduction-guide.cpp
+++ b/clang/test/SemaTemplate/deduction-guide.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -std=c++2a -verify -ast-dump -ast-dump-decl-types -ast-dump-filter "deduction guide" %s | FileCheck %s --strict-whitespace
+// RUN: %clang_cc1 -std=c++2a -verify -ast-dump -ast-dump-decl-types -ast-dump-filter "deduction guide" %s | FileCheck %s --strict-whitespace -dump-input=always
template<auto ...> struct X {};
template<template<typename X, X> typename> struct Y {};
@@ -809,4 +809,80 @@ AA a{};
// CHECK-NEXT: | `-BuiltinType {{.+}} 'int'
// CHECK-NEXT: `-TemplateArgument type 'int'
// CHECK-NEXT: `-BuiltinType {{.+}} 'int'
+
+template <template <class> class _X>
+struct B {};
+
+template <template <class> class _X = A, template <class> class _Y = _X>
+using BB = B<_Y>;
+
+BB b{};
+
+// CHECK-LABEL: Dumping GH133132::<deduction guide for BB>:
+// CHECK-NEXT: FunctionTemplateDecl {{.+}} implicit <deduction guide for BB>
+// CHECK-NEXT: |-TemplateTemplateParmDecl {{.+}} depth 0 index 0 _X
+// CHECK-NEXT: | |-TemplateTypeParmDecl {{.+}} class depth 0 index 0
+// CHECK-NEXT: | `-TemplateArgument {{.+}} template 'A':'GH133132::A' qualified
+// CHECK-NEXT: | `-ClassTemplateDecl {{.+}} A
+// CHECK-NEXT: |-TemplateTemplateParmDecl {{.+}} depth 0 index 1 _Y
+// CHECK-NEXT: | |-TemplateTypeParmDecl {{.+}} class depth 0 index 0
+// CHECK-NEXT: | `-TemplateArgument {{.+}} template '_X':'template-parameter-0-0' qualified
+// CHECK-NEXT: | `-TemplateTemplateParmDecl {{.+}} depth 0 index 0 _X
+// CHECK-NEXT: |-TypeTraitExpr {{.+}} 'bool' __is_deducible
+// CHECK-NEXT: | |-DeducedTemplateSpecializationType {{.+}} 'GH133132::BB' dependent
+// CHECK-NEXT: | | `-name: 'GH133132::BB'
+// CHECK-NEXT: | | `-TypeAliasTemplateDecl {{.+}} BB
+// CHECK-NEXT: | `-TemplateSpecializationType {{.+}} 'B<_Y>' dependent
+// CHECK-NEXT: | |-name: 'B':'GH133132::B' qualified
+// CHECK-NEXT: | | `-ClassTemplateDecl {{.+}} B
+// CHECK-NEXT: | `-TemplateArgument template '_Y':'template-parameter-0-1' subst index 0
+// CHECK-NEXT: | |-parameter: TemplateTemplateParmDecl {{.+}} depth 0 index 0 _X
+// CHECK-NEXT: | |-associated FunctionTemplate {{.+}} '<deduction guide for B>'
+// CHECK-NEXT: | `-replacement: '_Y':'template-parameter-0-1' qualified
+// CHECK-NEXT: | `-TemplateTemplateParmDecl {{.+}} depth 0 index 1 _Y
+// CHECK-NEXT: |-CXXDeductionGuideDecl {{.+}} implicit <deduction guide for BB> 'auto () -> B<_Y>'
+// CHECK-NEXT: `-CXXDeductionGuideDecl {{.+}} implicit used <deduction guide for BB> 'auto () -> B<GH133132::A>' implicit_instantiation
+// CHECK-NEXT: |-TemplateArgument template 'GH133132::A'
+// CHECK-NEXT: | `-ClassTemplateDecl {{.+}} A
+// CHECK-NEXT: `-TemplateArgument template 'GH133132::A'
+// CHECK-NEXT: `-ClassTemplateDecl {{.+}} A
+
+template <int N = 42, class U = A<decltype(N)>>
+using CC = A<U>;
+
+CC c{};
+
+// CHECK-LABEL: Dumping GH133132::<deduction guide for CC>:
+// CHECK-NEXT: FunctionTemplateDecl {{.+}} implicit <deduction guide for CC>
+// CHECK-NEXT: |-NonTypeTemplateParmDecl {{.+}} 'int' depth 0 index 0 N
+// CHECK-NEXT: | `-TemplateArgument {{.+}} expr '42'
+// CHECK-NEXT: | `-IntegerLiteral {{.+}} 'int' 42
+// CHECK-NEXT: |-TemplateTypeParmDecl {{.+}} class depth 0 index 1 U
+// CHECK-NEXT: | `-TemplateArgument type 'A<decltype(N)>'
+// CHECK-NEXT: | `-ElaboratedType {{.+}} 'A<decltype(N)>' sugar dependent
+// CHECK-NEXT: | `-TemplateSpecializationType {{.+}} 'A<decltype(N)>' dependent
+// CHECK-NEXT: | |-name: 'A':'GH133132::A' qualified
+// CHECK-NEXT: | | `-ClassTemplateDecl {{.+}} A
+// CHECK-NEXT: | `-TemplateArgument type 'decltype(N)'
+// CHECK-NEXT: | `-DecltypeType {{.+}} 'decltype(N)' dependent
+// CHECK-NEXT: | `-DeclRefExpr {{.+}} 'int' NonTypeTemplateParm {{.+}} 'N' 'int'
+// CHECK-NEXT: |-TypeTraitExpr {{.+}} 'bool' __is_deducible
+// CHECK-NEXT: | |-DeducedTemplateSpecializationType {{.+}} 'GH133132::CC' dependent
+// CHECK-NEXT: | | `-name: 'GH133132::CC'
+// CHECK-NEXT: | | `-TypeAliasTemplateDecl {{.+}} CC
+// CHECK-NEXT: | `-TemplateSpecializationType {{.+}} 'A<U>' dependent
+// CHECK-NEXT: | |-name: 'A':'GH133132::A' qualified
+// CHECK-NEXT: | | `-ClassTemplateDecl {{.+}} A
+// CHECK-NEXT: | `-TemplateArgument type 'U':'type-parameter-0-1'
+// CHECK-NEXT: | `-SubstTemplateTypeParmType {{.+}} 'U' sugar dependent class depth 0 index 0 _Ty
+// CHECK-NEXT: | |-FunctionTemplate {{.+}} '<deduction guide for A>'
+// CHECK-NEXT: | `-TemplateTypeParmType {{.+}} 'U' dependent depth 0 index 1
+// CHECK-NEXT: | `-TemplateTypeParm {{.+}} 'U'
+// CHECK-NEXT: |-CXXDeductionGuideDecl {{.+}} implicit <deduction guide for CC> 'auto () -> A<U>'
+// CHECK-NEXT: `-CXXDeductionGuideDecl {{.+}} implicit used <deduction guide for CC> 'auto () -> A<GH133132::A<int>>' implicit_instantiation
+// CHECK-NEXT: |-TemplateArgument integral '42'
+// CHECK-NEXT: `-TemplateArgument type 'GH133132::A<int>'
+// CHECK-NEXT: `-RecordType {{.+}} 'GH133132::A<int>'
+// CHECK-NEXT: `-ClassTemplateSpecialization {{.+}} 'A'
+
}
More information about the cfe-commits
mailing list