diff --git a/clang/include/clang/Sema/Overload.h b/clang/include/clang/Sema/Overload.h index c716a25bb673b8..d38278c5041118 100644 --- a/clang/include/clang/Sema/Overload.h +++ b/clang/include/clang/Sema/Overload.h @@ -925,6 +925,11 @@ class Sema; bool TookAddressOfOverload : 1; + /// Have we matched any packs on the parameter side, versus any non-packs on + /// the argument side, in a context where the opposite matching is also + /// allowed? + bool HasMatchedPackOnParmToNonPackOnArg : 1; + /// True if the candidate was found using ADL. CallExpr::ADLCallKind IsADLCandidate : 1; @@ -999,8 +1004,9 @@ class Sema; friend class OverloadCandidateSet; OverloadCandidate() : IsSurrogate(false), IgnoreObjectArgument(false), - TookAddressOfOverload(false), IsADLCandidate(CallExpr::NotADL), - RewriteKind(CRK_None) {} + TookAddressOfOverload(false), + HasMatchedPackOnParmToNonPackOnArg(false), + IsADLCandidate(CallExpr::NotADL), RewriteKind(CRK_None) {} }; /// OverloadCandidateSet - A set of overload candidates, used in C++ diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index d73b7dc2ab62a2..ef010fafb1573e 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -10133,7 +10133,8 @@ class Sema final : public SemaBase { ADLCallKind IsADLCandidate = ADLCallKind::NotADL, ConversionSequenceList EarlyConversions = std::nullopt, OverloadCandidateParamOrder PO = {}, - bool AggregateCandidateDeduction = false); + bool AggregateCandidateDeduction = false, + bool HasMatchedPackOnParmToNonPackOnArg = false); /// Add all of the function declarations in the given function set to /// the overload candidate set. @@ -10168,7 +10169,8 @@ class Sema final : public SemaBase { bool SuppressUserConversions = false, bool PartialOverloading = false, ConversionSequenceList EarlyConversions = std::nullopt, - OverloadCandidateParamOrder PO = {}); + OverloadCandidateParamOrder PO = {}, + bool HasMatchedPackOnParmToNonPackOnArg = false); /// Add a C++ member function template as a candidate to the candidate /// set, using template argument deduction to produce an appropriate member @@ -10214,7 +10216,8 @@ class Sema final : public SemaBase { CXXConversionDecl *Conversion, DeclAccessPair FoundDecl, CXXRecordDecl *ActingContext, Expr *From, QualType ToType, OverloadCandidateSet &CandidateSet, bool AllowObjCConversionOnExplicit, - bool AllowExplicit, bool AllowResultConversion = true); + bool AllowExplicit, bool AllowResultConversion = true, + bool HasMatchedPackOnParmToNonPackOnArg = false); /// Adds a conversion function template specialization /// candidate to the overload set, using template argument deduction @@ -11637,7 +11640,7 @@ class Sema final : public SemaBase { SourceLocation RAngleLoc, unsigned ArgumentPackIndex, SmallVectorImpl &SugaredConverted, SmallVectorImpl &CanonicalConverted, - CheckTemplateArgumentKind CTAK, + CheckTemplateArgumentKind CTAK, bool PartialOrdering, bool *MatchedPackOnParmToNonPackOnArg); /// Check that the given template arguments can be provided to @@ -11720,7 +11723,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, @@ -12232,8 +12236,8 @@ class Sema final : public SemaBase { SmallVectorImpl &Deduced, unsigned NumExplicitlySpecified, FunctionDecl *&Specialization, sema::TemplateDeductionInfo &Info, - SmallVectorImpl const *OriginalCallArgs = nullptr, - bool PartialOverloading = false, + SmallVectorImpl const *OriginalCallArgs, + bool PartialOverloading, bool PartialOrdering, llvm::function_ref CheckNonDependent = [] { return false; }); /// Perform template argument deduction from a function call @@ -12267,7 +12271,8 @@ class Sema final : public SemaBase { TemplateArgumentListInfo *ExplicitTemplateArgs, ArrayRef 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)> CheckNonDependent); /// Deduce template arguments when taking the address of a function @@ -12422,7 +12427,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..f545e9341e1ae6 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -6864,7 +6864,8 @@ void Sema::AddOverloadCandidate( OverloadCandidateSet &CandidateSet, bool SuppressUserConversions, bool PartialOverloading, bool AllowExplicit, bool AllowExplicitConversions, ADLCallKind IsADLCandidate, ConversionSequenceList EarlyConversions, - OverloadCandidateParamOrder PO, bool AggregateCandidateDeduction) { + OverloadCandidateParamOrder PO, bool AggregateCandidateDeduction, + bool HasMatchedPackOnParmToNonPackOnArg) { const FunctionProtoType *Proto = dyn_cast(Function->getType()->getAs()); assert(Proto && "Functions without a prototype cannot be overloaded"); @@ -6883,7 +6884,8 @@ void Sema::AddOverloadCandidate( AddMethodCandidate(Method, FoundDecl, Method->getParent(), QualType(), Expr::Classification::makeSimpleLValue(), Args, CandidateSet, SuppressUserConversions, - PartialOverloading, EarlyConversions, PO); + PartialOverloading, EarlyConversions, PO, + HasMatchedPackOnParmToNonPackOnArg); return; } // We treat a constructor like a non-member function, since its object @@ -6926,6 +6928,8 @@ void Sema::AddOverloadCandidate( CandidateSet.getRewriteInfo().getRewriteKind(Function, PO); Candidate.IsADLCandidate = IsADLCandidate; Candidate.ExplicitCallArguments = Args.size(); + Candidate.HasMatchedPackOnParmToNonPackOnArg = + HasMatchedPackOnParmToNonPackOnArg; // Explicit functions are not actually candidates at all if we're not // allowing them in this context, but keep them around so we can point @@ -7453,16 +7457,13 @@ void Sema::AddMethodCandidate(DeclAccessPair FoundDecl, QualType ObjectType, } } -void -Sema::AddMethodCandidate(CXXMethodDecl *Method, DeclAccessPair FoundDecl, - CXXRecordDecl *ActingContext, QualType ObjectType, - Expr::Classification ObjectClassification, - ArrayRef Args, - OverloadCandidateSet &CandidateSet, - bool SuppressUserConversions, - bool PartialOverloading, - ConversionSequenceList EarlyConversions, - OverloadCandidateParamOrder PO) { +void Sema::AddMethodCandidate( + CXXMethodDecl *Method, DeclAccessPair FoundDecl, + CXXRecordDecl *ActingContext, QualType ObjectType, + Expr::Classification ObjectClassification, ArrayRef Args, + OverloadCandidateSet &CandidateSet, bool SuppressUserConversions, + bool PartialOverloading, ConversionSequenceList EarlyConversions, + OverloadCandidateParamOrder PO, bool HasMatchedPackOnParmToNonPackOnArg) { const FunctionProtoType *Proto = dyn_cast(Method->getType()->getAs()); assert(Proto && "Methods without a prototype cannot be overloaded"); @@ -7493,6 +7494,8 @@ Sema::AddMethodCandidate(CXXMethodDecl *Method, DeclAccessPair FoundDecl, Candidate.TookAddressOfOverload = CandidateSet.getKind() == OverloadCandidateSet::CSK_AddressOfOverloadSet; Candidate.ExplicitCallArguments = Args.size(); + Candidate.HasMatchedPackOnParmToNonPackOnArg = + HasMatchedPackOnParmToNonPackOnArg; bool IgnoreExplicitObject = (Method->isExplicitObjectMemberFunction() && @@ -7663,8 +7666,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 ParamTypes) { return CheckNonDependentConversions( MethodTmpl, ParamTypes, Args, CandidateSet, Conversions, @@ -7702,7 +7705,8 @@ void Sema::AddMethodTemplateCandidate( AddMethodCandidate(cast(Specialization), FoundDecl, ActingContext, ObjectType, ObjectClassification, Args, CandidateSet, SuppressUserConversions, PartialOverloading, - Conversions, PO); + Conversions, PO, + Info.hasMatchedPackOnParmToNonPackOnArg()); } /// Determine whether a given function template has a simple explicit specifier @@ -7748,6 +7752,7 @@ void Sema::AddTemplateOverloadCandidate( if (TemplateDeductionResult Result = DeduceTemplateArguments( FunctionTemplate, ExplicitTemplateArgs, Args, Specialization, Info, PartialOverloading, AggregateCandidateDeduction, + /*PartialOrdering=*/false, /*ObjectType=*/QualType(), /*ObjectClassification=*/Expr::Classification(), [&](ArrayRef ParamTypes) { @@ -7788,7 +7793,8 @@ void Sema::AddTemplateOverloadCandidate( Specialization, FoundDecl, Args, CandidateSet, SuppressUserConversions, PartialOverloading, AllowExplicit, /*AllowExplicitConversions=*/false, IsADLCandidate, Conversions, PO, - Info.AggregateDeductionCandidateHasMismatchedArity); + Info.AggregateDeductionCandidateHasMismatchedArity, + Info.hasMatchedPackOnParmToNonPackOnArg()); } bool Sema::CheckNonDependentConversions( @@ -7910,7 +7916,8 @@ void Sema::AddConversionCandidate( CXXConversionDecl *Conversion, DeclAccessPair FoundDecl, CXXRecordDecl *ActingContext, Expr *From, QualType ToType, OverloadCandidateSet &CandidateSet, bool AllowObjCConversionOnExplicit, - bool AllowExplicit, bool AllowResultConversion) { + bool AllowExplicit, bool AllowResultConversion, + bool HasMatchedPackOnParmToNonPackOnArg) { assert(!Conversion->getDescribedFunctionTemplate() && "Conversion function templates use AddTemplateConversionCandidate"); QualType ConvType = Conversion->getConversionType().getNonReferenceType(); @@ -7955,6 +7962,8 @@ void Sema::AddConversionCandidate( Candidate.FinalConversion.setAllToTypes(ToType); Candidate.Viable = true; Candidate.ExplicitCallArguments = 1; + Candidate.HasMatchedPackOnParmToNonPackOnArg = + HasMatchedPackOnParmToNonPackOnArg; // Explicit functions are not actually candidates at all if we're not // allowing them in this context, but keep them around so we can point @@ -8156,7 +8165,8 @@ void Sema::AddTemplateConversionCandidate( assert(Specialization && "Missing function template specialization?"); AddConversionCandidate(Specialization, FoundDecl, ActingDC, From, ToType, CandidateSet, AllowObjCConversionOnExplicit, - AllowExplicit, AllowResultConversion); + AllowExplicit, AllowResultConversion, + Info.hasMatchedPackOnParmToNonPackOnArg()); } void Sema::AddSurrogateCandidate(CXXConversionDecl *Conversion, @@ -10509,6 +10519,10 @@ bool clang::isBetterOverloadCandidate( isa(Cand2.Function)) return isa(Cand1.Function); + if (Cand1.HasMatchedPackOnParmToNonPackOnArg != + Cand2.HasMatchedPackOnParmToNonPackOnArg) + return Cand2.HasMatchedPackOnParmToNonPackOnArg; + // -- F1 is a non-template function and F2 is a function template // specialization, or, if not that, bool Cand1IsSpecialization = Cand1.Function && diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 4f13669c2490c0..62d0d0914fa306 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -5179,7 +5179,8 @@ bool Sema::CheckTemplateArgument( unsigned ArgumentPackIndex, SmallVectorImpl &SugaredConverted, SmallVectorImpl &CanonicalConverted, - CheckTemplateArgumentKind CTAK, bool *MatchedPackOnParmToNonPackOnArg) { + CheckTemplateArgumentKind CTAK, bool PartialOrdering, + bool *MatchedPackOnParmToNonPackOnArg) { // Check template type parameters. if (TemplateTypeParmDecl *TTP = dyn_cast(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( @@ -5707,7 +5708,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; @@ -7293,7 +7294,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(); @@ -7338,8 +7339,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 48a39a90f72a8b..e49d315f7186bc 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 &SugaredOutput, SmallVectorImpl &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 &Deduced, TemplateDeductionInfo &Info, SmallVectorImpl &SugaredBuilder, - SmallVectorImpl &CanonicalBuilder, - LocalInstantiationScope *CurrentInstantiationScope = nullptr, - unsigned NumAlreadyConverted = 0, bool *IsIncomplete = nullptr) { + SmallVectorImpl &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( @@ -3174,7 +3174,8 @@ 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, + /*ArgumentPackIndex=*/0, SugaredBuilder, CanonicalBuilder, + Sema::CTAK_Specified, /*PartialOrdering=*/false, /*MatchedPackOnParmToNonPackOnArg=*/nullptr)) { Info.Param = makeTemplateParameter( const_cast(TemplateParams->getParam(I))); @@ -3283,7 +3284,9 @@ FinishTemplateArgumentDeduction( SmallVector 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 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; @@ -3451,7 +3454,9 @@ static TemplateDeductionResult FinishTemplateArgumentDeduction( SmallVector 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; @@ -3989,7 +3994,8 @@ TemplateDeductionResult Sema::FinishTemplateArgumentDeduction( unsigned NumExplicitlySpecified, FunctionDecl *&Specialization, TemplateDeductionInfo &Info, SmallVectorImpl const *OriginalCallArgs, - bool PartialOverloading, llvm::function_ref CheckNonDependent) { + bool PartialOverloading, bool PartialOrdering, + llvm::function_ref CheckNonDependent) { // Unevaluated SFINAE context. EnterExpressionEvaluationContext Unevaluated( *this, Sema::ExpressionEvaluationContext::Unevaluated); @@ -4012,9 +4018,10 @@ TemplateDeductionResult Sema::FinishTemplateArgumentDeduction( bool IsIncomplete = false; SmallVector 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; @@ -4546,7 +4553,8 @@ TemplateDeductionResult Sema::DeduceTemplateArguments( TemplateArgumentListInfo *ExplicitTemplateArgs, ArrayRef Args, FunctionDecl *&Specialization, TemplateDeductionInfo &Info, bool PartialOverloading, bool AggregateDeductionCandidate, - QualType ObjectType, Expr::Classification ObjectClassification, + bool PartialOrdering, QualType ObjectType, + Expr::Classification ObjectClassification, llvm::function_ref)> CheckNonDependent) { if (FunctionTemplate->isInvalidDecl()) return TemplateDeductionResult::Invalid; @@ -4761,7 +4769,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); }); @@ -4873,9 +4882,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; @@ -5055,9 +5065,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=*/false); }); Specialization = cast_or_null(ConversionSpecialized); return Result; @@ -5634,7 +5645,8 @@ static TemplateDeductionResult FinishTemplateArgumentDeduction( SmallVector 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; @@ -6479,8 +6491,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 @@ -6559,7 +6571,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 56091e84cf4e95..3825239de4a285 100644 --- a/clang/test/SemaTemplate/cwg2398.cpp +++ b/clang/test/SemaTemplate/cwg2398.cpp @@ -405,6 +405,87 @@ namespace packs { } // namespace t4 } // namespace packs +namespace fun_tmpl_call { + namespace match_func { + template