[llvm-branch-commits] [clang] [clang] WIP: Implement TTP 'reversed' pack matching for deduced function template calls. (PR #111457)
via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Mon Oct 7 17:20:17 PDT 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang
Author: Matheus Izvekov (mizvekov)
<details>
<summary>Changes</summary>
Clang previously missed implementing the historical rule https://eel.is/c++draft/temp.arg.template#<!-- -->3.sentence-3 for deduced function template calls.
This patch implements this rule, but only on the
'frelaxed-template-template-args' mode, which is
currently the default.
As its negation is deprecated and will be removed soon, this patch does not change the implementation in that case.
WIP, as it's missing some changes which will help in not breaking compatibility in overload resolution.
---
Patch is 20.92 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/111457.diff
6 Files Affected:
- (modified) clang/include/clang/Sema/Sema.h (+8-6)
- (modified) clang/lib/Sema/SemaLookup.cpp (+1)
- (modified) clang/lib/Sema/SemaOverload.cpp (+3-2)
- (modified) clang/lib/Sema/SemaTemplate.cpp (+12-11)
- (modified) clang/lib/Sema/SemaTemplateDeduction.cpp (+44-32)
- (modified) clang/test/SemaTemplate/cwg2398.cpp (+34)
``````````diff
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 5d38862ce59f0c..05857884fdc2e1 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -11636,7 +11636,7 @@ class Sema final : public SemaBase {
SourceLocation RAngleLoc, unsigned ArgumentPackIndex,
SmallVectorImpl<TemplateArgument> &SugaredConverted,
SmallVectorImpl<TemplateArgument> &CanonicalConverted,
- CheckTemplateArgumentKind CTAK,
+ CheckTemplateArgumentKind CTAK, bool PartialOrdering,
bool *MatchedPackOnParmToNonPackOnArg);
/// Check that the given template arguments can be provided to
@@ -11719,7 +11719,8 @@ class Sema final : public SemaBase {
/// It returns true if an error occurred, and false otherwise.
bool CheckTemplateTemplateArgument(TemplateTemplateParmDecl *Param,
TemplateParameterList *Params,
- TemplateArgumentLoc &Arg, bool IsDeduced,
+ TemplateArgumentLoc &Arg,
+ bool PartialOrdering,
bool *MatchedPackOnParmToNonPackOnArg);
void NoteTemplateLocation(const NamedDecl &Decl,
@@ -12231,8 +12232,8 @@ class Sema final : public SemaBase {
SmallVectorImpl<DeducedTemplateArgument> &Deduced,
unsigned NumExplicitlySpecified, FunctionDecl *&Specialization,
sema::TemplateDeductionInfo &Info,
- SmallVectorImpl<OriginalCallArg> const *OriginalCallArgs = nullptr,
- bool PartialOverloading = false,
+ SmallVectorImpl<OriginalCallArg> const *OriginalCallArgs,
+ bool PartialOverloading, bool PartialOrdering,
llvm::function_ref<bool()> CheckNonDependent = [] { return false; });
/// Perform template argument deduction from a function call
@@ -12266,7 +12267,8 @@ class Sema final : public SemaBase {
TemplateArgumentListInfo *ExplicitTemplateArgs, ArrayRef<Expr *> Args,
FunctionDecl *&Specialization, sema::TemplateDeductionInfo &Info,
bool PartialOverloading, bool AggregateDeductionCandidate,
- QualType ObjectType, Expr::Classification ObjectClassification,
+ bool PartialOrdering, QualType ObjectType,
+ Expr::Classification ObjectClassification,
llvm::function_ref<bool(ArrayRef<QualType>)> CheckNonDependent);
/// Deduce template arguments when taking the address of a function
@@ -12421,7 +12423,7 @@ class Sema final : public SemaBase {
bool isTemplateTemplateParameterAtLeastAsSpecializedAs(
TemplateParameterList *PParam, TemplateDecl *PArg, TemplateDecl *AArg,
const DefaultArguments &DefaultArgs, SourceLocation ArgLoc,
- bool IsDeduced, bool *MatchedPackOnParmToNonPackOnArg);
+ bool PartialOrdering, bool *MatchedPackOnParmToNonPackOnArg);
/// Mark which template parameters are used in a given expression.
///
diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp
index 31422c213ac249..60fa195221c938 100644
--- a/clang/lib/Sema/SemaLookup.cpp
+++ b/clang/lib/Sema/SemaLookup.cpp
@@ -3667,6 +3667,7 @@ Sema::LookupLiteralOperator(Scope *S, LookupResult &R,
if (CheckTemplateArgument(
Params->getParam(0), Arg, FD, R.getNameLoc(), R.getNameLoc(),
0, SugaredChecked, CanonicalChecked, CTAK_Specified,
+ /*PartialOrdering=*/false,
/*MatchedPackOnParmToNonPackOnArg=*/nullptr) ||
Trap.hasErrorOccurred())
IsTemplate = false;
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index 2cde8131108fbe..a8c3dd05a9a3c5 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -7663,8 +7663,8 @@ void Sema::AddMethodTemplateCandidate(
ConversionSequenceList Conversions;
if (TemplateDeductionResult Result = DeduceTemplateArguments(
MethodTmpl, ExplicitTemplateArgs, Args, Specialization, Info,
- PartialOverloading, /*AggregateDeductionCandidate=*/false, ObjectType,
- ObjectClassification,
+ PartialOverloading, /*AggregateDeductionCandidate=*/false,
+ /*PartialOrdering=*/false, ObjectType, ObjectClassification,
[&](ArrayRef<QualType> ParamTypes) {
return CheckNonDependentConversions(
MethodTmpl, ParamTypes, Args, CandidateSet, Conversions,
@@ -7748,6 +7748,7 @@ void Sema::AddTemplateOverloadCandidate(
if (TemplateDeductionResult Result = DeduceTemplateArguments(
FunctionTemplate, ExplicitTemplateArgs, Args, Specialization, Info,
PartialOverloading, AggregateCandidateDeduction,
+ /*PartialOrdering=*/false,
/*ObjectType=*/QualType(),
/*ObjectClassification=*/Expr::Classification(),
[&](ArrayRef<QualType> ParamTypes) {
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index 82fd4789956622..94cb4c8e32d703 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -5179,7 +5179,8 @@ bool Sema::CheckTemplateArgument(
unsigned ArgumentPackIndex,
SmallVectorImpl<TemplateArgument> &SugaredConverted,
SmallVectorImpl<TemplateArgument> &CanonicalConverted,
- CheckTemplateArgumentKind CTAK, bool *MatchedPackOnParmToNonPackOnArg) {
+ CheckTemplateArgumentKind CTAK, bool PartialOrdering,
+ bool *MatchedPackOnParmToNonPackOnArg) {
// Check template type parameters.
if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(Param))
return CheckTemplateTypeArgument(TTP, Arg, SugaredConverted,
@@ -5394,8 +5395,7 @@ bool Sema::CheckTemplateArgument(
case TemplateArgument::Template:
case TemplateArgument::TemplateExpansion:
- if (CheckTemplateTemplateArgument(TempParm, Params, Arg,
- /*IsDeduced=*/CTAK != CTAK_Specified,
+ if (CheckTemplateTemplateArgument(TempParm, Params, Arg, PartialOrdering,
MatchedPackOnParmToNonPackOnArg))
return true;
@@ -5546,10 +5546,11 @@ bool Sema::CheckTemplateArgumentList(
if (ArgIdx < NumArgs) {
// Check the template argument we were given.
- if (CheckTemplateArgument(
- *Param, NewArgs[ArgIdx], Template, TemplateLoc, RAngleLoc,
- SugaredArgumentPack.size(), SugaredConverted, CanonicalConverted,
- CTAK_Specified, MatchedPackOnParmToNonPackOnArg))
+ if (CheckTemplateArgument(*Param, NewArgs[ArgIdx], Template, TemplateLoc,
+ RAngleLoc, SugaredArgumentPack.size(),
+ SugaredConverted, CanonicalConverted,
+ CTAK_Specified, /*PartialOrdering=*/false,
+ MatchedPackOnParmToNonPackOnArg))
return true;
CanonicalConverted.back().setIsDefaulted(
@@ -5715,7 +5716,7 @@ bool Sema::CheckTemplateArgumentList(
// Check the default template argument.
if (CheckTemplateArgument(*Param, Arg, Template, TemplateLoc, RAngleLoc, 0,
SugaredConverted, CanonicalConverted,
- CTAK_Specified,
+ CTAK_Specified, /*PartialOrdering=*/false,
/*MatchedPackOnParmToNonPackOnArg=*/nullptr))
return true;
@@ -7296,7 +7297,7 @@ static void DiagnoseTemplateParameterListArityMismatch(
bool Sema::CheckTemplateTemplateArgument(
TemplateTemplateParmDecl *Param, TemplateParameterList *Params,
- TemplateArgumentLoc &Arg, bool IsDeduced,
+ TemplateArgumentLoc &Arg, bool PartialOrdering,
bool *MatchedPackOnParmToNonPackOnArg) {
TemplateName Name = Arg.getArgument().getAsTemplateOrTemplatePattern();
auto [Template, DefaultArgs] = Name.getTemplateDeclAndDefaultArgs();
@@ -7341,8 +7342,8 @@ bool Sema::CheckTemplateTemplateArgument(
// A template-argument matches a template template-parameter P when P
// is at least as specialized as the template-argument A.
if (!isTemplateTemplateParameterAtLeastAsSpecializedAs(
- Params, Param, Template, DefaultArgs, Arg.getLocation(), IsDeduced,
- MatchedPackOnParmToNonPackOnArg))
+ Params, Param, Template, DefaultArgs, Arg.getLocation(),
+ PartialOrdering, MatchedPackOnParmToNonPackOnArg))
return true;
// P2113
// C++20[temp.func.order]p2
diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp
index 925d3cbf9310f7..b4abbf7265da9b 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -2955,7 +2955,7 @@ Sema::getIdentityTemplateArgumentLoc(NamedDecl *TemplateParm,
/// fully-converted template arguments.
static bool ConvertDeducedTemplateArgument(
Sema &S, NamedDecl *Param, DeducedTemplateArgument Arg, NamedDecl *Template,
- TemplateDeductionInfo &Info, bool IsDeduced,
+ TemplateDeductionInfo &Info, bool IsDeduced, bool PartialOrdering,
SmallVectorImpl<TemplateArgument> &SugaredOutput,
SmallVectorImpl<TemplateArgument> &CanonicalOutput) {
auto ConvertArg = [&](DeducedTemplateArgument Arg,
@@ -2976,7 +2976,7 @@ static bool ConvertDeducedTemplateArgument(
? (Arg.wasDeducedFromArrayBound() ? Sema::CTAK_DeducedFromArrayBound
: Sema::CTAK_Deduced)
: Sema::CTAK_Specified,
- &MatchedPackOnParmToNonPackOnArg);
+ PartialOrdering, &MatchedPackOnParmToNonPackOnArg);
if (MatchedPackOnParmToNonPackOnArg)
Info.setMatchedPackOnParmToNonPackOnArg();
return Res;
@@ -3062,9 +3062,9 @@ static TemplateDeductionResult ConvertDeducedTemplateArguments(
SmallVectorImpl<DeducedTemplateArgument> &Deduced,
TemplateDeductionInfo &Info,
SmallVectorImpl<TemplateArgument> &SugaredBuilder,
- SmallVectorImpl<TemplateArgument> &CanonicalBuilder,
- LocalInstantiationScope *CurrentInstantiationScope = nullptr,
- unsigned NumAlreadyConverted = 0, bool *IsIncomplete = nullptr) {
+ SmallVectorImpl<TemplateArgument> &CanonicalBuilder, bool PartialOrdering,
+ LocalInstantiationScope *CurrentInstantiationScope,
+ unsigned NumAlreadyConverted, bool *IsIncomplete) {
TemplateParameterList *TemplateParams = Template->getTemplateParameters();
for (unsigned I = 0, N = TemplateParams->size(); I != N; ++I) {
@@ -3107,8 +3107,8 @@ static TemplateDeductionResult ConvertDeducedTemplateArguments(
// We may have deduced this argument, so it still needs to be
// checked and converted.
if (ConvertDeducedTemplateArgument(S, Param, Deduced[I], Template, Info,
- IsDeduced, SugaredBuilder,
- CanonicalBuilder)) {
+ IsDeduced, PartialOrdering,
+ SugaredBuilder, CanonicalBuilder)) {
Info.Param = makeTemplateParameter(Param);
// FIXME: These template arguments are temporary. Free them!
Info.reset(
@@ -3172,10 +3172,11 @@ static TemplateDeductionResult ConvertDeducedTemplateArguments(
}
// Check whether we can actually use the default argument.
- if (S.CheckTemplateArgument(
- Param, DefArg, TD, TD->getLocation(), TD->getSourceRange().getEnd(),
- 0, SugaredBuilder, CanonicalBuilder, Sema::CTAK_Specified,
- /*MatchedPackOnParmToNonPackOnArg=*/nullptr)) {
+ if (S.CheckTemplateArgument(Param, DefArg, TD, TD->getLocation(),
+ TD->getSourceRange().getEnd(), 0,
+ SugaredBuilder, CanonicalBuilder,
+ Sema::CTAK_Specified, /*PartialOrdering=*/false,
+ /*MatchedPackOnParmToNonPackOnArg=*/nullptr)) {
Info.Param = makeTemplateParameter(
const_cast<NamedDecl *>(TemplateParams->getParam(I)));
// FIXME: These template arguments are temporary. Free them!
@@ -3283,7 +3284,9 @@ FinishTemplateArgumentDeduction(
SmallVector<TemplateArgument, 4> SugaredBuilder, CanonicalBuilder;
if (auto Result = ConvertDeducedTemplateArguments(
S, Partial, IsPartialOrdering, Deduced, Info, SugaredBuilder,
- CanonicalBuilder);
+ CanonicalBuilder, IsPartialOrdering,
+ /*CurrentInstantiationScope=*/nullptr, /*NumAlreadyConverted=*/0,
+ /*IsIncomplete=*/nullptr);
Result != TemplateDeductionResult::Success)
return Result;
@@ -3383,10 +3386,10 @@ static TemplateDeductionResult FinishTemplateArgumentDeduction(
// explicitly specified, template argument deduction fails.
SmallVector<TemplateArgument, 4> SugaredBuilder, CanonicalBuilder;
if (auto Result = ConvertDeducedTemplateArguments(
- S, Template, /*IsDeduced*/ PartialOrdering, Deduced, Info,
- SugaredBuilder, CanonicalBuilder,
+ S, Template, /*IsDeduced=*/PartialOrdering, Deduced, Info,
+ SugaredBuilder, CanonicalBuilder, PartialOrdering,
/*CurrentInstantiationScope=*/nullptr,
- /*NumAlreadyConverted=*/0U);
+ /*NumAlreadyConverted=*/0U, /*IsIncomplete=*/nullptr);
Result != TemplateDeductionResult::Success)
return Result;
@@ -3456,7 +3459,9 @@ static TemplateDeductionResult FinishTemplateArgumentDeduction(
SmallVector<TemplateArgument, 4> SugaredBuilder, CanonicalBuilder;
if (auto Result = ConvertDeducedTemplateArguments(
S, TD, /*IsDeduced=*/false, Deduced, Info, SugaredBuilder,
- CanonicalBuilder);
+ CanonicalBuilder, /*PartialOrdering=*/false,
+ /*CurrentInstantiationScope=*/nullptr, /*NumAlreadyConverted=*/0,
+ /*IsIncomplete=*/nullptr);
Result != TemplateDeductionResult::Success)
return Result;
@@ -3994,7 +3999,8 @@ TemplateDeductionResult Sema::FinishTemplateArgumentDeduction(
unsigned NumExplicitlySpecified, FunctionDecl *&Specialization,
TemplateDeductionInfo &Info,
SmallVectorImpl<OriginalCallArg> const *OriginalCallArgs,
- bool PartialOverloading, llvm::function_ref<bool()> CheckNonDependent) {
+ bool PartialOverloading, bool PartialOrdering,
+ llvm::function_ref<bool()> CheckNonDependent) {
// Unevaluated SFINAE context.
EnterExpressionEvaluationContext Unevaluated(
*this, Sema::ExpressionEvaluationContext::Unevaluated);
@@ -4017,9 +4023,10 @@ TemplateDeductionResult Sema::FinishTemplateArgumentDeduction(
bool IsIncomplete = false;
SmallVector<TemplateArgument, 4> SugaredBuilder, CanonicalBuilder;
if (auto Result = ConvertDeducedTemplateArguments(
- *this, FunctionTemplate, /*IsDeduced*/ true, Deduced, Info,
- SugaredBuilder, CanonicalBuilder, CurrentInstantiationScope,
- NumExplicitlySpecified, PartialOverloading ? &IsIncomplete : nullptr);
+ *this, FunctionTemplate, /*IsDeduced=*/true, Deduced, Info,
+ SugaredBuilder, CanonicalBuilder, PartialOrdering,
+ CurrentInstantiationScope, NumExplicitlySpecified,
+ PartialOverloading ? &IsIncomplete : nullptr);
Result != TemplateDeductionResult::Success)
return Result;
@@ -4551,7 +4558,8 @@ TemplateDeductionResult Sema::DeduceTemplateArguments(
TemplateArgumentListInfo *ExplicitTemplateArgs, ArrayRef<Expr *> Args,
FunctionDecl *&Specialization, TemplateDeductionInfo &Info,
bool PartialOverloading, bool AggregateDeductionCandidate,
- QualType ObjectType, Expr::Classification ObjectClassification,
+ bool PartialOrdering, QualType ObjectType,
+ Expr::Classification ObjectClassification,
llvm::function_ref<bool(ArrayRef<QualType>)> CheckNonDependent) {
if (FunctionTemplate->isInvalidDecl())
return TemplateDeductionResult::Invalid;
@@ -4766,7 +4774,8 @@ TemplateDeductionResult Sema::DeduceTemplateArguments(
runWithSufficientStackSpace(Info.getLocation(), [&] {
Result = FinishTemplateArgumentDeduction(
FunctionTemplate, Deduced, NumExplicitlySpecified, Specialization, Info,
- &OriginalCallArgs, PartialOverloading, [&, CallingCtx]() {
+ &OriginalCallArgs, PartialOverloading, PartialOrdering,
+ [&, CallingCtx]() {
ContextRAII SavedContext(*this, CallingCtx);
return CheckNonDependent(ParamTypesForArgChecking);
});
@@ -4878,9 +4887,10 @@ TemplateDeductionResult Sema::DeduceTemplateArguments(
TemplateDeductionResult Result;
runWithSufficientStackSpace(Info.getLocation(), [&] {
- Result = FinishTemplateArgumentDeduction(FunctionTemplate, Deduced,
- NumExplicitlySpecified,
- Specialization, Info);
+ Result = FinishTemplateArgumentDeduction(
+ FunctionTemplate, Deduced, NumExplicitlySpecified, Specialization, Info,
+ /*OriginalCallArgs=*/nullptr, /*PartialOverloading=*/false,
+ /*PartialOrdering=*/true);
});
if (Result != TemplateDeductionResult::Success)
return Result;
@@ -5060,9 +5070,10 @@ TemplateDeductionResult Sema::DeduceTemplateArguments(
FunctionDecl *ConversionSpecialized = nullptr;
TemplateDeductionResult Result;
runWithSufficientStackSpace(Info.getLocation(), [&] {
- Result = FinishTemplateArgumentDeduction(ConversionTemplate, Deduced, 0,
- ConversionSpecialized, Info,
- &OriginalCallArgs);
+ Result = FinishTemplateArgumentDeduction(
+ ConversionTemplate, Deduced, 0, ConversionSpecialized, Info,
+ &OriginalCallArgs, /*PartialOverloading=*/false,
+ /*PartialOrdering=*/true);
});
Specialization = cast_or_null<CXXConversionDecl>(ConversionSpecialized);
return Result;
@@ -5639,7 +5650,8 @@ static TemplateDeductionResult FinishTemplateArgumentDeduction(
SmallVector<TemplateArgument, 4> SugaredBuilder, CanonicalBuilder;
if (auto Result = ConvertDeducedTemplateArguments(
S, FTD, /*IsDeduced=*/true, Deduced, Info, SugaredBuilder,
- CanonicalBuilder, /*CurrentInstantiationScope=*/nullptr,
+ CanonicalBuilder, /*PartialOrdering=*/true,
+ /*CurrentInstantiationScope=*/nullptr,
/*NumAlreadyConverted=*/0, &IsIncomplete);
Result != TemplateDeductionResult::Success)
return Result;
@@ -6484,8 +6496,8 @@ bool Sema::isMoreSpecializedThanPrimary(
bool Sema::isTemplateTemplateParameterAtLeastAsSpecializedAs(
TemplateParameterList *P, TemplateDecl *PArg, TemplateDecl *AArg,
- const DefaultArguments &DefaultArgs, SourceLocation ArgLoc, bool IsDeduced,
- bool *MatchedPackOnParmToNonPackOnArg) {
+ const DefaultArguments &DefaultArgs, SourceLocation ArgLoc,
+ bool PartialOrdering, bool *MatchedPackOnParmToNonPackOnArg) {
// C++1z [temp.arg.template]p4: (DR 150)
// A template template-parameter P is at least as specialized as a
// template template-argument A if, given the following rewrite to two
@@ -6564,7 +6576,7 @@ bool Sema::isTemplateTemplateParameterAtLeastAsSpecializedAs(
switch (::DeduceTemplateArguments(
*this, A, AArgs, PArgs, Info, Deduced,
/*NumberOfArgumentsMustMatch=*/false, /*PartialOrdering=*/true,
- IsDeduced ? PackFold::ArgumentToParameter : PackFold::Both,
+ PartialOrdering ? PackFold::ArgumentToParameter : PackFold::Both,
/*HasDeducedAnyParam=*/nullptr)) {
case clang::TemplateDeductionResult::Success:
if (MatchedPackOnParmToNonPackOnArg &&
diff --git a/clang/test/SemaTemplate/cwg2398.cpp b/clang/test/SemaTemplate/cwg2398.cpp
index b161b5a542b38f..a7ff06748068d5 100644
--- a/clang/test/SemaTemplate/cwg2398.cpp
+++ b/clang/test/SemaTemplate/cwg2398.cpp
@@ -405,6 +405,40 @@ namespace packs {
} // namespace t4
} // namespace packs
+namespace fun_tmpl_call {
+ namespace t1 {
+ template <template <class> class TT> void f(TT<int>) {};
+ // old-note at -1 {{has different template parameters}}
+ template <class...> struct A {};
+ void test() { f(A<int>()); }
+ // old-error at -1 {{no matching function for call to 'f'}}
+ } // namespace t1
+ namespace t2 {
+ template...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/111457
More information about the llvm-branch-commits
mailing list