From 6bb6c305752adef5a0034e4a039df19487ce8945 Mon Sep 17 00:00:00 2001 From: Matheus Izvekov Date: Tue, 28 Jan 2025 19:39:08 -0300 Subject: [PATCH] [clang] NFC: cleanup check template argument (#124668) --- clang/include/clang/Sema/Sema.h | 70 +++-- clang/lib/Sema/SemaLookup.cpp | 6 +- clang/lib/Sema/SemaTemplate.cpp | 277 +++++++++--------- clang/lib/Sema/SemaTemplateDeduction.cpp | 208 +++++++------ .../lib/Sema/SemaTemplateInstantiateDecl.cpp | 47 +-- 5 files changed, 307 insertions(+), 301 deletions(-) diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 8a6dd4f6820bc..eb82d1b978e94 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -11651,6 +11651,33 @@ class Sema final : public SemaBase { CTAK_DeducedFromArrayBound }; + struct CheckTemplateArgumentInfo { + explicit CheckTemplateArgumentInfo(bool PartialOrdering = false, + bool MatchingTTP = false) + : PartialOrdering(PartialOrdering), MatchingTTP(MatchingTTP) {} + CheckTemplateArgumentInfo(const CheckTemplateArgumentInfo &) = delete; + CheckTemplateArgumentInfo & + operator=(const CheckTemplateArgumentInfo &) = delete; + + /// The checked, converted argument will be added to the + /// end of these vectors. + SmallVector SugaredConverted, CanonicalConverted; + + /// The check is being performed in the context of partial ordering. + bool PartialOrdering; + + /// If true, assume these template arguments are + /// the injected template arguments for a template template parameter. + /// This will relax the requirement that all its possible uses are valid: + /// TTP checking is loose, and assumes that invalid uses will be diagnosed + /// during instantiation. + bool MatchingTTP; + + /// Is set to true when, in the context of TTP matching, a pack parameter + /// matches non-pack arguments. + bool MatchedPackOnParmToNonPackOnArg = false; + }; + /// Check that the given template argument corresponds to the given /// template parameter. /// @@ -11670,22 +11697,16 @@ class Sema final : public SemaBase { /// \param ArgumentPackIndex The index into the argument pack where this /// argument will be placed. Only valid if the parameter is a parameter pack. /// - /// \param Converted The checked, converted argument will be added to the - /// end of this small vector. - /// /// \param CTAK Describes how we arrived at this particular template argument: /// explicitly written, deduced, etc. /// /// \returns true on error, false otherwise. - bool - CheckTemplateArgument(NamedDecl *Param, TemplateArgumentLoc &Arg, - NamedDecl *Template, SourceLocation TemplateLoc, - SourceLocation RAngleLoc, unsigned ArgumentPackIndex, - SmallVectorImpl &SugaredConverted, - SmallVectorImpl &CanonicalConverted, - CheckTemplateArgumentKind CTAK, bool PartialOrdering, - bool PartialOrderingTTP, - bool *MatchedPackOnParmToNonPackOnArg); + bool CheckTemplateArgument(NamedDecl *Param, TemplateArgumentLoc &Arg, + NamedDecl *Template, SourceLocation TemplateLoc, + SourceLocation RAngleLoc, + unsigned ArgumentPackIndex, + CheckTemplateArgumentInfo &CTAI, + CheckTemplateArgumentKind CTAK); /// Check that the given template arguments can be provided to /// the given template, converting the arguments along the way. @@ -11718,22 +11739,15 @@ class Sema final : public SemaBase { /// \param DefaultArgs any default arguments from template specialization /// deduction. /// - /// \param PartialOrderingTTP If true, assume these template arguments are - /// the injected template arguments for a template template parameter. - /// This will relax the requirement that all its possible uses are valid: - /// TTP checking is loose, and assumes that invalid uses will be diagnosed - /// during instantiation. - /// /// \returns true if an error occurred, false otherwise. - bool CheckTemplateArgumentList( - TemplateDecl *Template, SourceLocation TemplateLoc, - TemplateArgumentListInfo &TemplateArgs, - const DefaultArguments &DefaultArgs, bool PartialTemplateArgs, - SmallVectorImpl &SugaredConverted, - SmallVectorImpl &CanonicalConverted, - bool UpdateArgsWithConversions = true, - bool *ConstraintsNotSatisfied = nullptr, bool PartialOrderingTTP = false, - bool *MatchedPackOnParmToNonPackOnArg = nullptr); + bool CheckTemplateArgumentList(TemplateDecl *Template, + SourceLocation TemplateLoc, + TemplateArgumentListInfo &TemplateArgs, + const DefaultArguments &DefaultArgs, + bool PartialTemplateArgs, + CheckTemplateArgumentInfo &CTAI, + bool UpdateArgsWithConversions = true, + bool *ConstraintsNotSatisfied = nullptr); bool CheckTemplateTypeArgument( TemplateTypeParmDecl *Param, TemplateArgumentLoc &Arg, @@ -11758,7 +11772,7 @@ class Sema final : public SemaBase { QualType InstantiatedParamType, Expr *Arg, TemplateArgument &SugaredConverted, TemplateArgument &CanonicalConverted, - bool PartialOrderingTTP, + bool MatchingTTP, CheckTemplateArgumentKind CTAK); /// Check a template argument against its corresponding diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp index 641780fa072a5..0f5b7426e743e 100644 --- a/clang/lib/Sema/SemaLookup.cpp +++ b/clang/lib/Sema/SemaLookup.cpp @@ -3721,13 +3721,11 @@ Sema::LookupLiteralOperator(Scope *S, LookupResult &R, // is a well-formed template argument for the template parameter. if (StringLit) { SFINAETrap Trap(*this); - SmallVector SugaredChecked, CanonicalChecked; + CheckTemplateArgumentInfo CTAI; TemplateArgumentLoc Arg(TemplateArgument(StringLit), StringLit); if (CheckTemplateArgument( Params->getParam(0), Arg, FD, R.getNameLoc(), R.getNameLoc(), - 0, SugaredChecked, CanonicalChecked, CTAK_Specified, - /*PartialOrdering=*/false, /*PartialOrderingTTP=*/false, - /*MatchedPackOnParmToNonPackOnArg=*/nullptr) || + /*ArgumentPackIndex=*/0, CTAI, CTAK_Specified) || Trap.hasErrorOccurred()) IsTemplate = false; } diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index cb9d78734e6bb..3944c4f67bab9 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -38,6 +38,7 @@ #include "clang/Sema/TemplateDeduction.h" #include "llvm/ADT/SmallBitVector.h" #include "llvm/ADT/StringExtras.h" +#include "llvm/Support/SaveAndRestore.h" #include using namespace clang; @@ -3497,10 +3498,10 @@ QualType Sema::CheckTemplateIdType(TemplateName Name, // Check that the template argument list is well-formed for this // template. - SmallVector SugaredConverted, CanonicalConverted; + CheckTemplateArgumentInfo CTAI; if (CheckTemplateArgumentList(Template, TemplateLoc, TemplateArgs, - DefaultArgs, false, SugaredConverted, - CanonicalConverted, + DefaultArgs, /*PartialTemplateArgs=*/false, + CTAI, /*UpdateArgsWithConversions=*/true)) return QualType(); @@ -3522,7 +3523,7 @@ QualType Sema::CheckTemplateIdType(TemplateName Name, // template type alias specializations apart. MultiLevelTemplateArgumentList TemplateArgLists; TemplateArgLists.addOuterTemplateArguments( - Template, SugaredConverted, + Template, CTAI.SugaredConverted, /*Final=*/!getLangOpts().RetainSubstTemplateTypeParmTypeAstNodes); TemplateArgLists.addOuterRetainedLevels( AliasTemplate->getTemplateParameters()->getDepth()); @@ -3582,11 +3583,11 @@ QualType Sema::CheckTemplateIdType(TemplateName Name, return QualType(); } } else if (auto *BTD = dyn_cast(Template)) { - CanonType = checkBuiltinTemplateIdType(*this, BTD, SugaredConverted, + CanonType = checkBuiltinTemplateIdType(*this, BTD, CTAI.SugaredConverted, TemplateLoc, TemplateArgs); } else if (Name.isDependent() || TemplateSpecializationType::anyDependentTemplateArguments( - TemplateArgs, CanonicalConverted)) { + TemplateArgs, CTAI.CanonicalConverted)) { // This class template specialization is a dependent // type. Therefore, its canonical type is another class template // specialization type that contains all of the converted @@ -3595,7 +3596,7 @@ QualType Sema::CheckTemplateIdType(TemplateName Name, // // template struct A; CanonType = Context.getCanonicalTemplateSpecializationType( - Name, CanonicalConverted); + Name, CTAI.CanonicalConverted); // This might work out to be a current instantiation, in which // case the canonical type needs to be the InjectedClassNameType. @@ -3640,7 +3641,7 @@ QualType Sema::CheckTemplateIdType(TemplateName Name, // corresponds to these arguments. void *InsertPos = nullptr; ClassTemplateSpecializationDecl *Decl = - ClassTemplate->findSpecialization(CanonicalConverted, InsertPos); + ClassTemplate->findSpecialization(CTAI.CanonicalConverted, InsertPos); if (!Decl) { // This is the first time we have referenced this class template // specialization. Create the canonical declaration and add it to @@ -3649,7 +3650,7 @@ QualType Sema::CheckTemplateIdType(TemplateName Name, Context, ClassTemplate->getTemplatedDecl()->getTagKind(), ClassTemplate->getDeclContext(), ClassTemplate->getTemplatedDecl()->getBeginLoc(), - ClassTemplate->getLocation(), ClassTemplate, CanonicalConverted, + ClassTemplate->getLocation(), ClassTemplate, CTAI.CanonicalConverted, nullptr); ClassTemplate->AddSpecialization(Decl, InsertPos); if (ClassTemplate->isOutOfLine()) @@ -3661,7 +3662,7 @@ QualType Sema::CheckTemplateIdType(TemplateName Name, InstantiatingTemplate Inst(*this, TemplateLoc, Decl); if (!Inst.isInvalid()) { MultiLevelTemplateArgumentList TemplateArgLists(Template, - CanonicalConverted, + CTAI.CanonicalConverted, /*Final=*/false); InstantiateAttrsForDecl(TemplateArgLists, ClassTemplate->getTemplatedDecl(), Decl); @@ -4183,10 +4184,10 @@ DeclResult Sema::ActOnVarTemplateSpecialization( // Check that the template argument list is well-formed for this // template. - SmallVector SugaredConverted, CanonicalConverted; + CheckTemplateArgumentInfo CTAI; if (CheckTemplateArgumentList(VarTemplate, TemplateNameLoc, TemplateArgs, - /*DefaultArgs=*/{}, false, SugaredConverted, - CanonicalConverted, + /*DefaultArgs=*/{}, + /*PartialTemplateArgs=*/false, CTAI, /*UpdateArgsWithConversions=*/true)) return true; @@ -4195,21 +4196,21 @@ DeclResult Sema::ActOnVarTemplateSpecialization( if (IsPartialSpecialization) { if (CheckTemplatePartialSpecializationArgs(TemplateNameLoc, VarTemplate, TemplateArgs.size(), - CanonicalConverted)) + CTAI.CanonicalConverted)) return true; - // FIXME: Move these checks to CheckTemplatePartialSpecializationArgs so we - // also do them during instantiation. + // FIXME: Move these checks to CheckTemplatePartialSpecializationArgs so + // we also do them during instantiation. if (!Name.isDependent() && !TemplateSpecializationType::anyDependentTemplateArguments( - TemplateArgs, CanonicalConverted)) { + TemplateArgs, CTAI.CanonicalConverted)) { Diag(TemplateNameLoc, diag::err_partial_spec_fully_specialized) << VarTemplate->getDeclName(); IsPartialSpecialization = false; } if (isSameAsPrimaryTemplate(VarTemplate->getTemplateParameters(), - CanonicalConverted) && + CTAI.CanonicalConverted) && (!Context.getLangOpts().CPlusPlus20 || !TemplateParams->hasAssociatedConstraints())) { // C++ [temp.class.spec]p9b3: @@ -4217,11 +4218,11 @@ DeclResult Sema::ActOnVarTemplateSpecialization( // -- The argument list of the specialization shall not be identical // to the implicit argument list of the primary template. Diag(TemplateNameLoc, diag::err_partial_spec_args_match_primary_template) - << /*variable template*/ 1 - << /*is definition*/(SC != SC_Extern && !CurContext->isRecord()) - << FixItHint::CreateRemoval(SourceRange(LAngleLoc, RAngleLoc)); - // FIXME: Recover from this by treating the declaration as a redeclaration - // of the primary template. + << /*variable template*/ 1 + << /*is definition*/ (SC != SC_Extern && !CurContext->isRecord()) + << FixItHint::CreateRemoval(SourceRange(LAngleLoc, RAngleLoc)); + // FIXME: Recover from this by treating the declaration as a + // redeclaration of the primary template. return true; } } @@ -4231,9 +4232,10 @@ DeclResult Sema::ActOnVarTemplateSpecialization( if (IsPartialSpecialization) PrevDecl = VarTemplate->findPartialSpecialization( - CanonicalConverted, TemplateParams, InsertPos); + CTAI.CanonicalConverted, TemplateParams, InsertPos); else - PrevDecl = VarTemplate->findSpecialization(CanonicalConverted, InsertPos); + PrevDecl = + VarTemplate->findSpecialization(CTAI.CanonicalConverted, InsertPos); VarTemplateSpecializationDecl *Specialization = nullptr; @@ -4260,7 +4262,7 @@ DeclResult Sema::ActOnVarTemplateSpecialization( VarTemplatePartialSpecializationDecl::Create( Context, VarTemplate->getDeclContext(), TemplateKWLoc, TemplateNameLoc, TemplateParams, VarTemplate, DI->getType(), DI, SC, - CanonicalConverted); + CTAI.CanonicalConverted); Partial->setTemplateArgsAsWritten(TemplateArgs); if (!PrevPartial) @@ -4278,7 +4280,7 @@ DeclResult Sema::ActOnVarTemplateSpecialization( // this explicit specialization or friend declaration. Specialization = VarTemplateSpecializationDecl::Create( Context, VarTemplate->getDeclContext(), TemplateKWLoc, TemplateNameLoc, - VarTemplate, DI->getType(), DI, SC, CanonicalConverted); + VarTemplate, DI->getType(), DI, SC, CTAI.CanonicalConverted); Specialization->setTemplateArgsAsWritten(TemplateArgs); if (!PrevDecl) @@ -4350,25 +4352,25 @@ Sema::CheckVarTemplateId(VarTemplateDecl *Template, SourceLocation TemplateLoc, assert(Template && "A variable template id without template?"); // Check that the template argument list is well-formed for this template. - SmallVector SugaredConverted, CanonicalConverted; + CheckTemplateArgumentInfo CTAI; if (CheckTemplateArgumentList( Template, TemplateNameLoc, const_cast(TemplateArgs), - /*DefaultArgs=*/{}, false, SugaredConverted, CanonicalConverted, + /*DefaultArgs=*/{}, /*PartialTemplateArgs=*/false, CTAI, /*UpdateArgsWithConversions=*/true)) return true; // Produce a placeholder value if the specialization is dependent. if (Template->getDeclContext()->isDependentContext() || TemplateSpecializationType::anyDependentTemplateArguments( - TemplateArgs, CanonicalConverted)) + TemplateArgs, CTAI.CanonicalConverted)) return DeclResult(); // Find the variable template specialization declaration that // corresponds to these arguments. void *InsertPos = nullptr; if (VarTemplateSpecializationDecl *Spec = - Template->findSpecialization(CanonicalConverted, InsertPos)) { + Template->findSpecialization(CTAI.CanonicalConverted, InsertPos)) { checkSpecializationReachability(TemplateNameLoc, Spec); // If we already have a variable template specialization, return it. return Spec; @@ -4412,7 +4414,7 @@ Sema::CheckVarTemplateId(VarTemplateDecl *Template, SourceLocation TemplateLoc, TemplateDeductionInfo Info(FailedCandidates.getLocation()); if (TemplateDeductionResult Result = - DeduceTemplateArguments(Partial, SugaredConverted, Info); + DeduceTemplateArguments(Partial, CTAI.SugaredConverted, Info); Result != TemplateDeductionResult::Success) { // Store the failed-deduction information for use in diagnostics, later. // TODO: Actually use the failed-deduction info? @@ -4479,7 +4481,7 @@ Sema::CheckVarTemplateId(VarTemplateDecl *Template, SourceLocation TemplateLoc, // FIXME: LateAttrs et al.? VarTemplateSpecializationDecl *Decl = BuildVarTemplateInstantiation( Template, InstantiationPattern, PartialSpecArgs, TemplateArgs, - CanonicalConverted, TemplateNameLoc /*, LateAttrs, StartingScope*/); + CTAI.CanonicalConverted, TemplateNameLoc /*, LateAttrs, StartingScope*/); if (!Decl) return true; @@ -4559,12 +4561,12 @@ Sema::CheckConceptTemplateId(const CXXScopeSpec &SS, if (NamedConcept->isInvalidDecl()) return ExprError(); - llvm::SmallVector SugaredConverted, CanonicalConverted; + CheckTemplateArgumentInfo CTAI; if (CheckTemplateArgumentList( NamedConcept, ConceptNameInfo.getLoc(), const_cast(*TemplateArgs), /*DefaultArgs=*/{}, - /*PartialTemplateArgs=*/false, SugaredConverted, CanonicalConverted, + /*PartialTemplateArgs=*/false, CTAI, /*UpdateArgsWithConversions=*/false)) return ExprError(); @@ -4572,12 +4574,12 @@ Sema::CheckConceptTemplateId(const CXXScopeSpec &SS, auto *CSD = ImplicitConceptSpecializationDecl::Create( Context, NamedConcept->getDeclContext(), NamedConcept->getLocation(), - CanonicalConverted); + CTAI.CanonicalConverted); ConstraintSatisfaction Satisfaction; bool AreArgsDependent = TemplateSpecializationType::anyDependentTemplateArguments( - *TemplateArgs, CanonicalConverted); - MultiLevelTemplateArgumentList MLTAL(NamedConcept, CanonicalConverted, + *TemplateArgs, CTAI.CanonicalConverted); + MultiLevelTemplateArgumentList MLTAL(NamedConcept, CTAI.CanonicalConverted, /*Final=*/false); LocalInstantiationScope Scope(*this); @@ -5198,18 +5200,17 @@ convertTypeTemplateArgumentToTemplate(ASTContext &Context, TypeLoc TLoc) { return TemplateArgumentLoc(); } -bool Sema::CheckTemplateArgument( - NamedDecl *Param, TemplateArgumentLoc &ArgLoc, NamedDecl *Template, - SourceLocation TemplateLoc, SourceLocation RAngleLoc, - unsigned ArgumentPackIndex, - SmallVectorImpl &SugaredConverted, - SmallVectorImpl &CanonicalConverted, - CheckTemplateArgumentKind CTAK, bool PartialOrdering, - bool PartialOrderingTTP, bool *MatchedPackOnParmToNonPackOnArg) { +bool Sema::CheckTemplateArgument(NamedDecl *Param, TemplateArgumentLoc &ArgLoc, + NamedDecl *Template, + SourceLocation TemplateLoc, + SourceLocation RAngleLoc, + unsigned ArgumentPackIndex, + CheckTemplateArgumentInfo &CTAI, + CheckTemplateArgumentKind CTAK) { // Check template type parameters. if (TemplateTypeParmDecl *TTP = dyn_cast(Param)) - return CheckTemplateTypeArgument(TTP, ArgLoc, SugaredConverted, - CanonicalConverted); + return CheckTemplateTypeArgument(TTP, ArgLoc, CTAI.SugaredConverted, + CTAI.CanonicalConverted); const TemplateArgument &Arg = ArgLoc.getArgument(); // Check non-type template parameters. @@ -5226,12 +5227,12 @@ bool Sema::CheckTemplateArgument( !Template->getDeclContext()->isDependentContext()) { // Do substitution on the type of the non-type template parameter. InstantiatingTemplate Inst(*this, TemplateLoc, Template, NTTP, - SugaredConverted, + CTAI.SugaredConverted, SourceRange(TemplateLoc, RAngleLoc)); if (Inst.isInvalid()) return true; - MultiLevelTemplateArgumentList MLTAL(Template, SugaredConverted, + MultiLevelTemplateArgumentList MLTAL(Template, CTAI.SugaredConverted, /*Final=*/true); // If the parameter is a pack expansion, expand this slice of the pack. if (auto *PET = NTTPType->getAs()) { @@ -5258,12 +5259,12 @@ bool Sema::CheckTemplateArgument( unsigned CurSFINAEErrors = NumSFINAEErrors; ExprResult Res = CheckTemplateArgument(NTTP, NTTPType, E, SugaredResult, - CanonicalResult, PartialOrderingTTP, CTAK); + CanonicalResult, CTAI.MatchingTTP, CTAK); // If the current template argument causes an error, give up now. if (Res.isInvalid() || CurSFINAEErrors < NumSFINAEErrors) return nullptr; - SugaredConverted.push_back(SugaredResult); - CanonicalConverted.push_back(CanonicalResult); + CTAI.SugaredConverted.push_back(SugaredResult); + CTAI.CanonicalConverted.push_back(CanonicalResult); return Res.get(); }; @@ -5343,8 +5344,8 @@ bool Sema::CheckTemplateArgument( if (E.isInvalid()) return true; - SugaredConverted.push_back(SugaredResult); - CanonicalConverted.push_back(CanonicalResult); + CTAI.SugaredConverted.push_back(SugaredResult); + CTAI.CanonicalConverted.push_back(CanonicalResult); break; } @@ -5402,16 +5403,16 @@ bool Sema::CheckTemplateArgument( // Set up a template instantiation context. LocalInstantiationScope Scope(*this); InstantiatingTemplate Inst(*this, TemplateLoc, Template, TempParm, - SugaredConverted, + CTAI.SugaredConverted, SourceRange(TemplateLoc, RAngleLoc)); if (Inst.isInvalid()) return true; - Params = - SubstTemplateParams(Params, CurContext, - MultiLevelTemplateArgumentList( - Template, SugaredConverted, /*Final=*/true), - /*EvaluateConstraints=*/false); + Params = SubstTemplateParams( + Params, CurContext, + MultiLevelTemplateArgumentList(Template, CTAI.SugaredConverted, + /*Final=*/true), + /*EvaluateConstraints=*/false); if (!Params) return true; } @@ -5433,12 +5434,14 @@ bool Sema::CheckTemplateArgument( case TemplateArgument::Template: case TemplateArgument::TemplateExpansion: - if (CheckTemplateTemplateArgument(TempParm, Params, ArgLoc, PartialOrdering, - MatchedPackOnParmToNonPackOnArg)) + if (CheckTemplateTemplateArgument(TempParm, Params, ArgLoc, + CTAI.PartialOrdering, + &CTAI.MatchedPackOnParmToNonPackOnArg)) return true; - SugaredConverted.push_back(Arg); - CanonicalConverted.push_back(Context.getCanonicalTemplateArgument(Arg)); + CTAI.SugaredConverted.push_back(Arg); + CTAI.CanonicalConverted.push_back( + Context.getCanonicalTemplateArgument(Arg)); break; case TemplateArgument::Expression: @@ -5503,11 +5506,8 @@ static bool diagnoseMissingArgument(Sema &S, SourceLocation Loc, bool Sema::CheckTemplateArgumentList( TemplateDecl *Template, SourceLocation TemplateLoc, TemplateArgumentListInfo &TemplateArgs, const DefaultArguments &DefaultArgs, - bool PartialTemplateArgs, - SmallVectorImpl &SugaredConverted, - SmallVectorImpl &CanonicalConverted, - bool UpdateArgsWithConversions, bool *ConstraintsNotSatisfied, - bool PartialOrderingTTP, bool *MatchedPackOnParmToNonPackOnArg) { + bool PartialTemplateArgs, CheckTemplateArgumentInfo &CTAI, + bool UpdateArgsWithConversions, bool *ConstraintsNotSatisfied) { if (ConstraintsNotSatisfied) *ConstraintsNotSatisfied = false; @@ -5544,8 +5544,8 @@ bool Sema::CheckTemplateArgumentList( assert(Param + DefaultArgs.Args.size() <= ParamEnd); // Default arguments from a DeducedTemplateName are already converted. for (const TemplateArgument &DefArg : DefaultArgs.Args) { - SugaredConverted.push_back(DefArg); - CanonicalConverted.push_back( + CTAI.SugaredConverted.push_back(DefArg); + CTAI.CanonicalConverted.push_back( Context.getCanonicalTemplateArgument(DefArg)); ++Param; } @@ -5559,11 +5559,11 @@ bool Sema::CheckTemplateArgumentList( if (*Expansions == SugaredArgumentPack.size()) { // We're done with this parameter pack. Pack up its arguments and add // them to the list. - SugaredConverted.push_back( + CTAI.SugaredConverted.push_back( TemplateArgument::CreatePackCopy(Context, SugaredArgumentPack)); SugaredArgumentPack.clear(); - CanonicalConverted.push_back( + CTAI.CanonicalConverted.push_back( TemplateArgument::CreatePackCopy(Context, CanonicalArgumentPack)); CanonicalArgumentPack.clear(); @@ -5587,7 +5587,7 @@ bool Sema::CheckTemplateArgumentList( !(*Param)->isTemplateParameterPack() || getExpandedPackSize(*Param); bool ArgIsExpansion = ArgLoc.getArgument().isPackExpansion(); - if (ArgIsExpansion && PartialOrderingTTP) { + if (ArgIsExpansion && CTAI.MatchingTTP) { SmallVector Args(ParamEnd - Param); for (TemplateParameterList::iterator First = Param; Param != ParamEnd; ++Param) { @@ -5597,31 +5597,30 @@ bool Sema::CheckTemplateArgumentList( getExpandedPackSize(*Param)) Arg = Arg.getPackExpansionPattern(); TemplateArgumentLoc NewArgLoc(Arg, ArgLoc.getLocInfo()); - if (CheckTemplateArgument( - *Param, NewArgLoc, Template, TemplateLoc, RAngleLoc, - SugaredArgumentPack.size(), SugaredConverted, - CanonicalConverted, CTAK_Specified, /*PartialOrdering=*/false, - /*PartialOrderingTTP=*/true, MatchedPackOnParmToNonPackOnArg)) + SaveAndRestore _1(CTAI.PartialOrdering, false); + SaveAndRestore _2(CTAI.MatchingTTP, true); + if (CheckTemplateArgument(*Param, NewArgLoc, Template, TemplateLoc, + RAngleLoc, SugaredArgumentPack.size(), CTAI, + CTAK_Specified)) return true; Arg = NewArgLoc.getArgument(); - CanonicalConverted.back().setIsDefaulted( + CTAI.CanonicalConverted.back().setIsDefaulted( clang::isSubstitutedDefaultArgument(Context, Arg, *Param, - CanonicalConverted, + CTAI.CanonicalConverted, Params->getDepth())); } ArgLoc = TemplateArgumentLoc(TemplateArgument::CreatePackCopy(Context, Args), ArgLoc.getLocInfo()); } else { - if (CheckTemplateArgument( - *Param, ArgLoc, Template, TemplateLoc, RAngleLoc, - SugaredArgumentPack.size(), SugaredConverted, - CanonicalConverted, CTAK_Specified, /*PartialOrdering=*/false, - PartialOrderingTTP, MatchedPackOnParmToNonPackOnArg)) + SaveAndRestore _1(CTAI.PartialOrdering, false); + if (CheckTemplateArgument(*Param, ArgLoc, Template, TemplateLoc, + RAngleLoc, SugaredArgumentPack.size(), CTAI, + CTAK_Specified)) return true; - CanonicalConverted.back().setIsDefaulted( + CTAI.CanonicalConverted.back().setIsDefaulted( clang::isSubstitutedDefaultArgument(Context, ArgLoc.getArgument(), - *Param, CanonicalConverted, + *Param, CTAI.CanonicalConverted, Params->getDepth())); if (ArgIsExpansion && NonPackParameter) { // CWG1430/CWG2686: we have a pack expansion as an argument to an @@ -5641,28 +5640,28 @@ bool Sema::CheckTemplateArgumentList( // We're now done with this argument. ++ArgIdx; - if (ArgIsExpansion && (PartialOrderingTTP || NonPackParameter)) { + if (ArgIsExpansion && (CTAI.MatchingTTP || NonPackParameter)) { // Directly convert the remaining arguments, because we don't know what // parameters they'll match up with. if (!SugaredArgumentPack.empty()) { // If we were part way through filling in an expanded parameter pack, // fall back to just producing individual arguments. - SugaredConverted.insert(SugaredConverted.end(), - SugaredArgumentPack.begin(), - SugaredArgumentPack.end()); + CTAI.SugaredConverted.insert(CTAI.SugaredConverted.end(), + SugaredArgumentPack.begin(), + SugaredArgumentPack.end()); SugaredArgumentPack.clear(); - CanonicalConverted.insert(CanonicalConverted.end(), - CanonicalArgumentPack.begin(), - CanonicalArgumentPack.end()); + CTAI.CanonicalConverted.insert(CTAI.CanonicalConverted.end(), + CanonicalArgumentPack.begin(), + CanonicalArgumentPack.end()); CanonicalArgumentPack.clear(); } while (ArgIdx < NumArgs) { const TemplateArgument &Arg = NewArgs[ArgIdx].getArgument(); - SugaredConverted.push_back(Arg); - CanonicalConverted.push_back( + CTAI.SugaredConverted.push_back(Arg); + CTAI.CanonicalConverted.push_back( Context.getCanonicalTemplateArgument(Arg)); ++ArgIdx; } @@ -5675,8 +5674,8 @@ bool Sema::CheckTemplateArgumentList( // deduced argument and place it on the argument pack. Note that we // stay on the same template parameter so that we can deduce more // arguments. - SugaredArgumentPack.push_back(SugaredConverted.pop_back_val()); - CanonicalArgumentPack.push_back(CanonicalConverted.pop_back_val()); + SugaredArgumentPack.push_back(CTAI.SugaredConverted.pop_back_val()); + CanonicalArgumentPack.push_back(CTAI.CanonicalConverted.pop_back_val()); } else { // Move to the next template parameter. ++Param; @@ -5687,9 +5686,9 @@ bool Sema::CheckTemplateArgumentList( // If we're checking a partial template argument list, we're done. if (PartialTemplateArgs) { if ((*Param)->isTemplateParameterPack() && !SugaredArgumentPack.empty()) { - SugaredConverted.push_back( + CTAI.SugaredConverted.push_back( TemplateArgument::CreatePackCopy(Context, SugaredArgumentPack)); - CanonicalConverted.push_back( + CTAI.CanonicalConverted.push_back( TemplateArgument::CreatePackCopy(Context, CanonicalArgumentPack)); } return false; @@ -5711,11 +5710,11 @@ bool Sema::CheckTemplateArgumentList( return true; } - SugaredConverted.push_back( + CTAI.SugaredConverted.push_back( TemplateArgument::CreatePackCopy(Context, SugaredArgumentPack)); SugaredArgumentPack.clear(); - CanonicalConverted.push_back( + CTAI.CanonicalConverted.push_back( TemplateArgument::CreatePackCopy(Context, CanonicalArgumentPack)); CanonicalArgumentPack.clear(); @@ -5732,8 +5731,8 @@ bool Sema::CheckTemplateArgumentList( // (when the template parameter was part of a nested template) into // the default argument. TemplateArgumentLoc Arg = SubstDefaultTemplateArgumentIfAvailable( - Template, TemplateLoc, RAngleLoc, *Param, SugaredConverted, - CanonicalConverted, HasDefaultArg); + Template, TemplateLoc, RAngleLoc, *Param, CTAI.SugaredConverted, + CTAI.CanonicalConverted, HasDefaultArg); if (Arg.getArgument().isNull()) { if (!HasDefaultArg) { @@ -5756,21 +5755,21 @@ bool Sema::CheckTemplateArgumentList( // template here, we just create this object to put a note into the // context stack. InstantiatingTemplate Inst(*this, RAngleLoc, Template, *Param, - SugaredConverted, + CTAI.SugaredConverted, SourceRange(TemplateLoc, RAngleLoc)); if (Inst.isInvalid()) return true; + SaveAndRestore _1(CTAI.PartialOrdering, false); + SaveAndRestore _2(CTAI.MatchingTTP, false); + SaveAndRestore _3(CTAI.MatchedPackOnParmToNonPackOnArg, {}); // Check the default template argument. if (CheckTemplateArgument(*Param, Arg, Template, TemplateLoc, RAngleLoc, 0, - SugaredConverted, CanonicalConverted, - CTAK_Specified, /*PartialOrdering=*/false, - /*PartialOrderingTTP=*/false, - /*MatchedPackOnParmToNonPackOnArg=*/nullptr)) + CTAI, CTAK_Specified)) return true; - SugaredConverted.back().setIsDefaulted(true); - CanonicalConverted.back().setIsDefaulted(true); + CTAI.SugaredConverted.back().setIsDefaulted(true); + CTAI.CanonicalConverted.back().setIsDefaulted(true); // Core issue 150 (assumed resolution): if this is a template template // parameter, keep track of the default template arguments from the @@ -5787,14 +5786,15 @@ bool Sema::CheckTemplateArgumentList( // pack expansions; they might be empty. This can happen even if // PartialTemplateArgs is false (the list of arguments is complete but // still dependent). - if (PartialOrderingTTP || + if (CTAI.MatchingTTP || (CurrentInstantiationScope && CurrentInstantiationScope->getPartiallySubstitutedPack())) { while (ArgIdx < NumArgs && NewArgs[ArgIdx].getArgument().isPackExpansion()) { const TemplateArgument &Arg = NewArgs[ArgIdx++].getArgument(); - SugaredConverted.push_back(Arg); - CanonicalConverted.push_back(Context.getCanonicalTemplateArgument(Arg)); + CTAI.SugaredConverted.push_back(Arg); + CTAI.CanonicalConverted.push_back( + Context.getCanonicalTemplateArgument(Arg)); } } @@ -5835,7 +5835,7 @@ bool Sema::CheckTemplateArgumentList( CXXThisScopeRAII(*this, RD, ThisQuals, RD != nullptr); MultiLevelTemplateArgumentList MLTAL = getTemplateInstantiationArgs( - Template, NewContext, /*Final=*/false, CanonicalConverted, + Template, NewContext, /*Final=*/false, CTAI.CanonicalConverted, /*RelativeToPrimary=*/true, /*Pattern=*/nullptr, /*ForConceptInstantiation=*/true); @@ -8459,11 +8459,10 @@ DeclResult Sema::ActOnClassTemplateSpecialization( // Check that the template argument list is well-formed for this // template. - SmallVector SugaredConverted, CanonicalConverted; + CheckTemplateArgumentInfo CTAI; if (CheckTemplateArgumentList(ClassTemplate, TemplateNameLoc, TemplateArgs, /*DefaultArgs=*/{}, - /*PartialTemplateArgs=*/false, SugaredConverted, - CanonicalConverted, + /*PartialTemplateArgs=*/false, CTAI, /*UpdateArgsWithConversions=*/true)) return true; @@ -8472,14 +8471,14 @@ DeclResult Sema::ActOnClassTemplateSpecialization( if (isPartialSpecialization) { if (CheckTemplatePartialSpecializationArgs(TemplateNameLoc, ClassTemplate, TemplateArgs.size(), - CanonicalConverted)) + CTAI.CanonicalConverted)) return true; // FIXME: Move this to CheckTemplatePartialSpecializationArgs so we // also do it during instantiation. if (!Name.isDependent() && !TemplateSpecializationType::anyDependentTemplateArguments( - TemplateArgs, CanonicalConverted)) { + TemplateArgs, CTAI.CanonicalConverted)) { Diag(TemplateNameLoc, diag::err_partial_spec_fully_specialized) << ClassTemplate->getDeclName(); isPartialSpecialization = false; @@ -8492,9 +8491,10 @@ DeclResult Sema::ActOnClassTemplateSpecialization( if (isPartialSpecialization) PrevDecl = ClassTemplate->findPartialSpecialization( - CanonicalConverted, TemplateParams, InsertPos); + CTAI.CanonicalConverted, TemplateParams, InsertPos); else - PrevDecl = ClassTemplate->findSpecialization(CanonicalConverted, InsertPos); + PrevDecl = + ClassTemplate->findSpecialization(CTAI.CanonicalConverted, InsertPos); ClassTemplateSpecializationDecl *Specialization = nullptr; @@ -8513,7 +8513,7 @@ DeclResult Sema::ActOnClassTemplateSpecialization( // arguments of the class template partial specialization. TemplateName CanonTemplate = Context.getCanonicalTemplateName(Name); CanonType = Context.getTemplateSpecializationType(CanonTemplate, - CanonicalConverted); + CTAI.CanonicalConverted); if (Context.hasSameType(CanonType, ClassTemplate->getInjectedClassNameSpecialization()) && @@ -8543,7 +8543,7 @@ DeclResult Sema::ActOnClassTemplateSpecialization( ClassTemplatePartialSpecializationDecl *Partial = ClassTemplatePartialSpecializationDecl::Create( Context, Kind, DC, KWLoc, TemplateNameLoc, TemplateParams, - ClassTemplate, CanonicalConverted, CanonType, PrevPartial); + ClassTemplate, CTAI.CanonicalConverted, CanonType, PrevPartial); Partial->setTemplateArgsAsWritten(TemplateArgs); SetNestedNameSpecifier(*this, Partial, SS); if (TemplateParameterLists.size() > 1 && SS.isSet()) { @@ -8566,7 +8566,7 @@ DeclResult Sema::ActOnClassTemplateSpecialization( // this explicit specialization or friend declaration. Specialization = ClassTemplateSpecializationDecl::Create( Context, Kind, DC, KWLoc, TemplateNameLoc, ClassTemplate, - CanonicalConverted, PrevDecl); + CTAI.CanonicalConverted, PrevDecl); Specialization->setTemplateArgsAsWritten(TemplateArgs); SetNestedNameSpecifier(*this, Specialization, SS); if (TemplateParameterLists.size() > 0) { @@ -8579,8 +8579,8 @@ DeclResult Sema::ActOnClassTemplateSpecialization( if (CurContext->isDependentContext()) { TemplateName CanonTemplate = Context.getCanonicalTemplateName(Name); - CanonType = Context.getTemplateSpecializationType(CanonTemplate, - CanonicalConverted); + CanonType = Context.getTemplateSpecializationType( + CanonTemplate, CTAI.CanonicalConverted); } else { CanonType = Context.getTypeDeclType(Specialization); } @@ -9839,21 +9839,18 @@ DeclResult Sema::ActOnExplicitInstantiation( // Check that the template argument list is well-formed for this // template. - bool PrimaryHasMatchedPackOnParmToNonPackOnArg = false; - SmallVector SugaredConverted, CanonicalConverted; - if (CheckTemplateArgumentList( - ClassTemplate, TemplateNameLoc, TemplateArgs, - /*DefaultArgs=*/{}, false, SugaredConverted, CanonicalConverted, - /*UpdateArgsWithConversions=*/true, - /*ConstraintsNotSatisfied=*/nullptr, /*PartialOrderingTTP=*/false, - &PrimaryHasMatchedPackOnParmToNonPackOnArg)) + CheckTemplateArgumentInfo CTAI; + if (CheckTemplateArgumentList(ClassTemplate, TemplateNameLoc, TemplateArgs, + /*DefaultArgs=*/{}, false, CTAI, + /*UpdateArgsWithConversions=*/true, + /*ConstraintsNotSatisfied=*/nullptr)) return true; // Find the class template specialization declaration that // corresponds to these arguments. void *InsertPos = nullptr; ClassTemplateSpecializationDecl *PrevDecl = - ClassTemplate->findSpecialization(CanonicalConverted, InsertPos); + ClassTemplate->findSpecialization(CTAI.CanonicalConverted, InsertPos); TemplateSpecializationKind PrevDecl_TSK = PrevDecl ? PrevDecl->getTemplateSpecializationKind() : TSK_Undeclared; @@ -9912,7 +9909,7 @@ DeclResult Sema::ActOnExplicitInstantiation( // this explicit specialization. Specialization = ClassTemplateSpecializationDecl::Create( Context, Kind, ClassTemplate->getDeclContext(), KWLoc, TemplateNameLoc, - ClassTemplate, CanonicalConverted, PrevDecl); + ClassTemplate, CTAI.CanonicalConverted, PrevDecl); SetNestedNameSpecifier(*this, Specialization, SS); // A MSInheritanceAttr attached to the previous declaration must be @@ -9969,7 +9966,7 @@ DeclResult Sema::ActOnExplicitInstantiation( if (!Def) InstantiateClassTemplateSpecialization( TemplateNameLoc, Specialization, TSK, - /*Complain=*/true, PrimaryHasMatchedPackOnParmToNonPackOnArg); + /*Complain=*/true, CTAI.MatchedPackOnParmToNonPackOnArg); else if (TSK == TSK_ExplicitInstantiationDefinition) { MarkVTableUsed(TemplateNameLoc, Specialization, true); Specialization->setPointOfInstantiation(Def->getPointOfInstantiation()); diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp index 1e1fce10e7c01..137942f0c30bf 100644 --- a/clang/lib/Sema/SemaTemplateDeduction.cpp +++ b/clang/lib/Sema/SemaTemplateDeduction.cpp @@ -53,6 +53,7 @@ #include "llvm/Support/Casting.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/SaveAndRestore.h" #include #include #include @@ -2957,11 +2958,11 @@ Sema::getIdentityTemplateArgumentLoc(NamedDecl *TemplateParm, /// Convert the given deduced template argument and add it to the set of /// fully-converted template arguments. -static bool ConvertDeducedTemplateArgument( - Sema &S, NamedDecl *Param, DeducedTemplateArgument Arg, NamedDecl *Template, - TemplateDeductionInfo &Info, bool IsDeduced, bool PartialOrdering, - SmallVectorImpl &SugaredOutput, - SmallVectorImpl &CanonicalOutput) { +static bool +ConvertDeducedTemplateArgument(Sema &S, NamedDecl *Param, + DeducedTemplateArgument Arg, NamedDecl *Template, + TemplateDeductionInfo &Info, bool IsDeduced, + Sema::CheckTemplateArgumentInfo &CTAI) { auto ConvertArg = [&](DeducedTemplateArgument Arg, unsigned ArgumentPackIndex) { // Convert the deduced template argument into a template @@ -2970,19 +2971,17 @@ static bool ConvertDeducedTemplateArgument( TemplateArgumentLoc ArgLoc = S.getTrivialTemplateArgumentLoc( Arg, QualType(), Info.getLocation(), Param); - bool MatchedPackOnParmToNonPackOnArg = false; + SaveAndRestore _1(CTAI.MatchingTTP, false); + SaveAndRestore _2(CTAI.MatchedPackOnParmToNonPackOnArg, false); // Check the template argument, converting it as necessary. auto Res = S.CheckTemplateArgument( Param, ArgLoc, Template, Template->getLocation(), - Template->getSourceRange().getEnd(), ArgumentPackIndex, SugaredOutput, - CanonicalOutput, + Template->getSourceRange().getEnd(), ArgumentPackIndex, CTAI, IsDeduced ? (Arg.wasDeducedFromArrayBound() ? Sema::CTAK_DeducedFromArrayBound : Sema::CTAK_Deduced) - : Sema::CTAK_Specified, - PartialOrdering, /*PartialOrderingTTP=*/false, - &MatchedPackOnParmToNonPackOnArg); - if (MatchedPackOnParmToNonPackOnArg) + : Sema::CTAK_Specified); + if (CTAI.MatchedPackOnParmToNonPackOnArg) Info.setMatchedPackOnParmToNonPackOnArg(); return Res; }; @@ -3014,20 +3013,21 @@ static bool ConvertDeducedTemplateArgument( return true; // Move the converted template argument into our argument pack. - SugaredPackedArgsBuilder.push_back(SugaredOutput.pop_back_val()); - CanonicalPackedArgsBuilder.push_back(CanonicalOutput.pop_back_val()); + SugaredPackedArgsBuilder.push_back(CTAI.SugaredConverted.pop_back_val()); + CanonicalPackedArgsBuilder.push_back( + CTAI.CanonicalConverted.pop_back_val()); } // If the pack is empty, we still need to substitute into the parameter // itself, in case that substitution fails. if (SugaredPackedArgsBuilder.empty()) { LocalInstantiationScope Scope(S); - MultiLevelTemplateArgumentList Args(Template, SugaredOutput, + MultiLevelTemplateArgumentList Args(Template, CTAI.SugaredConverted, /*Final=*/true); if (auto *NTTP = dyn_cast(Param)) { Sema::InstantiatingTemplate Inst(S, Template->getLocation(), Template, - NTTP, SugaredOutput, + NTTP, CTAI.SugaredConverted, Template->getSourceRange()); if (Inst.isInvalid() || S.SubstType(NTTP->getType(), Args, NTTP->getLocation(), @@ -3035,7 +3035,7 @@ static bool ConvertDeducedTemplateArgument( return true; } else if (auto *TTP = dyn_cast(Param)) { Sema::InstantiatingTemplate Inst(S, Template->getLocation(), Template, - TTP, SugaredOutput, + TTP, CTAI.SugaredConverted, Template->getSourceRange()); if (Inst.isInvalid() || !S.SubstDecl(TTP, S.CurContext, Args)) return true; @@ -3044,9 +3044,9 @@ static bool ConvertDeducedTemplateArgument( } // Create the resulting argument pack. - SugaredOutput.push_back( + CTAI.SugaredConverted.push_back( TemplateArgument::CreatePackCopy(S.Context, SugaredPackedArgsBuilder)); - CanonicalOutput.push_back(TemplateArgument::CreatePackCopy( + CTAI.CanonicalConverted.push_back(TemplateArgument::CreatePackCopy( S.Context, CanonicalPackedArgsBuilder)); return false; } @@ -3065,9 +3065,7 @@ template static TemplateDeductionResult ConvertDeducedTemplateArguments( Sema &S, TemplateDeclT *Template, bool IsDeduced, SmallVectorImpl &Deduced, - TemplateDeductionInfo &Info, - SmallVectorImpl &SugaredBuilder, - SmallVectorImpl &CanonicalBuilder, bool PartialOrdering, + TemplateDeductionInfo &Info, Sema::CheckTemplateArgumentInfo &CTAI, LocalInstantiationScope *CurrentInstantiationScope, unsigned NumAlreadyConverted, bool *IsIncomplete) { TemplateParameterList *TemplateParams = Template->getTemplateParameters(); @@ -3102,8 +3100,8 @@ static TemplateDeductionResult ConvertDeducedTemplateArguments( // We have already fully type-checked and converted this // argument, because it was explicitly-specified. Just record the // presence of this argument. - SugaredBuilder.push_back(Deduced[I]); - CanonicalBuilder.push_back( + CTAI.SugaredConverted.push_back(Deduced[I]); + CTAI.CanonicalConverted.push_back( S.Context.getCanonicalTemplateArgument(Deduced[I])); continue; } @@ -3112,13 +3110,13 @@ static TemplateDeductionResult ConvertDeducedTemplateArguments( // We may have deduced this argument, so it still needs to be // checked and converted. if (ConvertDeducedTemplateArgument(S, Param, Deduced[I], Template, Info, - IsDeduced, PartialOrdering, - SugaredBuilder, CanonicalBuilder)) { + IsDeduced, CTAI)) { Info.Param = makeTemplateParameter(Param); // FIXME: These template arguments are temporary. Free them! Info.reset( - TemplateArgumentList::CreateCopy(S.Context, SugaredBuilder), - TemplateArgumentList::CreateCopy(S.Context, CanonicalBuilder)); + TemplateArgumentList::CreateCopy(S.Context, CTAI.SugaredConverted), + TemplateArgumentList::CreateCopy(S.Context, + CTAI.CanonicalConverted)); return TemplateDeductionResult::SubstitutionFailure; } @@ -3132,8 +3130,8 @@ static TemplateDeductionResult ConvertDeducedTemplateArguments( // arguments. if (IsIncomplete) { *IsIncomplete = true; - SugaredBuilder.push_back({}); - CanonicalBuilder.push_back({}); + CTAI.SugaredConverted.push_back({}); + CTAI.CanonicalConverted.push_back({}); continue; } @@ -3162,32 +3160,34 @@ static TemplateDeductionResult ConvertDeducedTemplateArguments( DefArg = S.SubstDefaultTemplateArgumentIfAvailable( TD, TD->getLocation(), TD->getSourceRange().getEnd(), Param, - SugaredBuilder, CanonicalBuilder, HasDefaultArg); + CTAI.SugaredConverted, CTAI.CanonicalConverted, HasDefaultArg); } // If there was no default argument, deduction is incomplete. if (DefArg.getArgument().isNull()) { Info.Param = makeTemplateParameter( const_cast(TemplateParams->getParam(I))); - Info.reset(TemplateArgumentList::CreateCopy(S.Context, SugaredBuilder), - TemplateArgumentList::CreateCopy(S.Context, CanonicalBuilder)); + Info.reset( + TemplateArgumentList::CreateCopy(S.Context, CTAI.SugaredConverted), + TemplateArgumentList::CreateCopy(S.Context, CTAI.CanonicalConverted)); return HasDefaultArg ? TemplateDeductionResult::SubstitutionFailure : TemplateDeductionResult::Incomplete; } + SaveAndRestore _1(CTAI.PartialOrdering, false); + SaveAndRestore _2(CTAI.MatchingTTP, false); + SaveAndRestore _3(CTAI.MatchedPackOnParmToNonPackOnArg, false); // Check whether we can actually use the default argument. if (S.CheckTemplateArgument( Param, DefArg, TD, TD->getLocation(), TD->getSourceRange().getEnd(), - /*ArgumentPackIndex=*/0, SugaredBuilder, CanonicalBuilder, - Sema::CTAK_Specified, /*PartialOrdering=*/false, - /*PartialOrderingTTP=*/false, - /*MatchedPackOnParmToNonPackOnArg=*/nullptr)) { + /*ArgumentPackIndex=*/0, CTAI, Sema::CTAK_Specified)) { Info.Param = makeTemplateParameter( const_cast(TemplateParams->getParam(I))); // FIXME: These template arguments are temporary. Free them! - Info.reset(TemplateArgumentList::CreateCopy(S.Context, SugaredBuilder), - TemplateArgumentList::CreateCopy(S.Context, CanonicalBuilder)); + Info.reset( + TemplateArgumentList::CreateCopy(S.Context, CTAI.SugaredConverted), + TemplateArgumentList::CreateCopy(S.Context, CTAI.CanonicalConverted)); return TemplateDeductionResult::SubstitutionFailure; } @@ -3287,10 +3287,9 @@ FinishTemplateArgumentDeduction( // C++ [temp.deduct.type]p2: // [...] or if any template argument remains neither deduced nor // explicitly specified, template argument deduction fails. - SmallVector SugaredBuilder, CanonicalBuilder; + Sema::CheckTemplateArgumentInfo CTAI(IsPartialOrdering); if (auto Result = ConvertDeducedTemplateArguments( - S, Partial, IsPartialOrdering, Deduced, Info, SugaredBuilder, - CanonicalBuilder, IsPartialOrdering, + S, Partial, IsPartialOrdering, Deduced, Info, CTAI, /*CurrentInstantiationScope=*/nullptr, /*NumAlreadyConverted=*/0, /*IsIncomplete=*/nullptr); Result != TemplateDeductionResult::Success) @@ -3298,9 +3297,9 @@ FinishTemplateArgumentDeduction( // Form the template argument list from the deduced template arguments. TemplateArgumentList *SugaredDeducedArgumentList = - TemplateArgumentList::CreateCopy(S.Context, SugaredBuilder); + TemplateArgumentList::CreateCopy(S.Context, CTAI.SugaredConverted); TemplateArgumentList *CanonicalDeducedArgumentList = - TemplateArgumentList::CreateCopy(S.Context, CanonicalBuilder); + TemplateArgumentList::CreateCopy(S.Context, CTAI.CanonicalConverted); Info.reset(SugaredDeducedArgumentList, CanonicalDeducedArgumentList); @@ -3317,11 +3316,11 @@ FinishTemplateArgumentDeduction( TemplateArgumentListInfo InstArgs(PartialTemplArgInfo->LAngleLoc, PartialTemplArgInfo->RAngleLoc); - if (S.SubstTemplateArguments(PartialTemplArgInfo->arguments(), - MultiLevelTemplateArgumentList(Partial, - SugaredBuilder, - /*Final=*/true), - InstArgs)) { + if (S.SubstTemplateArguments( + PartialTemplArgInfo->arguments(), + MultiLevelTemplateArgumentList(Partial, CTAI.SugaredConverted, + /*Final=*/true), + InstArgs)) { unsigned ArgIdx = InstArgs.size(), ParamIdx = ArgIdx; if (ParamIdx >= Partial->getTemplateParameters()->size()) ParamIdx = Partial->getTemplateParameters()->size() - 1; @@ -3333,24 +3332,21 @@ FinishTemplateArgumentDeduction( return TemplateDeductionResult::SubstitutionFailure; } - bool MatchedPackOnParmToNonPackOnArg = false; bool ConstraintsNotSatisfied; - SmallVector SugaredConvertedInstArgs, - CanonicalConvertedInstArgs; - if (S.CheckTemplateArgumentList( - Template, Partial->getLocation(), InstArgs, /*DefaultArgs=*/{}, false, - SugaredConvertedInstArgs, CanonicalConvertedInstArgs, - /*UpdateArgsWithConversions=*/true, &ConstraintsNotSatisfied, - /*PartialOrderingTTP=*/false, &MatchedPackOnParmToNonPackOnArg)) + Sema::CheckTemplateArgumentInfo InstCTAI; + if (S.CheckTemplateArgumentList(Template, Partial->getLocation(), InstArgs, + /*DefaultArgs=*/{}, false, InstCTAI, + /*UpdateArgsWithConversions=*/true, + &ConstraintsNotSatisfied)) return ConstraintsNotSatisfied ? TemplateDeductionResult::ConstraintsNotSatisfied : TemplateDeductionResult::SubstitutionFailure; - if (MatchedPackOnParmToNonPackOnArg) + if (InstCTAI.MatchedPackOnParmToNonPackOnArg) Info.setMatchedPackOnParmToNonPackOnArg(); TemplateParameterList *TemplateParams = Template->getTemplateParameters(); for (unsigned I = 0, E = TemplateParams->size(); I != E; ++I) { - TemplateArgument InstArg = SugaredConvertedInstArgs.data()[I]; + TemplateArgument InstArg = InstCTAI.SugaredConverted.data()[I]; if (!isSameTemplateArg(S.Context, TemplateArgs[I], InstArg, IsPartialOrdering)) { Info.Param = makeTemplateParameter(TemplateParams->getParam(I)); @@ -3365,7 +3361,7 @@ FinishTemplateArgumentDeduction( if (!IsPartialOrdering) { if (auto Result = CheckDeducedArgumentConstraints( - S, Partial, SugaredBuilder, CanonicalBuilder, Info); + S, Partial, CTAI.SugaredConverted, CTAI.CanonicalConverted, Info); Result != TemplateDeductionResult::Success) return Result; } @@ -3390,10 +3386,9 @@ static TemplateDeductionResult FinishTemplateArgumentDeduction( // C++ [temp.deduct.type]p2: // [...] or if any template argument remains neither deduced nor // explicitly specified, template argument deduction fails. - SmallVector SugaredBuilder, CanonicalBuilder; + Sema::CheckTemplateArgumentInfo CTAI(PartialOrdering); if (auto Result = ConvertDeducedTemplateArguments( - S, Template, /*IsDeduced=*/PartialOrdering, Deduced, Info, - SugaredBuilder, CanonicalBuilder, PartialOrdering, + S, Template, /*IsDeduced=*/PartialOrdering, Deduced, Info, CTAI, /*CurrentInstantiationScope=*/nullptr, /*NumAlreadyConverted=*/0U, /*IsIncomplete=*/nullptr); Result != TemplateDeductionResult::Success) @@ -3401,7 +3396,7 @@ static TemplateDeductionResult FinishTemplateArgumentDeduction( // Check that we produced the correct argument list. SmallVector, 4> PsStack{TemplateArgs}, - AsStack{CanonicalBuilder}; + AsStack{CTAI.CanonicalConverted}; for (;;) { auto take = [](SmallVectorImpl> &Stack) -> std::tuple &, TemplateArgument> { @@ -3458,7 +3453,7 @@ static TemplateDeductionResult FinishTemplateArgumentDeduction( if (!PartialOrdering) { if (auto Result = CheckDeducedArgumentConstraints( - S, Template, SugaredBuilder, CanonicalBuilder, Info); + S, Template, CTAI.SugaredConverted, CTAI.CanonicalConverted, Info); Result != TemplateDeductionResult::Success) return Result; } @@ -3482,17 +3477,16 @@ static TemplateDeductionResult FinishTemplateArgumentDeduction( // C++ [temp.deduct.type]p2: // [...] or if any template argument remains neither deduced nor // explicitly specified, template argument deduction fails. - SmallVector SugaredBuilder, CanonicalBuilder; + Sema::CheckTemplateArgumentInfo CTAI; if (auto Result = ConvertDeducedTemplateArguments( - S, TD, /*IsDeduced=*/false, Deduced, Info, SugaredBuilder, - CanonicalBuilder, /*PartialOrdering=*/false, + S, TD, /*IsDeduced=*/false, Deduced, Info, CTAI, /*CurrentInstantiationScope=*/nullptr, /*NumAlreadyConverted=*/0, /*IsIncomplete=*/nullptr); Result != TemplateDeductionResult::Success) return Result; - return ::CheckDeducedArgumentConstraints(S, TD, SugaredBuilder, - CanonicalBuilder, Info); + return ::CheckDeducedArgumentConstraints(S, TD, CTAI.SugaredConverted, + CTAI.CanonicalConverted, Info); } /// Perform template argument deduction to determine whether the given template @@ -3673,7 +3667,6 @@ TemplateDeductionResult Sema::SubstituteExplicitTemplateArguments( // declaration order of their corresponding template-parameters. The // template argument list shall not specify more template-arguments than // there are corresponding template-parameters. - SmallVector SugaredBuilder, CanonicalBuilder; // Enter a new template instantiation context where we check the // explicitly-specified template arguments against this function template, @@ -3685,12 +3678,13 @@ TemplateDeductionResult Sema::SubstituteExplicitTemplateArguments( if (Inst.isInvalid()) return TemplateDeductionResult::InstantiationDepth; + CheckTemplateArgumentInfo CTAI; if (CheckTemplateArgumentList(FunctionTemplate, SourceLocation(), - ExplicitTemplateArgs, /*DefaultArgs=*/{}, true, - SugaredBuilder, CanonicalBuilder, + ExplicitTemplateArgs, /*DefaultArgs=*/{}, + /*PartialTemplateArgs=*/true, CTAI, /*UpdateArgsWithConversions=*/false) || Trap.hasErrorOccurred()) { - unsigned Index = SugaredBuilder.size(); + unsigned Index = CTAI.SugaredConverted.size(); if (Index >= TemplateParams->size()) return TemplateDeductionResult::SubstitutionFailure; Info.Param = makeTemplateParameter(TemplateParams->getParam(Index)); @@ -3700,9 +3694,9 @@ TemplateDeductionResult Sema::SubstituteExplicitTemplateArguments( // Form the template argument list from the explicitly-specified // template arguments. TemplateArgumentList *SugaredExplicitArgumentList = - TemplateArgumentList::CreateCopy(Context, SugaredBuilder); + TemplateArgumentList::CreateCopy(Context, CTAI.SugaredConverted); TemplateArgumentList *CanonicalExplicitArgumentList = - TemplateArgumentList::CreateCopy(Context, CanonicalBuilder); + TemplateArgumentList::CreateCopy(Context, CTAI.CanonicalConverted); Info.setExplicitArgs(SugaredExplicitArgumentList, CanonicalExplicitArgumentList); @@ -3717,15 +3711,15 @@ TemplateDeductionResult Sema::SubstituteExplicitTemplateArguments( // the explicit template arguments. They'll be used as part of deduction // for this template parameter pack. unsigned PartiallySubstitutedPackIndex = -1u; - if (!SugaredBuilder.empty()) { - const TemplateArgument &Arg = SugaredBuilder.back(); + if (!CTAI.SugaredConverted.empty()) { + const TemplateArgument &Arg = CTAI.SugaredConverted.back(); if (Arg.getKind() == TemplateArgument::Pack) { - auto *Param = TemplateParams->getParam(SugaredBuilder.size() - 1); + auto *Param = TemplateParams->getParam(CTAI.SugaredConverted.size() - 1); // If this is a fully-saturated fixed-size pack, it should be // fully-substituted, not partially-substituted. std::optional Expansions = getExpandedPackSize(Param); if (!Expansions || Arg.pack_size() < *Expansions) { - PartiallySubstitutedPackIndex = SugaredBuilder.size() - 1; + PartiallySubstitutedPackIndex = CTAI.SugaredConverted.size() - 1; CurrentInstantiationScope->SetPartiallySubstitutedPack( Param, Arg.pack_begin(), Arg.pack_size()); } @@ -4047,10 +4041,9 @@ TemplateDeductionResult Sema::FinishTemplateArgumentDeduction( // [...] or if any template argument remains neither deduced nor // explicitly specified, template argument deduction fails. bool IsIncomplete = false; - SmallVector SugaredBuilder, CanonicalBuilder; + CheckTemplateArgumentInfo CTAI(PartialOrdering); if (auto Result = ConvertDeducedTemplateArguments( - *this, FunctionTemplate, /*IsDeduced=*/true, Deduced, Info, - SugaredBuilder, CanonicalBuilder, PartialOrdering, + *this, FunctionTemplate, /*IsDeduced=*/true, Deduced, Info, CTAI, CurrentInstantiationScope, NumExplicitlySpecified, PartialOverloading ? &IsIncomplete : nullptr); Result != TemplateDeductionResult::Success) @@ -4070,9 +4063,9 @@ TemplateDeductionResult Sema::FinishTemplateArgumentDeduction( // Form the template argument list from the deduced template arguments. TemplateArgumentList *SugaredDeducedArgumentList = - TemplateArgumentList::CreateCopy(Context, SugaredBuilder); + TemplateArgumentList::CreateCopy(Context, CTAI.SugaredConverted); TemplateArgumentList *CanonicalDeducedArgumentList = - TemplateArgumentList::CreateCopy(Context, CanonicalBuilder); + TemplateArgumentList::CreateCopy(Context, CTAI.CanonicalConverted); Info.reset(SugaredDeducedArgumentList, CanonicalDeducedArgumentList); // Substitute the deduced template arguments into the function template @@ -4133,13 +4126,13 @@ TemplateDeductionResult Sema::FinishTemplateArgumentDeduction( // deduction fails. if (!IsIncomplete) { if (CheckInstantiatedFunctionTemplateConstraints( - Info.getLocation(), Specialization, CanonicalBuilder, + Info.getLocation(), Specialization, CTAI.CanonicalConverted, Info.AssociatedConstraintsSatisfaction)) return TemplateDeductionResult::MiscellaneousDeductionFailure; if (!Info.AssociatedConstraintsSatisfaction.IsSatisfied) { - Info.reset(Info.takeSugared(), - TemplateArgumentList::CreateCopy(Context, CanonicalBuilder)); + Info.reset(Info.takeSugared(), TemplateArgumentList::CreateCopy( + Context, CTAI.CanonicalConverted)); return TemplateDeductionResult::ConstraintsNotSatisfied; } } @@ -5222,12 +5215,12 @@ static bool CheckDeducedPlaceholderConstraints(Sema &S, const AutoType &Type, for (unsigned I = 0, C = TypeLoc.getNumArgs(); I != C; ++I) TemplateArgs.addArgument(TypeLoc.getArgLoc(I)); - llvm::SmallVector SugaredConverted, CanonicalConverted; - if (S.CheckTemplateArgumentList( - Concept, SourceLocation(), TemplateArgs, /*DefaultArgs=*/{}, - /*PartialTemplateArgs=*/false, SugaredConverted, CanonicalConverted)) + Sema::CheckTemplateArgumentInfo CTAI; + if (S.CheckTemplateArgumentList(Concept, SourceLocation(), TemplateArgs, + /*DefaultArgs=*/{}, + /*PartialTemplateArgs=*/false, CTAI)) return true; - MultiLevelTemplateArgumentList MLTAL(Concept, CanonicalConverted, + MultiLevelTemplateArgumentList MLTAL(Concept, CTAI.CanonicalConverted, /*Final=*/false); // Build up an EvaluationContext with an ImplicitConceptSpecializationDecl so // that the template arguments of the constraint can be preserved. For @@ -5242,7 +5235,7 @@ static bool CheckDeducedPlaceholderConstraints(Sema &S, const AutoType &Type, S, Sema::ExpressionEvaluationContext::Unevaluated, ImplicitConceptSpecializationDecl::Create( S.getASTContext(), Concept->getDeclContext(), Concept->getLocation(), - CanonicalConverted)); + CTAI.CanonicalConverted)); if (S.CheckConstraintSatisfaction(Concept, {Concept->getConstraintExpr()}, MLTAL, TypeLoc.getLocalSourceRange(), Satisfaction)) @@ -5672,10 +5665,9 @@ static TemplateDeductionResult FinishTemplateArgumentDeduction( // [...] or if any template argument remains neither deduced nor // explicitly specified, template argument deduction fails. bool IsIncomplete = false; - SmallVector SugaredBuilder, CanonicalBuilder; + Sema::CheckTemplateArgumentInfo CTAI(/*PartialOrdering=*/true); if (auto Result = ConvertDeducedTemplateArguments( - S, FTD, /*IsDeduced=*/true, Deduced, Info, SugaredBuilder, - CanonicalBuilder, /*PartialOrdering=*/true, + S, FTD, /*IsDeduced=*/true, Deduced, Info, CTAI, /*CurrentInstantiationScope=*/nullptr, /*NumAlreadyConverted=*/0, &IsIncomplete); Result != TemplateDeductionResult::Success) @@ -5683,9 +5675,9 @@ static TemplateDeductionResult FinishTemplateArgumentDeduction( // Form the template argument list from the deduced template arguments. TemplateArgumentList *SugaredDeducedArgumentList = - TemplateArgumentList::CreateCopy(S.Context, SugaredBuilder); + TemplateArgumentList::CreateCopy(S.Context, CTAI.SugaredConverted); TemplateArgumentList *CanonicalDeducedArgumentList = - TemplateArgumentList::CreateCopy(S.Context, CanonicalBuilder); + TemplateArgumentList::CreateCopy(S.Context, CTAI.CanonicalConverted); Info.reset(SugaredDeducedArgumentList, CanonicalDeducedArgumentList); @@ -5694,7 +5686,7 @@ static TemplateDeductionResult FinishTemplateArgumentDeduction( // and equivalent to the parameter. LocalInstantiationScope InstScope(S); - if (auto TDR = CheckDeductionConsistency(S, FTD, SugaredBuilder); + if (auto TDR = CheckDeductionConsistency(S, FTD, CTAI.SugaredConverted); TDR != TemplateDeductionResult::Success) return TDR; @@ -6571,13 +6563,17 @@ bool Sema::isTemplateTemplateParameterAtLeastAsSpecializedAs( // C++1z [temp.arg.template]p3: // If the rewrite produces an invalid type, then P is not at least as // specialized as A. - SmallVector CanonicalPArgs; - if (CheckTemplateArgumentList( - AArg, ArgLoc, PArgList, DefaultArgs, false, PArgs, CanonicalPArgs, - /*UpdateArgsWithConversions=*/true, - /*ConstraintsNotSatisfied=*/nullptr, - /*PartialOrderingTTP=*/true, MatchedPackOnParmToNonPackOnArg)) + CheckTemplateArgumentInfo CTAI( + /*PartialOrdering=*/false, /*MatchingTTP=*/true); + CTAI.SugaredConverted = std::move(PArgs); + if (CheckTemplateArgumentList(AArg, ArgLoc, PArgList, DefaultArgs, + /*PartialTemplateArgs=*/false, CTAI, + /*UpdateArgsWithConversions=*/true, + /*ConstraintsNotSatisfied=*/nullptr)) return false; + PArgs = std::move(CTAI.SugaredConverted); + if (MatchedPackOnParmToNonPackOnArg) + *MatchedPackOnParmToNonPackOnArg |= CTAI.MatchedPackOnParmToNonPackOnArg; } // Determine whether P1 is at least as specialized as P2. diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index 16a7049821a5c..131f5c8ad1a09 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -3957,10 +3957,10 @@ TemplateDeclInstantiator::VisitClassTemplateSpecializationDecl( // Check that the template argument list is well-formed for this // class template. - SmallVector SugaredConverted, CanonicalConverted; + Sema::CheckTemplateArgumentInfo CTAI; if (SemaRef.CheckTemplateArgumentList( InstClassTemplate, D->getLocation(), InstTemplateArgs, - /*DefaultArgs=*/{}, false, SugaredConverted, CanonicalConverted, + /*DefaultArgs=*/{}, /*PartialTemplateArgs=*/false, CTAI, /*UpdateArgsWithConversions=*/true)) return nullptr; @@ -3968,7 +3968,7 @@ TemplateDeclInstantiator::VisitClassTemplateSpecializationDecl( // in the member template's set of class template explicit specializations. void *InsertPos = nullptr; ClassTemplateSpecializationDecl *PrevDecl = - InstClassTemplate->findSpecialization(CanonicalConverted, InsertPos); + InstClassTemplate->findSpecialization(CTAI.CanonicalConverted, InsertPos); // Check whether we've already seen a conflicting instantiation of this // declaration (for instance, if there was a prior implicit instantiation). @@ -4006,7 +4006,8 @@ TemplateDeclInstantiator::VisitClassTemplateSpecializationDecl( ClassTemplateSpecializationDecl *InstD = ClassTemplateSpecializationDecl::Create( SemaRef.Context, D->getTagKind(), Owner, D->getBeginLoc(), - D->getLocation(), InstClassTemplate, CanonicalConverted, PrevDecl); + D->getLocation(), InstClassTemplate, CTAI.CanonicalConverted, + PrevDecl); InstD->setTemplateArgsAsWritten(InstTemplateArgs); // Add this partial specialization to the set of class template partial @@ -4065,17 +4066,17 @@ Decl *TemplateDeclInstantiator::VisitVarTemplateSpecializationDecl( } // Check that the template argument list is well-formed for this template. - SmallVector SugaredConverted, CanonicalConverted; + Sema::CheckTemplateArgumentInfo CTAI; if (SemaRef.CheckTemplateArgumentList( InstVarTemplate, D->getLocation(), VarTemplateArgsInfo, - /*DefaultArgs=*/{}, false, SugaredConverted, CanonicalConverted, + /*DefaultArgs=*/{}, /*PartialTemplateArgs=*/false, CTAI, /*UpdateArgsWithConversions=*/true)) return nullptr; // Check whether we've already seen a declaration of this specialization. void *InsertPos = nullptr; VarTemplateSpecializationDecl *PrevDecl = - InstVarTemplate->findSpecialization(CanonicalConverted, InsertPos); + InstVarTemplate->findSpecialization(CTAI.CanonicalConverted, InsertPos); // Check whether we've already seen a conflicting instantiation of this // declaration (for instance, if there was a prior implicit instantiation). @@ -4086,8 +4087,9 @@ Decl *TemplateDeclInstantiator::VisitVarTemplateSpecializationDecl( PrevDecl->getPointOfInstantiation(), Ignored)) return nullptr; - return VisitVarTemplateSpecializationDecl( - InstVarTemplate, D, VarTemplateArgsInfo, CanonicalConverted, PrevDecl); + return VisitVarTemplateSpecializationDecl(InstVarTemplate, D, + VarTemplateArgsInfo, + CTAI.CanonicalConverted, PrevDecl); } Decl *TemplateDeclInstantiator::VisitVarTemplateSpecializationDecl( @@ -4331,37 +4333,37 @@ TemplateDeclInstantiator::InstantiateClassTemplatePartialSpecialization( // Check that the template argument list is well-formed for this // class template. - SmallVector SugaredConverted, CanonicalConverted; + Sema::CheckTemplateArgumentInfo CTAI; if (SemaRef.CheckTemplateArgumentList( ClassTemplate, PartialSpec->getLocation(), InstTemplateArgs, /*DefaultArgs=*/{}, - /*PartialTemplateArgs=*/false, SugaredConverted, CanonicalConverted)) + /*PartialTemplateArgs=*/false, CTAI)) return nullptr; // Check these arguments are valid for a template partial specialization. if (SemaRef.CheckTemplatePartialSpecializationArgs( PartialSpec->getLocation(), ClassTemplate, InstTemplateArgs.size(), - CanonicalConverted)) + CTAI.CanonicalConverted)) return nullptr; // Figure out where to insert this class template partial specialization // in the member template's set of class template partial specializations. void *InsertPos = nullptr; ClassTemplateSpecializationDecl *PrevDecl = - ClassTemplate->findPartialSpecialization(CanonicalConverted, InstParams, - InsertPos); + ClassTemplate->findPartialSpecialization(CTAI.CanonicalConverted, + InstParams, InsertPos); // Build the canonical type that describes the converted template // arguments of the class template partial specialization. QualType CanonType = SemaRef.Context.getTemplateSpecializationType( - TemplateName(ClassTemplate), CanonicalConverted); + TemplateName(ClassTemplate), CTAI.CanonicalConverted); // Create the class template partial specialization declaration. ClassTemplatePartialSpecializationDecl *InstPartialSpec = ClassTemplatePartialSpecializationDecl::Create( SemaRef.Context, PartialSpec->getTagKind(), Owner, PartialSpec->getBeginLoc(), PartialSpec->getLocation(), InstParams, - ClassTemplate, CanonicalConverted, CanonType, + ClassTemplate, CTAI.CanonicalConverted, CanonType, /*PrevDecl=*/nullptr); InstPartialSpec->setTemplateArgsAsWritten(InstTemplateArgs); @@ -4445,25 +4447,24 @@ TemplateDeclInstantiator::InstantiateVarTemplatePartialSpecialization( // Check that the template argument list is well-formed for this // class template. - SmallVector SugaredConverted, CanonicalConverted; + Sema::CheckTemplateArgumentInfo CTAI; if (SemaRef.CheckTemplateArgumentList(VarTemplate, PartialSpec->getLocation(), InstTemplateArgs, /*DefaultArgs=*/{}, - /*PartialTemplateArgs=*/false, - SugaredConverted, CanonicalConverted)) + /*PartialTemplateArgs=*/false, CTAI)) return nullptr; // Check these arguments are valid for a template partial specialization. if (SemaRef.CheckTemplatePartialSpecializationArgs( PartialSpec->getLocation(), VarTemplate, InstTemplateArgs.size(), - CanonicalConverted)) + CTAI.CanonicalConverted)) return nullptr; // Figure out where to insert this variable template partial specialization // in the member template's set of variable template partial specializations. void *InsertPos = nullptr; VarTemplateSpecializationDecl *PrevDecl = - VarTemplate->findPartialSpecialization(CanonicalConverted, InstParams, - InsertPos); + VarTemplate->findPartialSpecialization(CTAI.CanonicalConverted, + InstParams, InsertPos); // Do substitution on the type of the declaration TypeSourceInfo *DI = SemaRef.SubstType( @@ -4484,7 +4485,7 @@ TemplateDeclInstantiator::InstantiateVarTemplatePartialSpecialization( VarTemplatePartialSpecializationDecl::Create( SemaRef.Context, Owner, PartialSpec->getInnerLocStart(), PartialSpec->getLocation(), InstParams, VarTemplate, DI->getType(), - DI, PartialSpec->getStorageClass(), CanonicalConverted); + DI, PartialSpec->getStorageClass(), CTAI.CanonicalConverted); InstPartialSpec->setTemplateArgsAsWritten(InstTemplateArgs);