[Clang] Remove the PackExpansion restrictions for rewrite substitution (#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,
this might not be the case because we'll call
`TransformTemplateArgument()` for the alias template arguments, where
there might be cases e.g. a non-pack expansion type into a pack
expansion, so the assumption wouldn't hold.
This patch fixes that by making it treat the non-pack expansions as
direct patterns when rewriting.
Fixes #124715
This commit is contained in:
@@ -4905,7 +4905,7 @@ bool Sema::CheckTemplateTypeArgument(
|
||||
[[fallthrough]];
|
||||
}
|
||||
default: {
|
||||
// We allow instantiateing a template with template argument packs when
|
||||
// We allow instantiating a template with template argument packs when
|
||||
// building deduction guides.
|
||||
if (Arg.getKind() == TemplateArgument::Pack &&
|
||||
CodeSynthesisContexts.back().Kind ==
|
||||
|
||||
@@ -1466,6 +1466,18 @@ namespace {
|
||||
}
|
||||
}
|
||||
|
||||
static TemplateArgument
|
||||
getTemplateArgumentPackPatternForRewrite(const TemplateArgument &TA) {
|
||||
if (TA.getKind() != TemplateArgument::Pack)
|
||||
return TA;
|
||||
assert(TA.pack_size() == 1 &&
|
||||
"unexpected pack arguments in template rewrite");
|
||||
TemplateArgument Arg = *TA.pack_begin();
|
||||
if (Arg.isPackExpansion())
|
||||
Arg = Arg.getPackExpansionPattern();
|
||||
return Arg;
|
||||
}
|
||||
|
||||
/// Transform the given declaration by instantiating a reference to
|
||||
/// this declaration.
|
||||
Decl *TransformDecl(SourceLocation Loc, Decl *D);
|
||||
@@ -1627,7 +1639,7 @@ namespace {
|
||||
TemplateArgumentLoc Input = SemaRef.getTrivialTemplateArgumentLoc(
|
||||
pack, QualType(), SourceLocation{});
|
||||
TemplateArgumentLoc Output;
|
||||
if (SemaRef.SubstTemplateArgument(Input, TemplateArgs, Output))
|
||||
if (TransformTemplateArgument(Input, Output, Uneval))
|
||||
return true; // fails
|
||||
TArgs.push_back(Output.getArgument());
|
||||
}
|
||||
@@ -2040,11 +2052,7 @@ TemplateName TemplateInstantiator::TransformTemplateName(
|
||||
if (TemplateArgs.isRewrite()) {
|
||||
// We're rewriting the template parameter as a reference to another
|
||||
// template parameter.
|
||||
if (Arg.getKind() == TemplateArgument::Pack) {
|
||||
assert(Arg.pack_size() == 1 && Arg.pack_begin()->isPackExpansion() &&
|
||||
"unexpected pack arguments in template rewrite");
|
||||
Arg = Arg.pack_begin()->getPackExpansionPattern();
|
||||
}
|
||||
Arg = getTemplateArgumentPackPatternForRewrite(Arg);
|
||||
assert(Arg.getKind() == TemplateArgument::Template &&
|
||||
"unexpected nontype template argument kind in template rewrite");
|
||||
return Arg.getAsTemplate();
|
||||
@@ -2125,11 +2133,7 @@ TemplateInstantiator::TransformTemplateParmRefExpr(DeclRefExpr *E,
|
||||
if (TemplateArgs.isRewrite()) {
|
||||
// We're rewriting the template parameter as a reference to another
|
||||
// template parameter.
|
||||
if (Arg.getKind() == TemplateArgument::Pack) {
|
||||
assert(Arg.pack_size() == 1 && Arg.pack_begin()->isPackExpansion() &&
|
||||
"unexpected pack arguments in template rewrite");
|
||||
Arg = Arg.pack_begin()->getPackExpansionPattern();
|
||||
}
|
||||
Arg = getTemplateArgumentPackPatternForRewrite(Arg);
|
||||
assert(Arg.getKind() == TemplateArgument::Expression &&
|
||||
"unexpected nontype template argument kind in template rewrite");
|
||||
// FIXME: This can lead to the same subexpression appearing multiple times
|
||||
@@ -2591,11 +2595,7 @@ TemplateInstantiator::TransformTemplateTypeParmType(TypeLocBuilder &TLB,
|
||||
if (TemplateArgs.isRewrite()) {
|
||||
// We're rewriting the template parameter as a reference to another
|
||||
// template parameter.
|
||||
if (Arg.getKind() == TemplateArgument::Pack) {
|
||||
assert(Arg.pack_size() == 1 && Arg.pack_begin()->isPackExpansion() &&
|
||||
"unexpected pack arguments in template rewrite");
|
||||
Arg = Arg.pack_begin()->getPackExpansionPattern();
|
||||
}
|
||||
Arg = getTemplateArgumentPackPatternForRewrite(Arg);
|
||||
assert(Arg.getKind() == TemplateArgument::Type &&
|
||||
"unexpected nontype template argument kind in template rewrite");
|
||||
QualType NewT = Arg.getAsType();
|
||||
|
||||
@@ -156,3 +156,49 @@ 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...> struct Packs {};
|
||||
|
||||
template <class Lambda, class... Args>
|
||||
Struct(Lambda lambda, Args... args) -> Struct<Lambda, Args...>;
|
||||
|
||||
template <class T, class... Ts> using Alias = Struct<T, Packs<Ts...>>;
|
||||
|
||||
void foo() {
|
||||
Alias([](int) {}, Packs<int>());
|
||||
}
|
||||
|
||||
// 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 '<Packs<type-parameter-0-1...>>'
|
||||
// CHECK-NEXT: | | | | `-TemplateArgument type 'Packs<type-parameter-0-1...>'
|
||||
// CHECK-NEXT: | | | | `-TemplateSpecializationType {{.*}} 'Packs<type-parameter-0-1...>' dependent
|
||||
// CHECK-NEXT: | | | | |-name: 'GH124715::Packs'
|
||||
// CHECK-NEXT: | | | | | `-ClassTemplateDecl {{.*}} Packs
|
||||
// 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'
|
||||
|
||||
} // namespace GH124715
|
||||
|
||||
Reference in New Issue
Block a user