[clang] Propagate requires-clause from constructor template to implicit deduction guide

Fixes https://github.com/clangd/clangd/issues/890

Differential Revision: https://reviews.llvm.org/D113874
This commit is contained in:
Nathan Ridge 2021-11-14 01:39:17 -05:00
parent 940bd4c771
commit 56a54910c5
2 changed files with 49 additions and 1 deletions

View File

@ -2184,10 +2184,24 @@ struct ConvertConstructorToDeductionGuideTransform {
SubstArgs.push_back(SemaRef.Context.getCanonicalTemplateArgument(
SemaRef.Context.getInjectedTemplateArg(NewParam)));
}
// Substitute new template parameters into requires-clause if present.
Expr *RequiresClause = nullptr;
if (Expr *InnerRC = InnerParams->getRequiresClause()) {
MultiLevelTemplateArgumentList Args;
Args.setKind(TemplateSubstitutionKind::Rewrite);
Args.addOuterTemplateArguments(SubstArgs);
Args.addOuterRetainedLevel();
ExprResult E = SemaRef.SubstExpr(InnerRC, Args);
if (E.isInvalid())
return nullptr;
RequiresClause = E.getAs<Expr>();
}
TemplateParams = TemplateParameterList::Create(
SemaRef.Context, InnerParams->getTemplateLoc(),
InnerParams->getLAngleLoc(), AllParams, InnerParams->getRAngleLoc(),
/*FIXME: RequiresClause*/ nullptr);
RequiresClause);
}
// If we built a new template-parameter-list, track that we need to

View File

@ -206,3 +206,37 @@ using ET = E<1, 3>;
// CHECK: `-TemplateArgument expr
// CHECK-NOT: Subst
// CHECK: `-DeclRefExpr {{.*}} 'int' NonTypeTemplateParm [[M2]] 'M2' 'int'
template <char = 'x'> struct F;
template <char> struct F {
template <typename U>
requires(false) F(U);
template <typename U>
requires(true) F(U);
};
F s(0);
// CHECK-LABEL: Dumping <deduction guide for F>:
// CHECK: FunctionTemplateDecl
// CHECK: |-NonTypeTemplateParmDecl {{.*}} 'char' depth 0 index 0
// CHECK: `-TemplateArgument expr
// CHECK: | |-inherited from NonTypeTemplateParm {{.*}} '' 'char'
// CHECK: | `-ConstantExpr {{.*}} 'char'
// CHECK: | |-value: Int 120
// CHECK: | `-CharacterLiteral {{.*}} 'char' 120
// CHECK: |-TemplateTypeParmDecl {{.*}} typename depth 0 index 1 U
// CHECK: |-ParenExpr {{.*}} 'bool'
// CHECK: | `-CXXBoolLiteralExpr {{.*}} 'bool' false
// CHECK: |-CXXDeductionGuideDecl {{.*}} implicit <deduction guide for F> 'auto (type-parameter-0-1) -> F<>'
// CHECK: | `-ParmVarDecl {{.*}} 'type-parameter-0-1'
// CHECK: `-CXXDeductionGuideDecl {{.*}} implicit <deduction guide for F> 'auto (int) -> F<'x'>'
// CHECK: |-TemplateArgument integral 120
// CHECK: |-TemplateArgument type 'int'
// CHECK: | `-BuiltinType {{.*}} 'int'
// CHECK: `-ParmVarDecl {{.*}} 'int':'int'
// CHECK: FunctionProtoType {{.*}} 'auto (type-parameter-0-1) -> F<>' dependent trailing_return cdecl
// CHECK: |-InjectedClassNameType {{.*}} 'F<>' dependent
// CHECK: | `-CXXRecord {{.*}} 'F'
// CHECK: `-TemplateTypeParmType {{.*}} 'type-parameter-0-1' dependent depth 0 index 1