diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -6993,7 +6993,8 @@ bool addInstantiatedParametersToScope( FunctionDecl *Function, const FunctionDecl *PatternDecl, LocalInstantiationScope &Scope, - const MultiLevelTemplateArgumentList &TemplateArgs); + const MultiLevelTemplateArgumentList &TemplateArgs, + bool EarlySubstitution); public: const NormalizedConstraint * @@ -7552,10 +7553,14 @@ SourceLocation(), PDiag()); } - void HandleDependentAccessCheck(const DependentDiagnostic &DD, - const MultiLevelTemplateArgumentList &TemplateArgs); - void PerformDependentDiagnostics(const DeclContext *Pattern, - const MultiLevelTemplateArgumentList &TemplateArgs); + void + HandleDependentAccessCheck(const DependentDiagnostic &DD, + const MultiLevelTemplateArgumentList &TemplateArgs, + bool EarlySibstitution); + void PerformDependentDiagnostics( + const DeclContext *Pattern, + const MultiLevelTemplateArgumentList &TemplateArgs, + bool EarlySubstitution); void HandleDelayedAccessCheck(sema::DelayedDiagnostic &DD, Decl *Ctx); @@ -9505,42 +9510,46 @@ TypeSourceInfo *SubstType(TypeSourceInfo *T, const MultiLevelTemplateArgumentList &TemplateArgs, - SourceLocation Loc, DeclarationName Entity, - bool AllowDeducedTST = false); + bool EarlySubstitution, SourceLocation Loc, + DeclarationName Entity, bool AllowDeducedTST); QualType SubstType(QualType T, const MultiLevelTemplateArgumentList &TemplateArgs, - SourceLocation Loc, DeclarationName Entity); + bool EarlySubstitution, SourceLocation Loc, + DeclarationName Entity); TypeSourceInfo *SubstType(TypeLoc TL, const MultiLevelTemplateArgumentList &TemplateArgs, - SourceLocation Loc, DeclarationName Entity); + bool EarlySubstitution, SourceLocation Loc, + DeclarationName Entity); - TypeSourceInfo *SubstFunctionDeclType(TypeSourceInfo *T, - const MultiLevelTemplateArgumentList &TemplateArgs, - SourceLocation Loc, - DeclarationName Entity, - CXXRecordDecl *ThisContext, - Qualifiers ThisTypeQuals); + TypeSourceInfo *SubstFunctionDeclType( + TypeSourceInfo *T, const MultiLevelTemplateArgumentList &TemplateArgs, + bool EarlySubstitution, SourceLocation Loc, DeclarationName Entity, + CXXRecordDecl *ThisContext, Qualifiers ThisTypeQuals); void SubstExceptionSpec(FunctionDecl *New, const FunctionProtoType *Proto, - const MultiLevelTemplateArgumentList &Args); + const MultiLevelTemplateArgumentList &Args, + bool EarlySubstitution); bool SubstExceptionSpec(SourceLocation Loc, FunctionProtoType::ExceptionSpecInfo &ESI, SmallVectorImpl &ExceptionStorage, - const MultiLevelTemplateArgumentList &Args); - ParmVarDecl *SubstParmVarDecl(ParmVarDecl *D, - const MultiLevelTemplateArgumentList &TemplateArgs, - int indexAdjustment, - Optional NumExpansions, - bool ExpectParameterPack); + const MultiLevelTemplateArgumentList &Args, + bool EarlySubstitution); + ParmVarDecl * + SubstParmVarDecl(ParmVarDecl *D, + const MultiLevelTemplateArgumentList &TemplateArgs, + bool EarlySubstitution, int indexAdjustment, + Optional NumExpansions, bool ExpectParameterPack); bool SubstParmTypes(SourceLocation Loc, ArrayRef Params, const FunctionProtoType::ExtParameterInfo *ExtParamInfos, const MultiLevelTemplateArgumentList &TemplateArgs, + bool EarlySubstitution, SmallVectorImpl &ParamTypes, SmallVectorImpl *OutParams, ExtParameterInfoBuilder &ParamInfos); ExprResult SubstExpr(Expr *E, - const MultiLevelTemplateArgumentList &TemplateArgs); + const MultiLevelTemplateArgumentList &TemplateArgs, + bool EarlySubstitution); /// Substitute the given template arguments into a list of /// expressions, expanding pack expansions if required. @@ -9557,53 +9566,55 @@ /// \returns true if an error occurred, false otherwise. bool SubstExprs(ArrayRef Exprs, bool IsCall, const MultiLevelTemplateArgumentList &TemplateArgs, - SmallVectorImpl &Outputs); + bool EarlySubstitution, SmallVectorImpl &Outputs); StmtResult SubstStmt(Stmt *S, - const MultiLevelTemplateArgumentList &TemplateArgs); + const MultiLevelTemplateArgumentList &TemplateArgs, + bool EarlySubstitution); TemplateParameterList * SubstTemplateParams(TemplateParameterList *Params, DeclContext *Owner, - const MultiLevelTemplateArgumentList &TemplateArgs); + const MultiLevelTemplateArgumentList &TemplateArgs, + bool EarlySubstitution); bool SubstTemplateArguments(ArrayRef Args, const MultiLevelTemplateArgumentList &TemplateArgs, + bool EarlySubstitution, TemplateArgumentListInfo &Outputs); - Decl *SubstDecl(Decl *D, DeclContext *Owner, - const MultiLevelTemplateArgumentList &TemplateArgs); + const MultiLevelTemplateArgumentList &TemplateArgs, + bool EarlySubstitution); /// Substitute the name and return type of a defaulted 'operator<=>' to form /// an implicit 'operator=='. FunctionDecl *SubstSpaceshipAsEqualEqual(CXXRecordDecl *RD, FunctionDecl *Spaceship); - ExprResult SubstInitializer(Expr *E, - const MultiLevelTemplateArgumentList &TemplateArgs, - bool CXXDirectInit); + ExprResult + SubstInitializer(Expr *E, const MultiLevelTemplateArgumentList &TemplateArgs, + bool EarlySubstitution, bool CXXDirectInit); - bool - SubstBaseSpecifiers(CXXRecordDecl *Instantiation, - CXXRecordDecl *Pattern, - const MultiLevelTemplateArgumentList &TemplateArgs); + bool SubstBaseSpecifiers(CXXRecordDecl *Instantiation, CXXRecordDecl *Pattern, + const MultiLevelTemplateArgumentList &TemplateArgs, + bool EarlySubstitution); - bool - InstantiateClass(SourceLocation PointOfInstantiation, - CXXRecordDecl *Instantiation, CXXRecordDecl *Pattern, - const MultiLevelTemplateArgumentList &TemplateArgs, - TemplateSpecializationKind TSK, - bool Complain = true); + bool InstantiateClass(SourceLocation PointOfInstantiation, + CXXRecordDecl *Instantiation, CXXRecordDecl *Pattern, + const MultiLevelTemplateArgumentList &TemplateArgs, + bool EarlySubstitution, TemplateSpecializationKind TSK, + bool Complain); bool InstantiateEnum(SourceLocation PointOfInstantiation, EnumDecl *Instantiation, EnumDecl *Pattern, const MultiLevelTemplateArgumentList &TemplateArgs, - TemplateSpecializationKind TSK); + bool EarlySubstitution, TemplateSpecializationKind TSK); bool InstantiateInClassInitializer( SourceLocation PointOfInstantiation, FieldDecl *Instantiation, - FieldDecl *Pattern, const MultiLevelTemplateArgumentList &TemplateArgs); + FieldDecl *Pattern, const MultiLevelTemplateArgumentList &TemplateArgs, + bool EarlySubstitution); struct LateInstantiatedAttribute { const Attr *TmplAttr; @@ -9618,15 +9629,15 @@ typedef SmallVector LateInstantiatedAttrVec; void InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs, - const Decl *Pattern, Decl *Inst, - LateInstantiatedAttrVec *LateAttrs = nullptr, - LocalInstantiationScope *OuterMostScope = nullptr); + bool EarlySubstitution, const Decl *Pattern, Decl *Inst, + LateInstantiatedAttrVec *LateAttrs, + LocalInstantiationScope *OuterMostScope); void InstantiateAttrsForDecl(const MultiLevelTemplateArgumentList &TemplateArgs, - const Decl *Pattern, Decl *Inst, - LateInstantiatedAttrVec *LateAttrs = nullptr, - LocalInstantiationScope *OuterMostScope = nullptr); + bool EarlySubstitution, const Decl *Pattern, + Decl *Inst, LateInstantiatedAttrVec *LateAttrs, + LocalInstantiationScope *OuterMostScope); void InstantiateDefaultCtorDefaultArgs(CXXConstructorDecl *Ctor); @@ -9639,30 +9650,34 @@ TemplateSpecializationKind TSK, bool Complain = true); - void InstantiateClassMembers(SourceLocation PointOfInstantiation, - CXXRecordDecl *Instantiation, - const MultiLevelTemplateArgumentList &TemplateArgs, - TemplateSpecializationKind TSK); + void InstantiateClassMembers( + SourceLocation PointOfInstantiation, CXXRecordDecl *Instantiation, + const MultiLevelTemplateArgumentList &TemplateArgs, + bool EarlySubstitution, TemplateSpecializationKind TSK); void InstantiateClassTemplateSpecializationMembers( SourceLocation PointOfInstantiation, ClassTemplateSpecializationDecl *ClassTemplateSpec, TemplateSpecializationKind TSK); - NestedNameSpecifierLoc - SubstNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS, - const MultiLevelTemplateArgumentList &TemplateArgs); + NestedNameSpecifierLoc SubstNestedNameSpecifierLoc( + NestedNameSpecifierLoc NNS, + const MultiLevelTemplateArgumentList &TemplateArgs, + bool EarlySubstitution); DeclarationNameInfo SubstDeclarationNameInfo(const DeclarationNameInfo &NameInfo, - const MultiLevelTemplateArgumentList &TemplateArgs); + const MultiLevelTemplateArgumentList &TemplateArgs, + bool EarlySubstitution); TemplateName SubstTemplateName(NestedNameSpecifierLoc QualifierLoc, TemplateName Name, SourceLocation Loc, - const MultiLevelTemplateArgumentList &TemplateArgs); + const MultiLevelTemplateArgumentList &TemplateArgs, + bool EarlySubstitution); bool SubstTypeConstraint(TemplateTypeParmDecl *Inst, const TypeConstraint *TC, - const MultiLevelTemplateArgumentList &TemplateArgs); + const MultiLevelTemplateArgumentList &TemplateArgs, + bool EarlySubstitution); bool InstantiateDefaultArgument(SourceLocation CallLoc, FunctionDecl *FD, ParmVarDecl *Param); @@ -9674,6 +9689,7 @@ ConstraintSatisfaction &Satisfaction); FunctionDecl *InstantiateFunctionDeclaration(FunctionTemplateDecl *FTD, const TemplateArgumentList *Args, + bool EarlySubstitution, SourceLocation Loc); void InstantiateFunctionDefinition(SourceLocation PointOfInstantiation, FunctionDecl *Function, @@ -9690,33 +9706,38 @@ LocalInstantiationScope *StartingScope = nullptr); VarTemplateSpecializationDecl *CompleteVarTemplateSpecializationDecl( VarTemplateSpecializationDecl *VarSpec, VarDecl *PatternDecl, - const MultiLevelTemplateArgumentList &TemplateArgs); - void - BuildVariableInstantiation(VarDecl *NewVar, VarDecl *OldVar, - const MultiLevelTemplateArgumentList &TemplateArgs, - LateInstantiatedAttrVec *LateAttrs, - DeclContext *Owner, - LocalInstantiationScope *StartingScope, - bool InstantiatingVarTemplate = false, - VarTemplateSpecializationDecl *PrevVTSD = nullptr); + const MultiLevelTemplateArgumentList &TemplateArgs, + bool EarlySubstitution); + void BuildVariableInstantiation( + VarDecl *NewVar, VarDecl *OldVar, + const MultiLevelTemplateArgumentList &TemplateArgs, + bool EarlySubstitution, LateInstantiatedAttrVec *LateAttrs, + DeclContext *Owner, LocalInstantiationScope *StartingScope, + bool InstantiatingVarTemplate, VarTemplateSpecializationDecl *PrevVTSD); void InstantiateVariableInitializer( VarDecl *Var, VarDecl *OldVar, - const MultiLevelTemplateArgumentList &TemplateArgs); + const MultiLevelTemplateArgumentList &TemplateArgs, + bool EarlySubstitution); void InstantiateVariableDefinition(SourceLocation PointOfInstantiation, VarDecl *Var, bool Recursive = false, bool DefinitionRequired = false, bool AtEndOfTU = false); - void InstantiateMemInitializers(CXXConstructorDecl *New, - const CXXConstructorDecl *Tmpl, - const MultiLevelTemplateArgumentList &TemplateArgs); + void + InstantiateMemInitializers(CXXConstructorDecl *New, + const CXXConstructorDecl *Tmpl, + const MultiLevelTemplateArgumentList &TemplateArgs, + bool EarlySubstitution); - NamedDecl *FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D, + NamedDecl * + FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D, + const MultiLevelTemplateArgumentList &TemplateArgs, + bool EarlySubstitution, bool FindingInstantiatedContext); + DeclContext * + FindInstantiatedContext(SourceLocation Loc, DeclContext *DC, const MultiLevelTemplateArgumentList &TemplateArgs, - bool FindingInstantiatedContext = false); - DeclContext *FindInstantiatedContext(SourceLocation Loc, DeclContext *DC, - const MultiLevelTemplateArgumentList &TemplateArgs); + bool EarlySubstitution); // Objective-C declarations. enum ObjCContainerKind { diff --git a/clang/include/clang/Sema/Template.h b/clang/include/clang/Sema/Template.h --- a/clang/include/clang/Sema/Template.h +++ b/clang/include/clang/Sema/Template.h @@ -485,12 +485,16 @@ std::pair, 4> OutOfLineVarPartialSpecs; + bool EarlySubstitution; + public: TemplateDeclInstantiator(Sema &SemaRef, DeclContext *Owner, - const MultiLevelTemplateArgumentList &TemplateArgs) + const MultiLevelTemplateArgumentList &TemplateArgs, + bool EarlySubstitution) : SemaRef(SemaRef), SubstIndex(SemaRef, SemaRef.ArgumentPackSubstitutionIndex), - Owner(Owner), TemplateArgs(TemplateArgs) {} + Owner(Owner), TemplateArgs(TemplateArgs), + EarlySubstitution(EarlySubstitution) {} // Define all the decl visitors using DeclNodes.inc #define DECL(DERIVED, BASE) \ @@ -622,6 +626,26 @@ template Decl *instantiateUnresolvedUsingDecl(T *D, bool InstantiatingPackElement = false); + + unsigned getNewDepth(unsigned Depth) const { + return Depth - + (EarlySubstitution ? 0 : TemplateArgs.getNumSubstitutedLevels()); + } + + class EarlySubstitutionRAII { + bool *EarlySubstitution, OldEarlySubstitution; + friend class TemplateDeclInstantiator; + + EarlySubstitutionRAII(bool &EarlySubstitution) + : EarlySubstitution(&EarlySubstitution), + OldEarlySubstitution(std::exchange(EarlySubstitution, true)) {} + + public: + ~EarlySubstitutionRAII() { *EarlySubstitution = OldEarlySubstitution; } + }; + EarlySubstitutionRAII getEarlySubstitutionRAII() { + return EarlySubstitution; + } }; } // namespace clang diff --git a/clang/lib/Sema/SemaAccess.cpp b/clang/lib/Sema/SemaAccess.cpp --- a/clang/lib/Sema/SemaAccess.cpp +++ b/clang/lib/Sema/SemaAccess.cpp @@ -1503,16 +1503,20 @@ DD.Triggered = true; } -void Sema::HandleDependentAccessCheck(const DependentDiagnostic &DD, - const MultiLevelTemplateArgumentList &TemplateArgs) { +void Sema::HandleDependentAccessCheck( + const DependentDiagnostic &DD, + const MultiLevelTemplateArgumentList &TemplateArgs, + bool EarlySubstitution) { SourceLocation Loc = DD.getAccessLoc(); AccessSpecifier Access = DD.getAccess(); Decl *NamingD = FindInstantiatedDecl(Loc, DD.getAccessNamingClass(), - TemplateArgs); + TemplateArgs, EarlySubstitution, + /*FindingInstantiatedContext=*/false); if (!NamingD) return; - Decl *TargetD = FindInstantiatedDecl(Loc, DD.getAccessTarget(), - TemplateArgs); + Decl *TargetD = FindInstantiatedDecl(Loc, DD.getAccessTarget(), TemplateArgs, + EarlySubstitution, + /*FindingInstantiatedContext=*/false); if (!TargetD) return; if (DD.isAccessToMember()) { @@ -1520,8 +1524,8 @@ NamedDecl *TargetDecl = cast(TargetD); QualType BaseObjectType = DD.getAccessBaseObjectType(); if (!BaseObjectType.isNull()) { - BaseObjectType = SubstType(BaseObjectType, TemplateArgs, Loc, - DeclarationName()); + BaseObjectType = SubstType(BaseObjectType, TemplateArgs, + EarlySubstitution, Loc, DeclarationName()); if (BaseObjectType.isNull()) return; } diff --git a/clang/lib/Sema/SemaCXXScopeSpec.cpp b/clang/lib/Sema/SemaCXXScopeSpec.cpp --- a/clang/lib/Sema/SemaCXXScopeSpec.cpp +++ b/clang/lib/Sema/SemaCXXScopeSpec.cpp @@ -260,9 +260,9 @@ if (EnumDecl *Pattern = EnumD->getInstantiatedFromMemberEnum()) { MemberSpecializationInfo *MSI = EnumD->getMemberSpecializationInfo(); if (MSI->getTemplateSpecializationKind() != TSK_ExplicitSpecialization) { - if (InstantiateEnum(L, EnumD, Pattern, - getTemplateInstantiationArgs(EnumD), - TSK_ImplicitInstantiation)) { + if (InstantiateEnum( + L, EnumD, Pattern, getTemplateInstantiationArgs(EnumD), + /*EarlySubstitution=*/false, TSK_ImplicitInstantiation)) { if (SS) SS->SetInvalid(SS->getRange()); return true; diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp --- a/clang/lib/Sema/SemaConcept.cpp +++ b/clang/lib/Sema/SemaConcept.cpp @@ -219,8 +219,9 @@ return ExprError(); // We do not want error diagnostics escaping here. Sema::SFINAETrap Trap(S); - SubstitutedExpression = S.SubstExpr(const_cast(AtomicExpr), - MLTAL); + SubstitutedExpression = + S.SubstExpr(const_cast(AtomicExpr), MLTAL, + /*EarlySubstitution=*/false); // Substitution might have stripped off a contextual conversion to // bool if this is the operand of an '&&' or '||'. For example, we // might lose an lvalue-to-rvalue conversion here. If so, put it back @@ -435,7 +436,8 @@ MultiLevelTemplateArgumentList MLTAL( *Decl->getTemplateSpecializationArgs()); if (addInstantiatedParametersToScope( - Decl, Decl->getPrimaryTemplate()->getTemplatedDecl(), Scope, MLTAL)) + Decl, Decl->getPrimaryTemplate()->getTemplatedDecl(), Scope, MLTAL, + /*EarlySubstitution=*/false)) return true; } Qualifiers ThisQuals; @@ -765,7 +767,8 @@ Sema::InstantiatingTemplate::ParameterMappingSubstitution{}, Concept, SourceRange(ArgsAsWritten->arguments()[0].getSourceRange().getBegin(), ArgsAsWritten->arguments().back().getSourceRange().getEnd())); - if (S.SubstTemplateArguments(*Atomic.ParameterMapping, MLTAL, SubstArgs)) + if (S.SubstTemplateArguments(*Atomic.ParameterMapping, MLTAL, + /*EarlySubstitution=*/false, SubstArgs)) return true; Atomic.ParameterMapping.emplace( MutableArrayRef( diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -15307,12 +15307,14 @@ if (auto *TemplateArgs = Conv->getTemplateSpecializationArgs()) { CallOp = InstantiateFunctionDeclaration( - CallOp->getDescribedFunctionTemplate(), TemplateArgs, CurrentLocation); + CallOp->getDescribedFunctionTemplate(), TemplateArgs, + /*EarlySubstitution=*/false, CurrentLocation); if (!CallOp) return; Invoker = InstantiateFunctionDeclaration( - Invoker->getDescribedFunctionTemplate(), TemplateArgs, CurrentLocation); + Invoker->getDescribedFunctionTemplate(), TemplateArgs, + /*EarlySubstitution=*/false, CurrentLocation); if (!Invoker) return; } @@ -15560,7 +15562,8 @@ if (!Pattern->hasInClassInitializer() || InstantiateInClassInitializer(Loc, Field, Pattern, - getTemplateInstantiationArgs(Field))) { + getTemplateInstantiationArgs(Field), + /*EarlySubstitution=*/false)) { // Don't diagnose this again. Field->setInvalidDecl(); return ExprError(); diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -8970,7 +8970,7 @@ Expr *IDC = cast(TPL->getParam(0))->getTypeConstraint() ->getImmediatelyDeclaredConstraint(); - ExprResult Constraint = SubstExpr(IDC, MLTAL); + ExprResult Constraint = SubstExpr(IDC, MLTAL, /*EarlySubstitution=*/false); assert(!Constraint.isInvalid() && "Substitution cannot fail as it is simply putting a type template " "argument into a concept specialization expression's parameter."); diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -2181,7 +2181,8 @@ Args.setKind(TemplateSubstitutionKind::Rewrite); Args.addOuterTemplateArguments(SubstArgs); Args.addOuterRetainedLevel(); - NamedDecl *NewParam = transformTemplateParameter(Param, Args); + NamedDecl *NewParam = transformTemplateParameter( + Param, Args, /*EarlySubstitution=*/false); if (!NewParam) return nullptr; AllParams.push_back(NewParam); @@ -2196,7 +2197,8 @@ Args.setKind(TemplateSubstitutionKind::Rewrite); Args.addOuterTemplateArguments(SubstArgs); Args.addOuterRetainedLevel(); - ExprResult E = SemaRef.SubstExpr(InnerRC, Args); + ExprResult E = + SemaRef.SubstExpr(InnerRC, Args, /*EarlySubstitution=*/false); if (E.isInvalid()) return nullptr; RequiresClause = E.getAs(); @@ -2229,6 +2231,7 @@ SmallVector Params; SmallVector MaterializedTypedefs; QualType NewType = transformFunctionProtoType(TLB, FPTL, Params, Args, + /*EarlySubstitution=*/false, MaterializedTypedefs); if (NewType.isNull()) return nullptr; @@ -2273,7 +2276,8 @@ /// parameter, rebuilding any internal references to earlier parameters and /// renumbering as we go. NamedDecl *transformTemplateParameter(NamedDecl *TemplateParam, - MultiLevelTemplateArgumentList &Args) { + MultiLevelTemplateArgumentList &Args, + bool EarlySubstitution) { if (auto *TTP = dyn_cast(TemplateParam)) { // TemplateTypeParmDecl's index cannot be changed after creation, so // substitute it directly. @@ -2285,11 +2289,12 @@ TTP->isExpandedParameterPack() ? llvm::Optional(TTP->getNumExpansionParameters()) : None); if (const auto *TC = TTP->getTypeConstraint()) - SemaRef.SubstTypeConstraint(NewTTP, TC, Args); + SemaRef.SubstTypeConstraint(NewTTP, TC, Args, EarlySubstitution); if (TTP->hasDefaultArgument()) { - TypeSourceInfo *InstantiatedDefaultArg = - SemaRef.SubstType(TTP->getDefaultArgumentInfo(), Args, - TTP->getDefaultArgumentLoc(), TTP->getDeclName()); + TypeSourceInfo *InstantiatedDefaultArg = SemaRef.SubstType( + TTP->getDefaultArgumentInfo(), Args, EarlySubstitution, + TTP->getDefaultArgumentLoc(), TTP->getDeclName(), + /*AllowDeducedTST=*/false); if (InstantiatedDefaultArg) NewTTP->setDefaultArgument(InstantiatedDefaultArg); } @@ -2299,19 +2304,20 @@ } if (auto *TTP = dyn_cast(TemplateParam)) - return transformTemplateParameterImpl(TTP, Args); + return transformTemplateParameterImpl(TTP, Args, EarlySubstitution); return transformTemplateParameterImpl( - cast(TemplateParam), Args); + cast(TemplateParam), Args, EarlySubstitution); } - template + template TemplateParmDecl * transformTemplateParameterImpl(TemplateParmDecl *OldParam, - MultiLevelTemplateArgumentList &Args) { + MultiLevelTemplateArgumentList &Args, + bool EarlySubstitution) { // Ask the template instantiator to do the heavy lifting for us, then adjust // the index of the parameter once it's done. - auto *NewParam = - cast(SemaRef.SubstDecl(OldParam, DC, Args)); + auto *NewParam = cast( + SemaRef.SubstDecl(OldParam, DC, Args, EarlySubstitution)); assert(NewParam->getDepth() == 0 && "unexpected template param depth"); NewParam->setPosition(NewParam->getPosition() + Depth1IndexAdjustment); return NewParam; @@ -2320,15 +2326,15 @@ QualType transformFunctionProtoType( TypeLocBuilder &TLB, FunctionProtoTypeLoc TL, SmallVectorImpl &Params, - MultiLevelTemplateArgumentList &Args, + MultiLevelTemplateArgumentList &Args, bool EarlySubstitution, SmallVectorImpl &MaterializedTypedefs) { SmallVector ParamTypes; const FunctionProtoType *T = TL.getTypePtr(); // -- The types of the function parameters are those of the constructor. for (auto *OldParam : TL.getParams()) { - ParmVarDecl *NewParam = - transformFunctionTypeParam(OldParam, Args, MaterializedTypedefs); + ParmVarDecl *NewParam = transformFunctionTypeParam( + OldParam, Args, EarlySubstitution, MaterializedTypedefs); if (!NewParam) return QualType(); ParamTypes.push_back(NewParam->getType()); @@ -2372,6 +2378,7 @@ ParmVarDecl *transformFunctionTypeParam( ParmVarDecl *OldParam, MultiLevelTemplateArgumentList &Args, + bool EarlySubstitution, llvm::SmallVectorImpl &MaterializedTypedefs) { TypeSourceInfo *OldDI = OldParam->getTypeSourceInfo(); TypeSourceInfo *NewDI; @@ -2379,15 +2386,17 @@ // Expand out the one and only element in each inner pack. Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(SemaRef, 0); NewDI = - SemaRef.SubstType(PackTL.getPatternLoc(), Args, + SemaRef.SubstType(PackTL.getPatternLoc(), Args, EarlySubstitution, OldParam->getLocation(), OldParam->getDeclName()); if (!NewDI) return nullptr; NewDI = SemaRef.CheckPackExpansion(NewDI, PackTL.getEllipsisLoc(), PackTL.getTypePtr()->getNumExpansions()); } else - NewDI = SemaRef.SubstType(OldDI, Args, OldParam->getLocation(), - OldParam->getDeclName()); + NewDI = + SemaRef.SubstType(OldDI, Args, EarlySubstitution, + OldParam->getLocation(), OldParam->getDeclName(), + /*AllowDeducedTST=*/false); if (!NewDI) return nullptr; @@ -3717,9 +3726,10 @@ if (Inst.isInvalid()) return QualType(); - CanonType = SubstType(Pattern->getUnderlyingType(), - TemplateArgLists, AliasTemplate->getLocation(), - AliasTemplate->getDeclName()); + CanonType = + SubstType(Pattern->getUnderlyingType(), TemplateArgLists, + /*EarlySubstitution=*/false, AliasTemplate->getLocation(), + AliasTemplate->getDeclName()); if (CanonType.isNull()) { // If this was enable_if and we failed to find the nested type // within enable_if in a SFINAE context, dig out the specific @@ -3831,8 +3841,10 @@ if (!Inst.isInvalid()) { MultiLevelTemplateArgumentList TemplateArgLists; TemplateArgLists.addOuterTemplateArguments(Converted); - InstantiateAttrsForDecl(TemplateArgLists, - ClassTemplate->getTemplatedDecl(), Decl); + InstantiateAttrsForDecl(TemplateArgLists, /*EarlySubstitution=*/false, + ClassTemplate->getTemplatedDecl(), Decl, + /*LateAttrs=*/nullptr, + /*OuterMostScope=*/nullptr); } } @@ -5110,6 +5122,7 @@ TemplateArgumentList TemplateArgs(TemplateArgumentList::OnStack, Converted); // Only substitute for the innermost template argument list. + // FIXME: Use EarlySubstitution=true MultiLevelTemplateArgumentList TemplateArgLists; TemplateArgLists.addOuterTemplateArguments(&TemplateArgs); for (unsigned i = 0, e = Param->getDepth(); i != e; ++i) @@ -5120,9 +5133,10 @@ ForLambdaCallOperator = Rec->isLambda(); Sema::ContextRAII SavedContext(SemaRef, Template->getDeclContext(), !ForLambdaCallOperator); - ArgType = - SemaRef.SubstType(ArgType, TemplateArgLists, - Param->getDefaultArgumentLoc(), Param->getDeclName()); + ArgType = SemaRef.SubstType( + ArgType, TemplateArgLists, /*EarlySubstitution=*/false, + Param->getDefaultArgumentLoc(), Param->getDeclName(), + /*AllowDeducedTST=*/false); } return ArgType; @@ -5174,7 +5188,8 @@ Sema::ContextRAII SavedContext(SemaRef, Template->getDeclContext()); EnterExpressionEvaluationContext ConstantEvaluated( SemaRef, Sema::ExpressionEvaluationContext::ConstantEvaluated); - return SemaRef.SubstExpr(Param->getDefaultArgument(), TemplateArgLists); + return SemaRef.SubstExpr(Param->getDefaultArgument(), TemplateArgLists, + /*EarlySubstitution=*/false); } /// Substitute template arguments into the default template argument for @@ -5228,17 +5243,16 @@ // Substitute into the nested-name-specifier first, QualifierLoc = Param->getDefaultArgument().getTemplateQualifierLoc(); if (QualifierLoc) { - QualifierLoc = - SemaRef.SubstNestedNameSpecifierLoc(QualifierLoc, TemplateArgLists); + QualifierLoc = SemaRef.SubstNestedNameSpecifierLoc( + QualifierLoc, TemplateArgLists, /*EarlySubstitution=*/false); if (!QualifierLoc) return TemplateName(); } return SemaRef.SubstTemplateName( - QualifierLoc, - Param->getDefaultArgument().getArgument().getAsTemplate(), - Param->getDefaultArgument().getTemplateNameLoc(), - TemplateArgLists); + QualifierLoc, Param->getDefaultArgument().getArgument().getAsTemplate(), + Param->getDefaultArgument().getTemplateNameLoc(), TemplateArgLists, + /*EarlySubstitution=*/false); } /// If the given template parameter has a default template @@ -5410,13 +5424,13 @@ ArgumentPackIndex); NTTPType = SubstType(PET->getPattern(), MultiLevelTemplateArgumentList(TemplateArgs), - NTTP->getLocation(), + /*EarlySubstitution=*/false, NTTP->getLocation(), NTTP->getDeclName()); } else { - NTTPType = SubstType(NTTPType, - MultiLevelTemplateArgumentList(TemplateArgs), - NTTP->getLocation(), - NTTP->getDeclName()); + NTTPType = + SubstType(NTTPType, MultiLevelTemplateArgumentList(TemplateArgs), + /*EarlySubstitution=*/false, NTTP->getLocation(), + NTTP->getDeclName()); } // If that worked, check the non-type template parameter type @@ -5566,7 +5580,8 @@ TemplateArgumentList TemplateArgs(TemplateArgumentList::OnStack, Converted); Params = SubstTemplateParams(Params, CurContext, - MultiLevelTemplateArgumentList(TemplateArgs)); + MultiLevelTemplateArgumentList(TemplateArgs), + /*EarlySubstitution=*/false); if (!Params) return true; } @@ -9915,7 +9930,8 @@ } else { if (InstantiateClass(NameLoc, Record, Def, getTemplateInstantiationArgs(Record), - TSK)) + /*EarlySubstitution=*/false, TSK, + /*Complain=*/true)) return true; RecordDef = cast_or_null(Record->getDefinition()); @@ -9926,7 +9942,8 @@ // Instantiate all of the members of the class. InstantiateClassMembers(NameLoc, RecordDef, - getTemplateInstantiationArgs(Record), TSK); + getTemplateInstantiationArgs(Record), + /*EarlySubstitution=*/false, TSK); if (TSK == TSK_ExplicitInstantiationDefinition) MarkVTableUsed(NameLoc, RecordDef, true); diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp --- a/clang/lib/Sema/SemaTemplateDeduction.cpp +++ b/clang/lib/Sema/SemaTemplateDeduction.cpp @@ -2629,14 +2629,17 @@ NTTP, Output, Template->getSourceRange()); if (Inst.isInvalid() || - S.SubstType(NTTP->getType(), Args, NTTP->getLocation(), - NTTP->getDeclName()).isNull()) + S.SubstType(NTTP->getType(), Args, + /*EarlySubstitution=*/false, NTTP->getLocation(), + NTTP->getDeclName()) + .isNull()) return true; } else if (auto *TTP = dyn_cast(Param)) { Sema::InstantiatingTemplate Inst(S, Template->getLocation(), Template, TTP, Output, Template->getSourceRange()); - if (Inst.isInvalid() || !S.SubstDecl(TTP, S.CurContext, Args)) + if (Inst.isInvalid() || !S.SubstDecl(TTP, S.CurContext, Args, + /*EarlySubstitution=*/false)) return true; } // For type parameters, no substitution is ever required. @@ -2846,7 +2849,8 @@ if (S.SubstTemplateArguments( PartialTemplArgInfo->arguments(), - MultiLevelTemplateArgumentList(*DeducedArgumentList), InstArgs)) { + MultiLevelTemplateArgumentList(*DeducedArgumentList), + /*EarlySubstitution=*/false, InstArgs)) { unsigned ArgIdx = InstArgs.size(), ParamIdx = ArgIdx; if (ParamIdx >= Partial->getTemplateParameters()->size()) ParamIdx = Partial->getTemplateParameters()->size() - 1; @@ -3183,7 +3187,8 @@ if (SubstParmTypes(Function->getLocation(), Function->parameters(), Proto->getExtParameterInfosOrNull(), MultiLevelTemplateArgumentList(*ExplicitArgumentList), - ParamTypes, /*params*/ nullptr, ExtParamInfos)) + /*EarlySubstitution=*/false, ParamTypes, + /*params*/ nullptr, ExtParamInfos)) return TDK_SubstitutionFailure; } @@ -3209,7 +3214,8 @@ ResultType = SubstType(Proto->getReturnType(), MultiLevelTemplateArgumentList(*ExplicitArgumentList), - Function->getTypeSpecStartLoc(), Function->getDeclName()); + /*EarlySubstitution=*/false, Function->getTypeSpecStartLoc(), + Function->getDeclName()); if (ResultType.isNull() || Trap.hasErrorOccurred()) return TDK_SubstitutionFailure; // CUDA: Kernel function must have 'void' return type. @@ -3227,7 +3233,8 @@ SubstParmTypes(Function->getLocation(), Function->parameters(), Proto->getExtParameterInfosOrNull(), MultiLevelTemplateArgumentList(*ExplicitArgumentList), - ParamTypes, /*params*/ nullptr, ExtParamInfos)) + /*EarlySubstitution=*/false, ParamTypes, + /*params*/ nullptr, ExtParamInfos)) return TDK_SubstitutionFailure; if (FunctionType) { @@ -3241,7 +3248,8 @@ if (getLangOpts().CPlusPlus17 && SubstExceptionSpec( Function->getLocation(), EPI.ExceptionSpec, ExceptionStorage, - MultiLevelTemplateArgumentList(*ExplicitArgumentList))) + MultiLevelTemplateArgumentList(*ExplicitArgumentList), + /*EarlySubstitution=*/false)) return TDK_SubstitutionFailure; *FunctionType = BuildFunctionType(ResultType, ParamTypes, @@ -3483,7 +3491,8 @@ Owner = FunctionTemplate->getLexicalDeclContext(); MultiLevelTemplateArgumentList SubstArgs(*DeducedArgumentList); Specialization = cast_or_null( - SubstDecl(FunctionTemplate->getTemplatedDecl(), Owner, SubstArgs)); + SubstDecl(FunctionTemplate->getTemplatedDecl(), Owner, SubstArgs, + /*EarlySubstitution=*/false)); if (!Specialization || Specialization->isInvalidDecl()) return TDK_SubstitutionFailure; @@ -3555,10 +3564,10 @@ ArgumentPackSubstitutionIndexRAII PackIndex( *this, getPackIndexForParam(*this, FunctionTemplate, SubstArgs, ParamIdx)); - CacheEntry = - SubstType(OriginalArg.OriginalParamType, SubstArgs, - Specialization->getTypeSpecStartLoc(), - Specialization->getDeclName()); + CacheEntry = SubstType(OriginalArg.OriginalParamType, SubstArgs, + /*EarlySubstitution=*/false, + Specialization->getTypeSpecStartLoc(), + Specialization->getDeclName()); } DeducedA = CacheEntry; } @@ -4868,7 +4877,8 @@ // For a generic lambda, instantiate the call operator if needed. if (auto *Args = FD->getTemplateSpecializationArgs()) { CallOp = InstantiateFunctionDeclaration( - CallOp->getDescribedFunctionTemplate(), Args, Loc); + CallOp->getDescribedFunctionTemplate(), Args, + /*EarlySubstitution=*/false, Loc); if (!CallOp || CallOp->isInvalidDecl()) return true; diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp --- a/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -928,16 +928,17 @@ const MultiLevelTemplateArgumentList &TemplateArgs; SourceLocation Loc; DeclarationName Entity; + bool EarlySubstitution; public: typedef TreeTransform inherited; TemplateInstantiator(Sema &SemaRef, const MultiLevelTemplateArgumentList &TemplateArgs, - SourceLocation Loc, - DeclarationName Entity) - : inherited(SemaRef), TemplateArgs(TemplateArgs), Loc(Loc), - Entity(Entity) { } + SourceLocation Loc, DeclarationName Entity, + bool EarlySubstitution) + : inherited(SemaRef), TemplateArgs(TemplateArgs), Loc(Loc), + Entity(Entity), EarlySubstitution(EarlySubstitution) {} /// Determine whether the given type \p T has already been /// transformed. @@ -1016,7 +1017,9 @@ Decl *TransformDecl(SourceLocation Loc, Decl *D); void transformAttrs(Decl *Old, Decl *New) { - SemaRef.InstantiateAttrs(TemplateArgs, Old, New); + SemaRef.InstantiateAttrs(TemplateArgs, EarlySubstitution, Old, New, + /*LateAttrs=*/nullptr, + /*OuterMostScope=*/nullptr); } void transformedLocalDecl(Decl *Old, ArrayRef NewDecls) { @@ -1051,7 +1054,8 @@ // We recreated a local declaration, but not by instantiating it. There // may be pending dependent diagnostics to produce. if (auto *DC = dyn_cast(Old)) - SemaRef.PerformDependentDiagnostics(DC, TemplateArgs); + SemaRef.PerformDependentDiagnostics(DC, TemplateArgs, + EarlySubstitution); } /// Transform the definition of the given declaration by @@ -1187,8 +1191,9 @@ if (!OrigTPL || !OrigTPL->size()) return OrigTPL; DeclContext *Owner = OrigTPL->getParam(0)->getDeclContext(); - TemplateDeclInstantiator DeclInstantiator(getSema(), - /* DeclContext *Owner */ Owner, TemplateArgs); + TemplateDeclInstantiator DeclInstantiator( + getSema(), + /* DeclContext *Owner */ Owner, TemplateArgs, EarlySubstitution); return DeclInstantiator.SubstTemplateParams(OrigTPL); } @@ -1203,6 +1208,11 @@ ExprResult transformNonTypeTemplateParmRef(NonTypeTemplateParmDecl *parm, SourceLocation loc, TemplateArgument arg); + + unsigned getNewDepth(unsigned Depth) const { + return Depth - + (EarlySubstitution ? 0 : TemplateArgs.getNumSubstitutedLevels()); + } }; } @@ -1259,11 +1269,14 @@ // template parameter. } - return SemaRef.FindInstantiatedDecl(Loc, cast(D), TemplateArgs); + return SemaRef.FindInstantiatedDecl(Loc, cast(D), TemplateArgs, + EarlySubstitution, + /*FindingInstantiatedContext=*/false); } Decl *TemplateInstantiator::TransformDefinition(SourceLocation Loc, Decl *D) { - Decl *Inst = getSema().SubstDecl(D, getSema().CurContext, TemplateArgs); + Decl *Inst = getSema().SubstDecl(D, getSema().CurContext, TemplateArgs, + EarlySubstitution); if (!Inst) return nullptr; @@ -1475,9 +1488,9 @@ // We have an argument pack, but we can't select a particular argument // out of it yet. Therefore, we'll build an expression to hold on to that // argument pack. - QualType TargetType = SemaRef.SubstType(NTTP->getType(), TemplateArgs, - E->getLocation(), - NTTP->getDeclName()); + QualType TargetType = + SemaRef.SubstType(NTTP->getType(), TemplateArgs, EarlySubstitution, + E->getLocation(), NTTP->getDeclName()); if (TargetType.isNull()) return ExprError(); @@ -1529,7 +1542,8 @@ T = parm->getType(); if (parm->isParameterPack() && isa(T)) T = cast(T)->getPattern(); - return SemaRef.SubstType(T, TemplateArgs, loc, parm->getDeclName()); + return SemaRef.SubstType(T, TemplateArgs, EarlySubstitution, loc, + parm->getDeclName()); }; bool refParam = false; @@ -1559,8 +1573,9 @@ // Find the instantiation of the template argument. This is // required for nested templates. - VD = cast_or_null( - getSema().FindInstantiatedDecl(loc, VD, TemplateArgs)); + VD = cast_or_null(getSema().FindInstantiatedDecl( + loc, VD, TemplateArgs, EarlySubstitution, + /*FindingInstantiatedContext=*/false)); if (!VD) return ExprError(); } else { @@ -1764,9 +1779,9 @@ int indexAdjustment, Optional NumExpansions, bool ExpectParameterPack) { - auto NewParm = - SemaRef.SubstParmVarDecl(OldParm, TemplateArgs, indexAdjustment, - NumExpansions, ExpectParameterPack); + auto NewParm = SemaRef.SubstParmVarDecl(OldParm, TemplateArgs, + EarlySubstitution, indexAdjustment, + NumExpansions, ExpectParameterPack); if (NewParm && SemaRef.getLangOpts().OpenCL) SemaRef.deduceOpenCLAddressSpace(NewParm); return NewParm; @@ -1854,8 +1869,8 @@ TransformDecl(TL.getNameLoc(), OldTTPDecl)); QualType Result = getSema().Context.getTemplateTypeParmType( - T->getDepth() - TemplateArgs.getNumSubstitutedLevels(), T->getIndex(), - T->isParameterPack(), NewTTPDecl); + getNewDepth(T->getDepth()), T->getIndex(), T->isParameterPack(), + NewTTPDecl); TemplateTypeParmTypeLoc NewTL = TLB.push(Result); NewTL.setNameLoc(TL.getNameLoc()); return Result; @@ -2077,9 +2092,8 @@ /// type. Otherwise, produces diagnostics and returns a NULL type. TypeSourceInfo *Sema::SubstType(TypeSourceInfo *T, const MultiLevelTemplateArgumentList &Args, - SourceLocation Loc, - DeclarationName Entity, - bool AllowDeducedTST) { + bool EarlySubstitution, SourceLocation Loc, + DeclarationName Entity, bool AllowDeducedTST) { assert(!CodeSynthesisContexts.empty() && "Cannot perform an instantiation without some context on the " "instantiation stack"); @@ -2088,14 +2102,15 @@ !T->getType()->isVariablyModifiedType()) return T; - TemplateInstantiator Instantiator(*this, Args, Loc, Entity); + TemplateInstantiator Instantiator(*this, Args, Loc, Entity, + EarlySubstitution); return AllowDeducedTST ? Instantiator.TransformTypeWithDeducedTST(T) : Instantiator.TransformType(T); } TypeSourceInfo *Sema::SubstType(TypeLoc TL, const MultiLevelTemplateArgumentList &Args, - SourceLocation Loc, + bool EarlySubstitution, SourceLocation Loc, DeclarationName Entity) { assert(!CodeSynthesisContexts.empty() && "Cannot perform an instantiation without some context on the " @@ -2113,7 +2128,8 @@ return TLB.getTypeSourceInfo(Context, TL.getType()); } - TemplateInstantiator Instantiator(*this, Args, Loc, Entity); + TemplateInstantiator Instantiator(*this, Args, Loc, Entity, + EarlySubstitution); TypeLocBuilder TLB; TLB.reserve(TL.getFullDataSize()); QualType Result = Instantiator.TransformType(TLB, TL); @@ -2126,7 +2142,8 @@ /// Deprecated form of the above. QualType Sema::SubstType(QualType T, const MultiLevelTemplateArgumentList &TemplateArgs, - SourceLocation Loc, DeclarationName Entity) { + bool EarlySubstitution, SourceLocation Loc, + DeclarationName Entity) { assert(!CodeSynthesisContexts.empty() && "Cannot perform an instantiation without some context on the " "instantiation stack"); @@ -2136,7 +2153,8 @@ if (!T->isInstantiationDependentType() && !T->isVariablyModifiedType()) return T; - TemplateInstantiator Instantiator(*this, TemplateArgs, Loc, Entity); + TemplateInstantiator Instantiator(*this, TemplateArgs, Loc, Entity, + EarlySubstitution); return Instantiator.TransformType(T); } @@ -2166,12 +2184,10 @@ /// type of a FunctionDecl. Its purpose is solely to force the /// instantiation of default-argument expressions and to avoid /// instantiating an exception-specification. -TypeSourceInfo *Sema::SubstFunctionDeclType(TypeSourceInfo *T, - const MultiLevelTemplateArgumentList &Args, - SourceLocation Loc, - DeclarationName Entity, - CXXRecordDecl *ThisContext, - Qualifiers ThisTypeQuals) { +TypeSourceInfo *Sema::SubstFunctionDeclType( + TypeSourceInfo *T, const MultiLevelTemplateArgumentList &Args, + bool EarlySubstitution, SourceLocation Loc, DeclarationName Entity, + CXXRecordDecl *ThisContext, Qualifiers ThisTypeQuals) { assert(!CodeSynthesisContexts.empty() && "Cannot perform an instantiation without some context on the " "instantiation stack"); @@ -2179,7 +2195,8 @@ if (!NeedsInstantiationAsFunctionType(T)) return T; - TemplateInstantiator Instantiator(*this, Args, Loc, Entity); + TemplateInstantiator Instantiator(*this, Args, Loc, Entity, + EarlySubstitution); TypeLocBuilder TLB; @@ -2197,8 +2214,9 @@ // instead of rebuilding the function type again later. Result = Instantiator.TransformFunctionProtoType( TLB, Proto, ThisContext, ThisTypeQuals, - [](FunctionProtoType::ExceptionSpecInfo &ESI, - bool &Changed) { return false; }); + [](FunctionProtoType::ExceptionSpecInfo &ESI, bool &Changed) { + return false; + }); } else { Result = Instantiator.TransformType(TLB, TL); } @@ -2211,23 +2229,26 @@ bool Sema::SubstExceptionSpec(SourceLocation Loc, FunctionProtoType::ExceptionSpecInfo &ESI, SmallVectorImpl &ExceptionStorage, - const MultiLevelTemplateArgumentList &Args) { + const MultiLevelTemplateArgumentList &Args, + bool EarlySubstitution) { assert(ESI.Type != EST_Uninstantiated); bool Changed = false; - TemplateInstantiator Instantiator(*this, Args, Loc, DeclarationName()); + TemplateInstantiator Instantiator(*this, Args, Loc, DeclarationName(), + EarlySubstitution); return Instantiator.TransformExceptionSpec(Loc, ESI, ExceptionStorage, Changed); } void Sema::SubstExceptionSpec(FunctionDecl *New, const FunctionProtoType *Proto, - const MultiLevelTemplateArgumentList &Args) { + const MultiLevelTemplateArgumentList &Args, + bool EarlySubstitution) { FunctionProtoType::ExceptionSpecInfo ESI = Proto->getExtProtoInfo().ExceptionSpec; SmallVector ExceptionStorage; if (SubstExceptionSpec(New->getTypeSourceInfo()->getTypeLoc().getEndLoc(), - ESI, ExceptionStorage, Args)) + ESI, ExceptionStorage, Args, EarlySubstitution)) // On error, recover by dropping the exception specification. ESI.Type = EST_None; @@ -2324,7 +2345,8 @@ bool Sema::SubstTypeConstraint( TemplateTypeParmDecl *Inst, const TypeConstraint *TC, - const MultiLevelTemplateArgumentList &TemplateArgs) { + const MultiLevelTemplateArgumentList &TemplateArgs, + bool EarlySubstitution) { const ASTTemplateArgumentListInfo *TemplArgInfo = TC->getTemplateArgsAsWritten(); TemplateArgumentListInfo InstArgs; @@ -2333,7 +2355,7 @@ InstArgs.setLAngleLoc(TemplArgInfo->LAngleLoc); InstArgs.setRAngleLoc(TemplArgInfo->RAngleLoc); if (SubstTemplateArguments(TemplArgInfo->arguments(), TemplateArgs, - InstArgs)) + EarlySubstitution, InstArgs)) return true; } return AttachTypeConstraint( @@ -2345,11 +2367,10 @@ : SourceLocation()); } -ParmVarDecl *Sema::SubstParmVarDecl(ParmVarDecl *OldParm, - const MultiLevelTemplateArgumentList &TemplateArgs, - int indexAdjustment, - Optional NumExpansions, - bool ExpectParameterPack) { +ParmVarDecl *Sema::SubstParmVarDecl( + ParmVarDecl *OldParm, const MultiLevelTemplateArgumentList &TemplateArgs, + bool EarlySubstitution, int indexAdjustment, + Optional NumExpansions, bool ExpectParameterPack) { TypeSourceInfo *OldDI = OldParm->getTypeSourceInfo(); TypeSourceInfo *NewDI = nullptr; @@ -2358,8 +2379,9 @@ // We have a function parameter pack. Substitute into the pattern of the // expansion. - NewDI = SubstType(ExpansionTL.getPatternLoc(), TemplateArgs, - OldParm->getLocation(), OldParm->getDeclName()); + NewDI = + SubstType(ExpansionTL.getPatternLoc(), TemplateArgs, EarlySubstitution, + OldParm->getLocation(), OldParm->getDeclName()); if (!NewDI) return nullptr; @@ -2380,8 +2402,9 @@ return nullptr; } } else { - NewDI = SubstType(OldDI, TemplateArgs, OldParm->getLocation(), - OldParm->getDeclName()); + NewDI = SubstType(OldDI, TemplateArgs, EarlySubstitution, + OldParm->getLocation(), OldParm->getDeclName(), + /*AllowDeducedTST=*/false); } if (!NewDI) @@ -2401,15 +2424,16 @@ if (TemplateTypeParmDecl *TTP = GetContainedInventedTypeParmVisitor().Visit(OldDI->getType())) { if (const TypeConstraint *TC = TTP->getTypeConstraint()) { - auto *Inst = cast_or_null( - FindInstantiatedDecl(TTP->getLocation(), TTP, TemplateArgs)); + auto *Inst = cast_or_null(FindInstantiatedDecl( + TTP->getLocation(), TTP, TemplateArgs, EarlySubstitution, + /*FindingInstantiatedContext=*/false)); // We will first get here when instantiating the abbreviated function // template's described function, but we might also get here later. // Make sure we do not instantiate the TypeConstraint more than once. if (Inst && !Inst->getTypeConstraint()) { // TODO: Concepts: do not instantiate the constraint (delayed constraint // substitution) - if (SubstTypeConstraint(Inst, TC, TemplateArgs)) + if (SubstTypeConstraint(Inst, TC, TemplateArgs, EarlySubstitution)) return nullptr; } } @@ -2438,7 +2462,7 @@ // and non-defining declarations. Sema::ContextRAII SavedContext(*this, OwningFunc); LocalInstantiationScope Local(*this, true); - ExprResult NewArg = SubstExpr(Arg, TemplateArgs); + ExprResult NewArg = SubstExpr(Arg, TemplateArgs, EarlySubstitution); if (NewArg.isUsable()) { // It would be nice if we still had this. SourceLocation EqualLoc = NewArg.get()->getBeginLoc(); @@ -2474,7 +2498,9 @@ NewParm->setScopeInfo(OldParm->getFunctionScopeDepth(), OldParm->getFunctionScopeIndex() + indexAdjustment); - InstantiateAttrs(TemplateArgs, OldParm, NewParm); + InstantiateAttrs(TemplateArgs, EarlySubstitution, OldParm, NewParm, + /*LateAttrs=*/nullptr, + /*OuterMostScope=*/nullptr); return NewParm; } @@ -2485,7 +2511,7 @@ bool Sema::SubstParmTypes( SourceLocation Loc, ArrayRef Params, const FunctionProtoType::ExtParameterInfo *ExtParamInfos, - const MultiLevelTemplateArgumentList &TemplateArgs, + const MultiLevelTemplateArgumentList &TemplateArgs, bool EarlySubstitution, SmallVectorImpl &ParamTypes, SmallVectorImpl *OutParams, ExtParameterInfoBuilder &ParamInfos) { @@ -2493,8 +2519,8 @@ "Cannot perform an instantiation without some context on the " "instantiation stack"); - TemplateInstantiator Instantiator(*this, TemplateArgs, Loc, - DeclarationName()); + TemplateInstantiator Instantiator(*this, TemplateArgs, Loc, DeclarationName(), + EarlySubstitution); return Instantiator.TransformFunctionTypeParams( Loc, Params, nullptr, ExtParamInfos, ParamTypes, OutParams, ParamInfos); } @@ -2505,10 +2531,10 @@ /// Produces a diagnostic and returns true on error, returns false and /// attaches the instantiated base classes to the class template /// specialization if successful. -bool -Sema::SubstBaseSpecifiers(CXXRecordDecl *Instantiation, - CXXRecordDecl *Pattern, - const MultiLevelTemplateArgumentList &TemplateArgs) { +bool Sema::SubstBaseSpecifiers( + CXXRecordDecl *Instantiation, CXXRecordDecl *Pattern, + const MultiLevelTemplateArgumentList &TemplateArgs, + bool EarlySubstitution) { bool Invalid = false; SmallVector InstantiatedBases; for (const auto &Base : Pattern->bases()) { @@ -2547,13 +2573,13 @@ for (unsigned I = 0; I != *NumExpansions; ++I) { Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(*this, I); - TypeSourceInfo *BaseTypeLoc = SubstType(Base.getTypeSourceInfo(), - TemplateArgs, - Base.getSourceRange().getBegin(), - DeclarationName()); - if (!BaseTypeLoc) { - Invalid = true; - continue; + TypeSourceInfo *BaseTypeLoc = SubstType( + Base.getTypeSourceInfo(), TemplateArgs, EarlySubstitution, + Base.getSourceRange().getBegin(), DeclarationName(), + /*AllowDeducedTST=*/false); + if (!BaseTypeLoc) { + Invalid = true; + continue; } if (CXXBaseSpecifier *InstantiatedBase @@ -2574,15 +2600,15 @@ // The resulting base specifier will (still) be a pack expansion. EllipsisLoc = Base.getEllipsisLoc(); Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(*this, -1); - BaseTypeLoc = SubstType(Base.getTypeSourceInfo(), - TemplateArgs, - Base.getSourceRange().getBegin(), - DeclarationName()); + BaseTypeLoc = + SubstType(Base.getTypeSourceInfo(), TemplateArgs, EarlySubstitution, + Base.getSourceRange().getBegin(), DeclarationName(), + /*AllowDeducedTST=*/false); } else { - BaseTypeLoc = SubstType(Base.getTypeSourceInfo(), - TemplateArgs, - Base.getSourceRange().getBegin(), - DeclarationName()); + BaseTypeLoc = + SubstType(Base.getTypeSourceInfo(), TemplateArgs, EarlySubstitution, + Base.getSourceRange().getBegin(), DeclarationName(), + /*AllowDeducedTST=*/false); } if (!BaseTypeLoc) { @@ -2611,11 +2637,14 @@ // Defined via #include from SemaTemplateInstantiateDecl.cpp namespace clang { namespace sema { - Attr *instantiateTemplateAttribute(const Attr *At, ASTContext &C, Sema &S, - const MultiLevelTemplateArgumentList &TemplateArgs); - Attr *instantiateTemplateAttributeForDecl( - const Attr *At, ASTContext &C, Sema &S, - const MultiLevelTemplateArgumentList &TemplateArgs); + Attr *instantiateTemplateAttribute( + const Attr *At, ASTContext &C, Sema &S, + const MultiLevelTemplateArgumentList &TemplateArgs, + bool EarlySubstitution); + Attr *instantiateTemplateAttributeForDecl( + const Attr *At, ASTContext &C, Sema &S, + const MultiLevelTemplateArgumentList &TemplateArgs, + bool EarlySubstitution); } } @@ -2641,12 +2670,12 @@ /// to the lack of a definition. /// /// \returns true if an error occurred, false otherwise. -bool -Sema::InstantiateClass(SourceLocation PointOfInstantiation, - CXXRecordDecl *Instantiation, CXXRecordDecl *Pattern, - const MultiLevelTemplateArgumentList &TemplateArgs, - TemplateSpecializationKind TSK, - bool Complain) { +bool Sema::InstantiateClass(SourceLocation PointOfInstantiation, + CXXRecordDecl *Instantiation, + CXXRecordDecl *Pattern, + const MultiLevelTemplateArgumentList &TemplateArgs, + bool EarlySubstitution, + TemplateSpecializationKind TSK, bool Complain) { CXXRecordDecl *PatternDef = cast_or_null(Pattern->getDefinition()); if (DiagnoseUninstantiableTemplate(PointOfInstantiation, Instantiation, @@ -2701,7 +2730,9 @@ SavePendingParsedClassStateRAII SavedPendingParsedClassState(*this); // Pull attributes from the pattern onto the instantiation. - InstantiateAttrs(TemplateArgs, Pattern, Instantiation); + InstantiateAttrs(TemplateArgs, EarlySubstitution, Pattern, Instantiation, + /*LateAttrs=*/nullptr, + /*OuterMostScope=*/nullptr); // Start the definition of this instantiation. Instantiation->startDefinition(); @@ -2714,10 +2745,12 @@ Instantiation->setTagKind(Pattern->getTagKind()); // Do substitution on the base class specifiers. - if (SubstBaseSpecifiers(Instantiation, Pattern, TemplateArgs)) + if (SubstBaseSpecifiers(Instantiation, Pattern, TemplateArgs, + EarlySubstitution)) Instantiation->setInvalidDecl(); - TemplateDeclInstantiator Instantiator(*this, Instantiation, TemplateArgs); + TemplateDeclInstantiator Instantiator(*this, Instantiation, TemplateArgs, + EarlySubstitution); SmallVector Fields; // Delay instantiation of late parsed attributes. LateInstantiatedAttrVec LateAttrs; @@ -2813,8 +2846,8 @@ CXXThisScopeRAII ThisScope(*this, ThisContext, Qualifiers(), ND->isCXXInstanceMember()); - Attr *NewAttr = - instantiateTemplateAttribute(I->TmplAttr, Context, *this, TemplateArgs); + Attr *NewAttr = instantiateTemplateAttribute( + I->TmplAttr, Context, *this, TemplateArgs, EarlySubstitution); if (NewAttr) I->NewDecl->addAttr(NewAttr); LocalInstantiationScope::deleteScopes(I->Scope, @@ -2836,7 +2869,7 @@ if (!Instantiation->isInvalidDecl()) { // Perform any dependent diagnostics from the pattern. if (Pattern->isDependentContext()) - PerformDependentDiagnostics(Pattern, TemplateArgs); + PerformDependentDiagnostics(Pattern, TemplateArgs, EarlySubstitution); // Instantiate any out-of-line class template partial // specializations now. @@ -2903,6 +2936,7 @@ bool Sema::InstantiateEnum(SourceLocation PointOfInstantiation, EnumDecl *Instantiation, EnumDecl *Pattern, const MultiLevelTemplateArgumentList &TemplateArgs, + bool EarlySubstitution, TemplateSpecializationKind TSK) { EnumDecl *PatternDef = Pattern->getDefinition(); if (DiagnoseUninstantiableTemplate(PointOfInstantiation, Instantiation, @@ -2939,9 +2973,12 @@ LocalInstantiationScope Scope(*this, /*MergeWithParentScope*/true); // Pull attributes from the pattern onto the instantiation. - InstantiateAttrs(TemplateArgs, Pattern, Instantiation); + InstantiateAttrs(TemplateArgs, EarlySubstitution, Pattern, Instantiation, + /*LateAttrs=*/nullptr, + /*OuterMostScope=*/nullptr); - TemplateDeclInstantiator Instantiator(*this, Instantiation, TemplateArgs); + TemplateDeclInstantiator Instantiator(*this, Instantiation, TemplateArgs, + EarlySubstitution); Instantiator.InstantiateEnumDefinition(Instantiation, Pattern); // Exit the scope of this instantiation. @@ -2950,7 +2987,6 @@ return Instantiation->isInvalidDecl(); } - /// Instantiate the definition of a field from the given pattern. /// /// \param PointOfInstantiation The point of instantiation within the @@ -2967,7 +3003,8 @@ /// \return \c true if an error occurred, \c false otherwise. bool Sema::InstantiateInClassInitializer( SourceLocation PointOfInstantiation, FieldDecl *Instantiation, - FieldDecl *Pattern, const MultiLevelTemplateArgumentList &TemplateArgs) { + FieldDecl *Pattern, const MultiLevelTemplateArgumentList &TemplateArgs, + bool EarlySubstitution) { // If there is no initializer, we don't need to do anything. if (!Pattern->hasInClassInitializer()) return false; @@ -3015,8 +3052,9 @@ ActOnStartCXXInClassMemberInitializer(); CXXThisScopeRAII ThisScope(*this, Instantiation->getParent(), Qualifiers()); - ExprResult NewInit = SubstInitializer(OldInit, TemplateArgs, - /*CXXDirectInit=*/false); + ExprResult NewInit = + SubstInitializer(OldInit, TemplateArgs, EarlySubstitution, + /*CXXDirectInit=*/false); Expr *Init = NewInit.get(); assert((!Init || !isa(Init)) && "call-style init in class"); ActOnFinishCXXInClassMemberInitializer( @@ -3223,19 +3261,19 @@ if (!Pattern.isUsable()) return Pattern.isInvalid(); - return InstantiateClass( - PointOfInstantiation, ClassTemplateSpec, Pattern.get(), - getTemplateInstantiationArgs(ClassTemplateSpec), TSK, Complain); + return InstantiateClass(PointOfInstantiation, ClassTemplateSpec, + Pattern.get(), + getTemplateInstantiationArgs(ClassTemplateSpec), + /*EarlySubstitution=*/false, TSK, Complain); } /// Instantiates the definitions of all of the member /// of the given class, which is an instantiation of a class template /// or a member class of a template. -void -Sema::InstantiateClassMembers(SourceLocation PointOfInstantiation, - CXXRecordDecl *Instantiation, - const MultiLevelTemplateArgumentList &TemplateArgs, - TemplateSpecializationKind TSK) { +void Sema::InstantiateClassMembers( + SourceLocation PointOfInstantiation, CXXRecordDecl *Instantiation, + const MultiLevelTemplateArgumentList &TemplateArgs, bool EarlySubstitution, + TemplateSpecializationKind TSK) { // FIXME: We need to notify the ASTMutationListener that we did all of these // things, in case we have an explicit instantiation definition in a PCM, a // module, or preamble, and the declaration is in an imported AST. @@ -3394,9 +3432,9 @@ continue; } - InstantiateClass(PointOfInstantiation, Record, Pattern, - TemplateArgs, - TSK); + InstantiateClass(PointOfInstantiation, Record, Pattern, TemplateArgs, + EarlySubstitution, TSK, + /*Complain=*/true); } else { if (TSK == TSK_ExplicitInstantiationDefinition && Record->getTemplateSpecializationKind() == @@ -3409,7 +3447,7 @@ Pattern = cast_or_null(Record->getDefinition()); if (Pattern) InstantiateClassMembers(PointOfInstantiation, Pattern, TemplateArgs, - TSK); + EarlySubstitution, TSK); } else if (auto *Enum = dyn_cast(D)) { MemberSpecializationInfo *MSInfo = Enum->getMemberSpecializationInfo(); assert(MSInfo && "No member specialization information?"); @@ -3435,7 +3473,8 @@ if (!Pattern->getDefinition()) continue; - InstantiateEnum(PointOfInstantiation, Enum, Pattern, TemplateArgs, TSK); + InstantiateEnum(PointOfInstantiation, Enum, Pattern, TemplateArgs, + EarlySubstitution, TSK); } else { MSInfo->setTemplateSpecializationKind(TSK); MSInfo->setPointOfInstantiation(PointOfInstantiation); @@ -3451,7 +3490,7 @@ FieldDecl *Pattern = Lookup.find_first(); assert(Pattern); InstantiateInClassInitializer(PointOfInstantiation, Field, Pattern, - TemplateArgs); + TemplateArgs, EarlySubstitution); } } } @@ -3475,90 +3514,91 @@ // below. InstantiateClassMembers(PointOfInstantiation, ClassTemplateSpec, getTemplateInstantiationArgs(ClassTemplateSpec), - TSK); + /*EarlySubstitution=*/false, TSK); } -StmtResult -Sema::SubstStmt(Stmt *S, const MultiLevelTemplateArgumentList &TemplateArgs) { +StmtResult Sema::SubstStmt(Stmt *S, + const MultiLevelTemplateArgumentList &TemplateArgs, + bool EarlySubstitution) { if (!S) return S; - TemplateInstantiator Instantiator(*this, TemplateArgs, - SourceLocation(), - DeclarationName()); + TemplateInstantiator Instantiator(*this, TemplateArgs, SourceLocation(), + DeclarationName(), EarlySubstitution); return Instantiator.TransformStmt(S); } bool Sema::SubstTemplateArguments( ArrayRef Args, - const MultiLevelTemplateArgumentList &TemplateArgs, + const MultiLevelTemplateArgumentList &TemplateArgs, bool EarlySubstitution, TemplateArgumentListInfo &Out) { - TemplateInstantiator Instantiator(*this, TemplateArgs, - SourceLocation(), - DeclarationName()); - return Instantiator.TransformTemplateArguments(Args.begin(), Args.end(), - Out); + TemplateInstantiator Instantiator(*this, TemplateArgs, SourceLocation(), + DeclarationName(), EarlySubstitution); + return Instantiator.TransformTemplateArguments(Args.begin(), Args.end(), Out); } -ExprResult -Sema::SubstExpr(Expr *E, const MultiLevelTemplateArgumentList &TemplateArgs) { +ExprResult Sema::SubstExpr(Expr *E, + const MultiLevelTemplateArgumentList &TemplateArgs, + bool EarlySubstitution) { if (!E) return E; - TemplateInstantiator Instantiator(*this, TemplateArgs, - SourceLocation(), - DeclarationName()); + TemplateInstantiator Instantiator(*this, TemplateArgs, SourceLocation(), + DeclarationName(), EarlySubstitution); return Instantiator.TransformExpr(E); } -ExprResult Sema::SubstInitializer(Expr *Init, - const MultiLevelTemplateArgumentList &TemplateArgs, - bool CXXDirectInit) { - TemplateInstantiator Instantiator(*this, TemplateArgs, - SourceLocation(), - DeclarationName()); +ExprResult +Sema::SubstInitializer(Expr *Init, + const MultiLevelTemplateArgumentList &TemplateArgs, + bool EarlySubstitution, bool CXXDirectInit) { + TemplateInstantiator Instantiator(*this, TemplateArgs, SourceLocation(), + DeclarationName(), EarlySubstitution); return Instantiator.TransformInitializer(Init, CXXDirectInit); } bool Sema::SubstExprs(ArrayRef Exprs, bool IsCall, const MultiLevelTemplateArgumentList &TemplateArgs, + bool EarlySubstitution, SmallVectorImpl &Outputs) { if (Exprs.empty()) return false; - TemplateInstantiator Instantiator(*this, TemplateArgs, - SourceLocation(), - DeclarationName()); - return Instantiator.TransformExprs(Exprs.data(), Exprs.size(), - IsCall, Outputs); + TemplateInstantiator Instantiator(*this, TemplateArgs, SourceLocation(), + DeclarationName(), EarlySubstitution); + return Instantiator.TransformExprs(Exprs.data(), Exprs.size(), IsCall, + Outputs); } -NestedNameSpecifierLoc -Sema::SubstNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS, - const MultiLevelTemplateArgumentList &TemplateArgs) { +NestedNameSpecifierLoc Sema::SubstNestedNameSpecifierLoc( + NestedNameSpecifierLoc NNS, + const MultiLevelTemplateArgumentList &TemplateArgs, + bool EarlySubstitution) { if (!NNS) return NestedNameSpecifierLoc(); TemplateInstantiator Instantiator(*this, TemplateArgs, NNS.getBeginLoc(), - DeclarationName()); + DeclarationName(), EarlySubstitution); return Instantiator.TransformNestedNameSpecifierLoc(NNS); } /// Do template substitution on declaration name info. -DeclarationNameInfo -Sema::SubstDeclarationNameInfo(const DeclarationNameInfo &NameInfo, - const MultiLevelTemplateArgumentList &TemplateArgs) { +DeclarationNameInfo Sema::SubstDeclarationNameInfo( + const DeclarationNameInfo &NameInfo, + const MultiLevelTemplateArgumentList &TemplateArgs, + bool EarlySubstitution) { TemplateInstantiator Instantiator(*this, TemplateArgs, NameInfo.getLoc(), - NameInfo.getName()); + NameInfo.getName(), EarlySubstitution); return Instantiator.TransformDeclarationNameInfo(NameInfo); } TemplateName -Sema::SubstTemplateName(NestedNameSpecifierLoc QualifierLoc, - TemplateName Name, SourceLocation Loc, - const MultiLevelTemplateArgumentList &TemplateArgs) { - TemplateInstantiator Instantiator(*this, TemplateArgs, Loc, - DeclarationName()); +Sema::SubstTemplateName(NestedNameSpecifierLoc QualifierLoc, TemplateName Name, + SourceLocation Loc, + const MultiLevelTemplateArgumentList &TemplateArgs, + bool EarlySubstitution) { + TemplateInstantiator Instantiator(*this, TemplateArgs, Loc, DeclarationName(), + EarlySubstitution); CXXScopeSpec SS; SS.Adopt(QualifierLoc); return Instantiator.TransformTemplateName(SS, Name, Loc); diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -43,9 +43,10 @@ return false; } -template +template static bool SubstQualifier(Sema &SemaRef, const DeclT *OldDecl, DeclT *NewDecl, - const MultiLevelTemplateArgumentList &TemplateArgs) { + const MultiLevelTemplateArgumentList &TemplateArgs, + bool EarlySubstitution) { if (!OldDecl->getQualifierLoc()) return false; @@ -58,9 +59,8 @@ ? NewDecl->getLexicalDeclContext() : OldDecl->getLexicalDeclContext())); - NestedNameSpecifierLoc NewQualifierLoc - = SemaRef.SubstNestedNameSpecifierLoc(OldDecl->getQualifierLoc(), - TemplateArgs); + NestedNameSpecifierLoc NewQualifierLoc = SemaRef.SubstNestedNameSpecifierLoc( + OldDecl->getQualifierLoc(), TemplateArgs, EarlySubstitution); if (!NewQualifierLoc) return true; @@ -71,12 +71,14 @@ bool TemplateDeclInstantiator::SubstQualifier(const DeclaratorDecl *OldDecl, DeclaratorDecl *NewDecl) { - return ::SubstQualifier(SemaRef, OldDecl, NewDecl, TemplateArgs); + return ::SubstQualifier(SemaRef, OldDecl, NewDecl, TemplateArgs, + EarlySubstitution); } bool TemplateDeclInstantiator::SubstQualifier(const TagDecl *OldDecl, TagDecl *NewDecl) { - return ::SubstQualifier(SemaRef, OldDecl, NewDecl, TemplateArgs); + return ::SubstQualifier(SemaRef, OldDecl, NewDecl, TemplateArgs, + EarlySubstitution); } // Include attribute instantiation code. @@ -84,18 +86,21 @@ static void instantiateDependentAlignedAttr( Sema &S, const MultiLevelTemplateArgumentList &TemplateArgs, - const AlignedAttr *Aligned, Decl *New, bool IsPackExpansion) { + bool EarlySubstitution, const AlignedAttr *Aligned, Decl *New, + bool IsPackExpansion) { if (Aligned->isAlignmentExpr()) { // The alignment expression is a constant expression. EnterExpressionEvaluationContext Unevaluated( S, Sema::ExpressionEvaluationContext::ConstantEvaluated); - ExprResult Result = S.SubstExpr(Aligned->getAlignmentExpr(), TemplateArgs); + ExprResult Result = S.SubstExpr(Aligned->getAlignmentExpr(), TemplateArgs, + EarlySubstitution); if (!Result.isInvalid()) S.AddAlignedAttr(New, *Aligned, Result.getAs(), IsPackExpansion); } else { - TypeSourceInfo *Result = S.SubstType(Aligned->getAlignmentType(), - TemplateArgs, Aligned->getLocation(), - DeclarationName()); + TypeSourceInfo *Result = S.SubstType( + Aligned->getAlignmentType(), TemplateArgs, EarlySubstitution, + Aligned->getLocation(), DeclarationName(), + /*AllowDeducedTST=*/false); if (Result) S.AddAlignedAttr(New, *Aligned, Result, IsPackExpansion); } @@ -103,9 +108,10 @@ static void instantiateDependentAlignedAttr( Sema &S, const MultiLevelTemplateArgumentList &TemplateArgs, - const AlignedAttr *Aligned, Decl *New) { + bool EarlySubstitution, const AlignedAttr *Aligned, Decl *New) { if (!Aligned->isPackExpansion()) { - instantiateDependentAlignedAttr(S, TemplateArgs, Aligned, New, false); + instantiateDependentAlignedAttr(S, TemplateArgs, EarlySubstitution, Aligned, + New, /*IsPackExpansion=*/false); return; } @@ -130,30 +136,33 @@ if (!Expand) { Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(S, -1); - instantiateDependentAlignedAttr(S, TemplateArgs, Aligned, New, true); + instantiateDependentAlignedAttr(S, TemplateArgs, EarlySubstitution, Aligned, + New, true); } else { for (unsigned I = 0; I != *NumExpansions; ++I) { Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(S, I); - instantiateDependentAlignedAttr(S, TemplateArgs, Aligned, New, false); + instantiateDependentAlignedAttr(S, TemplateArgs, EarlySubstitution, + Aligned, New, false); } } } static void instantiateDependentAssumeAlignedAttr( Sema &S, const MultiLevelTemplateArgumentList &TemplateArgs, - const AssumeAlignedAttr *Aligned, Decl *New) { + bool EarlySubstitution, const AssumeAlignedAttr *Aligned, Decl *New) { // The alignment expression is a constant expression. EnterExpressionEvaluationContext Unevaluated( S, Sema::ExpressionEvaluationContext::ConstantEvaluated); Expr *E, *OE = nullptr; - ExprResult Result = S.SubstExpr(Aligned->getAlignment(), TemplateArgs); + ExprResult Result = + S.SubstExpr(Aligned->getAlignment(), TemplateArgs, EarlySubstitution); if (Result.isInvalid()) return; E = Result.getAs(); if (Aligned->getOffset()) { - Result = S.SubstExpr(Aligned->getOffset(), TemplateArgs); + Result = S.SubstExpr(Aligned->getOffset(), TemplateArgs, EarlySubstitution); if (Result.isInvalid()) return; OE = Result.getAs(); @@ -164,11 +173,12 @@ static void instantiateDependentAlignValueAttr( Sema &S, const MultiLevelTemplateArgumentList &TemplateArgs, - const AlignValueAttr *Aligned, Decl *New) { + bool EarlySubstitution, const AlignValueAttr *Aligned, Decl *New) { // The alignment expression is a constant expression. EnterExpressionEvaluationContext Unevaluated( S, Sema::ExpressionEvaluationContext::ConstantEvaluated); - ExprResult Result = S.SubstExpr(Aligned->getAlignment(), TemplateArgs); + ExprResult Result = + S.SubstExpr(Aligned->getAlignment(), TemplateArgs, EarlySubstitution); if (!Result.isInvalid()) S.AddAlignValueAttr(New, *Aligned, Result.getAs()); } @@ -185,7 +195,7 @@ static void instantiateDependentAnnotationAttr( Sema &S, const MultiLevelTemplateArgumentList &TemplateArgs, - const AnnotateAttr *Attr, Decl *New) { + bool EarlySubstitution, const AnnotateAttr *Attr, Decl *New) { EnterExpressionEvaluationContext Unevaluated( S, Sema::ExpressionEvaluationContext::ConstantEvaluated); @@ -200,7 +210,7 @@ SmallVector Args; if (S.SubstExprs(ArgsToInstantiate, - /*IsCall=*/false, TemplateArgs, Args)) + /*IsCall=*/false, TemplateArgs, EarlySubstitution, Args)) return; StringRef Str = Attr->getAnnotation(); @@ -223,13 +233,14 @@ static Expr *instantiateDependentFunctionAttrCondition( Sema &S, const MultiLevelTemplateArgumentList &TemplateArgs, - const Attr *A, Expr *OldCond, const Decl *Tmpl, FunctionDecl *New) { + bool EarlySubstitution, const Attr *A, Expr *OldCond, const Decl *Tmpl, + FunctionDecl *New) { Expr *Cond = nullptr; { Sema::ContextRAII SwitchContext(S, New); EnterExpressionEvaluationContext Unevaluated( S, Sema::ExpressionEvaluationContext::ConstantEvaluated); - ExprResult Result = S.SubstExpr(OldCond, TemplateArgs); + ExprResult Result = S.SubstExpr(OldCond, TemplateArgs, EarlySubstitution); if (Result.isInvalid()) return nullptr; Cond = Result.getAs(); @@ -254,9 +265,10 @@ static void instantiateDependentEnableIfAttr( Sema &S, const MultiLevelTemplateArgumentList &TemplateArgs, - const EnableIfAttr *EIA, const Decl *Tmpl, FunctionDecl *New) { + bool EarlySubstitution, const EnableIfAttr *EIA, const Decl *Tmpl, + FunctionDecl *New) { Expr *Cond = instantiateDependentFunctionAttrCondition( - S, TemplateArgs, EIA, EIA->getCond(), Tmpl, New); + S, TemplateArgs, EarlySubstitution, EIA, EIA->getCond(), Tmpl, New); if (Cond) New->addAttr(new (S.getASTContext()) EnableIfAttr(S.getASTContext(), *EIA, @@ -265,9 +277,10 @@ static void instantiateDependentDiagnoseIfAttr( Sema &S, const MultiLevelTemplateArgumentList &TemplateArgs, - const DiagnoseIfAttr *DIA, const Decl *Tmpl, FunctionDecl *New) { + bool EarlySubstitution, const DiagnoseIfAttr *DIA, const Decl *Tmpl, + FunctionDecl *New) { Expr *Cond = instantiateDependentFunctionAttrCondition( - S, TemplateArgs, DIA, DIA->getCond(), Tmpl, New); + S, TemplateArgs, EarlySubstitution, DIA, DIA->getCond(), Tmpl, New); if (Cond) New->addAttr(new (S.getASTContext()) DiagnoseIfAttr( @@ -279,19 +292,20 @@ // template A as the base and arguments from TemplateArgs. static void instantiateDependentCUDALaunchBoundsAttr( Sema &S, const MultiLevelTemplateArgumentList &TemplateArgs, - const CUDALaunchBoundsAttr &Attr, Decl *New) { + bool EarlySubstitution, const CUDALaunchBoundsAttr &Attr, Decl *New) { // The alignment expression is a constant expression. EnterExpressionEvaluationContext Unevaluated( S, Sema::ExpressionEvaluationContext::ConstantEvaluated); - ExprResult Result = S.SubstExpr(Attr.getMaxThreads(), TemplateArgs); + ExprResult Result = + S.SubstExpr(Attr.getMaxThreads(), TemplateArgs, EarlySubstitution); if (Result.isInvalid()) return; Expr *MaxThreads = Result.getAs(); Expr *MinBlocks = nullptr; if (Attr.getMinBlocks()) { - Result = S.SubstExpr(Attr.getMinBlocks(), TemplateArgs); + Result = S.SubstExpr(Attr.getMinBlocks(), TemplateArgs, EarlySubstitution); if (Result.isInvalid()) return; MinBlocks = Result.getAs(); @@ -300,10 +314,8 @@ S.AddLaunchBoundsAttr(New, Attr, MaxThreads, MinBlocks); } -static void -instantiateDependentModeAttr(Sema &S, - const MultiLevelTemplateArgumentList &TemplateArgs, - const ModeAttr &Attr, Decl *New) { +static void instantiateDependentModeAttr(Sema &S, const ModeAttr &Attr, + Decl *New) { S.AddModeAttr(New, Attr, Attr.getMode(), /*InInstantiation=*/true); } @@ -311,7 +323,7 @@ /// Instantiation of 'declare simd' attribute and its arguments. static void instantiateOMPDeclareSimdDeclAttr( Sema &S, const MultiLevelTemplateArgumentList &TemplateArgs, - const OMPDeclareSimdDeclAttr &Attr, Decl *New) { + bool EarlySubstitution, const OMPDeclareSimdDeclAttr &Attr, Decl *New) { // Allow 'this' in clauses with varlists. if (auto *FTD = dyn_cast(New)) New = FTD->getTemplatedDecl(); @@ -328,11 +340,11 @@ if (FD->getNumParams() > PVD->getFunctionScopeIndex()) Local.InstantiatedLocal( PVD, FD->getParamDecl(PVD->getFunctionScopeIndex())); - return S.SubstExpr(E, TemplateArgs); + return S.SubstExpr(E, TemplateArgs, EarlySubstitution); } Sema::CXXThisScopeRAII ThisScope(S, ThisContext, Qualifiers(), FD->isCXXInstanceMember()); - return S.SubstExpr(E, TemplateArgs); + return S.SubstExpr(E, TemplateArgs, EarlySubstitution); }; // Substitute a single OpenMP clause, which is a potentially-evaluated @@ -367,7 +379,7 @@ Aligneds.push_back(Inst.get()); Inst = ExprEmpty(); if (*AI) - Inst = S.SubstExpr(*AI, TemplateArgs); + Inst = S.SubstExpr(*AI, TemplateArgs, EarlySubstitution); Alignments.push_back(Inst.get()); ++AI; } @@ -380,7 +392,7 @@ Linears.push_back(Inst.get()); Inst = ExprEmpty(); if (*SI) - Inst = S.SubstExpr(*SI, TemplateArgs); + Inst = S.SubstExpr(*SI, TemplateArgs, EarlySubstitution); Steps.push_back(Inst.get()); ++SI; } @@ -394,14 +406,15 @@ /// Instantiation of 'declare variant' attribute and its arguments. static void instantiateOMPDeclareVariantAttr( Sema &S, const MultiLevelTemplateArgumentList &TemplateArgs, - const OMPDeclareVariantAttr &Attr, Decl *New) { + bool EarlySubstitution, const OMPDeclareVariantAttr &Attr, Decl *New) { // Allow 'this' in clauses with varlists. if (auto *FTD = dyn_cast(New)) New = FTD->getTemplatedDecl(); auto *FD = cast(New); auto *ThisContext = dyn_cast_or_null(FD->getDeclContext()); - auto &&SubstExpr = [FD, ThisContext, &S, &TemplateArgs](Expr *E) { + auto &&SubstExpr = [FD, ThisContext, &S, &TemplateArgs, + &EarlySubstitution](Expr *E) { if (auto *DRE = dyn_cast(E->IgnoreParenImpCasts())) if (auto *PVD = dyn_cast(DRE->getDecl())) { Sema::ContextRAII SavedContext(S, FD); @@ -409,11 +422,11 @@ if (FD->getNumParams() > PVD->getFunctionScopeIndex()) Local.InstantiatedLocal( PVD, FD->getParamDecl(PVD->getFunctionScopeIndex())); - return S.SubstExpr(E, TemplateArgs); + return S.SubstExpr(E, TemplateArgs, EarlySubstitution); } Sema::CXXThisScopeRAII ThisScope(S, ThisContext, Qualifiers(), FD->isCXXInstanceMember()); - return S.SubstExpr(E, TemplateArgs); + return S.SubstExpr(E, TemplateArgs, EarlySubstitution); }; // Substitute a single OpenMP clause, which is a potentially-evaluated @@ -481,8 +494,8 @@ const TemplateArgumentList *TAL = TemplateArgumentList::CreateCopy( S.Context, TemplateArgs.getInnermost()); - auto *SubstFD = S.InstantiateFunctionDeclaration(VariantFTD, TAL, - New->getLocation()); + auto *SubstFD = S.InstantiateFunctionDeclaration( + VariantFTD, TAL, EarlySubstitution, New->getLocation()); if (!SubstFD) return; QualType NewType = S.Context.mergeFunctionTypes( @@ -529,17 +542,19 @@ static void instantiateDependentAMDGPUFlatWorkGroupSizeAttr( Sema &S, const MultiLevelTemplateArgumentList &TemplateArgs, - const AMDGPUFlatWorkGroupSizeAttr &Attr, Decl *New) { + bool EarlySubstitution, const AMDGPUFlatWorkGroupSizeAttr &Attr, + Decl *New) { // Both min and max expression are constant expressions. EnterExpressionEvaluationContext Unevaluated( S, Sema::ExpressionEvaluationContext::ConstantEvaluated); - ExprResult Result = S.SubstExpr(Attr.getMin(), TemplateArgs); + ExprResult Result = + S.SubstExpr(Attr.getMin(), TemplateArgs, EarlySubstitution); if (Result.isInvalid()) return; Expr *MinExpr = Result.getAs(); - Result = S.SubstExpr(Attr.getMax(), TemplateArgs); + Result = S.SubstExpr(Attr.getMax(), TemplateArgs, EarlySubstitution); if (Result.isInvalid()) return; Expr *MaxExpr = Result.getAs(); @@ -547,10 +562,9 @@ S.addAMDGPUFlatWorkGroupSizeAttr(New, Attr, MinExpr, MaxExpr); } -static ExplicitSpecifier -instantiateExplicitSpecifier(Sema &S, - const MultiLevelTemplateArgumentList &TemplateArgs, - ExplicitSpecifier ES, FunctionDecl *New) { +static ExplicitSpecifier instantiateExplicitSpecifier( + Sema &S, const MultiLevelTemplateArgumentList &TemplateArgs, + bool EarlySubstitution, ExplicitSpecifier ES, FunctionDecl *New) { if (!ES.getExpr()) return ES; Expr *OldCond = ES.getExpr(); @@ -558,7 +572,8 @@ { EnterExpressionEvaluationContext Unevaluated( S, Sema::ExpressionEvaluationContext::ConstantEvaluated); - ExprResult SubstResult = S.SubstExpr(OldCond, TemplateArgs); + ExprResult SubstResult = + S.SubstExpr(OldCond, TemplateArgs, EarlySubstitution); if (SubstResult.isInvalid()) { return ExplicitSpecifier::Invalid(); } @@ -572,19 +587,20 @@ static void instantiateDependentAMDGPUWavesPerEUAttr( Sema &S, const MultiLevelTemplateArgumentList &TemplateArgs, - const AMDGPUWavesPerEUAttr &Attr, Decl *New) { + bool EarlySubstitution, const AMDGPUWavesPerEUAttr &Attr, Decl *New) { // Both min and max expression are constant expressions. EnterExpressionEvaluationContext Unevaluated( S, Sema::ExpressionEvaluationContext::ConstantEvaluated); - ExprResult Result = S.SubstExpr(Attr.getMin(), TemplateArgs); + ExprResult Result = + S.SubstExpr(Attr.getMin(), TemplateArgs, EarlySubstitution); if (Result.isInvalid()) return; Expr *MinExpr = Result.getAs(); Expr *MaxExpr = nullptr; if (auto Max = Attr.getMax()) { - Result = S.SubstExpr(Max, TemplateArgs); + Result = S.SubstExpr(Max, TemplateArgs, EarlySubstitution); if (Result.isInvalid()) return; MaxExpr = Result.getAs(); @@ -596,9 +612,9 @@ // This doesn't take any template parameters, but we have a custom action that // needs to happen when the kernel itself is instantiated. We need to run the // ItaniumMangler to mark the names required to name this kernel. -static void instantiateDependentSYCLKernelAttr( - Sema &S, const MultiLevelTemplateArgumentList &TemplateArgs, - const SYCLKernelAttr &Attr, Decl *New) { +static void instantiateDependentSYCLKernelAttr(Sema &S, + const SYCLKernelAttr &Attr, + Decl *New) { New->addAttr(Attr.clone(S.getASTContext())); } @@ -650,8 +666,8 @@ } void Sema::InstantiateAttrsForDecl( - const MultiLevelTemplateArgumentList &TemplateArgs, const Decl *Tmpl, - Decl *New, LateInstantiatedAttrVec *LateAttrs, + const MultiLevelTemplateArgumentList &TemplateArgs, bool EarlySubstitution, + const Decl *Tmpl, Decl *New, LateInstantiatedAttrVec *LateAttrs, LocalInstantiationScope *OuterMostScope) { if (NamedDecl *ND = dyn_cast(New)) { // FIXME: This function is called multiple times for the same template @@ -668,7 +684,7 @@ Qualifiers(), ND->isCXXInstanceMember()); Attr *NewAttr = sema::instantiateTemplateAttributeForDecl( - TmplAttr, Context, *this, TemplateArgs); + TmplAttr, Context, *this, TemplateArgs, EarlySubstitution); if (NewAttr && isRelevantAttr(*this, New, NewAttr)) New->addAttr(NewAttr); } @@ -690,7 +706,7 @@ } void Sema::InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs, - const Decl *Tmpl, Decl *New, + bool EarlySubstitution, const Decl *Tmpl, Decl *New, LateInstantiatedAttrVec *LateAttrs, LocalInstantiationScope *OuterMostScope) { for (const auto *TmplAttr : Tmpl->attrs()) { @@ -700,17 +716,20 @@ // FIXME: This should be generalized to more than just the AlignedAttr. const AlignedAttr *Aligned = dyn_cast(TmplAttr); if (Aligned && Aligned->isAlignmentDependent()) { - instantiateDependentAlignedAttr(*this, TemplateArgs, Aligned, New); + instantiateDependentAlignedAttr(*this, TemplateArgs, EarlySubstitution, + Aligned, New); continue; } if (const auto *AssumeAligned = dyn_cast(TmplAttr)) { - instantiateDependentAssumeAlignedAttr(*this, TemplateArgs, AssumeAligned, New); + instantiateDependentAssumeAlignedAttr( + *this, TemplateArgs, EarlySubstitution, AssumeAligned, New); continue; } if (const auto *AlignValue = dyn_cast(TmplAttr)) { - instantiateDependentAlignValueAttr(*this, TemplateArgs, AlignValue, New); + instantiateDependentAlignValueAttr(*this, TemplateArgs, EarlySubstitution, + AlignValue, New); continue; } @@ -720,53 +739,59 @@ } if (const auto *Annotate = dyn_cast(TmplAttr)) { - instantiateDependentAnnotationAttr(*this, TemplateArgs, Annotate, New); + instantiateDependentAnnotationAttr(*this, TemplateArgs, EarlySubstitution, + Annotate, New); continue; } if (const auto *EnableIf = dyn_cast(TmplAttr)) { - instantiateDependentEnableIfAttr(*this, TemplateArgs, EnableIf, Tmpl, - cast(New)); + instantiateDependentEnableIfAttr(*this, TemplateArgs, EarlySubstitution, + EnableIf, Tmpl, cast(New)); continue; } if (const auto *DiagnoseIf = dyn_cast(TmplAttr)) { - instantiateDependentDiagnoseIfAttr(*this, TemplateArgs, DiagnoseIf, Tmpl, + instantiateDependentDiagnoseIfAttr(*this, TemplateArgs, EarlySubstitution, + DiagnoseIf, Tmpl, cast(New)); continue; } if (const auto *CUDALaunchBounds = dyn_cast(TmplAttr)) { - instantiateDependentCUDALaunchBoundsAttr(*this, TemplateArgs, - *CUDALaunchBounds, New); + instantiateDependentCUDALaunchBoundsAttr( + *this, TemplateArgs, EarlySubstitution, *CUDALaunchBounds, New); continue; } if (const auto *Mode = dyn_cast(TmplAttr)) { - instantiateDependentModeAttr(*this, TemplateArgs, *Mode, New); + instantiateDependentModeAttr(*this, *Mode, New); continue; } if (const auto *OMPAttr = dyn_cast(TmplAttr)) { - instantiateOMPDeclareSimdDeclAttr(*this, TemplateArgs, *OMPAttr, New); + instantiateOMPDeclareSimdDeclAttr(*this, TemplateArgs, EarlySubstitution, + *OMPAttr, New); continue; } if (const auto *OMPAttr = dyn_cast(TmplAttr)) { - instantiateOMPDeclareVariantAttr(*this, TemplateArgs, *OMPAttr, New); + instantiateOMPDeclareVariantAttr(*this, TemplateArgs, EarlySubstitution, + *OMPAttr, New); continue; } if (const auto *AMDGPUFlatWorkGroupSize = dyn_cast(TmplAttr)) { instantiateDependentAMDGPUFlatWorkGroupSizeAttr( - *this, TemplateArgs, *AMDGPUFlatWorkGroupSize, New); + *this, TemplateArgs, EarlySubstitution, *AMDGPUFlatWorkGroupSize, + New); } if (const auto *AMDGPUFlatWorkGroupSize = dyn_cast(TmplAttr)) { instantiateDependentAMDGPUWavesPerEUAttr(*this, TemplateArgs, + EarlySubstitution, *AMDGPUFlatWorkGroupSize, New); } @@ -803,7 +828,7 @@ } if (auto *A = dyn_cast(TmplAttr)) { - instantiateDependentSYCLKernelAttr(*this, TemplateArgs, *A, New); + instantiateDependentSYCLKernelAttr(*this, *A, New); continue; } @@ -822,8 +847,8 @@ CXXThisScopeRAII ThisScope(*this, ThisContext, Qualifiers(), ND->isCXXInstanceMember()); - Attr *NewAttr = sema::instantiateTemplateAttribute(TmplAttr, Context, - *this, TemplateArgs); + Attr *NewAttr = sema::instantiateTemplateAttribute( + TmplAttr, Context, *this, TemplateArgs, EarlySubstitution); if (NewAttr && isRelevantAttr(*this, New, TmplAttr)) New->addAttr(NewAttr); } @@ -935,8 +960,9 @@ TypeSourceInfo *DI = D->getTypeSourceInfo(); if (DI->getType()->isInstantiationDependentType() || DI->getType()->isVariablyModifiedType()) { - DI = SemaRef.SubstType(DI, TemplateArgs, - D->getLocation(), D->getDeclName()); + DI = SemaRef.SubstType(DI, TemplateArgs, EarlySubstitution, + D->getLocation(), D->getDeclName(), + /*AllowDeducedTST=*/false); if (!DI) { Invalid = true; DI = SemaRef.Context.getTrivialTypeSourceInfo(SemaRef.Context.IntTy); @@ -985,8 +1011,9 @@ } if (TypedefNameDecl *Prev = getPreviousDeclForInstantiation(D)) { - NamedDecl *InstPrev = SemaRef.FindInstantiatedDecl(D->getLocation(), Prev, - TemplateArgs); + NamedDecl *InstPrev = SemaRef.FindInstantiatedDecl( + D->getLocation(), Prev, TemplateArgs, EarlySubstitution, + /*FindingInstantiatedContext=*/false); if (!InstPrev) return nullptr; @@ -998,7 +1025,9 @@ Typedef->setPreviousDecl(InstPrevTypedef); } - SemaRef.InstantiateAttrs(TemplateArgs, D, Typedef); + SemaRef.InstantiateAttrs(TemplateArgs, EarlySubstitution, D, Typedef, + /*LateAttrs=*/nullptr, + /*OuterMostScope=*/nullptr); if (D->getUnderlyingType()->getAs()) SemaRef.inferGslPointerAttribute(Typedef); @@ -1028,9 +1057,10 @@ // Create a local instantiation scope for this type alias template, which // will contain the instantiations of the template parameters. LocalInstantiationScope Scope(SemaRef); + auto EarlySubstitutionScope = getEarlySubstitutionRAII(); - TemplateParameterList *TempParams = D->getTemplateParameters(); - TemplateParameterList *InstParams = SubstTemplateParams(TempParams); + TemplateParameterList *InstParams = + SubstTemplateParams(D->getTemplateParameters()); if (!InstParams) return nullptr; @@ -1045,12 +1075,12 @@ } TypeAliasDecl *AliasInst = cast_or_null( - InstantiateTypedefNameDecl(Pattern, /*IsTypeAlias=*/true)); + InstantiateTypedefNameDecl(Pattern, /*IsTypeAlias=*/true)); if (!AliasInst) return nullptr; - TypeAliasTemplateDecl *Inst - = TypeAliasTemplateDecl::Create(SemaRef.Context, Owner, D->getLocation(), + TypeAliasTemplateDecl *Inst = + TypeAliasTemplateDecl::Create(SemaRef.Context, Owner, D->getLocation(), D->getDeclName(), InstParams, AliasInst); AliasInst->setDescribedAliasTemplate(Inst); if (PrevAliasTemplate) @@ -1101,8 +1131,8 @@ // Do substitution on the type of the declaration TypeSourceInfo *DI = SemaRef.SubstType( - D->getTypeSourceInfo(), TemplateArgs, D->getTypeSpecStartLoc(), - D->getDeclName(), /*AllowDeducedTST*/true); + D->getTypeSourceInfo(), TemplateArgs, EarlySubstitution, + D->getTypeSpecStartLoc(), D->getDeclName(), /*AllowDeducedTST=*/true); if (!DI) return nullptr; @@ -1139,8 +1169,10 @@ if (SubstQualifier(D, Var)) return nullptr; - SemaRef.BuildVariableInstantiation(Var, D, TemplateArgs, LateAttrs, Owner, - StartingScope, InstantiatingVarTemplate); + SemaRef.BuildVariableInstantiation(Var, D, TemplateArgs, EarlySubstitution, + LateAttrs, Owner, StartingScope, + InstantiatingVarTemplate, + /*PrevVTSD=*/nullptr); if (D->isNRVOVariable() && !Var->isInvalidDecl()) { QualType RT; if (auto *F = dyn_cast(DC)) @@ -1188,8 +1220,9 @@ TypeSourceInfo *DI = D->getTypeSourceInfo(); if (DI->getType()->isInstantiationDependentType() || DI->getType()->isVariablyModifiedType()) { - DI = SemaRef.SubstType(DI, TemplateArgs, - D->getLocation(), D->getDeclName()); + DI = SemaRef.SubstType(DI, TemplateArgs, EarlySubstitution, + D->getLocation(), D->getDeclName(), + /*AllowDeducedTST=*/false); if (!DI) { DI = D->getTypeSourceInfo(); Invalid = true; @@ -1216,8 +1249,8 @@ EnterExpressionEvaluationContext Unevaluated( SemaRef, Sema::ExpressionEvaluationContext::ConstantEvaluated); - ExprResult InstantiatedBitWidth - = SemaRef.SubstExpr(BitWidth, TemplateArgs); + ExprResult InstantiatedBitWidth = + SemaRef.SubstExpr(BitWidth, TemplateArgs, EarlySubstitution); if (InstantiatedBitWidth.isInvalid()) { Invalid = true; BitWidth = nullptr; @@ -1240,7 +1273,8 @@ return nullptr; } - SemaRef.InstantiateAttrs(TemplateArgs, D, Field, LateAttrs, StartingScope); + SemaRef.InstantiateAttrs(TemplateArgs, EarlySubstitution, D, Field, LateAttrs, + StartingScope); if (Field->hasAttrs()) SemaRef.CheckAlignasUnderalignment(Field); @@ -1274,8 +1308,9 @@ << D; Invalid = true; } else if (DI->getType()->isInstantiationDependentType()) { - DI = SemaRef.SubstType(DI, TemplateArgs, - D->getLocation(), D->getDeclName()); + DI = SemaRef.SubstType(DI, TemplateArgs, EarlySubstitution, + D->getLocation(), D->getDeclName(), + /*AllowDeducedTST=*/false); if (!DI) { DI = D->getTypeSourceInfo(); Invalid = true; @@ -1298,8 +1333,8 @@ SemaRef.Context, Owner, D->getLocation(), D->getDeclName(), DI->getType(), DI, D->getBeginLoc(), D->getGetterId(), D->getSetterId()); - SemaRef.InstantiateAttrs(TemplateArgs, D, Property, LateAttrs, - StartingScope); + SemaRef.InstantiateAttrs(TemplateArgs, EarlySubstitution, D, Property, + LateAttrs, StartingScope); if (Invalid) Property->setInvalidDecl(); @@ -1316,8 +1351,9 @@ int i = 0; for (auto *PI : D->chain()) { - NamedDecl *Next = SemaRef.FindInstantiatedDecl(D->getLocation(), PI, - TemplateArgs); + NamedDecl *Next = SemaRef.FindInstantiatedDecl( + D->getLocation(), PI, TemplateArgs, EarlySubstitution, + /*FindingInstantiatedContext=*/false); if (!Next) return nullptr; @@ -1350,8 +1386,9 @@ if (D->isUnsupportedFriend()) { InstTy = Ty; } else { - InstTy = SemaRef.SubstType(Ty, TemplateArgs, - D->getLocation(), DeclarationName()); + InstTy = SemaRef.SubstType(Ty, TemplateArgs, EarlySubstitution, + D->getLocation(), DeclarationName(), + /*AllowDeducedTST=*/false); } if (!InstTy) return nullptr; @@ -1393,8 +1430,8 @@ EnterExpressionEvaluationContext Unevaluated( SemaRef, Sema::ExpressionEvaluationContext::ConstantEvaluated); - ExprResult InstantiatedAssertExpr - = SemaRef.SubstExpr(AssertExpr, TemplateArgs); + ExprResult InstantiatedAssertExpr = + SemaRef.SubstExpr(AssertExpr, TemplateArgs, EarlySubstitution); if (InstantiatedAssertExpr.isInvalid()) return nullptr; @@ -1408,9 +1445,9 @@ Decl *TemplateDeclInstantiator::VisitEnumDecl(EnumDecl *D) { EnumDecl *PrevDecl = nullptr; if (EnumDecl *PatternPrev = getPreviousDeclForInstantiation(D)) { - NamedDecl *Prev = SemaRef.FindInstantiatedDecl(D->getLocation(), - PatternPrev, - TemplateArgs); + NamedDecl *Prev = SemaRef.FindInstantiatedDecl( + D->getLocation(), PatternPrev, TemplateArgs, EarlySubstitution, + /*FindingInstantiatedContext=*/false); if (!Prev) return nullptr; PrevDecl = cast(Prev); } @@ -1425,8 +1462,9 @@ // has been explicitly set by the user. Perform substitution on it before // moving on. SourceLocation UnderlyingLoc = TI->getTypeLoc().getBeginLoc(); - TypeSourceInfo *NewTI = SemaRef.SubstType(TI, TemplateArgs, UnderlyingLoc, - DeclarationName()); + TypeSourceInfo *NewTI = SemaRef.SubstType( + TI, TemplateArgs, EarlySubstitution, UnderlyingLoc, DeclarationName(), + /*AllowDeducedTST=*/false); if (!NewTI || SemaRef.CheckEnumUnderlyingType(NewTI)) Enum->setIntegerType(SemaRef.Context.IntTy); else @@ -1438,7 +1476,9 @@ } } - SemaRef.InstantiateAttrs(TemplateArgs, D, Enum); + SemaRef.InstantiateAttrs(TemplateArgs, EarlySubstitution, D, Enum, + /*LateAttrs=*/nullptr, + /*OuterMostScope=*/nullptr); Enum->setInstantiationOfMemberEnum(D, TSK_ImplicitInstantiation); Enum->setAccess(D->getAccess()); @@ -1463,8 +1503,8 @@ if (TypeSourceInfo *TI = Def->getIntegerTypeSourceInfo()) { SourceLocation UnderlyingLoc = TI->getTypeLoc().getBeginLoc(); QualType DefnUnderlying = - SemaRef.SubstType(TI->getType(), TemplateArgs, - UnderlyingLoc, DeclarationName()); + SemaRef.SubstType(TI->getType(), TemplateArgs, EarlySubstitution, + UnderlyingLoc, DeclarationName()); SemaRef.CheckEnumRedeclaration(Def->getLocation(), Def->isScoped(), DefnUnderlying, /*IsFixed=*/true, Enum); } @@ -1503,7 +1543,7 @@ EnterExpressionEvaluationContext Unevaluated( SemaRef, Sema::ExpressionEvaluationContext::ConstantEvaluated); - Value = SemaRef.SubstExpr(UninstValue, TemplateArgs); + Value = SemaRef.SubstExpr(UninstValue, TemplateArgs, EarlySubstitution); } // Drop the initial value and continue. @@ -1525,7 +1565,9 @@ } if (EnumConst) { - SemaRef.InstantiateAttrs(TemplateArgs, EC, EnumConst); + SemaRef.InstantiateAttrs(TemplateArgs, EarlySubstitution, EC, EnumConst, + /*LateAttrs=*/nullptr, + /*OuterMostScope=*/nullptr); EnumConst->setAccess(Enum->getAccess()); Enum->addDecl(EnumConst); @@ -1572,8 +1614,8 @@ // the new declaration in the appropriate context. NestedNameSpecifierLoc QualifierLoc = Pattern->getQualifierLoc(); if (QualifierLoc) { - QualifierLoc = SemaRef.SubstNestedNameSpecifierLoc(QualifierLoc, - TemplateArgs); + QualifierLoc = SemaRef.SubstNestedNameSpecifierLoc( + QualifierLoc, TemplateArgs, EarlySubstitution); if (!QualifierLoc) return nullptr; } @@ -1604,7 +1646,7 @@ } else { DC = SemaRef.FindInstantiatedContext(Pattern->getLocation(), Pattern->getDeclContext(), - TemplateArgs); + TemplateArgs, EarlySubstitution); } // Look for a previous declaration of the template in the owning @@ -1652,8 +1694,8 @@ if (QualifierLoc) RecordInst->setQualifierInfo(QualifierLoc); - SemaRef.InstantiateAttrsForDecl(TemplateArgs, Pattern, RecordInst, LateAttrs, - StartingScope); + SemaRef.InstantiateAttrsForDecl(TemplateArgs, EarlySubstitution, Pattern, + RecordInst, LateAttrs, StartingScope); ClassTemplateDecl *Inst = ClassTemplateDecl::Create(SemaRef.Context, DC, D->getLocation(), @@ -1871,9 +1913,9 @@ Decl *TemplateDeclInstantiator::VisitCXXRecordDecl(CXXRecordDecl *D) { CXXRecordDecl *PrevDecl = nullptr; if (CXXRecordDecl *PatternPrev = getPreviousDeclForInstantiation(D)) { - NamedDecl *Prev = SemaRef.FindInstantiatedDecl(D->getLocation(), - PatternPrev, - TemplateArgs); + NamedDecl *Prev = SemaRef.FindInstantiatedDecl( + D->getLocation(), PatternPrev, TemplateArgs, EarlySubstitution, + /*FindingInstantiatedContext=*/false); if (!Prev) return nullptr; PrevDecl = cast(Prev); } @@ -1898,8 +1940,8 @@ if (SubstQualifier(D, Record)) return nullptr; - SemaRef.InstantiateAttrsForDecl(TemplateArgs, D, Record, LateAttrs, - StartingScope); + SemaRef.InstantiateAttrsForDecl(TemplateArgs, EarlySubstitution, D, Record, + LateAttrs, StartingScope); Record->setImplicit(D->isImplicit()); // FIXME: Check against AS_none is an ugly hack to work around the issue that @@ -1944,13 +1986,14 @@ Sema::LocalEagerInstantiationScope LocalInstantiations(SemaRef); SemaRef.InstantiateClass(D->getLocation(), Record, D, TemplateArgs, - TSK_ImplicitInstantiation, + EarlySubstitution, TSK_ImplicitInstantiation, /*Complain=*/true); // For nested local classes, we will instantiate the members when we // reach the end of the outermost (non-nested) local class. if (!D->isCXXClassMember()) SemaRef.InstantiateClassMembers(D->getLocation(), Record, TemplateArgs, + EarlySubstitution, TSK_ImplicitInstantiation); // This class may have local implicit instantiations that need to be @@ -2025,8 +2068,9 @@ ExplicitSpecifier InstantiatedExplicitSpecifier; if (auto *DGuide = dyn_cast(D)) { - InstantiatedExplicitSpecifier = instantiateExplicitSpecifier( - SemaRef, TemplateArgs, DGuide->getExplicitSpecifier(), DGuide); + InstantiatedExplicitSpecifier = + instantiateExplicitSpecifier(SemaRef, TemplateArgs, EarlySubstitution, + DGuide->getExplicitSpecifier(), DGuide); if (InstantiatedExplicitSpecifier.isInvalid()) return nullptr; } @@ -2056,8 +2100,8 @@ NestedNameSpecifierLoc QualifierLoc = D->getQualifierLoc(); if (QualifierLoc) { - QualifierLoc = SemaRef.SubstNestedNameSpecifierLoc(QualifierLoc, - TemplateArgs); + QualifierLoc = SemaRef.SubstNestedNameSpecifierLoc( + QualifierLoc, TemplateArgs, EarlySubstitution); if (!QualifierLoc) return nullptr; } @@ -2067,8 +2111,8 @@ if (TrailingRequiresClause) { EnterExpressionEvaluationContext ConstantEvaluated( SemaRef, Sema::ExpressionEvaluationContext::Unevaluated); - ExprResult SubstRC = SemaRef.SubstExpr(TrailingRequiresClause, - TemplateArgs); + ExprResult SubstRC = SemaRef.SubstExpr(TrailingRequiresClause, TemplateArgs, + EarlySubstitution); if (SubstRC.isInvalid()) return nullptr; TrailingRequiresClause = SubstRC.get(); @@ -2090,11 +2134,11 @@ if (!DC) return nullptr; } else { DC = SemaRef.FindInstantiatedContext(D->getLocation(), D->getDeclContext(), - TemplateArgs); + TemplateArgs, EarlySubstitution); } - DeclarationNameInfo NameInfo - = SemaRef.SubstDeclarationNameInfo(D->getNameInfo(), TemplateArgs); + DeclarationNameInfo NameInfo = SemaRef.SubstDeclarationNameInfo( + D->getNameInfo(), TemplateArgs, EarlySubstitution); if (FunctionRewriteKind != RewriteKind::None) adjustForRewrite(FunctionRewriteKind, D, T, TInfo, NameInfo); @@ -2210,14 +2254,15 @@ TemplateArgumentListInfo ExplicitArgs(Info->getLAngleLoc(), Info->getRAngleLoc()); if (SemaRef.SubstTemplateArguments(Info->arguments(), TemplateArgs, - ExplicitArgs)) + EarlySubstitution, ExplicitArgs)) return nullptr; // Map the candidate templates to their instantiations. for (unsigned I = 0, E = Info->getNumTemplates(); I != E; ++I) { - Decl *Temp = SemaRef.FindInstantiatedDecl(D->getLocation(), - Info->getTemplate(I), - TemplateArgs); + Decl *Temp = + SemaRef.FindInstantiatedDecl(D->getLocation(), Info->getTemplate(I), + TemplateArgs, EarlySubstitution, + /*FindingInstantiatedContext=*/false); if (!Temp) return nullptr; Previous.addDecl(cast(Temp)); @@ -2238,7 +2283,7 @@ TemplateArgumentListInfo ExplicitArgs(Info->getLAngleLoc(), Info->getRAngleLoc()); if (SemaRef.SubstTemplateArguments(Info->arguments(), TemplateArgs, - ExplicitArgs)) + EarlySubstitution, ExplicitArgs)) return nullptr; if (SemaRef.CheckFunctionTemplateSpecialization(Function, @@ -2370,7 +2415,7 @@ } ExplicitSpecifier InstantiatedExplicitSpecifier = - instantiateExplicitSpecifier(SemaRef, TemplateArgs, + instantiateExplicitSpecifier(SemaRef, TemplateArgs, EarlySubstitution, ExplicitSpecifier::getFromDecl(D), D); if (InstantiatedExplicitSpecifier.isInvalid()) return nullptr; @@ -2414,8 +2459,8 @@ NestedNameSpecifierLoc QualifierLoc = D->getQualifierLoc(); if (QualifierLoc) { - QualifierLoc = SemaRef.SubstNestedNameSpecifierLoc(QualifierLoc, - TemplateArgs); + QualifierLoc = SemaRef.SubstNestedNameSpecifierLoc( + QualifierLoc, TemplateArgs, EarlySubstitution); if (!QualifierLoc) return nullptr; } @@ -2428,8 +2473,8 @@ auto *ThisContext = dyn_cast_or_null(Owner); Sema::CXXThisScopeRAII ThisScope(SemaRef, ThisContext, D->getMethodQualifiers(), ThisContext); - ExprResult SubstRC = SemaRef.SubstExpr(TrailingRequiresClause, - TemplateArgs); + ExprResult SubstRC = SemaRef.SubstExpr(TrailingRequiresClause, TemplateArgs, + EarlySubstitution); if (SubstRC.isInvalid()) return nullptr; TrailingRequiresClause = SubstRC.get(); @@ -2447,15 +2492,15 @@ if (DC && SemaRef.RequireCompleteDeclContext(SS, DC)) return nullptr; } else { - DC = SemaRef.FindInstantiatedContext(D->getLocation(), - D->getDeclContext(), - TemplateArgs); + DC = + SemaRef.FindInstantiatedContext(D->getLocation(), D->getDeclContext(), + TemplateArgs, EarlySubstitution); } if (!DC) return nullptr; } - DeclarationNameInfo NameInfo - = SemaRef.SubstDeclarationNameInfo(D->getNameInfo(), TemplateArgs); + DeclarationNameInfo NameInfo = SemaRef.SubstDeclarationNameInfo( + D->getNameInfo(), TemplateArgs, EarlySubstitution); if (FunctionRewriteKind != RewriteKind::None) adjustForRewrite(FunctionRewriteKind, D, T, TInfo, NameInfo); @@ -2575,14 +2620,15 @@ TemplateArgumentListInfo ExplicitArgs(Info->getLAngleLoc(), Info->getRAngleLoc()); if (SemaRef.SubstTemplateArguments(Info->arguments(), TemplateArgs, - ExplicitArgs)) + EarlySubstitution, ExplicitArgs)) return nullptr; // Map the candidate templates to their instantiations. for (unsigned I = 0, E = Info->getNumTemplates(); I != E; ++I) { - Decl *Temp = SemaRef.FindInstantiatedDecl(D->getLocation(), - Info->getTemplate(I), - TemplateArgs); + Decl *Temp = + SemaRef.FindInstantiatedDecl(D->getLocation(), Info->getTemplate(I), + TemplateArgs, EarlySubstitution, + /*FindingInstantiatedContext=*/false); if (!Temp) return nullptr; Previous.addDecl(cast(Temp)); @@ -2602,7 +2648,7 @@ TemplateArgumentListInfo ExplicitArgs(Info->getLAngleLoc(), Info->getRAngleLoc()); if (SemaRef.SubstTemplateArguments(Info->arguments(), TemplateArgs, - ExplicitArgs)) + EarlySubstitution, ExplicitArgs)) return nullptr; if (SemaRef.CheckFunctionTemplateSpecialization(Method, @@ -2717,8 +2763,9 @@ } Decl *TemplateDeclInstantiator::VisitParmVarDecl(ParmVarDecl *D) { - return SemaRef.SubstParmVarDecl(D, TemplateArgs, /*indexAdjustment*/ 0, None, - /*ExpectParameterPack=*/ false); + return SemaRef.SubstParmVarDecl(D, TemplateArgs, EarlySubstitution, + /*indexAdjustment*/ 0, None, + /*ExpectParameterPack=*/false); } Decl *TemplateDeclInstantiator::VisitTemplateTypeParmDecl( @@ -2757,8 +2804,8 @@ TemplateTypeParmDecl *Inst = TemplateTypeParmDecl::Create( SemaRef.Context, Owner, D->getBeginLoc(), D->getLocation(), - D->getDepth() - TemplateArgs.getNumSubstitutedLevels(), D->getIndex(), - D->getIdentifier(), D->wasDeclaredWithTypename(), D->isParameterPack(), + getNewDepth(D->getDepth()), D->getIndex(), D->getIdentifier(), + D->wasDeclaredWithTypename(), D->isParameterPack(), D->hasTypeConstraint(), NumExpanded); Inst->setAccess(AS_public); @@ -2771,14 +2818,16 @@ // TODO: Concepts: do not instantiate the constraint (delayed constraint // substitution) - if (SemaRef.SubstTypeConstraint(Inst, TC, TemplateArgs)) + if (SemaRef.SubstTypeConstraint(Inst, TC, TemplateArgs, + EarlySubstitution)) return nullptr; } } if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited()) { - TypeSourceInfo *InstantiatedDefaultArg = - SemaRef.SubstType(D->getDefaultArgumentInfo(), TemplateArgs, - D->getDefaultArgumentLoc(), D->getDeclName()); + TypeSourceInfo *InstantiatedDefaultArg = SemaRef.SubstType( + D->getDefaultArgumentInfo(), TemplateArgs, EarlySubstitution, + D->getDefaultArgumentLoc(), D->getDeclName(), + /*AllowDeducedTST=*/false); if (InstantiatedDefaultArg) Inst->setDefaultArgument(InstantiatedDefaultArg); } @@ -2807,9 +2856,10 @@ ExpandedParameterPackTypes.reserve(D->getNumExpansionTypes()); ExpandedParameterPackTypesAsWritten.reserve(D->getNumExpansionTypes()); for (unsigned I = 0, N = D->getNumExpansionTypes(); I != N; ++I) { - TypeSourceInfo *NewDI = - SemaRef.SubstType(D->getExpansionTypeSourceInfo(I), TemplateArgs, - D->getLocation(), D->getDeclName()); + TypeSourceInfo *NewDI = SemaRef.SubstType( + D->getExpansionTypeSourceInfo(I), TemplateArgs, EarlySubstitution, + D->getLocation(), D->getDeclName(), + /*AllowDeducedTST=*/false); if (!NewDI) return nullptr; @@ -2852,9 +2902,9 @@ if (Expand) { for (unsigned I = 0; I != *NumExpansions; ++I) { Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(SemaRef, I); - TypeSourceInfo *NewDI = SemaRef.SubstType(Pattern, TemplateArgs, - D->getLocation(), - D->getDeclName()); + TypeSourceInfo *NewDI = + SemaRef.SubstType(Pattern, TemplateArgs, EarlySubstitution, + D->getLocation(), D->getDeclName()); if (!NewDI) return nullptr; @@ -2877,9 +2927,9 @@ // We cannot fully expand the pack expansion now, so substitute into the // pattern and create a new pack expansion type. Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(SemaRef, -1); - TypeSourceInfo *NewPattern = SemaRef.SubstType(Pattern, TemplateArgs, - D->getLocation(), - D->getDeclName()); + TypeSourceInfo *NewPattern = + SemaRef.SubstType(Pattern, TemplateArgs, EarlySubstitution, + D->getLocation(), D->getDeclName()); if (!NewPattern) return nullptr; @@ -2893,8 +2943,10 @@ } } else { // Simple case: substitution into a parameter that is not a parameter pack. - DI = SemaRef.SubstType(D->getTypeSourceInfo(), TemplateArgs, - D->getLocation(), D->getDeclName()); + DI = + SemaRef.SubstType(D->getTypeSourceInfo(), TemplateArgs, + EarlySubstitution, D->getLocation(), D->getDeclName(), + /*AllowDeducedTST=*/false); if (!DI) return nullptr; @@ -2910,14 +2962,13 @@ if (IsExpandedParameterPack) Param = NonTypeTemplateParmDecl::Create( SemaRef.Context, Owner, D->getInnerLocStart(), D->getLocation(), - D->getDepth() - TemplateArgs.getNumSubstitutedLevels(), - D->getPosition(), D->getIdentifier(), T, DI, ExpandedParameterPackTypes, - ExpandedParameterPackTypesAsWritten); + getNewDepth(D->getDepth()), D->getPosition(), D->getIdentifier(), T, DI, + ExpandedParameterPackTypes, ExpandedParameterPackTypesAsWritten); else Param = NonTypeTemplateParmDecl::Create( SemaRef.Context, Owner, D->getInnerLocStart(), D->getLocation(), - D->getDepth() - TemplateArgs.getNumSubstitutedLevels(), - D->getPosition(), D->getIdentifier(), T, D->isParameterPack(), DI); + getNewDepth(D->getDepth()), D->getPosition(), D->getIdentifier(), T, + D->isParameterPack(), DI); if (AutoTypeLoc AutoLoc = DI->getTypeLoc().getContainedAutoTypeLoc()) if (AutoLoc.isConstrained()) @@ -2937,7 +2988,8 @@ if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited()) { EnterExpressionEvaluationContext ConstantEvaluated( SemaRef, Sema::ExpressionEvaluationContext::ConstantEvaluated); - ExprResult Value = SemaRef.SubstExpr(D->getDefaultArgument(), TemplateArgs); + ExprResult Value = SemaRef.SubstExpr(D->getDefaultArgument(), TemplateArgs, + EarlySubstitution); if (!Value.isInvalid()) Param->setDefaultArgument(Value.get()); } @@ -3050,22 +3102,21 @@ TemplateTemplateParmDecl *Param; if (IsExpandedParameterPack) Param = TemplateTemplateParmDecl::Create( - SemaRef.Context, Owner, D->getLocation(), - D->getDepth() - TemplateArgs.getNumSubstitutedLevels(), + SemaRef.Context, Owner, D->getLocation(), getNewDepth(D->getDepth()), D->getPosition(), D->getIdentifier(), InstParams, ExpandedParams); else Param = TemplateTemplateParmDecl::Create( - SemaRef.Context, Owner, D->getLocation(), - D->getDepth() - TemplateArgs.getNumSubstitutedLevels(), + SemaRef.Context, Owner, D->getLocation(), getNewDepth(D->getDepth()), D->getPosition(), D->isParameterPack(), D->getIdentifier(), InstParams); if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited()) { NestedNameSpecifierLoc QualifierLoc = D->getDefaultArgument().getTemplateQualifierLoc(); - QualifierLoc = - SemaRef.SubstNestedNameSpecifierLoc(QualifierLoc, TemplateArgs); + QualifierLoc = SemaRef.SubstNestedNameSpecifierLoc( + QualifierLoc, TemplateArgs, EarlySubstitution); TemplateName TName = SemaRef.SubstTemplateName( QualifierLoc, D->getDefaultArgument().getArgument().getAsTemplate(), - D->getDefaultArgument().getTemplateNameLoc(), TemplateArgs); + D->getDefaultArgument().getTemplateNameLoc(), TemplateArgs, + EarlySubstitution); if (!TName.isNull()) Param->setDefaultArgument( SemaRef.Context, @@ -3125,7 +3176,8 @@ SemaRef.Context, Owner, EmptyD->getLocation(), EmptyD->getDeclName()); } else { InstTarget = cast_or_null(SemaRef.FindInstantiatedDecl( - Shadow->getLocation(), OldTarget, TemplateArgs)); + Shadow->getLocation(), OldTarget, TemplateArgs, EarlySubstitution, + /*FindingInstantiatedContext=*/false)); } if (!InstTarget) return nullptr; @@ -3137,7 +3189,8 @@ if (UsingShadowDecl *OldPrev = getPreviousDeclForInstantiation(Shadow)) PrevDecl = cast_or_null(SemaRef.FindInstantiatedDecl( - Shadow->getLocation(), OldPrev, TemplateArgs)); + Shadow->getLocation(), OldPrev, TemplateArgs, EarlySubstitution, + /*FindingInstantiatedContext=*/false)); UsingShadowDecl *InstShadow = SemaRef.BuildUsingShadowDecl( /*Scope*/ nullptr, Inst, InstTarget, PrevDecl); @@ -3160,9 +3213,8 @@ // template struct t; // Here, in using s1::f1, s1 refers to t::s1; // we need to substitute for t::s1. - NestedNameSpecifierLoc QualifierLoc - = SemaRef.SubstNestedNameSpecifierLoc(D->getQualifierLoc(), - TemplateArgs); + NestedNameSpecifierLoc QualifierLoc = SemaRef.SubstNestedNameSpecifierLoc( + D->getQualifierLoc(), TemplateArgs, EarlySubstitution); if (!QualifierLoc) return nullptr; @@ -3224,7 +3276,8 @@ Decl *TemplateDeclInstantiator::VisitUsingEnumDecl(UsingEnumDecl *D) { // Cannot be a dependent type, but still could be an instantiation EnumDecl *EnumD = cast_or_null(SemaRef.FindInstantiatedDecl( - D->getLocation(), D->getEnumDecl(), TemplateArgs)); + D->getLocation(), D->getEnumDecl(), TemplateArgs, EarlySubstitution, + /*FindingInstantiatedContext=*/false)); if (SemaRef.RequireCompleteEnumDecl(EnumD, EnumD->getLocation())) return nullptr; @@ -3326,17 +3379,16 @@ UnresolvedUsingTypenameDecl *TD = dyn_cast(D); SourceLocation TypenameLoc = TD ? TD->getTypenameLoc() : SourceLocation(); - NestedNameSpecifierLoc QualifierLoc - = SemaRef.SubstNestedNameSpecifierLoc(D->getQualifierLoc(), - TemplateArgs); + NestedNameSpecifierLoc QualifierLoc = SemaRef.SubstNestedNameSpecifierLoc( + D->getQualifierLoc(), TemplateArgs, EarlySubstitution); if (!QualifierLoc) return nullptr; CXXScopeSpec SS; SS.Adopt(QualifierLoc); - DeclarationNameInfo NameInfo - = SemaRef.SubstDeclarationNameInfo(D->getNameInfo(), TemplateArgs); + DeclarationNameInfo NameInfo = SemaRef.SubstDeclarationNameInfo( + D->getNameInfo(), TemplateArgs, EarlySubstitution); // Produce a pack expansion only if we're not instantiating a particular // slice of a pack expansion. @@ -3352,7 +3404,9 @@ ParsedAttributesView(), /*IsInstantiation*/ true, IsUsingIfExists); if (UD) { - SemaRef.InstantiateAttrs(TemplateArgs, D, UD); + SemaRef.InstantiateAttrs(TemplateArgs, EarlySubstitution, D, UD, + /*LateAttrs=*/nullptr, + /*OuterMostScope=*/nullptr); SemaRef.Context.setInstantiatedFromUsingDecl(UD, D); } @@ -3377,8 +3431,9 @@ Decl *TemplateDeclInstantiator::VisitUsingPackDecl(UsingPackDecl *D) { SmallVector Expansions; for (auto *UD : D->expansions()) { - if (NamedDecl *NewUD = - SemaRef.FindInstantiatedDecl(D->getLocation(), UD, TemplateArgs)) + if (NamedDecl *NewUD = SemaRef.FindInstantiatedDecl( + D->getLocation(), UD, TemplateArgs, EarlySubstitution, + /*FindingInstantiatedContext=*/false)) Expansions.push_back(NewUD); else return nullptr; @@ -3401,7 +3456,7 @@ OMPThreadPrivateDecl *D) { SmallVector Vars; for (auto *I : D->varlists()) { - Expr *Var = SemaRef.SubstExpr(I, TemplateArgs).get(); + Expr *Var = SemaRef.SubstExpr(I, TemplateArgs, EarlySubstitution).get(); assert(isa(Var) && "threadprivate arg is not a DeclRefExpr"); Vars.push_back(Var); } @@ -3418,7 +3473,7 @@ Decl *TemplateDeclInstantiator::VisitOMPAllocateDecl(OMPAllocateDecl *D) { SmallVector Vars; for (auto *I : D->varlists()) { - Expr *Var = SemaRef.SubstExpr(I, TemplateArgs).get(); + Expr *Var = SemaRef.SubstExpr(I, TemplateArgs, EarlySubstitution).get(); assert(isa(Var) && "allocate arg is not a DeclRefExpr"); Vars.push_back(Var); } @@ -3427,13 +3482,15 @@ for (OMPClause *C : D->clauselists()) { OMPClause *IC = nullptr; if (auto *AC = dyn_cast(C)) { - ExprResult NewE = SemaRef.SubstExpr(AC->getAllocator(), TemplateArgs); + ExprResult NewE = SemaRef.SubstExpr(AC->getAllocator(), TemplateArgs, + EarlySubstitution); if (!NewE.isUsable()) continue; IC = SemaRef.ActOnOpenMPAllocatorClause( NewE.get(), AC->getBeginLoc(), AC->getLParenLoc(), AC->getEndLoc()); } else if (auto *AC = dyn_cast(C)) { - ExprResult NewE = SemaRef.SubstExpr(AC->getAlignment(), TemplateArgs); + ExprResult NewE = SemaRef.SubstExpr(AC->getAlignment(), TemplateArgs, + EarlySubstitution); if (!NewE.isUsable()) continue; IC = SemaRef.ActOnOpenMPAlignClause(NewE.get(), AC->getBeginLoc(), @@ -3467,9 +3524,9 @@ QualType SubstReductionType; if (RequiresInstantiation) { SubstReductionType = SemaRef.ActOnOpenMPDeclareReductionType( - D->getLocation(), - ParsedType::make(SemaRef.SubstType( - D->getType(), TemplateArgs, D->getLocation(), DeclarationName()))); + D->getLocation(), ParsedType::make(SemaRef.SubstType( + D->getType(), TemplateArgs, EarlySubstitution, + D->getLocation(), DeclarationName()))); } else { SubstReductionType = D->getType(); } @@ -3507,7 +3564,8 @@ auto *ThisContext = dyn_cast_or_null(Owner); Sema::CXXThisScopeRAII ThisScope(SemaRef, ThisContext, Qualifiers(), ThisContext); - SubstCombiner = SemaRef.SubstExpr(Combiner, TemplateArgs).get(); + SubstCombiner = + SemaRef.SubstExpr(Combiner, TemplateArgs, EarlySubstitution).get(); SemaRef.ActOnOpenMPDeclareReductionCombinerEnd(NewDRD, SubstCombiner); } // Initializers instantiation sequence. @@ -3521,14 +3579,15 @@ cast(D->getInitPriv())->getDecl(), cast(NewDRD->getInitPriv())->getDecl()); if (D->getInitializerKind() == OMPDeclareReductionDecl::CallInit) { - SubstInitializer = SemaRef.SubstExpr(Init, TemplateArgs).get(); + SubstInitializer = + SemaRef.SubstExpr(Init, TemplateArgs, EarlySubstitution).get(); } else { auto *OldPrivParm = cast(cast(D->getInitPriv())->getDecl()); IsCorrect = IsCorrect && OldPrivParm->hasInit(); if (IsCorrect) SemaRef.InstantiateVariableInitializer(OmpPrivParm, OldPrivParm, - TemplateArgs); + TemplateArgs, EarlySubstitution); } SemaRef.ActOnOpenMPDeclareReductionInitializerEnd(NewDRD, SubstInitializer, OmpPrivParm); @@ -3557,9 +3616,9 @@ DeclarationName VN = D->getVarName(); if (RequiresInstantiation) { SubstMapperTy = SemaRef.ActOnOpenMPDeclareMapperType( - D->getLocation(), - ParsedType::make(SemaRef.SubstType(D->getType(), TemplateArgs, - D->getLocation(), VN))); + D->getLocation(), ParsedType::make(SemaRef.SubstType( + D->getType(), TemplateArgs, EarlySubstitution, + D->getLocation(), VN))); } else { SubstMapperTy = D->getType(); } @@ -3592,7 +3651,7 @@ auto *OldC = cast(C); SmallVector NewVars; for (Expr *OE : OldC->varlists()) { - Expr *NE = SemaRef.SubstExpr(OE, TemplateArgs).get(); + Expr *NE = SemaRef.SubstExpr(OE, TemplateArgs, EarlySubstitution).get(); if (!NE) { IsCorrect = false; break; @@ -3603,11 +3662,11 @@ break; NestedNameSpecifierLoc NewQualifierLoc = SemaRef.SubstNestedNameSpecifierLoc(OldC->getMapperQualifierLoc(), - TemplateArgs); + TemplateArgs, EarlySubstitution); CXXScopeSpec SS; SS.Adopt(NewQualifierLoc); - DeclarationNameInfo NewNameInfo = - SemaRef.SubstDeclarationNameInfo(OldC->getMapperIdInfo(), TemplateArgs); + DeclarationNameInfo NewNameInfo = SemaRef.SubstDeclarationNameInfo( + OldC->getMapperIdInfo(), TemplateArgs, EarlySubstitution); OMPVarListLocTy Locs(OldC->getBeginLoc(), OldC->getLParenLoc(), OldC->getEndLoc()); OMPClause *NewC = SemaRef.ActOnOpenMPMapClause( @@ -3667,7 +3726,8 @@ // of the class template. ClassTemplateDecl *InstClassTemplate = cast_or_null(SemaRef.FindInstantiatedDecl( - D->getLocation(), ClassTemplate, TemplateArgs)); + D->getLocation(), ClassTemplate, TemplateArgs, EarlySubstitution, + /*FindingInstantiatedContext=*/false)); if (!InstClassTemplate) return nullptr; @@ -3680,7 +3740,8 @@ SmallVector ArgLocs; for (unsigned I = 0; I != Loc.getNumArgs(); ++I) ArgLocs.push_back(Loc.getArgLoc(I)); - if (SemaRef.SubstTemplateArguments(ArgLocs, TemplateArgs, InstTemplateArgs)) + if (SemaRef.SubstTemplateArguments(ArgLocs, TemplateArgs, EarlySubstitution, + InstTemplateArgs)) return nullptr; // Check that the template argument list is well-formed for this @@ -3779,7 +3840,7 @@ // FIXME: This is wrong in standard C++. if (D->isThisDeclarationADefinition() && SemaRef.InstantiateClass(D->getLocation(), InstD, D, TemplateArgs, - TSK_ImplicitInstantiation, + EarlySubstitution, TSK_ImplicitInstantiation, /*Complain=*/true)) return nullptr; @@ -3796,7 +3857,8 @@ VarTemplateDecl *InstVarTemplate = cast_or_null(SemaRef.FindInstantiatedDecl( - D->getLocation(), VarTemplate, TemplateArgs)); + D->getLocation(), VarTemplate, TemplateArgs, EarlySubstitution, + /*FindingInstantiatedContext=*/false)); if (!InstVarTemplate) return nullptr; @@ -3806,7 +3868,7 @@ VarTemplateArgsInfo.setRAngleLoc(TemplateArgsInfo.getRAngleLoc()); if (SemaRef.SubstTemplateArguments(TemplateArgsInfo.arguments(), TemplateArgs, - VarTemplateArgsInfo)) + EarlySubstitution, VarTemplateArgsInfo)) return nullptr; // Check that the template argument list is well-formed for this template. @@ -3842,8 +3904,9 @@ // Do substitution on the type of the declaration TypeSourceInfo *DI = - SemaRef.SubstType(D->getTypeSourceInfo(), TemplateArgs, - D->getTypeSpecStartLoc(), D->getDeclName()); + SemaRef.SubstType(D->getTypeSourceInfo(), TemplateArgs, EarlySubstitution, + D->getTypeSpecStartLoc(), D->getDeclName(), + /*AllowDeducedTST=*/false); if (!DI) return nullptr; @@ -3871,8 +3934,9 @@ if (SubstQualifier(D, Var)) return nullptr; - SemaRef.BuildVariableInstantiation(Var, D, TemplateArgs, LateAttrs, Owner, - StartingScope, false, PrevDecl); + SemaRef.BuildVariableInstantiation(Var, D, TemplateArgs, EarlySubstitution, + LateAttrs, Owner, StartingScope, false, + PrevDecl); return Var; } @@ -3907,15 +3971,16 @@ } Decl *Sema::SubstDecl(Decl *D, DeclContext *Owner, - const MultiLevelTemplateArgumentList &TemplateArgs) { - TemplateDeclInstantiator Instantiator(*this, Owner, TemplateArgs); + const MultiLevelTemplateArgumentList &TemplateArgs, + bool EarlySubstitution) { + TemplateDeclInstantiator Instantiator(*this, Owner, TemplateArgs, + EarlySubstitution); if (D->isInvalidDecl()) return nullptr; Decl *SubstD; - runWithSufficientStackSpace(D->getLocation(), [&] { - SubstD = Instantiator.Visit(D); - }); + runWithSufficientStackSpace(D->getLocation(), + [&] { SubstD = Instantiator.Visit(D); }); return SubstD; } @@ -3963,7 +4028,8 @@ MultiLevelTemplateArgumentList NoTemplateArgs; NoTemplateArgs.setKind(TemplateSubstitutionKind::Rewrite); NoTemplateArgs.addOuterRetainedLevels(RD->getTemplateDepth()); - TemplateDeclInstantiator Instantiator(*this, RD, NoTemplateArgs); + TemplateDeclInstantiator Instantiator(*this, RD, NoTemplateArgs, + /*EarlySubstitution=*/false); Decl *R; if (auto *MD = dyn_cast(Spaceship)) { R = Instantiator.VisitCXXMethodDecl( @@ -4019,7 +4085,8 @@ if (Expr *E = L->getRequiresClause()) { EnterExpressionEvaluationContext ConstantEvaluated( SemaRef, Sema::ExpressionEvaluationContext::Unevaluated); - ExprResult Res = SemaRef.SubstExpr(E, TemplateArgs); + ExprResult Res = + SemaRef.SubstExpr(E, TemplateArgs, /*EarlySubstitution=*/false); if (Res.isInvalid() || !Res.isUsable()) { return nullptr; } @@ -4035,8 +4102,10 @@ TemplateParameterList * Sema::SubstTemplateParams(TemplateParameterList *Params, DeclContext *Owner, - const MultiLevelTemplateArgumentList &TemplateArgs) { - TemplateDeclInstantiator Instantiator(*this, Owner, TemplateArgs); + const MultiLevelTemplateArgumentList &TemplateArgs, + bool EarlySubstitution) { + TemplateDeclInstantiator Instantiator(*this, Owner, TemplateArgs, + EarlySubstitution); return Instantiator.SubstTemplateParams(Params); } @@ -4074,7 +4143,7 @@ TemplateArgumentListInfo InstTemplateArgs(TemplArgInfo->LAngleLoc, TemplArgInfo->RAngleLoc); if (SemaRef.SubstTemplateArguments(TemplArgInfo->arguments(), TemplateArgs, - InstTemplateArgs)) + EarlySubstitution, InstTemplateArgs)) return nullptr; // Check that the template argument list is well-formed for this @@ -4201,7 +4270,7 @@ TemplateArgumentListInfo InstTemplateArgs(TemplArgInfo->LAngleLoc, TemplArgInfo->RAngleLoc); if (SemaRef.SubstTemplateArguments(TemplArgInfo->arguments(), TemplateArgs, - InstTemplateArgs)) + EarlySubstitution, InstTemplateArgs)) return nullptr; // Check that the template argument list is well-formed for this @@ -4265,8 +4334,9 @@ // Do substitution on the type of the declaration TypeSourceInfo *DI = SemaRef.SubstType( - PartialSpec->getTypeSourceInfo(), TemplateArgs, - PartialSpec->getTypeSpecStartLoc(), PartialSpec->getDeclName()); + PartialSpec->getTypeSourceInfo(), TemplateArgs, EarlySubstitution, + PartialSpec->getTypeSpecStartLoc(), PartialSpec->getDeclName(), + /*AllowDeducedTST=*/false); if (!DI) return nullptr; @@ -4298,8 +4368,10 @@ // specializations. The instantiation of the initializer is not necessary. VarTemplate->AddPartialSpecialization(InstPartialSpec, /*InsertPos=*/nullptr); - SemaRef.BuildVariableInstantiation(InstPartialSpec, PartialSpec, TemplateArgs, - LateAttrs, Owner, StartingScope); + SemaRef.BuildVariableInstantiation( + InstPartialSpec, PartialSpec, TemplateArgs, EarlySubstitution, LateAttrs, + Owner, StartingScope, /*InstantiatingVarTemplate=*/false, + /*PrevVTSD=*/nullptr); return InstPartialSpec; } @@ -4318,11 +4390,9 @@ ThisTypeQuals = Method->getMethodQualifiers(); } - TypeSourceInfo *NewTInfo - = SemaRef.SubstFunctionDeclType(OldTInfo, TemplateArgs, - D->getTypeSpecStartLoc(), - D->getDeclName(), - ThisContext, ThisTypeQuals); + TypeSourceInfo *NewTInfo = SemaRef.SubstFunctionDeclType( + OldTInfo, TemplateArgs, EarlySubstitution, D->getTypeSpecStartLoc(), + D->getDeclName(), ThisContext, ThisTypeQuals); if (!NewTInfo) return nullptr; @@ -4398,8 +4468,8 @@ SmallVector ParamTypes; Sema::ExtParameterInfoBuilder ExtParamInfos; if (SemaRef.SubstParmTypes(D->getLocation(), D->parameters(), nullptr, - TemplateArgs, ParamTypes, &Params, - ExtParamInfos)) + TemplateArgs, EarlySubstitution, ParamTypes, + &Params, ExtParamInfos)) return nullptr; } @@ -4412,7 +4482,8 @@ bool Sema::addInstantiatedParametersToScope( FunctionDecl *Function, const FunctionDecl *PatternDecl, LocalInstantiationScope &Scope, - const MultiLevelTemplateArgumentList &TemplateArgs) { + const MultiLevelTemplateArgumentList &TemplateArgs, + bool EarlySubstitution) { unsigned FParamIdx = 0; for (unsigned I = 0, N = PatternDecl->getNumParams(); I != N; ++I) { const ParmVarDecl *PatternParam = PatternDecl->getParamDecl(I); @@ -4429,7 +4500,7 @@ // FIXME: Updating the type to work around this is at best fragile. if (!PatternDecl->getType()->isDependentType()) { QualType T = SubstType(PatternParam->getType(), TemplateArgs, - FunctionParam->getLocation(), + EarlySubstitution, FunctionParam->getLocation(), FunctionParam->getDeclName()); if (T.isNull()) return true; @@ -4453,9 +4524,9 @@ FunctionParam->setDeclName(PatternParam->getDeclName()); if (!PatternDecl->getType()->isDependentType()) { Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(*this, Arg); - QualType T = - SubstType(PatternType, TemplateArgs, FunctionParam->getLocation(), - FunctionParam->getDeclName()); + QualType T = SubstType(PatternType, TemplateArgs, EarlySubstitution, + FunctionParam->getLocation(), + FunctionParam->getDeclName()); if (T.isNull()) return true; FunctionParam->setType(T); @@ -4519,12 +4590,14 @@ FunctionDecl *Pattern = FD->getTemplateInstantiationPattern( /*ForDefinition*/ false); - if (addInstantiatedParametersToScope(FD, Pattern, Local, TemplateArgs)) + if (addInstantiatedParametersToScope(FD, Pattern, Local, TemplateArgs, + /*EarlySubstitution=*/false)) return true; runWithSufficientStackSpace(CallLoc, [&] { Result = SubstInitializer(UninstExpr, TemplateArgs, - /*DirectInit*/false); + /*EarlySubstitution=*/false, + /*DirectInit*/ false); }); } if (Result.isInvalid()) @@ -4592,13 +4665,14 @@ // we don't store enough information to map back to the friend declaration in // the template. FunctionDecl *Template = Proto->getExceptionSpecTemplate(); - if (addInstantiatedParametersToScope(Decl, Template, Scope, TemplateArgs)) { + if (addInstantiatedParametersToScope(Decl, Template, Scope, TemplateArgs, + /*EarlySubstitution=*/false)) { UpdateExceptionSpec(Decl, EST_None); return; } SubstExceptionSpec(Decl, Template->getType()->castAs(), - TemplateArgs); + TemplateArgs, /*EarlySubstitution=*/false); } /// Initializes the common fields of an instantiation function @@ -4676,7 +4750,7 @@ NewProto->getReturnType(), NewProto->getParamTypes(), EPI)); } else { Sema::ContextRAII SwitchContext(SemaRef, New); - SemaRef.SubstExceptionSpec(New, Proto, TemplateArgs); + SemaRef.SubstExceptionSpec(New, Proto, TemplateArgs, EarlySubstitution); } } @@ -4684,8 +4758,8 @@ const FunctionDecl *Definition = Tmpl; Tmpl->isDefined(Definition); - SemaRef.InstantiateAttrs(TemplateArgs, Definition, New, - LateAttrs, StartingScope); + SemaRef.InstantiateAttrs(TemplateArgs, /*EarlySubstitution=*/false, + Definition, New, LateAttrs, StartingScope); return false; } @@ -4720,8 +4794,9 @@ Lookups.reserve(DFI->getUnqualifiedLookups().size()); bool AnyChanged = false; for (DeclAccessPair DA : DFI->getUnqualifiedLookups()) { - NamedDecl *D = SemaRef.FindInstantiatedDecl(New->getLocation(), - DA.getDecl(), TemplateArgs); + NamedDecl *D = SemaRef.FindInstantiatedDecl( + New->getLocation(), DA.getDecl(), TemplateArgs, EarlySubstitution, + /*FindingInstantiatedContext=*/false); if (!D) return true; AnyChanged |= (D != DA.getDecl()); @@ -4745,10 +4820,9 @@ /// /// Usually this should not be used, and template argument deduction should be /// used in its place. -FunctionDecl * -Sema::InstantiateFunctionDeclaration(FunctionTemplateDecl *FTD, - const TemplateArgumentList *Args, - SourceLocation Loc) { +FunctionDecl *Sema::InstantiateFunctionDeclaration( + FunctionTemplateDecl *FTD, const TemplateArgumentList *Args, + bool EarlySubstitution, SourceLocation Loc) { FunctionDecl *FD = FTD->getTemplatedDecl(); sema::TemplateDeductionInfo Info(Loc); @@ -4761,7 +4835,8 @@ ContextRAII SavedContext(*this, FD); MultiLevelTemplateArgumentList MArgs(*Args); - return cast_or_null(SubstDecl(FD, FD->getParent(), MArgs)); + return cast_or_null( + SubstDecl(FD, FD->getParent(), MArgs, EarlySubstitution)); } /// Instantiate the definition of the given function from its @@ -5031,7 +5106,8 @@ // through evil use of alias templates. // FIXME: Is CurContext correct for this? Should we go to the (instantiation // of the) lexical context of the pattern? - SubstQualifier(*this, PatternDecl, Function, TemplateArgs); + SubstQualifier(*this, PatternDecl, Function, TemplateArgs, + /*EarlySubstitution=*/false); ActOnStartOfFunctionDef(nullptr, Function); @@ -5040,7 +5116,8 @@ Sema::ContextRAII savedContext(*this, Function); if (addInstantiatedParametersToScope(Function, PatternDecl, Scope, - TemplateArgs)) + TemplateArgs, + /*EarlySubstitution=*/false)) return; StmtResult Body; @@ -5051,7 +5128,7 @@ if (CXXConstructorDecl *Ctor = dyn_cast(Function)) { // If this is a constructor, instantiate the member initializers. InstantiateMemInitializers(Ctor, cast(PatternDecl), - TemplateArgs); + TemplateArgs, /*EarlySubstitution=*/false); // If this is an MS ABI dllexport default constructor, instantiate any // default arguments. @@ -5062,7 +5139,7 @@ } // Instantiate the function body. - Body = SubstStmt(Pattern, TemplateArgs); + Body = SubstStmt(Pattern, TemplateArgs, /*EarlySubstitution=*/false); if (Body.isInvalid()) Function->setInvalidDecl(); @@ -5071,7 +5148,8 @@ // context seems wrong. Investigate more. ActOnFinishFunctionBody(Function, Body.get(), /*IsInstantiation=*/true); - PerformDependentDiagnostics(PatternDecl, TemplateArgs); + PerformDependentDiagnostics(PatternDecl, TemplateArgs, + /*EarlySubstitution=*/false); if (auto *Listener = getASTMutationListener()) Listener->FunctionDefinitionInstantiated(Function); @@ -5127,7 +5205,8 @@ MultiLevelTemplateArgumentList MultiLevelList(TemplateArgList); TemplateDeclInstantiator Instantiator(*this, FromVar->getDeclContext(), - MultiLevelList); + MultiLevelList, + /*EarlySubstitution=*/false); // TODO: Set LateAttrs and StartingScope ... @@ -5140,14 +5219,16 @@ /// with appropriate type information and initializer. VarTemplateSpecializationDecl *Sema::CompleteVarTemplateSpecializationDecl( VarTemplateSpecializationDecl *VarSpec, VarDecl *PatternDecl, - const MultiLevelTemplateArgumentList &TemplateArgs) { + const MultiLevelTemplateArgumentList &TemplateArgs, + bool EarlySubstitution) { assert(PatternDecl->isThisDeclarationADefinition() && "don't have a definition to instantiate from"); // Do substitution on the type of the declaration - TypeSourceInfo *DI = - SubstType(PatternDecl->getTypeSourceInfo(), TemplateArgs, - PatternDecl->getTypeSpecStartLoc(), PatternDecl->getDeclName()); + TypeSourceInfo *DI = SubstType( + PatternDecl->getTypeSourceInfo(), TemplateArgs, EarlySubstitution, + PatternDecl->getTypeSpecStartLoc(), PatternDecl->getDeclName(), + /*AllowDeducedTST=*/false); if (!DI) return nullptr; @@ -5158,7 +5239,8 @@ VarSpec->setCompleteDefinition(); // Instantiate the initializer. - InstantiateVariableInitializer(VarSpec, PatternDecl, TemplateArgs); + InstantiateVariableInitializer(VarSpec, PatternDecl, TemplateArgs, + EarlySubstitution); if (getLangOpts().OpenCL) deduceOpenCLAddressSpace(VarSpec); @@ -5171,10 +5253,9 @@ /// variable instantiation. void Sema::BuildVariableInstantiation( VarDecl *NewVar, VarDecl *OldVar, - const MultiLevelTemplateArgumentList &TemplateArgs, + const MultiLevelTemplateArgumentList &TemplateArgs, bool EarlySubstitution, LateInstantiatedAttrVec *LateAttrs, DeclContext *Owner, - LocalInstantiationScope *StartingScope, - bool InstantiatingVarTemplate, + LocalInstantiationScope *StartingScope, bool InstantiatingVarTemplate, VarTemplateSpecializationDecl *PrevDeclForVarTemplateSpecialization) { // Instantiating a partial specialization to produce a partial // specialization. @@ -5214,7 +5295,8 @@ NewVar->setReferenced(OldVar->isReferenced()); } - InstantiateAttrs(TemplateArgs, OldVar, NewVar, LateAttrs, StartingScope); + InstantiateAttrs(TemplateArgs, EarlySubstitution, OldVar, NewVar, LateAttrs, + StartingScope); LookupResult Previous( *this, NewVar->getDeclName(), NewVar->getLocation(), @@ -5229,7 +5311,9 @@ // We have a previous declaration. Use that one, so we merge with the // right type. if (NamedDecl *NewPrev = FindInstantiatedDecl( - NewVar->getLocation(), OldVar->getPreviousDecl(), TemplateArgs)) + NewVar->getLocation(), OldVar->getPreviousDecl(), TemplateArgs, + EarlySubstitution, + /*FindingInstantiatedContext=*/false)) Previous.addDecl(NewPrev); } else if (!isa(NewVar) && OldVar->hasLinkage()) { @@ -5280,7 +5364,8 @@ // We're producing a template. Don't instantiate the initializer yet. } else if (NewVar->getType()->isUndeducedType()) { // We need the type to complete the declaration of the variable. - InstantiateVariableInitializer(NewVar, OldVar, TemplateArgs); + InstantiateVariableInitializer(NewVar, OldVar, TemplateArgs, + EarlySubstitution); } else if (InstantiatingSpecFromTemplate || (OldVar->isInline() && OldVar->isThisDeclarationADefinition() && !NewVar->isThisDeclarationADefinition())) { @@ -5288,7 +5373,8 @@ // specializations or inline static data members until a definition of the // variable is needed. } else { - InstantiateVariableInitializer(NewVar, OldVar, TemplateArgs); + InstantiateVariableInitializer(NewVar, OldVar, TemplateArgs, + EarlySubstitution); } // Diagnose unused local variables with dependent types, where the diagnostic @@ -5302,7 +5388,8 @@ /// Instantiate the initializer of a variable. void Sema::InstantiateVariableInitializer( VarDecl *Var, VarDecl *OldVar, - const MultiLevelTemplateArgumentList &TemplateArgs) { + const MultiLevelTemplateArgumentList &TemplateArgs, + bool EarlySubstitution) { if (ASTMutationListener *L = getASTContext().getASTMutationListener()) L->VariableDefinitionInstantiated(Var); @@ -5323,8 +5410,9 @@ { ContextRAII SwitchContext(*this, Var->getDeclContext()); - Init = SubstInitializer(OldVar->getInit(), TemplateArgs, - OldVar->getInitStyle() == VarDecl::CallInit); + Init = + SubstInitializer(OldVar->getInit(), TemplateArgs, EarlySubstitution, + OldVar->getInitStyle() == VarDecl::CallInit); } if (!Init.isInvalid()) { @@ -5438,7 +5526,8 @@ // Enter the scope of this instantiation. We don't use // PushDeclContext because we don't have a scope. ContextRAII PreviousContext(*this, Var->getDeclContext()); - InstantiateVariableInitializer(Var, PatternDecl, TemplateArgs); + InstantiateVariableInitializer(Var, PatternDecl, TemplateArgs, + /*EarlySubstitution=*/false); PreviousContext.pop(); // This variable may have local implicit instantiations that need to be @@ -5543,17 +5632,19 @@ if (Def->isStaticDataMember() && !Def->isOutOfLine()) { // We're instantiating an inline static data member whose definition was // provided inside the class. - InstantiateVariableInitializer(Var, Def, TemplateArgs); + InstantiateVariableInitializer(Var, Def, TemplateArgs, + /*EarlySubstitution=*/false); } else if (!VarSpec) { - Var = cast_or_null(SubstDecl(Def, Var->getDeclContext(), - TemplateArgs)); + Var = cast_or_null(SubstDecl( + Def, Var->getDeclContext(), TemplateArgs, /*EarlySubstitution=*/false)); } else if (Var->isStaticDataMember() && Var->getLexicalDeclContext()->isRecord()) { // We need to instantiate the definition of a static data member template, // and all we have is the in-class declaration of it. Instantiate a separate // declaration of the definition. TemplateDeclInstantiator Instantiator(*this, Var->getDeclContext(), - TemplateArgs); + TemplateArgs, + /*EarlySubstitution=*/false); Var = cast_or_null(Instantiator.VisitVarTemplateSpecializationDecl( VarSpec->getSpecializedTemplate(), Def, VarSpec->getTemplateArgsInfo(), VarSpec->getTemplateArgs().asArray(), VarSpec)); @@ -5567,12 +5658,14 @@ Partial, &VarSpec->getTemplateInstantiationArgs()); // Attach the initializer. - InstantiateVariableInitializer(Var, Def, TemplateArgs); + InstantiateVariableInitializer(Var, Def, TemplateArgs, + /*EarlySubstitution=*/false); } } else // Complete the existing variable's definition with an appropriately // substituted type and initializer. - Var = CompleteVarTemplateSpecializationDecl(VarSpec, Def, TemplateArgs); + Var = CompleteVarTemplateSpecializationDecl(VarSpec, Def, TemplateArgs, + /*EarlySubstitution=*/false); PreviousContext.pop(); @@ -5589,10 +5682,10 @@ GlobalInstantiations.perform(); } -void -Sema::InstantiateMemInitializers(CXXConstructorDecl *New, - const CXXConstructorDecl *Tmpl, - const MultiLevelTemplateArgumentList &TemplateArgs) { +void Sema::InstantiateMemInitializers( + CXXConstructorDecl *New, const CXXConstructorDecl *Tmpl, + const MultiLevelTemplateArgumentList &TemplateArgs, + bool EarlySubstitution) { SmallVector NewInits; bool AnyErrors = Tmpl->isInvalidDecl(); @@ -5632,18 +5725,19 @@ Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(*this, I); // Instantiate the initializer. - ExprResult TempInit = SubstInitializer(Init->getInit(), TemplateArgs, - /*CXXDirectInit=*/true); + ExprResult TempInit = + SubstInitializer(Init->getInit(), TemplateArgs, EarlySubstitution, + /*CXXDirectInit=*/true); if (TempInit.isInvalid()) { AnyErrors = true; break; } // Instantiate the base type. - TypeSourceInfo *BaseTInfo = SubstType(Init->getTypeSourceInfo(), - TemplateArgs, - Init->getSourceLocation(), - New->getDeclName()); + TypeSourceInfo *BaseTInfo = SubstType( + Init->getTypeSourceInfo(), TemplateArgs, EarlySubstitution, + Init->getSourceLocation(), New->getDeclName(), + /*AllowDeducedTST=*/false); if (!BaseTInfo) { AnyErrors = true; break; @@ -5666,8 +5760,9 @@ } // Instantiate the initializer. - ExprResult TempInit = SubstInitializer(Init->getInit(), TemplateArgs, - /*CXXDirectInit=*/true); + ExprResult TempInit = + SubstInitializer(Init->getInit(), TemplateArgs, EarlySubstitution, + /*CXXDirectInit=*/true); if (TempInit.isInvalid()) { AnyErrors = true; continue; @@ -5675,10 +5770,10 @@ MemInitResult NewInit; if (Init->isDelegatingInitializer() || Init->isBaseInitializer()) { - TypeSourceInfo *TInfo = SubstType(Init->getTypeSourceInfo(), - TemplateArgs, - Init->getSourceLocation(), - New->getDeclName()); + TypeSourceInfo *TInfo = + SubstType(Init->getTypeSourceInfo(), TemplateArgs, EarlySubstitution, + Init->getSourceLocation(), New->getDeclName(), + /*AllowDeducedTST=*/false); if (!TInfo) { AnyErrors = true; New->setInvalidDecl(); @@ -5692,10 +5787,10 @@ NewInit = BuildDelegatingInitializer(TInfo, TempInit.get(), cast(CurContext->getParent())); } else if (Init->isMemberInitializer()) { - FieldDecl *Member = cast_or_null(FindInstantiatedDecl( - Init->getMemberLocation(), - Init->getMember(), - TemplateArgs)); + FieldDecl *Member = cast_or_null( + FindInstantiatedDecl(Init->getMemberLocation(), Init->getMember(), + TemplateArgs, EarlySubstitution, + /*FindingInstantiatedContext=*/false)); if (!Member) { AnyErrors = true; New->setInvalidDecl(); @@ -5706,9 +5801,10 @@ Init->getSourceLocation()); } else if (Init->isIndirectMemberInitializer()) { IndirectFieldDecl *IndirectMember = - cast_or_null(FindInstantiatedDecl( - Init->getMemberLocation(), - Init->getIndirectMember(), TemplateArgs)); + cast_or_null(FindInstantiatedDecl( + Init->getMemberLocation(), Init->getIndirectMember(), + TemplateArgs, EarlySubstitution, + /*FindingInstantiatedContext=*/false)); if (!IndirectMember) { AnyErrors = true; @@ -5943,10 +6039,13 @@ /// within the current instantiation. /// /// \returns NULL if there was an error -DeclContext *Sema::FindInstantiatedContext(SourceLocation Loc, DeclContext* DC, - const MultiLevelTemplateArgumentList &TemplateArgs) { +DeclContext *Sema::FindInstantiatedContext( + SourceLocation Loc, DeclContext *DC, + const MultiLevelTemplateArgumentList &TemplateArgs, + bool EarlySubstitution) { if (NamedDecl *D = dyn_cast(DC)) { - Decl* ID = FindInstantiatedDecl(Loc, D, TemplateArgs, true); + Decl *ID = FindInstantiatedDecl(Loc, D, TemplateArgs, EarlySubstitution, + /*FindingInstantiatedContext=*/true); return cast_or_null(ID); } else return DC; } @@ -5991,9 +6090,11 @@ /// X::::KnownValue) to its instantiation (X::::KnownValue). /// \p FindInstantiatedDecl performs this mapping from within the instantiation /// of X. -NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D, - const MultiLevelTemplateArgumentList &TemplateArgs, - bool FindingInstantiatedContext) { +NamedDecl * +Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D, + const MultiLevelTemplateArgumentList &TemplateArgs, + bool EarlySubstitution, + bool FindingInstantiatedContext) { DeclContext *ParentDC = D->getDeclContext(); // Determine whether our parent context depends on any of the template // arguments we're currently substituting. @@ -6073,7 +6174,7 @@ else NeedInstantiate = isa(D); if (NeedInstantiate) { - Decl *Inst = SubstDecl(D, CurContext, TemplateArgs); + Decl *Inst = SubstDecl(D, CurContext, TemplateArgs, EarlySubstitution); CurrentInstantiationScope->InstantiatedLocal(D, Inst); return cast(Inst); } @@ -6082,7 +6183,7 @@ // been found yet. Lazily instantiate it and return it now. assert(isa(D)); - Decl *Inst = SubstDecl(D, CurContext, TemplateArgs); + Decl *Inst = SubstDecl(D, CurContext, TemplateArgs, EarlySubstitution); assert(Inst && "Failed to instantiate label??"); CurrentInstantiationScope->InstantiatedLocal(D, Inst); @@ -6181,7 +6282,8 @@ if (!ParentDependsOnArgs) return D; - ParentDC = FindInstantiatedContext(Loc, ParentDC, TemplateArgs); + ParentDC = + FindInstantiatedContext(Loc, ParentDC, TemplateArgs, EarlySubstitution); if (!ParentDC) return nullptr; @@ -6214,7 +6316,7 @@ if (auto Name = D->getDeclName()) { DeclarationNameInfo NameInfo(Name, D->getLocation()); DeclarationNameInfo NewNameInfo = - SubstDeclarationNameInfo(NameInfo, TemplateArgs); + SubstDeclarationNameInfo(NameInfo, TemplateArgs, EarlySubstitution); Name = NewNameInfo.getName(); if (!Name) return nullptr; @@ -6258,8 +6360,9 @@ // but can't be found in the instantiation. This can happen if an // unscoped enumeration member is explicitly specialized. EnumDecl *Enum = cast(ED->getLexicalDeclContext()); - EnumDecl *Spec = cast(FindInstantiatedDecl(Loc, Enum, - TemplateArgs)); + EnumDecl *Spec = cast( + FindInstantiatedDecl(Loc, Enum, TemplateArgs, EarlySubstitution, + /*FindingInstantiatedContext=*/false)); assert(Spec->getTemplateSpecializationKind() == TSK_ExplicitSpecialization); Diag(Loc, diag::err_enumerator_does_not_exist) @@ -6367,12 +6470,14 @@ PendingInstantiations.swap(delayedPCHInstantiations); } -void Sema::PerformDependentDiagnostics(const DeclContext *Pattern, - const MultiLevelTemplateArgumentList &TemplateArgs) { +void Sema::PerformDependentDiagnostics( + const DeclContext *Pattern, + const MultiLevelTemplateArgumentList &TemplateArgs, + bool EarlySubstitution) { for (auto DD : Pattern->ddiags()) { switch (DD->getKind()) { case DependentDiagnostic::Access: - HandleDependentAccessCheck(*DD, TemplateArgs); + HandleDependentAccessCheck(*DD, TemplateArgs, EarlySubstitution); break; } } diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -8799,10 +8799,10 @@ if (MSI->getTemplateSpecializationKind() != TSK_ExplicitSpecialization) { runWithSufficientStackSpace(Loc, [&] { - Diagnosed = InstantiateClass(Loc, RD, Pattern, - getTemplateInstantiationArgs(RD), - TSK_ImplicitInstantiation, - /*Complain=*/Diagnoser); + Diagnosed = InstantiateClass( + Loc, RD, Pattern, getTemplateInstantiationArgs(RD), + /*EarlySubstitution=*/false, TSK_ImplicitInstantiation, + /*Complain=*/Diagnoser); }); Instantiated = true; } diff --git a/clang/utils/TableGen/ClangAttrEmitter.cpp b/clang/utils/TableGen/ClangAttrEmitter.cpp --- a/clang/utils/TableGen/ClangAttrEmitter.cpp +++ b/clang/utils/TableGen/ClangAttrEmitter.cpp @@ -1165,8 +1165,10 @@ OS << " {\n"; OS << " EnterExpressionEvaluationContext " << "Unevaluated(S, Sema::ExpressionEvaluationContext::Unevaluated);\n"; - OS << " ExprResult " << "Result = S.SubstExpr(" - << "A->get" << getUpperName() << "(), TemplateArgs);\n"; + OS << " ExprResult " + << "Result = S.SubstExpr(" + << "A->get" << getUpperName() + << "(), TemplateArgs, EarlySubstitution);\n"; OS << " if (Result.isInvalid())\n"; OS << " return nullptr;\n"; OS << " tempInst" << getUpperName() << " = Result.get();\n"; @@ -1223,7 +1225,8 @@ OS << " " << getType() << " *E = A->" << getLowerName() << "_end();\n"; OS << " for (; I != E; ++I, ++TI) {\n"; - OS << " ExprResult Result = S.SubstExpr(*I, TemplateArgs);\n"; + OS << " ExprResult Result = S.SubstExpr(*I, TemplateArgs, " + "EarlySubstitution);\n"; OS << " if (Result.isInvalid())\n"; OS << " return nullptr;\n"; OS << " *TI = Result.get();\n"; @@ -1300,7 +1303,8 @@ void writeTemplateInstantiation(raw_ostream &OS) const override { OS << " " << getType() << " tempInst" << getUpperName() << " =\n"; OS << " S.SubstType(A->get" << getUpperName() << "Loc(), " - << "TemplateArgs, A->getLoc(), A->getAttrName());\n"; + << "TemplateArgs, EarlySubstitution, A->getLoc(), A->getAttrName(), " + << "/*AllowDeducedTST=*/false);\n"; OS << " if (!tempInst" << getUpperName() << ")\n"; OS << " return nullptr;\n"; } @@ -3538,12 +3542,14 @@ << "namespace sema {\n\n" << "Attr *instantiateTemplateAttribute(const Attr *At, ASTContext &C, " << "Sema &S,\n" - << " const MultiLevelTemplateArgumentList &TemplateArgs) {\n"; + << " const MultiLevelTemplateArgumentList &TemplateArgs,\n" + << " bool EarlySubstitution) {\n"; EmitClangAttrTemplateInstantiateHelper(Attrs, OS, /*AppliesToDecl*/false); OS << "}\n\n" << "Attr *instantiateTemplateAttributeForDecl(const Attr *At,\n" << " ASTContext &C, Sema &S,\n" - << " const MultiLevelTemplateArgumentList &TemplateArgs) {\n"; + << " const MultiLevelTemplateArgumentList &TemplateArgs,\n" + << " bool EarlySubstitution) {\n"; EmitClangAttrTemplateInstantiateHelper(Attrs, OS, /*AppliesToDecl*/true); OS << "}\n\n" << "} // end namespace sema\n"