Skip to content

Commit 56a5491

Browse files
[clang] Propagate requires-clause from constructor template to implicit deduction guide
Fixes clangd/clangd#890 Differential Revision: https://reviews.llvm.org/D113874
1 parent 940bd4c commit 56a5491

File tree

2 files changed

+49
-1
lines changed

2 files changed

+49
-1
lines changed

clang/lib/Sema/SemaTemplate.cpp

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2184,10 +2184,24 @@ struct ConvertConstructorToDeductionGuideTransform {
21842184
SubstArgs.push_back(SemaRef.Context.getCanonicalTemplateArgument(
21852185
SemaRef.Context.getInjectedTemplateArg(NewParam)));
21862186
}
2187+
2188+
// Substitute new template parameters into requires-clause if present.
2189+
Expr *RequiresClause = nullptr;
2190+
if (Expr *InnerRC = InnerParams->getRequiresClause()) {
2191+
MultiLevelTemplateArgumentList Args;
2192+
Args.setKind(TemplateSubstitutionKind::Rewrite);
2193+
Args.addOuterTemplateArguments(SubstArgs);
2194+
Args.addOuterRetainedLevel();
2195+
ExprResult E = SemaRef.SubstExpr(InnerRC, Args);
2196+
if (E.isInvalid())
2197+
return nullptr;
2198+
RequiresClause = E.getAs<Expr>();
2199+
}
2200+
21872201
TemplateParams = TemplateParameterList::Create(
21882202
SemaRef.Context, InnerParams->getTemplateLoc(),
21892203
InnerParams->getLAngleLoc(), AllParams, InnerParams->getRAngleLoc(),
2190-
/*FIXME: RequiresClause*/ nullptr);
2204+
RequiresClause);
21912205
}
21922206

21932207
// If we built a new template-parameter-list, track that we need to

clang/test/SemaTemplate/deduction-guide.cpp

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,3 +206,37 @@ using ET = E<1, 3>;
206206
// CHECK: `-TemplateArgument expr
207207
// CHECK-NOT: Subst
208208
// CHECK: `-DeclRefExpr {{.*}} 'int' NonTypeTemplateParm [[M2]] 'M2' 'int'
209+
210+
template <char = 'x'> struct F;
211+
212+
template <char> struct F {
213+
template <typename U>
214+
requires(false) F(U);
215+
template <typename U>
216+
requires(true) F(U);
217+
};
218+
219+
F s(0);
220+
221+
// CHECK-LABEL: Dumping <deduction guide for F>:
222+
// CHECK: FunctionTemplateDecl
223+
// CHECK: |-NonTypeTemplateParmDecl {{.*}} 'char' depth 0 index 0
224+
// CHECK: `-TemplateArgument expr
225+
// CHECK: | |-inherited from NonTypeTemplateParm {{.*}} '' 'char'
226+
// CHECK: | `-ConstantExpr {{.*}} 'char'
227+
// CHECK: | |-value: Int 120
228+
// CHECK: | `-CharacterLiteral {{.*}} 'char' 120
229+
// CHECK: |-TemplateTypeParmDecl {{.*}} typename depth 0 index 1 U
230+
// CHECK: |-ParenExpr {{.*}} 'bool'
231+
// CHECK: | `-CXXBoolLiteralExpr {{.*}} 'bool' false
232+
// CHECK: |-CXXDeductionGuideDecl {{.*}} implicit <deduction guide for F> 'auto (type-parameter-0-1) -> F<>'
233+
// CHECK: | `-ParmVarDecl {{.*}} 'type-parameter-0-1'
234+
// CHECK: `-CXXDeductionGuideDecl {{.*}} implicit <deduction guide for F> 'auto (int) -> F<'x'>'
235+
// CHECK: |-TemplateArgument integral 120
236+
// CHECK: |-TemplateArgument type 'int'
237+
// CHECK: | `-BuiltinType {{.*}} 'int'
238+
// CHECK: `-ParmVarDecl {{.*}} 'int':'int'
239+
// CHECK: FunctionProtoType {{.*}} 'auto (type-parameter-0-1) -> F<>' dependent trailing_return cdecl
240+
// CHECK: |-InjectedClassNameType {{.*}} 'F<>' dependent
241+
// CHECK: | `-CXXRecord {{.*}} 'F'
242+
// CHECK: `-TemplateTypeParmType {{.*}} 'type-parameter-0-1' dependent depth 0 index 1

0 commit comments

Comments
 (0)