[clang] [Clang] Form PackExpansionTypes of TemplateArguments for rewrite substitution (PR #126206)
Younan Zhang via cfe-commits
cfe-commits at lists.llvm.org
Fri Feb 7 01:27:24 PST 2025
https://github.com/zyn0217 created https://github.com/llvm/llvm-project/pull/126206
When substituting for rewrite purposes, as in rebuilding constraints for a synthesized deduction guide, it assumed that packs were in `PackExpansion*` form, such that the instantiator could extract a pattern. For type aliases CTAD, while rebuilding their associated constraints, we rebuild the template arguments using `TransformTemplateArgument()`, which did not guarantee the establishment of PackExpansions as `getInjectedTemplateArguments()` does.
This patch fixes that by making it call `RebuildPackExpansion()` if the transformed arguments are still having unexpanded parameter packs.
No release note as I think this is a good candidate for backporting.
Fixes #124715
>From 2fece00684322b1ebd57a0d94f14c21cc570e262 Mon Sep 17 00:00:00 2001
From: Younan Zhang <zyn7109 at gmail.com>
Date: Fri, 7 Feb 2025 17:15:05 +0800
Subject: [PATCH] [Clang] Form PackExpansionTypes of TemplateArguments for
rewrite substitution
When substituting for rewrite purposes, as in rebuilding constraints for a synthesized
deduction guide, it assumed that packs were in PackExpansion* form, such that the
instantiator could extract a pattern. For type aliases CTAD, while rebuilding their
associated constraints, we rebuild the template arguments using TransformTemplateArgument(),
which did not guarantee the establishment of PackExpansions as getInjectedTemplateArguments() does.
This patch fixes that by making it call RebuildPackExpansion() if the
transformed arguments are still having unexpanded parameter packs.
---
clang/lib/Sema/SemaTemplateInstantiate.cpp | 8 +++-
clang/test/AST/ast-dump-ctad-alias.cpp | 44 ++++++++++++++++++++++
2 files changed, 51 insertions(+), 1 deletion(-)
diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp
index 12e98a33d07853e..522bd418e2f1881 100644
--- a/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -1627,8 +1627,14 @@ namespace {
TemplateArgumentLoc Input = SemaRef.getTrivialTemplateArgumentLoc(
pack, QualType(), SourceLocation{});
TemplateArgumentLoc Output;
- if (SemaRef.SubstTemplateArgument(Input, TemplateArgs, Output))
+ if (TransformTemplateArgument(Input, Output, Uneval))
return true; // fails
+ if (Output.getArgument().containsUnexpandedParameterPack())
+ // FIXME: Is EllipsisLoc necessary? This pack expansion merely
+ // serves as a placeholder type for future rewrite-substitution
+ // (e.g. into constraint expressions.)
+ Output =
+ RebuildPackExpansion(Output, SourceLocation{}, std::nullopt);
TArgs.push_back(Output.getArgument());
}
Output = SemaRef.getTrivialTemplateArgumentLoc(
diff --git a/clang/test/AST/ast-dump-ctad-alias.cpp b/clang/test/AST/ast-dump-ctad-alias.cpp
index b1631f7822ce017..464808af784c2c3 100644
--- a/clang/test/AST/ast-dump-ctad-alias.cpp
+++ b/clang/test/AST/ast-dump-ctad-alias.cpp
@@ -156,3 +156,47 @@ ATemplatedClass2 test2(list);
// CHECK-NEXT: |-TypeTraitExpr {{.*}} 'bool' __is_deducible
} // namespace GH90209
+
+namespace GH124715 {
+
+template <class T, class... Args>
+concept invocable = true;
+
+template <class T, class... Args> struct Struct {
+ template <class U>
+ requires invocable<U, Args...>
+ Struct(U, Args...) {}
+};
+
+template <class Lambda, class... Args>
+Struct(Lambda lambda, Args... args) -> Struct<Lambda, Args...>;
+
+template <class T, class... Ts> using Alias = Struct<T, Ts...>;
+
+void foo() {
+ Alias([](int) {}, 0);
+}
+
+// CHECK: |-FunctionTemplateDecl {{.*}} implicit <deduction guide for Alias>
+// CHECK-NEXT: | |-TemplateTypeParmDecl {{.*}} class depth 0 index 0 T
+// CHECK-NEXT: | |-TemplateTypeParmDecl {{.*}} class depth 0 index 1 ... Ts
+// CHECK-NEXT: | |-TemplateTypeParmDecl {{.*}} class depth 0 index 2 U
+// CHECK-NEXT: | |-BinaryOperator {{.*}} 'bool' '&&'
+// CHECK-NEXT: | | |-ConceptSpecializationExpr {{.*}} 'bool' Concept {{.*}} 'invocable'
+// CHECK-NEXT: | | | |-ImplicitConceptSpecializationDecl {{.*}}
+// CHECK-NEXT: | | | | |-TemplateArgument type 'type-parameter-0-2'
+// CHECK-NEXT: | | | | | `-TemplateTypeParmType {{.*}} 'type-parameter-0-2' dependent depth 0 index 2
+// CHECK-NEXT: | | | | `-TemplateArgument pack '<type-parameter-0-1...>'
+// CHECK-NEXT: | | | | `-TemplateArgument type 'type-parameter-0-1...'
+// CHECK-NEXT: | | | | `-PackExpansionType {{.*}} 'type-parameter-0-1...' dependent
+// CHECK-NEXT: | | | | `-TemplateTypeParmType {{.*}} 'type-parameter-0-1' dependent contains_unexpanded_pack depth 0 index 1 pack
+// CHECK-NEXT: | | | |-TemplateArgument {{.*}} type 'U':'type-parameter-0-2'
+// CHECK-NEXT: | | | | `-TemplateTypeParmType {{.*}} 'U' dependent depth 0 index 2
+// CHECK-NEXT: | | | | `-TemplateTypeParm {{.*}} 'U'
+// CHECK-NEXT: | | | `-TemplateArgument {{.*}} type 'Ts...':'type-parameter-0-1...'
+// CHECK-NEXT: | | | `-PackExpansionType {{.*}} 'Ts...' dependent
+// CHECK-NEXT: | | | `-TemplateTypeParmType {{.*}} 'Ts' dependent contains_unexpanded_pack depth 0 index 1 pack
+// CHECK-NEXT: | | | `-TemplateTypeParm {{.*}} 'Ts'
+// CHECK-NEXT: | | `-TypeTraitExpr {{.*}} 'bool' __is_deducible
+
+} // namespace GH124715
More information about the cfe-commits
mailing list