Skip to content

Commit 3007684

Browse files
authored
release/20.x: [Clang] Remove the PackExpansion restrictions for rewrite substitution (#127174)
This backports c08b80e with a release note towards 20 so that we could resolve some pains in CTAD.
1 parent 6dcece4 commit 3007684

File tree

4 files changed

+65
-17
lines changed

4 files changed

+65
-17
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1053,6 +1053,8 @@ Bug Fixes to C++ Support
10531053
template parameter. Now, such expression can be used with ``static_assert`` and ``constexpr``. (#GH123498)
10541054
- Correctly determine the implicit constexprness of lambdas in dependent contexts. (#GH97958) (#GH114234)
10551055
- Fix that some dependent immediate expressions did not cause immediate escalation (#GH119046)
1056+
- Fixed a substitution bug in transforming CTAD aliases when the type alias contains a non-pack template argument
1057+
corresponding to a pack parameter (#GH124715)
10561058

10571059
Bug Fixes to AST Handling
10581060
^^^^^^^^^^^^^^^^^^^^^^^^^

clang/lib/Sema/SemaTemplate.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4905,7 +4905,7 @@ bool Sema::CheckTemplateTypeArgument(
49054905
[[fallthrough]];
49064906
}
49074907
default: {
4908-
// We allow instantiateing a template with template argument packs when
4908+
// We allow instantiating a template with template argument packs when
49094909
// building deduction guides.
49104910
if (Arg.getKind() == TemplateArgument::Pack &&
49114911
CodeSynthesisContexts.back().Kind ==

clang/lib/Sema/SemaTemplateInstantiate.cpp

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1467,6 +1467,18 @@ namespace {
14671467
}
14681468
}
14691469

1470+
static TemplateArgument
1471+
getTemplateArgumentPackPatternForRewrite(const TemplateArgument &TA) {
1472+
if (TA.getKind() != TemplateArgument::Pack)
1473+
return TA;
1474+
assert(TA.pack_size() == 1 &&
1475+
"unexpected pack arguments in template rewrite");
1476+
TemplateArgument Arg = *TA.pack_begin();
1477+
if (Arg.isPackExpansion())
1478+
Arg = Arg.getPackExpansionPattern();
1479+
return Arg;
1480+
}
1481+
14701482
/// Transform the given declaration by instantiating a reference to
14711483
/// this declaration.
14721484
Decl *TransformDecl(SourceLocation Loc, Decl *D);
@@ -1624,7 +1636,7 @@ namespace {
16241636
TemplateArgumentLoc Input = SemaRef.getTrivialTemplateArgumentLoc(
16251637
pack, QualType(), SourceLocation{});
16261638
TemplateArgumentLoc Output;
1627-
if (SemaRef.SubstTemplateArgument(Input, TemplateArgs, Output))
1639+
if (TransformTemplateArgument(Input, Output, Uneval))
16281640
return true; // fails
16291641
TArgs.push_back(Output.getArgument());
16301642
}
@@ -2036,11 +2048,7 @@ TemplateName TemplateInstantiator::TransformTemplateName(
20362048
if (TemplateArgs.isRewrite()) {
20372049
// We're rewriting the template parameter as a reference to another
20382050
// template parameter.
2039-
if (Arg.getKind() == TemplateArgument::Pack) {
2040-
assert(Arg.pack_size() == 1 && Arg.pack_begin()->isPackExpansion() &&
2041-
"unexpected pack arguments in template rewrite");
2042-
Arg = Arg.pack_begin()->getPackExpansionPattern();
2043-
}
2051+
Arg = getTemplateArgumentPackPatternForRewrite(Arg);
20442052
assert(Arg.getKind() == TemplateArgument::Template &&
20452053
"unexpected nontype template argument kind in template rewrite");
20462054
return Arg.getAsTemplate();
@@ -2121,11 +2129,7 @@ TemplateInstantiator::TransformTemplateParmRefExpr(DeclRefExpr *E,
21212129
if (TemplateArgs.isRewrite()) {
21222130
// We're rewriting the template parameter as a reference to another
21232131
// template parameter.
2124-
if (Arg.getKind() == TemplateArgument::Pack) {
2125-
assert(Arg.pack_size() == 1 && Arg.pack_begin()->isPackExpansion() &&
2126-
"unexpected pack arguments in template rewrite");
2127-
Arg = Arg.pack_begin()->getPackExpansionPattern();
2128-
}
2132+
Arg = getTemplateArgumentPackPatternForRewrite(Arg);
21292133
assert(Arg.getKind() == TemplateArgument::Expression &&
21302134
"unexpected nontype template argument kind in template rewrite");
21312135
// FIXME: This can lead to the same subexpression appearing multiple times
@@ -2578,11 +2582,7 @@ TemplateInstantiator::TransformTemplateTypeParmType(TypeLocBuilder &TLB,
25782582
if (TemplateArgs.isRewrite()) {
25792583
// We're rewriting the template parameter as a reference to another
25802584
// template parameter.
2581-
if (Arg.getKind() == TemplateArgument::Pack) {
2582-
assert(Arg.pack_size() == 1 && Arg.pack_begin()->isPackExpansion() &&
2583-
"unexpected pack arguments in template rewrite");
2584-
Arg = Arg.pack_begin()->getPackExpansionPattern();
2585-
}
2585+
Arg = getTemplateArgumentPackPatternForRewrite(Arg);
25862586
assert(Arg.getKind() == TemplateArgument::Type &&
25872587
"unexpected nontype template argument kind in template rewrite");
25882588
QualType NewT = Arg.getAsType();

clang/test/AST/ast-dump-ctad-alias.cpp

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,3 +156,49 @@ ATemplatedClass2 test2(list);
156156
// CHECK-NEXT: |-TypeTraitExpr {{.*}} 'bool' __is_deducible
157157

158158
} // namespace GH90209
159+
160+
namespace GH124715 {
161+
162+
template <class T, class... Args>
163+
concept invocable = true;
164+
165+
template <class T, class... Args> struct Struct {
166+
template <class U>
167+
requires invocable<U, Args...>
168+
Struct(U, Args...) {}
169+
};
170+
171+
template <class...> struct Packs {};
172+
173+
template <class Lambda, class... Args>
174+
Struct(Lambda lambda, Args... args) -> Struct<Lambda, Args...>;
175+
176+
template <class T, class... Ts> using Alias = Struct<T, Packs<Ts...>>;
177+
178+
void foo() {
179+
Alias([](int) {}, Packs<int>());
180+
}
181+
182+
// CHECK: |-FunctionTemplateDecl {{.*}} implicit <deduction guide for Alias>
183+
// CHECK-NEXT: | |-TemplateTypeParmDecl {{.*}} class depth 0 index 0 T
184+
// CHECK-NEXT: | |-TemplateTypeParmDecl {{.*}} class depth 0 index 1 ... Ts
185+
// CHECK-NEXT: | |-TemplateTypeParmDecl {{.*}} class depth 0 index 2 U
186+
// CHECK-NEXT: | |-BinaryOperator {{.*}} 'bool' '&&'
187+
// CHECK-NEXT: | | |-ConceptSpecializationExpr {{.*}} 'bool' Concept {{.*}} 'invocable'
188+
// CHECK-NEXT: | | | |-ImplicitConceptSpecializationDecl {{.*}}
189+
// CHECK-NEXT: | | | | |-TemplateArgument type 'type-parameter-0-2'
190+
// CHECK-NEXT: | | | | | `-TemplateTypeParmType {{.*}} 'type-parameter-0-2' dependent depth 0 index 2
191+
// CHECK-NEXT: | | | | `-TemplateArgument pack '<Packs<type-parameter-0-1...>>'
192+
// CHECK-NEXT: | | | | `-TemplateArgument type 'Packs<type-parameter-0-1...>'
193+
// CHECK-NEXT: | | | | `-TemplateSpecializationType {{.*}} 'Packs<type-parameter-0-1...>' dependent
194+
// CHECK-NEXT: | | | | |-name: 'GH124715::Packs'
195+
// CHECK-NEXT: | | | | | `-ClassTemplateDecl {{.*}} Packs
196+
// CHECK-NEXT: | | | | `-TemplateArgument pack '<type-parameter-0-1...>'
197+
// CHECK-NEXT: | | | | `-TemplateArgument type 'type-parameter-0-1...'
198+
// CHECK-NEXT: | | | | `-PackExpansionType {{.*}} 'type-parameter-0-1...' dependent
199+
// CHECK-NEXT: | | | | `-TemplateTypeParmType {{.*}} 'type-parameter-0-1' dependent contains_unexpanded_pack depth 0 index 1 pack
200+
// CHECK-NEXT: | | | |-TemplateArgument {{.*}} type 'U':'type-parameter-0-2'
201+
// CHECK-NEXT: | | | | `-TemplateTypeParmType {{.*}} 'U' dependent depth 0 index 2
202+
// CHECK-NEXT: | | | | `-TemplateTypeParm {{.*}} 'U'
203+
204+
} // namespace GH124715

0 commit comments

Comments
 (0)