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 <zyn7...@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 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits