Skip to content

Commit 28ad897

Browse files
authored
Reland: [clang] unified CWG2398 and P0522 changes; finishes implementation of P3310 (#124137)
This patch relands the following PRs: * #111711 * #107350 * #111457 All of these patches were reverted due to an issue reported in #111711 (comment), due to interdependencies. --- [clang] Finish implementation of P0522 This finishes the clang implementation of P0522, getting rid of the fallback to the old, pre-P0522 rules. Before this patch, when partial ordering template template parameters, we would perform, in order: * If the old rules would match, we would accept it. Otherwise, don't generate diagnostics yet. * If the new rules would match, just accept it. Otherwise, don't generate any diagnostics yet again. * Apply the old rules again, this time with diagnostics. This situation was far from ideal, as we would sometimes: * Accept some things we shouldn't. * Reject some things we shouldn't. * Only diagnose rejection in terms of the old rules. With this patch, we apply the P0522 rules throughout. This needed to extend template argument deduction in order to accept the historial rule for TTP matching pack parameter to non-pack arguments. This change also makes us accept some combinations of historical and P0522 allowances we wouldn't before. It also fixes a bunch of bugs that were documented in the test suite, which I am not sure there are issues already created for them. This causes a lot of changes to the way these failures are diagnosed, with related test suite churn. The problem here is that the old rules were very simple and non-recursive, making it easy to provide customized diagnostics, and to keep them consistent with each other. The new rules are a lot more complex and rely on template argument deduction, substitutions, and they are recursive. The approach taken here is to mostly rely on existing diagnostics, and create a new instantiation context that keeps track of this context. So for example when a substitution failure occurs, we use the error produced there unmodified, and just attach notes to it explaining that it occurred in the context of partial ordering this template argument against that template parameter. This diverges from the old diagnostics, which would lead with an error pointing to the template argument, explain the problem in subsequent notes, and produce a final note pointing to the parameter. --- [clang] CWG2398: improve overload resolution backwards compat With this change, we discriminate if the primary template and which partial specializations would have participated in overload resolution prior to P0522 changes. We collect those in an initial set. If this set is not empty, or the primary template would have matched, we proceed with this set as the candidates for overload resolution. Otherwise, we build a new overload set with everything else, and proceed as usual. --- [clang] Implement TTP 'reversed' pack matching for deduced function template calls. Clang previously missed implementing P0522 pack matching for deduced function template calls.
1 parent bc74a1e commit 28ad897

22 files changed

+1034
-404
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -325,6 +325,10 @@ C++20 Feature Support
325325

326326
- Implemented module level lookup for C++20 modules. (#GH90154)
327327

328+
C++17 Feature Support
329+
^^^^^^^^^^^^^^^^^^^^^
330+
- The implementation of the relaxed template template argument matching rules is
331+
more complete and reliable, and should provide more accurate diagnostics.
328332

329333
Resolutions to C++ Defect Reports
330334
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -351,7 +355,8 @@ Resolutions to C++ Defect Reports
351355
(`CWG2351: void{} <https://cplusplus.github.io/CWG/issues/2351.html>`_).
352356

353357
- Clang now has improved resolution to CWG2398, allowing class templates to have
354-
default arguments deduced when partial ordering.
358+
default arguments deduced when partial ordering, and better backwards compatibility
359+
in overload resolution.
355360

356361
- Clang now allows comparing unequal object pointers that have been cast to ``void *``
357362
in constant expressions. These comparisons always worked in non-constant expressions.
@@ -636,6 +641,10 @@ Improvements to Clang's diagnostics
636641

637642
- Clang now diagnoses when the result of a [[nodiscard]] function is discarded after being cast in C. Fixes #GH104391.
638643

644+
- Clang now properly explains the reason a template template argument failed to
645+
match a template template parameter, in terms of the C++17 relaxed matching rules
646+
instead of the old ones.
647+
639648
- Don't emit duplicated dangling diagnostics. (#GH93386).
640649

641650
- Improved diagnostic when trying to befriend a concept. (#GH45182).
@@ -887,6 +896,8 @@ Bug Fixes to C++ Support
887896
- Correctly check constraints of explicit instantiations of member functions. (#GH46029)
888897
- When performing partial ordering of function templates, clang now checks that
889898
the deduction was consistent. Fixes (#GH18291).
899+
- Fixes to several issues in partial ordering of template template parameters, which
900+
were documented in the test suite.
890901
- Fixed an assertion failure about a constraint of a friend function template references to a value with greater
891902
template depth than the friend function template. (#GH98258)
892903
- Clang now rebuilds the template parameters of out-of-line declarations and specializations in the context

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5323,6 +5323,13 @@ def note_template_arg_refers_here_func : Note<
53235323
def err_template_arg_template_params_mismatch : Error<
53245324
"template template argument has different template parameters than its "
53255325
"corresponding template template parameter">;
5326+
def note_template_arg_template_params_mismatch : Note<
5327+
"template template argument has different template parameters than its "
5328+
"corresponding template template parameter">;
5329+
def err_non_deduced_mismatch : Error<
5330+
"could not match %diff{$ against $|types}0,1">;
5331+
def err_inconsistent_deduction : Error<
5332+
"conflicting deduction %diff{$ against $|types}0,1 for parameter">;
53265333
def err_template_arg_not_integral_or_enumeral : Error<
53275334
"non-type template argument of type %0 must have an integral or enumeration"
53285335
" type">;

clang/include/clang/Sema/Overload.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -930,6 +930,11 @@ class Sema;
930930
LLVM_PREFERRED_TYPE(bool)
931931
unsigned TookAddressOfOverload : 1;
932932

933+
/// Have we matched any packs on the parameter side, versus any non-packs on
934+
/// the argument side, in a context where the opposite matching is also
935+
/// allowed?
936+
bool HasMatchedPackOnParmToNonPackOnArg : 1;
937+
933938
/// True if the candidate was found using ADL.
934939
LLVM_PREFERRED_TYPE(CallExpr::ADLCallKind)
935940
unsigned IsADLCandidate : 1;
@@ -1006,6 +1011,7 @@ class Sema;
10061011
OverloadCandidate()
10071012
: IsSurrogate(false), IgnoreObjectArgument(false),
10081013
TookAddressOfOverload(false),
1014+
HasMatchedPackOnParmToNonPackOnArg(false),
10091015
IsADLCandidate(llvm::to_underlying(CallExpr::NotADL)),
10101016
RewriteKind(CRK_None) {}
10111017
};

clang/include/clang/Sema/Sema.h

Lines changed: 31 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10169,7 +10169,8 @@ class Sema final : public SemaBase {
1016910169
ADLCallKind IsADLCandidate = ADLCallKind::NotADL,
1017010170
ConversionSequenceList EarlyConversions = {},
1017110171
OverloadCandidateParamOrder PO = {},
10172-
bool AggregateCandidateDeduction = false);
10172+
bool AggregateCandidateDeduction = false,
10173+
bool HasMatchedPackOnParmToNonPackOnArg = false);
1017310174

1017410175
/// Add all of the function declarations in the given function set to
1017510176
/// the overload candidate set.
@@ -10204,7 +10205,8 @@ class Sema final : public SemaBase {
1020410205
bool SuppressUserConversions = false,
1020510206
bool PartialOverloading = false,
1020610207
ConversionSequenceList EarlyConversions = {},
10207-
OverloadCandidateParamOrder PO = {});
10208+
OverloadCandidateParamOrder PO = {},
10209+
bool HasMatchedPackOnParmToNonPackOnArg = false);
1020810210

1020910211
/// Add a C++ member function template as a candidate to the candidate
1021010212
/// set, using template argument deduction to produce an appropriate member
@@ -10250,7 +10252,8 @@ class Sema final : public SemaBase {
1025010252
CXXConversionDecl *Conversion, DeclAccessPair FoundDecl,
1025110253
CXXRecordDecl *ActingContext, Expr *From, QualType ToType,
1025210254
OverloadCandidateSet &CandidateSet, bool AllowObjCConversionOnExplicit,
10253-
bool AllowExplicit, bool AllowResultConversion = true);
10255+
bool AllowExplicit, bool AllowResultConversion = true,
10256+
bool HasMatchedPackOnParmToNonPackOnArg = false);
1025410257

1025510258
/// Adds a conversion function template specialization
1025610259
/// candidate to the overload set, using template argument deduction
@@ -11678,7 +11681,8 @@ class Sema final : public SemaBase {
1167811681
SourceLocation RAngleLoc, unsigned ArgumentPackIndex,
1167911682
SmallVectorImpl<TemplateArgument> &SugaredConverted,
1168011683
SmallVectorImpl<TemplateArgument> &CanonicalConverted,
11681-
CheckTemplateArgumentKind CTAK);
11684+
CheckTemplateArgumentKind CTAK, bool PartialOrdering,
11685+
bool *MatchedPackOnParmToNonPackOnArg);
1168211686

1168311687
/// Check that the given template arguments can be provided to
1168411688
/// the given template, converting the arguments along the way.
@@ -11725,7 +11729,8 @@ class Sema final : public SemaBase {
1172511729
SmallVectorImpl<TemplateArgument> &SugaredConverted,
1172611730
SmallVectorImpl<TemplateArgument> &CanonicalConverted,
1172711731
bool UpdateArgsWithConversions = true,
11728-
bool *ConstraintsNotSatisfied = nullptr, bool PartialOrderingTTP = false);
11732+
bool *ConstraintsNotSatisfied = nullptr, bool PartialOrderingTTP = false,
11733+
bool *MatchedPackOnParmToNonPackOnArg = nullptr);
1172911734

1173011735
bool CheckTemplateTypeArgument(
1173111736
TemplateTypeParmDecl *Param, TemplateArgumentLoc &Arg,
@@ -11759,7 +11764,9 @@ class Sema final : public SemaBase {
1175911764
/// It returns true if an error occurred, and false otherwise.
1176011765
bool CheckTemplateTemplateArgument(TemplateTemplateParmDecl *Param,
1176111766
TemplateParameterList *Params,
11762-
TemplateArgumentLoc &Arg, bool IsDeduced);
11767+
TemplateArgumentLoc &Arg,
11768+
bool PartialOrdering,
11769+
bool *MatchedPackOnParmToNonPackOnArg);
1176311770

1176411771
void NoteTemplateLocation(const NamedDecl &Decl,
1176511772
std::optional<SourceRange> ParamRange = {});
@@ -12270,8 +12277,8 @@ class Sema final : public SemaBase {
1227012277
SmallVectorImpl<DeducedTemplateArgument> &Deduced,
1227112278
unsigned NumExplicitlySpecified, FunctionDecl *&Specialization,
1227212279
sema::TemplateDeductionInfo &Info,
12273-
SmallVectorImpl<OriginalCallArg> const *OriginalCallArgs = nullptr,
12274-
bool PartialOverloading = false,
12280+
SmallVectorImpl<OriginalCallArg> const *OriginalCallArgs,
12281+
bool PartialOverloading, bool PartialOrdering,
1227512282
llvm::function_ref<bool()> CheckNonDependent = [] { return false; });
1227612283

1227712284
/// Perform template argument deduction from a function call
@@ -12305,7 +12312,8 @@ class Sema final : public SemaBase {
1230512312
TemplateArgumentListInfo *ExplicitTemplateArgs, ArrayRef<Expr *> Args,
1230612313
FunctionDecl *&Specialization, sema::TemplateDeductionInfo &Info,
1230712314
bool PartialOverloading, bool AggregateDeductionCandidate,
12308-
QualType ObjectType, Expr::Classification ObjectClassification,
12315+
bool PartialOrdering, QualType ObjectType,
12316+
Expr::Classification ObjectClassification,
1230912317
llvm::function_ref<bool(ArrayRef<QualType>)> CheckNonDependent);
1231012318

1231112319
/// Deduce template arguments when taking the address of a function
@@ -12458,8 +12466,9 @@ class Sema final : public SemaBase {
1245812466
sema::TemplateDeductionInfo &Info);
1245912467

1246012468
bool isTemplateTemplateParameterAtLeastAsSpecializedAs(
12461-
TemplateParameterList *PParam, TemplateDecl *AArg,
12462-
const DefaultArguments &DefaultArgs, SourceLocation Loc, bool IsDeduced);
12469+
TemplateParameterList *PParam, TemplateDecl *PArg, TemplateDecl *AArg,
12470+
const DefaultArguments &DefaultArgs, SourceLocation ArgLoc,
12471+
bool PartialOrdering, bool *MatchedPackOnParmToNonPackOnArg);
1246312472

1246412473
/// Mark which template parameters are used in a given expression.
1246512474
///
@@ -12768,6 +12777,9 @@ class Sema final : public SemaBase {
1276812777

1276912778
/// We are instantiating a type alias template declaration.
1277012779
TypeAliasTemplateInstantiation,
12780+
12781+
/// We are performing partial ordering for template template parameters.
12782+
PartialOrderingTTP,
1277112783
} Kind;
1277212784

1277312785
/// Was the enclosing context a non-instantiation SFINAE context?
@@ -12989,6 +13001,12 @@ class Sema final : public SemaBase {
1298913001
TemplateDecl *Entity, BuildingDeductionGuidesTag,
1299013002
SourceRange InstantiationRange = SourceRange());
1299113003

13004+
struct PartialOrderingTTP {};
13005+
/// \brief Note that we are partial ordering template template parameters.
13006+
InstantiatingTemplate(Sema &SemaRef, SourceLocation ArgLoc,
13007+
PartialOrderingTTP, TemplateDecl *PArg,
13008+
SourceRange InstantiationRange = SourceRange());
13009+
1299213010
/// Note that we have finished instantiating this template.
1299313011
void Clear();
1299413012

@@ -13450,7 +13468,8 @@ class Sema final : public SemaBase {
1345013468
bool InstantiateClassTemplateSpecialization(
1345113469
SourceLocation PointOfInstantiation,
1345213470
ClassTemplateSpecializationDecl *ClassTemplateSpec,
13453-
TemplateSpecializationKind TSK, bool Complain = true);
13471+
TemplateSpecializationKind TSK, bool Complain = true,
13472+
bool PrimaryHasMatchedPackOnParmToNonPackOnArg = false);
1345413473

1345513474
/// Instantiates the definitions of all of the member
1345613475
/// of the given class, which is an instantiation of a class template

clang/include/clang/Sema/TemplateDeduction.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,11 @@ class TemplateDeductionInfo {
5151
/// Have we suppressed an error during deduction?
5252
bool HasSFINAEDiagnostic = false;
5353

54+
/// Have we matched any packs on the parameter side, versus any non-packs on
55+
/// the argument side, in a context where the opposite matching is also
56+
/// allowed?
57+
bool MatchedPackOnParmToNonPackOnArg = false;
58+
5459
/// The template parameter depth for which we're performing deduction.
5560
unsigned DeducedDepth;
5661

@@ -87,6 +92,14 @@ class TemplateDeductionInfo {
8792
return DeducedDepth;
8893
}
8994

95+
bool hasMatchedPackOnParmToNonPackOnArg() const {
96+
return MatchedPackOnParmToNonPackOnArg;
97+
}
98+
99+
void setMatchedPackOnParmToNonPackOnArg() {
100+
MatchedPackOnParmToNonPackOnArg = true;
101+
}
102+
90103
/// Get the number of explicitly-specified arguments.
91104
unsigned getNumExplicitArgs() const {
92105
return ExplicitArgs;

clang/lib/Frontend/FrontendActions.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -459,6 +459,8 @@ class DefaultTemplateInstCallback : public TemplateInstantiationCallback {
459459
return "BuildingDeductionGuides";
460460
case CodeSynthesisContext::TypeAliasTemplateInstantiation:
461461
return "TypeAliasTemplateInstantiation";
462+
case CodeSynthesisContext::PartialOrderingTTP:
463+
return "PartialOrderingTTP";
462464
}
463465
return "";
464466
}

clang/lib/Sema/SemaLookup.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3675,7 +3675,9 @@ Sema::LookupLiteralOperator(Scope *S, LookupResult &R,
36753675
TemplateArgumentLoc Arg(TemplateArgument(StringLit), StringLit);
36763676
if (CheckTemplateArgument(
36773677
Params->getParam(0), Arg, FD, R.getNameLoc(), R.getNameLoc(),
3678-
0, SugaredChecked, CanonicalChecked, CTAK_Specified) ||
3678+
0, SugaredChecked, CanonicalChecked, CTAK_Specified,
3679+
/*PartialOrdering=*/false,
3680+
/*MatchedPackOnParmToNonPackOnArg=*/nullptr) ||
36793681
Trap.hasErrorOccurred())
36803682
IsTemplate = false;
36813683
}

clang/lib/Sema/SemaOverload.cpp

Lines changed: 32 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -6917,7 +6917,8 @@ void Sema::AddOverloadCandidate(
69176917
OverloadCandidateSet &CandidateSet, bool SuppressUserConversions,
69186918
bool PartialOverloading, bool AllowExplicit, bool AllowExplicitConversions,
69196919
ADLCallKind IsADLCandidate, ConversionSequenceList EarlyConversions,
6920-
OverloadCandidateParamOrder PO, bool AggregateCandidateDeduction) {
6920+
OverloadCandidateParamOrder PO, bool AggregateCandidateDeduction,
6921+
bool HasMatchedPackOnParmToNonPackOnArg) {
69216922
const FunctionProtoType *Proto
69226923
= dyn_cast<FunctionProtoType>(Function->getType()->getAs<FunctionType>());
69236924
assert(Proto && "Functions without a prototype cannot be overloaded");
@@ -6936,7 +6937,8 @@ void Sema::AddOverloadCandidate(
69366937
AddMethodCandidate(Method, FoundDecl, Method->getParent(), QualType(),
69376938
Expr::Classification::makeSimpleLValue(), Args,
69386939
CandidateSet, SuppressUserConversions,
6939-
PartialOverloading, EarlyConversions, PO);
6940+
PartialOverloading, EarlyConversions, PO,
6941+
HasMatchedPackOnParmToNonPackOnArg);
69406942
return;
69416943
}
69426944
// We treat a constructor like a non-member function, since its object
@@ -6979,6 +6981,8 @@ void Sema::AddOverloadCandidate(
69796981
CandidateSet.getRewriteInfo().getRewriteKind(Function, PO);
69806982
Candidate.IsADLCandidate = llvm::to_underlying(IsADLCandidate);
69816983
Candidate.ExplicitCallArguments = Args.size();
6984+
Candidate.HasMatchedPackOnParmToNonPackOnArg =
6985+
HasMatchedPackOnParmToNonPackOnArg;
69826986

69836987
// Explicit functions are not actually candidates at all if we're not
69846988
// allowing them in this context, but keep them around so we can point
@@ -7521,16 +7525,13 @@ void Sema::AddMethodCandidate(DeclAccessPair FoundDecl, QualType ObjectType,
75217525
}
75227526
}
75237527

7524-
void
7525-
Sema::AddMethodCandidate(CXXMethodDecl *Method, DeclAccessPair FoundDecl,
7526-
CXXRecordDecl *ActingContext, QualType ObjectType,
7527-
Expr::Classification ObjectClassification,
7528-
ArrayRef<Expr *> Args,
7529-
OverloadCandidateSet &CandidateSet,
7530-
bool SuppressUserConversions,
7531-
bool PartialOverloading,
7532-
ConversionSequenceList EarlyConversions,
7533-
OverloadCandidateParamOrder PO) {
7528+
void Sema::AddMethodCandidate(
7529+
CXXMethodDecl *Method, DeclAccessPair FoundDecl,
7530+
CXXRecordDecl *ActingContext, QualType ObjectType,
7531+
Expr::Classification ObjectClassification, ArrayRef<Expr *> Args,
7532+
OverloadCandidateSet &CandidateSet, bool SuppressUserConversions,
7533+
bool PartialOverloading, ConversionSequenceList EarlyConversions,
7534+
OverloadCandidateParamOrder PO, bool HasMatchedPackOnParmToNonPackOnArg) {
75347535
const FunctionProtoType *Proto
75357536
= dyn_cast<FunctionProtoType>(Method->getType()->getAs<FunctionType>());
75367537
assert(Proto && "Methods without a prototype cannot be overloaded");
@@ -7561,6 +7562,8 @@ Sema::AddMethodCandidate(CXXMethodDecl *Method, DeclAccessPair FoundDecl,
75617562
Candidate.TookAddressOfOverload =
75627563
CandidateSet.getKind() == OverloadCandidateSet::CSK_AddressOfOverloadSet;
75637564
Candidate.ExplicitCallArguments = Args.size();
7565+
Candidate.HasMatchedPackOnParmToNonPackOnArg =
7566+
HasMatchedPackOnParmToNonPackOnArg;
75647567

75657568
bool IgnoreExplicitObject =
75667569
(Method->isExplicitObjectMemberFunction() &&
@@ -7731,8 +7734,8 @@ void Sema::AddMethodTemplateCandidate(
77317734
ConversionSequenceList Conversions;
77327735
if (TemplateDeductionResult Result = DeduceTemplateArguments(
77337736
MethodTmpl, ExplicitTemplateArgs, Args, Specialization, Info,
7734-
PartialOverloading, /*AggregateDeductionCandidate=*/false, ObjectType,
7735-
ObjectClassification,
7737+
PartialOverloading, /*AggregateDeductionCandidate=*/false,
7738+
/*PartialOrdering=*/false, ObjectType, ObjectClassification,
77367739
[&](ArrayRef<QualType> ParamTypes) {
77377740
return CheckNonDependentConversions(
77387741
MethodTmpl, ParamTypes, Args, CandidateSet, Conversions,
@@ -7770,7 +7773,8 @@ void Sema::AddMethodTemplateCandidate(
77707773
AddMethodCandidate(cast<CXXMethodDecl>(Specialization), FoundDecl,
77717774
ActingContext, ObjectType, ObjectClassification, Args,
77727775
CandidateSet, SuppressUserConversions, PartialOverloading,
7773-
Conversions, PO);
7776+
Conversions, PO,
7777+
Info.hasMatchedPackOnParmToNonPackOnArg());
77747778
}
77757779

77767780
/// Determine whether a given function template has a simple explicit specifier
@@ -7816,6 +7820,7 @@ void Sema::AddTemplateOverloadCandidate(
78167820
if (TemplateDeductionResult Result = DeduceTemplateArguments(
78177821
FunctionTemplate, ExplicitTemplateArgs, Args, Specialization, Info,
78187822
PartialOverloading, AggregateCandidateDeduction,
7823+
/*PartialOrdering=*/false,
78197824
/*ObjectType=*/QualType(),
78207825
/*ObjectClassification=*/Expr::Classification(),
78217826
[&](ArrayRef<QualType> ParamTypes) {
@@ -7856,7 +7861,8 @@ void Sema::AddTemplateOverloadCandidate(
78567861
Specialization, FoundDecl, Args, CandidateSet, SuppressUserConversions,
78577862
PartialOverloading, AllowExplicit,
78587863
/*AllowExplicitConversions=*/false, IsADLCandidate, Conversions, PO,
7859-
Info.AggregateDeductionCandidateHasMismatchedArity);
7864+
Info.AggregateDeductionCandidateHasMismatchedArity,
7865+
Info.hasMatchedPackOnParmToNonPackOnArg());
78607866
}
78617867

78627868
bool Sema::CheckNonDependentConversions(
@@ -7978,7 +7984,8 @@ void Sema::AddConversionCandidate(
79787984
CXXConversionDecl *Conversion, DeclAccessPair FoundDecl,
79797985
CXXRecordDecl *ActingContext, Expr *From, QualType ToType,
79807986
OverloadCandidateSet &CandidateSet, bool AllowObjCConversionOnExplicit,
7981-
bool AllowExplicit, bool AllowResultConversion) {
7987+
bool AllowExplicit, bool AllowResultConversion,
7988+
bool HasMatchedPackOnParmToNonPackOnArg) {
79827989
assert(!Conversion->getDescribedFunctionTemplate() &&
79837990
"Conversion function templates use AddTemplateConversionCandidate");
79847991
QualType ConvType = Conversion->getConversionType().getNonReferenceType();
@@ -8023,6 +8030,8 @@ void Sema::AddConversionCandidate(
80238030
Candidate.FinalConversion.setAllToTypes(ToType);
80248031
Candidate.Viable = true;
80258032
Candidate.ExplicitCallArguments = 1;
8033+
Candidate.HasMatchedPackOnParmToNonPackOnArg =
8034+
HasMatchedPackOnParmToNonPackOnArg;
80268035

80278036
// Explicit functions are not actually candidates at all if we're not
80288037
// allowing them in this context, but keep them around so we can point
@@ -8224,7 +8233,8 @@ void Sema::AddTemplateConversionCandidate(
82248233
assert(Specialization && "Missing function template specialization?");
82258234
AddConversionCandidate(Specialization, FoundDecl, ActingDC, From, ToType,
82268235
CandidateSet, AllowObjCConversionOnExplicit,
8227-
AllowExplicit, AllowResultConversion);
8236+
AllowExplicit, AllowResultConversion,
8237+
Info.hasMatchedPackOnParmToNonPackOnArg());
82288238
}
82298239

82308240
void Sema::AddSurrogateCandidate(CXXConversionDecl *Conversion,
@@ -10576,6 +10586,10 @@ bool clang::isBetterOverloadCandidate(
1057610586
isa<CXXConstructorDecl>(Cand2.Function))
1057710587
return isa<CXXConstructorDecl>(Cand1.Function);
1057810588

10589+
if (Cand1.HasMatchedPackOnParmToNonPackOnArg !=
10590+
Cand2.HasMatchedPackOnParmToNonPackOnArg)
10591+
return Cand2.HasMatchedPackOnParmToNonPackOnArg;
10592+
1057910593
// -- F1 is a non-template function and F2 is a function template
1058010594
// specialization, or, if not that,
1058110595
bool Cand1IsSpecialization = Cand1.Function &&

0 commit comments

Comments
 (0)