Skip to content

Commit

Permalink
[clang] CTAD: Respect requires-clause of the original function templa…
Browse files Browse the repository at this point in the history
…te 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.
  • Loading branch information
hokein committed Mar 13, 2024
1 parent 1c792d2 commit 0be9592
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 5 deletions.
19 changes: 14 additions & 5 deletions clang/lib/Sema/SemaTemplate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2906,18 +2906,27 @@ void DeclareImplicitDeductionGuidesForTypeAlias(
Context.getCanonicalTemplateArgument(
Context.getInjectedTemplateArg(NewParam));
}
// FIXME: implement the associated constraint per C++
// Substitute new template parameters into requires-clause if present.
Expr *RequiresClause = nullptr;
if (Expr *InnerRC = F->getTemplateParameters()->getRequiresClause()) {
MultiLevelTemplateArgumentList Args;
Args.setKind(TemplateSubstitutionKind::Rewrite);
Args.addOuterTemplateArguments(TemplateArgsForBuildingFPrime);
ExprResult E = SemaRef.SubstExpr(InnerRC, Args);
if (E.isInvalid())
return;
RequiresClause = E.getAs<Expr>();
}
// FIXME: implement the is_deducible constraint per C++
// [over.match.class.deduct]p3.3:
// The associated constraints ([temp.constr.decl]) are the
// conjunction of the associated constraints of g and a
// constraint that is satisfied if and only if the arguments
// ... and a constraint that is satisfied if and only if the arguments
// of A are deducible (see below) from the return type.
auto *FPrimeTemplateParamList = TemplateParameterList::Create(
Context, AliasTemplate->getTemplateParameters()->getTemplateLoc(),
AliasTemplate->getTemplateParameters()->getLAngleLoc(),
FPrimeTemplateParams,
AliasTemplate->getTemplateParameters()->getRAngleLoc(),
/*RequiresClause=*/nullptr);
/*RequiresClause=*/RequiresClause);

// To form a deduction guide f' from f, we leverage clang's instantiation
// mechanism, we construct a template argument list where the template
Expand Down
17 changes: 17 additions & 0 deletions clang/test/SemaCXX/cxx20-ctad-type-alias.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -230,3 +230,20 @@ using AFoo = Foo<U>*; // expected-note {{template is declared here}}

AFoo s = {1}; // expected-error {{alias template 'AFoo' requires template arguments; argument deduction only allowed for}}
} // namespace test17

namespace test18 {
template<typename T>
concept False = false; // expected-note {{because 'false' evaluated to false}}

template <typename T> struct Foo { T t; };

template<typename T> requires False<T> // expected-note {{because 'int' does not satisfy 'False'}}
Foo(T) -> Foo<int>;

template <typename U>
using Bar = Foo<U>; // expected-note {{could not match 'Foo<type-parameter-0-0>' against 'int'}} \
// expected-note {{candidate template ignored: constraints not satisfied}} \
// expected-note {{candidate function template not viable}}

Bar s = {1}; // expected-error {{no viable constructor or deduction guide for deduction of template arguments}}
} // namespace test18

0 comments on commit 0be9592

Please sign in to comment.