Skip to content

Commit 0be9592

Browse files
authored
[clang] CTAD: Respect requires-clause of the original function template for the synthesized deduction guide (#84913)
We ignored the require-clause of the original template when building the deduction guide for type-alias CTAD, this resulted in accepting code which should be rejected (see the test case). This patch fixes it, part of #84492.
1 parent 1c792d2 commit 0be9592

File tree

2 files changed

+31
-5
lines changed

2 files changed

+31
-5
lines changed

clang/lib/Sema/SemaTemplate.cpp

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2906,18 +2906,27 @@ void DeclareImplicitDeductionGuidesForTypeAlias(
29062906
Context.getCanonicalTemplateArgument(
29072907
Context.getInjectedTemplateArg(NewParam));
29082908
}
2909-
// FIXME: implement the associated constraint per C++
2909+
// Substitute new template parameters into requires-clause if present.
2910+
Expr *RequiresClause = nullptr;
2911+
if (Expr *InnerRC = F->getTemplateParameters()->getRequiresClause()) {
2912+
MultiLevelTemplateArgumentList Args;
2913+
Args.setKind(TemplateSubstitutionKind::Rewrite);
2914+
Args.addOuterTemplateArguments(TemplateArgsForBuildingFPrime);
2915+
ExprResult E = SemaRef.SubstExpr(InnerRC, Args);
2916+
if (E.isInvalid())
2917+
return;
2918+
RequiresClause = E.getAs<Expr>();
2919+
}
2920+
// FIXME: implement the is_deducible constraint per C++
29102921
// [over.match.class.deduct]p3.3:
2911-
// The associated constraints ([temp.constr.decl]) are the
2912-
// conjunction of the associated constraints of g and a
2913-
// constraint that is satisfied if and only if the arguments
2922+
// ... and a constraint that is satisfied if and only if the arguments
29142923
// of A are deducible (see below) from the return type.
29152924
auto *FPrimeTemplateParamList = TemplateParameterList::Create(
29162925
Context, AliasTemplate->getTemplateParameters()->getTemplateLoc(),
29172926
AliasTemplate->getTemplateParameters()->getLAngleLoc(),
29182927
FPrimeTemplateParams,
29192928
AliasTemplate->getTemplateParameters()->getRAngleLoc(),
2920-
/*RequiresClause=*/nullptr);
2929+
/*RequiresClause=*/RequiresClause);
29212930

29222931
// To form a deduction guide f' from f, we leverage clang's instantiation
29232932
// mechanism, we construct a template argument list where the template

clang/test/SemaCXX/cxx20-ctad-type-alias.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,3 +230,20 @@ using AFoo = Foo<U>*; // expected-note {{template is declared here}}
230230

231231
AFoo s = {1}; // expected-error {{alias template 'AFoo' requires template arguments; argument deduction only allowed for}}
232232
} // namespace test17
233+
234+
namespace test18 {
235+
template<typename T>
236+
concept False = false; // expected-note {{because 'false' evaluated to false}}
237+
238+
template <typename T> struct Foo { T t; };
239+
240+
template<typename T> requires False<T> // expected-note {{because 'int' does not satisfy 'False'}}
241+
Foo(T) -> Foo<int>;
242+
243+
template <typename U>
244+
using Bar = Foo<U>; // expected-note {{could not match 'Foo<type-parameter-0-0>' against 'int'}} \
245+
// expected-note {{candidate template ignored: constraints not satisfied}} \
246+
// expected-note {{candidate function template not viable}}
247+
248+
Bar s = {1}; // expected-error {{no viable constructor or deduction guide for deduction of template arguments}}
249+
} // namespace test18

0 commit comments

Comments
 (0)