diff options
Diffstat (limited to 'clang/lib/Sema/SemaTemplate.cpp')
-rw-r--r-- | clang/lib/Sema/SemaTemplate.cpp | 1261 |
1 files changed, 763 insertions, 498 deletions
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 1542a07713fb..4b144c239fa4 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -39,6 +39,7 @@ #include "llvm/ADT/StringExtras.h" #include <iterator> +#include <optional> using namespace clang; using namespace sema; @@ -109,7 +110,7 @@ NamedDecl *Sema::getAsTemplateNameDecl(NamedDecl *D, return D; } - if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(D)) { + if (const auto *Record = dyn_cast<CXXRecordDecl>(D)) { // C++ [temp.local]p1: // Like normal (non-template) classes, class templates have an // injected-class-name (Clause 9). The injected-class-name @@ -126,8 +127,7 @@ NamedDecl *Sema::getAsTemplateNameDecl(NamedDecl *D, if (Record->getDescribedClassTemplate()) return Record->getDescribedClassTemplate(); - if (ClassTemplateSpecializationDecl *Spec - = dyn_cast<ClassTemplateSpecializationDecl>(Record)) + if (const auto *Spec = dyn_cast<ClassTemplateSpecializationDecl>(Record)) return Spec->getSpecializedTemplate(); } @@ -399,6 +399,7 @@ bool Sema::LookupTemplateName(LookupResult &Found, LookupCtx = computeDeclContext(ObjectType); IsDependent = !LookupCtx && ObjectType->isDependentType(); assert((IsDependent || !ObjectType->isIncompleteType() || + !ObjectType->getAs<TagType>() || ObjectType->castAs<TagType>()->isBeingDefined()) && "Caller should have completed object type"); @@ -816,7 +817,7 @@ bool Sema::DiagnoseUninstantiableTemplate(SourceLocation PointOfInstantiation, if (!Complain || (PatternDef && PatternDef->isInvalidDecl())) return true; - llvm::Optional<unsigned> Note; + std::optional<unsigned> Note; QualType InstantiationTy; if (TagDecl *TD = dyn_cast<TagDecl>(Instantiation)) InstantiationTy = Context.getTypeDeclType(TD); @@ -941,7 +942,7 @@ static TemplateArgumentLoc translateTemplateArgument(Sema &SemaRef, TemplateName Template = Arg.getAsTemplate().get(); TemplateArgument TArg; if (Arg.getEllipsisLoc().isValid()) - TArg = TemplateArgument(Template, Optional<unsigned int>()); + TArg = TemplateArgument(Template, std::optional<unsigned int>()); else TArg = Template; return TemplateArgumentLoc( @@ -1207,7 +1208,7 @@ static ExprResult formImmediatelyDeclaredConstraint( ImmediatelyDeclaredConstraint.get(), BO_LAnd, EllipsisLoc, /*RHS=*/nullptr, /*RParenLoc=*/SourceLocation(), - /*NumExpansions=*/None); + /*NumExpansions=*/std::nullopt); } /// Attach a type-constraint to a template parameter. @@ -1530,11 +1531,11 @@ NamedDecl *Sema::ActOnNonTypeTemplateParameter(Scope *S, Declarator &D, CheckValidDeclSpecifiers(); - if (TInfo->getType()->isUndeducedType()) { - Diag(D.getIdentifierLoc(), - diag::warn_cxx14_compat_template_nontype_parm_auto_type) - << QualType(TInfo->getType()->getContainedAutoType(), 0); - } + if (const auto *T = TInfo->getType()->getContainedDeducedType()) + if (isa<AutoType>(T)) + Diag(D.getIdentifierLoc(), + diag::warn_cxx14_compat_template_nontype_parm_auto_type) + << QualType(TInfo->getType()->getContainedAutoType(), 0); assert(S->isTemplateParamScope() && "Non-type template parameter not in template parameter scope!"); @@ -1591,9 +1592,10 @@ NamedDecl *Sema::ActOnNonTypeTemplateParameter(Scope *S, Declarator &D, 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; @@ -1686,6 +1688,99 @@ NamedDecl *Sema::ActOnTemplateTemplateParameter(Scope* S, return Param; } +namespace { +class ConstraintRefersToContainingTemplateChecker + : public TreeTransform<ConstraintRefersToContainingTemplateChecker> { + bool Result = false; + const FunctionDecl *Friend = nullptr; + unsigned TemplateDepth = 0; + + // Check a record-decl that we've seen to see if it is a lexical parent of the + // Friend, likely because it was referred to without its template arguments. + void CheckIfContainingRecord(const CXXRecordDecl *CheckingRD) { + CheckingRD = CheckingRD->getMostRecentDecl(); + + for (const DeclContext *DC = Friend->getLexicalDeclContext(); + DC && !DC->isFileContext(); DC = DC->getParent()) + if (const auto *RD = dyn_cast<CXXRecordDecl>(DC)) + if (CheckingRD == RD->getMostRecentDecl()) + Result = true; + } + + void CheckNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D) { + assert(D->getDepth() <= TemplateDepth && + "Nothing should reference a value below the actual template depth, " + "depth is likely wrong"); + if (D->getDepth() != TemplateDepth) + Result = true; + + // Necessary because the type of the NTTP might be what refers to the parent + // constriant. + TransformType(D->getType()); + } + +public: + using inherited = TreeTransform<ConstraintRefersToContainingTemplateChecker>; + + ConstraintRefersToContainingTemplateChecker(Sema &SemaRef, + const FunctionDecl *Friend, + unsigned TemplateDepth) + : inherited(SemaRef), Friend(Friend), TemplateDepth(TemplateDepth) {} + bool getResult() const { return Result; } + + // This should be the only template parm type that we have to deal with. + // SubstTempalteTypeParmPack, SubstNonTypeTemplateParmPack, and + // FunctionParmPackExpr are all partially substituted, which cannot happen + // with concepts at this point in translation. + using inherited::TransformTemplateTypeParmType; + QualType TransformTemplateTypeParmType(TypeLocBuilder &TLB, + TemplateTypeParmTypeLoc TL, bool) { + assert(TL.getDecl()->getDepth() <= TemplateDepth && + "Nothing should reference a value below the actual template depth, " + "depth is likely wrong"); + if (TL.getDecl()->getDepth() != TemplateDepth) + Result = true; + return inherited::TransformTemplateTypeParmType( + TLB, TL, + /*SuppressObjCLifetime=*/false); + } + + Decl *TransformDecl(SourceLocation Loc, Decl *D) { + if (!D) + return D; + // FIXME : This is possibly an incomplete list, but it is unclear what other + // Decl kinds could be used to refer to the template parameters. This is a + // best guess so far based on examples currently available, but the + // unreachable should catch future instances/cases. + if (auto *TD = dyn_cast<TypedefNameDecl>(D)) + TransformType(TD->getUnderlyingType()); + else if (auto *NTTPD = dyn_cast<NonTypeTemplateParmDecl>(D)) + CheckNonTypeTemplateParmDecl(NTTPD); + else if (auto *VD = dyn_cast<ValueDecl>(D)) + TransformType(VD->getType()); + else if (auto *TD = dyn_cast<TemplateDecl>(D)) + TransformTemplateParameterList(TD->getTemplateParameters()); + else if (auto *RD = dyn_cast<CXXRecordDecl>(D)) + CheckIfContainingRecord(RD); + else if (isa<NamedDecl>(D)) { + // No direct types to visit here I believe. + } else + llvm_unreachable("Don't know how to handle this declaration type yet"); + return D; + } +}; +} // namespace + +bool Sema::ConstraintExpressionDependsOnEnclosingTemplate( + const FunctionDecl *Friend, unsigned TemplateDepth, + const Expr *Constraint) { + assert(Friend->getFriendObjectKind() && "Only works on a friend"); + ConstraintRefersToContainingTemplateChecker Checker(*this, Friend, + TemplateDepth); + Checker.TransformExpr(const_cast<Expr *>(Constraint)); + return Checker.getResult(); +} + /// ActOnTemplateParameterList - Builds a TemplateParameterList, optionally /// constrained by RequiresClause, that contains the template parameters in /// Params. @@ -1705,8 +1800,7 @@ Sema::ActOnTemplateParameterList(unsigned Depth, return TemplateParameterList::Create( Context, TemplateLoc, LAngleLoc, - llvm::makeArrayRef(Params.data(), Params.size()), - RAngleLoc, RequiresClause); + llvm::ArrayRef(Params.data(), Params.size()), RAngleLoc, RequiresClause); } static void SetNestedNameSpecifier(Sema &S, TagDecl *T, @@ -1985,8 +2079,8 @@ DeclResult Sema::CheckClassTemplate( SetNestedNameSpecifier(*this, NewClass, SS); if (NumOuterTemplateParamLists > 0) NewClass->setTemplateParameterListsInfo( - Context, llvm::makeArrayRef(OuterTemplateParamLists, - NumOuterTemplateParamLists)); + Context, + llvm::ArrayRef(OuterTemplateParamLists, NumOuterTemplateParamLists)); // Add alignment attributes if necessary; these attributes are checked when // the ASTContext lays out the structure. @@ -2284,10 +2378,12 @@ private: /*Depth*/ 0, Depth1IndexAdjustment + TTP->getIndex(), TTP->getIdentifier(), TTP->wasDeclaredWithTypename(), TTP->isParameterPack(), TTP->hasTypeConstraint(), - TTP->isExpandedParameterPack() ? - llvm::Optional<unsigned>(TTP->getNumExpansionParameters()) : None); + TTP->isExpandedParameterPack() + ? std::optional<unsigned>(TTP->getNumExpansionParameters()) + : std::nullopt); if (const auto *TC = TTP->getTypeConstraint()) - SemaRef.SubstTypeConstraint(NewTTP, TC, Args); + SemaRef.SubstTypeConstraint(NewTTP, TC, Args, + /*EvaluateConstraint*/ true); if (TTP->hasDefaultArgument()) { TypeSourceInfo *InstantiatedDefaultArg = SemaRef.SubstType(TTP->getDefaultArgumentInfo(), Args, @@ -2444,6 +2540,8 @@ private: TInfo->getType(), TInfo, LocEnd, Ctor); Guide->setImplicit(); Guide->setParams(Params); + if (Ctor && Ctor->getTrailingRequiresClause()) + Guide->setTrailingRequiresClause(Ctor->getTrailingRequiresClause()); for (auto *Param : Params) Param->setDeclContext(Guide); @@ -2535,7 +2633,7 @@ void Sema::DeclareImplicitDeductionGuides(TemplateDecl *Template, // additional function template derived as above from a hypothetical // constructor C(). if (!AddedAny) - Transform.buildSimpleDeductionGuide(None); + Transform.buildSimpleDeductionGuide(std::nullopt); // -- An additional function template derived as above from a hypothetical // constructor C(C), called the copy deduction candidate. @@ -3411,7 +3509,7 @@ TemplateParameterList *Sema::MatchTemplateParametersToScopeSpecifier( // Fabricate an empty template parameter list for the invented header. return TemplateParameterList::Create(Context, SourceLocation(), - SourceLocation(), None, + SourceLocation(), std::nullopt, SourceLocation(), nullptr); } @@ -3496,45 +3594,54 @@ void Sema::NoteAllFoundTemplates(TemplateName Name) { static QualType checkBuiltinTemplateIdType(Sema &SemaRef, BuiltinTemplateDecl *BTD, - const SmallVectorImpl<TemplateArgument> &Converted, + ArrayRef<TemplateArgument> Converted, SourceLocation TemplateLoc, TemplateArgumentListInfo &TemplateArgs) { ASTContext &Context = SemaRef.getASTContext(); + switch (BTD->getBuiltinTemplateKind()) { case BTK__make_integer_seq: { // Specializations of __make_integer_seq<S, T, N> are treated like // S<T, 0, ..., N-1>. + QualType OrigType = Converted[1].getAsType(); // C++14 [inteseq.intseq]p1: // T shall be an integer type. - if (!Converted[1].getAsType()->isIntegralType(Context)) { + if (!OrigType->isDependentType() && !OrigType->isIntegralType(Context)) { SemaRef.Diag(TemplateArgs[1].getLocation(), diag::err_integer_sequence_integral_element_type); return QualType(); } - // C++14 [inteseq.make]p1: - // If N is negative the program is ill-formed. TemplateArgument NumArgsArg = Converted[2]; - llvm::APSInt NumArgs = NumArgsArg.getAsIntegral(); - if (NumArgs < 0) { + if (NumArgsArg.isDependent()) + return Context.getCanonicalTemplateSpecializationType(TemplateName(BTD), + Converted); + + TemplateArgumentListInfo SyntheticTemplateArgs; + // The type argument, wrapped in substitution sugar, gets reused as the + // first template argument in the synthetic template argument list. + SyntheticTemplateArgs.addArgument( + TemplateArgumentLoc(TemplateArgument(OrigType), + SemaRef.Context.getTrivialTypeSourceInfo( + OrigType, TemplateArgs[1].getLocation()))); + + if (llvm::APSInt NumArgs = NumArgsArg.getAsIntegral(); NumArgs >= 0) { + // Expand N into 0 ... N-1. + for (llvm::APSInt I(NumArgs.getBitWidth(), NumArgs.isUnsigned()); + I < NumArgs; ++I) { + TemplateArgument TA(Context, I, OrigType); + SyntheticTemplateArgs.addArgument(SemaRef.getTrivialTemplateArgumentLoc( + TA, OrigType, TemplateArgs[2].getLocation())); + } + } else { + // C++14 [inteseq.make]p1: + // If N is negative the program is ill-formed. SemaRef.Diag(TemplateArgs[2].getLocation(), diag::err_integer_sequence_negative_length); return QualType(); } - QualType ArgTy = NumArgsArg.getIntegralType(); - TemplateArgumentListInfo SyntheticTemplateArgs; - // The type argument gets reused as the first template argument in the - // synthetic template argument list. - SyntheticTemplateArgs.addArgument(TemplateArgs[1]); - // Expand N into 0 ... N-1. - for (llvm::APSInt I(NumArgs.getBitWidth(), NumArgs.isUnsigned()); - I < NumArgs; ++I) { - TemplateArgument TA(Context, I, ArgTy); - SyntheticTemplateArgs.addArgument(SemaRef.getTrivialTemplateArgumentLoc( - TA, ArgTy, TemplateArgs[2].getLocation())); - } // The first template argument will be reused as the template decl that // our synthetic template arguments will be applied to. return SemaRef.CheckTemplateIdType(Converted[0].getAsTemplate(), @@ -3548,11 +3655,15 @@ checkBuiltinTemplateIdType(Sema &SemaRef, BuiltinTemplateDecl *BTD, assert(Converted.size() == 2 && "__type_pack_element should be given an index and a parameter pack"); - // If the Index is out of bounds, the program is ill-formed. TemplateArgument IndexArg = Converted[0], Ts = Converted[1]; + if (IndexArg.isDependent() || Ts.isDependent()) + return Context.getCanonicalTemplateSpecializationType(TemplateName(BTD), + Converted); + llvm::APSInt Index = IndexArg.getAsIntegral(); assert(Index >= 0 && "the index used with __type_pack_element should be of " "type std::size_t, and hence be non-negative"); + // If the Index is out of bounds, the program is ill-formed. if (Index >= Ts.pack_size()) { SemaRef.Diag(TemplateArgs[0].getLocation(), diag::err_type_pack_element_out_of_bounds); @@ -3560,8 +3671,8 @@ checkBuiltinTemplateIdType(Sema &SemaRef, BuiltinTemplateDecl *BTD, } // We simply return the type at index `Index`. - auto Nth = std::next(Ts.pack_begin(), Index.getExtValue()); - return Nth->getAsType(); + int64_t N = Index.getExtValue(); + return Ts.getPackAsArray()[N].getAsType(); } llvm_unreachable("unexpected BuiltinTemplateDecl!"); } @@ -3585,9 +3696,8 @@ static void collectConjunctionTerms(Expr *Clause, if (BinOp->getOpcode() == BO_LAnd) { collectConjunctionTerms(BinOp->getLHS(), Terms); collectConjunctionTerms(BinOp->getRHS(), Terms); + return; } - - return; } Terms.push_back(Clause); @@ -3715,10 +3825,9 @@ QualType Sema::CheckTemplateIdType(TemplateName Name, // assume the template is a type template. Either our assumption is // correct, or the code is ill-formed and will be diagnosed when the // dependent name is substituted. - return Context.getDependentTemplateSpecializationType(ETK_None, - DTN->getQualifier(), - DTN->getIdentifier(), - TemplateArgs); + return Context.getDependentTemplateSpecializationType( + ETK_None, DTN->getQualifier(), DTN->getIdentifier(), + TemplateArgs.arguments()); if (Name.getAsAssumedTemplateName() && resolveAssumedTemplateNameAsType(/*Scope*/nullptr, Name, TemplateLoc)) @@ -3730,7 +3839,8 @@ QualType Sema::CheckTemplateIdType(TemplateName Name, // We might have a substituted template template parameter pack. If so, // build a template specialization type for it. if (Name.getAsSubstTemplateTemplateParmPack()) - return Context.getTemplateSpecializationType(Name, TemplateArgs); + return Context.getTemplateSpecializationType(Name, + TemplateArgs.arguments()); Diag(TemplateLoc, diag::err_template_id_not_a_type) << Name; @@ -3740,9 +3850,9 @@ QualType Sema::CheckTemplateIdType(TemplateName Name, // Check that the template argument list is well-formed for this // template. - SmallVector<TemplateArgument, 4> Converted; - if (CheckTemplateArgumentList(Template, TemplateLoc, TemplateArgs, - false, Converted, + SmallVector<TemplateArgument, 4> SugaredConverted, CanonicalConverted; + if (CheckTemplateArgumentList(Template, TemplateLoc, TemplateArgs, false, + SugaredConverted, CanonicalConverted, /*UpdateArgsWithConversions=*/true)) return QualType(); @@ -3756,12 +3866,10 @@ QualType Sema::CheckTemplateIdType(TemplateName Name, if (Pattern->isInvalidDecl()) return QualType(); - TemplateArgumentList StackTemplateArgs(TemplateArgumentList::OnStack, - Converted); - // Only substitute for the innermost template argument list. MultiLevelTemplateArgumentList TemplateArgLists; - TemplateArgLists.addOuterTemplateArguments(&StackTemplateArgs); + TemplateArgLists.addOuterTemplateArguments(Template, CanonicalConverted, + /*Final=*/false); TemplateArgLists.addOuterRetainedLevels( AliasTemplate->getTemplateParameters()->getDepth()); @@ -3808,9 +3916,12 @@ QualType Sema::CheckTemplateIdType(TemplateName Name, return QualType(); } + } else if (auto *BTD = dyn_cast<BuiltinTemplateDecl>(Template)) { + 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 @@ -3818,7 +3929,8 @@ QualType Sema::CheckTemplateIdType(TemplateName Name, // A<T, T> have identical types when A is declared as: // // template<typename T, typename U = T> 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. @@ -3857,13 +3969,13 @@ QualType Sema::CheckTemplateIdType(TemplateName Name, break; } } - } else if (ClassTemplateDecl *ClassTemplate - = dyn_cast<ClassTemplateDecl>(Template)) { + } else if (ClassTemplateDecl *ClassTemplate = + dyn_cast<ClassTemplateDecl>(Template)) { // 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 @@ -3872,7 +3984,8 @@ QualType Sema::CheckTemplateIdType(TemplateName Name, 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()); @@ -3882,8 +3995,9 @@ QualType Sema::CheckTemplateIdType(TemplateName Name, ClassTemplate->getTemplatedDecl()->hasAttrs()) { InstantiatingTemplate Inst(*this, TemplateLoc, Decl); if (!Inst.isInvalid()) { - MultiLevelTemplateArgumentList TemplateArgLists; - TemplateArgLists.addOuterTemplateArguments(Converted); + MultiLevelTemplateArgumentList TemplateArgLists(Template, + CanonicalConverted, + /*Final=*/false); InstantiateAttrsForDecl(TemplateArgLists, ClassTemplate->getTemplatedDecl(), Decl); } @@ -3895,15 +4009,15 @@ QualType Sema::CheckTemplateIdType(TemplateName Name, CanonType = Context.getTypeDeclType(Decl); assert(isa<RecordType>(CanonType) && "type of non-dependent specialization is not a RecordType"); - } else if (auto *BTD = dyn_cast<BuiltinTemplateDecl>(Template)) { - CanonType = checkBuiltinTemplateIdType(*this, BTD, Converted, TemplateLoc, - TemplateArgs); + } else { + llvm_unreachable("Unhandled template kind"); } // Build the fully-sugared type for this class template // specialization, which refers back to the class template // specialization we created or found. - return Context.getTemplateSpecializationType(Name, TemplateArgs, CanonType); + return Context.getTemplateSpecializationType(Name, TemplateArgs.arguments(), + CanonType); } void Sema::ActOnUndeclaredTypeTemplateName(Scope *S, TemplateTy &ParsedName, @@ -3964,7 +4078,8 @@ TypeResult Sema::ActOnTemplateIdType( TemplateTy TemplateD, IdentifierInfo *TemplateII, SourceLocation TemplateIILoc, SourceLocation LAngleLoc, ASTTemplateArgsPtr TemplateArgsIn, SourceLocation RAngleLoc, - bool IsCtorOrDtorName, bool IsClassName) { + bool IsCtorOrDtorName, bool IsClassName, + ImplicitTypenameContext AllowImplicitTypename) { if (SS.isInvalid()) return true; @@ -3978,9 +4093,18 @@ TypeResult Sema::ActOnTemplateIdType( // qualified-id denotes a type, forming an // elaborated-type-specifier (7.1.5.3). if (!LookupCtx && isDependentScopeSpecifier(SS)) { - Diag(SS.getBeginLoc(), diag::err_typename_missing_template) - << SS.getScopeRep() << TemplateII->getName(); - // Recover as if 'typename' were specified. + // C++2a relaxes some of those restrictions in [temp.res]p5. + if (AllowImplicitTypename == ImplicitTypenameContext::Yes) { + if (getLangOpts().CPlusPlus20) + Diag(SS.getBeginLoc(), diag::warn_cxx17_compat_implicit_typename); + else + Diag(SS.getBeginLoc(), diag::ext_implicit_typename) + << SS.getScopeRep() << TemplateII->getName() + << FixItHint::CreateInsertion(SS.getBeginLoc(), "typename "); + } else + Diag(SS.getBeginLoc(), diag::err_typename_missing_template) + << SS.getScopeRep() << TemplateII->getName(); + // FIXME: This is not quite correct recovery as we don't transform SS // into the corresponding dependent form (and we don't diagnose missing // 'template' keywords within SS as a result). @@ -4014,11 +4138,10 @@ TypeResult Sema::ActOnTemplateIdType( translateTemplateArguments(TemplateArgsIn, TemplateArgs); if (DependentTemplateName *DTN = Template.getAsDependentTemplateName()) { - QualType T - = Context.getDependentTemplateSpecializationType(ETK_None, - DTN->getQualifier(), - DTN->getIdentifier(), - TemplateArgs); + assert(SS.getScopeRep() == DTN->getQualifier()); + QualType T = Context.getDependentTemplateSpecializationType( + ETK_None, DTN->getQualifier(), DTN->getIdentifier(), + TemplateArgs.arguments()); // Build type-source information. TypeLocBuilder TLB; DependentTemplateSpecializationTypeLoc SpecTL @@ -4034,14 +4157,14 @@ TypeResult Sema::ActOnTemplateIdType( return CreateParsedType(T, TLB.getTypeSourceInfo(Context, T)); } - QualType Result = CheckTemplateIdType(Template, TemplateIILoc, TemplateArgs); - if (Result.isNull()) + QualType SpecTy = CheckTemplateIdType(Template, TemplateIILoc, TemplateArgs); + if (SpecTy.isNull()) return true; // Build type-source information. TypeLocBuilder TLB; - TemplateSpecializationTypeLoc SpecTL - = TLB.push<TemplateSpecializationTypeLoc>(Result); + TemplateSpecializationTypeLoc SpecTL = + TLB.push<TemplateSpecializationTypeLoc>(SpecTy); SpecTL.setTemplateKeywordLoc(TemplateKWLoc); SpecTL.setTemplateNameLoc(TemplateIILoc); SpecTL.setLAngleLoc(LAngleLoc); @@ -4049,18 +4172,14 @@ TypeResult Sema::ActOnTemplateIdType( for (unsigned i = 0, e = SpecTL.getNumArgs(); i != e; ++i) SpecTL.setArgLocInfo(i, TemplateArgs[i].getLocInfo()); - // NOTE: avoid constructing an ElaboratedTypeLoc if this is a - // constructor or destructor name (in such a case, the scope specifier - // will be attached to the enclosing Decl or Expr node). - if (SS.isNotEmpty() && !IsCtorOrDtorName) { - // Create an elaborated-type-specifier containing the nested-name-specifier. - Result = Context.getElaboratedType(ETK_None, SS.getScopeRep(), Result); - ElaboratedTypeLoc ElabTL = TLB.push<ElaboratedTypeLoc>(Result); - ElabTL.setElaboratedKeywordLoc(SourceLocation()); + // Create an elaborated-type-specifier containing the nested-name-specifier. + QualType ElTy = getElaboratedType( + ETK_None, !IsCtorOrDtorName ? SS : CXXScopeSpec(), SpecTy); + ElaboratedTypeLoc ElabTL = TLB.push<ElaboratedTypeLoc>(ElTy); + ElabTL.setElaboratedKeywordLoc(SourceLocation()); + if (!ElabTL.isEmpty()) ElabTL.setQualifierLoc(SS.getWithLocInContext(Context)); - } - - return CreateParsedType(Result, TLB.getTypeSourceInfo(Context, Result)); + return CreateParsedType(ElTy, TLB.getTypeSourceInfo(Context, ElTy)); } TypeResult Sema::ActOnTagTemplateIdType(TagUseKind TUK, @@ -4088,10 +4207,10 @@ TypeResult Sema::ActOnTagTemplateIdType(TagUseKind TUK, = TypeWithKeyword::getKeywordForTagTypeKind(TagKind); if (DependentTemplateName *DTN = Template.getAsDependentTemplateName()) { - QualType T = Context.getDependentTemplateSpecializationType(Keyword, - DTN->getQualifier(), - DTN->getIdentifier(), - TemplateArgs); + assert(SS.getScopeRep() == DTN->getQualifier()); + QualType T = Context.getDependentTemplateSpecializationType( + Keyword, DTN->getQualifier(), DTN->getIdentifier(), + TemplateArgs.arguments()); // Build type-source information. TypeLocBuilder TLB; @@ -4386,9 +4505,9 @@ DeclResult Sema::ActOnVarTemplateSpecialization( // Check that the template argument list is well-formed for this // template. - SmallVector<TemplateArgument, 4> Converted; + SmallVector<TemplateArgument, 4> SugaredConverted, CanonicalConverted; if (CheckTemplateArgumentList(VarTemplate, TemplateNameLoc, TemplateArgs, - false, Converted, + false, SugaredConverted, CanonicalConverted, /*UpdateArgsWithConversions=*/true)) return true; @@ -4396,21 +4515,22 @@ DeclResult Sema::ActOnVarTemplateSpecialization( // 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: @@ -4431,10 +4551,10 @@ DeclResult Sema::ActOnVarTemplateSpecialization( 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; @@ -4461,7 +4581,7 @@ DeclResult Sema::ActOnVarTemplateSpecialization( VarTemplatePartialSpecializationDecl::Create( Context, VarTemplate->getDeclContext(), TemplateKWLoc, TemplateNameLoc, TemplateParams, VarTemplate, DI->getType(), DI, SC, - Converted, TemplateArgs); + CanonicalConverted, TemplateArgs); if (!PrevPartial) VarTemplate->AddPartialSpecialization(Partial, InsertPos); @@ -4478,7 +4598,7 @@ DeclResult Sema::ActOnVarTemplateSpecialization( // 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) @@ -4556,24 +4676,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<TemplateArgument, 4> Converted; + SmallVector<TemplateArgument, 4> SugaredConverted, CanonicalConverted; if (CheckTemplateArgumentList( Template, TemplateNameLoc, const_cast<TemplateArgumentListInfo &>(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; @@ -4585,7 +4706,7 @@ Sema::CheckVarTemplateId(VarTemplateDecl *Template, SourceLocation TemplateLoc, // that it represents. That is, VarDecl *InstantiationPattern = Template->getTemplatedDecl(); TemplateArgumentList TemplateArgList(TemplateArgumentList::OnStack, - Converted); + CanonicalConverted); TemplateArgumentList *InstantiationArgs = &TemplateArgList; bool AmbiguousPartialSpec = false; typedef PartialSpecMatchResult MatchResult; @@ -4617,7 +4738,7 @@ Sema::CheckVarTemplateId(VarTemplateDecl *Template, SourceLocation TemplateLoc, } else { Matched.push_back(PartialSpecMatchResult()); Matched.back().Partial = Partial; - Matched.back().Args = Info.take(); + Matched.back().Args = Info.takeCanonical(); } } @@ -4673,7 +4794,7 @@ Sema::CheckVarTemplateId(VarTemplateDecl *Template, SourceLocation TemplateLoc, // FIXME: LateAttrs et al.? VarTemplateSpecializationDecl *Decl = BuildVarTemplateInstantiation( Template, InstantiationPattern, *InstantiationArgs, TemplateArgs, - Converted, TemplateNameLoc /*, LateAttrs, StartingScope*/); + CanonicalConverted, TemplateNameLoc /*, LateAttrs, StartingScope*/); if (!Decl) return true; @@ -4744,29 +4865,41 @@ Sema::CheckConceptTemplateId(const CXXScopeSpec &SS, const TemplateArgumentListInfo *TemplateArgs) { assert(NamedConcept && "A concept template id without a template?"); - llvm::SmallVector<TemplateArgument, 4> Converted; - if (CheckTemplateArgumentList(NamedConcept, ConceptNameInfo.getLoc(), - const_cast<TemplateArgumentListInfo&>(*TemplateArgs), - /*PartialTemplateArgs=*/false, Converted, - /*UpdateArgsWithConversions=*/false)) + llvm::SmallVector<TemplateArgument, 4> SugaredConverted, CanonicalConverted; + if (CheckTemplateArgumentList( + NamedConcept, ConceptNameInfo.getLoc(), + const_cast<TemplateArgumentListInfo &>(*TemplateArgs), + /*PartialTemplateArgs=*/false, SugaredConverted, CanonicalConverted, + /*UpdateArgsWithConversions=*/false)) return ExprError(); + auto *CSD = ImplicitConceptSpecializationDecl::Create( + Context, NamedConcept->getDeclContext(), NamedConcept->getLocation(), + CanonicalConverted); ConstraintSatisfaction Satisfaction; bool AreArgsDependent = - TemplateSpecializationType::anyDependentTemplateArguments(*TemplateArgs, - Converted); + TemplateSpecializationType::anyDependentTemplateArguments( + *TemplateArgs, CanonicalConverted); + MultiLevelTemplateArgumentList MLTAL(NamedConcept, CanonicalConverted, + /*Final=*/false); + LocalInstantiationScope Scope(*this); + + EnterExpressionEvaluationContext EECtx{ + *this, ExpressionEvaluationContext::ConstantEvaluated, CSD}; + if (!AreArgsDependent && CheckConstraintSatisfaction( - NamedConcept, {NamedConcept->getConstraintExpr()}, Converted, + NamedConcept, {NamedConcept->getConstraintExpr()}, MLTAL, SourceRange(SS.isSet() ? SS.getBeginLoc() : ConceptNameInfo.getLoc(), TemplateArgs->getRAngleLoc()), 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, + ASTTemplateArgumentListInfo::Create(Context, *TemplateArgs), CSD, AreArgsDependent ? nullptr : &Satisfaction); } @@ -5008,9 +5141,10 @@ TemplateNameKind Sema::ActOnTemplateName(Scope *S, return TNK_Non_template; } -bool Sema::CheckTemplateTypeArgument(TemplateTypeParmDecl *Param, - TemplateArgumentLoc &AL, - SmallVectorImpl<TemplateArgument> &Converted) { +bool Sema::CheckTemplateTypeArgument( + TemplateTypeParmDecl *Param, TemplateArgumentLoc &AL, + SmallVectorImpl<TemplateArgument> &SugaredConverted, + SmallVectorImpl<TemplateArgument> &CanonicalConverted) { const TemplateArgument &Arg = AL.getArgument(); QualType ArgType; TypeSourceInfo *TSI = nullptr; @@ -5087,7 +5221,7 @@ bool Sema::CheckTemplateTypeArgument(TemplateTypeParmDecl *Param, } } // fallthrough - LLVM_FALLTHROUGH; + [[fallthrough]]; } default: { // We have a template type parameter but the template argument @@ -5103,9 +5237,6 @@ bool Sema::CheckTemplateTypeArgument(TemplateTypeParmDecl *Param, 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. @@ -5117,7 +5248,9 @@ bool Sema::CheckTemplateTypeArgument(TemplateTypeParmDecl *Param, ArgType = Context.getQualifiedType(ArgType, Qs); } - Converted.push_back(TemplateArgument(ArgType)); + SugaredConverted.push_back(TemplateArgument(ArgType)); + CanonicalConverted.push_back( + TemplateArgument(Context.getCanonicalType(ArgType))); return false; } @@ -5142,31 +5275,27 @@ bool Sema::CheckTemplateTypeArgument(TemplateTypeParmDecl *Param, /// \param Converted the list of template arguments provided for template /// parameters that precede \p Param in the template parameter list. /// \returns the substituted template argument, or NULL if an error occurred. -static TypeSourceInfo * -SubstDefaultTemplateArgument(Sema &SemaRef, - TemplateDecl *Template, - SourceLocation TemplateLoc, - SourceLocation RAngleLoc, - TemplateTypeParmDecl *Param, - SmallVectorImpl<TemplateArgument> &Converted) { +static TypeSourceInfo *SubstDefaultTemplateArgument( + Sema &SemaRef, TemplateDecl *Template, SourceLocation TemplateLoc, + SourceLocation RAngleLoc, TemplateTypeParmDecl *Param, + ArrayRef<TemplateArgument> SugaredConverted, + ArrayRef<TemplateArgument> CanonicalConverted) { TypeSourceInfo *ArgType = Param->getDefaultArgumentInfo(); // If the argument type is dependent, instantiate it now based // on the previously-computed template arguments. if (ArgType->getType()->isInstantiationDependentType()) { - Sema::InstantiatingTemplate Inst(SemaRef, TemplateLoc, - Param, Template, Converted, + Sema::InstantiatingTemplate Inst(SemaRef, TemplateLoc, Param, Template, + SugaredConverted, SourceRange(TemplateLoc, RAngleLoc)); if (Inst.isInvalid()) return nullptr; - TemplateArgumentList TemplateArgs(TemplateArgumentList::OnStack, Converted); - // Only substitute for the innermost template argument list. - MultiLevelTemplateArgumentList TemplateArgLists; - TemplateArgLists.addOuterTemplateArguments(&TemplateArgs); + MultiLevelTemplateArgumentList TemplateArgLists(Template, SugaredConverted, + /*Final=*/true); for (unsigned i = 0, e = Param->getDepth(); i != e; ++i) - TemplateArgLists.addOuterTemplateArguments(None); + TemplateArgLists.addOuterTemplateArguments(std::nullopt); bool ForLambdaCallOperator = false; if (const auto *Rec = dyn_cast<CXXRecordDecl>(Template->getDeclContext())) @@ -5203,26 +5332,22 @@ SubstDefaultTemplateArgument(Sema &SemaRef, /// parameters that precede \p Param in the template parameter list. /// /// \returns the substituted template argument, or NULL if an error occurred. -static ExprResult -SubstDefaultTemplateArgument(Sema &SemaRef, - TemplateDecl *Template, - SourceLocation TemplateLoc, - SourceLocation RAngleLoc, - NonTypeTemplateParmDecl *Param, - SmallVectorImpl<TemplateArgument> &Converted) { - Sema::InstantiatingTemplate Inst(SemaRef, TemplateLoc, - Param, Template, Converted, +static ExprResult SubstDefaultTemplateArgument( + Sema &SemaRef, TemplateDecl *Template, SourceLocation TemplateLoc, + SourceLocation RAngleLoc, NonTypeTemplateParmDecl *Param, + ArrayRef<TemplateArgument> SugaredConverted, + ArrayRef<TemplateArgument> CanonicalConverted) { + Sema::InstantiatingTemplate Inst(SemaRef, TemplateLoc, Param, Template, + SugaredConverted, SourceRange(TemplateLoc, RAngleLoc)); if (Inst.isInvalid()) return ExprError(); - TemplateArgumentList TemplateArgs(TemplateArgumentList::OnStack, Converted); - // Only substitute for the innermost template argument list. - MultiLevelTemplateArgumentList TemplateArgLists; - TemplateArgLists.addOuterTemplateArguments(&TemplateArgs); + MultiLevelTemplateArgumentList TemplateArgLists(Template, SugaredConverted, + /*Final=*/true); for (unsigned i = 0, e = Param->getDepth(); i != e; ++i) - TemplateArgLists.addOuterTemplateArguments(None); + TemplateArgLists.addOuterTemplateArguments(std::nullopt); Sema::ContextRAII SavedContext(SemaRef, Template->getDeclContext()); EnterExpressionEvaluationContext ConstantEvaluated( @@ -5255,27 +5380,23 @@ SubstDefaultTemplateArgument(Sema &SemaRef, /// source-location information) that precedes the template name. /// /// \returns the substituted template argument, or NULL if an error occurred. -static TemplateName -SubstDefaultTemplateArgument(Sema &SemaRef, - TemplateDecl *Template, - SourceLocation TemplateLoc, - SourceLocation RAngleLoc, - TemplateTemplateParmDecl *Param, - SmallVectorImpl<TemplateArgument> &Converted, - NestedNameSpecifierLoc &QualifierLoc) { +static TemplateName SubstDefaultTemplateArgument( + Sema &SemaRef, TemplateDecl *Template, SourceLocation TemplateLoc, + SourceLocation RAngleLoc, TemplateTemplateParmDecl *Param, + ArrayRef<TemplateArgument> SugaredConverted, + ArrayRef<TemplateArgument> CanonicalConverted, + NestedNameSpecifierLoc &QualifierLoc) { Sema::InstantiatingTemplate Inst( - SemaRef, TemplateLoc, TemplateParameter(Param), Template, Converted, - SourceRange(TemplateLoc, RAngleLoc)); + SemaRef, TemplateLoc, TemplateParameter(Param), Template, + SugaredConverted, SourceRange(TemplateLoc, RAngleLoc)); if (Inst.isInvalid()) return TemplateName(); - TemplateArgumentList TemplateArgs(TemplateArgumentList::OnStack, Converted); - // Only substitute for the innermost template argument list. - MultiLevelTemplateArgumentList TemplateArgLists; - TemplateArgLists.addOuterTemplateArguments(&TemplateArgs); + MultiLevelTemplateArgumentList TemplateArgLists(Template, SugaredConverted, + /*Final=*/true); for (unsigned i = 0, e = Param->getDepth(); i != e; ++i) - TemplateArgLists.addOuterTemplateArguments(None); + TemplateArgLists.addOuterTemplateArguments(std::nullopt); Sema::ContextRAII SavedContext(SemaRef, Template->getDeclContext()); // Substitute into the nested-name-specifier first, @@ -5297,14 +5418,11 @@ SubstDefaultTemplateArgument(Sema &SemaRef, /// If the given template parameter has a default template /// argument, substitute into that default template argument and /// return the corresponding template argument. -TemplateArgumentLoc -Sema::SubstDefaultTemplateArgumentIfAvailable(TemplateDecl *Template, - SourceLocation TemplateLoc, - SourceLocation RAngleLoc, - Decl *Param, - SmallVectorImpl<TemplateArgument> - &Converted, - bool &HasDefaultArg) { +TemplateArgumentLoc Sema::SubstDefaultTemplateArgumentIfAvailable( + TemplateDecl *Template, SourceLocation TemplateLoc, + SourceLocation RAngleLoc, Decl *Param, + ArrayRef<TemplateArgument> SugaredConverted, + ArrayRef<TemplateArgument> CanonicalConverted, bool &HasDefaultArg) { HasDefaultArg = false; if (TemplateTypeParmDecl *TypeParm = dyn_cast<TemplateTypeParmDecl>(Param)) { @@ -5312,11 +5430,9 @@ Sema::SubstDefaultTemplateArgumentIfAvailable(TemplateDecl *Template, return TemplateArgumentLoc(); HasDefaultArg = true; - TypeSourceInfo *DI = SubstDefaultTemplateArgument(*this, Template, - TemplateLoc, - RAngleLoc, - TypeParm, - Converted); + TypeSourceInfo *DI = SubstDefaultTemplateArgument( + *this, Template, TemplateLoc, RAngleLoc, TypeParm, SugaredConverted, + CanonicalConverted); if (DI) return TemplateArgumentLoc(TemplateArgument(DI->getType()), DI); @@ -5329,11 +5445,9 @@ Sema::SubstDefaultTemplateArgumentIfAvailable(TemplateDecl *Template, return TemplateArgumentLoc(); HasDefaultArg = true; - ExprResult Arg = SubstDefaultTemplateArgument(*this, Template, - TemplateLoc, - RAngleLoc, - NonTypeParm, - Converted); + ExprResult Arg = SubstDefaultTemplateArgument( + *this, Template, TemplateLoc, RAngleLoc, NonTypeParm, SugaredConverted, + CanonicalConverted); if (Arg.isInvalid()) return TemplateArgumentLoc(); @@ -5348,12 +5462,9 @@ Sema::SubstDefaultTemplateArgumentIfAvailable(TemplateDecl *Template, HasDefaultArg = true; NestedNameSpecifierLoc QualifierLoc; - TemplateName TName = SubstDefaultTemplateArgument(*this, Template, - TemplateLoc, - RAngleLoc, - TempTempParm, - Converted, - QualifierLoc); + TemplateName TName = SubstDefaultTemplateArgument( + *this, Template, TemplateLoc, RAngleLoc, TempTempParm, SugaredConverted, + CanonicalConverted, QualifierLoc); if (TName.isNull()) return TemplateArgumentLoc(); @@ -5423,17 +5534,17 @@ convertTypeTemplateArgumentToTemplate(ASTContext &Context, TypeLoc TLoc) { /// 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<TemplateArgument> &Converted, - CheckTemplateArgumentKind CTAK) { +bool Sema::CheckTemplateArgument( + NamedDecl *Param, TemplateArgumentLoc &Arg, NamedDecl *Template, + SourceLocation TemplateLoc, SourceLocation RAngleLoc, + unsigned ArgumentPackIndex, + SmallVectorImpl<TemplateArgument> &SugaredConverted, + SmallVectorImpl<TemplateArgument> &CanonicalConverted, + CheckTemplateArgumentKind CTAK) { // Check template type parameters. if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(Param)) - return CheckTemplateTypeArgument(TTP, Arg, Converted); + return CheckTemplateTypeArgument(TTP, Arg, SugaredConverted, + CanonicalConverted); // Check non-type template parameters. if (NonTypeTemplateParmDecl *NTTP =dyn_cast<NonTypeTemplateParmDecl>(Param)) { @@ -5448,27 +5559,22 @@ bool Sema::CheckTemplateArgument(NamedDecl *Param, !isa<TemplateTemplateParmDecl>(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; - TemplateArgumentList TemplateArgs(TemplateArgumentList::OnStack, - Converted); - + MultiLevelTemplateArgumentList MLTAL(Template, SugaredConverted, + /*Final=*/true); // If the parameter is a pack expansion, expand this slice of the pack. if (auto *PET = NTTPType->getAs<PackExpansionType>()) { Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(*this, ArgumentPackIndex); - NTTPType = SubstType(PET->getPattern(), - MultiLevelTemplateArgumentList(TemplateArgs), - NTTP->getLocation(), + NTTPType = SubstType(PET->getPattern(), MLTAL, NTTP->getLocation(), NTTP->getDeclName()); } else { - NTTPType = SubstType(NTTPType, - MultiLevelTemplateArgumentList(TemplateArgs), - NTTP->getLocation(), + NTTPType = SubstType(NTTPType, MLTAL, NTTP->getLocation(), NTTP->getDeclName()); } @@ -5486,11 +5592,11 @@ bool Sema::CheckTemplateArgument(NamedDecl *Param, llvm_unreachable("Should never see a NULL template argument here"); case TemplateArgument::Expression: { - TemplateArgument Result; + Expr *E = Arg.getArgument().getAsExpr(); + 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. @@ -5499,12 +5605,13 @@ bool Sema::CheckTemplateArgument(NamedDecl *Param, // If the resulting expression is new, then use it in place of the // old expression in the template argument. - if (Res.get() != Arg.getArgument().getAsExpr()) { + if (Res.get() != E) { TemplateArgument TA(Res.get()); Arg = TemplateArgumentLoc(TA, Res.get()); } - Converted.push_back(Result); + SugaredConverted.push_back(SugaredResult); + CanonicalConverted.push_back(CanonicalResult); break; } @@ -5513,7 +5620,9 @@ bool Sema::CheckTemplateArgument(NamedDecl *Param, 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: @@ -5549,12 +5658,14 @@ bool Sema::CheckTemplateArgument(NamedDecl *Param, 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; } @@ -5611,15 +5722,17 @@ bool Sema::CheckTemplateArgument(NamedDecl *Param, { // Set up a template instantiation context. LocalInstantiationScope Scope(*this); - InstantiatingTemplate Inst(*this, TemplateLoc, Template, - TempParm, Converted, + InstantiatingTemplate Inst(*this, TemplateLoc, Template, TempParm, + SugaredConverted, SourceRange(TemplateLoc, RAngleLoc)); if (Inst.isInvalid()) return true; - TemplateArgumentList TemplateArgs(TemplateArgumentList::OnStack, Converted); - Params = SubstTemplateParams(Params, CurContext, - MultiLevelTemplateArgumentList(TemplateArgs)); + Params = + SubstTemplateParams(Params, CurContext, + MultiLevelTemplateArgumentList( + Template, SugaredConverted, /*Final=*/true), + /*EvaluateConstraints=*/false); if (!Params) return true; } @@ -5644,7 +5757,9 @@ bool Sema::CheckTemplateArgument(NamedDecl *Param, if (CheckTemplateTemplateArgument(TempParm, Params, Arg)) return true; - Converted.push_back(Arg.getArgument()); + SugaredConverted.push_back(Arg.getArgument()); + CanonicalConverted.push_back( + Context.getCanonicalTemplateArgument(Arg.getArgument())); break; case TemplateArgument::Expression: @@ -5711,7 +5826,8 @@ static bool diagnoseMissingArgument(Sema &S, SourceLocation Loc, bool Sema::CheckTemplateArgumentList( TemplateDecl *Template, SourceLocation TemplateLoc, TemplateArgumentListInfo &TemplateArgs, bool PartialTemplateArgs, - SmallVectorImpl<TemplateArgument> &Converted, + SmallVectorImpl<TemplateArgument> &SugaredConverted, + SmallVectorImpl<TemplateArgument> &CanonicalConverted, bool UpdateArgsWithConversions, bool *ConstraintsNotSatisfied) { if (ConstraintsNotSatisfied) @@ -5737,7 +5853,8 @@ bool Sema::CheckTemplateArgumentList( // corresponding parameter declared by the template in its // template-parameter-list. bool isTemplateTemplateParameter = isa<TemplateTemplateParmDecl>(Template); - SmallVector<TemplateArgument, 2> ArgumentPack; + SmallVector<TemplateArgument, 2> SugaredArgumentPack; + SmallVector<TemplateArgument, 2> CanonicalArgumentPack; unsigned ArgIdx = 0, NumArgs = NewArgs.size(); LocalInstantiationScope InstScope(*this, true); for (TemplateParameterList::iterator Param = Params->begin(), @@ -5745,13 +5862,17 @@ bool Sema::CheckTemplateArgumentList( Param != ParamEnd; /* increment in loop */) { // If we have an expanded parameter pack, make sure we don't have too // many arguments. - if (Optional<unsigned> Expansions = getExpandedPackSize(*Param)) { - if (*Expansions == ArgumentPack.size()) { + if (std::optional<unsigned> Expansions = getExpandedPackSize(*Param)) { + 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; @@ -5770,9 +5891,10 @@ bool Sema::CheckTemplateArgumentList( 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 = @@ -5801,7 +5923,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. - 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; @@ -5811,16 +5934,25 @@ bool Sema::CheckTemplateArgumentList( // 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. - Converted.insert(Converted.end(), - ArgumentPack.begin(), ArgumentPack.end()); - 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(NewArgs[ArgIdx].getArgument()); + const TemplateArgument &Arg = NewArgs[ArgIdx].getArgument(); + SugaredConverted.push_back(Arg); + CanonicalConverted.push_back( + Context.getCanonicalTemplateArgument(Arg)); ++ArgIdx; } @@ -5832,9 +5964,12 @@ bool Sema::CheckTemplateArgumentList( // 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; } @@ -5847,12 +5982,20 @@ bool Sema::CheckTemplateArgumentList( // A non-expanded parameter pack before the end of the parameter list // only occurs for an ill-formed template parameter list, unless we've // got a partial argument list for a function template, so just bail out. - if (Param + 1 != ParamEnd) + if (Param + 1 != ParamEnd) { + assert( + (Template->getMostRecentDecl()->getKind() != Decl::Kind::Concept) && + "Concept templates must have parameter packs at the end."); return true; + } + + SugaredConverted.push_back( + TemplateArgument::CreatePackCopy(Context, SugaredArgumentPack)); + SugaredArgumentPack.clear(); - Converted.push_back( - TemplateArgument::CreatePackCopy(Context, ArgumentPack)); - ArgumentPack.clear(); + CanonicalConverted.push_back( + TemplateArgument::CreatePackCopy(Context, CanonicalArgumentPack)); + CanonicalArgumentPack.clear(); ++Param; continue; @@ -5871,12 +6014,9 @@ bool Sema::CheckTemplateArgumentList( return diagnoseMissingArgument(*this, TemplateLoc, Template, TTP, NewArgs); - TypeSourceInfo *ArgType = SubstDefaultTemplateArgument(*this, - Template, - TemplateLoc, - RAngleLoc, - TTP, - Converted); + TypeSourceInfo *ArgType = SubstDefaultTemplateArgument( + *this, Template, TemplateLoc, RAngleLoc, TTP, SugaredConverted, + CanonicalConverted); if (!ArgType) return true; @@ -5888,11 +6028,9 @@ bool Sema::CheckTemplateArgumentList( return diagnoseMissingArgument(*this, TemplateLoc, Template, NTTP, NewArgs); - ExprResult E = SubstDefaultTemplateArgument(*this, Template, - TemplateLoc, - RAngleLoc, - NTTP, - Converted); + ExprResult E = SubstDefaultTemplateArgument( + *this, Template, TemplateLoc, RAngleLoc, NTTP, SugaredConverted, + CanonicalConverted); if (E.isInvalid()) return true; @@ -5907,12 +6045,9 @@ bool Sema::CheckTemplateArgumentList( NewArgs); NestedNameSpecifierLoc QualifierLoc; - TemplateName Name = SubstDefaultTemplateArgument(*this, Template, - TemplateLoc, - RAngleLoc, - TempParm, - Converted, - QualifierLoc); + TemplateName Name = SubstDefaultTemplateArgument( + *this, Template, TemplateLoc, RAngleLoc, TempParm, SugaredConverted, + CanonicalConverted, QualifierLoc); if (Name.isNull()) return true; @@ -5925,14 +6060,16 @@ bool Sema::CheckTemplateArgumentList( // 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 @@ -5952,8 +6089,12 @@ bool Sema::CheckTemplateArgumentList( // still dependent). if (ArgIdx < NumArgs && CurrentInstantiationScope && CurrentInstantiationScope->getPartiallySubstitutedPack()) { - while (ArgIdx < NumArgs && NewArgs[ArgIdx].getArgument().isPackExpansion()) - Converted.push_back(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. @@ -5974,13 +6115,39 @@ bool Sema::CheckTemplateArgumentList( if (UpdateArgsWithConversions) TemplateArgs = std::move(NewArgs); - if (!PartialTemplateArgs && - EnsureTemplateArgumentListConstraints( - Template, Converted, SourceRange(TemplateLoc, - TemplateArgs.getRAngleLoc()))) { - if (ConstraintsNotSatisfied) - *ConstraintsNotSatisfied = true; - return true; + if (!PartialTemplateArgs) { + TemplateArgumentList StackTemplateArgs(TemplateArgumentList::OnStack, + CanonicalConverted); + // Setup the context/ThisScope for the case where we are needing to + // re-instantiate constraints outside of normal instantiation. + DeclContext *NewContext = Template->getDeclContext(); + + // If this template is in a template, make sure we extract the templated + // decl. + if (auto *TD = dyn_cast<TemplateDecl>(NewContext)) + NewContext = Decl::castToDeclContext(TD->getTemplatedDecl()); + auto *RD = dyn_cast<CXXRecordDecl>(NewContext); + + Qualifiers ThisQuals; + if (const auto *Method = + dyn_cast_or_null<CXXMethodDecl>(Template->getTemplatedDecl())) + ThisQuals = Method->getMethodQualifiers(); + + ContextRAII Context(*this, NewContext); + CXXThisScopeRAII(*this, RD, ThisQuals, RD != nullptr); + + MultiLevelTemplateArgumentList MLTAL = getTemplateInstantiationArgs( + Template, /*Final=*/false, &StackTemplateArgs, + /*RelativeToPrimary=*/true, + /*Pattern=*/nullptr, + /*ForConceptInstantiation=*/true); + if (EnsureTemplateArgumentListConstraints( + Template, MLTAL, + SourceRange(TemplateLoc, TemplateArgs.getRAngleLoc()))) { + if (ConstraintsNotSatisfied) + *ConstraintsNotSatisfied = true; + return true; + } } return false; @@ -6125,7 +6292,7 @@ bool UnnamedLocalNoLinkageFinder::VisitTypeOfExprType(const TypeOfExprType*) { } bool UnnamedLocalNoLinkageFinder::VisitTypeOfType(const TypeOfType* T) { - return Visit(T->getUnderlyingType()); + return Visit(T->getUnmodifiedType()); } bool UnnamedLocalNoLinkageFinder::VisitDecltypeType(const DecltypeType*) { @@ -6274,8 +6441,9 @@ bool Sema::CheckTemplateArgument(TypeSourceInfo *ArgInfo) { assert(ArgInfo && "invalid TypeSourceInfo"); QualType Arg = ArgInfo->getType(); SourceRange SR = ArgInfo->getTypeLoc().getSourceRange(); + QualType CanonArg = Context.getCanonicalType(Arg); - if (Arg->isVariablyModifiedType()) { + if (CanonArg->isVariablyModifiedType()) { return Diag(SR.getBegin(), diag::err_variably_modified_template_arg) << Arg; } else if (Context.hasSameUnqualifiedType(Arg, Context.OverloadTy)) { return Diag(SR.getBegin(), diag::err_template_arg_overload_type) << SR; @@ -6288,9 +6456,9 @@ bool Sema::CheckTemplateArgument(TypeSourceInfo *ArgInfo) { // // C++11 allows these, and even in C++03 we allow them as an extension with // a warning. - if (LangOpts.CPlusPlus11 || Arg->hasUnnamedOrLocalType()) { + if (LangOpts.CPlusPlus11 || CanonArg->hasUnnamedOrLocalType()) { UnnamedLocalNoLinkageFinder Finder(*this, SR); - (void)Finder.Visit(Context.getCanonicalType(Arg)); + (void)Finder.Visit(CanonArg); } return false; @@ -6362,7 +6530,7 @@ isNullPointerValueTemplateArgument(Sema &S, NonTypeTemplateParmDecl *Param, // - a constant expression that evaluates to a null pointer value (4.10); or // - a constant expression that evaluates to a null member pointer value // (4.11); or - if ((EvalResult.Val.isLValue() && !EvalResult.Val.getLValueBase()) || + if ((EvalResult.Val.isLValue() && EvalResult.Val.isNullPointer()) || (EvalResult.Val.isMemberPointer() && !EvalResult.Val.getMemberPointerDecl())) { // If our expression has an appropriate type, we've succeeded. @@ -6380,6 +6548,16 @@ isNullPointerValueTemplateArgument(Sema &S, NonTypeTemplateParmDecl *Param, return NPV_NullPointer; } + if (EvalResult.Val.isLValue() && !EvalResult.Val.getLValueBase()) { + // We found a pointer that isn't null, but doesn't refer to an object. + // We could just return NPV_NotNullPointer, but we can print a better + // message with the information we have here. + S.Diag(Arg->getExprLoc(), diag::err_template_arg_invalid) + << EvalResult.Val.getAsString(S.Context, ParamType); + S.Diag(Param->getLocation(), diag::note_template_param_here); + return NPV_Error; + } + // If we don't have a null pointer value, but we do have a NULL pointer // constant, suggest a cast to the appropriate type. if (Arg->isNullPointerConstant(S.Context, Expr::NPC_NeverValueDependent)) { @@ -6457,12 +6635,9 @@ static bool CheckTemplateArgumentIsCompatibleWithParameter( /// 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(); @@ -6566,8 +6741,11 @@ CheckTemplateArgumentAddressOfObjectOrFunction(Sema &S, 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: @@ -6581,7 +6759,9 @@ CheckTemplateArgumentAddressOfObjectOrFunction(Sema &S, // 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; } @@ -6711,19 +6891,21 @@ CheckTemplateArgumentAddressOfObjectOrFunction(Sema &S, return true; // Create the template argument. - Converted = TemplateArgument(cast<ValueDecl>(Entity->getCanonicalDecl()), - S.Context.getCanonicalType(ParamType)); + SugaredConverted = TemplateArgument(Entity, ParamType); + CanonicalConverted = + TemplateArgument(cast<ValueDecl>(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; @@ -6771,10 +6953,14 @@ static bool CheckTemplateArgumentPointerToMember(Sema &S, if (VD->getType()->isMemberPointerType()) { if (isa<NonTypeTemplateParmDecl>(VD)) { if (Arg->isTypeDependent() || Arg->isValueDependent()) { - Converted = TemplateArgument(Arg); + SugaredConverted = TemplateArgument(Arg); + CanonicalConverted = + S.Context.getCanonicalTemplateArgument(SugaredConverted); } else { - VD = cast<ValueDecl>(VD->getCanonicalDecl()); - Converted = TemplateArgument(VD, ParamType); + SugaredConverted = TemplateArgument(VD, ParamType); + CanonicalConverted = + TemplateArgument(cast<ValueDecl>(VD->getCanonicalDecl()), + S.Context.getCanonicalType(ParamType)); } return Invalid; } @@ -6792,8 +6978,10 @@ static bool CheckTemplateArgumentPointerToMember(Sema &S, 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; @@ -6830,10 +7018,15 @@ static bool CheckTemplateArgumentPointerToMember(Sema &S, // 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<ValueDecl>(DRE->getDecl()->getCanonicalDecl()); - Converted = TemplateArgument(D, S.Context.getCanonicalType(ParamType)); + ValueDecl *D = DRE->getDecl(); + SugaredConverted = TemplateArgument(D, ParamType); + CanonicalConverted = + TemplateArgument(cast<ValueDecl>(D->getCanonicalDecl()), + S.Context.getCanonicalType(ParamType)); } return Invalid; } @@ -6854,7 +7047,8 @@ static bool CheckTemplateArgumentPointerToMember(Sema &S, /// 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(); @@ -6869,7 +7063,9 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, if (CTAK == CTAK_Deduced && Arg->isTypeDependent()) { auto *AT = dyn_cast<AutoType>(DeducedT); if (AT && AT->isDecltypeAuto()) { - Converted = TemplateArgument(Arg); + SugaredConverted = TemplateArgument(Arg); + CanonicalConverted = TemplateArgument( + Context.getCanonicalTemplateArgument(SugaredConverted)); return Arg; } } @@ -6877,7 +7073,6 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, // When checking a deduced template argument, deduce from its type even if // the type is dependent, in order to check the types of non-type template // arguments line up properly in partial ordering. - Optional<unsigned> Depth = Param->getDepth() + 1; Expr *DeductionArg = Arg; if (auto *PE = dyn_cast<PackExpansionExpr>(DeductionArg)) DeductionArg = PE->getPattern(); @@ -6893,20 +7088,30 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, DeduceTemplateSpecializationFromInitializer(TSI, Entity, Kind, Inits); if (ParamType.isNull()) return ExprError(); - } else if (DeduceAutoType( - TSI, DeductionArg, ParamType, Depth, - // We do not check constraints right now because the - // immediately-declared constraint of the auto type is also - // an associated constraint, and will be checked along with - // the other associated constraints after checking the - // template argument list. - /*IgnoreConstraints=*/true) == DAR_Failed) { - Diag(Arg->getExprLoc(), - diag::err_non_type_template_parm_type_deduction_failure) - << Param->getDeclName() << Param->getType() << Arg->getType() - << Arg->getSourceRange(); - Diag(Param->getLocation(), diag::note_template_param_here); - return ExprError(); + } else { + TemplateDeductionInfo Info(DeductionArg->getExprLoc(), + Param->getDepth() + 1); + ParamType = QualType(); + TemplateDeductionResult Result = + DeduceAutoType(TSI->getTypeLoc(), DeductionArg, ParamType, Info, + /*DependentDeduction=*/true, + // We do not check constraints right now because the + // immediately-declared constraint of the auto type is + // also an associated constraint, and will be checked + // along with the other associated constraints after + // checking the template argument list. + /*IgnoreConstraints=*/true); + if (Result == TDK_AlreadyDiagnosed) { + if (ParamType.isNull()) + return ExprError(); + } else if (Result != TDK_Success) { + Diag(Arg->getExprLoc(), + diag::err_non_type_template_parm_type_deduction_failure) + << Param->getDeclName() << Param->getType() << Arg->getType() + << Arg->getSourceRange(); + Diag(Param->getLocation(), diag::note_template_param_here); + return ExprError(); + } } // CheckNonTypeTemplateParameterType will produce a diagnostic if there's // an error. The error message normally references the parameter @@ -6938,7 +7143,9 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, // work. Similarly for CTAD, when comparing 'A<x>' 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, @@ -6953,11 +7160,8 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, } // If either the parameter has a dependent type or the argument is - // type-dependent, there's nothing we can check now. The argument only - // contains an unexpanded pack during partial ordering, and there's - // nothing more we can check in that case. - if (ParamType->isDependentType() || Arg->isTypeDependent() || - Arg->containsUnexpandedParameterPack()) { + // type-dependent, there's nothing we can check now. + if (ParamType->isDependentType() || Arg->isTypeDependent()) { // Force the argument to the type of the parameter to maintain invariants. auto *PE = dyn_cast<PackExpansionExpr>(Arg); if (PE) @@ -6975,7 +7179,9 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, 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; } @@ -7000,11 +7206,16 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, Context.hasSameUnqualifiedType(ParamType, InnerArg->getType())) { NamedDecl *ND = cast<DeclRefExpr>(InnerArg)->getDecl(); if (auto *TPO = dyn_cast<TemplateParamObjectDecl>(ND)) { - Converted = TemplateArgument(TPO, CanonParamType); + + SugaredConverted = TemplateArgument(TPO, ParamType); + CanonicalConverted = + TemplateArgument(TPO->getCanonicalDecl(), CanonParamType); return Arg; } if (isa<NonTypeTemplateParmDecl>(ND)) { - Converted = TemplateArgument(Arg); + SugaredConverted = TemplateArgument(Arg); + CanonicalConverted = + Context.getCanonicalTemplateArgument(SugaredConverted); return Arg; } } @@ -7021,7 +7232,9 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, // 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; } @@ -7029,14 +7242,17 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, 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()); @@ -7051,8 +7267,12 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, } auto *VD = const_cast<ValueDecl*>(Value.getMemberPointerDecl()); - Converted = VD ? TemplateArgument(VD, CanonParamType) - : TemplateArgument(CanonParamType, /*isNullPtr*/true); + SugaredConverted = VD ? TemplateArgument(VD, ParamType) + : TemplateArgument(ParamType, /*isNullPtr=*/true); + CanonicalConverted = + VD ? TemplateArgument(cast<ValueDecl>(VD->getCanonicalDecl()), + CanonParamType) + : TemplateArgument(CanonParamType, /*isNullPtr=*/true); break; } case APValue::LValue: { @@ -7092,17 +7312,25 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, "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); + + SugaredConverted = VD ? TemplateArgument(VD, ParamType) + : TemplateArgument(ParamType, /*isNullPtr=*/true); + CanonicalConverted = + VD ? TemplateArgument(cast<ValueDecl>(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: @@ -7152,7 +7380,9 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, // 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; } @@ -7166,8 +7396,9 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, ? 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; } @@ -7237,13 +7468,16 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, 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<EnumType>()) - IntegerType = Context.getCanonicalType(Enum->getDecl()->getIntegerType()); + QualType IntegerType = ParamType; + if (const EnumType *Enum = IntegerType->getAs<EnumType>()) { + IntegerType = Enum->getDecl()->getIntegerType(); + } if (ParamType->isBooleanType()) { // Value must be zero or one. @@ -7289,10 +7523,10 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, } } - 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; } @@ -7337,15 +7571,15 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, } 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; } @@ -7358,9 +7592,8 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, 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; } @@ -7389,9 +7622,8 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, return ExprError(); } - if (CheckTemplateArgumentAddressOfObjectOrFunction(*this, Param, - ParamType, - Arg, Converted)) + if (CheckTemplateArgumentAddressOfObjectOrFunction( + *this, Param, ParamType, Arg, SugaredConverted, CanonicalConverted)) return ExprError(); return Arg; } @@ -7399,7 +7631,9 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, // 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; } @@ -7415,8 +7649,10 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, 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; } } @@ -7425,8 +7661,8 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, // 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; } @@ -7499,10 +7735,10 @@ bool Sema::CheckTemplateTemplateArgument(TemplateTemplateParmDecl *Param, if (isTemplateTemplateParameterAtLeastAsSpecializedAs(Params, Template, Arg.getLocation())) { - // C++2a[temp.func.order]p2 + // P2113 + // C++20[temp.func.order]p2 // [...] If both deductions succeed, the partial ordering selects the - // more constrained template as described by the rules in - // [temp.constr.order]. + // more constrained template (if one exists) as determined below. SmallVector<const Expr *, 3> ParamsAC, TemplateAC; Params->getAssociatedConstraints(ParamsAC); // C++2a[temp.arg.template]p3 @@ -7510,7 +7746,9 @@ bool Sema::CheckTemplateTemplateArgument(TemplateTemplateParmDecl *Param, // are not considered. if (ParamsAC.empty()) return false; + Template->getAssociatedConstraints(TemplateAC); + bool IsParamAtLeastAsConstrained; if (IsAtLeastAsConstrained(Param, ParamsAC, Template, TemplateAC, IsParamAtLeastAsConstrained)) @@ -7685,8 +7923,8 @@ Sema::BuildExpressionFromIntegralTemplateArgument(const TemplateArgument &Arg, E = new (Context) CharacterLiteral(Arg.getAsIntegral().getZExtValue(), Kind, T, Loc); } else if (T->isBooleanType()) { - E = new (Context) CXXBoolLiteralExpr(Arg.getAsIntegral().getBoolValue(), - T, Loc); + E = CXXBoolLiteralExpr::Create(Context, Arg.getAsIntegral().getBoolValue(), + T, Loc); } else if (T->isNullPtrType()) { E = new (Context) CXXNullPtrLiteralExpr(Context.NullPtrTy, Loc); } else { @@ -7706,10 +7944,11 @@ Sema::BuildExpressionFromIntegralTemplateArgument(const TemplateArgument &Arg, } /// Match two template parameters within template parameter lists. -static bool MatchTemplateParameterKind(Sema &S, NamedDecl *New, NamedDecl *Old, - bool Complain, - Sema::TemplateParameterListEqualKind Kind, - SourceLocation TemplateArgLoc) { +static bool MatchTemplateParameterKind( + Sema &S, NamedDecl *New, const NamedDecl *NewInstFrom, NamedDecl *Old, + const NamedDecl *OldInstFrom, bool Complain, + Sema::TemplateParameterListEqualKind Kind, SourceLocation TemplateArgLoc, + bool PartialOrdering) { // Check the actual kind (type, non-type, template). if (Old->getKind() != New->getKind()) { if (Complain) { @@ -7791,20 +8030,34 @@ static bool MatchTemplateParameterKind(Sema &S, NamedDecl *New, NamedDecl *Old, else if (TemplateTemplateParmDecl *OldTTP = dyn_cast<TemplateTemplateParmDecl>(Old)) { TemplateTemplateParmDecl *NewTTP = cast<TemplateTemplateParmDecl>(New); - if (!S.TemplateParameterListsAreEqual(NewTTP->getTemplateParameters(), - OldTTP->getTemplateParameters(), - Complain, - (Kind == Sema::TPL_TemplateMatch - ? Sema::TPL_TemplateTemplateParmMatch - : Kind), - TemplateArgLoc)) + if (!S.TemplateParameterListsAreEqual( + NewInstFrom, NewTTP->getTemplateParameters(), OldInstFrom, + OldTTP->getTemplateParameters(), Complain, + (Kind == Sema::TPL_TemplateMatch + ? Sema::TPL_TemplateTemplateParmMatch + : Kind), + TemplateArgLoc, PartialOrdering)) return false; - } else if (Kind != Sema::TPL_TemplateTemplateArgumentMatch) { + } + + if (!PartialOrdering && Kind != Sema::TPL_TemplateTemplateArgumentMatch && + !isa<TemplateTemplateParmDecl>(Old)) { const Expr *NewC = nullptr, *OldC = nullptr; - if (const auto *TC = cast<TemplateTypeParmDecl>(New)->getTypeConstraint()) - NewC = TC->getImmediatelyDeclaredConstraint(); - if (const auto *TC = cast<TemplateTypeParmDecl>(Old)->getTypeConstraint()) - OldC = TC->getImmediatelyDeclaredConstraint(); + + if (isa<TemplateTypeParmDecl>(New)) { + if (const auto *TC = cast<TemplateTypeParmDecl>(New)->getTypeConstraint()) + NewC = TC->getImmediatelyDeclaredConstraint(); + if (const auto *TC = cast<TemplateTypeParmDecl>(Old)->getTypeConstraint()) + OldC = TC->getImmediatelyDeclaredConstraint(); + } else if (isa<NonTypeTemplateParmDecl>(New)) { + if (const Expr *E = cast<NonTypeTemplateParmDecl>(New) + ->getPlaceholderTypeConstraint()) + NewC = E; + if (const Expr *E = cast<NonTypeTemplateParmDecl>(Old) + ->getPlaceholderTypeConstraint()) + OldC = E; + } else + llvm_unreachable("unexpected template parameter type"); auto Diagnose = [&] { S.Diag(NewC ? NewC->getBeginLoc() : New->getBeginLoc(), @@ -7820,10 +8073,8 @@ static bool MatchTemplateParameterKind(Sema &S, NamedDecl *New, NamedDecl *Old, } if (NewC) { - llvm::FoldingSetNodeID OldCID, NewCID; - OldC->Profile(OldCID, S.Context, /*Canonical=*/true); - NewC->Profile(NewCID, S.Context, /*Canonical=*/true); - if (OldCID != NewCID) { + if (!S.AreConstraintExpressionsEqual(OldInstFrom, OldC, NewInstFrom, + NewC)) { if (Complain) Diagnose(); return false; @@ -7879,12 +8130,11 @@ void DiagnoseTemplateParameterListArityMismatch(Sema &S, /// /// \returns True if the template parameter lists are equal, false /// otherwise. -bool -Sema::TemplateParameterListsAreEqual(TemplateParameterList *New, - TemplateParameterList *Old, - bool Complain, - TemplateParameterListEqualKind Kind, - SourceLocation TemplateArgLoc) { +bool Sema::TemplateParameterListsAreEqual( + const NamedDecl *NewInstFrom, TemplateParameterList *New, + const NamedDecl *OldInstFrom, TemplateParameterList *Old, bool Complain, + TemplateParameterListEqualKind Kind, SourceLocation TemplateArgLoc, + bool PartialOrdering) { if (Old->size() != New->size() && Kind != TPL_TemplateTemplateArgumentMatch) { if (Complain) DiagnoseTemplateParameterListArityMismatch(*this, New, Old, Kind, @@ -7914,8 +8164,9 @@ Sema::TemplateParameterListsAreEqual(TemplateParameterList *New, return false; } - if (!MatchTemplateParameterKind(*this, *NewParm, *OldParm, Complain, - Kind, TemplateArgLoc)) + if (!MatchTemplateParameterKind(*this, *NewParm, NewInstFrom, *OldParm, + OldInstFrom, Complain, Kind, + TemplateArgLoc, PartialOrdering)) return false; ++NewParm; @@ -7930,8 +8181,9 @@ Sema::TemplateParameterListsAreEqual(TemplateParameterList *New, // template parameter pack in P (ignoring whether those template // parameters are template parameter packs). for (; NewParm != NewParmEnd; ++NewParm) { - if (!MatchTemplateParameterKind(*this, *NewParm, *OldParm, Complain, - Kind, TemplateArgLoc)) + if (!MatchTemplateParameterKind(*this, *NewParm, NewInstFrom, *OldParm, + OldInstFrom, Complain, Kind, + TemplateArgLoc, PartialOrdering)) return false; } } @@ -7945,7 +8197,7 @@ Sema::TemplateParameterListsAreEqual(TemplateParameterList *New, return false; } - if (Kind != TPL_TemplateTemplateArgumentMatch) { + if (!PartialOrdering && Kind != TPL_TemplateTemplateArgumentMatch) { const Expr *NewRC = New->getRequiresClause(); const Expr *OldRC = Old->getRequiresClause(); @@ -7963,10 +8215,8 @@ Sema::TemplateParameterListsAreEqual(TemplateParameterList *New, } if (NewRC) { - llvm::FoldingSetNodeID OldRCID, NewRCID; - OldRC->Profile(OldRCID, Context, /*Canonical=*/true); - NewRC->Profile(NewRCID, Context, /*Canonical=*/true); - if (OldRCID != NewRCID) { + if (!AreConstraintExpressionsEqual(OldInstFrom, OldRC, NewInstFrom, + NewRC)) { if (Complain) Diagnose(); return false; @@ -8413,9 +8663,9 @@ DeclResult Sema::ActOnClassTemplateSpecialization( // Check that the template argument list is well-formed for this // template. - SmallVector<TemplateArgument, 4> Converted; - if (CheckTemplateArgumentList(ClassTemplate, TemplateNameLoc, - TemplateArgs, false, Converted, + SmallVector<TemplateArgument, 4> SugaredConverted, CanonicalConverted; + if (CheckTemplateArgumentList(ClassTemplate, TemplateNameLoc, TemplateArgs, + false, SugaredConverted, CanonicalConverted, /*UpdateArgsWithConversions=*/true)) return true; @@ -8423,14 +8673,15 @@ DeclResult Sema::ActOnClassTemplateSpecialization( // 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; @@ -8441,11 +8692,10 @@ DeclResult Sema::ActOnClassTemplateSpecialization( 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; @@ -8464,7 +8714,7 @@ DeclResult Sema::ActOnClassTemplateSpecialization( // arguments of the class template partial specialization. TemplateName CanonTemplate = Context.getCanonicalTemplateName(Name); CanonType = Context.getTemplateSpecializationType(CanonTemplate, - Converted); + CanonicalConverted); if (Context.hasSameType(CanonType, ClassTemplate->getInjectedClassNameSpecialization()) && @@ -8494,16 +8744,11 @@ DeclResult Sema::ActOnClassTemplateSpecialization( // Create a new class template partial specialization declaration node. ClassTemplatePartialSpecializationDecl *PrevPartial = cast_or_null<ClassTemplatePartialSpecializationDecl>(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( @@ -8523,13 +8768,9 @@ DeclResult Sema::ActOnClassTemplateSpecialization( } 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, @@ -8541,8 +8782,8 @@ DeclResult Sema::ActOnClassTemplateSpecialization( if (CurContext->isDependentContext()) { TemplateName CanonTemplate = Context.getCanonicalTemplateName(Name); - CanonType = Context.getTemplateSpecializationType( - CanonTemplate, Converted); + CanonType = Context.getTemplateSpecializationType(CanonTemplate, + CanonicalConverted); } else { CanonType = Context.getTypeDeclType(Specialization); } @@ -8686,17 +8927,33 @@ Decl *Sema::ActOnConceptDefinition(Scope *S, return nullptr; } - if (TemplateParameterLists.front()->size() == 0) { + TemplateParameterList *Params = TemplateParameterLists.front(); + + if (Params->size() == 0) { Diag(NameLoc, diag::err_concept_no_parameters); return nullptr; } + // Ensure that the parameter pack, if present, is the last parameter in the + // template. + for (TemplateParameterList::const_iterator ParamIt = Params->begin(), + ParamEnd = Params->end(); + ParamIt != ParamEnd; ++ParamIt) { + Decl const *Param = *ParamIt; + if (Param->isParameterPack()) { + if (++ParamIt == ParamEnd) + break; + Diag(Param->getLocation(), + diag::err_template_param_pack_must_be_last_template_parameter); + return nullptr; + } + } + if (DiagnoseUnexpandedParameterPack(ConstraintExpr)) return nullptr; - ConceptDecl *NewDecl = ConceptDecl::Create(Context, DC, NameLoc, Name, - TemplateParameterLists.front(), - ConstraintExpr); + ConceptDecl *NewDecl = + ConceptDecl::Create(Context, DC, NameLoc, Name, Params, ConstraintExpr); if (NewDecl->hasAssociatedConstraints()) { // C++2a [temp.concept]p4: @@ -8728,7 +8985,7 @@ void Sema::CheckConceptRedefinition(ConceptDecl *NewDecl, if (Previous.empty()) return; - auto *OldConcept = dyn_cast<ConceptDecl>(Previous.getRepresentativeDecl()); + auto *OldConcept = dyn_cast<ConceptDecl>(Previous.getRepresentativeDecl()->getUnderlyingDecl()); if (!OldConcept) { auto *Old = Previous.getRepresentativeDecl(); Diag(NewDecl->getLocation(), diag::err_redefinition_different_kind) @@ -8746,7 +9003,8 @@ void Sema::CheckConceptRedefinition(ConceptDecl *NewDecl, AddToScope = false; return; } - if (hasReachableDefinition(OldConcept)) { + if (hasReachableDefinition(OldConcept) && + IsRedefinitionInModule(NewDecl, OldConcept)) { Diag(NewDecl->getLocation(), diag::err_redefinition) << NewDecl->getDeclName(); notePreviousDefinition(OldConcept, NewDecl->getLocation()); @@ -8758,14 +9016,18 @@ void Sema::CheckConceptRedefinition(ConceptDecl *NewDecl, // Other decls (e.g. namespaces) also have this shortcoming. return; } - Context.setPrimaryMergedDecl(NewDecl, OldConcept); + // We unwrap canonical decl late to check for module visibility. + Context.setPrimaryMergedDecl(NewDecl, OldConcept->getCanonicalDecl()); } /// \brief Strips various properties off an implicit instantiation /// that has just been explicitly specialized. -static void StripImplicitInstantiation(NamedDecl *D) { - D->dropAttr<DLLImportAttr>(); - D->dropAttr<DLLExportAttr>(); +static void StripImplicitInstantiation(NamedDecl *D, bool MinGW) { + if (MinGW || (isa<FunctionDecl>(D) && + cast<FunctionDecl>(D)->isFunctionTemplateSpecialization())) { + D->dropAttr<DLLImportAttr>(); + D->dropAttr<DLLExportAttr>(); + } if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) FD->setInlineSpecified(false); @@ -8840,11 +9102,13 @@ Sema::CheckSpecializationInstantiationRedecl(SourceLocation NewLoc, if (PrevPointOfInstantiation.isInvalid()) { // The declaration itself has not actually been instantiated, so it is // still okay to specialize it. - StripImplicitInstantiation(PrevDecl); + StripImplicitInstantiation( + PrevDecl, + Context.getTargetInfo().getTriple().isWindowsGNUEnvironment()); return false; } // Fall through - LLVM_FALLTHROUGH; + [[fallthrough]]; case TSK_ExplicitInstantiationDeclaration: case TSK_ExplicitInstantiationDefinition: @@ -9701,17 +9965,17 @@ DeclResult Sema::ActOnExplicitInstantiation( // Check that the template argument list is well-formed for this // template. - SmallVector<TemplateArgument, 4> Converted; - if (CheckTemplateArgumentList(ClassTemplate, TemplateNameLoc, - TemplateArgs, false, Converted, + SmallVector<TemplateArgument, 4> 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; @@ -9768,13 +10032,9 @@ DeclResult Sema::ActOnExplicitInstantiation( 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) { @@ -9921,13 +10181,14 @@ Sema::ActOnExplicitInstantiation(Scope *S, SourceLocation ExternLoc, bool Owned = false; bool IsDependent = false; - Decl *TagD = ActOnTag(S, TagSpec, Sema::TUK_Reference, - KWLoc, SS, Name, NameLoc, Attr, AS_none, - /*ModulePrivateLoc=*/SourceLocation(), - MultiTemplateParamsArg(), Owned, IsDependent, - SourceLocation(), false, TypeResult(), - /*IsTypeSpecifier*/false, - /*IsTemplateParamOrArg*/false); + UsingShadowDecl* FoundUsing = nullptr; + Decl *TagD = + ActOnTag(S, TagSpec, Sema::TUK_Reference, KWLoc, SS, Name, NameLoc, Attr, + AS_none, /*ModulePrivateLoc=*/SourceLocation(), + MultiTemplateParamsArg(), Owned, IsDependent, SourceLocation(), + false, TypeResult(), /*IsTypeSpecifier*/ false, + /*IsTemplateParamOrArg*/ false, /*OOK=*/OOK_Outside, FoundUsing) + .get(); assert(!IsDependent && "explicit instantiation of dependent name not yet handled"); if (!TagD) @@ -10469,10 +10730,11 @@ Sema::ActOnDependentTag(Scope *S, unsigned TagSpec, TagUseKind TUK, return CreateParsedType(Result, TLB.getTypeSourceInfo(Context, Result)); } -TypeResult -Sema::ActOnTypenameType(Scope *S, SourceLocation TypenameLoc, - const CXXScopeSpec &SS, const IdentifierInfo &II, - SourceLocation IdLoc) { +TypeResult Sema::ActOnTypenameType(Scope *S, SourceLocation TypenameLoc, + const CXXScopeSpec &SS, + const IdentifierInfo &II, + SourceLocation IdLoc, + ImplicitTypenameContext IsImplicitTypename) { if (SS.isInvalid()) return true; @@ -10485,9 +10747,13 @@ Sema::ActOnTypenameType(Scope *S, SourceLocation TypenameLoc, NestedNameSpecifierLoc QualifierLoc = SS.getWithLocInContext(Context); TypeSourceInfo *TSI = nullptr; - QualType T = CheckTypenameType(TypenameLoc.isValid()? ETK_Typename : ETK_None, - TypenameLoc, QualifierLoc, II, IdLoc, &TSI, - /*DeducedTSTContext=*/true); + QualType T = + CheckTypenameType((TypenameLoc.isValid() || + IsImplicitTypename == ImplicitTypenameContext::Yes) + ? ETK_Typename + : ETK_None, + TypenameLoc, QualifierLoc, II, IdLoc, &TSI, + /*DeducedTSTContext=*/true); if (T.isNull()) return true; return CreateParsedType(T, TSI); @@ -10533,10 +10799,9 @@ Sema::ActOnTypenameType(Scope *S, // Construct a dependent template specialization type. assert(DTN && "dependent template has non-dependent name?"); assert(DTN->getQualifier() == SS.getScopeRep()); - QualType T = Context.getDependentTemplateSpecializationType(ETK_Typename, - DTN->getQualifier(), - DTN->getIdentifier(), - TemplateArgs); + QualType T = Context.getDependentTemplateSpecializationType( + ETK_Typename, DTN->getQualifier(), DTN->getIdentifier(), + TemplateArgs.arguments()); // Create source-location information for this type. TypeLocBuilder Builder; @@ -10745,7 +11010,7 @@ Sema::CheckTypenameType(ElaboratedTypeKeyword Keyword, } // Fall through to create a dependent typename type, from which we can recover // better. - LLVM_FALLTHROUGH; + [[fallthrough]]; case LookupResult::NotFoundInCurrentInstantiation: // Okay, it's a member of an unknown instantiation. |