@@ -5498,7 +5498,8 @@ bool Sema::CheckTemplateArgumentList(
5498
5498
DefaultArgs && ParamIdx >= DefaultArgs.StartPos ) {
5499
5499
// All written arguments should have been consumed by this point.
5500
5500
assert (ArgIdx == NumArgs && " bad default argument deduction" );
5501
- if (ParamIdx == DefaultArgs.StartPos ) {
5501
+ // FIXME: Don't ignore parameter packs.
5502
+ if (ParamIdx == DefaultArgs.StartPos && !(*Param)->isParameterPack ()) {
5502
5503
assert (Param + DefaultArgs.Args .size () <= ParamEnd);
5503
5504
// Default arguments from a DeducedTemplateName are already converted.
5504
5505
for (const TemplateArgument &DefArg : DefaultArgs.Args ) {
@@ -5575,6 +5576,9 @@ bool Sema::CheckTemplateArgumentList(
5575
5576
return true ;
5576
5577
}
5577
5578
5579
+ // We're now done with this argument.
5580
+ ++ArgIdx;
5581
+
5578
5582
if ((*Param)->isTemplateParameterPack ()) {
5579
5583
// The template parameter was a template parameter pack, so take the
5580
5584
// deduced argument and place it on the argument pack. Note that we
@@ -5585,19 +5589,8 @@ bool Sema::CheckTemplateArgumentList(
5585
5589
} else {
5586
5590
// Move to the next template parameter.
5587
5591
++Param;
5588
- if (PartialOrderingTTP && PackExpansionIntoNonPack) {
5589
- // Keep converting the pattern in the argument against
5590
- // subsequent parameters. The argument is converted
5591
- // in place and will be added back when we are done.
5592
- SugaredConverted.pop_back ();
5593
- CanonicalConverted.pop_back ();
5594
- continue ;
5595
- }
5596
5592
}
5597
5593
5598
- // We're now done with this argument.
5599
- ++ArgIdx;
5600
-
5601
5594
// If we just saw a pack expansion into a non-pack, then directly convert
5602
5595
// the remaining arguments, because we don't know what parameters they'll
5603
5596
// match up with.
@@ -5731,10 +5724,14 @@ bool Sema::CheckTemplateArgumentList(
5731
5724
// pack expansions; they might be empty. This can happen even if
5732
5725
// PartialTemplateArgs is false (the list of arguments is complete but
5733
5726
// still dependent).
5734
- while (ArgIdx < NumArgs && NewArgs[ArgIdx].getArgument ().isPackExpansion ()) {
5735
- const TemplateArgument &Arg = NewArgs[ArgIdx++].getArgument ();
5736
- SugaredConverted.push_back (Arg);
5737
- CanonicalConverted.push_back (Context.getCanonicalTemplateArgument (Arg));
5727
+ if (ArgIdx < NumArgs && CurrentInstantiationScope &&
5728
+ CurrentInstantiationScope->getPartiallySubstitutedPack ()) {
5729
+ while (ArgIdx < NumArgs &&
5730
+ NewArgs[ArgIdx].getArgument ().isPackExpansion ()) {
5731
+ const TemplateArgument &Arg = NewArgs[ArgIdx++].getArgument ();
5732
+ SugaredConverted.push_back (Arg);
5733
+ CanonicalConverted.push_back (Context.getCanonicalTemplateArgument (Arg));
5734
+ }
5738
5735
}
5739
5736
5740
5737
// If we have any leftover arguments, then there were too many arguments.
@@ -7324,46 +7321,64 @@ bool Sema::CheckTemplateTemplateArgument(TemplateTemplateParmDecl *Param,
7324
7321
<< Template;
7325
7322
}
7326
7323
7327
- if (!getLangOpts ().RelaxedTemplateTemplateArgs )
7328
- return !TemplateParameterListsAreEqual (
7329
- Template->getTemplateParameters (), Params, /* Complain=*/ true ,
7330
- TPL_TemplateTemplateArgumentMatch, Arg.getLocation ());
7331
-
7332
7324
// C++1z [temp.arg.template]p3: (DR 150)
7333
7325
// A template-argument matches a template template-parameter P when P
7334
7326
// is at least as specialized as the template-argument A.
7335
- if (!isTemplateTemplateParameterAtLeastAsSpecializedAs (
7336
- Params, Param, Template, DefaultArgs, Arg.getLocation (), IsDeduced))
7337
- return true ;
7338
- // P2113
7339
- // C++20[temp.func.order]p2
7340
- // [...] If both deductions succeed, the partial ordering selects the
7341
- // more constrained template (if one exists) as determined below.
7342
- SmallVector<const Expr *, 3 > ParamsAC, TemplateAC;
7343
- Params->getAssociatedConstraints (ParamsAC);
7344
- // C++20[temp.arg.template]p3
7345
- // [...] In this comparison, if P is unconstrained, the constraints on A
7346
- // are not considered.
7347
- if (ParamsAC.empty ())
7348
- return false ;
7327
+ if (getLangOpts ().RelaxedTemplateTemplateArgs ) {
7328
+ // Quick check for the common case:
7329
+ // If P contains a parameter pack, then A [...] matches P if each of A's
7330
+ // template parameters matches the corresponding template parameter in
7331
+ // the template-parameter-list of P.
7332
+ if (TemplateParameterListsAreEqual (
7333
+ Template->getTemplateParameters (), Params, false ,
7334
+ TPL_TemplateTemplateArgumentMatch, Arg.getLocation ()) &&
7335
+ // If the argument has no associated constraints, then the parameter is
7336
+ // definitely at least as specialized as the argument.
7337
+ // Otherwise - we need a more thorough check.
7338
+ !Template->hasAssociatedConstraints ())
7339
+ return false ;
7349
7340
7350
- Template->getAssociatedConstraints (TemplateAC);
7341
+ if (isTemplateTemplateParameterAtLeastAsSpecializedAs (
7342
+ Params, Template, DefaultArgs, Arg.getLocation (), IsDeduced)) {
7343
+ // P2113
7344
+ // C++20[temp.func.order]p2
7345
+ // [...] If both deductions succeed, the partial ordering selects the
7346
+ // more constrained template (if one exists) as determined below.
7347
+ SmallVector<const Expr *, 3 > ParamsAC, TemplateAC;
7348
+ Params->getAssociatedConstraints (ParamsAC);
7349
+ // C++2a[temp.arg.template]p3
7350
+ // [...] In this comparison, if P is unconstrained, the constraints on A
7351
+ // are not considered.
7352
+ if (ParamsAC.empty ())
7353
+ return false ;
7351
7354
7352
- bool IsParamAtLeastAsConstrained;
7353
- if (IsAtLeastAsConstrained (Param, ParamsAC, Template, TemplateAC,
7354
- IsParamAtLeastAsConstrained))
7355
- return true ;
7356
- if (!IsParamAtLeastAsConstrained) {
7357
- Diag (Arg.getLocation (),
7358
- diag::err_template_template_parameter_not_at_least_as_constrained)
7359
- << Template << Param << Arg.getSourceRange ();
7360
- Diag (Param->getLocation (), diag::note_entity_declared_at) << Param;
7361
- Diag (Template->getLocation (), diag::note_entity_declared_at) << Template;
7362
- MaybeEmitAmbiguousAtomicConstraintsDiagnostic (Param, ParamsAC, Template,
7363
- TemplateAC);
7364
- return true ;
7355
+ Template->getAssociatedConstraints (TemplateAC);
7356
+
7357
+ bool IsParamAtLeastAsConstrained;
7358
+ if (IsAtLeastAsConstrained (Param, ParamsAC, Template, TemplateAC,
7359
+ IsParamAtLeastAsConstrained))
7360
+ return true ;
7361
+ if (!IsParamAtLeastAsConstrained) {
7362
+ Diag (Arg.getLocation (),
7363
+ diag::err_template_template_parameter_not_at_least_as_constrained)
7364
+ << Template << Param << Arg.getSourceRange ();
7365
+ Diag (Param->getLocation (), diag::note_entity_declared_at) << Param;
7366
+ Diag (Template->getLocation (), diag::note_entity_declared_at)
7367
+ << Template;
7368
+ MaybeEmitAmbiguousAtomicConstraintsDiagnostic (Param, ParamsAC, Template,
7369
+ TemplateAC);
7370
+ return true ;
7371
+ }
7372
+ return false ;
7373
+ }
7374
+ // FIXME: Produce better diagnostics for deduction failures.
7365
7375
}
7366
- return false ;
7376
+
7377
+ return !TemplateParameterListsAreEqual (Template->getTemplateParameters (),
7378
+ Params,
7379
+ true ,
7380
+ TPL_TemplateTemplateArgumentMatch,
7381
+ Arg.getLocation ());
7367
7382
}
7368
7383
7369
7384
static Sema::SemaDiagnosticBuilder noteLocation (Sema &S, const NamedDecl &Decl,
0 commit comments