@@ -1187,9 +1187,8 @@ class PackDeductionScope {
1187
1187
1188
1188
template <class T >
1189
1189
static TemplateDeductionResult DeduceForEachType (
1190
- Sema &S, TemplateParameterList *TemplateParams, const QualType *Params,
1191
- unsigned NumParams, const QualType *Args, unsigned NumArgs,
1192
- TemplateDeductionInfo &Info,
1190
+ Sema &S, TemplateParameterList *TemplateParams, ArrayRef<QualType> Params,
1191
+ ArrayRef<QualType> Args, TemplateDeductionInfo &Info,
1193
1192
SmallVectorImpl<DeducedTemplateArgument> &Deduced, bool PartialOrdering,
1194
1193
bool FinishingDeduction, T &&DeductFunc) {
1195
1194
// C++0x [temp.deduct.type]p10:
@@ -1198,15 +1197,15 @@ static TemplateDeductionResult DeduceForEachType(
1198
1197
// corresponding parameter type Ai of the corresponding parameter-type-list
1199
1198
// of A. [...]
1200
1199
unsigned ArgIdx = 0 , ParamIdx = 0 ;
1201
- for (; ParamIdx != NumParams ; ++ParamIdx) {
1200
+ for (; ParamIdx != Params. size () ; ++ParamIdx) {
1202
1201
// Check argument types.
1203
1202
const PackExpansionType *Expansion
1204
1203
= dyn_cast<PackExpansionType>(Params[ParamIdx]);
1205
1204
if (!Expansion) {
1206
1205
// Simple case: compare the parameter and argument types at this point.
1207
1206
1208
1207
// Make sure we have an argument.
1209
- if (ArgIdx >= NumArgs )
1208
+ if (ArgIdx >= Args. size () )
1210
1209
return TemplateDeductionResult::MiscellaneousDeductionFailure;
1211
1210
1212
1211
if (isa<PackExpansionType>(Args[ArgIdx])) {
@@ -1243,8 +1242,8 @@ static TemplateDeductionResult DeduceForEachType(
1243
1242
1244
1243
// A pack scope with fixed arity is not really a pack any more, so is not
1245
1244
// a non-deduced context.
1246
- if (ParamIdx + 1 == NumParams || PackScope.hasFixedArity ()) {
1247
- for (; ArgIdx < NumArgs && PackScope.hasNextElement (); ++ArgIdx) {
1245
+ if (ParamIdx + 1 == Params. size () || PackScope.hasFixedArity ()) {
1246
+ for (; ArgIdx < Args. size () && PackScope.hasNextElement (); ++ArgIdx) {
1248
1247
// Deduce template arguments from the pattern.
1249
1248
if (TemplateDeductionResult Result = DeductFunc (
1250
1249
S, TemplateParams, ParamIdx, ArgIdx,
@@ -1274,7 +1273,7 @@ static TemplateDeductionResult DeduceForEachType(
1274
1273
// by the expansion.
1275
1274
std::optional<unsigned > NumExpansions = Expansion->getNumExpansions ();
1276
1275
if (NumExpansions && !PackScope.isPartiallyExpanded ()) {
1277
- for (unsigned I = 0 ; I != *NumExpansions && ArgIdx < NumArgs ;
1276
+ for (unsigned I = 0 ; I != *NumExpansions && ArgIdx < Args. size () ;
1278
1277
++I, ++ArgIdx)
1279
1278
PackScope.nextPackElement ();
1280
1279
}
@@ -1293,12 +1292,12 @@ static TemplateDeductionResult DeduceForEachType(
1293
1292
// During partial ordering, if Ai was originally a function parameter pack:
1294
1293
// - if P does not contain a function parameter type corresponding to Ai then
1295
1294
// Ai is ignored;
1296
- if (PartialOrdering && ArgIdx + 1 == NumArgs &&
1295
+ if (PartialOrdering && ArgIdx + 1 == Args. size () &&
1297
1296
isa<PackExpansionType>(Args[ArgIdx]))
1298
1297
return TemplateDeductionResult::Success;
1299
1298
1300
1299
// Make sure we don't have any extra arguments.
1301
- if (ArgIdx < NumArgs )
1300
+ if (ArgIdx < Args. size () )
1302
1301
return TemplateDeductionResult::MiscellaneousDeductionFailure;
1303
1302
1304
1303
return TemplateDeductionResult::Success;
@@ -1314,12 +1313,8 @@ static TemplateDeductionResult DeduceForEachType(
1314
1313
// /
1315
1314
// / \param Params The list of parameter types
1316
1315
// /
1317
- // / \param NumParams The number of types in \c Params
1318
- // /
1319
1316
// / \param Args The list of argument types
1320
1317
// /
1321
- // / \param NumArgs The number of types in \c Args
1322
- // /
1323
1318
// / \param Info information about the template argument deduction itself
1324
1319
// /
1325
1320
// / \param Deduced the deduced template arguments
@@ -1341,15 +1336,14 @@ static TemplateDeductionResult DeduceForEachType(
1341
1336
// / "success" result means that template argument deduction has not yet failed,
1342
1337
// / but it may still fail, later, for other reasons.
1343
1338
static TemplateDeductionResult DeduceTemplateArguments (
1344
- Sema &S, TemplateParameterList *TemplateParams, const QualType *Params,
1345
- unsigned NumParams, const QualType *Args, unsigned NumArgs,
1346
- TemplateDeductionInfo &Info,
1339
+ Sema &S, TemplateParameterList *TemplateParams, ArrayRef<QualType> Params,
1340
+ ArrayRef<QualType> Args, TemplateDeductionInfo &Info,
1347
1341
SmallVectorImpl<DeducedTemplateArgument> &Deduced, unsigned TDF,
1348
1342
bool PartialOrdering, bool *HasDeducedAnyParam,
1349
1343
llvm::SmallBitVector *HasDeducedParam) {
1350
1344
return ::DeduceForEachType (
1351
- S, TemplateParams, Params, NumParams, Args, NumArgs, Info, Deduced,
1352
- PartialOrdering, /* FinishingDeduction=*/ false ,
1345
+ S, TemplateParams, Params, Args, Info, Deduced, PartialOrdering ,
1346
+ /* FinishingDeduction=*/ false ,
1353
1347
[&](Sema &S, TemplateParameterList *TemplateParams, int ParamIdx,
1354
1348
int ArgIdx, QualType P, QualType A, TemplateDeductionInfo &Info,
1355
1349
SmallVectorImpl<DeducedTemplateArgument> &Deduced,
@@ -2028,9 +2022,8 @@ static TemplateDeductionResult DeduceTemplateArgumentsByTypeMatch(
2028
2022
2029
2023
// Check parameter types.
2030
2024
if (auto Result = DeduceTemplateArguments (
2031
- S, TemplateParams, FPP->param_type_begin (), FPP->getNumParams (),
2032
- FPA->param_type_begin (), FPA->getNumParams (), Info, Deduced,
2033
- TDF & TDF_TopLevelParameterTypeList, PartialOrdering,
2025
+ S, TemplateParams, FPP->param_types (), FPA->param_types (), Info,
2026
+ Deduced, TDF & TDF_TopLevelParameterTypeList, PartialOrdering,
2034
2027
HasDeducedAnyParam, /* HasDeducedParam=*/ nullptr );
2035
2028
Result != TemplateDeductionResult::Success)
2036
2029
return Result;
@@ -5623,135 +5616,109 @@ static bool isAtLeastAsSpecializedAs(Sema &S, SourceLocation Loc,
5623
5616
FunctionTemplateDecl *FT1,
5624
5617
FunctionTemplateDecl *FT2,
5625
5618
TemplatePartialOrderingContext TPOC,
5626
- bool Reversed,
5627
- const SmallVector<QualType> &Args1,
5628
- const SmallVector<QualType> &Args2) {
5629
- assert (!Reversed || TPOC == TPOC_Call);
5630
-
5619
+ ArrayRef<QualType> Args1,
5620
+ ArrayRef<QualType> Args2) {
5631
5621
FunctionDecl *FD1 = FT1->getTemplatedDecl ();
5632
5622
FunctionDecl *FD2 = FT2->getTemplatedDecl ();
5633
5623
const FunctionProtoType *Proto1 = FD1->getType ()->getAs <FunctionProtoType>();
5634
5624
const FunctionProtoType *Proto2 = FD2->getType ()->getAs <FunctionProtoType>();
5635
-
5636
5625
assert (Proto1 && Proto2 && " Function templates must have prototypes" );
5637
- TemplateParameterList *TemplateParams = FT2->getTemplateParameters ();
5638
- SmallVector<DeducedTemplateArgument, 4 > Deduced;
5639
- Deduced.resize (TemplateParams->size ());
5640
5626
5641
- // C++0x [temp.deduct.partial]p3:
5627
+ // C++26 [temp.deduct.partial]p3:
5642
5628
// The types used to determine the ordering depend on the context in which
5643
5629
// the partial ordering is done:
5644
- TemplateDeductionInfo Info (Loc);
5645
- switch (TPOC) {
5646
- case TPOC_Call: {
5647
- llvm::SmallBitVector HasDeducedParam (Args2.size ());
5648
- if (DeduceTemplateArguments (
5649
- S, TemplateParams, Args2.data (), Args2.size (), Args1.data (),
5650
- Args1.size (), Info, Deduced, TDF_None, /* PartialOrdering=*/ true ,
5651
- /* HasDeducedAnyParam=*/ nullptr ,
5652
- &HasDeducedParam) != TemplateDeductionResult::Success)
5653
- return false ;
5630
+ // - In the context of a function call, the types used are those function
5631
+ // parameter types for which the function call has arguments.
5632
+ // - In the context of a call to a conversion operator, the return types
5633
+ // of the conversion function templates are used.
5634
+ // - In other contexts (14.6.6.2) the function template's function type
5635
+ // is used.
5636
+
5637
+ if (TPOC == TPOC_Other) {
5638
+ // We wouldn't be partial ordering these candidates if these didn't match.
5639
+ assert (Proto1->getMethodQuals () == Proto2->getMethodQuals () &&
5640
+ Proto1->getRefQualifier () == Proto2->getRefQualifier () &&
5641
+ Proto1->isVariadic () == Proto2->isVariadic () &&
5642
+ " shouldn't partial order functions with different qualifiers in a "
5643
+ " context where the function type is used" );
5644
+
5645
+ assert (Args1.empty () && Args2.empty () &&
5646
+ " Only call context should have arguments" );
5647
+ Args1 = Proto1->getParamTypes ();
5648
+ Args2 = Proto2->getParamTypes ();
5649
+ }
5654
5650
5655
- SmallVector<TemplateArgument, 4 > DeducedArgs (Deduced.begin (),
5656
- Deduced.end ());
5657
- Sema::InstantiatingTemplate Inst (
5658
- S, Info.getLocation (), FT2, DeducedArgs,
5659
- Sema::CodeSynthesisContext::DeducedTemplateArgumentSubstitution, Info);
5660
- if (Inst.isInvalid ())
5661
- return false ;
5651
+ TemplateParameterList *TemplateParams = FT2->getTemplateParameters ();
5652
+ SmallVector<DeducedTemplateArgument, 4 > Deduced (TemplateParams->size ());
5653
+ TemplateDeductionInfo Info (Loc);
5662
5654
5663
- bool AtLeastAsSpecialized = true ;
5664
- S.runWithSufficientStackSpace (Info.getLocation (), [&] {
5665
- AtLeastAsSpecialized =
5666
- ::FinishTemplateArgumentDeduction (
5667
- S, FT2, Deduced, Info,
5668
- [&](Sema &S, FunctionTemplateDecl *FTD,
5669
- ArrayRef<TemplateArgument> DeducedArgs) {
5670
- return ::DeduceForEachType (
5671
- S, TemplateParams, Args2.data (), Args2.size (), Args1.data (),
5672
- Args1.size (), Info, Deduced,
5673
- /* PartialOrdering=*/ true , /* FinishingDeduction=*/ true ,
5674
- [&](Sema &S, TemplateParameterList *, int ParamIdx,
5675
- int ArgIdx, QualType P, QualType A,
5676
- TemplateDeductionInfo &Info,
5677
- SmallVectorImpl<DeducedTemplateArgument> &Deduced,
5678
- bool ) {
5679
- // As a provisional fix for a core issue that does not
5680
- // exist yet, only check the consistency of parameters
5681
- // which participated in deduction. We still try to
5682
- // substitute them though.
5683
- return ::CheckDeductionConsistency (
5684
- S, FTD, ArgIdx, P, A, DeducedArgs,
5685
- HasDeducedParam[ParamIdx]);
5686
- });
5687
- }) == TemplateDeductionResult::Success;
5688
- });
5689
- if (!AtLeastAsSpecialized)
5690
- return false ;
5691
- } break ;
5692
- case TPOC_Conversion:
5693
- case TPOC_Other: {
5694
- // - In the context of a call to a conversion operator, the return types
5695
- // of the conversion function templates are used.
5696
- // - In other contexts (14.6.6.2) the function template's function type
5697
- // is used.
5698
- auto [A, P, TDF] = TPOC == TPOC_Other
5699
- ? std::make_tuple (FD1->getType (), FD2->getType (),
5700
- TDF_AllowCompatibleFunctionType)
5701
- : std::make_tuple (Proto1->getReturnType (),
5702
- Proto2->getReturnType (), TDF_None);
5655
+ bool HasDeducedAnyParamFromReturnType = false ;
5656
+ if (TPOC != TPOC_Call) {
5703
5657
if (DeduceTemplateArgumentsByTypeMatch (
5704
- S, TemplateParams, P, A, Info, Deduced, TDF,
5658
+ S, TemplateParams, Proto2->getReturnType (), Proto1->getReturnType (),
5659
+ Info, Deduced, TDF_None,
5705
5660
/* PartialOrdering=*/ true , /* DeducedFromArrayBound=*/ false ,
5706
- /* HasDeducedAnyParam=*/ nullptr ) != TemplateDeductionResult::Success)
5661
+ &HasDeducedAnyParamFromReturnType) !=
5662
+ TemplateDeductionResult::Success)
5707
5663
return false ;
5664
+ }
5708
5665
5709
- SmallVector<TemplateArgument, 4 > DeducedArgs (Deduced.begin (),
5710
- Deduced.end ());
5711
- Sema::InstantiatingTemplate Inst (
5712
- S, Info.getLocation (), FT2, DeducedArgs,
5713
- Sema::CodeSynthesisContext::DeducedTemplateArgumentSubstitution, Info);
5714
- if (Inst.isInvalid ())
5666
+ llvm::SmallBitVector HasDeducedParam;
5667
+ if (TPOC != TPOC_Conversion) {
5668
+ HasDeducedParam.resize (Args2.size ());
5669
+ if (DeduceTemplateArguments (S, TemplateParams, Args2, Args1, Info, Deduced,
5670
+ TDF_None, /* PartialOrdering=*/ true ,
5671
+ /* HasDeducedAnyParam=*/ nullptr ,
5672
+ &HasDeducedParam) !=
5673
+ TemplateDeductionResult::Success)
5715
5674
return false ;
5675
+ }
5716
5676
5717
- bool AtLeastAsSpecialized;
5718
- S.runWithSufficientStackSpace (Info.getLocation (), [&] {
5719
- AtLeastAsSpecialized =
5720
- ::FinishTemplateArgumentDeduction (
5721
- S, FT2, Deduced, Info,
5722
- [&](Sema &S, FunctionTemplateDecl *FTD,
5723
- ArrayRef<TemplateArgument> DeducedArgs) {
5677
+ SmallVector<TemplateArgument, 4 > DeducedArgs (Deduced.begin (), Deduced.end ());
5678
+ Sema::InstantiatingTemplate Inst (
5679
+ S, Info.getLocation (), FT2, DeducedArgs,
5680
+ Sema::CodeSynthesisContext::DeducedTemplateArgumentSubstitution, Info);
5681
+ if (Inst.isInvalid ())
5682
+ return false ;
5683
+
5684
+ bool AtLeastAsSpecialized;
5685
+ S.runWithSufficientStackSpace (Info.getLocation (), [&] {
5686
+ AtLeastAsSpecialized =
5687
+ ::FinishTemplateArgumentDeduction (
5688
+ S, FT2, Deduced, Info,
5689
+ [&](Sema &S, FunctionTemplateDecl *FTD,
5690
+ ArrayRef<TemplateArgument> DeducedArgs) {
5691
+ // As a provisional fix for a core issue that does not
5692
+ // exist yet, which may be related to CWG2160, only check the
5693
+ // consistency of parameters and return types which participated
5694
+ // in deduction. We will still try to substitute them though.
5695
+ if (TPOC != TPOC_Call) {
5724
5696
if (auto TDR = ::CheckDeductionConsistency (
5725
5697
S, FTD, /* ArgIdx=*/ -1 , Proto2->getReturnType (),
5726
5698
Proto1->getReturnType (), DeducedArgs,
5727
- /* CheckConsistency=*/ true );
5699
+ /* CheckConsistency=*/ HasDeducedAnyParamFromReturnType );
5728
5700
TDR != TemplateDeductionResult::Success)
5729
5701
return TDR;
5702
+ }
5730
5703
5731
- if (TPOC != TPOC_Conversion)
5732
- return TemplateDeductionResult::Success;
5733
-
5734
- return ::DeduceForEachType (
5735
- S, TemplateParams, Proto2->getParamTypes ().data (),
5736
- Proto2->getParamTypes ().size (),
5737
- Proto1->getParamTypes ().data (),
5738
- Proto1->getParamTypes ().size (), Info, Deduced,
5739
- /* PartialOrdering=*/ true , /* FinishingDeduction=*/ true ,
5740
- [&](Sema &S, TemplateParameterList *, int ParamIdx,
5741
- int ArgIdx, QualType P, QualType A,
5742
- TemplateDeductionInfo &Info,
5743
- SmallVectorImpl<DeducedTemplateArgument> &Deduced,
5744
- bool ) {
5745
- return ::CheckDeductionConsistency (
5746
- S, FTD, ArgIdx, P, A, DeducedArgs,
5747
- /* CheckConsistency=*/ true );
5748
- });
5749
- }) == TemplateDeductionResult::Success;
5750
- });
5751
- if (!AtLeastAsSpecialized)
5752
- return false ;
5753
- } break ;
5754
- }
5704
+ if (TPOC == TPOC_Conversion)
5705
+ return TemplateDeductionResult::Success;
5706
+
5707
+ return ::DeduceForEachType (
5708
+ S, TemplateParams, Args2, Args1, Info, Deduced,
5709
+ /* PartialOrdering=*/ true , /* FinishingDeduction=*/ true ,
5710
+ [&](Sema &S, TemplateParameterList *, int ParamIdx,
5711
+ int ArgIdx, QualType P, QualType A,
5712
+ TemplateDeductionInfo &Info,
5713
+ SmallVectorImpl<DeducedTemplateArgument> &Deduced, bool ) {
5714
+ return ::CheckDeductionConsistency (
5715
+ S, FTD, ArgIdx, P, A, DeducedArgs,
5716
+ /* CheckConsistency=*/ HasDeducedParam[ParamIdx]);
5717
+ });
5718
+ }) == TemplateDeductionResult::Success;
5719
+ });
5720
+ if (!AtLeastAsSpecialized)
5721
+ return false ;
5755
5722
5756
5723
// C++0x [temp.deduct.partial]p11:
5757
5724
// In most cases, all template parameters must have values in order for
@@ -5907,11 +5874,13 @@ FunctionTemplateDecl *Sema::getMoreSpecializedTemplate(
5907
5874
5908
5875
if (Reversed)
5909
5876
std::reverse (Args2.begin (), Args2.end ());
5877
+ } else {
5878
+ assert (!Reversed && " Only call context could have reversed arguments" );
5910
5879
}
5911
- bool Better1 = isAtLeastAsSpecializedAs (* this , Loc, FT1, FT2, TPOC, Reversed,
5912
- Args1, Args2);
5913
- bool Better2 = isAtLeastAsSpecializedAs (* this , Loc, FT2, FT1, TPOC, Reversed,
5914
- Args2, Args1);
5880
+ bool Better1 =
5881
+ isAtLeastAsSpecializedAs (* this , Loc, FT1, FT2, TPOC, Args1, Args2);
5882
+ bool Better2 =
5883
+ isAtLeastAsSpecializedAs (* this , Loc, FT2, FT1, TPOC, Args2, Args1);
5915
5884
// C++ [temp.deduct.partial]p10:
5916
5885
// F is more specialized than G if F is at least as specialized as G and G
5917
5886
// is not at least as specialized as F.
0 commit comments