@@ -145,7 +145,7 @@ DeduceTemplateArguments(Sema &S, TemplateParameterList *TemplateParams,
145
145
ArrayRef<TemplateArgument> As,
146
146
TemplateDeductionInfo &Info,
147
147
SmallVectorImpl<DeducedTemplateArgument> &Deduced,
148
- bool NumberOfArgumentsMustMatch);
148
+ bool NumberOfArgumentsMustMatch, bool Swapped );
149
149
150
150
static void MarkUsedTemplateParameters (ASTContext &Ctx,
151
151
const TemplateArgument &TemplateArg,
@@ -703,9 +703,9 @@ DeduceTemplateSpecArguments(Sema &S, TemplateParameterList *TemplateParams,
703
703
// Perform template argument deduction on each template
704
704
// argument. Ignore any missing/extra arguments, since they could be
705
705
// filled in by default arguments.
706
- return DeduceTemplateArguments (S, TemplateParams, PResolved,
707
- SA->template_arguments (), Info, Deduced,
708
- /* NumberOfArgumentsMustMatch=*/ false );
706
+ return DeduceTemplateArguments (
707
+ S, TemplateParams, PResolved, SA->template_arguments (), Info, Deduced,
708
+ /* NumberOfArgumentsMustMatch= */ false , /* Swapped =*/ false );
709
709
}
710
710
711
711
// If the argument type is a class template specialization, we
@@ -731,7 +731,8 @@ DeduceTemplateSpecArguments(Sema &S, TemplateParameterList *TemplateParams,
731
731
// Perform template argument deduction for the template arguments.
732
732
return DeduceTemplateArguments (S, TemplateParams, PResolved,
733
733
SA->getTemplateArgs ().asArray (), Info, Deduced,
734
- /* NumberOfArgumentsMustMatch=*/ true );
734
+ /* NumberOfArgumentsMustMatch=*/ true ,
735
+ /* Swapped=*/ false );
735
736
}
736
737
737
738
static bool IsPossiblyOpaquelyQualifiedTypeInternal (const Type *T) {
@@ -2552,7 +2553,7 @@ DeduceTemplateArguments(Sema &S, TemplateParameterList *TemplateParams,
2552
2553
ArrayRef<TemplateArgument> As,
2553
2554
TemplateDeductionInfo &Info,
2554
2555
SmallVectorImpl<DeducedTemplateArgument> &Deduced,
2555
- bool NumberOfArgumentsMustMatch) {
2556
+ bool NumberOfArgumentsMustMatch, bool Swapped ) {
2556
2557
// C++0x [temp.deduct.type]p9:
2557
2558
// If the template argument list of P contains a pack expansion that is not
2558
2559
// the last template argument, the entire template argument list is a
@@ -2583,8 +2584,11 @@ DeduceTemplateArguments(Sema &S, TemplateParameterList *TemplateParams,
2583
2584
return TemplateDeductionResult::MiscellaneousDeductionFailure;
2584
2585
2585
2586
// Perform deduction for this Pi/Ai pair.
2586
- if (auto Result = DeduceTemplateArguments (S, TemplateParams, P,
2587
- As[ArgIdx], Info, Deduced);
2587
+ TemplateArgument Pi = P, Ai = As[ArgIdx];
2588
+ if (Swapped)
2589
+ std::swap (Pi, Ai);
2590
+ if (auto Result =
2591
+ DeduceTemplateArguments (S, TemplateParams, Pi, Ai, Info, Deduced);
2588
2592
Result != TemplateDeductionResult::Success)
2589
2593
return Result;
2590
2594
@@ -2611,9 +2615,12 @@ DeduceTemplateArguments(Sema &S, TemplateParameterList *TemplateParams,
2611
2615
for (; hasTemplateArgumentForDeduction (As, ArgIdx) &&
2612
2616
PackScope.hasNextElement ();
2613
2617
++ArgIdx) {
2618
+ TemplateArgument Pi = Pattern, Ai = As[ArgIdx];
2619
+ if (Swapped)
2620
+ std::swap (Pi, Ai);
2614
2621
// Deduce template arguments from the pattern.
2615
- if (auto Result = DeduceTemplateArguments (S, TemplateParams, Pattern,
2616
- As[ArgIdx] , Info, Deduced);
2622
+ if (auto Result =
2623
+ DeduceTemplateArguments (S, TemplateParams, Pi, Ai , Info, Deduced);
2617
2624
Result != TemplateDeductionResult::Success)
2618
2625
return Result;
2619
2626
@@ -2636,7 +2643,8 @@ TemplateDeductionResult Sema::DeduceTemplateArguments(
2636
2643
SmallVectorImpl<DeducedTemplateArgument> &Deduced,
2637
2644
bool NumberOfArgumentsMustMatch) {
2638
2645
return ::DeduceTemplateArguments (*this , TemplateParams, Ps, As, Info, Deduced,
2639
- NumberOfArgumentsMustMatch);
2646
+ NumberOfArgumentsMustMatch,
2647
+ /* Swapped=*/ false );
2640
2648
}
2641
2649
2642
2650
// / Determine whether two template arguments are the same.
@@ -3272,7 +3280,7 @@ DeduceTemplateArguments(Sema &S, T *Partial,
3272
3280
if (TemplateDeductionResult Result = ::DeduceTemplateArguments (
3273
3281
S, Partial->getTemplateParameters (),
3274
3282
Partial->getTemplateArgs ().asArray (), TemplateArgs, Info, Deduced,
3275
- /* NumberOfArgumentsMustMatch=*/ false );
3283
+ /* NumberOfArgumentsMustMatch=*/ false , /* Swapped= */ false );
3276
3284
Result != TemplateDeductionResult::Success)
3277
3285
return Result;
3278
3286
@@ -6187,7 +6195,8 @@ bool Sema::isMoreSpecializedThanPrimary(
6187
6195
}
6188
6196
6189
6197
bool Sema::isTemplateTemplateParameterAtLeastAsSpecializedAs (
6190
- TemplateParameterList *P, TemplateDecl *AArg, SourceLocation Loc) {
6198
+ TemplateParameterList *P, TemplateDecl *AArg, SourceLocation Loc,
6199
+ bool IsDeduced) {
6191
6200
// C++1z [temp.arg.template]p4: (DR 150)
6192
6201
// A template template-parameter P is at least as specialized as a
6193
6202
// template template-argument A if, given the following rewrite to two
@@ -6197,11 +6206,10 @@ bool Sema::isTemplateTemplateParameterAtLeastAsSpecializedAs(
6197
6206
// equivalent partial ordering by performing deduction directly on
6198
6207
// the template parameter lists of the template template parameters.
6199
6208
//
6200
- // Given an invented class template X with the template parameter list of
6201
- // A (including default arguments):
6202
- TemplateName X = Context.getCanonicalTemplateName (TemplateName (AArg));
6203
6209
TemplateParameterList *A = AArg->getTemplateParameters ();
6204
6210
6211
+ // Given an invented class template X with the template parameter list of
6212
+ // A (including default arguments):
6205
6213
// - Each function template has a single function parameter whose type is
6206
6214
// a specialization of X with template arguments corresponding to the
6207
6215
// template parameters from the respective function template
@@ -6242,14 +6250,45 @@ bool Sema::isTemplateTemplateParameterAtLeastAsSpecializedAs(
6242
6250
return false ;
6243
6251
}
6244
6252
6245
- QualType AType = Context.getCanonicalTemplateSpecializationType (X, AArgs);
6246
- QualType PType = Context.getCanonicalTemplateSpecializationType (X, PArgs);
6253
+ // Determine whether P1 is at least as specialized as P2.
6254
+ TemplateDeductionInfo Info (Loc, A->getDepth ());
6255
+ SmallVector<DeducedTemplateArgument, 4 > Deduced;
6256
+ Deduced.resize (A->size ());
6247
6257
6248
6258
// ... the function template corresponding to P is at least as specialized
6249
6259
// as the function template corresponding to A according to the partial
6250
6260
// ordering rules for function templates.
6251
- TemplateDeductionInfo Info (Loc, A->getDepth ());
6252
- return isAtLeastAsSpecializedAs (*this , PType, AType, AArg, Info);
6261
+
6262
+ // Provisional resolution for CWG2398: Regarding temp.arg.template]p4, when
6263
+ // applying the partial ordering rules for function templates on
6264
+ // the rewritten template template parameters:
6265
+ // - In a deduced context, the specific rules in [temp.deduct.type]p9
6266
+ // regarding how the argument lists themselves are matched is swapped
6267
+ // between P and A.
6268
+ // Note: The roles of the elements themselves are not swapped.
6269
+ ArrayRef<TemplateArgument> Ps = AArgs, As = PArgs;
6270
+ if (IsDeduced)
6271
+ std::swap (Ps, As);
6272
+ if (::DeduceTemplateArguments (*this , A, Ps, As, Info, Deduced,
6273
+ /* NumberOfArgumentsMustMatch=*/ false ,
6274
+ /* Swapped=*/ IsDeduced) !=
6275
+ TemplateDeductionResult::Success)
6276
+ return false ;
6277
+
6278
+ SmallVector<TemplateArgument, 4 > DeducedArgs (Deduced.begin (), Deduced.end ());
6279
+ Sema::InstantiatingTemplate Inst (*this , Info.getLocation (), AArg, DeducedArgs,
6280
+ Info);
6281
+ if (Inst.isInvalid ())
6282
+ return false ;
6283
+
6284
+ bool AtLeastAsSpecialized;
6285
+ runWithSufficientStackSpace (Info.getLocation (), [&] {
6286
+ AtLeastAsSpecialized =
6287
+ ::FinishTemplateArgumentDeduction (
6288
+ *this , AArg, /* IsPartialOrdering=*/ true , PArgs, Deduced, Info) ==
6289
+ TemplateDeductionResult::Success;
6290
+ });
6291
+ return AtLeastAsSpecialized;
6253
6292
}
6254
6293
6255
6294
namespace {
0 commit comments