@@ -730,6 +730,7 @@ class PackDeductionScope {
730
730
void addPack (unsigned Index) {
731
731
// Save the deduced template argument for the parameter pack expanded
732
732
// by this pack expansion, then clear out the deduction.
733
+ DeducedFromEarlierParameter = !Deduced[Index].isNull ();
733
734
DeducedPack Pack (Index);
734
735
Pack.Saved = Deduced[Index];
735
736
Deduced[Index] = TemplateArgument ();
@@ -858,6 +859,29 @@ class PackDeductionScope {
858
859
Info.PendingDeducedPacks [Pack.Index ] = Pack.Outer ;
859
860
}
860
861
862
+ std::optional<unsigned > getSavedPackSize (unsigned Index,
863
+ TemplateArgument Pattern) const {
864
+
865
+ SmallVector<UnexpandedParameterPack, 2 > Unexpanded;
866
+ S.collectUnexpandedParameterPacks (Pattern, Unexpanded);
867
+ if (Unexpanded.size () == 0 ||
868
+ Packs[0 ].Saved .getKind () != clang::TemplateArgument::Pack)
869
+ return {};
870
+ unsigned PackSize = Packs[0 ].Saved .pack_size ();
871
+
872
+ if (std::all_of (Packs.begin () + 1 , Packs.end (),
873
+ [&PackSize](auto P) {
874
+ return P.Saved .getKind () == TemplateArgument::Pack &&
875
+ P.Saved .pack_size () == PackSize;
876
+ }))
877
+ return PackSize;
878
+ return {};
879
+ }
880
+
881
+ // / Determine whether this pack has already been deduced from a previous
882
+ // / argument.
883
+ bool isDeducedFromEarlierParameter () const {return DeducedFromEarlierParameter;}
884
+
861
885
// / Determine whether this pack has already been partially expanded into a
862
886
// / sequence of (prior) function parameters / template arguments.
863
887
bool isPartiallyExpanded () { return IsPartiallyExpanded; }
@@ -970,7 +994,6 @@ class PackDeductionScope {
970
994
NewPack = Pack.DeferredDeduction ;
971
995
Result = checkDeducedTemplateArguments (S.Context , OldPack, NewPack);
972
996
}
973
-
974
997
NamedDecl *Param = TemplateParams->getParam (Pack.Index );
975
998
if (Result.isNull ()) {
976
999
Info.Param = makeTemplateParameter (Param);
@@ -1003,9 +1026,12 @@ class PackDeductionScope {
1003
1026
unsigned PackElements = 0 ;
1004
1027
bool IsPartiallyExpanded = false ;
1005
1028
bool DeducePackIfNotAlreadyDeduced = false ;
1029
+ bool DeducedFromEarlierParameter = false ;
1030
+
1006
1031
// / The number of expansions, if we have a fully-expanded pack in this scope.
1007
1032
std::optional<unsigned > FixedNumExpansions;
1008
1033
1034
+
1009
1035
SmallVector<DeducedPack, 2 > Packs;
1010
1036
};
1011
1037
@@ -4371,6 +4397,41 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments(
4371
4397
// corresponding argument is a list?
4372
4398
PackScope.nextPackElement ();
4373
4399
}
4400
+ } else if (!IsTrailingPack && !PackScope.isPartiallyExpanded () &&
4401
+ PackScope.isDeducedFromEarlierParameter () &&
4402
+ !isa<PackExpansionType>(ParamTypes[ParamIdx + 1 ])) {
4403
+ // [temp.deduct.general#3]
4404
+ // When all template arguments have been deduced
4405
+ // or obtained from default template arguments, all uses of template
4406
+ // parameters in the template parameter list of the template are
4407
+ // replaced with the corresponding deduced or default argument values
4408
+ //
4409
+ // If we have a trailing parameter pack, that has been deduced perviously
4410
+ // we substitute the pack here in a similar fashion as seen above with
4411
+ // the trailing parameter packs. The main difference here is that, in
4412
+ // this case we are not processing all of the remaining arguments. We
4413
+ // are only process as many arguments as much we have in the already
4414
+ // deduced parameter.
4415
+ SmallVector<UnexpandedParameterPack, 2 > Unexpanded;
4416
+ collectUnexpandedParameterPacks (ParamPattern, Unexpanded);
4417
+ if (Unexpanded.size () == 0 )
4418
+ continue ;
4419
+
4420
+ std::optional<unsigned > ArgPosAfterSubstitution =
4421
+ PackScope.getSavedPackSize (getDepthAndIndex (Unexpanded[0 ]).second ,
4422
+ ParamPattern);
4423
+ if (!ArgPosAfterSubstitution)
4424
+ continue ;
4425
+
4426
+ unsigned PackArgEnd = ArgIdx + *ArgPosAfterSubstitution;
4427
+ for (; ArgIdx < PackArgEnd && ArgIdx < Args.size (); ArgIdx++) {
4428
+ ParamTypesForArgChecking.push_back (ParamPattern);
4429
+ if (auto Result = DeduceCallArgument (ParamPattern, ArgIdx,
4430
+ /* ExplicitObjetArgument=*/ false ))
4431
+ return Result;
4432
+
4433
+ PackScope.nextPackElement ();
4434
+ }
4374
4435
}
4375
4436
}
4376
4437
0 commit comments