@@ -5498,7 +5498,8 @@ bool Sema::CheckTemplateArgumentList(
54985498 DefaultArgs && ParamIdx >= DefaultArgs.StartPos ) {
54995499 // All written arguments should have been consumed by this point.
55005500 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 ()) {
55025503 assert (Param + DefaultArgs.Args .size () <= ParamEnd);
55035504 // Default arguments from a DeducedTemplateName are already converted.
55045505 for (const TemplateArgument &DefArg : DefaultArgs.Args ) {
@@ -5575,6 +5576,9 @@ bool Sema::CheckTemplateArgumentList(
55755576 return true ;
55765577 }
55775578
5579+ // We're now done with this argument.
5580+ ++ArgIdx;
5581+
55785582 if ((*Param)->isTemplateParameterPack ()) {
55795583 // The template parameter was a template parameter pack, so take the
55805584 // deduced argument and place it on the argument pack. Note that we
@@ -5585,19 +5589,8 @@ bool Sema::CheckTemplateArgumentList(
55855589 } else {
55865590 // Move to the next template parameter.
55875591 ++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- }
55965592 }
55975593
5598- // We're now done with this argument.
5599- ++ArgIdx;
5600-
56015594 // If we just saw a pack expansion into a non-pack, then directly convert
56025595 // the remaining arguments, because we don't know what parameters they'll
56035596 // match up with.
@@ -5731,10 +5724,14 @@ bool Sema::CheckTemplateArgumentList(
57315724 // pack expansions; they might be empty. This can happen even if
57325725 // PartialTemplateArgs is false (the list of arguments is complete but
57335726 // 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+ }
57385735 }
57395736
57405737 // If we have any leftover arguments, then there were too many arguments.
@@ -7324,46 +7321,64 @@ bool Sema::CheckTemplateTemplateArgument(TemplateTemplateParmDecl *Param,
73247321 << Template;
73257322 }
73267323
7327- if (!getLangOpts ().RelaxedTemplateTemplateArgs )
7328- return !TemplateParameterListsAreEqual (
7329- Template->getTemplateParameters (), Params, /* Complain=*/ true ,
7330- TPL_TemplateTemplateArgumentMatch, Arg.getLocation ());
7331-
73327324 // C++1z [temp.arg.template]p3: (DR 150)
73337325 // A template-argument matches a template template-parameter P when P
73347326 // 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 ;
73497340
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 ;
73517354
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.
73657375 }
7366- return false ;
7376+
7377+ return !TemplateParameterListsAreEqual (Template->getTemplateParameters (),
7378+ Params,
7379+ true ,
7380+ TPL_TemplateTemplateArgumentMatch,
7381+ Arg.getLocation ());
73677382}
73687383
73697384static Sema::SemaDiagnosticBuilder noteLocation (Sema &S, const NamedDecl &Decl,
0 commit comments