diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -8110,14 +8110,13 @@ CTAK_DeducedFromArrayBound }; - bool CheckTemplateArgument(NamedDecl *Param, - TemplateArgumentLoc &Arg, - NamedDecl *Template, - SourceLocation TemplateLoc, - SourceLocation RAngleLoc, - unsigned ArgumentPackIndex, - SmallVectorImpl &Converted, - CheckTemplateArgumentKind CTAK = CTAK_Specified); + bool + CheckTemplateArgument(NamedDecl *Param, TemplateArgumentLoc &Arg, + NamedDecl *Template, SourceLocation TemplateLoc, + SourceLocation RAngleLoc, unsigned ArgumentPackIndex, + SmallVectorImpl &SugaredConverted, + SmallVectorImpl &CanonicalConverted, + CheckTemplateArgumentKind CTAK); /// Check that the given template arguments can be be provided to /// the given template, converting the arguments along the way. @@ -8148,23 +8147,25 @@ /// the template not being satisfied by the template arguments. /// /// \returns true if an error occurred, false otherwise. - bool CheckTemplateArgumentList(TemplateDecl *Template, - SourceLocation TemplateLoc, - TemplateArgumentListInfo &TemplateArgs, - bool PartialTemplateArgs, - SmallVectorImpl &Converted, - bool UpdateArgsWithConversions = true, - bool *ConstraintsNotSatisfied = nullptr); - - bool CheckTemplateTypeArgument(TemplateTypeParmDecl *Param, - TemplateArgumentLoc &Arg, - SmallVectorImpl &Converted); + bool CheckTemplateArgumentList( + TemplateDecl *Template, SourceLocation TemplateLoc, + TemplateArgumentListInfo &TemplateArgs, bool PartialTemplateArgs, + SmallVectorImpl &SugaredConverted, + SmallVectorImpl &CanonicalConverted, + bool UpdateArgsWithConversions = true, + bool *ConstraintsNotSatisfied = nullptr); + + bool CheckTemplateTypeArgument( + TemplateTypeParmDecl *Param, TemplateArgumentLoc &Arg, + SmallVectorImpl &SugaredConverted, + SmallVectorImpl &CanonicalConverted); bool CheckTemplateArgument(TypeSourceInfo *Arg); ExprResult CheckTemplateArgument(NonTypeTemplateParmDecl *Param, QualType InstantiatedParamType, Expr *Arg, - TemplateArgument &Converted, - CheckTemplateArgumentKind CTAK = CTAK_Specified); + TemplateArgument &SugaredConverted, + TemplateArgument &CanonicalConverted, + CheckTemplateArgumentKind CTAK); bool CheckTemplateTemplateArgument(TemplateTemplateParmDecl *Param, TemplateParameterList *Params, TemplateArgumentLoc &Arg); diff --git a/clang/include/clang/Sema/TemplateDeduction.h b/clang/include/clang/Sema/TemplateDeduction.h --- a/clang/include/clang/Sema/TemplateDeduction.h +++ b/clang/include/clang/Sema/TemplateDeduction.h @@ -41,7 +41,7 @@ /// TemplateDeductionResult value. class TemplateDeductionInfo { /// The deduced template argument list. - TemplateArgumentList *Deduced = nullptr; + TemplateArgumentList *DeducedSugared = nullptr, *DeducedCanonical = nullptr; /// The source location at which template argument /// deduction is occurring. @@ -71,8 +71,8 @@ /// Create temporary template deduction info for speculatively deducing /// against a base class of an argument's type. TemplateDeductionInfo(ForBaseTag, const TemplateDeductionInfo &Info) - : Deduced(Info.Deduced), Loc(Info.Loc), DeducedDepth(Info.DeducedDepth), - ExplicitArgs(Info.ExplicitArgs) {} + : DeducedSugared(Info.DeducedSugared), Loc(Info.Loc), + DeducedDepth(Info.DeducedDepth), ExplicitArgs(Info.ExplicitArgs) {} /// Returns the location at which template argument is /// occurring. @@ -91,10 +91,15 @@ return ExplicitArgs; } - /// Take ownership of the deduced template argument list. - TemplateArgumentList *take() { - TemplateArgumentList *Result = Deduced; - Deduced = nullptr; + /// Take ownership of the deduced template argument lists. + TemplateArgumentList *takeSugared() { + TemplateArgumentList *Result = DeducedSugared; + DeducedSugared = nullptr; + return Result; + } + TemplateArgumentList *takeCanonical() { + TemplateArgumentList *Result = DeducedCanonical; + DeducedCanonical = nullptr; return Result; } @@ -120,15 +125,20 @@ /// Provide an initial template argument list that contains the /// explicitly-specified arguments. - void setExplicitArgs(TemplateArgumentList *NewDeduced) { - Deduced = NewDeduced; - ExplicitArgs = Deduced->size(); + void setExplicitArgs(TemplateArgumentList *NewDeducedSugared, + TemplateArgumentList *NewDeducedCanonical) { + assert(NewDeducedSugared->size() == NewDeducedCanonical->size()); + DeducedSugared = NewDeducedSugared; + DeducedCanonical = NewDeducedCanonical; + ExplicitArgs = DeducedSugared->size(); } /// Provide a new template argument list that contains the /// results of template argument deduction. - void reset(TemplateArgumentList *NewDeduced) { - Deduced = NewDeduced; + void reset(TemplateArgumentList *NewDeducedSugared, + TemplateArgumentList *NewDeducedCanonical) { + DeducedSugared = NewDeducedSugared; + DeducedCanonical = NewDeducedCanonical; } /// Is a SFINAE diagnostic available? diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp --- a/clang/lib/Sema/SemaLookup.cpp +++ b/clang/lib/Sema/SemaLookup.cpp @@ -3691,11 +3691,11 @@ // is a well-formed template argument for the template parameter. if (StringLit) { SFINAETrap Trap(*this); - SmallVector Checked; + SmallVector SugaredChecked, CanonicalChecked; TemplateArgumentLoc Arg(TemplateArgument(StringLit), StringLit); - if (CheckTemplateArgument(Params->getParam(0), Arg, FD, - R.getNameLoc(), R.getNameLoc(), 0, - Checked) || + if (CheckTemplateArgument( + Params->getParam(0), Arg, FD, R.getNameLoc(), R.getNameLoc(), + 0, SugaredChecked, CanonicalChecked, CTAK_Specified) || Trap.hasErrorOccurred()) IsTemplate = false; } diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -636,7 +636,7 @@ auto *Saved = new (Context) DFIDeducedMismatchArgs; Saved->FirstArg = Info.FirstArg; Saved->SecondArg = Info.SecondArg; - Saved->TemplateArgs = Info.take(); + Saved->TemplateArgs = Info.takeSugared(); Saved->CallArgIndex = Info.CallArgIndex; Result.Data = Saved; break; @@ -665,7 +665,7 @@ } case Sema::TDK_SubstitutionFailure: - Result.Data = Info.take(); + Result.Data = Info.takeSugared(); if (Info.hasSFINAEDiagnostic()) { PartialDiagnosticAt *Diag = new (Result.Diagnostic) PartialDiagnosticAt( SourceLocation(), PartialDiagnostic::NullDiagnostic()); @@ -676,7 +676,7 @@ case Sema::TDK_ConstraintsNotSatisfied: { CNSInfo *Saved = new (Context) CNSInfo; - Saved->TemplateArgs = Info.take(); + Saved->TemplateArgs = Info.takeSugared(); Saved->Satisfaction = Info.AssociatedConstraintsSatisfaction; Result.Data = Saved; break; diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -1592,9 +1592,10 @@ if (DiagnoseUnexpandedParameterPack(Default, UPPC_DefaultArgument)) return Param; - TemplateArgument Converted; - ExprResult DefaultRes = - CheckTemplateArgument(Param, Param->getType(), Default, Converted); + TemplateArgument SugaredConverted, CanonicalConverted; + ExprResult DefaultRes = CheckTemplateArgument( + Param, Param->getType(), Default, SugaredConverted, CanonicalConverted, + CTAK_Specified); if (DefaultRes.isInvalid()) { Param->setInvalidDecl(); return Param; @@ -3771,9 +3772,9 @@ // Check that the template argument list is well-formed for this // template. - SmallVector Converted; - if (CheckTemplateArgumentList(Template, TemplateLoc, TemplateArgs, - false, Converted, + SmallVector SugaredConverted, CanonicalConverted; + if (CheckTemplateArgumentList(Template, TemplateLoc, TemplateArgs, false, + SugaredConverted, CanonicalConverted, /*UpdateArgsWithConversions=*/true)) return QualType(); @@ -3788,7 +3789,7 @@ return QualType(); TemplateArgumentList StackTemplateArgs(TemplateArgumentList::OnStack, - Converted); + CanonicalConverted); // Only substitute for the innermost template argument list. MultiLevelTemplateArgumentList TemplateArgLists; @@ -3841,11 +3842,11 @@ return QualType(); } } else if (auto *BTD = dyn_cast(Template)) { - CanonType = checkBuiltinTemplateIdType(*this, BTD, Converted, TemplateLoc, - TemplateArgs); + CanonType = checkBuiltinTemplateIdType(*this, BTD, SugaredConverted, + TemplateLoc, TemplateArgs); } else if (Name.isDependent() || TemplateSpecializationType::anyDependentTemplateArguments( - TemplateArgs, Converted)) { + TemplateArgs, 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 @@ -3853,7 +3854,8 @@ // A have identical types when A is declared as: // // template struct A; - CanonType = Context.getCanonicalTemplateSpecializationType(Name, Converted); + CanonType = Context.getCanonicalTemplateSpecializationType( + Name, CanonicalConverted); // This might work out to be a current instantiation, in which // case the canonical type needs to be the InjectedClassNameType. @@ -3897,8 +3899,8 @@ // Find the class template specialization declaration that // corresponds to these arguments. void *InsertPos = nullptr; - ClassTemplateSpecializationDecl *Decl - = ClassTemplate->findSpecialization(Converted, InsertPos); + ClassTemplateSpecializationDecl *Decl = + ClassTemplate->findSpecialization(CanonicalConverted, InsertPos); if (!Decl) { // This is the first time we have referenced this class template // specialization. Create the canonical declaration and add it to @@ -3907,7 +3909,8 @@ Context, ClassTemplate->getTemplatedDecl()->getTagKind(), ClassTemplate->getDeclContext(), ClassTemplate->getTemplatedDecl()->getBeginLoc(), - ClassTemplate->getLocation(), ClassTemplate, Converted, nullptr); + ClassTemplate->getLocation(), ClassTemplate, CanonicalConverted, + nullptr); ClassTemplate->AddSpecialization(Decl, InsertPos); if (ClassTemplate->isOutOfLine()) Decl->setLexicalDeclContext(ClassTemplate->getLexicalDeclContext()); @@ -3918,7 +3921,8 @@ InstantiatingTemplate Inst(*this, TemplateLoc, Decl); if (!Inst.isInvalid()) { MultiLevelTemplateArgumentList TemplateArgLists; - TemplateArgLists.addOuterTemplateArguments(Template, Converted); + TemplateArgLists.addOuterTemplateArguments(Template, + CanonicalConverted); InstantiateAttrsForDecl(TemplateArgLists, ClassTemplate->getTemplatedDecl(), Decl); } @@ -4417,9 +4421,9 @@ // Check that the template argument list is well-formed for this // template. - SmallVector Converted; + SmallVector SugaredConverted, CanonicalConverted; if (CheckTemplateArgumentList(VarTemplate, TemplateNameLoc, TemplateArgs, - false, Converted, + false, SugaredConverted, CanonicalConverted, /*UpdateArgsWithConversions=*/true)) return true; @@ -4427,21 +4431,22 @@ // corresponds to these arguments. if (IsPartialSpecialization) { if (CheckTemplatePartialSpecializationArgs(TemplateNameLoc, VarTemplate, - TemplateArgs.size(), Converted)) + TemplateArgs.size(), + CanonicalConverted)) return true; // FIXME: Move these checks to CheckTemplatePartialSpecializationArgs so we // also do them during instantiation. if (!Name.isDependent() && - !TemplateSpecializationType::anyDependentTemplateArguments(TemplateArgs, - Converted)) { + !TemplateSpecializationType::anyDependentTemplateArguments( + TemplateArgs, CanonicalConverted)) { Diag(TemplateNameLoc, diag::err_partial_spec_fully_specialized) << VarTemplate->getDeclName(); IsPartialSpecialization = false; } if (isSameAsPrimaryTemplate(VarTemplate->getTemplateParameters(), - Converted) && + CanonicalConverted) && (!Context.getLangOpts().CPlusPlus20 || !TemplateParams->hasAssociatedConstraints())) { // C++ [temp.class.spec]p9b3: @@ -4462,10 +4467,10 @@ VarTemplateSpecializationDecl *PrevDecl = nullptr; if (IsPartialSpecialization) - PrevDecl = VarTemplate->findPartialSpecialization(Converted, TemplateParams, - InsertPos); + PrevDecl = VarTemplate->findPartialSpecialization( + CanonicalConverted, TemplateParams, InsertPos); else - PrevDecl = VarTemplate->findSpecialization(Converted, InsertPos); + PrevDecl = VarTemplate->findSpecialization(CanonicalConverted, InsertPos); VarTemplateSpecializationDecl *Specialization = nullptr; @@ -4492,7 +4497,7 @@ VarTemplatePartialSpecializationDecl::Create( Context, VarTemplate->getDeclContext(), TemplateKWLoc, TemplateNameLoc, TemplateParams, VarTemplate, DI->getType(), DI, SC, - Converted, TemplateArgs); + CanonicalConverted, TemplateArgs); if (!PrevPartial) VarTemplate->AddPartialSpecialization(Partial, InsertPos); @@ -4509,7 +4514,7 @@ // this explicit specialization or friend declaration. Specialization = VarTemplateSpecializationDecl::Create( Context, VarTemplate->getDeclContext(), TemplateKWLoc, TemplateNameLoc, - VarTemplate, DI->getType(), DI, SC, Converted); + VarTemplate, DI->getType(), DI, SC, CanonicalConverted); Specialization->setTemplateArgsInfo(TemplateArgs); if (!PrevDecl) @@ -4587,24 +4592,25 @@ assert(Template && "A variable template id without template?"); // Check that the template argument list is well-formed for this template. - SmallVector Converted; + SmallVector SugaredConverted, CanonicalConverted; if (CheckTemplateArgumentList( Template, TemplateNameLoc, const_cast(TemplateArgs), false, - Converted, /*UpdateArgsWithConversions=*/true)) + SugaredConverted, CanonicalConverted, + /*UpdateArgsWithConversions=*/true)) return true; // Produce a placeholder value if the specialization is dependent. if (Template->getDeclContext()->isDependentContext() || - TemplateSpecializationType::anyDependentTemplateArguments(TemplateArgs, - Converted)) + TemplateSpecializationType::anyDependentTemplateArguments( + TemplateArgs, CanonicalConverted)) return DeclResult(); // Find the variable template specialization declaration that // corresponds to these arguments. void *InsertPos = nullptr; - if (VarTemplateSpecializationDecl *Spec = Template->findSpecialization( - Converted, InsertPos)) { + if (VarTemplateSpecializationDecl *Spec = + Template->findSpecialization(CanonicalConverted, InsertPos)) { checkSpecializationReachability(TemplateNameLoc, Spec); // If we already have a variable template specialization, return it. return Spec; @@ -4616,7 +4622,7 @@ // that it represents. That is, VarDecl *InstantiationPattern = Template->getTemplatedDecl(); TemplateArgumentList TemplateArgList(TemplateArgumentList::OnStack, - Converted); + CanonicalConverted); TemplateArgumentList *InstantiationArgs = &TemplateArgList; bool AmbiguousPartialSpec = false; typedef PartialSpecMatchResult MatchResult; @@ -4648,7 +4654,7 @@ } else { Matched.push_back(PartialSpecMatchResult()); Matched.back().Partial = Partial; - Matched.back().Args = Info.take(); + Matched.back().Args = Info.takeCanonical(); } } @@ -4704,7 +4710,7 @@ // FIXME: LateAttrs et al.? VarTemplateSpecializationDecl *Decl = BuildVarTemplateInstantiation( Template, InstantiationPattern, *InstantiationArgs, TemplateArgs, - Converted, TemplateNameLoc /*, LateAttrs, StartingScope*/); + CanonicalConverted, TemplateNameLoc /*, LateAttrs, StartingScope*/); if (!Decl) return true; @@ -4775,19 +4781,21 @@ const TemplateArgumentListInfo *TemplateArgs) { assert(NamedConcept && "A concept template id without a template?"); - llvm::SmallVector Converted; - if (CheckTemplateArgumentList(NamedConcept, ConceptNameInfo.getLoc(), - const_cast(*TemplateArgs), - /*PartialTemplateArgs=*/false, Converted, - /*UpdateArgsWithConversions=*/false)) + llvm::SmallVector SugaredConverted, CanonicalConverted; + if (CheckTemplateArgumentList( + NamedConcept, ConceptNameInfo.getLoc(), + const_cast(*TemplateArgs), + /*PartialTemplateArgs=*/false, SugaredConverted, CanonicalConverted, + /*UpdateArgsWithConversions=*/false)) return ExprError(); ConstraintSatisfaction Satisfaction; bool AreArgsDependent = - TemplateSpecializationType::anyDependentTemplateArguments(*TemplateArgs, - Converted); + TemplateSpecializationType::anyDependentTemplateArguments( + *TemplateArgs, CanonicalConverted); + // FIXME: use SugaredConverted. MultiLevelTemplateArgumentList MLTAL; - MLTAL.addOuterTemplateArguments(NamedConcept, Converted); + MLTAL.addOuterTemplateArguments(NamedConcept, CanonicalConverted); LocalInstantiationScope Scope(*this); if (!AreArgsDependent && CheckConstraintSatisfaction( @@ -4797,11 +4805,12 @@ Satisfaction)) return ExprError(); - return ConceptSpecializationExpr::Create(Context, + return ConceptSpecializationExpr::Create( + Context, SS.isSet() ? SS.getWithLocInContext(Context) : NestedNameSpecifierLoc{}, TemplateKWLoc, ConceptNameInfo, FoundDecl, NamedConcept, - ASTTemplateArgumentListInfo::Create(Context, *TemplateArgs), Converted, - AreArgsDependent ? nullptr : &Satisfaction); + ASTTemplateArgumentListInfo::Create(Context, *TemplateArgs), + CanonicalConverted, AreArgsDependent ? nullptr : &Satisfaction); } ExprResult Sema::BuildTemplateIdExpr(const CXXScopeSpec &SS, @@ -5042,9 +5051,10 @@ return TNK_Non_template; } -bool Sema::CheckTemplateTypeArgument(TemplateTypeParmDecl *Param, - TemplateArgumentLoc &AL, - SmallVectorImpl &Converted) { +bool Sema::CheckTemplateTypeArgument( + TemplateTypeParmDecl *Param, TemplateArgumentLoc &AL, + SmallVectorImpl &SugaredConverted, + SmallVectorImpl &CanonicalConverted) { const TemplateArgument &Arg = AL.getArgument(); QualType ArgType; TypeSourceInfo *TSI = nullptr; @@ -5137,9 +5147,6 @@ if (CheckTemplateArgument(TSI)) return true; - // Add the converted template type argument. - ArgType = Context.getCanonicalType(ArgType); - // Objective-C ARC: // If an explicitly-specified template argument type is a lifetime type // with no lifetime qualifier, the __strong lifetime qualifier is inferred. @@ -5151,7 +5158,9 @@ ArgType = Context.getQualifiedType(ArgType, Qs); } - Converted.push_back(TemplateArgument(ArgType)); + SugaredConverted.push_back(TemplateArgument(ArgType)); + CanonicalConverted.push_back( + TemplateArgument(Context.getCanonicalType(ArgType))); return false; } @@ -5457,17 +5466,17 @@ /// explicitly written, deduced, etc. /// /// \returns true on error, false otherwise. -bool Sema::CheckTemplateArgument(NamedDecl *Param, - TemplateArgumentLoc &Arg, - NamedDecl *Template, - SourceLocation TemplateLoc, - SourceLocation RAngleLoc, - unsigned ArgumentPackIndex, - SmallVectorImpl &Converted, - CheckTemplateArgumentKind CTAK) { +bool Sema::CheckTemplateArgument( + NamedDecl *Param, TemplateArgumentLoc &Arg, NamedDecl *Template, + SourceLocation TemplateLoc, SourceLocation RAngleLoc, + unsigned ArgumentPackIndex, + SmallVectorImpl &SugaredConverted, + SmallVectorImpl &CanonicalConverted, + CheckTemplateArgumentKind CTAK) { // Check template type parameters. if (TemplateTypeParmDecl *TTP = dyn_cast(Param)) - return CheckTemplateTypeArgument(TTP, Arg, Converted); + return CheckTemplateTypeArgument(TTP, Arg, SugaredConverted, + CanonicalConverted); // Check non-type template parameters. if (NonTypeTemplateParmDecl *NTTP =dyn_cast(Param)) { @@ -5482,14 +5491,16 @@ !isa(Template) && !Template->getDeclContext()->isDependentContext()) { // Do substitution on the type of the non-type template parameter. - InstantiatingTemplate Inst(*this, TemplateLoc, Template, - NTTP, Converted, + InstantiatingTemplate Inst(*this, TemplateLoc, Template, NTTP, + SugaredConverted, SourceRange(TemplateLoc, RAngleLoc)); if (Inst.isInvalid()) return true; + // FIXME: Substitute with sugared arguments. + // getSubstTemplateTypeParmPackType needs to handle non-canonical pack. TemplateArgumentList TemplateArgs(TemplateArgumentList::OnStack, - Converted); + CanonicalConverted); MultiLevelTemplateArgumentList MLTAL(Template, TemplateArgs.asArray()); // If the parameter is a pack expansion, expand this slice of the pack. @@ -5517,11 +5528,18 @@ llvm_unreachable("Should never see a NULL template argument here"); case TemplateArgument::Expression: { - TemplateArgument Result; + Expr *E = Arg.getArgument().getAsExpr(); + // FIXME: Workaround for double conversion + if (isa(E)) { + SugaredConverted.push_back(Arg.getArgument()); + CanonicalConverted.push_back( + Context.getCanonicalTemplateArgument(Arg.getArgument())); + break; + } + TemplateArgument SugaredResult, CanonicalResult; unsigned CurSFINAEErrors = NumSFINAEErrors; - ExprResult Res = - CheckTemplateArgument(NTTP, NTTPType, Arg.getArgument().getAsExpr(), - Result, CTAK); + ExprResult Res = CheckTemplateArgument(NTTP, NTTPType, E, SugaredResult, + CanonicalResult, CTAK); if (Res.isInvalid()) return true; // If the current template argument causes an error, give up now. @@ -5535,7 +5553,8 @@ Arg = TemplateArgumentLoc(TA, Res.get()); } - Converted.push_back(Result); + SugaredConverted.push_back(SugaredResult); + CanonicalConverted.push_back(CanonicalResult); break; } @@ -5544,7 +5563,9 @@ case TemplateArgument::NullPtr: // We've already checked this template argument, so just copy // it to the list of converted arguments. - Converted.push_back(Arg.getArgument()); + SugaredConverted.push_back(Arg.getArgument()); + CanonicalConverted.push_back( + Context.getCanonicalTemplateArgument(Arg.getArgument())); break; case TemplateArgument::Template: @@ -5580,12 +5601,14 @@ return true; } - TemplateArgument Result; - E = CheckTemplateArgument(NTTP, NTTPType, E.get(), Result); + TemplateArgument SugaredResult, CanonicalResult; + E = CheckTemplateArgument(NTTP, NTTPType, E.get(), SugaredResult, + CanonicalResult, CTAK_Specified); if (E.isInvalid()) return true; - Converted.push_back(Result); + SugaredConverted.push_back(SugaredResult); + CanonicalConverted.push_back(CanonicalResult); break; } @@ -5643,11 +5666,13 @@ // Set up a template instantiation context. LocalInstantiationScope Scope(*this); InstantiatingTemplate Inst(*this, TemplateLoc, Template, TempParm, - Converted, SourceRange(TemplateLoc, RAngleLoc)); + SugaredConverted, + SourceRange(TemplateLoc, RAngleLoc)); if (Inst.isInvalid()) return true; - TemplateArgumentList TemplateArgs(TemplateArgumentList::OnStack, Converted); + TemplateArgumentList TemplateArgs(TemplateArgumentList::OnStack, + SugaredConverted); Params = SubstTemplateParams( Params, CurContext, MultiLevelTemplateArgumentList(Template, TemplateArgs.asArray())); @@ -5675,7 +5700,8 @@ if (CheckTemplateTemplateArgument(TempParm, Params, Arg)) return true; - Converted.push_back( + SugaredConverted.push_back(Arg.getArgument()); + CanonicalConverted.push_back( Context.getCanonicalTemplateArgument(Arg.getArgument())); break; @@ -5743,7 +5769,8 @@ bool Sema::CheckTemplateArgumentList( TemplateDecl *Template, SourceLocation TemplateLoc, TemplateArgumentListInfo &TemplateArgs, bool PartialTemplateArgs, - SmallVectorImpl &Converted, + SmallVectorImpl &SugaredConverted, + SmallVectorImpl &CanonicalConverted, bool UpdateArgsWithConversions, bool *ConstraintsNotSatisfied) { if (ConstraintsNotSatisfied) @@ -5769,7 +5796,8 @@ // corresponding parameter declared by the template in its // template-parameter-list. bool isTemplateTemplateParameter = isa(Template); - SmallVector ArgumentPack; + SmallVector SugaredArgumentPack; + SmallVector CanonicalArgumentPack; unsigned ArgIdx = 0, NumArgs = NewArgs.size(); LocalInstantiationScope InstScope(*this, true); for (TemplateParameterList::iterator Param = Params->begin(), @@ -5778,12 +5806,16 @@ // If we have an expanded parameter pack, make sure we don't have too // many arguments. if (Optional Expansions = getExpandedPackSize(*Param)) { - if (*Expansions == ArgumentPack.size()) { + if (*Expansions == SugaredArgumentPack.size()) { // We're done with this parameter pack. Pack up its arguments and add // them to the list. - Converted.push_back( - TemplateArgument::CreatePackCopy(Context, ArgumentPack)); - ArgumentPack.clear(); + SugaredConverted.push_back( + TemplateArgument::CreatePackCopy(Context, SugaredArgumentPack)); + SugaredArgumentPack.clear(); + + CanonicalConverted.push_back( + TemplateArgument::CreatePackCopy(Context, CanonicalArgumentPack)); + CanonicalArgumentPack.clear(); // This argument is assigned to the next parameter. ++Param; @@ -5802,9 +5834,10 @@ if (ArgIdx < NumArgs) { // Check the template argument we were given. - if (CheckTemplateArgument(*Param, NewArgs[ArgIdx], Template, - TemplateLoc, RAngleLoc, - ArgumentPack.size(), Converted)) + if (CheckTemplateArgument(*Param, NewArgs[ArgIdx], Template, TemplateLoc, + RAngleLoc, SugaredArgumentPack.size(), + SugaredConverted, CanonicalConverted, + CTAK_Specified)) return true; bool PackExpansionIntoNonPack = @@ -5833,7 +5866,8 @@ // 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. - ArgumentPack.push_back(Converted.pop_back_val()); + SugaredArgumentPack.push_back(SugaredConverted.pop_back_val()); + CanonicalArgumentPack.push_back(CanonicalConverted.pop_back_val()); } else { // Move to the next template parameter. ++Param; @@ -5843,17 +5877,25 @@ // the remaining arguments, because we don't know what parameters they'll // match up with. if (PackExpansionIntoNonPack) { - if (!ArgumentPack.empty()) { + if (!SugaredArgumentPack.empty()) { // If we were part way through filling in an expanded parameter pack, // fall back to just producing individual arguments. - for (const TemplateArgument &I : ArgumentPack) - Converted.push_back(Context.getCanonicalTemplateArgument(I)); - ArgumentPack.clear(); + SugaredConverted.insert(SugaredConverted.end(), + SugaredArgumentPack.begin(), + SugaredArgumentPack.end()); + SugaredArgumentPack.clear(); + + CanonicalConverted.insert(CanonicalConverted.end(), + CanonicalArgumentPack.begin(), + CanonicalArgumentPack.end()); + CanonicalArgumentPack.clear(); } while (ArgIdx < NumArgs) { - Converted.push_back(Context.getCanonicalTemplateArgument( - NewArgs[ArgIdx].getArgument())); + const TemplateArgument &Arg = NewArgs[ArgIdx].getArgument(); + SugaredConverted.push_back(Arg); + CanonicalConverted.push_back( + Context.getCanonicalTemplateArgument(Arg)); ++ArgIdx; } @@ -5865,9 +5907,12 @@ // If we're checking a partial template argument list, we're done. if (PartialTemplateArgs) { - if ((*Param)->isTemplateParameterPack() && !ArgumentPack.empty()) - Converted.push_back( - TemplateArgument::CreatePackCopy(Context, ArgumentPack)); + if ((*Param)->isTemplateParameterPack() && !SugaredArgumentPack.empty()) { + SugaredConverted.push_back( + TemplateArgument::CreatePackCopy(Context, SugaredArgumentPack)); + CanonicalConverted.push_back( + TemplateArgument::CreatePackCopy(Context, CanonicalArgumentPack)); + } return false; } @@ -5883,9 +5928,13 @@ if (Param + 1 != ParamEnd) return true; - Converted.push_back( - TemplateArgument::CreatePackCopy(Context, ArgumentPack)); - ArgumentPack.clear(); + SugaredConverted.push_back( + TemplateArgument::CreatePackCopy(Context, SugaredArgumentPack)); + SugaredArgumentPack.clear(); + + CanonicalConverted.push_back( + TemplateArgument::CreatePackCopy(Context, CanonicalArgumentPack)); + CanonicalArgumentPack.clear(); ++Param; continue; @@ -5904,12 +5953,8 @@ return diagnoseMissingArgument(*this, TemplateLoc, Template, TTP, NewArgs); - TypeSourceInfo *ArgType = SubstDefaultTemplateArgument(*this, - Template, - TemplateLoc, - RAngleLoc, - TTP, - Converted); + TypeSourceInfo *ArgType = SubstDefaultTemplateArgument( + *this, Template, TemplateLoc, RAngleLoc, TTP, CanonicalConverted); if (!ArgType) return true; @@ -5921,11 +5966,8 @@ return diagnoseMissingArgument(*this, TemplateLoc, Template, NTTP, NewArgs); - ExprResult E = SubstDefaultTemplateArgument(*this, Template, - TemplateLoc, - RAngleLoc, - NTTP, - Converted); + ExprResult E = SubstDefaultTemplateArgument( + *this, Template, TemplateLoc, RAngleLoc, NTTP, CanonicalConverted); if (E.isInvalid()) return true; @@ -5940,12 +5982,9 @@ NewArgs); NestedNameSpecifierLoc QualifierLoc; - TemplateName Name = SubstDefaultTemplateArgument(*this, Template, - TemplateLoc, - RAngleLoc, - TempParm, - Converted, - QualifierLoc); + TemplateName Name = SubstDefaultTemplateArgument( + *this, Template, TemplateLoc, RAngleLoc, TempParm, CanonicalConverted, + QualifierLoc); if (Name.isNull()) return true; @@ -5958,14 +5997,16 @@ // the default template argument. We're not actually instantiating a // template here, we just create this object to put a note into the // context stack. - InstantiatingTemplate Inst(*this, RAngleLoc, Template, *Param, Converted, + InstantiatingTemplate Inst(*this, RAngleLoc, Template, *Param, + SugaredConverted, SourceRange(TemplateLoc, RAngleLoc)); if (Inst.isInvalid()) return true; // Check the default template argument. - if (CheckTemplateArgument(*Param, Arg, Template, TemplateLoc, - RAngleLoc, 0, Converted)) + if (CheckTemplateArgument(*Param, Arg, Template, TemplateLoc, RAngleLoc, 0, + SugaredConverted, CanonicalConverted, + CTAK_Specified)) return true; // Core issue 150 (assumed resolution): if this is a template template @@ -5985,9 +6026,12 @@ // still dependent). if (ArgIdx < NumArgs && CurrentInstantiationScope && CurrentInstantiationScope->getPartiallySubstitutedPack()) { - while (ArgIdx < NumArgs && NewArgs[ArgIdx].getArgument().isPackExpansion()) - Converted.push_back(Context.getCanonicalTemplateArgument( - NewArgs[ArgIdx++].getArgument())); + while (ArgIdx < NumArgs && + NewArgs[ArgIdx].getArgument().isPackExpansion()) { + const TemplateArgument &Arg = NewArgs[ArgIdx++].getArgument(); + SugaredConverted.push_back(Arg); + CanonicalConverted.push_back(Context.getCanonicalTemplateArgument(Arg)); + } } // If we have any leftover arguments, then there were too many arguments. @@ -6011,8 +6055,9 @@ if (!PartialTemplateArgs) { // FIXME: This will be changed a bit once deferred concept instantiation is // implemented. + // FIXME: Use SugaredConverted MultiLevelTemplateArgumentList MLTAL; - MLTAL.addOuterTemplateArguments(Template, Converted); + MLTAL.addOuterTemplateArguments(Template, CanonicalConverted); if (EnsureTemplateArgumentListConstraints( Template, MLTAL, SourceRange(TemplateLoc, TemplateArgs.getRAngleLoc()))) { @@ -6497,12 +6542,9 @@ /// Checks whether the given template argument is the address /// of an object or function according to C++ [temp.arg.nontype]p1. -static bool -CheckTemplateArgumentAddressOfObjectOrFunction(Sema &S, - NonTypeTemplateParmDecl *Param, - QualType ParamType, - Expr *ArgIn, - TemplateArgument &Converted) { +static bool CheckTemplateArgumentAddressOfObjectOrFunction( + Sema &S, NonTypeTemplateParmDecl *Param, QualType ParamType, Expr *ArgIn, + TemplateArgument &SugaredConverted, TemplateArgument &CanonicalConverted) { bool Invalid = false; Expr *Arg = ArgIn; QualType ArgType = Arg->getType(); @@ -6606,8 +6648,11 @@ Entity)) { case NPV_NullPointer: S.Diag(Arg->getExprLoc(), diag::warn_cxx98_compat_template_arg_null); - Converted = TemplateArgument(S.Context.getCanonicalType(ParamType), - /*isNullPtr=*/true); + SugaredConverted = TemplateArgument(ParamType, + /*isNullPtr=*/true); + CanonicalConverted = + TemplateArgument(S.Context.getCanonicalType(ParamType), + /*isNullPtr=*/true); return false; case NPV_Error: @@ -6621,7 +6666,9 @@ // Stop checking the precise nature of the argument if it is value dependent, // it should be checked when instantiated. if (Arg->isValueDependent()) { - Converted = TemplateArgument(ArgIn); + SugaredConverted = TemplateArgument(ArgIn); + CanonicalConverted = + S.Context.getCanonicalTemplateArgument(SugaredConverted); return false; } @@ -6751,19 +6798,21 @@ return true; // Create the template argument. - Converted = TemplateArgument(cast(Entity->getCanonicalDecl()), - S.Context.getCanonicalType(ParamType)); + SugaredConverted = TemplateArgument(Entity, ParamType); + CanonicalConverted = + TemplateArgument(cast(Entity->getCanonicalDecl()), + S.Context.getCanonicalType(ParamType)); S.MarkAnyDeclReferenced(Arg->getBeginLoc(), Entity, false); return false; } /// Checks whether the given template argument is a pointer to /// member constant according to C++ [temp.arg.nontype]p1. -static bool CheckTemplateArgumentPointerToMember(Sema &S, - NonTypeTemplateParmDecl *Param, - QualType ParamType, - Expr *&ResultArg, - TemplateArgument &Converted) { +static bool +CheckTemplateArgumentPointerToMember(Sema &S, NonTypeTemplateParmDecl *Param, + QualType ParamType, Expr *&ResultArg, + TemplateArgument &SugaredConverted, + TemplateArgument &CanonicalConverted) { bool Invalid = false; Expr *Arg = ResultArg; @@ -6811,10 +6860,14 @@ if (VD->getType()->isMemberPointerType()) { if (isa(VD)) { if (Arg->isTypeDependent() || Arg->isValueDependent()) { - Converted = TemplateArgument(Arg); + SugaredConverted = TemplateArgument(Arg); + CanonicalConverted = + S.Context.getCanonicalTemplateArgument(SugaredConverted); } else { - VD = cast(VD->getCanonicalDecl()); - Converted = TemplateArgument(VD, ParamType); + SugaredConverted = TemplateArgument(VD, ParamType); + CanonicalConverted = + TemplateArgument(cast(VD->getCanonicalDecl()), + S.Context.getCanonicalType(ParamType)); } return Invalid; } @@ -6832,8 +6885,10 @@ return true; case NPV_NullPointer: S.Diag(ResultArg->getExprLoc(), diag::warn_cxx98_compat_template_arg_null); - Converted = TemplateArgument(S.Context.getCanonicalType(ParamType), - /*isNullPtr*/true); + SugaredConverted = TemplateArgument(ParamType, + /*isNullPtr*/ true); + CanonicalConverted = TemplateArgument(S.Context.getCanonicalType(ParamType), + /*isNullPtr*/ true); return false; case NPV_NotNullPointer: break; @@ -6870,10 +6925,15 @@ // Okay: this is the address of a non-static member, and therefore // a member pointer constant. if (Arg->isTypeDependent() || Arg->isValueDependent()) { - Converted = TemplateArgument(Arg); + SugaredConverted = TemplateArgument(Arg); + CanonicalConverted = + S.Context.getCanonicalTemplateArgument(SugaredConverted); } else { - ValueDecl *D = cast(DRE->getDecl()->getCanonicalDecl()); - Converted = TemplateArgument(D, S.Context.getCanonicalType(ParamType)); + ValueDecl *D = DRE->getDecl(); + SugaredConverted = TemplateArgument(D, ParamType); + CanonicalConverted = + TemplateArgument(cast(D->getCanonicalDecl()), + S.Context.getCanonicalType(ParamType)); } return Invalid; } @@ -6894,7 +6954,8 @@ /// type of the non-type template parameter after it has been instantiated. ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, QualType ParamType, Expr *Arg, - TemplateArgument &Converted, + TemplateArgument &SugaredConverted, + TemplateArgument &CanonicalConverted, CheckTemplateArgumentKind CTAK) { SourceLocation StartLoc = Arg->getBeginLoc(); @@ -6909,7 +6970,9 @@ if (CTAK == CTAK_Deduced && Arg->isTypeDependent()) { auto *AT = dyn_cast(DeducedT); if (AT && AT->isDecltypeAuto()) { - Converted = TemplateArgument(Arg); + SugaredConverted = TemplateArgument(Arg); + CanonicalConverted = TemplateArgument( + Context.getCanonicalTemplateArgument(SugaredConverted)); return Arg; } } @@ -6987,7 +7050,9 @@ // work. Similarly for CTAD, when comparing 'A' against 'A'. if ((ParamType->isDependentType() || Arg->isTypeDependent()) && !Arg->getType()->getContainedDeducedType()) { - Converted = TemplateArgument(Arg); + SugaredConverted = TemplateArgument(Arg); + CanonicalConverted = TemplateArgument( + Context.getCanonicalTemplateArgument(SugaredConverted)); return Arg; } // FIXME: This attempts to implement C++ [temp.deduct.type]p17. Per DR1770, @@ -7024,7 +7089,9 @@ PackExpansionExpr(E.get()->getType(), E.get(), PE->getEllipsisLoc(), PE->getNumExpansions()); } - Converted = TemplateArgument(E.get()); + SugaredConverted = TemplateArgument(E.get()); + CanonicalConverted = TemplateArgument( + Context.getCanonicalTemplateArgument(SugaredConverted)); return E; } @@ -7049,11 +7116,16 @@ Context.hasSameUnqualifiedType(ParamType, InnerArg->getType())) { NamedDecl *ND = cast(InnerArg)->getDecl(); if (auto *TPO = dyn_cast(ND)) { - Converted = TemplateArgument(TPO, CanonParamType); + + SugaredConverted = TemplateArgument(TPO, ParamType); + CanonicalConverted = + TemplateArgument(TPO->getCanonicalDecl(), CanonParamType); return Arg; } if (isa(ND)) { - Converted = TemplateArgument(Arg); + SugaredConverted = TemplateArgument(Arg); + CanonicalConverted = + Context.getCanonicalTemplateArgument(SugaredConverted); return Arg; } } @@ -7070,7 +7142,9 @@ // For a value-dependent argument, CheckConvertedConstantExpression is // permitted (and expected) to be unable to determine a value. if (ArgResult.get()->isValueDependent()) { - Converted = TemplateArgument(ArgResult.get()); + SugaredConverted = TemplateArgument(ArgResult.get()); + CanonicalConverted = + Context.getCanonicalTemplateArgument(SugaredConverted); return ArgResult; } @@ -7078,14 +7152,17 @@ switch (Value.getKind()) { case APValue::None: assert(ParamType->isNullPtrType()); - Converted = TemplateArgument(CanonParamType, /*isNullPtr*/true); + SugaredConverted = TemplateArgument(ParamType, /*isNullPtr=*/true); + CanonicalConverted = TemplateArgument(CanonParamType, /*isNullPtr=*/true); break; case APValue::Indeterminate: llvm_unreachable("result of constant evaluation should be initialized"); break; case APValue::Int: assert(ParamType->isIntegralOrEnumerationType()); - Converted = TemplateArgument(Context, Value.getInt(), CanonParamType); + SugaredConverted = TemplateArgument(Context, Value.getInt(), ParamType); + CanonicalConverted = + TemplateArgument(Context, Value.getInt(), CanonParamType); break; case APValue::MemberPointer: { assert(ParamType->isMemberPointerType()); @@ -7100,8 +7177,12 @@ } auto *VD = const_cast(Value.getMemberPointerDecl()); - Converted = VD ? TemplateArgument(VD, CanonParamType) - : TemplateArgument(CanonParamType, /*isNullPtr*/true); + SugaredConverted = VD ? TemplateArgument(VD, ParamType) + : TemplateArgument(ParamType, /*isNullPtr=*/true); + CanonicalConverted = + VD ? TemplateArgument(cast(VD->getCanonicalDecl()), + CanonParamType) + : TemplateArgument(CanonParamType, /*isNullPtr=*/true); break; } case APValue::LValue: { @@ -7141,17 +7222,25 @@ "null reference should not be a constant expression"); assert((!VD || !ParamType->isNullPtrType()) && "non-null value of type nullptr_t?"); - Converted = VD ? TemplateArgument(VD, CanonParamType) - : TemplateArgument(CanonParamType, /*isNullPtr*/true); + // FIXME: copy pasta from case above. + SugaredConverted = VD ? TemplateArgument(VD, ParamType) + : TemplateArgument(ParamType, /*isNullPtr=*/true); + CanonicalConverted = + VD ? TemplateArgument(cast(VD->getCanonicalDecl()), + CanonParamType) + : TemplateArgument(CanonParamType, /*isNullPtr=*/true); break; } case APValue::Struct: - case APValue::Union: + case APValue::Union: { // Get or create the corresponding template parameter object. - Converted = TemplateArgument( - Context.getTemplateParamObjectDecl(CanonParamType, Value), - CanonParamType); + TemplateParamObjectDecl *D = + Context.getTemplateParamObjectDecl(ParamType, Value); + SugaredConverted = TemplateArgument(D, ParamType); + CanonicalConverted = + TemplateArgument(D->getCanonicalDecl(), CanonParamType); break; + } case APValue::AddrLabelDiff: return Diag(StartLoc, diag::err_non_type_template_arg_addr_label_diff); case APValue::FixedPoint: @@ -7201,7 +7290,9 @@ // We can't check arbitrary value-dependent arguments. if (ArgResult.get()->isValueDependent()) { - Converted = TemplateArgument(ArgResult.get()); + SugaredConverted = TemplateArgument(ArgResult.get()); + CanonicalConverted = + Context.getCanonicalTemplateArgument(SugaredConverted); return ArgResult; } @@ -7215,8 +7306,9 @@ ? Context.getIntWidth(IntegerType) : Context.getTypeSize(IntegerType)); - Converted = TemplateArgument(Context, Value, - Context.getCanonicalType(ParamType)); + SugaredConverted = TemplateArgument(Context, Value, ParamType); + CanonicalConverted = + TemplateArgument(Context, Value, Context.getCanonicalType(ParamType)); return ArgResult; } @@ -7286,13 +7378,16 @@ if (Arg->isValueDependent()) { // The argument is value-dependent. Create a new // TemplateArgument with the converted expression. - Converted = TemplateArgument(Arg); + SugaredConverted = TemplateArgument(Arg); + CanonicalConverted = + Context.getCanonicalTemplateArgument(SugaredConverted); return Arg; } - QualType IntegerType = Context.getCanonicalType(ParamType); - if (const EnumType *Enum = IntegerType->getAs()) - IntegerType = Context.getCanonicalType(Enum->getDecl()->getIntegerType()); + QualType IntegerType = ParamType; + if (const EnumType *Enum = IntegerType->getAs()) { + IntegerType = Enum->getDecl()->getIntegerType(); + } if (ParamType->isBooleanType()) { // Value must be zero or one. @@ -7338,10 +7433,10 @@ } } - Converted = TemplateArgument(Context, Value, - ParamType->isEnumeralType() - ? Context.getCanonicalType(ParamType) - : IntegerType); + QualType T = ParamType->isEnumeralType() ? ParamType : IntegerType; + SugaredConverted = TemplateArgument(Context, Value, T); + CanonicalConverted = + TemplateArgument(Context, Value, Context.getCanonicalType(T)); return Arg; } @@ -7386,15 +7481,15 @@ } if (!ParamType->isMemberPointerType()) { - if (CheckTemplateArgumentAddressOfObjectOrFunction(*this, Param, - ParamType, - Arg, Converted)) + if (CheckTemplateArgumentAddressOfObjectOrFunction( + *this, Param, ParamType, Arg, SugaredConverted, + CanonicalConverted)) return ExprError(); return Arg; } - if (CheckTemplateArgumentPointerToMember(*this, Param, ParamType, Arg, - Converted)) + if (CheckTemplateArgumentPointerToMember( + *this, Param, ParamType, Arg, SugaredConverted, CanonicalConverted)) return ExprError(); return Arg; } @@ -7407,9 +7502,8 @@ assert(ParamType->getPointeeType()->isIncompleteOrObjectType() && "Only object pointers allowed here"); - if (CheckTemplateArgumentAddressOfObjectOrFunction(*this, Param, - ParamType, - Arg, Converted)) + if (CheckTemplateArgumentAddressOfObjectOrFunction( + *this, Param, ParamType, Arg, SugaredConverted, CanonicalConverted)) return ExprError(); return Arg; } @@ -7438,9 +7532,8 @@ return ExprError(); } - if (CheckTemplateArgumentAddressOfObjectOrFunction(*this, Param, - ParamType, - Arg, Converted)) + if (CheckTemplateArgumentAddressOfObjectOrFunction( + *this, Param, ParamType, Arg, SugaredConverted, CanonicalConverted)) return ExprError(); return Arg; } @@ -7448,7 +7541,9 @@ // Deal with parameters of type std::nullptr_t. if (ParamType->isNullPtrType()) { if (Arg->isTypeDependent() || Arg->isValueDependent()) { - Converted = TemplateArgument(Arg); + SugaredConverted = TemplateArgument(Arg); + CanonicalConverted = + Context.getCanonicalTemplateArgument(SugaredConverted); return Arg; } @@ -7464,8 +7559,10 @@ case NPV_NullPointer: Diag(Arg->getExprLoc(), diag::warn_cxx98_compat_template_arg_null); - Converted = TemplateArgument(Context.getCanonicalType(ParamType), - /*isNullPtr*/true); + SugaredConverted = TemplateArgument(ParamType, + /*isNullPtr*/ true); + CanonicalConverted = TemplateArgument(Context.getCanonicalType(ParamType), + /*isNullPtr*/ true); return Arg; } } @@ -7474,8 +7571,8 @@ // member, qualification conversions (4.4) are applied. assert(ParamType->isMemberPointerType() && "Only pointers to members remain"); - if (CheckTemplateArgumentPointerToMember(*this, Param, ParamType, Arg, - Converted)) + if (CheckTemplateArgumentPointerToMember( + *this, Param, ParamType, Arg, SugaredConverted, CanonicalConverted)) return ExprError(); return Arg; } @@ -8462,9 +8559,9 @@ // Check that the template argument list is well-formed for this // template. - SmallVector Converted; - if (CheckTemplateArgumentList(ClassTemplate, TemplateNameLoc, - TemplateArgs, false, Converted, + SmallVector SugaredConverted, CanonicalConverted; + if (CheckTemplateArgumentList(ClassTemplate, TemplateNameLoc, TemplateArgs, + false, SugaredConverted, CanonicalConverted, /*UpdateArgsWithConversions=*/true)) return true; @@ -8472,14 +8569,15 @@ // corresponds to these arguments. if (isPartialSpecialization) { if (CheckTemplatePartialSpecializationArgs(TemplateNameLoc, ClassTemplate, - TemplateArgs.size(), Converted)) + TemplateArgs.size(), + CanonicalConverted)) return true; // FIXME: Move this to CheckTemplatePartialSpecializationArgs so we // also do it during instantiation. if (!Name.isDependent() && - !TemplateSpecializationType::anyDependentTemplateArguments(TemplateArgs, - Converted)) { + !TemplateSpecializationType::anyDependentTemplateArguments( + TemplateArgs, CanonicalConverted)) { Diag(TemplateNameLoc, diag::err_partial_spec_fully_specialized) << ClassTemplate->getDeclName(); isPartialSpecialization = false; @@ -8490,11 +8588,10 @@ ClassTemplateSpecializationDecl *PrevDecl = nullptr; if (isPartialSpecialization) - PrevDecl = ClassTemplate->findPartialSpecialization(Converted, - TemplateParams, - InsertPos); + PrevDecl = ClassTemplate->findPartialSpecialization( + CanonicalConverted, TemplateParams, InsertPos); else - PrevDecl = ClassTemplate->findSpecialization(Converted, InsertPos); + PrevDecl = ClassTemplate->findSpecialization(CanonicalConverted, InsertPos); ClassTemplateSpecializationDecl *Specialization = nullptr; @@ -8513,7 +8610,7 @@ // arguments of the class template partial specialization. TemplateName CanonTemplate = Context.getCanonicalTemplateName(Name); CanonType = Context.getTemplateSpecializationType(CanonTemplate, - Converted); + CanonicalConverted); if (Context.hasSameType(CanonType, ClassTemplate->getInjectedClassNameSpecialization()) && @@ -8543,16 +8640,11 @@ // Create a new class template partial specialization declaration node. ClassTemplatePartialSpecializationDecl *PrevPartial = cast_or_null(PrevDecl); - ClassTemplatePartialSpecializationDecl *Partial - = ClassTemplatePartialSpecializationDecl::Create(Context, Kind, - ClassTemplate->getDeclContext(), - KWLoc, TemplateNameLoc, - TemplateParams, - ClassTemplate, - Converted, - TemplateArgs, - CanonType, - PrevPartial); + ClassTemplatePartialSpecializationDecl *Partial = + ClassTemplatePartialSpecializationDecl::Create( + Context, Kind, ClassTemplate->getDeclContext(), KWLoc, + TemplateNameLoc, TemplateParams, ClassTemplate, CanonicalConverted, + TemplateArgs, CanonType, PrevPartial); SetNestedNameSpecifier(*this, Partial, SS); if (TemplateParameterLists.size() > 1 && SS.isSet()) { Partial->setTemplateParameterListsInfo( @@ -8572,13 +8664,9 @@ } else { // Create a new class template specialization declaration node for // this explicit specialization or friend declaration. - Specialization - = ClassTemplateSpecializationDecl::Create(Context, Kind, - ClassTemplate->getDeclContext(), - KWLoc, TemplateNameLoc, - ClassTemplate, - Converted, - PrevDecl); + Specialization = ClassTemplateSpecializationDecl::Create( + Context, Kind, ClassTemplate->getDeclContext(), KWLoc, TemplateNameLoc, + ClassTemplate, CanonicalConverted, PrevDecl); SetNestedNameSpecifier(*this, Specialization, SS); if (TemplateParameterLists.size() > 0) { Specialization->setTemplateParameterListsInfo(Context, @@ -8590,8 +8678,8 @@ if (CurContext->isDependentContext()) { TemplateName CanonTemplate = Context.getCanonicalTemplateName(Name); - CanonType = Context.getTemplateSpecializationType( - CanonTemplate, Converted); + CanonType = Context.getTemplateSpecializationType(CanonTemplate, + CanonicalConverted); } else { CanonType = Context.getTypeDeclType(Specialization); } @@ -9752,17 +9840,17 @@ // Check that the template argument list is well-formed for this // template. - SmallVector Converted; - if (CheckTemplateArgumentList(ClassTemplate, TemplateNameLoc, - TemplateArgs, false, Converted, + SmallVector SugaredConverted, CanonicalConverted; + if (CheckTemplateArgumentList(ClassTemplate, TemplateNameLoc, TemplateArgs, + false, SugaredConverted, CanonicalConverted, /*UpdateArgsWithConversions=*/true)) return true; // Find the class template specialization declaration that // corresponds to these arguments. void *InsertPos = nullptr; - ClassTemplateSpecializationDecl *PrevDecl - = ClassTemplate->findSpecialization(Converted, InsertPos); + ClassTemplateSpecializationDecl *PrevDecl = + ClassTemplate->findSpecialization(CanonicalConverted, InsertPos); TemplateSpecializationKind PrevDecl_TSK = PrevDecl ? PrevDecl->getTemplateSpecializationKind() : TSK_Undeclared; @@ -9819,13 +9907,9 @@ if (!Specialization) { // Create a new class template specialization declaration node for // this explicit specialization. - Specialization - = ClassTemplateSpecializationDecl::Create(Context, Kind, - ClassTemplate->getDeclContext(), - KWLoc, TemplateNameLoc, - ClassTemplate, - Converted, - PrevDecl); + Specialization = ClassTemplateSpecializationDecl::Create( + Context, Kind, ClassTemplate->getDeclContext(), KWLoc, TemplateNameLoc, + ClassTemplate, CanonicalConverted, PrevDecl); SetNestedNameSpecifier(*this, Specialization, SS); if (!HasNoEffect && !PrevDecl) { diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp --- a/clang/lib/Sema/SemaTemplateDeduction.cpp +++ b/clang/lib/Sema/SemaTemplateDeduction.cpp @@ -2628,13 +2628,11 @@ /// 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, - SmallVectorImpl &Output) { +static bool ConvertDeducedTemplateArgument( + Sema &S, NamedDecl *Param, DeducedTemplateArgument Arg, NamedDecl *Template, + TemplateDeductionInfo &Info, bool IsDeduced, + SmallVectorImpl &SugaredOutput, + SmallVectorImpl &CanonicalOutput) { auto ConvertArg = [&](DeducedTemplateArgument Arg, unsigned ArgumentPackIndex) { // Convert the deduced template argument into a template @@ -2646,7 +2644,8 @@ // Check the template argument, converting it as necessary. return S.CheckTemplateArgument( Param, ArgLoc, Template, Template->getLocation(), - Template->getSourceRange().getEnd(), ArgumentPackIndex, Output, + Template->getSourceRange().getEnd(), ArgumentPackIndex, SugaredOutput, + CanonicalOutput, IsDeduced ? (Arg.wasDeducedFromArrayBound() ? Sema::CTAK_DeducedFromArrayBound : Sema::CTAK_Deduced) @@ -2656,7 +2655,8 @@ if (Arg.getKind() == TemplateArgument::Pack) { // This is a template argument pack, so check each of its arguments against // the template parameter. - SmallVector PackedArgsBuilder; + SmallVector SugaredPackedArgsBuilder, + CanonicalPackedArgsBuilder; for (const auto &P : Arg.pack_elements()) { // When converting the deduced template argument, append it to the // general output list. We need to do this so that the template argument @@ -2675,23 +2675,25 @@ << Arg << Param; return true; } - if (ConvertArg(InnerArg, PackedArgsBuilder.size())) + if (ConvertArg(InnerArg, SugaredPackedArgsBuilder.size())) return true; // Move the converted template argument into our argument pack. - PackedArgsBuilder.push_back(Output.pop_back_val()); + SugaredPackedArgsBuilder.push_back(SugaredOutput.pop_back_val()); + CanonicalPackedArgsBuilder.push_back(CanonicalOutput.pop_back_val()); } // If the pack is empty, we still need to substitute into the parameter // itself, in case that substitution fails. - if (PackedArgsBuilder.empty()) { + if (SugaredPackedArgsBuilder.empty()) { LocalInstantiationScope Scope(S); - TemplateArgumentList TemplateArgs(TemplateArgumentList::OnStack, Output); + TemplateArgumentList TemplateArgs(TemplateArgumentList::OnStack, + SugaredOutput); MultiLevelTemplateArgumentList Args(Template, TemplateArgs.asArray()); if (auto *NTTP = dyn_cast(Param)) { Sema::InstantiatingTemplate Inst(S, Template->getLocation(), Template, - NTTP, Output, + NTTP, SugaredOutput, Template->getSourceRange()); if (Inst.isInvalid() || S.SubstType(NTTP->getType(), Args, NTTP->getLocation(), @@ -2699,7 +2701,7 @@ return true; } else if (auto *TTP = dyn_cast(Param)) { Sema::InstantiatingTemplate Inst(S, Template->getLocation(), Template, - TTP, Output, + TTP, SugaredOutput, Template->getSourceRange()); if (Inst.isInvalid() || !S.SubstDecl(TTP, S.CurContext, Args)) return true; @@ -2708,8 +2710,10 @@ } // Create the resulting argument pack. - Output.push_back( - TemplateArgument::CreatePackCopy(S.Context, PackedArgsBuilder)); + SugaredOutput.push_back( + TemplateArgument::CreatePackCopy(S.Context, SugaredPackedArgsBuilder)); + CanonicalOutput.push_back(TemplateArgument::CreatePackCopy( + S.Context, CanonicalPackedArgsBuilder)); return false; } @@ -2719,11 +2723,13 @@ // FIXME: This should not be a template, but // ClassTemplatePartialSpecializationDecl sadly does not derive from // TemplateDecl. -template +template static Sema::TemplateDeductionResult ConvertDeducedTemplateArguments( Sema &S, TemplateDeclT *Template, bool IsDeduced, SmallVectorImpl &Deduced, - TemplateDeductionInfo &Info, SmallVectorImpl &Builder, + TemplateDeductionInfo &Info, + SmallVectorImpl &SugaredBuilder, + SmallVectorImpl &CanonicalBuilder, LocalInstantiationScope *CurrentInstantiationScope = nullptr, unsigned NumAlreadyConverted = 0, bool PartialOverloading = false) { TemplateParameterList *TemplateParams = Template->getTemplateParameters(); @@ -2757,7 +2763,9 @@ // We have already fully type-checked and converted this // argument, because it was explicitly-specified. Just record the // presence of this argument. - Builder.push_back(Deduced[I]); + SugaredBuilder.push_back(Deduced[I]); + CanonicalBuilder.push_back( + S.Context.getCanonicalTemplateArgument(Deduced[I])); continue; } } @@ -2765,10 +2773,13 @@ // We may have deduced this argument, so it still needs to be // checked and converted. if (ConvertDeducedTemplateArgument(S, Param, Deduced[I], Template, Info, - IsDeduced, Builder)) { + IsDeduced, SugaredBuilder, + CanonicalBuilder)) { Info.Param = makeTemplateParameter(Param); // FIXME: These template arguments are temporary. Free them! - Info.reset(TemplateArgumentList::CreateCopy(S.Context, Builder)); + Info.reset( + TemplateArgumentList::CreateCopy(S.Context, SugaredBuilder), + TemplateArgumentList::CreateCopy(S.Context, CanonicalBuilder)); return Sema::TDK_SubstitutionFailure; } @@ -2799,15 +2810,16 @@ S.getLangOpts().CPlusPlus17); DefArg = S.SubstDefaultTemplateArgumentIfAvailable( - TD, TD->getLocation(), TD->getSourceRange().getEnd(), Param, Builder, - HasDefaultArg); + TD, TD->getLocation(), TD->getSourceRange().getEnd(), Param, + CanonicalBuilder, 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, Builder)); + Info.reset(TemplateArgumentList::CreateCopy(S.Context, SugaredBuilder), + TemplateArgumentList::CreateCopy(S.Context, CanonicalBuilder)); if (PartialOverloading) break; return HasDefaultArg ? Sema::TDK_SubstitutionFailure @@ -2815,13 +2827,14 @@ } // Check whether we can actually use the default argument. - if (S.CheckTemplateArgument(Param, DefArg, TD, TD->getLocation(), - TD->getSourceRange().getEnd(), 0, Builder, - Sema::CTAK_Specified)) { + if (S.CheckTemplateArgument( + Param, DefArg, TD, TD->getLocation(), TD->getSourceRange().getEnd(), + 0, SugaredBuilder, CanonicalBuilder, 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, Builder)); + Info.reset(TemplateArgumentList::CreateCopy(S.Context, SugaredBuilder), + TemplateArgumentList::CreateCopy(S.Context, CanonicalBuilder)); return Sema::TDK_SubstitutionFailure; } @@ -2849,23 +2862,27 @@ static constexpr bool value = true; }; -template +template static Sema::TemplateDeductionResult -CheckDeducedArgumentConstraints(Sema& S, TemplateDeclT *Template, - ArrayRef DeducedArgs, - TemplateDeductionInfo& Info) { +CheckDeducedArgumentConstraints(Sema &S, TemplateDeclT *Template, + ArrayRef SugaredDeducedArgs, + ArrayRef CanonicalDeducedArgs, + TemplateDeductionInfo &Info) { llvm::SmallVector AssociatedConstraints; Template->getAssociatedConstraints(AssociatedConstraints); // FIXME: This will change quite a bit once deferred concept instantiation is // implemented. + // FIXME: Use SugaredDeducedArgs MultiLevelTemplateArgumentList MLTAL; - MLTAL.addOuterTemplateArguments(Template, DeducedArgs); + MLTAL.addOuterTemplateArguments(Template, CanonicalDeducedArgs); if (S.CheckConstraintSatisfaction(Template, AssociatedConstraints, MLTAL, Info.getLocation(), Info.AssociatedConstraintsSatisfaction) || !Info.AssociatedConstraintsSatisfaction.IsSatisfied) { - Info.reset(TemplateArgumentList::CreateCopy(S.Context, DeducedArgs)); + Info.reset( + TemplateArgumentList::CreateCopy(S.Context, SugaredDeducedArgs), + TemplateArgumentList::CreateCopy(S.Context, CanonicalDeducedArgs)); return Sema::TDK_ConstraintsNotSatisfied; } return Sema::TDK_Success; @@ -2890,16 +2907,19 @@ // C++ [temp.deduct.type]p2: // [...] or if any template argument remains neither deduced nor // explicitly specified, template argument deduction fails. - SmallVector Builder; + SmallVector SugaredBuilder, CanonicalBuilder; if (auto Result = ConvertDeducedTemplateArguments( - S, Partial, IsPartialOrdering, Deduced, Info, Builder)) + S, Partial, IsPartialOrdering, Deduced, Info, SugaredBuilder, + CanonicalBuilder)) return Result; // Form the template argument list from the deduced template arguments. - TemplateArgumentList *DeducedArgumentList - = TemplateArgumentList::CreateCopy(S.Context, Builder); + TemplateArgumentList *SugaredDeducedArgumentList = + TemplateArgumentList::CreateCopy(S.Context, SugaredBuilder); + TemplateArgumentList *CanonicalDeducedArgumentList = + TemplateArgumentList::CreateCopy(S.Context, CanonicalBuilder); - Info.reset(DeducedArgumentList); + Info.reset(SugaredDeducedArgumentList, CanonicalDeducedArgumentList); // Substitute the deduced template arguments into the template // arguments of the class template partial specialization, and @@ -2914,10 +2934,11 @@ TemplateArgumentListInfo InstArgs(PartialTemplArgInfo->LAngleLoc, PartialTemplArgInfo->RAngleLoc); - if (S.SubstTemplateArguments(PartialTemplArgInfo->arguments(), - MultiLevelTemplateArgumentList( - Partial, DeducedArgumentList->asArray()), - InstArgs)) { + if (S.SubstTemplateArguments( + PartialTemplArgInfo->arguments(), + MultiLevelTemplateArgumentList( + Partial, CanonicalDeducedArgumentList->asArray()), + InstArgs)) { unsigned ArgIdx = InstArgs.size(), ParamIdx = ArgIdx; if (ParamIdx >= Partial->getTemplateParameters()->size()) ParamIdx = Partial->getTemplateParameters()->size() - 1; @@ -2930,17 +2951,18 @@ } bool ConstraintsNotSatisfied; - SmallVector ConvertedInstArgs; - if (S.CheckTemplateArgumentList(Template, Partial->getLocation(), InstArgs, - false, ConvertedInstArgs, - /*UpdateArgsWithConversions=*/true, - &ConstraintsNotSatisfied)) - return ConstraintsNotSatisfied ? Sema::TDK_ConstraintsNotSatisfied : - Sema::TDK_SubstitutionFailure; + SmallVector SugaredConvertedInstArgs, + CanonicalConvertedInstArgs; + if (S.CheckTemplateArgumentList( + Template, Partial->getLocation(), InstArgs, false, + SugaredConvertedInstArgs, CanonicalConvertedInstArgs, + /*UpdateArgsWithConversions=*/true, &ConstraintsNotSatisfied)) + return ConstraintsNotSatisfied ? Sema::TDK_ConstraintsNotSatisfied + : Sema::TDK_SubstitutionFailure; TemplateParameterList *TemplateParams = Template->getTemplateParameters(); for (unsigned I = 0, E = TemplateParams->size(); I != E; ++I) { - TemplateArgument InstArg = ConvertedInstArgs.data()[I]; + TemplateArgument InstArg = SugaredConvertedInstArgs.data()[I]; if (!isSameTemplateArg(S.Context, TemplateArgs[I], InstArg, IsPartialOrdering)) { Info.Param = makeTemplateParameter(TemplateParams->getParam(I)); @@ -2953,7 +2975,8 @@ if (Trap.hasErrorOccurred()) return Sema::TDK_SubstitutionFailure; - if (auto Result = CheckDeducedArgumentConstraints(S, Partial, Builder, Info)) + if (auto Result = CheckDeducedArgumentConstraints(S, Partial, SugaredBuilder, + CanonicalBuilder, Info)) return Result; return Sema::TDK_Success; @@ -2977,17 +3000,20 @@ // C++ [temp.deduct.type]p2: // [...] or if any template argument remains neither deduced nor // explicitly specified, template argument deduction fails. - SmallVector Builder; + SmallVector SugaredBuilder, CanonicalBuilder; if (auto Result = ConvertDeducedTemplateArguments( - S, Template, /*IsDeduced*/PartialOrdering, Deduced, Info, Builder)) + S, Template, /*IsDeduced*/ PartialOrdering, Deduced, Info, + SugaredBuilder, CanonicalBuilder, + /*CurrentInstantiationScope=*/nullptr, + /*NumAlreadyConverted=*/0U, /*PartialOverloading=*/false)) return Result; // Check that we produced the correct argument list. TemplateParameterList *TemplateParams = Template->getTemplateParameters(); for (unsigned I = 0, E = TemplateParams->size(); I != E; ++I) { - TemplateArgument InstArg = Builder[I]; + TemplateArgument InstArg = CanonicalBuilder[I]; if (!isSameTemplateArg(S.Context, TemplateArgs[I], InstArg, PartialOrdering, - /*PackExpansionMatchesPack*/ true)) { + /*PackExpansionMatchesPack=*/true)) { Info.Param = makeTemplateParameter(TemplateParams->getParam(I)); Info.FirstArg = TemplateArgs[I]; Info.SecondArg = InstArg; @@ -2998,8 +3024,8 @@ if (Trap.hasErrorOccurred()) return Sema::TDK_SubstitutionFailure; - if (auto Result = CheckDeducedArgumentConstraints(S, Template, Builder, - Info)) + if (auto Result = CheckDeducedArgumentConstraints(S, Template, SugaredBuilder, + CanonicalBuilder, Info)) return Result; return Sema::TDK_Success; @@ -3151,14 +3177,12 @@ /// /// \returns TDK_Success if substitution was successful, or some failure /// condition. -Sema::TemplateDeductionResult -Sema::SubstituteExplicitTemplateArguments( - FunctionTemplateDecl *FunctionTemplate, - TemplateArgumentListInfo &ExplicitTemplateArgs, - SmallVectorImpl &Deduced, - SmallVectorImpl &ParamTypes, - QualType *FunctionType, - TemplateDeductionInfo &Info) { +Sema::TemplateDeductionResult Sema::SubstituteExplicitTemplateArguments( + FunctionTemplateDecl *FunctionTemplate, + TemplateArgumentListInfo &ExplicitTemplateArgs, + SmallVectorImpl &Deduced, + SmallVectorImpl &ParamTypes, QualType *FunctionType, + TemplateDeductionInfo &Info) { FunctionDecl *Function = FunctionTemplate->getTemplatedDecl(); TemplateParameterList *TemplateParams = FunctionTemplate->getTemplateParameters(); @@ -3184,7 +3208,7 @@ // declaration order of their corresponding template-parameters. The // template argument list shall not specify more template-arguments than // there are corresponding template-parameters. - SmallVector Builder; + SmallVector SugaredBuilder, CanonicalBuilder; // Enter a new template instantiation context where we check the // explicitly-specified template arguments against this function template, @@ -3197,9 +3221,11 @@ return TDK_InstantiationDepth; if (CheckTemplateArgumentList(FunctionTemplate, SourceLocation(), - ExplicitTemplateArgs, true, Builder, false) || + ExplicitTemplateArgs, true, SugaredBuilder, + CanonicalBuilder, + /*UpdateArgsWithConversions=*/false) || Trap.hasErrorOccurred()) { - unsigned Index = Builder.size(); + unsigned Index = SugaredBuilder.size(); if (Index >= TemplateParams->size()) return TDK_SubstitutionFailure; Info.Param = makeTemplateParameter(TemplateParams->getParam(Index)); @@ -3208,9 +3234,12 @@ // Form the template argument list from the explicitly-specified // template arguments. - TemplateArgumentList *ExplicitArgumentList - = TemplateArgumentList::CreateCopy(Context, Builder); - Info.setExplicitArgs(ExplicitArgumentList); + TemplateArgumentList *SugaredExplicitArgumentList = + TemplateArgumentList::CreateCopy(Context, SugaredBuilder); + TemplateArgumentList *CanonicalExplicitArgumentList = + TemplateArgumentList::CreateCopy(Context, CanonicalBuilder); + Info.setExplicitArgs(SugaredExplicitArgumentList, + CanonicalExplicitArgumentList); // Template argument deduction and the final substitution should be // done in the context of the templated declaration. Explicit @@ -3223,15 +3252,15 @@ // the explicit template arguments. They'll be used as part of deduction // for this template parameter pack. unsigned PartiallySubstitutedPackIndex = -1u; - if (!Builder.empty()) { - const TemplateArgument &Arg = Builder.back(); + if (!CanonicalBuilder.empty()) { + const TemplateArgument &Arg = CanonicalBuilder.back(); if (Arg.getKind() == TemplateArgument::Pack) { - auto *Param = TemplateParams->getParam(Builder.size() - 1); + auto *Param = TemplateParams->getParam(CanonicalBuilder.size() - 1); // If this is a fully-saturated fixed-size pack, it should be // fully-substituted, not partially-substituted. Optional Expansions = getExpandedPackSize(Param); if (!Expansions || Arg.pack_size() < *Expansions) { - PartiallySubstitutedPackIndex = Builder.size() - 1; + PartiallySubstitutedPackIndex = CanonicalBuilder.size() - 1; CurrentInstantiationScope->SetPartiallySubstitutedPack( Param, Arg.pack_begin(), Arg.pack_size()); } @@ -3252,11 +3281,12 @@ // return type, substitute it after the arguments to ensure we substitute // in lexical order. if (Proto->hasTrailingReturn()) { - if (SubstParmTypes(Function->getLocation(), Function->parameters(), - Proto->getExtParameterInfosOrNull(), - MultiLevelTemplateArgumentList( - FunctionTemplate, ExplicitArgumentList->asArray()), - ParamTypes, /*params*/ nullptr, ExtParamInfos)) + if (SubstParmTypes( + Function->getLocation(), Function->parameters(), + Proto->getExtParameterInfosOrNull(), + MultiLevelTemplateArgumentList( + FunctionTemplate, CanonicalExplicitArgumentList->asArray()), + ParamTypes, /*params*/ nullptr, ExtParamInfos)) return TDK_SubstitutionFailure; } @@ -3279,11 +3309,11 @@ CXXThisScopeRAII ThisScope(*this, ThisContext, ThisTypeQuals, getLangOpts().CPlusPlus11); - ResultType = - SubstType(Proto->getReturnType(), - MultiLevelTemplateArgumentList( - FunctionTemplate, ExplicitArgumentList->asArray()), - Function->getTypeSpecStartLoc(), Function->getDeclName()); + ResultType = SubstType( + Proto->getReturnType(), + MultiLevelTemplateArgumentList( + FunctionTemplate, CanonicalExplicitArgumentList->asArray()), + Function->getTypeSpecStartLoc(), Function->getDeclName()); if (ResultType.isNull() || Trap.hasErrorOccurred()) return TDK_SubstitutionFailure; // CUDA: Kernel function must have 'void' return type. @@ -3298,11 +3328,12 @@ // Instantiate the types of each of the function parameters given the // explicitly-specified template arguments if we didn't do so earlier. if (!Proto->hasTrailingReturn() && - SubstParmTypes(Function->getLocation(), Function->parameters(), - Proto->getExtParameterInfosOrNull(), - MultiLevelTemplateArgumentList( - FunctionTemplate, ExplicitArgumentList->asArray()), - ParamTypes, /*params*/ nullptr, ExtParamInfos)) + SubstParmTypes( + Function->getLocation(), Function->parameters(), + Proto->getExtParameterInfosOrNull(), + MultiLevelTemplateArgumentList( + FunctionTemplate, CanonicalExplicitArgumentList->asArray()), + ParamTypes, /*params*/ nullptr, ExtParamInfos)) return TDK_SubstitutionFailure; if (FunctionType) { @@ -3316,8 +3347,8 @@ if (getLangOpts().CPlusPlus17 && SubstExceptionSpec( Function->getLocation(), EPI.ExceptionSpec, ExceptionStorage, - MultiLevelTemplateArgumentList(FunctionTemplate, - ExplicitArgumentList->asArray()))) + MultiLevelTemplateArgumentList( + FunctionTemplate, CanonicalExplicitArgumentList->asArray()))) return TDK_SubstitutionFailure; *FunctionType = BuildFunctionType(ResultType, ParamTypes, @@ -3339,8 +3370,8 @@ // parameter pack, however, will be set to NULL since the deduction // mechanism handles the partially-substituted argument pack directly. Deduced.reserve(TemplateParams->size()); - for (unsigned I = 0, N = ExplicitArgumentList->size(); I != N; ++I) { - const TemplateArgument &Arg = ExplicitArgumentList->get(I); + for (unsigned I = 0, N = SugaredExplicitArgumentList->size(); I != N; ++I) { + const TemplateArgument &Arg = SugaredExplicitArgumentList->get(I); if (I == PartiallySubstitutedPackIndex) Deduced.push_back(DeducedTemplateArgument()); else @@ -3528,11 +3559,11 @@ // C++ [temp.deduct.type]p2: // [...] or if any template argument remains neither deduced nor // explicitly specified, template argument deduction fails. - SmallVector Builder; + SmallVector SugaredBuilder, CanonicalBuilder; if (auto Result = ConvertDeducedTemplateArguments( - *this, FunctionTemplate, /*IsDeduced*/true, Deduced, Info, Builder, - CurrentInstantiationScope, NumExplicitlySpecified, - PartialOverloading)) + *this, FunctionTemplate, /*IsDeduced*/ true, Deduced, Info, + SugaredBuilder, CanonicalBuilder, CurrentInstantiationScope, + NumExplicitlySpecified, PartialOverloading)) return Result; // C++ [temp.deduct.call]p10: [DR1391] @@ -3548,17 +3579,19 @@ return TDK_NonDependentConversionFailure; // Form the template argument list from the deduced template arguments. - TemplateArgumentList *DeducedArgumentList - = TemplateArgumentList::CreateCopy(Context, Builder); - Info.reset(DeducedArgumentList); + TemplateArgumentList *SugaredDeducedArgumentList = + TemplateArgumentList::CreateCopy(Context, SugaredBuilder); + TemplateArgumentList *CanonicalDeducedArgumentList = + TemplateArgumentList::CreateCopy(Context, CanonicalBuilder); + Info.reset(SugaredDeducedArgumentList, CanonicalDeducedArgumentList); // Substitute the deduced template arguments into the function template // declaration to produce the function template specialization. DeclContext *Owner = FunctionTemplate->getDeclContext(); if (FunctionTemplate->getFriendObjectKind()) Owner = FunctionTemplate->getLexicalDeclContext(); - MultiLevelTemplateArgumentList SubstArgs(FunctionTemplate, - DeducedArgumentList->asArray()); + MultiLevelTemplateArgumentList SubstArgs( + FunctionTemplate, CanonicalDeducedArgumentList->asArray()); Specialization = cast_or_null( SubstDecl(FunctionTemplate->getTemplatedDecl(), Owner, SubstArgs)); if (!Specialization || Specialization->isInvalidDecl()) @@ -3569,9 +3602,10 @@ // If the template argument list is owned by the function template // specialization, release it. - if (Specialization->getTemplateSpecializationArgs() == DeducedArgumentList && + if (Specialization->getTemplateSpecializationArgs() == + CanonicalDeducedArgumentList && !Trap.hasErrorOccurred()) - Info.take(); + Info.takeCanonical(); // There may have been an error that did not prevent us from constructing a // declaration. Mark the declaration invalid and return with a substitution @@ -3590,13 +3624,16 @@ // ([temp.constr.constr]). If the constraints are not satisfied, type // deduction fails. if (!PartialOverloading || - (Builder.size() == FunctionTemplate->getTemplateParameters()->size())) { - if (CheckInstantiatedFunctionTemplateConstraints(Info.getLocation(), - Specialization, Builder, Info.AssociatedConstraintsSatisfaction)) + (CanonicalBuilder.size() == + FunctionTemplate->getTemplateParameters()->size())) { + if (CheckInstantiatedFunctionTemplateConstraints( + Info.getLocation(), Specialization, CanonicalBuilder, + Info.AssociatedConstraintsSatisfaction)) return TDK_MiscellaneousDeductionFailure; if (!Info.AssociatedConstraintsSatisfaction.IsSatisfied) { - Info.reset(TemplateArgumentList::CreateCopy(Context, Builder)); + Info.reset(Info.takeSugared(), + TemplateArgumentList::CreateCopy(Context, CanonicalBuilder)); return TDK_ConstraintsNotSatisfied; } } @@ -4610,12 +4647,14 @@ for (unsigned I = 0, C = TypeLoc.getNumArgs(); I != C; ++I) TemplateArgs.addArgument(TypeLoc.getArgLoc(I)); - llvm::SmallVector Converted; + llvm::SmallVector SugaredConverted, CanonicalConverted; if (S.CheckTemplateArgumentList(Concept, SourceLocation(), TemplateArgs, - /*PartialTemplateArgs=*/false, Converted)) + /*PartialTemplateArgs=*/false, + SugaredConverted, CanonicalConverted)) return true; + // FIXME: use SugaredConverted. MultiLevelTemplateArgumentList MLTAL; - MLTAL.addOuterTemplateArguments(Concept, Converted); + MLTAL.addOuterTemplateArguments(Concept, CanonicalConverted); if (S.CheckConstraintSatisfaction(Concept, {Concept->getConstraintExpr()}, MLTAL, TypeLoc.getLocalSourceRange(), Satisfaction)) @@ -5609,13 +5648,15 @@ // C++1z [temp.arg.template]p3: // If the rewrite produces an invalid type, then P is not at least as // specialized as A. - if (CheckTemplateArgumentList(AArg, Loc, PArgList, false, PArgs) || + SmallVector SugaredPArgs; + if (CheckTemplateArgumentList(AArg, Loc, PArgList, false, SugaredPArgs, + PArgs) || Trap.hasErrorOccurred()) return false; } - QualType AType = Context.getTemplateSpecializationType(X, AArgs); - QualType PType = Context.getTemplateSpecializationType(X, PArgs); + QualType AType = Context.getCanonicalTemplateSpecializationType(X, AArgs); + QualType PType = Context.getCanonicalTemplateSpecializationType(X, PArgs); // ... the function template corresponding to P is at least as specialized // as the function template corresponding to A according to the partial diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp --- a/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -1643,13 +1643,15 @@ // Type=char)), // Type=decltype(2))) // The call to CheckTemplateArgument here produces the ImpCast. - TemplateArgument Converted; - if (SemaRef.CheckTemplateArgument(E->getParameter(), SubstType, - SubstReplacement.get(), - Converted).isInvalid()) + TemplateArgument SugaredConverted, CanonicalConverted; + if (SemaRef + .CheckTemplateArgument(E->getParameter(), SubstType, + SubstReplacement.get(), SugaredConverted, + CanonicalConverted, Sema::CTAK_Specified) + .isInvalid()) return true; - return transformNonTypeTemplateParmRef(E->getParameter(), - E->getExprLoc(), Converted); + return transformNonTypeTemplateParmRef(E->getParameter(), E->getExprLoc(), + CanonicalConverted); } ExprResult TemplateInstantiator::RebuildVarDeclRefExpr(VarDecl *PD, @@ -3144,7 +3146,7 @@ } else { Matched.push_back(PartialSpecMatchResult()); Matched.back().Partial = Partial; - Matched.back().Args = Info.take(); + Matched.back().Args = Info.takeCanonical(); } } diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -3699,12 +3699,10 @@ // Check that the template argument list is well-formed for this // class template. - SmallVector Converted; - if (SemaRef.CheckTemplateArgumentList(InstClassTemplate, - D->getLocation(), - InstTemplateArgs, - false, - Converted, + SmallVector SugaredConverted, CanonicalConverted; + if (SemaRef.CheckTemplateArgumentList(InstClassTemplate, D->getLocation(), + InstTemplateArgs, false, + SugaredConverted, CanonicalConverted, /*UpdateArgsWithConversions=*/true)) return nullptr; @@ -3712,7 +3710,7 @@ // in the member template's set of class template explicit specializations. void *InsertPos = nullptr; ClassTemplateSpecializationDecl *PrevDecl = - InstClassTemplate->findSpecialization(Converted, InsertPos); + InstClassTemplate->findSpecialization(CanonicalConverted, InsertPos); // Check whether we've already seen a conflicting instantiation of this // declaration (for instance, if there was a prior implicit instantiation). @@ -3750,7 +3748,7 @@ ClassTemplateSpecializationDecl *InstD = ClassTemplateSpecializationDecl::Create( SemaRef.Context, D->getTagKind(), Owner, D->getBeginLoc(), - D->getLocation(), InstClassTemplate, Converted, PrevDecl); + D->getLocation(), InstClassTemplate, CanonicalConverted, PrevDecl); // Add this partial specialization to the set of class template partial // specializations. @@ -3764,7 +3762,7 @@ // Build the canonical type that describes the converted template // arguments of the class template explicit specialization. QualType CanonType = SemaRef.Context.getTemplateSpecializationType( - TemplateName(InstClassTemplate), Converted, + TemplateName(InstClassTemplate), CanonicalConverted, SemaRef.Context.getRecordType(InstD)); // Build the fully-sugared type for this class template @@ -3826,16 +3824,17 @@ } // Check that the template argument list is well-formed for this template. - SmallVector Converted; + SmallVector SugaredConverted, CanonicalConverted; if (SemaRef.CheckTemplateArgumentList(InstVarTemplate, D->getLocation(), - VarTemplateArgsInfo, false, Converted, + VarTemplateArgsInfo, false, + SugaredConverted, CanonicalConverted, /*UpdateArgsWithConversions=*/true)) return nullptr; // Check whether we've already seen a declaration of this specialization. void *InsertPos = nullptr; VarTemplateSpecializationDecl *PrevDecl = - InstVarTemplate->findSpecialization(Converted, InsertPos); + InstVarTemplate->findSpecialization(CanonicalConverted, InsertPos); // Check whether we've already seen a conflicting instantiation of this // declaration (for instance, if there was a prior implicit instantiation). @@ -3847,7 +3846,7 @@ return nullptr; return VisitVarTemplateSpecializationDecl( - InstVarTemplate, D, VarTemplateArgsInfo, Converted, PrevDecl); + InstVarTemplate, D, VarTemplateArgsInfo, CanonicalConverted, PrevDecl); } Decl *TemplateDeclInstantiator::VisitVarTemplateSpecializationDecl( @@ -4095,32 +4094,29 @@ // Check that the template argument list is well-formed for this // class template. - SmallVector Converted; - if (SemaRef.CheckTemplateArgumentList(ClassTemplate, - PartialSpec->getLocation(), - InstTemplateArgs, - false, - Converted)) + SmallVector SugaredConverted, CanonicalConverted; + if (SemaRef.CheckTemplateArgumentList( + ClassTemplate, PartialSpec->getLocation(), InstTemplateArgs, + /*PartialTemplateArgs=*/false, SugaredConverted, CanonicalConverted)) return nullptr; // Check these arguments are valid for a template partial specialization. if (SemaRef.CheckTemplatePartialSpecializationArgs( PartialSpec->getLocation(), ClassTemplate, InstTemplateArgs.size(), - Converted)) + 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(Converted, InstParams, + ClassTemplateSpecializationDecl *PrevDecl = + ClassTemplate->findPartialSpecialization(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), - Converted); + QualType CanonType = SemaRef.Context.getTemplateSpecializationType( + TemplateName(ClassTemplate), CanonicalConverted); // Build the fully-sugared type for this class template // specialization as the user wrote in the specialization @@ -4165,7 +4161,8 @@ ClassTemplatePartialSpecializationDecl::Create( SemaRef.Context, PartialSpec->getTagKind(), Owner, PartialSpec->getBeginLoc(), PartialSpec->getLocation(), InstParams, - ClassTemplate, Converted, InstTemplateArgs, CanonType, nullptr); + ClassTemplate, CanonicalConverted, InstTemplateArgs, CanonType, + nullptr); // Substitute the nested name specifier, if any. if (SubstQualifier(PartialSpec, InstPartialSpec)) return nullptr; @@ -4222,27 +4219,29 @@ // Check that the template argument list is well-formed for this // class template. - SmallVector Converted; - if (SemaRef.CheckTemplateArgumentList(VarTemplate, PartialSpec->getLocation(), - InstTemplateArgs, false, Converted)) + SmallVector SugaredConverted, CanonicalConverted; + if (SemaRef.CheckTemplateArgumentList( + VarTemplate, PartialSpec->getLocation(), InstTemplateArgs, + /*PartialTemplateArgs=*/false, SugaredConverted, CanonicalConverted)) return nullptr; // Check these arguments are valid for a template partial specialization. if (SemaRef.CheckTemplatePartialSpecializationArgs( PartialSpec->getLocation(), VarTemplate, InstTemplateArgs.size(), - Converted)) + 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(Converted, InstParams, InsertPos); + VarTemplate->findPartialSpecialization(CanonicalConverted, InstParams, + InsertPos); // Build the canonical type that describes the converted template // arguments of the variable template partial specialization. QualType CanonType = SemaRef.Context.getTemplateSpecializationType( - TemplateName(VarTemplate), Converted); + TemplateName(VarTemplate), CanonicalConverted); // Build the fully-sugared type for this variable template // specialization as the user wrote in the specialization @@ -4298,7 +4297,8 @@ VarTemplatePartialSpecializationDecl::Create( SemaRef.Context, Owner, PartialSpec->getInnerLocStart(), PartialSpec->getLocation(), InstParams, VarTemplate, DI->getType(), - DI, PartialSpec->getStorageClass(), Converted, InstTemplateArgs); + DI, PartialSpec->getStorageClass(), CanonicalConverted, + InstTemplateArgs); // Substitute the nested name specifier, if any. if (SubstQualifier(PartialSpec, InstPartialSpec)) diff --git a/clang/test/SemaCXX/ppc-pair-mma-types.cpp b/clang/test/SemaCXX/ppc-pair-mma-types.cpp --- a/clang/test/SemaCXX/ppc-pair-mma-types.cpp +++ b/clang/test/SemaCXX/ppc-pair-mma-types.cpp @@ -85,8 +85,8 @@ // template argument template - void testVQTemplate(T v, T *p) { // expected-note {{candidate template ignored: substitution failure [with T = __vector_quad]: invalid use of PPC MMA type}} \ - expected-note {{candidate template ignored: substitution failure [with T = __vector_quad]: invalid use of PPC MMA type}} + void testVQTemplate(T v, T *p) { // expected-note {{candidate template ignored: substitution failure [with T = vq_t]: invalid use of PPC MMA type}} \ + expected-note {{candidate template ignored: substitution failure [with T = __vector_quad]: invalid use of PPC MMA type}} *(p + 1) = v; } @@ -276,8 +276,8 @@ // template argument template - void testVPTemplate(T v, T *p) { // expected-note {{candidate template ignored: substitution failure [with T = __vector_pair]: invalid use of PPC MMA type}} \ - expected-note {{candidate template ignored: substitution failure [with T = __vector_pair]: invalid use of PPC MMA type}} + void testVPTemplate(T v, T *p) { // expected-note {{candidate template ignored: substitution failure [with T = vp_t]: invalid use of PPC MMA type}} \ + expected-note {{candidate template ignored: substitution failure [with T = __vector_pair]: invalid use of PPC MMA type}} *(p + 1) = v; } diff --git a/clang/test/SemaTemplate/make_integer_seq.cpp b/clang/test/SemaTemplate/make_integer_seq.cpp --- a/clang/test/SemaTemplate/make_integer_seq.cpp +++ b/clang/test/SemaTemplate/make_integer_seq.cpp @@ -53,7 +53,9 @@ // CHECK-NEXT: |-TemplateArgument type 'int':'int' // CHECK-NEXT: | `-SubstTemplateTypeParmType 0x{{[0-9A-Fa-f]+}} 'int' sugar typename depth 0 index 1 // CHECK-NEXT: | |-BuiltinTemplate 0x{{[0-9A-Fa-f]+}} '__make_integer_seq' -// CHECK-NEXT: | `-BuiltinType 0x{{[0-9A-Fa-f]+}} 'int' +// CHECK-NEXT: | `-SubstTemplateTypeParmType 0x{{[0-9A-Fa-f]+}} 'int' sugar class depth 0 index 0 B1 +// CHECK-NEXT: | |-TypeAliasTemplate 0x{{[0-9A-Fa-f]+}} 'B' +// CHECK-NEXT: | `-BuiltinType 0x{{[0-9A-Fa-f]+}} 'int' // CHECK-NEXT: |-TemplateArgument expr // CHECK-NEXT: | `-ConstantExpr 0x{{[0-9A-Fa-f]+}} 'int' // CHECK-NEXT: | |-value: Int 0 @@ -63,7 +65,7 @@ template