diff --git a/clang-tools-extra/clang-tidy/hicpp/ExceptionBaseclassCheck.cpp b/clang-tools-extra/clang-tidy/hicpp/ExceptionBaseclassCheck.cpp --- a/clang-tools-extra/clang-tidy/hicpp/ExceptionBaseclassCheck.cpp +++ b/clang-tools-extra/clang-tidy/hicpp/ExceptionBaseclassCheck.cpp @@ -52,7 +52,7 @@ diag(BadThrow->getSubExpr()->getBeginLoc(), "type %0 is a template instantiation of %1", DiagnosticIDs::Note) << BadThrow->getSubExpr()->getType() - << Template->getReplacedParameter()->getDecl(); + << Template->getReplacedParameter(); if (const auto *TypeDecl = Result.Nodes.getNodeAs("decl")) diag(TypeDecl->getBeginLoc(), "type defined here", DiagnosticIDs::Note); diff --git a/clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.cpp b/clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.cpp --- a/clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.cpp +++ b/clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.cpp @@ -191,12 +191,12 @@ getSubstitutedType(VarType, Context)) { if (const SubstTemplateTypeParmType *InitializerTmplType = getSubstitutedType(InitializerType, Context)) { - return VarTmplType->getReplacedParameter() - ->desugar() - .getCanonicalType() != - InitializerTmplType->getReplacedParameter() - ->desugar() - .getCanonicalType(); + const TemplateTypeParmDecl *VarTTP = VarTmplType->getReplacedParameter(); + const TemplateTypeParmDecl *InitTTP = + InitializerTmplType->getReplacedParameter(); + return (VarTTP->getDepth() != InitTTP->getDepth() || + VarTTP->getIndex() != InitTTP->getIndex() || + VarTTP->isParameterPack() != InitTTP->isParameterPack()); } } return false; diff --git a/clang-tools-extra/clangd/AST.cpp b/clang-tools-extra/clangd/AST.cpp --- a/clang-tools-extra/clangd/AST.cpp +++ b/clang-tools-extra/clangd/AST.cpp @@ -730,8 +730,8 @@ if (const auto *SubstType = dyn_cast(PlainType)) { const auto *ReplacedParameter = SubstType->getReplacedParameter(); if (ReplacedParameter->isParameterPack()) { - return dyn_cast( - ReplacedParameter->getCanonicalTypeUnqualified()->getTypePtr()); + return ReplacedParameter->getTypeForDecl() + ->castAs(); } } return nullptr; diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h @@ -1617,12 +1617,12 @@ QualType getBTFTagAttributedType(const BTFTypeTagAttr *BTFAttr, QualType Wrapped); - QualType getSubstTemplateTypeParmType(const TemplateTypeParmType *Replaced, - QualType Replacement, + QualType getSubstTemplateTypeParmType(QualType Replacement, + Decl *AssociatedDecl, unsigned Index, Optional PackIndex) const; - QualType - getSubstTemplateTypeParmPackType(const TemplateTypeParmType *Replaced, - const TemplateArgument &ArgPack); + QualType getSubstTemplateTypeParmPackType(Decl *AssociatedDecl, + unsigned Index, + const TemplateArgument &ArgPack); QualType getTemplateTypeParmType(unsigned Depth, unsigned Index, @@ -2202,10 +2202,13 @@ const IdentifierInfo *Name) const; TemplateName getDependentTemplateName(NestedNameSpecifier *NNS, OverloadedOperatorKind Operator) const; - TemplateName getSubstTemplateTemplateParm(TemplateTemplateParmDecl *param, - TemplateName replacement) const; - TemplateName getSubstTemplateTemplateParmPack(TemplateTemplateParmDecl *Param, - const TemplateArgument &ArgPack) const; + TemplateName getSubstTemplateTemplateParm(TemplateName replacement, + Decl *AssociatedDecl, + unsigned Index, + Optional PackIndex) const; + TemplateName getSubstTemplateTemplateParmPack(const TemplateArgument &ArgPack, + Decl *AssociatedDecl, + unsigned Index) const; enum GetBuiltinTypeError { /// No error diff --git a/clang/include/clang/AST/ASTNodeTraverser.h b/clang/include/clang/AST/ASTNodeTraverser.h --- a/clang/include/clang/AST/ASTNodeTraverser.h +++ b/clang/include/clang/AST/ASTNodeTraverser.h @@ -389,12 +389,9 @@ void VisitBTFTagAttributedType(const BTFTagAttributedType *T) { Visit(T->getWrappedType()); } - void VisitSubstTemplateTypeParmType(const SubstTemplateTypeParmType *T) { - Visit(T->getReplacedParameter()); - } + void VisitSubstTemplateTypeParmType(const SubstTemplateTypeParmType *) {} void VisitSubstTemplateTypeParmPackType(const SubstTemplateTypeParmPackType *T) { - Visit(T->getReplacedParameter()); Visit(T->getArgumentPack()); } void VisitTemplateSpecializationType(const TemplateSpecializationType *T) { diff --git a/clang/include/clang/AST/DeclTemplate.h b/clang/include/clang/AST/DeclTemplate.h --- a/clang/include/clang/AST/DeclTemplate.h +++ b/clang/include/clang/AST/DeclTemplate.h @@ -459,18 +459,17 @@ NamedDecl *TemplatedDecl; TemplateParameterList *TemplateParams; +public: void setTemplateParameters(TemplateParameterList *TParams) { TemplateParams = TParams; } -public: - /// Initialize the underlying templated declaration and - /// template parameters. - void init(NamedDecl *templatedDecl, TemplateParameterList* templateParams) { - assert(!TemplatedDecl && "TemplatedDecl already set!"); - assert(!TemplateParams && "TemplateParams already set!"); - TemplatedDecl = templatedDecl; - TemplateParams = templateParams; + /// Initialize the underlying templated declaration. + void init(NamedDecl *NewTemplatedDecl) { + if (TemplatedDecl) + assert(TemplatedDecl == NewTemplatedDecl && "Inconsistent TemplatedDecl"); + else + TemplatedDecl = NewTemplatedDecl; } }; @@ -3425,6 +3424,10 @@ return None; } +/// Internal helper used by Subst* nodes to retrieve the parameter list +/// for their AssociatedDecl. +TemplateParameterList *getReplacedTemplateParameterList(Decl *D); + } // namespace clang #endif // LLVM_CLANG_AST_DECLTEMPLATE_H diff --git a/clang/include/clang/AST/DeclarationName.h b/clang/include/clang/AST/DeclarationName.h --- a/clang/include/clang/AST/DeclarationName.h +++ b/clang/include/clang/AST/DeclarationName.h @@ -941,7 +941,7 @@ friend class ASTContext; AssumedTemplateStorage(DeclarationName Name) - : UncommonTemplateNameStorage(Assumed, 0), Name(Name) {} + : UncommonTemplateNameStorage(Assumed, 0, 0), Name(Name) {} DeclarationName Name; public: diff --git a/clang/include/clang/AST/ExprCXX.h b/clang/include/clang/AST/ExprCXX.h --- a/clang/include/clang/AST/ExprCXX.h +++ b/clang/include/clang/AST/ExprCXX.h @@ -4270,24 +4270,30 @@ friend class ASTReader; friend class ASTStmtReader; - /// The replaced parameter and a flag indicating if it was a reference + /// The replacement expression. + Stmt *Replacement; + + /// The associated declaration and a flag indicating if it was a reference /// parameter. For class NTTPs, we can't determine that based on the value /// category alone. - llvm::PointerIntPair ParamAndRef; + llvm::PointerIntPair AssociatedDeclAndRef; - /// The replacement expression. - Stmt *Replacement; + unsigned Index : 15; + unsigned PackIndex : 16; explicit SubstNonTypeTemplateParmExpr(EmptyShell Empty) : Expr(SubstNonTypeTemplateParmExprClass, Empty) {} public: SubstNonTypeTemplateParmExpr(QualType Ty, ExprValueKind ValueKind, - SourceLocation Loc, - NonTypeTemplateParmDecl *Param, bool RefParam, - Expr *Replacement) + SourceLocation Loc, Expr *Replacement, + Decl *AssociatedDecl, unsigned Index, + Optional PackIndex, bool RefParam) : Expr(SubstNonTypeTemplateParmExprClass, Ty, ValueKind, OK_Ordinary), - ParamAndRef(Param, RefParam), Replacement(Replacement) { + Replacement(Replacement), + AssociatedDeclAndRef(AssociatedDecl, RefParam), Index(Index), + PackIndex(PackIndex ? *PackIndex + 1 : 0) { + assert(AssociatedDecl != nullptr); SubstNonTypeTemplateParmExprBits.NameLoc = Loc; setDependence(computeDependence(this)); } @@ -4300,11 +4306,23 @@ Expr *getReplacement() const { return cast(Replacement); } - NonTypeTemplateParmDecl *getParameter() const { - return ParamAndRef.getPointer(); + /// A template-like entity which owns the whole pattern being substituted. + /// This will own a set of template parameters. + Decl *getAssociatedDecl() const { return AssociatedDeclAndRef.getPointer(); } + + /// Returns the index of the replaced parameter in the associated declaration. + /// This should match the result of `getParameter()->getIndex()`. + unsigned getIndex() const { return Index; } + + Optional getPackIndex() const { + if (PackIndex == 0) + return None; + return PackIndex - 1; } - bool isReferenceParameter() const { return ParamAndRef.getInt(); } + NonTypeTemplateParmDecl *getParameter() const; + + bool isReferenceParameter() const { return AssociatedDeclAndRef.getInt(); } /// Determine the substituted type of the template parameter. QualType getParameterType(const ASTContext &Ctx) const; @@ -4338,14 +4356,16 @@ friend class ASTStmtReader; /// The non-type template parameter pack itself. - NonTypeTemplateParmDecl *Param; + Decl *AssociatedDecl; /// A pointer to the set of template arguments that this /// parameter pack is instantiated with. const TemplateArgument *Arguments; /// The number of template arguments in \c Arguments. - unsigned NumArguments; + unsigned NumArguments : 16; + + unsigned Index : 16; /// The location of the non-type template parameter pack reference. SourceLocation NameLoc; @@ -4354,14 +4374,21 @@ : Expr(SubstNonTypeTemplateParmPackExprClass, Empty) {} public: - SubstNonTypeTemplateParmPackExpr(QualType T, - ExprValueKind ValueKind, - NonTypeTemplateParmDecl *Param, + SubstNonTypeTemplateParmPackExpr(QualType T, ExprValueKind ValueKind, SourceLocation NameLoc, - const TemplateArgument &ArgPack); + const TemplateArgument &ArgPack, + Decl *AssociatedDecl, unsigned Index); + + /// A template-like entity which owns the whole pattern being substituted. + /// This will own a set of template parameters. + Decl *getAssociatedDecl() const { return AssociatedDecl; } + + /// Returns the index of the replaced parameter in the associated declaration. + /// This should match the result of `getParameterPack()->getIndex()`. + unsigned getIndex() const { return Index; } /// Retrieve the non-type template parameter pack being substituted. - NonTypeTemplateParmDecl *getParameterPack() const { return Param; } + NonTypeTemplateParmDecl *getParameterPack() const; /// Retrieve the location of the parameter pack name. SourceLocation getParameterPackLocation() const { return NameLoc; } diff --git a/clang/include/clang/AST/JSONNodeDumper.h b/clang/include/clang/AST/JSONNodeDumper.h --- a/clang/include/clang/AST/JSONNodeDumper.h +++ b/clang/include/clang/AST/JSONNodeDumper.h @@ -222,6 +222,8 @@ void VisitTagType(const TagType *TT); void VisitTemplateTypeParmType(const TemplateTypeParmType *TTPT); void VisitSubstTemplateTypeParmType(const SubstTemplateTypeParmType *STTPT); + void + VisitSubstTemplateTypeParmPackType(const SubstTemplateTypeParmPackType *T); void VisitAutoType(const AutoType *AT); void VisitTemplateSpecializationType(const TemplateSpecializationType *TST); void VisitInjectedClassNameType(const InjectedClassNameType *ICNT); diff --git a/clang/include/clang/AST/PropertiesBase.td b/clang/include/clang/AST/PropertiesBase.td --- a/clang/include/clang/AST/PropertiesBase.td +++ b/clang/include/clang/AST/PropertiesBase.td @@ -701,28 +701,37 @@ def : ReadHelper<[{ auto parm = node.getAsSubstTemplateTemplateParm(); }]>; - def : Property<"parameter", TemplateTemplateParmDeclRef> { - let Read = [{ parm->getParameter() }]; - } def : Property<"replacement", TemplateName> { let Read = [{ parm->getReplacement() }]; } + def : Property<"associatedDecl", DeclRef> { + let Read = [{ parm->getAssociatedDecl() }]; + } + def : Property<"index", UInt32> { + let Read = [{ parm->getIndex() }]; + } + def : Property<"packIndex", Optional> { + let Read = [{ parm->getPackIndex() }]; + } def : Creator<[{ - return ctx.getSubstTemplateTemplateParm(parameter, replacement); + return ctx.getSubstTemplateTemplateParm(replacement, associatedDecl, index, packIndex); }]>; } let Class = PropertyTypeCase in { def : ReadHelper<[{ auto parm = node.getAsSubstTemplateTemplateParmPack(); }]>; - def : Property<"parameterPack", TemplateTemplateParmDeclRef> { - let Read = [{ parm->getParameterPack() }]; - } def : Property<"argumentPack", TemplateArgument> { let Read = [{ parm->getArgumentPack() }]; } + def : Property<"associatedDecl", DeclRef> { + let Read = [{ parm->getAssociatedDecl() }]; + } + def : Property<"index", UInt32> { + let Read = [{ parm->getIndex() }]; + } def : Creator<[{ - return ctx.getSubstTemplateTemplateParmPack(parameterPack, argumentPack); + return ctx.getSubstTemplateTemplateParmPack(argumentPack, associatedDecl, index); }]>; } diff --git a/clang/include/clang/AST/TemplateName.h b/clang/include/clang/AST/TemplateName.h --- a/clang/include/clang/AST/TemplateName.h +++ b/clang/include/clang/AST/TemplateName.h @@ -57,9 +57,12 @@ /// A Kind. unsigned Kind : 2; - /// The number of stored templates or template arguments, - /// depending on which subclass we have. - unsigned Size : 30; + // The template parameter index. + unsigned Index : 15; + + /// The pack index, or the number of stored templates + /// or template arguments, depending on which subclass we have. + unsigned Data : 15; }; union { @@ -67,14 +70,13 @@ void *PointerAlignment; }; - UncommonTemplateNameStorage(Kind kind, unsigned size) { - Bits.Kind = kind; - Bits.Size = size; + UncommonTemplateNameStorage(Kind Kind, unsigned Index, unsigned Data) { + Bits.Kind = Kind; + Bits.Index = Index; + Bits.Data = Data; } public: - unsigned size() const { return Bits.Size; } - OverloadedTemplateStorage *getAsOverloadedStorage() { return Bits.Kind == Overloaded ? reinterpret_cast(this) @@ -106,7 +108,7 @@ friend class ASTContext; OverloadedTemplateStorage(unsigned size) - : UncommonTemplateNameStorage(Overloaded, size) {} + : UncommonTemplateNameStorage(Overloaded, 0, size) {} NamedDecl **getStorage() { return reinterpret_cast(this + 1); @@ -116,10 +118,12 @@ } public: + unsigned size() const { return Bits.Data; } + using iterator = NamedDecl *const *; iterator begin() const { return getStorage(); } - iterator end() const { return getStorage() + size(); } + iterator end() const { return getStorage() + Bits.Data; } llvm::ArrayRef decls() const { return llvm::makeArrayRef(begin(), end()); @@ -132,23 +136,30 @@ /// This kind of template names occurs when the parameter pack has been /// provided with a template template argument pack in a context where its /// enclosing pack expansion could not be fully expanded. -class SubstTemplateTemplateParmPackStorage - : public UncommonTemplateNameStorage, public llvm::FoldingSetNode -{ - TemplateTemplateParmDecl *Parameter; +class SubstTemplateTemplateParmPackStorage : public UncommonTemplateNameStorage, + public llvm::FoldingSetNode { const TemplateArgument *Arguments; + Decl *AssociatedDecl; public: - SubstTemplateTemplateParmPackStorage(TemplateTemplateParmDecl *Parameter, - unsigned Size, - const TemplateArgument *Arguments) - : UncommonTemplateNameStorage(SubstTemplateTemplateParmPack, Size), - Parameter(Parameter), Arguments(Arguments) {} + SubstTemplateTemplateParmPackStorage(ArrayRef ArgPack, + Decl *AssociatedDecl, unsigned Index) + : UncommonTemplateNameStorage(SubstTemplateTemplateParmPack, Index, + ArgPack.size()), + Arguments(ArgPack.data()), AssociatedDecl(AssociatedDecl) { + assert(AssociatedDecl != nullptr); + } + + /// A template-like entity which owns the whole pattern being substituted. + /// This will own a set of template parameters. + Decl *getAssociatedDecl() const { return AssociatedDecl; } + + /// Returns the index of the replaced parameter in the associated declaration. + /// This should match the result of `getParameterPack()->getIndex()`. + unsigned getIndex() const { return Bits.Index; } /// Retrieve the template template parameter pack being substituted. - TemplateTemplateParmDecl *getParameterPack() const { - return Parameter; - } + TemplateTemplateParmDecl *getParameterPack() const; /// Retrieve the template template argument pack with which this /// parameter was substituted. @@ -156,10 +167,9 @@ void Profile(llvm::FoldingSetNodeID &ID, ASTContext &Context); - static void Profile(llvm::FoldingSetNodeID &ID, - ASTContext &Context, - TemplateTemplateParmDecl *Parameter, - const TemplateArgument &ArgPack); + static void Profile(llvm::FoldingSetNodeID &ID, ASTContext &Context, + const TemplateArgument &ArgPack, Decl *AssociatedDecl, + unsigned Index); }; /// Represents a C++ template name within the type system. @@ -365,23 +375,41 @@ : public UncommonTemplateNameStorage, public llvm::FoldingSetNode { friend class ASTContext; - TemplateTemplateParmDecl *Parameter; TemplateName Replacement; - - SubstTemplateTemplateParmStorage(TemplateTemplateParmDecl *parameter, - TemplateName replacement) - : UncommonTemplateNameStorage(SubstTemplateTemplateParm, 0), - Parameter(parameter), Replacement(replacement) {} + Decl *AssociatedDecl; + + SubstTemplateTemplateParmStorage(TemplateName Replacement, + Decl *AssociatedDecl, unsigned Index, + Optional PackIndex) + : UncommonTemplateNameStorage(SubstTemplateTemplateParm, Index, + PackIndex ? *PackIndex + 1 : 0), + Replacement(Replacement), AssociatedDecl(AssociatedDecl) { + assert(AssociatedDecl != nullptr); + } public: - TemplateTemplateParmDecl *getParameter() const { return Parameter; } + /// A template-like entity which owns the whole pattern being substituted. + /// This will own a set of template parameters. + Decl *getAssociatedDecl() const { return AssociatedDecl; } + + /// Returns the index of the replaced parameter in the associated declaration. + /// This should match the result of `getParameter()->getIndex()`. + unsigned getIndex() const { return Bits.Index; } + + Optional getPackIndex() const { + if (Bits.Data == 0) + return None; + return Bits.Data - 1; + } + + TemplateTemplateParmDecl *getParameter() const; TemplateName getReplacement() const { return Replacement; } void Profile(llvm::FoldingSetNodeID &ID); - static void Profile(llvm::FoldingSetNodeID &ID, - TemplateTemplateParmDecl *parameter, - TemplateName replacement); + static void Profile(llvm::FoldingSetNodeID &ID, TemplateName Replacement, + Decl *AssociatedDecl, unsigned Index, + Optional PackIndex); }; inline TemplateName TemplateName::getUnderlying() const { diff --git a/clang/include/clang/AST/TextNodeDumper.h b/clang/include/clang/AST/TextNodeDumper.h --- a/clang/include/clang/AST/TextNodeDumper.h +++ b/clang/include/clang/AST/TextNodeDumper.h @@ -318,6 +318,8 @@ void VisitTagType(const TagType *T); void VisitTemplateTypeParmType(const TemplateTypeParmType *T); void VisitSubstTemplateTypeParmType(const SubstTemplateTypeParmType *T); + void + VisitSubstTemplateTypeParmPackType(const SubstTemplateTypeParmPackType *T); void VisitAutoType(const AutoType *T); void VisitDeducedTemplateSpecializationType( const DeducedTemplateSpecializationType *T); diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h --- a/clang/include/clang/AST/Type.h +++ b/clang/include/clang/AST/Type.h @@ -1832,6 +1832,9 @@ unsigned HasNonCanonicalUnderlyingType : 1; + // The index of the template parameter this substitution represents. + unsigned Index : 15; + /// Represents the index within a pack if this represents a substitution /// from a pack expansion. This index starts at the end of the pack and /// increments towards the beginning. @@ -1845,14 +1848,14 @@ unsigned : NumTypeBits; + // The index of the template parameter this substitution represents. + unsigned Index : 16; + /// The number of template arguments in \c Arguments, which is /// expected to be able to hold at least 1024 according to [implimits]. /// However as this limit is somewhat easy to hit with template /// metaprogramming we'd prefer to keep it as large as possible. - /// At the moment it has been left as a non-bitfield since this type - /// safely fits in 64 bits as an unsigned, so there is no reason to - /// introduce the performance impact of a bitfield. - unsigned NumArgs; + unsigned NumArgs : 16; }; class TemplateSpecializationTypeBitfields { @@ -5083,18 +5086,12 @@ friend class ASTContext; friend class llvm::TrailingObjects; - // The original type parameter. - const TemplateTypeParmType *Replaced; + Decl *AssociatedDecl; - SubstTemplateTypeParmType(const TemplateTypeParmType *Param, QualType Canon, - Optional PackIndex); + SubstTemplateTypeParmType(QualType Replacement, Decl *AssociatedDecl, + unsigned Index, Optional PackIndex); public: - /// Gets the template parameter that was substituted for. - const TemplateTypeParmType *getReplacedParameter() const { - return Replaced; - } - /// Gets the type that was substituted for the template /// parameter. QualType getReplacementType() const { @@ -5103,6 +5100,18 @@ : getCanonicalTypeInternal(); } + /// A template-like entity which owns the whole pattern being substituted. + /// This will usually own a set of template parameters, or in some + /// cases might even be a template parameter itself. + Decl *getAssociatedDecl() const { return AssociatedDecl; } + + /// Gets the template parameter declaration that was substituted for. + const TemplateTypeParmDecl *getReplacedParameter() const; + + /// Returns the index of the replaced parameter in the associated declaration. + /// This should match the result of `getReplacedParameter()->getIndex()`. + unsigned getIndex() const { return SubstTemplateTypeParmTypeBits.Index; } + Optional getPackIndex() const { if (SubstTemplateTypeParmTypeBits.PackIndex == 0) return None; @@ -5113,14 +5122,16 @@ QualType desugar() const { return getReplacementType(); } void Profile(llvm::FoldingSetNodeID &ID) { - Profile(ID, getReplacedParameter(), getReplacementType(), getPackIndex()); + Profile(ID, getReplacementType(), getAssociatedDecl(), getIndex(), + getPackIndex()); } - static void Profile(llvm::FoldingSetNodeID &ID, - const TemplateTypeParmType *Replaced, - QualType Replacement, Optional PackIndex) { - ID.AddPointer(Replaced); + static void Profile(llvm::FoldingSetNodeID &ID, QualType Replacement, + const Decl *AssociatedDecl, unsigned Index, + Optional PackIndex) { Replacement.Profile(ID); + ID.AddPointer(AssociatedDecl); + ID.AddInteger(Index); ID.AddInteger(PackIndex ? *PackIndex - 1 : 0); } @@ -5144,24 +5155,30 @@ class SubstTemplateTypeParmPackType : public Type, public llvm::FoldingSetNode { friend class ASTContext; - /// The original type parameter. - const TemplateTypeParmType *Replaced; - /// A pointer to the set of template arguments that this /// parameter pack is instantiated with. const TemplateArgument *Arguments; - SubstTemplateTypeParmPackType(const TemplateTypeParmType *Param, - QualType Canon, + Decl *AssociatedDecl; + + SubstTemplateTypeParmPackType(QualType Canon, Decl *AssociatedDecl, + unsigned Index, const TemplateArgument &ArgPack); public: - IdentifierInfo *getIdentifier() const { return Replaced->getIdentifier(); } + IdentifierInfo *getIdentifier() const; - /// Gets the template parameter that was substituted for. - const TemplateTypeParmType *getReplacedParameter() const { - return Replaced; - } + /// A template-like entity which owns the whole pattern being substituted. + /// This will usually own a set of template parameters, or in some + /// cases might even be a template parameter itself. + Decl *getAssociatedDecl() const { return AssociatedDecl; } + + /// Gets the template parameter declaration that was substituted for. + const TemplateTypeParmDecl *getReplacedParameter() const; + + /// Returns the index of the replaced parameter in the associated declaration. + /// This should match the result of `getReplacedParameter()->getIndex()`. + unsigned getIndex() const { return SubstTemplateTypeParmPackTypeBits.Index; } unsigned getNumArgs() const { return SubstTemplateTypeParmPackTypeBits.NumArgs; @@ -5173,9 +5190,8 @@ TemplateArgument getArgumentPack() const; void Profile(llvm::FoldingSetNodeID &ID); - static void Profile(llvm::FoldingSetNodeID &ID, - const TemplateTypeParmType *Replaced, - const TemplateArgument &ArgPack); + static void Profile(llvm::FoldingSetNodeID &ID, const Decl *AssociatedDecl, + unsigned Index, const TemplateArgument &ArgPack); static bool classof(const Type *T) { return T->getTypeClass() == SubstTemplateTypeParmPack; diff --git a/clang/include/clang/AST/TypeProperties.td b/clang/include/clang/AST/TypeProperties.td --- a/clang/include/clang/AST/TypeProperties.td +++ b/clang/include/clang/AST/TypeProperties.td @@ -732,20 +732,23 @@ } let Class = SubstTemplateTypeParmType in { - def : Property<"replacedParameter", QualType> { - let Read = [{ QualType(node->getReplacedParameter(), 0) }]; - } def : Property<"replacementType", QualType> { let Read = [{ node->getReplacementType() }]; } + def : Property<"associatedDecl", DeclRef> { + let Read = [{ node->getAssociatedDecl() }]; + } + def : Property<"Index", UInt32> { + let Read = [{ node->getIndex() }]; + } def : Property<"PackIndex", Optional> { let Read = [{ node->getPackIndex() }]; } + // The call to getCanonicalType here existed in ASTReader.cpp, too. def : Creator<[{ return ctx.getSubstTemplateTypeParmType( - cast(replacedParameter), - replacementType, PackIndex); + replacementType, associatedDecl, Index, PackIndex); }]>; } @@ -764,8 +767,11 @@ } let Class = SubstTemplateTypeParmPackType in { - def : Property<"replacedParameter", QualType> { - let Read = [{ QualType(node->getReplacedParameter(), 0) }]; + def : Property<"associatedDecl", DeclRef> { + let Read = [{ node->getAssociatedDecl() }]; + } + def : Property<"Index", UInt32> { + let Read = [{ node->getIndex() }]; } def : Property<"replacementPack", TemplateArgument> { let Read = [{ node->getArgumentPack() }]; @@ -773,8 +779,7 @@ def : Creator<[{ return ctx.getSubstTemplateTypeParmPackType( - cast(replacedParameter), - replacementPack); + associatedDecl, Index, replacementPack); }]>; } 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 @@ -74,13 +74,20 @@ /// template argument list (17) at depth 1. class MultiLevelTemplateArgumentList { /// The template argument list at a certain template depth + using ArgList = ArrayRef; - using ArgListsIterator = SmallVector::iterator; - using ConstArgListsIterator = SmallVector::const_iterator; + struct ArgumentListLevel { + Decl *AssociatedDecl; + ArgList Args; + }; + using ContainerType = SmallVector; + + using ArgListsIterator = ContainerType::iterator; + using ConstArgListsIterator = ContainerType::const_iterator; /// The template argument lists, stored from the innermost template /// argument list (first) to the outermost template argument list (last). - SmallVector TemplateArgumentLists; + ContainerType TemplateArgumentLists; /// The number of outer levels of template arguments that are not /// being substituted. @@ -94,9 +101,8 @@ MultiLevelTemplateArgumentList() = default; /// Construct a single-level template argument list. - explicit - MultiLevelTemplateArgumentList(const TemplateArgumentList &TemplateArgs) { - addOuterTemplateArguments(&TemplateArgs); + MultiLevelTemplateArgumentList(Decl *D, ArgList Args) { + addOuterTemplateArguments(D, Args); } void setKind(TemplateSubstitutionKind K) { Kind = K; } @@ -126,7 +132,7 @@ // Determine the number of substituted args at 'Depth'. unsigned getNumSubsitutedArgs(unsigned Depth) const { assert(NumRetainedOuterLevels <= Depth && Depth < getNumLevels()); - return TemplateArgumentLists[getNumLevels() - Depth - 1].size(); + return TemplateArgumentLists[getNumLevels() - Depth - 1].Args.size(); } unsigned getNumRetainedOuterLevels() const { @@ -146,8 +152,17 @@ /// Retrieve the template argument at a given depth and index. const TemplateArgument &operator()(unsigned Depth, unsigned Index) const { assert(NumRetainedOuterLevels <= Depth && Depth < getNumLevels()); - assert(Index < TemplateArgumentLists[getNumLevels() - Depth - 1].size()); - return TemplateArgumentLists[getNumLevels() - Depth - 1][Index]; + assert(Index < + TemplateArgumentLists[getNumLevels() - Depth - 1].Args.size()); + return TemplateArgumentLists[getNumLevels() - Depth - 1].Args[Index]; + } + + /// A template-like entity which owns the whole pattern being substituted. + /// This will usually own a set of template parameters, or in some + /// cases might even be a template parameter itself. + Decl *getAssociatedDecl(unsigned Depth) const { + assert(NumRetainedOuterLevels <= Depth && Depth < getNumLevels()); + return TemplateArgumentLists[getNumLevels() - Depth - 1].AssociatedDecl; } /// Determine whether there is a non-NULL template argument at the @@ -160,15 +175,16 @@ if (Depth < NumRetainedOuterLevels) return false; - if (Index >= TemplateArgumentLists[getNumLevels() - Depth - 1].size()) + if (Index >= + TemplateArgumentLists[getNumLevels() - Depth - 1].Args.size()) return false; return !(*this)(Depth, Index).isNull(); } bool isAnyArgInstantiationDependent() const { - for (ArgList List : TemplateArgumentLists) - for (const TemplateArgument &TA : List) + for (ArgumentListLevel ListLevel : TemplateArgumentLists) + for (const TemplateArgument &TA : ListLevel.Args) if (TA.isInstantiationDependent()) return true; return false; @@ -178,25 +194,35 @@ void setArgument(unsigned Depth, unsigned Index, TemplateArgument Arg) { assert(NumRetainedOuterLevels <= Depth && Depth < getNumLevels()); - assert(Index < TemplateArgumentLists[getNumLevels() - Depth - 1].size()); - const_cast( - TemplateArgumentLists[getNumLevels() - Depth - 1][Index]) - = Arg; + assert(Index < + TemplateArgumentLists[getNumLevels() - Depth - 1].Args.size()); + const_cast( + TemplateArgumentLists[getNumLevels() - Depth - 1].Args[Index]) = Arg; } - /// Add a new outermost level to the multi-level template argument + /// Add a new outmost level to the multi-level template argument /// list. - void addOuterTemplateArguments(const TemplateArgumentList *TemplateArgs) { - addOuterTemplateArguments(ArgList(TemplateArgs->data(), - TemplateArgs->size())); + void addOuterTemplateArguments(Decl *AssociatedDecl, ArgList Args) { + assert(!NumRetainedOuterLevels && + "substituted args outside retained args?"); + assert(getKind() == TemplateSubstitutionKind::Specialization); + assert(AssociatedDecl != nullptr || Args.size() == 0); + TemplateArgumentLists.push_back( + {AssociatedDecl ? AssociatedDecl->getCanonicalDecl() : nullptr, + Args}); } - /// Add a new outmost level to the multi-level template argument - /// list. void addOuterTemplateArguments(ArgList Args) { assert(!NumRetainedOuterLevels && "substituted args outside retained args?"); - TemplateArgumentLists.push_back(Args); + assert(getKind() == TemplateSubstitutionKind::Rewrite); + TemplateArgumentLists.push_back({nullptr, Args}); + } + + void addOuterTemplateArguments(llvm::NoneType) { + assert(!NumRetainedOuterLevels && + "substituted args outside retained args?"); + TemplateArgumentLists.push_back({}); } /// Replaces the current 'innermost' level with the provided argument list. @@ -204,7 +230,7 @@ /// list from the AST, but then add the deduced innermost list. void replaceInnermostTemplateArguments(ArgList Args) { assert(TemplateArgumentLists.size() > 0 && "Replacing in an empty list?"); - TemplateArgumentLists[0] = Args; + TemplateArgumentLists[0].Args = Args; } /// Add an outermost level that we are not substituting. We have no @@ -219,11 +245,11 @@ /// Retrieve the innermost template argument list. const ArgList &getInnermost() const { - return TemplateArgumentLists.front(); + return TemplateArgumentLists.front().Args; } /// Retrieve the outermost template argument list. const ArgList &getOutermost() const { - return TemplateArgumentLists.back(); + return TemplateArgumentLists.back().Args; } ArgListsIterator begin() { return TemplateArgumentLists.begin(); } ConstArgListsIterator begin() const { diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -4785,21 +4785,22 @@ /// Retrieve a substitution-result type. QualType -ASTContext::getSubstTemplateTypeParmType(const TemplateTypeParmType *Parm, - QualType Replacement, +ASTContext::getSubstTemplateTypeParmType(QualType Replacement, + Decl *AssociatedDecl, unsigned Index, Optional PackIndex) const { llvm::FoldingSetNodeID ID; - SubstTemplateTypeParmType::Profile(ID, Parm, Replacement, PackIndex); + SubstTemplateTypeParmType::Profile(ID, Replacement, AssociatedDecl, Index, + PackIndex); void *InsertPos = nullptr; - SubstTemplateTypeParmType *SubstParm - = SubstTemplateTypeParmTypes.FindNodeOrInsertPos(ID, InsertPos); + SubstTemplateTypeParmType *SubstParm = + SubstTemplateTypeParmTypes.FindNodeOrInsertPos(ID, InsertPos); if (!SubstParm) { void *Mem = Allocate(SubstTemplateTypeParmType::totalSizeToAlloc( !Replacement.isCanonical()), TypeAlignment); - SubstParm = - new (Mem) SubstTemplateTypeParmType(Parm, Replacement, PackIndex); + SubstParm = new (Mem) SubstTemplateTypeParmType(Replacement, AssociatedDecl, + Index, PackIndex); Types.push_back(SubstParm); SubstTemplateTypeParmTypes.InsertNode(SubstParm, InsertPos); } @@ -4809,33 +4810,30 @@ /// Retrieve a QualType ASTContext::getSubstTemplateTypeParmPackType( - const TemplateTypeParmType *Parm, - const TemplateArgument &ArgPack) { + Decl *AssociatedDecl, unsigned Index, const TemplateArgument &ArgPack) { #ifndef NDEBUG for (const auto &P : ArgPack.pack_elements()) { - assert(P.getKind() == TemplateArgument::Type &&"Pack contains a non-type"); + assert(P.getKind() == TemplateArgument::Type && "Pack contains a non-type"); assert(P.getAsType().isCanonical() && "Pack contains non-canonical type"); } #endif llvm::FoldingSetNodeID ID; - SubstTemplateTypeParmPackType::Profile(ID, Parm, ArgPack); + SubstTemplateTypeParmPackType::Profile(ID, AssociatedDecl, Index, ArgPack); void *InsertPos = nullptr; - if (SubstTemplateTypeParmPackType *SubstParm - = SubstTemplateTypeParmPackTypes.FindNodeOrInsertPos(ID, InsertPos)) + if (SubstTemplateTypeParmPackType *SubstParm = + SubstTemplateTypeParmPackTypes.FindNodeOrInsertPos(ID, InsertPos)) return QualType(SubstParm, 0); QualType Canon; - if (!Parm->isCanonicalUnqualified()) { - Canon = getCanonicalType(QualType(Parm, 0)); - Canon = getSubstTemplateTypeParmPackType(cast(Canon), - ArgPack); + if (!AssociatedDecl->isCanonicalDecl()) { + Canon = getSubstTemplateTypeParmPackType(AssociatedDecl->getCanonicalDecl(), + Index, ArgPack); SubstTemplateTypeParmPackTypes.FindNodeOrInsertPos(ID, InsertPos); } - auto *SubstParm - = new (*this, TypeAlignment) SubstTemplateTypeParmPackType(Parm, Canon, - ArgPack); + auto *SubstParm = new (*this, TypeAlignment) + SubstTemplateTypeParmPackType(Canon, AssociatedDecl, Index, ArgPack); Types.push_back(SubstParm); SubstTemplateTypeParmPackTypes.InsertNode(SubstParm, InsertPos); return QualType(SubstParm, 0); @@ -6241,13 +6239,13 @@ } case TemplateName::SubstTemplateTemplateParmPack: { - SubstTemplateTemplateParmPackStorage *subst - = Name.getAsSubstTemplateTemplateParmPack(); - TemplateTemplateParmDecl *canonParameter - = getCanonicalTemplateTemplateParmDecl(subst->getParameterPack()); - TemplateArgument canonArgPack - = getCanonicalTemplateArgument(subst->getArgumentPack()); - return getSubstTemplateTemplateParmPack(canonParameter, canonArgPack); + SubstTemplateTemplateParmPackStorage *subst = + Name.getAsSubstTemplateTemplateParmPack(); + TemplateArgument canonArgPack = + getCanonicalTemplateArgument(subst->getArgumentPack()); + return getSubstTemplateTemplateParmPack( + canonArgPack, subst->getAssociatedDecl()->getCanonicalDecl(), + subst->getIndex()); } } @@ -9250,17 +9248,20 @@ } TemplateName -ASTContext::getSubstTemplateTemplateParm(TemplateTemplateParmDecl *param, - TemplateName replacement) const { +ASTContext::getSubstTemplateTemplateParm(TemplateName Replacement, + Decl *AssociatedDecl, unsigned Index, + Optional PackIndex) const { llvm::FoldingSetNodeID ID; - SubstTemplateTemplateParmStorage::Profile(ID, param, replacement); + SubstTemplateTemplateParmStorage::Profile(ID, Replacement, AssociatedDecl, + Index, PackIndex); void *insertPos = nullptr; SubstTemplateTemplateParmStorage *subst = SubstTemplateTemplateParms.FindNodeOrInsertPos(ID, insertPos); if (!subst) { - subst = new (*this) SubstTemplateTemplateParmStorage(param, replacement); + subst = new (*this) SubstTemplateTemplateParmStorage( + Replacement, AssociatedDecl, Index, PackIndex); SubstTemplateTemplateParms.InsertNode(subst, insertPos); } @@ -9268,20 +9269,21 @@ } TemplateName -ASTContext::getSubstTemplateTemplateParmPack(TemplateTemplateParmDecl *Param, - const TemplateArgument &ArgPack) const { +ASTContext::getSubstTemplateTemplateParmPack(const TemplateArgument &ArgPack, + Decl *AssociatedDecl, + unsigned Index) const { auto &Self = const_cast(*this); llvm::FoldingSetNodeID ID; - SubstTemplateTemplateParmPackStorage::Profile(ID, Self, Param, ArgPack); + SubstTemplateTemplateParmPackStorage::Profile(ID, Self, ArgPack, + AssociatedDecl, Index); void *InsertPos = nullptr; SubstTemplateTemplateParmPackStorage *Subst = SubstTemplateTemplateParmPacks.FindNodeOrInsertPos(ID, InsertPos); if (!Subst) { - Subst = new (*this) SubstTemplateTemplateParmPackStorage(Param, - ArgPack.pack_size(), - ArgPack.pack_begin()); + Subst = new (*this) SubstTemplateTemplateParmPackStorage( + ArgPack.pack_elements(), AssociatedDecl, Index); SubstTemplateTemplateParmPacks.InsertNode(Subst, InsertPos); } @@ -12931,14 +12933,18 @@ case Type::SubstTemplateTypeParm: { const auto *SX = cast(X), *SY = cast(Y); - const TemplateTypeParmType *PX = SX->getReplacedParameter(); - if (PX != SY->getReplacedParameter()) + Decl *CD = + ::getCommonDecl(SX->getAssociatedDecl(), SY->getAssociatedDecl()); + if (!CD) + return QualType(); + unsigned Index = SX->getIndex(); + if (Index != SY->getIndex()) return QualType(); auto PackIndex = SX->getPackIndex(); if (PackIndex != SY->getPackIndex()) return QualType(); - return Ctx.getSubstTemplateTypeParmType( - PX, Ctx.getQualifiedType(Underlying), PackIndex); + return Ctx.getSubstTemplateTypeParmType(Ctx.getQualifiedType(Underlying), + CD, Index, PackIndex); } case Type::ObjCTypeParam: // FIXME: Try to merge these. diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -1523,8 +1523,7 @@ ExpectedType ASTNodeImporter::VisitSubstTemplateTypeParmType( const SubstTemplateTypeParmType *T) { - Expected ReplacedOrErr = - import(T->getReplacedParameter()); + Expected ReplacedOrErr = import(T->getAssociatedDecl()); if (!ReplacedOrErr) return ReplacedOrErr.takeError(); @@ -1533,13 +1532,13 @@ return ToReplacementTypeOrErr.takeError(); return Importer.getToContext().getSubstTemplateTypeParmType( - *ReplacedOrErr, *ToReplacementTypeOrErr, T->getPackIndex()); + *ToReplacementTypeOrErr, *ReplacedOrErr, T->getIndex(), + T->getPackIndex()); } ExpectedType ASTNodeImporter::VisitSubstTemplateTypeParmPackType( const SubstTemplateTypeParmPackType *T) { - Expected ReplacedOrErr = - import(T->getReplacedParameter()); + Expected ReplacedOrErr = import(T->getAssociatedDecl()); if (!ReplacedOrErr) return ReplacedOrErr.takeError(); @@ -1548,7 +1547,7 @@ return ToArgumentPack.takeError(); return Importer.getToContext().getSubstTemplateTypeParmPackType( - *ReplacedOrErr, *ToArgumentPack); + *ReplacedOrErr, T->getIndex(), *ToArgumentPack); } ExpectedType ASTNodeImporter::VisitTemplateSpecializationType( @@ -3753,6 +3752,10 @@ } } + // If it is a template, import all related things. + if (Error Err = ImportTemplateInformation(D, ToFunction)) + return std::move(Err); + if (D->doesThisDeclarationHaveABody()) { Error Err = ImportFunctionDeclBody(D, ToFunction); @@ -3774,10 +3777,6 @@ // FIXME: Other bits to merge? - // If it is a template, import all related things. - if (Error Err = ImportTemplateInformation(D, ToFunction)) - return std::move(Err); - addDeclToContexts(D, ToFunction); if (auto *FromCXXMethod = dyn_cast(D)) @@ -5998,6 +5997,30 @@ D2->setTemplateSpecializationKind(D->getTemplateSpecializationKind()); + if (auto P = D->getInstantiatedFrom()) { + if (auto *CTD = P.dyn_cast()) { + if (auto CTDorErr = import(CTD)) + D2->setInstantiationOf(*CTDorErr); + } else { + auto *CTPSD = cast(P); + auto CTPSDOrErr = import(CTPSD); + if (!CTPSDOrErr) + return CTPSDOrErr.takeError(); + const TemplateArgumentList &DArgs = D->getTemplateInstantiationArgs(); + SmallVector D2ArgsVec(DArgs.size()); + for (unsigned I = 0; I < DArgs.size(); ++I) { + const TemplateArgument &DArg = DArgs[I]; + if (auto ArgOrErr = import(DArg)) + D2ArgsVec[I] = *ArgOrErr; + else + return ArgOrErr.takeError(); + } + D2->setInstantiationOf( + *CTPSDOrErr, + TemplateArgumentList::CreateCopy(Importer.getToContext(), D2ArgsVec)); + } + } + if (D->isCompleteDefinition()) if (Error Err = ImportDefinition(D, D2)) return std::move(Err); @@ -6161,15 +6184,6 @@ } } } else { - // Import the type. - QualType T; - if (Error Err = importInto(T, D->getType())) - return std::move(Err); - - auto TInfoOrErr = import(D->getTypeSourceInfo()); - if (!TInfoOrErr) - return TInfoOrErr.takeError(); - TemplateArgumentListInfo ToTAInfo; if (const ASTTemplateArgumentListInfo *Args = D->getTemplateArgsInfo()) { if (Error Err = ImportTemplateArgumentListInfo(*Args, ToTAInfo)) @@ -6194,7 +6208,7 @@ PartVarSpecDecl *ToPartial; if (GetImportedOrCreateDecl(ToPartial, D, Importer.getToContext(), DC, *BeginLocOrErr, *IdLocOrErr, *ToTPListOrErr, - VarTemplate, T, *TInfoOrErr, + VarTemplate, QualType(), nullptr, D->getStorageClass(), TemplateArgs, ArgInfos)) return ToPartial; @@ -6215,11 +6229,21 @@ } else { // Full specialization if (GetImportedOrCreateDecl(D2, D, Importer.getToContext(), DC, *BeginLocOrErr, *IdLocOrErr, VarTemplate, - T, *TInfoOrErr, - D->getStorageClass(), TemplateArgs)) + QualType(), nullptr, D->getStorageClass(), + TemplateArgs)) return D2; } + QualType T; + if (Error Err = importInto(T, D->getType())) + return std::move(Err); + D2->setType(T); + + auto TInfoOrErr = import(D->getTypeSourceInfo()); + if (!TInfoOrErr) + return TInfoOrErr.takeError(); + D2->setTypeSourceInfo(*TInfoOrErr); + if (D->getPointOfInstantiation().isValid()) { if (ExpectedSLoc POIOrErr = import(D->getPointOfInstantiation())) D2->setPointOfInstantiation(*POIOrErr); @@ -8412,14 +8436,14 @@ Error Err = Error::success(); auto ToType = importChecked(Err, E->getType()); auto ToExprLoc = importChecked(Err, E->getExprLoc()); - auto ToParameter = importChecked(Err, E->getParameter()); + auto ToAssociatedDecl = importChecked(Err, E->getAssociatedDecl()); auto ToReplacement = importChecked(Err, E->getReplacement()); if (Err) return std::move(Err); return new (Importer.getToContext()) SubstNonTypeTemplateParmExpr( - ToType, E->getValueKind(), ToExprLoc, ToParameter, - E->isReferenceParameter(), ToReplacement); + ToType, E->getValueKind(), ToExprLoc, ToReplacement, ToAssociatedDecl, + E->getIndex(), E->getPackIndex(), E->isReferenceParameter()); } ExpectedStmt ASTNodeImporter::VisitTypeTraitExpr(TypeTraitExpr *E) { @@ -9396,33 +9420,34 @@ case TemplateName::SubstTemplateTemplateParm: { SubstTemplateTemplateParmStorage *Subst = From.getAsSubstTemplateTemplateParm(); - ExpectedDecl ParamOrErr = Import(Subst->getParameter()); - if (!ParamOrErr) - return ParamOrErr.takeError(); - auto ReplacementOrErr = Import(Subst->getReplacement()); if (!ReplacementOrErr) return ReplacementOrErr.takeError(); + auto AssociatedDeclOrErr = Import(Subst->getAssociatedDecl()); + if (!AssociatedDeclOrErr) + return AssociatedDeclOrErr.takeError(); + return ToContext.getSubstTemplateTemplateParm( - cast(*ParamOrErr), *ReplacementOrErr); + *ReplacementOrErr, *AssociatedDeclOrErr, Subst->getIndex(), + Subst->getPackIndex()); } case TemplateName::SubstTemplateTemplateParmPack: { - SubstTemplateTemplateParmPackStorage *SubstPack - = From.getAsSubstTemplateTemplateParmPack(); - ExpectedDecl ParamOrErr = Import(SubstPack->getParameterPack()); - if (!ParamOrErr) - return ParamOrErr.takeError(); - + SubstTemplateTemplateParmPackStorage *SubstPack = + From.getAsSubstTemplateTemplateParmPack(); ASTNodeImporter Importer(*this); auto ArgPackOrErr = Importer.ImportTemplateArgument(SubstPack->getArgumentPack()); if (!ArgPackOrErr) return ArgPackOrErr.takeError(); + auto AssociatedDeclOrErr = Import(SubstPack->getAssociatedDecl()); + if (!AssociatedDeclOrErr) + return AssociatedDeclOrErr.takeError(); + return ToContext.getSubstTemplateTemplateParmPack( - cast(*ParamOrErr), *ArgPackOrErr); + *ArgPackOrErr, *AssociatedDeclOrErr, SubstPack->getIndex()); } case TemplateName::UsingTemplate: { auto UsingOrError = Import(From.getAsUsingShadowDecl()); diff --git a/clang/lib/AST/ASTStructuralEquivalence.cpp b/clang/lib/AST/ASTStructuralEquivalence.cpp --- a/clang/lib/AST/ASTStructuralEquivalence.cpp +++ b/clang/lib/AST/ASTStructuralEquivalence.cpp @@ -289,8 +289,14 @@ bool IsStmtEquivalent(const SubstNonTypeTemplateParmExpr *E1, const SubstNonTypeTemplateParmExpr *E2) { - return IsStructurallyEquivalent(Context, E1->getParameter(), - E2->getParameter()); + if (!IsStructurallyEquivalent(Context, E1->getAssociatedDecl(), + E2->getAssociatedDecl())) + return false; + if (E1->getIndex() != E2->getIndex()) + return false; + if (E1->getPackIndex() != E2->getPackIndex()) + return false; + return true; } bool IsStmtEquivalent(const SubstNonTypeTemplateParmPackExpr *E1, @@ -510,8 +516,9 @@ *P2 = N2.getAsSubstTemplateTemplateParmPack(); return IsStructurallyEquivalent(Context, P1->getArgumentPack(), P2->getArgumentPack()) && - IsStructurallyEquivalent(Context, P1->getParameterPack(), - P2->getParameterPack()); + IsStructurallyEquivalent(Context, P1->getAssociatedDecl(), + P2->getAssociatedDecl()) && + P1->getIndex() == P2->getIndex(); } case TemplateName::Template: @@ -1061,13 +1068,14 @@ case Type::SubstTemplateTypeParm: { const auto *Subst1 = cast(T1); const auto *Subst2 = cast(T2); - if (!IsStructurallyEquivalent(Context, - QualType(Subst1->getReplacedParameter(), 0), - QualType(Subst2->getReplacedParameter(), 0))) - return false; if (!IsStructurallyEquivalent(Context, Subst1->getReplacementType(), Subst2->getReplacementType())) return false; + if (!IsStructurallyEquivalent(Context, Subst1->getAssociatedDecl(), + Subst2->getAssociatedDecl())) + return false; + if (Subst1->getIndex() != Subst2->getIndex()) + return false; if (Subst1->getPackIndex() != Subst2->getPackIndex()) return false; break; @@ -1076,9 +1084,10 @@ case Type::SubstTemplateTypeParmPack: { const auto *Subst1 = cast(T1); const auto *Subst2 = cast(T2); - if (!IsStructurallyEquivalent(Context, - QualType(Subst1->getReplacedParameter(), 0), - QualType(Subst2->getReplacedParameter(), 0))) + if (!IsStructurallyEquivalent(Context, Subst1->getAssociatedDecl(), + Subst2->getAssociatedDecl())) + return false; + if (Subst1->getIndex() != Subst2->getIndex()) return false; if (!IsStructurallyEquivalent(Context, Subst1->getArgumentPack(), Subst2->getArgumentPack())) diff --git a/clang/lib/AST/DeclTemplate.cpp b/clang/lib/AST/DeclTemplate.cpp --- a/clang/lib/AST/DeclTemplate.cpp +++ b/clang/lib/AST/DeclTemplate.cpp @@ -1557,3 +1557,56 @@ const PrintingPolicy &Policy) const { getValue().printPretty(OS, Policy, getType(), &getASTContext()); } + +TemplateParameterList *clang::getReplacedTemplateParameterList(Decl *D) { + switch (D->getKind()) { + case Decl::Kind::ClassTemplate: + return cast(D)->getTemplateParameters(); + case Decl::Kind::ClassTemplateSpecialization: { + const auto *CTSD = cast(D); + auto P = CTSD->getSpecializedTemplateOrPartial(); + if (const auto *CTPSD = + P.dyn_cast()) + return CTPSD->getTemplateParameters(); + return cast(P)->getTemplateParameters(); + } + case Decl::Kind::ClassTemplatePartialSpecialization: + return cast(D) + ->getTemplateParameters(); + case Decl::Kind::TypeAliasTemplate: + return cast(D)->getTemplateParameters(); + case Decl::Kind::BuiltinTemplate: + return cast(D)->getTemplateParameters(); + case Decl::Kind::CXXDeductionGuide: + case Decl::Kind::CXXConversion: + case Decl::Kind::CXXConstructor: + case Decl::Kind::CXXDestructor: + case Decl::Kind::CXXMethod: + case Decl::Kind::Function: + return cast(D) + ->getTemplateSpecializationInfo() + ->getTemplate() + ->getTemplateParameters(); + case Decl::Kind::FunctionTemplate: + return cast(D)->getTemplateParameters(); + case Decl::Kind::VarTemplate: + return cast(D)->getTemplateParameters(); + case Decl::Kind::VarTemplateSpecialization: { + const auto *VTSD = cast(D); + auto P = VTSD->getSpecializedTemplateOrPartial(); + if (const auto *VTPSD = + P.dyn_cast()) + return VTPSD->getTemplateParameters(); + return cast(P)->getTemplateParameters(); + } + case Decl::Kind::VarTemplatePartialSpecialization: + return cast(D) + ->getTemplateParameters(); + case Decl::Kind::TemplateTemplateParm: + return cast(D)->getTemplateParameters(); + case Decl::Kind::Concept: + return cast(D)->getTemplateParameters(); + default: + llvm_unreachable("Unhandled templated declaration kind"); + } +} diff --git a/clang/lib/AST/ExprCXX.cpp b/clang/lib/AST/ExprCXX.cpp --- a/clang/lib/AST/ExprCXX.cpp +++ b/clang/lib/AST/ExprCXX.cpp @@ -1574,6 +1574,11 @@ return new (Storage) SizeOfPackExpr(EmptyShell(), NumPartialArgs); } +NonTypeTemplateParmDecl *SubstNonTypeTemplateParmExpr::getParameter() const { + return cast( + getReplacedTemplateParameterList(getAssociatedDecl())->asArray()[Index]); +} + QualType SubstNonTypeTemplateParmExpr::getParameterType( const ASTContext &Context) const { // Note that, for a class type NTTP, we will have an lvalue of type 'const @@ -1584,15 +1589,22 @@ } SubstNonTypeTemplateParmPackExpr::SubstNonTypeTemplateParmPackExpr( - QualType T, ExprValueKind ValueKind, NonTypeTemplateParmDecl *Param, - SourceLocation NameLoc, const TemplateArgument &ArgPack) + QualType T, ExprValueKind ValueKind, SourceLocation NameLoc, + const TemplateArgument &ArgPack, Decl *AssociatedDecl, unsigned Index) : Expr(SubstNonTypeTemplateParmPackExprClass, T, ValueKind, OK_Ordinary), - Param(Param), Arguments(ArgPack.pack_begin()), - NumArguments(ArgPack.pack_size()), NameLoc(NameLoc) { + AssociatedDecl(AssociatedDecl), Arguments(ArgPack.pack_begin()), + NumArguments(ArgPack.pack_size()), Index(Index), NameLoc(NameLoc) { + assert(AssociatedDecl != nullptr); setDependence(ExprDependence::TypeValueInstantiation | ExprDependence::UnexpandedPack); } +NonTypeTemplateParmDecl * +SubstNonTypeTemplateParmPackExpr::getParameterPack() const { + return cast( + getReplacedTemplateParameterList(getAssociatedDecl())->asArray()[Index]); +} + TemplateArgument SubstNonTypeTemplateParmPackExpr::getArgumentPack() const { return TemplateArgument(llvm::makeArrayRef(Arguments, NumArguments)); } diff --git a/clang/lib/AST/JSONNodeDumper.cpp b/clang/lib/AST/JSONNodeDumper.cpp --- a/clang/lib/AST/JSONNodeDumper.cpp +++ b/clang/lib/AST/JSONNodeDumper.cpp @@ -692,10 +692,16 @@ void JSONNodeDumper::VisitSubstTemplateTypeParmType( const SubstTemplateTypeParmType *STTPT) { + JOS.attribute("index", STTPT->getIndex()); if (auto PackIndex = STTPT->getPackIndex()) JOS.attribute("pack_index", *PackIndex); } +void JSONNodeDumper::VisitSubstTemplateTypeParmPackType( + const SubstTemplateTypeParmPackType *T) { + JOS.attribute("index", T->getIndex()); +} + void JSONNodeDumper::VisitAutoType(const AutoType *AT) { JOS.attribute("undeduced", !AT->isDeduced()); switch (AT->getKeyword()) { diff --git a/clang/lib/AST/ODRHash.cpp b/clang/lib/AST/ODRHash.cpp --- a/clang/lib/AST/ODRHash.cpp +++ b/clang/lib/AST/ODRHash.cpp @@ -671,7 +671,7 @@ } } - void AddDecl(Decl *D) { + void AddDecl(const Decl *D) { Hash.AddBoolean(D); if (D) { Hash.AddDecl(D); @@ -995,13 +995,13 @@ void VisitSubstTemplateTypeParmPackType(const SubstTemplateTypeParmPackType *T) { - AddType(T->getReplacedParameter()); + AddDecl(T->getAssociatedDecl()); Hash.AddTemplateArgument(T->getArgumentPack()); VisitType(T); } void VisitSubstTemplateTypeParmType(const SubstTemplateTypeParmType *T) { - AddType(T->getReplacedParameter()); + AddDecl(T->getAssociatedDecl()); AddQualType(T->getReplacementType()); VisitType(T); } diff --git a/clang/lib/AST/TemplateName.cpp b/clang/lib/AST/TemplateName.cpp --- a/clang/lib/AST/TemplateName.cpp +++ b/clang/lib/AST/TemplateName.cpp @@ -35,31 +35,49 @@ TemplateArgument SubstTemplateTemplateParmPackStorage::getArgumentPack() const { - return TemplateArgument(llvm::makeArrayRef(Arguments, size())); + return TemplateArgument(llvm::makeArrayRef(Arguments, Bits.Data)); +} + +TemplateTemplateParmDecl * +SubstTemplateTemplateParmPackStorage::getParameterPack() const { + return cast( + getReplacedTemplateParameterList(getAssociatedDecl()) + ->asArray()[Bits.Index]); +} + +TemplateTemplateParmDecl * +SubstTemplateTemplateParmStorage::getParameter() const { + return cast( + getReplacedTemplateParameterList(getAssociatedDecl()) + ->asArray()[Bits.Index]); } void SubstTemplateTemplateParmStorage::Profile(llvm::FoldingSetNodeID &ID) { - Profile(ID, Parameter, Replacement); + Profile(ID, Replacement, getAssociatedDecl(), getIndex(), getPackIndex()); } void SubstTemplateTemplateParmStorage::Profile(llvm::FoldingSetNodeID &ID, - TemplateTemplateParmDecl *parameter, - TemplateName replacement) { - ID.AddPointer(parameter); - ID.AddPointer(replacement.getAsVoidPointer()); + TemplateName Replacement, + Decl *AssociatedDecl, + unsigned Index, + Optional PackIndex) { + Replacement.Profile(ID); + ID.AddPointer(AssociatedDecl); + ID.AddInteger(Index); + ID.AddInteger(PackIndex ? *PackIndex + 1 : 0); } void SubstTemplateTemplateParmPackStorage::Profile(llvm::FoldingSetNodeID &ID, ASTContext &Context) { - Profile(ID, Context, Parameter, getArgumentPack()); + Profile(ID, Context, getArgumentPack(), getAssociatedDecl(), getIndex()); } -void SubstTemplateTemplateParmPackStorage::Profile(llvm::FoldingSetNodeID &ID, - ASTContext &Context, - TemplateTemplateParmDecl *Parameter, - const TemplateArgument &ArgPack) { - ID.AddPointer(Parameter); +void SubstTemplateTemplateParmPackStorage::Profile( + llvm::FoldingSetNodeID &ID, ASTContext &Context, + const TemplateArgument &ArgPack, Decl *AssociatedDecl, unsigned Index) { ArgPack.Profile(ID, Context); + ID.AddPointer(AssociatedDecl); + ID.AddInteger(Index); } TemplateName::TemplateName(void *Ptr) { diff --git a/clang/lib/AST/TextNodeDumper.cpp b/clang/lib/AST/TextNodeDumper.cpp --- a/clang/lib/AST/TextNodeDumper.cpp +++ b/clang/lib/AST/TextNodeDumper.cpp @@ -1576,10 +1576,18 @@ void TextNodeDumper::VisitSubstTemplateTypeParmType( const SubstTemplateTypeParmType *T) { + dumpDeclRef(T->getAssociatedDecl()); + VisitTemplateTypeParmDecl(T->getReplacedParameter()); if (auto PackIndex = T->getPackIndex()) OS << " pack_index " << *PackIndex; } +void TextNodeDumper::VisitSubstTemplateTypeParmPackType( + const SubstTemplateTypeParmPackType *T) { + dumpDeclRef(T->getAssociatedDecl()); + VisitTemplateTypeParmDecl(T->getReplacedParameter()); +} + void TextNodeDumper::VisitAutoType(const AutoType *T) { if (T->isDecltypeAuto()) OS << " decltype(auto)"; diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp --- a/clang/lib/AST/Type.cpp +++ b/clang/lib/AST/Type.cpp @@ -1166,8 +1166,9 @@ == T->getReplacementType().getAsOpaquePtr()) return QualType(T, 0); - return Ctx.getSubstTemplateTypeParmType(T->getReplacedParameter(), - replacementType, T->getPackIndex()); + return Ctx.getSubstTemplateTypeParmType(replacementType, + T->getAssociatedDecl(), + T->getIndex(), T->getPackIndex()); } // FIXME: Non-trivial to implement, but important for C++ @@ -3668,28 +3669,54 @@ return isCanonicalUnqualified() ? nullptr : getDecl()->getIdentifier(); } +static const TemplateTypeParmDecl *getReplacedParameter(Decl *D, + unsigned Index) { + if (const auto *TTP = dyn_cast(D)) + return TTP; + return cast( + getReplacedTemplateParameterList(D)->getParam(Index)); +} + SubstTemplateTypeParmType::SubstTemplateTypeParmType( - const TemplateTypeParmType *Param, QualType Replacement, + QualType Replacement, Decl *AssociatedDecl, unsigned Index, Optional PackIndex) : Type(SubstTemplateTypeParm, Replacement.getCanonicalType(), Replacement->getDependence()), - Replaced(Param) { + AssociatedDecl(AssociatedDecl) { SubstTemplateTypeParmTypeBits.HasNonCanonicalUnderlyingType = Replacement != getCanonicalTypeInternal(); if (SubstTemplateTypeParmTypeBits.HasNonCanonicalUnderlyingType) *getTrailingObjects() = Replacement; + SubstTemplateTypeParmTypeBits.Index = Index; SubstTemplateTypeParmTypeBits.PackIndex = PackIndex ? *PackIndex + 1 : 0; + assert(AssociatedDecl != nullptr); +} + +const TemplateTypeParmDecl * +SubstTemplateTypeParmType::getReplacedParameter() const { + return ::getReplacedParameter(getAssociatedDecl(), getIndex()); } SubstTemplateTypeParmPackType::SubstTemplateTypeParmPackType( - const TemplateTypeParmType *Param, QualType Canon, + QualType Canon, Decl *AssociatedDecl, unsigned Index, const TemplateArgument &ArgPack) : Type(SubstTemplateTypeParmPack, Canon, TypeDependence::DependentInstantiation | TypeDependence::UnexpandedPack), - Replaced(Param), Arguments(ArgPack.pack_begin()) { + Arguments(ArgPack.pack_begin()), AssociatedDecl(AssociatedDecl) { + SubstTemplateTypeParmPackTypeBits.Index = Index; SubstTemplateTypeParmPackTypeBits.NumArgs = ArgPack.pack_size(); + assert(AssociatedDecl != nullptr); +} + +const TemplateTypeParmDecl * +SubstTemplateTypeParmPackType::getReplacedParameter() const { + return ::getReplacedParameter(getAssociatedDecl(), getIndex()); +} + +IdentifierInfo *SubstTemplateTypeParmPackType::getIdentifier() const { + return getReplacedParameter()->getIdentifier(); } TemplateArgument SubstTemplateTypeParmPackType::getArgumentPack() const { @@ -3697,13 +3724,15 @@ } void SubstTemplateTypeParmPackType::Profile(llvm::FoldingSetNodeID &ID) { - Profile(ID, getReplacedParameter(), getArgumentPack()); + Profile(ID, getAssociatedDecl(), getIndex(), getArgumentPack()); } void SubstTemplateTypeParmPackType::Profile(llvm::FoldingSetNodeID &ID, - const TemplateTypeParmType *Replaced, + const Decl *AssociatedDecl, + unsigned Index, const TemplateArgument &ArgPack) { - ID.AddPointer(Replaced); + ID.AddPointer(AssociatedDecl); + ID.AddInteger(Index); ID.AddInteger(ArgPack.pack_size()); for (const auto &P : ArgPack.pack_elements()) ID.AddPointer(P.getAsType().getAsOpaquePtr()); diff --git a/clang/lib/AST/TypePrinter.cpp b/clang/lib/AST/TypePrinter.cpp --- a/clang/lib/AST/TypePrinter.cpp +++ b/clang/lib/AST/TypePrinter.cpp @@ -1464,14 +1464,27 @@ const SubstTemplateTypeParmPackType *T, raw_ostream &OS) { IncludeStrongLifetimeRAII Strong(Policy); - printTemplateTypeParmBefore(T->getReplacedParameter(), OS); + if (const TemplateTypeParmDecl *D = T->getReplacedParameter()) { + if (D && D->isImplicit()) { + if (auto *TC = D->getTypeConstraint()) { + TC->print(OS, Policy); + OS << ' '; + } + OS << "auto"; + } else if (IdentifierInfo *Id = D->getIdentifier()) + OS << (Policy.CleanUglifiedParameters ? Id->deuglifiedName() + : Id->getName()); + else + OS << "type-parameter-" << D->getDepth() << '-' << D->getIndex(); + + spaceBeforePlaceHolder(OS); + } } void TypePrinter::printSubstTemplateTypeParmPackAfter( const SubstTemplateTypeParmPackType *T, raw_ostream &OS) { IncludeStrongLifetimeRAII Strong(Policy); - printTemplateTypeParmAfter(T->getReplacedParameter(), OS); } void TypePrinter::printTemplateId(const TemplateSpecializationType *T, 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 @@ -396,8 +396,9 @@ // has no access to the MultiLevelTemplateArgumentList, so this has to happen // here. llvm::SmallVector FlattenedArgs; - for (ArrayRef List : TemplateArgsLists) - FlattenedArgs.insert(FlattenedArgs.end(), List.begin(), List.end()); + for (auto List : TemplateArgsLists) + FlattenedArgs.insert(FlattenedArgs.end(), List.Args.begin(), + List.Args.end()); llvm::FoldingSetNodeID ID; ConstraintSatisfaction::Profile(ID, Context, Template, FlattenedArgs); @@ -452,7 +453,7 @@ // the list of current template arguments to the list so that they also can // be picked out of the map. if (auto *SpecArgs = FD->getTemplateSpecializationArgs()) { - MultiLevelTemplateArgumentList JustTemplArgs(*SpecArgs); + MultiLevelTemplateArgumentList JustTemplArgs(FD, SpecArgs->asArray()); if (addInstantiatedParametersToScope( FD, PrimaryTemplate->getTemplatedDecl(), Scope, JustTemplArgs)) return true; 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 @@ -8960,13 +8960,13 @@ Context.getReferenceQualifiedType(E).getCanonicalType(); llvm::SmallVector Args; Args.push_back(TemplateArgument(MatchedType)); + + auto *Param = cast(TPL->getParam(0)); + TemplateArgumentList TAL(TemplateArgumentList::OnStack, Args); - MultiLevelTemplateArgumentList MLTAL(TAL); - for (unsigned I = 0; I < TPL->getDepth(); ++I) - MLTAL.addOuterRetainedLevel(); - Expr *IDC = - cast(TPL->getParam(0))->getTypeConstraint() - ->getImmediatelyDeclaredConstraint(); + MultiLevelTemplateArgumentList MLTAL(Param, TAL.asArray()); + MLTAL.addOuterRetainedLevels(TPL->getDepth()); + Expr *IDC = Param->getTypeConstraint()->getImmediatelyDeclaredConstraint(); ExprResult Constraint = SubstExpr(IDC, MLTAL); if (Constraint.isInvalid()) { Status = concepts::ExprRequirement::SS_ExprSubstitutionFailure; 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 @@ -3581,16 +3581,11 @@ TemplateArgumentListInfo &TemplateArgs) { ASTContext &Context = SemaRef.getASTContext(); - TemplateParameterList *TPL = BTD->getTemplateParameters(); - // Wrap the type in substitution sugar. auto getSubstType = [&](QualType Replacement, unsigned IndexReplaced, Optional PackIndexReplaced) { - QualType TTP = SemaRef.Context.getTemplateTypeParmType( - 0, IndexReplaced, false, - cast(TPL->getParam(IndexReplaced))); return SemaRef.Context.getSubstTemplateTypeParmType( - cast(TTP), Replacement, PackIndexReplaced); + Replacement, BTD, IndexReplaced, PackIndexReplaced); }; switch (BTD->getBuiltinTemplateKind()) { @@ -3639,8 +3634,7 @@ // Wrap the template in substitution sugar. TemplateName TN = SemaRef.Context.getSubstTemplateTemplateParm( - cast(TPL->getParam(0)), - Converted[0].getAsTemplate()); + Converted[0].getAsTemplate(), BTD, 0, None); // The first template argument will be reused as the template decl that // our synthetic template arguments will be applied to. @@ -3872,7 +3866,8 @@ // Only substitute for the innermost template argument list. MultiLevelTemplateArgumentList TemplateArgLists; - TemplateArgLists.addOuterTemplateArguments(&StackTemplateArgs); + TemplateArgLists.addOuterTemplateArguments(Template, + StackTemplateArgs.asArray()); TemplateArgLists.addOuterRetainedLevels( AliasTemplate->getTemplateParameters()->getDepth()); @@ -3997,7 +3992,7 @@ InstantiatingTemplate Inst(*this, TemplateLoc, Decl); if (!Inst.isInvalid()) { MultiLevelTemplateArgumentList TemplateArgLists; - TemplateArgLists.addOuterTemplateArguments(Converted); + TemplateArgLists.addOuterTemplateArguments(Template, Converted); InstantiateAttrsForDecl(TemplateArgLists, ClassTemplate->getTemplatedDecl(), Decl); } @@ -4876,7 +4871,7 @@ TemplateSpecializationType::anyDependentTemplateArguments(*TemplateArgs, Converted); MultiLevelTemplateArgumentList MLTAL; - MLTAL.addOuterTemplateArguments(Converted); + MLTAL.addOuterTemplateArguments(NamedConcept, Converted); LocalInstantiationScope Scope(*this); if (!AreArgsDependent && CheckConstraintSatisfaction( @@ -5286,8 +5281,8 @@ TemplateArgumentList TemplateArgs(TemplateArgumentList::OnStack, Converted); // Only substitute for the innermost template argument list. - MultiLevelTemplateArgumentList TemplateArgLists; - TemplateArgLists.addOuterTemplateArguments(&TemplateArgs); + MultiLevelTemplateArgumentList TemplateArgLists(Template, + TemplateArgs.asArray()); for (unsigned i = 0, e = Param->getDepth(); i != e; ++i) TemplateArgLists.addOuterTemplateArguments(None); @@ -5342,8 +5337,8 @@ TemplateArgumentList TemplateArgs(TemplateArgumentList::OnStack, Converted); // Only substitute for the innermost template argument list. - MultiLevelTemplateArgumentList TemplateArgLists; - TemplateArgLists.addOuterTemplateArguments(&TemplateArgs); + MultiLevelTemplateArgumentList TemplateArgLists(Template, + TemplateArgs.asArray()); for (unsigned i = 0, e = Param->getDepth(); i != e; ++i) TemplateArgLists.addOuterTemplateArguments(None); @@ -5395,8 +5390,8 @@ TemplateArgumentList TemplateArgs(TemplateArgumentList::OnStack, Converted); // Only substitute for the innermost template argument list. - MultiLevelTemplateArgumentList TemplateArgLists; - TemplateArgLists.addOuterTemplateArguments(&TemplateArgs); + MultiLevelTemplateArgumentList TemplateArgLists(Template, + TemplateArgs.asArray()); for (unsigned i = 0, e = Param->getDepth(); i != e; ++i) TemplateArgLists.addOuterTemplateArguments(None); @@ -5580,18 +5575,15 @@ TemplateArgumentList TemplateArgs(TemplateArgumentList::OnStack, Converted); + MultiLevelTemplateArgumentList MLTAL(Template, TemplateArgs.asArray()); // If the parameter is a pack expansion, expand this slice of the pack. if (auto *PET = NTTPType->getAs()) { Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(*this, ArgumentPackIndex); - NTTPType = SubstType(PET->getPattern(), - MultiLevelTemplateArgumentList(TemplateArgs), - NTTP->getLocation(), + NTTPType = SubstType(PET->getPattern(), MLTAL, NTTP->getLocation(), NTTP->getDeclName()); } else { - NTTPType = SubstType(NTTPType, - MultiLevelTemplateArgumentList(TemplateArgs), - NTTP->getLocation(), + NTTPType = SubstType(NTTPType, MLTAL, NTTP->getLocation(), NTTP->getDeclName()); } @@ -5734,15 +5726,15 @@ { // Set up a template instantiation context. LocalInstantiationScope Scope(*this); - InstantiatingTemplate Inst(*this, TemplateLoc, Template, - TempParm, Converted, - SourceRange(TemplateLoc, RAngleLoc)); + InstantiatingTemplate Inst(*this, TemplateLoc, Template, TempParm, + Converted, SourceRange(TemplateLoc, RAngleLoc)); if (Inst.isInvalid()) return true; TemplateArgumentList TemplateArgs(TemplateArgumentList::OnStack, Converted); - Params = SubstTemplateParams(Params, CurContext, - MultiLevelTemplateArgumentList(TemplateArgs)); + Params = SubstTemplateParams( + Params, CurContext, + MultiLevelTemplateArgumentList(Template, TemplateArgs.asArray())); if (!Params) return 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 @@ -2687,7 +2687,7 @@ if (PackedArgsBuilder.empty()) { LocalInstantiationScope Scope(S); TemplateArgumentList TemplateArgs(TemplateArgumentList::OnStack, Output); - MultiLevelTemplateArgumentList Args(TemplateArgs); + MultiLevelTemplateArgumentList Args(Template, TemplateArgs.asArray()); if (auto *NTTP = dyn_cast(Param)) { Sema::InstantiatingTemplate Inst(S, Template->getLocation(), Template, @@ -2870,12 +2870,11 @@ TemplateDeductionInfo& Info) { llvm::SmallVector AssociatedConstraints; Template->getAssociatedConstraints(AssociatedConstraints); - MultiLevelTemplateArgumentList MLTAL; bool NeedsReplacement = DeducedArgsNeedReplacement(Template); TemplateArgumentList DeducedTAL{TemplateArgumentList::OnStack, DeducedArgs}; - MLTAL = S.getTemplateInstantiationArgs( + MultiLevelTemplateArgumentList MLTAL = S.getTemplateInstantiationArgs( Template, /*InnerMost=*/NeedsReplacement ? nullptr : &DeducedTAL, /*RelativeToPrimary=*/true, /*Pattern=*/ nullptr, /*ForConstraintInstantiation=*/true); @@ -2940,9 +2939,10 @@ TemplateArgumentListInfo InstArgs(PartialTemplArgInfo->LAngleLoc, PartialTemplArgInfo->RAngleLoc); - if (S.SubstTemplateArguments( - PartialTemplArgInfo->arguments(), - MultiLevelTemplateArgumentList(*DeducedArgumentList), InstArgs)) { + if (S.SubstTemplateArguments(PartialTemplArgInfo->arguments(), + MultiLevelTemplateArgumentList( + Partial, DeducedArgumentList->asArray()), + InstArgs)) { unsigned ArgIdx = InstArgs.size(), ParamIdx = ArgIdx; if (ParamIdx >= Partial->getTemplateParameters()->size()) ParamIdx = Partial->getTemplateParameters()->size() - 1; @@ -3279,7 +3279,8 @@ if (Proto->hasTrailingReturn()) { if (SubstParmTypes(Function->getLocation(), Function->parameters(), Proto->getExtParameterInfosOrNull(), - MultiLevelTemplateArgumentList(*ExplicitArgumentList), + MultiLevelTemplateArgumentList( + FunctionTemplate, ExplicitArgumentList->asArray()), ParamTypes, /*params*/ nullptr, ExtParamInfos)) return TDK_SubstitutionFailure; } @@ -3305,7 +3306,8 @@ ResultType = SubstType(Proto->getReturnType(), - MultiLevelTemplateArgumentList(*ExplicitArgumentList), + MultiLevelTemplateArgumentList( + FunctionTemplate, ExplicitArgumentList->asArray()), Function->getTypeSpecStartLoc(), Function->getDeclName()); if (ResultType.isNull() || Trap.hasErrorOccurred()) return TDK_SubstitutionFailure; @@ -3323,7 +3325,8 @@ if (!Proto->hasTrailingReturn() && SubstParmTypes(Function->getLocation(), Function->parameters(), Proto->getExtParameterInfosOrNull(), - MultiLevelTemplateArgumentList(*ExplicitArgumentList), + MultiLevelTemplateArgumentList( + FunctionTemplate, ExplicitArgumentList->asArray()), ParamTypes, /*params*/ nullptr, ExtParamInfos)) return TDK_SubstitutionFailure; @@ -3338,7 +3341,8 @@ if (getLangOpts().CPlusPlus17 && SubstExceptionSpec( Function->getLocation(), EPI.ExceptionSpec, ExceptionStorage, - MultiLevelTemplateArgumentList(*ExplicitArgumentList))) + MultiLevelTemplateArgumentList(FunctionTemplate, + ExplicitArgumentList->asArray()))) return TDK_SubstitutionFailure; *FunctionType = BuildFunctionType(ResultType, ParamTypes, @@ -3578,7 +3582,8 @@ DeclContext *Owner = FunctionTemplate->getDeclContext(); if (FunctionTemplate->getFriendObjectKind()) Owner = FunctionTemplate->getLexicalDeclContext(); - MultiLevelTemplateArgumentList SubstArgs(*DeducedArgumentList); + MultiLevelTemplateArgumentList SubstArgs(FunctionTemplate, + DeducedArgumentList->asArray()); Specialization = cast_or_null( SubstDecl(FunctionTemplate->getTemplatedDecl(), Owner, SubstArgs)); if (!Specialization || Specialization->isInvalidDecl()) @@ -4635,7 +4640,7 @@ /*PartialTemplateArgs=*/false, Converted)) return true; MultiLevelTemplateArgumentList MLTAL; - MLTAL.addOuterTemplateArguments(Converted); + MLTAL.addOuterTemplateArguments(Concept, Converted); if (S.CheckConstraintSatisfaction(Concept, {Concept->getConstraintExpr()}, MLTAL, TypeLoc.getLocalSourceRange(), Satisfaction)) @@ -5939,9 +5944,8 @@ case Type::SubstTemplateTypeParmPack: { const SubstTemplateTypeParmPackType *Subst = cast(T); - MarkUsedTemplateParameters(Ctx, - QualType(Subst->getReplacedParameter(), 0), - OnlyDeduced, Depth, Used); + if (Subst->getReplacedParameter()->getDepth() == Depth) + Used[Subst->getIndex()] = true; MarkUsedTemplateParameters(Ctx, Subst->getArgumentPack(), OnlyDeduced, Depth, Used); break; 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 @@ -86,9 +86,6 @@ !isa(VarTemplSpec)) return Response::Done(); - Result.addOuterTemplateArguments( - &VarTemplSpec->getTemplateInstantiationArgs()); - // If this variable template specialization was instantiated from a // specialized member that is a variable template, we're done. assert(VarTemplSpec->getSpecializedTemplate() && "No variable template?"); @@ -96,10 +93,14 @@ Specialized = VarTemplSpec->getSpecializedTemplateOrPartial(); if (VarTemplatePartialSpecializationDecl *Partial = Specialized.dyn_cast()) { + Result.addOuterTemplateArguments( + Partial, VarTemplSpec->getTemplateInstantiationArgs().asArray()); if (Partial->isMemberSpecialization()) return Response::Done(); } else { VarTemplateDecl *Tmpl = Specialized.get(); + Result.addOuterTemplateArguments( + Tmpl, VarTemplSpec->getTemplateInstantiationArgs().asArray()); if (Tmpl->isMemberSpecialization()) return Response::Done(); } @@ -131,7 +132,8 @@ return Response::Done(); Result.addOuterTemplateArguments( - &ClassTemplSpec->getTemplateInstantiationArgs()); + const_cast(ClassTemplSpec), + ClassTemplSpec->getTemplateInstantiationArgs().asArray()); // If this class template specialization was instantiated from a // specialized member that is a class template, we're done. @@ -161,7 +163,8 @@ } else if (const TemplateArgumentList *TemplateArgs = Function->getTemplateSpecializationArgs()) { // Add the template arguments for this specialization. - Result.addOuterTemplateArguments(TemplateArgs); + Result.addOuterTemplateArguments(const_cast(Function), + TemplateArgs->asArray()); // If this function was instantiated from a specialized member that is // a function template, we're done. @@ -206,7 +209,8 @@ QualType Injected = cast(RecordType) ->getInjectedSpecializationType(); const auto *InjectedType = cast(Injected); - Result.addOuterTemplateArguments(InjectedType->template_arguments()); + Result.addOuterTemplateArguments(const_cast(Rec), + InjectedType->template_arguments()); } } @@ -266,7 +270,8 @@ MultiLevelTemplateArgumentList Result; if (Innermost) - Result.addOuterTemplateArguments(Innermost); + Result.addOuterTemplateArguments(const_cast(ND), + Innermost->asArray()); const Decl *CurDecl = ND; @@ -1371,9 +1376,9 @@ Sema::ExtParameterInfoBuilder &PInfos); private: - ExprResult transformNonTypeTemplateParmRef(NonTypeTemplateParmDecl *parm, - SourceLocation loc, - TemplateArgument arg); + ExprResult transformNonTypeTemplateParmRef( + Decl *AssociatedDecl, const NonTypeTemplateParmDecl *parm, + SourceLocation loc, TemplateArgument arg, Optional PackIndex); }; } @@ -1563,6 +1568,8 @@ return Arg.getAsTemplate(); } + Decl *AssociatedDecl = TemplateArgs.getAssociatedDecl(TTP->getDepth()); + Optional PackIndex; if (TTP->isParameterPack()) { assert(Arg.getKind() == TemplateArgument::Pack && "Missing argument pack"); @@ -1571,10 +1578,12 @@ // We have the template argument pack to substitute, but we're not // actually expanding the enclosing pack expansion yet. So, just // keep the entire argument pack. - return getSema().Context.getSubstTemplateTemplateParmPack(TTP, Arg); + return getSema().Context.getSubstTemplateTemplateParmPack( + Arg, AssociatedDecl, TTP->getIndex()); } Arg = getPackSubstitutedTemplateArgument(getSema(), Arg); + PackIndex = getSema().ArgumentPackSubstitutionIndex; } TemplateName Template = Arg.getAsTemplate().getNameToSubstitute(); @@ -1582,7 +1591,8 @@ assert(!Template.getAsQualifiedTemplateName() && "template decl to substitute is qualified?"); - Template = getSema().Context.getSubstTemplateTemplateParm(TTP, Template); + Template = getSema().Context.getSubstTemplateTemplateParm( + Template, AssociatedDecl, TTP->getIndex(), PackIndex); return Template; } } @@ -1638,6 +1648,8 @@ return Arg.getAsExpr(); } + Decl *AssociatedDecl = TemplateArgs.getAssociatedDecl(NTTP->getDepth()); + Optional PackIndex; if (NTTP->isParameterPack()) { assert(Arg.getKind() == TemplateArgument::Pack && "Missing argument pack"); @@ -1658,13 +1670,14 @@ return new (SemaRef.Context) SubstNonTypeTemplateParmPackExpr( ExprType, TargetType->isReferenceType() ? VK_LValue : VK_PRValue, - NTTP, E->getLocation(), Arg); + E->getLocation(), Arg, AssociatedDecl, NTTP->getPosition()); } - + PackIndex = getSema().ArgumentPackSubstitutionIndex; Arg = getPackSubstitutedTemplateArgument(getSema(), Arg); } - return transformNonTypeTemplateParmRef(NTTP, E->getLocation(), Arg); + return transformNonTypeTemplateParmRef(AssociatedDecl, NTTP, E->getLocation(), + Arg, PackIndex); } const LoopHintAttr * @@ -1685,9 +1698,8 @@ } ExprResult TemplateInstantiator::transformNonTypeTemplateParmRef( - NonTypeTemplateParmDecl *parm, - SourceLocation loc, - TemplateArgument arg) { + Decl *AssociatedDecl, const NonTypeTemplateParmDecl *parm, + SourceLocation loc, TemplateArgument arg, Optional PackIndex) { ExprResult result; // Determine the substituted parameter type. We can usually infer this from @@ -1756,23 +1768,24 @@ Expr *resultExpr = result.get(); return new (SemaRef.Context) SubstNonTypeTemplateParmExpr( - resultExpr->getType(), resultExpr->getValueKind(), loc, parm, refParam, - resultExpr); + resultExpr->getType(), resultExpr->getValueKind(), loc, resultExpr, + AssociatedDecl, parm->getIndex(), PackIndex, refParam); } ExprResult TemplateInstantiator::TransformSubstNonTypeTemplateParmPackExpr( SubstNonTypeTemplateParmPackExpr *E) { - if (getSema().ArgumentPackSubstitutionIndex == -1) { + int PackIndex = getSema().ArgumentPackSubstitutionIndex; + if (PackIndex == -1) { // We aren't expanding the parameter pack, so just return ourselves. return E; } TemplateArgument Arg = E->getArgumentPack(); Arg = getPackSubstitutedTemplateArgument(getSema(), Arg); - return transformNonTypeTemplateParmRef(E->getParameterPack(), - E->getParameterPackLocation(), - Arg); + return transformNonTypeTemplateParmRef( + E->getAssociatedDecl(), E->getParameterPack(), + E->getParameterPackLocation(), Arg, PackIndex); } ExprResult @@ -1811,8 +1824,9 @@ SubstReplacement.get(), Converted).isInvalid()) return true; - return transformNonTypeTemplateParmRef(E->getParameter(), - E->getExprLoc(), Converted); + return transformNonTypeTemplateParmRef(E->getAssociatedDecl(), + E->getParameter(), E->getExprLoc(), + Converted, E->getPackIndex()); } ExprResult TemplateInstantiator::RebuildVarDeclRefExpr(VarDecl *PD, @@ -1982,6 +1996,8 @@ return NewT; } + Decl *AssociatedDecl = + const_cast(TemplateArgs.getAssociatedDecl(T->getDepth())); Optional PackIndex; if (T->isParameterPack()) { assert(Arg.getKind() == TemplateArgument::Pack && @@ -1991,8 +2007,8 @@ // We have the template argument pack, but we're not expanding the // enclosing pack expansion yet. Just save the template argument // pack for later substitution. - QualType Result - = getSema().Context.getSubstTemplateTypeParmPackType(T, Arg); + QualType Result = getSema().Context.getSubstTemplateTypeParmPackType( + AssociatedDecl, T->getIndex(), Arg); SubstTemplateTypeParmPackTypeLoc NewTL = TLB.push(Result); NewTL.setNameLoc(TL.getNameLoc()); @@ -2011,7 +2027,7 @@ // TODO: only do this uniquing once, at the start of instantiation. QualType Result = getSema().Context.getSubstTemplateTypeParmType( - T, Replacement, PackIndex); + Replacement, AssociatedDecl, T->getIndex(), PackIndex); SubstTemplateTypeParmTypeLoc NewTL = TLB.push(Result); NewTL.setNameLoc(TL.getNameLoc()); @@ -2025,8 +2041,7 @@ TemplateTypeParmDecl *NewTTPDecl = nullptr; if (TemplateTypeParmDecl *OldTTPDecl = T->getDecl()) NewTTPDecl = cast_or_null( - TransformDecl(TL.getNameLoc(), OldTTPDecl)); - + TransformDecl(TL.getNameLoc(), OldTTPDecl)); QualType Result = getSema().Context.getTemplateTypeParmType( T->getDepth() - TemplateArgs.getNumSubstitutedLevels(), T->getIndex(), T->isParameterPack(), NewTTPDecl); @@ -2035,27 +2050,32 @@ return Result; } -QualType -TemplateInstantiator::TransformSubstTemplateTypeParmPackType( - TypeLocBuilder &TLB, - SubstTemplateTypeParmPackTypeLoc TL) { +QualType TemplateInstantiator::TransformSubstTemplateTypeParmPackType( + TypeLocBuilder &TLB, SubstTemplateTypeParmPackTypeLoc TL) { + const SubstTemplateTypeParmPackType *T = TL.getTypePtr(); + + Decl *NewReplaced = TransformDecl(TL.getNameLoc(), T->getAssociatedDecl()); + if (getSema().ArgumentPackSubstitutionIndex == -1) { // We aren't expanding the parameter pack, so just return ourselves. - SubstTemplateTypeParmPackTypeLoc NewTL - = TLB.push(TL.getType()); + QualType Result = TL.getType(); + if (NewReplaced != T->getAssociatedDecl()) + Result = getSema().Context.getSubstTemplateTypeParmPackType( + NewReplaced, T->getIndex(), T->getArgumentPack()); + SubstTemplateTypeParmPackTypeLoc NewTL = + TLB.push(Result); NewTL.setNameLoc(TL.getNameLoc()); - return TL.getType(); + return Result; } - const SubstTemplateTypeParmPackType *T = TL.getTypePtr(); TemplateArgument Pack = T->getArgumentPack(); TemplateArgument Arg = getPackSubstitutedTemplateArgument(getSema(), Pack); // PackIndex starts from last element. QualType Result = getSema().Context.getSubstTemplateTypeParmType( - T->getReplacedParameter(), Arg.getAsType(), + Arg.getAsType(), NewReplaced, T->getIndex(), Pack.pack_size() - 1 - getSema().ArgumentPackSubstitutionIndex); - SubstTemplateTypeParmTypeLoc NewTL - = TLB.push(Result); + SubstTemplateTypeParmTypeLoc NewTL = + TLB.push(Result); NewTL.setNameLoc(TL.getNameLoc()); return Result; } 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 @@ -4761,7 +4761,7 @@ return nullptr; ContextRAII SavedContext(*this, FD); - MultiLevelTemplateArgumentList MArgs(*Args); + MultiLevelTemplateArgumentList MArgs(FTD, Args->asArray()); return cast_or_null(SubstDecl(FD, FD->getParent(), MArgs)); } @@ -5097,8 +5097,7 @@ const TemplateArgumentList &TemplateArgList, const TemplateArgumentListInfo &TemplateArgsInfo, SmallVectorImpl &Converted, - SourceLocation PointOfInstantiation, - LateInstantiatedAttrVec *LateAttrs, + SourceLocation PointOfInstantiation, LateInstantiatedAttrVec *LateAttrs, LocalInstantiationScope *StartingScope) { if (FromVar->isInvalidDecl()) return nullptr; @@ -5107,9 +5106,6 @@ if (Inst.isInvalid()) return nullptr; - MultiLevelTemplateArgumentList TemplateArgLists; - TemplateArgLists.addOuterTemplateArguments(&TemplateArgList); - // Instantiate the first declaration of the variable template: for a partial // specialization of a static data member template, the first declaration may // or may not be the declaration in the class; if it's in the class, we want @@ -5120,15 +5116,21 @@ // partial specialization, don't do this. The member specialization completely // replaces the original declaration in this case. bool IsMemberSpec = false; - if (VarTemplatePartialSpecializationDecl *PartialSpec = - dyn_cast(FromVar)) + MultiLevelTemplateArgumentList MultiLevelList; + if (auto *PartialSpec = + dyn_cast(FromVar)) { IsMemberSpec = PartialSpec->isMemberSpecialization(); - else if (VarTemplateDecl *FromTemplate = FromVar->getDescribedVarTemplate()) - IsMemberSpec = FromTemplate->isMemberSpecialization(); + MultiLevelList.addOuterTemplateArguments(PartialSpec, + TemplateArgList.asArray()); + } else { + assert(VarTemplate == FromVar->getDescribedVarTemplate()); + IsMemberSpec = VarTemplate->isMemberSpecialization(); + MultiLevelList.addOuterTemplateArguments(VarTemplate, + TemplateArgList.asArray()); + } if (!IsMemberSpec) FromVar = FromVar->getFirstDecl(); - MultiLevelTemplateArgumentList MultiLevelList(TemplateArgList); TemplateDeclInstantiator Instantiator(*this, FromVar->getDeclContext(), MultiLevelList); diff --git a/clang/lib/Sema/SemaTemplateVariadic.cpp b/clang/lib/Sema/SemaTemplateVariadic.cpp --- a/clang/lib/Sema/SemaTemplateVariadic.cpp +++ b/clang/lib/Sema/SemaTemplateVariadic.cpp @@ -720,7 +720,7 @@ } else if (const auto *STP = P.dyn_cast()) { NewPackSize = STP->getNumArgs(); - ND = STP->getReplacedParameter()->getDecl(); + ND = STP->getReplacedParameter(); } else { const auto *SEP = P.get(); NewPackSize = SEP->getArgumentPack().pack_size(); diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -1285,9 +1285,10 @@ /// be resolved to a specific template, then builds the appropriate kind of /// template name. Subclasses may override this routine to provide different /// behavior. - TemplateName RebuildTemplateName(TemplateTemplateParmDecl *Param, - const TemplateArgument &ArgPack) { - return getSema().Context.getSubstTemplateTemplateParmPack(Param, ArgPack); + TemplateName RebuildTemplateName(const TemplateArgument &ArgPack, + Decl *AssociatedDecl, unsigned Index) { + return getSema().Context.getSubstTemplateTemplateParmPack( + ArgPack, AssociatedDecl, Index); } /// Build a new compound statement. @@ -4391,18 +4392,9 @@ if (SubstTemplateTemplateParmPackStorage *SubstPack = Name.getAsSubstTemplateTemplateParmPack()) { - TemplateTemplateParmDecl *TransParam - = cast_or_null( - getDerived().TransformDecl(NameLoc, SubstPack->getParameterPack())); - if (!TransParam) - return TemplateName(); - - if (!getDerived().AlwaysRebuild() && - TransParam == SubstPack->getParameterPack()) - return Name; - - return getDerived().RebuildTemplateName(TransParam, - SubstPack->getArgumentPack()); + return getDerived().RebuildTemplateName(SubstPack->getArgumentPack(), + SubstPack->getAssociatedDecl(), + SubstPack->getIndex()); } // These should be getting filtered out before they reach the AST. @@ -4887,8 +4879,8 @@ Replacement = SemaRef.Context.getQualifiedType( Replacement.getUnqualifiedType(), Qs); T = SemaRef.Context.getSubstTemplateTypeParmType( - SubstTypeParam->getReplacedParameter(), Replacement, - SubstTypeParam->getPackIndex()); + Replacement, SubstTypeParam->getAssociatedDecl(), + SubstTypeParam->getIndex(), SubstTypeParam->getPackIndex()); } else if ((AutoTy = dyn_cast(T)) && AutoTy->isDeduced()) { // 'auto' types behave the same way as template parameters. QualType Deduced = AutoTy->getDeducedType(); @@ -6440,6 +6432,9 @@ SubstTemplateTypeParmTypeLoc TL) { const SubstTemplateTypeParmType *T = TL.getTypePtr(); + Decl *NewReplaced = + getDerived().TransformDecl(TL.getNameLoc(), T->getAssociatedDecl()); + // Substitute into the replacement type, which itself might involve something // that needs to be transformed. This only tends to occur with default // template arguments of template template parameters. @@ -6449,7 +6444,7 @@ return QualType(); QualType Result = SemaRef.Context.getSubstTemplateTypeParmType( - T->getReplacedParameter(), Replacement, T->getPackIndex()); + Replacement, NewReplaced, T->getIndex(), T->getPackIndex()); // Propagate type-source information. SubstTemplateTypeParmTypeLoc NewTL diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp --- a/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/clang/lib/Serialization/ASTReaderDecl.cpp @@ -382,7 +382,7 @@ void VisitDecompositionDecl(DecompositionDecl *DD); void VisitBindingDecl(BindingDecl *BD); void VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D); - DeclID VisitTemplateDecl(TemplateDecl *D); + void VisitTemplateDecl(TemplateDecl *D); void VisitConceptDecl(ConceptDecl *D); void VisitRequiresExprBodyDecl(RequiresExprBodyDecl *D); RedeclarableResult VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D); @@ -415,14 +415,15 @@ template RedeclarableResult VisitRedeclarable(Redeclarable *D); - template - void mergeRedeclarable(Redeclarable *D, RedeclarableResult &Redecl, - DeclID TemplatePatternID = 0); + template + void mergeRedeclarable(Redeclarable *D, RedeclarableResult &Redecl); - template + void mergeRedeclarableTemplate(RedeclarableTemplateDecl *D, + RedeclarableResult &Redecl); + + template void mergeRedeclarable(Redeclarable *D, T *Existing, - RedeclarableResult &Redecl, - DeclID TemplatePatternID = 0); + RedeclarableResult &Redecl); template void mergeMergeable(Mergeable *D); @@ -431,7 +432,7 @@ void mergeTemplatePattern(RedeclarableTemplateDecl *D, RedeclarableTemplateDecl *Existing, - DeclID DsID, bool IsKeyDecl); + bool IsKeyDecl); ObjCTypeParamList *ReadObjCTypeParamList(); @@ -887,90 +888,27 @@ void ASTDeclReader::VisitFunctionDecl(FunctionDecl *FD) { RedeclarableResult Redecl = VisitRedeclarable(FD); - VisitDeclaratorDecl(FD); - - // Attach a type to this function. Use the real type if possible, but fall - // back to the type as written if it involves a deduced return type. - if (FD->getTypeSourceInfo() && - FD->getTypeSourceInfo()->getType()->castAs() - ->getReturnType()->getContainedAutoType()) { - // We'll set up the real type in Visit, once we've finished loading the - // function. - FD->setType(FD->getTypeSourceInfo()->getType()); - Reader.PendingFunctionTypes.push_back({FD, DeferredTypeID}); - } else { - FD->setType(Reader.GetType(DeferredTypeID)); - } - DeferredTypeID = 0; - FD->DNLoc = Record.readDeclarationNameLoc(FD->getDeclName()); - FD->IdentifierNamespace = Record.readInt(); - - // FunctionDecl's body is handled last at ASTDeclReader::Visit, - // after everything else is read. - - FD->setStorageClass(static_cast(Record.readInt())); - FD->setInlineSpecified(Record.readInt()); - FD->setImplicitlyInline(Record.readInt()); - FD->setVirtualAsWritten(Record.readInt()); - // We defer calling `FunctionDecl::setPure()` here as for methods of - // `CXXTemplateSpecializationDecl`s, we may not have connected up the - // definition (which is required for `setPure`). - const bool Pure = Record.readInt(); - FD->setHasInheritedPrototype(Record.readInt()); - FD->setHasWrittenPrototype(Record.readInt()); - FD->setDeletedAsWritten(Record.readInt()); - FD->setTrivial(Record.readInt()); - FD->setTrivialForCall(Record.readInt()); - FD->setDefaulted(Record.readInt()); - FD->setExplicitlyDefaulted(Record.readInt()); - FD->setHasImplicitReturnZero(Record.readInt()); - FD->setConstexprKind(static_cast(Record.readInt())); - FD->setUsesSEHTry(Record.readInt()); - FD->setHasSkippedBody(Record.readInt()); - FD->setIsMultiVersion(Record.readInt()); - FD->setLateTemplateParsed(Record.readInt()); - FD->setFriendConstraintRefersToEnclosingTemplate(Record.readInt()); - - FD->setCachedLinkage(static_cast(Record.readInt())); - FD->EndRangeLoc = readSourceLocation(); - FD->setDefaultLoc(readSourceLocation()); - - FD->ODRHash = Record.readInt(); - FD->setHasODRHash(true); - - if (FD->isDefaulted()) { - if (unsigned NumLookups = Record.readInt()) { - SmallVector Lookups; - for (unsigned I = 0; I != NumLookups; ++I) { - NamedDecl *ND = Record.readDeclAs(); - AccessSpecifier AS = (AccessSpecifier)Record.readInt(); - Lookups.push_back(DeclAccessPair::make(ND, AS)); - } - FD->setDefaultedFunctionInfo(FunctionDecl::DefaultedFunctionInfo::Create( - Reader.getContext(), Lookups)); - } - } + FunctionDecl *Existing = nullptr; switch ((FunctionDecl::TemplatedKind)Record.readInt()) { case FunctionDecl::TK_NonTemplate: - mergeRedeclarable(FD, Redecl); break; case FunctionDecl::TK_DependentNonTemplate: - mergeRedeclarable(FD, Redecl); FD->setInstantiatedFromDecl(readDeclAs()); break; - case FunctionDecl::TK_FunctionTemplate: - // Merged when we merge the template. - FD->setDescribedFunctionTemplate(readDeclAs()); + case FunctionDecl::TK_FunctionTemplate: { + auto *Template = readDeclAs(); + Template->init(FD); + FD->setDescribedFunctionTemplate(Template); break; + } case FunctionDecl::TK_MemberSpecialization: { auto *InstFD = readDeclAs(); auto TSK = (TemplateSpecializationKind)Record.readInt(); SourceLocation POI = readSourceLocation(); FD->setInstantiationOfMemberFunction(Reader.getContext(), InstFD, TSK); FD->getMemberSpecializationInfo()->setPointOfInstantiation(POI); - mergeRedeclarable(FD, Redecl); break; } case FunctionDecl::TK_FunctionTemplateSpecialization: { @@ -1041,7 +979,7 @@ else { assert(Reader.getContext().getLangOpts().Modules && "already deserialized this template specialization"); - mergeRedeclarable(FD, ExistingInfo->getFunction(), Redecl); + Existing = ExistingInfo->getFunction(); } } break; @@ -1069,6 +1007,96 @@ } } + VisitDeclaratorDecl(FD); + + // Attach a type to this function. Use the real type if possible, but fall + // back to the type as written if it involves a deduced return type. + if (FD->getTypeSourceInfo() && FD->getTypeSourceInfo() + ->getType() + ->castAs() + ->getReturnType() + ->getContainedAutoType()) { + // We'll set up the real type in Visit, once we've finished loading the + // function. + FD->setType(FD->getTypeSourceInfo()->getType()); + Reader.PendingFunctionTypes.push_back({FD, DeferredTypeID}); + } else { + FD->setType(Reader.GetType(DeferredTypeID)); + } + DeferredTypeID = 0; + + FD->DNLoc = Record.readDeclarationNameLoc(FD->getDeclName()); + FD->IdentifierNamespace = Record.readInt(); + + // FunctionDecl's body is handled last at ASTDeclReader::Visit, + // after everything else is read. + + FD->setStorageClass(static_cast(Record.readInt())); + FD->setInlineSpecified(Record.readInt()); + FD->setImplicitlyInline(Record.readInt()); + FD->setVirtualAsWritten(Record.readInt()); + // We defer calling `FunctionDecl::setPure()` here as for methods of + // `CXXTemplateSpecializationDecl`s, we may not have connected up the + // definition (which is required for `setPure`). + const bool Pure = Record.readInt(); + FD->setHasInheritedPrototype(Record.readInt()); + FD->setHasWrittenPrototype(Record.readInt()); + FD->setDeletedAsWritten(Record.readInt()); + FD->setTrivial(Record.readInt()); + FD->setTrivialForCall(Record.readInt()); + FD->setDefaulted(Record.readInt()); + FD->setExplicitlyDefaulted(Record.readInt()); + FD->setHasImplicitReturnZero(Record.readInt()); + FD->setConstexprKind(static_cast(Record.readInt())); + FD->setUsesSEHTry(Record.readInt()); + FD->setHasSkippedBody(Record.readInt()); + FD->setIsMultiVersion(Record.readInt()); + FD->setLateTemplateParsed(Record.readInt()); + FD->setFriendConstraintRefersToEnclosingTemplate(Record.readInt()); + + FD->setCachedLinkage(static_cast(Record.readInt())); + FD->EndRangeLoc = readSourceLocation(); + FD->setDefaultLoc(readSourceLocation()); + + FD->ODRHash = Record.readInt(); + FD->setHasODRHash(true); + + if (FD->isDefaulted()) { + if (unsigned NumLookups = Record.readInt()) { + SmallVector Lookups; + for (unsigned I = 0; I != NumLookups; ++I) { + NamedDecl *ND = Record.readDeclAs(); + AccessSpecifier AS = (AccessSpecifier)Record.readInt(); + Lookups.push_back(DeclAccessPair::make(ND, AS)); + } + FD->setDefaultedFunctionInfo(FunctionDecl::DefaultedFunctionInfo::Create( + Reader.getContext(), Lookups)); + } + } + + if (Existing) + mergeRedeclarable(FD, Existing, Redecl); + else if (auto Kind = FD->getTemplatedKind(); + Kind == FunctionDecl::TK_FunctionTemplate || + Kind == FunctionDecl::TK_FunctionTemplateSpecialization) { + // Function Templates have their FunctionTemplateDecls merged instead of + // their FunctionDecls. + auto merge = [this, &Redecl, FD](auto &&F) { + auto *Existing = cast_or_null(Redecl.getKnownMergeTarget()); + RedeclarableResult NewRedecl(Existing ? F(Existing) : nullptr, + Redecl.getFirstID(), Redecl.isKeyDecl()); + mergeRedeclarableTemplate(F(FD), NewRedecl); + }; + if (Kind == FunctionDecl::TK_FunctionTemplate) + merge( + [](FunctionDecl *FD) { return FD->getDescribedFunctionTemplate(); }); + else + merge([](FunctionDecl *FD) { + return FD->getTemplateSpecializationInfo()->getTemplate(); + }); + } else + mergeRedeclarable(FD, Redecl); + // Defer calling `setPure` until merging above has guaranteed we've set // `DefinitionData` (as this will need to access it). FD->setPure(Pure); @@ -2187,15 +2215,12 @@ D->FriendLoc = readSourceLocation(); } -DeclID ASTDeclReader::VisitTemplateDecl(TemplateDecl *D) { +void ASTDeclReader::VisitTemplateDecl(TemplateDecl *D) { VisitNamedDecl(D); - DeclID PatternID = readDeclID(); - auto *TemplatedDecl = cast_or_null(Reader.GetDecl(PatternID)); - TemplateParameterList *TemplateParams = Record.readTemplateParameterList(); - D->init(TemplatedDecl, TemplateParams); - - return PatternID; + assert(!D->TemplateParams && "TemplateParams already set!"); + D->TemplateParams = Record.readTemplateParameterList(); + D->init(readDeclAs()); } void ASTDeclReader::VisitConceptDecl(ConceptDecl *D) { @@ -2232,21 +2257,15 @@ } } - DeclID PatternID = VisitTemplateDecl(D); + VisitTemplateDecl(D); D->IdentifierNamespace = Record.readInt(); - mergeRedeclarable(D, Redecl, PatternID); - - // If we merged the template with a prior declaration chain, merge the common - // pointer. - // FIXME: Actually merge here, don't just overwrite. - D->Common = D->getCanonicalDecl()->Common; - return Redecl; } void ASTDeclReader::VisitClassTemplateDecl(ClassTemplateDecl *D) { RedeclarableResult Redecl = VisitRedeclarableTemplateDecl(D); + mergeRedeclarableTemplate(D, Redecl); if (ThisDeclID == Redecl.getFirstID()) { // This ClassTemplateDecl owns a CommonPtr; read it to keep track of all of @@ -2274,6 +2293,7 @@ /// VarTemplateDecl beyond TemplateDecl... void ASTDeclReader::VisitVarTemplateDecl(VarTemplateDecl *D) { RedeclarableResult Redecl = VisitRedeclarableTemplateDecl(D); + mergeRedeclarableTemplate(D, Redecl); if (ThisDeclID == Redecl.getFirstID()) { // This VarTemplateDecl owns a CommonPtr; read it to keep track of all of @@ -2402,8 +2422,6 @@ ASTDeclReader::RedeclarableResult ASTDeclReader::VisitVarTemplateSpecializationDeclImpl( VarTemplateSpecializationDecl *D) { - RedeclarableResult Redecl = VisitVarDeclImpl(D); - ASTContext &C = Reader.getContext(); if (Decl *InstD = readDecl()) { if (auto *VTD = dyn_cast(InstD)) { @@ -2440,6 +2458,8 @@ D->SpecializationKind = (TemplateSpecializationKind)Record.readInt(); D->IsCompleteDefinition = Record.readInt(); + RedeclarableResult Redecl = VisitVarDeclImpl(D); + bool writtenAsCanonicalDecl = Record.readInt(); if (writtenAsCanonicalDecl) { auto *CanonPattern = readDeclAs(); @@ -2547,7 +2567,8 @@ } void ASTDeclReader::VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *D) { - VisitRedeclarableTemplateDecl(D); + RedeclarableResult Redecl = VisitRedeclarableTemplateDecl(D); + mergeRedeclarableTemplate(D, Redecl); } void ASTDeclReader::VisitStaticAssertDecl(StaticAssertDecl *D) { @@ -2644,10 +2665,9 @@ /// Attempts to merge the given declaration (D) with another declaration /// of the same entity. -template +template void ASTDeclReader::mergeRedeclarable(Redeclarable *DBase, - RedeclarableResult &Redecl, - DeclID TemplatePatternID) { + RedeclarableResult &Redecl) { // If modules are not available, there is no reason to perform this merge. if (!Reader.getContext().getLangOpts().Modules) return; @@ -2660,10 +2680,19 @@ if (auto *Existing = Redecl.getKnownMergeTarget()) // We already know of an existing declaration we should merge with. - mergeRedeclarable(D, cast(Existing), Redecl, TemplatePatternID); + mergeRedeclarable(D, cast(Existing), Redecl); else if (FindExistingResult ExistingRes = findExisting(D)) if (T *Existing = ExistingRes) - mergeRedeclarable(D, Existing, Redecl, TemplatePatternID); + mergeRedeclarable(D, Existing, Redecl); +} + +void ASTDeclReader::mergeRedeclarableTemplate(RedeclarableTemplateDecl *D, + RedeclarableResult &Redecl) { + mergeRedeclarable(D, Redecl); + // If we merged the template with a prior declaration chain, merge the + // common pointer. + // FIXME: Actually merge here, don't just overwrite. + D->Common = D->getCanonicalDecl()->Common; } /// "Cast" to type T, asserting if we don't have an implicit conversion. @@ -2678,7 +2707,7 @@ /// declarations. void ASTDeclReader::mergeTemplatePattern(RedeclarableTemplateDecl *D, RedeclarableTemplateDecl *Existing, - DeclID DsID, bool IsKeyDecl) { + bool IsKeyDecl) { auto *DPattern = D->getTemplatedDecl(); auto *ExistingPattern = Existing->getTemplatedDecl(); RedeclarableResult Result(/*MergeWith*/ ExistingPattern, @@ -2718,17 +2747,13 @@ /// Attempts to merge the given declaration (D) with another declaration /// of the same entity. -template +template void ASTDeclReader::mergeRedeclarable(Redeclarable *DBase, T *Existing, - RedeclarableResult &Redecl, - DeclID TemplatePatternID) { + RedeclarableResult &Redecl) { auto *D = static_cast(DBase); T *ExistingCanon = Existing->getCanonicalDecl(); T *DCanon = D->getCanonicalDecl(); if (ExistingCanon != DCanon) { - assert(DCanon->getGlobalID() == Redecl.getFirstID() && - "already merged this declaration"); - // Have our redeclaration link point back at the canonical declaration // of the existing declaration, so that this declaration has the // appropriate canonical declaration. @@ -2747,8 +2772,8 @@ // When we merge a template, merge its pattern. if (auto *DTemplate = dyn_cast(D)) mergeTemplatePattern( - DTemplate, assert_cast(ExistingCanon), - TemplatePatternID, Redecl.isKeyDecl()); + DTemplate, assert_cast(ExistingCanon), + Redecl.isKeyDecl()); // If this declaration is a key declaration, make a note of that. if (Redecl.isKeyDecl()) diff --git a/clang/lib/Serialization/ASTReaderStmt.cpp b/clang/lib/Serialization/ASTReaderStmt.cpp --- a/clang/lib/Serialization/ASTReaderStmt.cpp +++ b/clang/lib/Serialization/ASTReaderStmt.cpp @@ -2118,8 +2118,10 @@ void ASTStmtReader::VisitSubstNonTypeTemplateParmExpr( SubstNonTypeTemplateParmExpr *E) { VisitExpr(E); - E->ParamAndRef.setPointer(readDeclAs()); - E->ParamAndRef.setInt(Record.readInt()); + E->AssociatedDeclAndRef.setPointer(readDeclAs()); + E->AssociatedDeclAndRef.setInt(Record.readInt()); + E->Index = Record.readInt(); + E->PackIndex = Record.readInt(); E->SubstNonTypeTemplateParmExprBits.NameLoc = readSourceLocation(); E->Replacement = Record.readSubExpr(); } @@ -2127,7 +2129,8 @@ void ASTStmtReader::VisitSubstNonTypeTemplateParmPackExpr( SubstNonTypeTemplateParmPackExpr *E) { VisitExpr(E); - E->Param = readDeclAs(); + E->AssociatedDecl = readDeclAs(); + E->Index = Record.readInt(); TemplateArgument ArgPack = Record.readTemplateArgument(); if (ArgPack.getKind() != TemplateArgument::Pack) return; diff --git a/clang/lib/Serialization/ASTWriterDecl.cpp b/clang/lib/Serialization/ASTWriterDecl.cpp --- a/clang/lib/Serialization/ASTWriterDecl.cpp +++ b/clang/lib/Serialization/ASTWriterDecl.cpp @@ -539,48 +539,6 @@ void ASTDeclWriter::VisitFunctionDecl(FunctionDecl *D) { VisitRedeclarable(D); - VisitDeclaratorDecl(D); - Record.AddDeclarationNameLoc(D->DNLoc, D->getDeclName()); - Record.push_back(D->getIdentifierNamespace()); - - // FunctionDecl's body is handled last at ASTWriterDecl::Visit, - // after everything else is written. - Record.push_back(static_cast(D->getStorageClass())); // FIXME: stable encoding - Record.push_back(D->isInlineSpecified()); - Record.push_back(D->isInlined()); - Record.push_back(D->isVirtualAsWritten()); - Record.push_back(D->isPure()); - Record.push_back(D->hasInheritedPrototype()); - Record.push_back(D->hasWrittenPrototype()); - Record.push_back(D->isDeletedBit()); - Record.push_back(D->isTrivial()); - Record.push_back(D->isTrivialForCall()); - Record.push_back(D->isDefaulted()); - Record.push_back(D->isExplicitlyDefaulted()); - Record.push_back(D->hasImplicitReturnZero()); - Record.push_back(static_cast(D->getConstexprKind())); - Record.push_back(D->usesSEHTry()); - Record.push_back(D->hasSkippedBody()); - Record.push_back(D->isMultiVersion()); - Record.push_back(D->isLateTemplateParsed()); - Record.push_back(D->FriendConstraintRefersToEnclosingTemplate()); - Record.push_back(D->getLinkageInternal()); - Record.AddSourceLocation(D->getEndLoc()); - Record.AddSourceLocation(D->getDefaultLoc()); - - Record.push_back(D->getODRHash()); - - if (D->isDefaulted()) { - if (auto *FDI = D->getDefaultedFunctionInfo()) { - Record.push_back(FDI->getUnqualifiedLookups().size()); - for (DeclAccessPair P : FDI->getUnqualifiedLookups()) { - Record.AddDeclRef(P.getDecl()); - Record.push_back(P.getAccess()); - } - } else { - Record.push_back(0); - } - } Record.push_back(D->getTemplatedKind()); switch (D->getTemplatedKind()) { @@ -661,6 +619,50 @@ } } + VisitDeclaratorDecl(D); + Record.AddDeclarationNameLoc(D->DNLoc, D->getDeclName()); + Record.push_back(D->getIdentifierNamespace()); + + // FunctionDecl's body is handled last at ASTWriterDecl::Visit, + // after everything else is written. + Record.push_back( + static_cast(D->getStorageClass())); // FIXME: stable encoding + Record.push_back(D->isInlineSpecified()); + Record.push_back(D->isInlined()); + Record.push_back(D->isVirtualAsWritten()); + Record.push_back(D->isPure()); + Record.push_back(D->hasInheritedPrototype()); + Record.push_back(D->hasWrittenPrototype()); + Record.push_back(D->isDeletedBit()); + Record.push_back(D->isTrivial()); + Record.push_back(D->isTrivialForCall()); + Record.push_back(D->isDefaulted()); + Record.push_back(D->isExplicitlyDefaulted()); + Record.push_back(D->hasImplicitReturnZero()); + Record.push_back(static_cast(D->getConstexprKind())); + Record.push_back(D->usesSEHTry()); + Record.push_back(D->hasSkippedBody()); + Record.push_back(D->isMultiVersion()); + Record.push_back(D->isLateTemplateParsed()); + Record.push_back(D->FriendConstraintRefersToEnclosingTemplate()); + Record.push_back(D->getLinkageInternal()); + Record.AddSourceLocation(D->getEndLoc()); + Record.AddSourceLocation(D->getDefaultLoc()); + + Record.push_back(D->getODRHash()); + + if (D->isDefaulted()) { + if (auto *FDI = D->getDefaultedFunctionInfo()) { + Record.push_back(FDI->getUnqualifiedLookups().size()); + for (DeclAccessPair P : FDI->getUnqualifiedLookups()) { + Record.AddDeclRef(P.getDecl()); + Record.push_back(P.getAccess()); + } + } else { + Record.push_back(0); + } + } + Record.push_back(D->param_size()); for (auto *P : D->parameters()) Record.AddDeclRef(P); @@ -1405,14 +1407,12 @@ } if (D->getDeclContext() == D->getLexicalDeclContext() && - D->getFirstDecl() == D->getMostRecentDecl() && - !D->isInvalidDecl() && - !D->hasAttrs() && - !D->isTopLevelDeclInObjCContainer() && + D->getFirstDecl() == D->getMostRecentDecl() && !D->isInvalidDecl() && + !D->hasAttrs() && !D->isTopLevelDeclInObjCContainer() && D->getDeclName().getNameKind() == DeclarationName::Identifier && - !D->hasExtInfo() && - !D->hasInheritedPrototype() && - D->hasWrittenPrototype()) + !D->hasExtInfo() && !D->hasInheritedPrototype() && + D->hasWrittenPrototype() && + D->getTemplatedKind() == FunctionDecl::TK_NonTemplate) AbbrevToUse = Writer.getDeclCXXMethodAbbrev(); Code = serialization::DECL_CXX_METHOD; @@ -1506,8 +1506,8 @@ void ASTDeclWriter::VisitTemplateDecl(TemplateDecl *D) { VisitNamedDecl(D); - Record.AddDeclRef(D->getTemplatedDecl()); Record.AddTemplateParameterList(D->getTemplateParameters()); + Record.AddDeclRef(D->getTemplatedDecl()); } void ASTDeclWriter::VisitConceptDecl(ConceptDecl *D) { @@ -1608,8 +1608,6 @@ VarTemplateSpecializationDecl *D) { RegisterTemplateSpecialization(D->getSpecializedTemplate(), D); - VisitVarDecl(D); - llvm::PointerUnion InstFrom = D->getSpecializedTemplateOrPartial(); if (Decl *InstFromD = InstFrom.dyn_cast()) { @@ -1630,6 +1628,9 @@ Record.AddSourceLocation(D->getPointOfInstantiation()); Record.push_back(D->getSpecializationKind()); Record.push_back(D->IsCompleteDefinition); + + VisitVarDecl(D); + Record.push_back(D->isCanonicalDecl()); if (D->isCanonicalDecl()) { @@ -2245,6 +2246,8 @@ Abv->Add(BitCodeAbbrevOp(serialization::DECL_CXX_METHOD)); // RedeclarableDecl Abv->Add(BitCodeAbbrevOp(0)); // CanonicalDecl + // FIXME: Implement abbreviation for other template kinds. + Abv->Add(BitCodeAbbrevOp(FunctionDecl::TK_NonTemplate)); // TemplateKind // Decl Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // DeclContext Abv->Add(BitCodeAbbrevOp(0)); // LexicalDeclContext @@ -2292,11 +2295,10 @@ Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // LocEnd Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Default Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // ODRHash - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); // TemplateKind // This Array slurps the rest of the record. Fortunately we want to encode // (nearly) all the remaining (variable number of) fields in the same way. // - // This is the function template information if any, then + // This is: // NumParams and Params[] from FunctionDecl, and // NumOverriddenMethods, OverriddenMethods[] from CXXMethodDecl. // diff --git a/clang/lib/Serialization/ASTWriterStmt.cpp b/clang/lib/Serialization/ASTWriterStmt.cpp --- a/clang/lib/Serialization/ASTWriterStmt.cpp +++ b/clang/lib/Serialization/ASTWriterStmt.cpp @@ -2028,8 +2028,13 @@ void ASTStmtWriter::VisitSubstNonTypeTemplateParmExpr( SubstNonTypeTemplateParmExpr *E) { VisitExpr(E); - Record.AddDeclRef(E->getParameter()); + Record.AddDeclRef(E->getAssociatedDecl()); Record.push_back(E->isReferenceParameter()); + Record.push_back(E->getIndex()); + if (auto PackIndex = E->getPackIndex()) + Record.push_back(*PackIndex + 1); + else + Record.push_back(0); Record.AddSourceLocation(E->getNameLoc()); Record.AddStmt(E->getReplacement()); Code = serialization::EXPR_SUBST_NON_TYPE_TEMPLATE_PARM; @@ -2038,7 +2043,8 @@ void ASTStmtWriter::VisitSubstNonTypeTemplateParmPackExpr( SubstNonTypeTemplateParmPackExpr *E) { VisitExpr(E); - Record.AddDeclRef(E->getParameterPack()); + Record.AddDeclRef(E->getAssociatedDecl()); + Record.push_back(E->getIndex()); Record.AddTemplateArgument(E->getArgumentPack()); Record.AddSourceLocation(E->getParameterPackLocation()); Code = serialization::EXPR_SUBST_NON_TYPE_TEMPLATE_PARM_PACK; diff --git a/clang/lib/StaticAnalyzer/Checkers/MismatchedIteratorChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/MismatchedIteratorChecker.cpp --- a/clang/lib/StaticAnalyzer/Checkers/MismatchedIteratorChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/MismatchedIteratorChecker.cpp @@ -176,8 +176,10 @@ const auto *Param = Func->getParamDecl(J); const auto *ParamType = Param->getType()->getAs(); - if (!ParamType || - ParamType->getReplacedParameter()->getDecl() != TPDecl) + if (!ParamType) + continue; + const TemplateTypeParmDecl *D = ParamType->getReplacedParameter(); + if (D != TPDecl) continue; if (LHS.isUndef()) { LHS = Call.getArgSVal(J); diff --git a/clang/test/AST/ast-dump-openmp-begin-declare-variant_reference.cpp b/clang/test/AST/ast-dump-openmp-begin-declare-variant_reference.cpp --- a/clang/test/AST/ast-dump-openmp-begin-declare-variant_reference.cpp +++ b/clang/test/AST/ast-dump-openmp-begin-declare-variant_reference.cpp @@ -122,9 +122,8 @@ // CHECK-NEXT: | | | `-BuiltinType [[ADDR_8:0x[a-z0-9]*]] 'float' // CHECK-NEXT: | | |-CXXRecordDecl [[ADDR_9:0x[a-z0-9]*]] col:29 implicit struct remove_reference // CHECK-NEXT: | | `-TypedefDecl [[ADDR_10:0x[a-z0-9]*]] col:67 referenced type 'float':'float' -// CHECK-NEXT: | | `-SubstTemplateTypeParmType [[ADDR_11:0x[a-z0-9]*]] 'float' sugar -// CHECK-NEXT: | | |-TemplateTypeParmType [[ADDR_12:0x[a-z0-9]*]] '_Tp' dependent depth 0 index 0 -// CHECK-NEXT: | | | `-TemplateTypeParm [[ADDR_13:0x[a-z0-9]*]] '_Tp' +// CHECK-NEXT: | | `-SubstTemplateTypeParmType [[ADDR_11:0x[a-z0-9]*]] 'float' sugar class depth 0 index 0 _Tp +// CHECK-NEXT: | | |-ClassTemplateSpecialization [[ADDR_6]] 'remove_reference' // CHECK-NEXT: | | `-BuiltinType [[ADDR_8]] 'float' // CHECK-NEXT: | `-ClassTemplateSpecializationDecl [[ADDR_14:0x[a-z0-9]*]] col:29 struct remove_reference definition // CHECK-NEXT: | |-DefinitionData pass_in_registers empty aggregate standard_layout trivially_copyable pod trivial literal has_constexpr_non_copy_move_ctor can_const_default_init @@ -139,9 +138,8 @@ // CHECK-NEXT: | | `-BuiltinType [[ADDR_16:0x[a-z0-9]*]] 'short' // CHECK-NEXT: | |-CXXRecordDecl [[ADDR_17:0x[a-z0-9]*]] col:29 implicit struct remove_reference // CHECK-NEXT: | `-TypedefDecl [[ADDR_18:0x[a-z0-9]*]] col:67 referenced type 'short':'short' -// CHECK-NEXT: | `-SubstTemplateTypeParmType [[ADDR_19:0x[a-z0-9]*]] 'short' sugar -// CHECK-NEXT: | |-TemplateTypeParmType [[ADDR_12]] '_Tp' dependent depth 0 index 0 -// CHECK-NEXT: | | `-TemplateTypeParm [[ADDR_13]] '_Tp' +// CHECK-NEXT: | `-SubstTemplateTypeParmType [[ADDR_19:0x[a-z0-9]*]] 'short' sugar class depth 0 index 0 _Tp +// CHECK-NEXT: | |-ClassTemplateSpecialization [[ADDR_14]] 'remove_reference' // CHECK-NEXT: | `-BuiltinType [[ADDR_16]] 'short' // CHECK-NEXT: |-ClassTemplatePartialSpecializationDecl [[ADDR_20:0x[a-z0-9]*]] col:29 struct remove_reference definition // CHECK-NEXT: | |-DefinitionData empty aggregate standard_layout trivially_copyable pod trivial literal has_constexpr_non_copy_move_ctor can_const_default_init @@ -154,10 +152,10 @@ // CHECK-NEXT: | |-TemplateArgument type 'type-parameter-0-0 &' // CHECK-NEXT: | | `-LValueReferenceType [[ADDR_21:0x[a-z0-9]*]] 'type-parameter-0-0 &' dependent // CHECK-NEXT: | | `-TemplateTypeParmType [[ADDR_22:0x[a-z0-9]*]] 'type-parameter-0-0' dependent depth 0 index 0 -// CHECK-NEXT: | |-TemplateTypeParmDecl [[ADDR_13]] col:17 referenced class depth 0 index 0 _Tp +// CHECK-NEXT: | |-TemplateTypeParmDecl [[ADDR_13:0x[a-z0-9]*]] col:17 referenced class depth 0 index 0 _Tp // CHECK-NEXT: | |-CXXRecordDecl [[ADDR_23:0x[a-z0-9]*]] col:29 implicit struct remove_reference // CHECK-NEXT: | `-TypedefDecl [[ADDR_24:0x[a-z0-9]*]] col:67 type '_Tp' -// CHECK-NEXT: | `-TemplateTypeParmType [[ADDR_12]] '_Tp' dependent depth 0 index 0 +// CHECK-NEXT: | `-TemplateTypeParmType [[ADDR_12:0x[a-z0-9]*]] '_Tp' dependent depth 0 index 0 // CHECK-NEXT: | `-TemplateTypeParm [[ADDR_13]] '_Tp' // CHECK-NEXT: |-ClassTemplatePartialSpecializationDecl [[ADDR_25:0x[a-z0-9]*]] col:29 struct remove_reference definition // CHECK-NEXT: | |-DefinitionData empty aggregate standard_layout trivially_copyable pod trivial literal has_constexpr_non_copy_move_ctor can_const_default_init @@ -197,9 +195,8 @@ // CHECK-NEXT: | | | `-ElaboratedType [[ADDR_47:0x[a-z0-9]*]] 'typename remove_reference::type' sugar // CHECK-NEXT: | | | `-TypedefType [[ADDR_48:0x[a-z0-9]*]] 'remove_reference::type' sugar // CHECK-NEXT: | | | |-Typedef [[ADDR_10]] 'type' -// CHECK-NEXT: | | | `-SubstTemplateTypeParmType [[ADDR_11]] 'float' sugar -// CHECK-NEXT: | | | |-TemplateTypeParmType [[ADDR_12]] '_Tp' dependent depth 0 index 0 -// CHECK-NEXT: | | | | `-TemplateTypeParm [[ADDR_13]] '_Tp' +// CHECK-NEXT: | | | `-SubstTemplateTypeParmType [[ADDR_11]] 'float' sugar class depth 0 index 0 _Tp +// CHECK-NEXT: | | | |-ClassTemplateSpecialization [[ADDR_6]] 'remove_reference' // CHECK-NEXT: | | | `-BuiltinType [[ADDR_8]] 'float' // CHECK-NEXT: | | `-ReturnStmt [[ADDR_49:0x[a-z0-9]*]] // CHECK-NEXT: | | `-CXXStaticCastExpr [[ADDR_50:0x[a-z0-9]*]] '_Up':'float' xvalue static_cast<_Up &&> @@ -215,9 +212,8 @@ // CHECK-NEXT: | | `-ElaboratedType [[ADDR_57:0x[a-z0-9]*]] 'typename remove_reference::type' sugar // CHECK-NEXT: | | `-TypedefType [[ADDR_58:0x[a-z0-9]*]] 'remove_reference::type' sugar // CHECK-NEXT: | | |-Typedef [[ADDR_18]] 'type' -// CHECK-NEXT: | | `-SubstTemplateTypeParmType [[ADDR_19]] 'short' sugar -// CHECK-NEXT: | | |-TemplateTypeParmType [[ADDR_12]] '_Tp' dependent depth 0 index 0 -// CHECK-NEXT: | | | `-TemplateTypeParm [[ADDR_13]] '_Tp' +// CHECK-NEXT: | | `-SubstTemplateTypeParmType [[ADDR_19]] 'short' sugar class depth 0 index 0 _Tp +// CHECK-NEXT: | | |-ClassTemplateSpecialization [[ADDR_14]] 'remove_reference' // CHECK-NEXT: | | `-BuiltinType [[ADDR_16]] 'short' // CHECK-NEXT: | `-ReturnStmt [[ADDR_59:0x[a-z0-9]*]] // CHECK-NEXT: | `-CXXStaticCastExpr [[ADDR_60:0x[a-z0-9]*]] '_Up':'short' xvalue static_cast<_Up &&> diff --git a/clang/test/AST/ast-dump-template-decls.cpp b/clang/test/AST/ast-dump-template-decls.cpp --- a/clang/test/AST/ast-dump-template-decls.cpp +++ b/clang/test/AST/ast-dump-template-decls.cpp @@ -120,12 +120,12 @@ // CHECK-NEXT: TemplateArgument type 'void' // CHECK-NEXT: BuiltinType 0x{{[^ ]*}} 'void' // CHECK-NEXT: FunctionProtoType 0x{{[^ ]*}} 'void (int)' cdecl -// CHECK-NEXT: SubstTemplateTypeParmType 0x{{[^ ]*}} 'void' sugar -// CHECK-NEXT: TemplateTypeParmType 0x{{[^ ]*}} 'U' dependent depth 0 index 0 -// CHECK-NEXT: TemplateTypeParm 0x{{[^ ]*}} 'U' +// CHECK-NEXT: SubstTemplateTypeParmType 0x{{[^ ]*}} 'void' sugar class depth 0 index 0 U +// CHECK-NEXT: TypeAliasTemplate 0x{{[^ ]*}} 'type1' // CHECK-NEXT: BuiltinType 0x{{[^ ]*}} 'void' -// CHECK-NEXT: SubstTemplateTypeParmType 0x{{[^ ]*}} 'int' sugar -// CHECK-NEXT: TemplateTypeParmType 0x{{[^ ]*}} 'T' dependent depth 0 index 0 +// CHECK-NEXT: SubstTemplateTypeParmType 0x{{[^ ]*}} 'int' sugar class depth 0 index 0 T +// CHECK-NEXT: ClassTemplateSpecialization 0x{{[^ ]*}} 'C' +// CHECK-NEXT: BuiltinType 0x{{[^ ]*}} 'int' } // namespace PR55886 namespace PR56099 { @@ -136,14 +136,14 @@ }; using t1 = foo::bind; // CHECK: TemplateSpecializationType 0x{{[^ ]*}} 'Y' sugar Y -// CHECK: SubstTemplateTypeParmType 0x{{[^ ]*}} 'char' sugar pack_index 3 -// CHECK-NEXT: TemplateTypeParmType 0x{{[^ ]*}} 'Bs' dependent contains_unexpanded_pack depth 0 index 0 pack -// CHECK: SubstTemplateTypeParmType 0x{{[^ ]*}} 'float' sugar pack_index 2 -// CHECK-NEXT: TemplateTypeParmType 0x{{[^ ]*}} 'Bs' dependent contains_unexpanded_pack depth 0 index 0 pack -// CHECK: SubstTemplateTypeParmType 0x{{[^ ]*}} 'int' sugar pack_index 1 -// CHECK-NEXT: TemplateTypeParmType 0x{{[^ ]*}} 'Bs' dependent contains_unexpanded_pack depth 0 index 0 pack -// CHECK: SubstTemplateTypeParmType 0x{{[^ ]*}} 'short' sugar pack_index 0 -// CHECK-NEXT: TemplateTypeParmType 0x{{[^ ]*}} 'Bs' dependent contains_unexpanded_pack depth 0 index 0 pack +// CHECK: SubstTemplateTypeParmType 0x{{[^ ]*}} 'char' sugar typename depth 0 index 0 ... Bs pack_index 3 +// CHECK-NEXT: TypeAliasTemplate 0x{{[^ ]*}} 'Z' +// CHECK: SubstTemplateTypeParmType 0x{{[^ ]*}} 'float' sugar typename depth 0 index 0 ... Bs pack_index 2 +// CHECK-NEXT: TypeAliasTemplate 0x{{[^ ]*}} 'Z' +// CHECK: SubstTemplateTypeParmType 0x{{[^ ]*}} 'int' sugar typename depth 0 index 0 ... Bs pack_index 1 +// CHECK-NEXT: TypeAliasTemplate 0x{{[^ ]*}} 'Z' +// CHECK: SubstTemplateTypeParmType 0x{{[^ ]*}} 'short' sugar typename depth 0 index 0 ... Bs pack_index 0 +// CHECK-NEXT: TypeAliasTemplate 0x{{[^ ]*}} 'Z' template struct D { template using B = int(int (*...p)(T, U)); @@ -152,15 +152,15 @@ // CHECK: TemplateSpecializationType 0x{{[^ ]*}} 'B' sugar alias B // CHECK: FunctionProtoType 0x{{[^ ]*}} 'int (int (*)(float, int), int (*)(char, short))' cdecl // CHECK: FunctionProtoType 0x{{[^ ]*}} 'int (float, int)' cdecl -// CHECK: SubstTemplateTypeParmType 0x{{[^ ]*}} 'float' sugar pack_index 1 -// CHECK-NEXT: TemplateTypeParmType 0x{{[^ ]*}} 'T' dependent contains_unexpanded_pack depth 0 index 0 pack -// CHECK: SubstTemplateTypeParmType 0x{{[^ ]*}} 'int' sugar pack_index 1 -// CHECK-NEXT: TemplateTypeParmType 0x{{[^ ]*}} 'U' dependent contains_unexpanded_pack depth 0 index 0 pack +// CHECK: SubstTemplateTypeParmType 0x{{[^ ]*}} 'float' sugar typename depth 0 index 0 ... T pack_index 1 +// CHECK-NEXT: ClassTemplateSpecialization 0x{{[^ ]*}} 'D' +// CHECK: SubstTemplateTypeParmType 0x{{[^ ]*}} 'int' sugar typename depth 0 index 0 ... U pack_index 1 +// CHECK-NEXT: TypeAliasTemplate 0x{{[^ ]*}} 'B' // CHECK: FunctionProtoType 0x{{[^ ]*}} 'int (char, short)' cdecl -// CHECK: SubstTemplateTypeParmType 0x{{[^ ]*}} 'char' sugar pack_index 0 -// CHECK-NEXT: TemplateTypeParmType 0x{{[^ ]*}} 'T' dependent contains_unexpanded_pack depth 0 index 0 pack -// CHECK: SubstTemplateTypeParmType 0x{{[^ ]*}} 'short' sugar pack_index 0 -// CHECK-NEXT: TemplateTypeParmType 0x{{[^ ]*}} 'U' dependent contains_unexpanded_pack depth 0 index 0 pack +// CHECK: SubstTemplateTypeParmType 0x{{[^ ]*}} 'char' sugar typename depth 0 index 0 ... T pack_index 0 +// CHECK-NEXT: ClassTemplateSpecialization 0x{{[^ ]*}} 'D' +// CHECK: SubstTemplateTypeParmType 0x{{[^ ]*}} 'short' sugar typename depth 0 index 0 ... U pack_index 0 +// CHECK-NEXT: TypeAliasTemplate 0x{{[^ ]*}} 'B' } // namespace PR56099 namespace subst_default_argument { @@ -172,11 +172,10 @@ // CHECK: TypeAliasDecl 0x{{[^ ]*}} col:7 test1 'D':'subst_default_argument::E>' // CHECK: TemplateSpecializationType 0x{{[^ ]*}} 'A' sugar A // CHECK-NEXT: |-TemplateArgument type 'int':'int' -// CHECK-NEXT: | `-SubstTemplateTypeParmType 0x{{[^ ]*}} 'int' sugar -// CHECK-NEXT: | |-TemplateTypeParmType 0x{{[^ ]*}} 'C1' dependent depth 1 index 0 -// CHECK-NEXT: | | `-TemplateTypeParm 0x{{[^ ]*}} 'C1' -// CHECK-NEXT: | `-SubstTemplateTypeParmType 0x{{[^ ]*}} 'int' sugar -// CHECK-NEXT: | |-TemplateTypeParmType 0x{{[^ ]*}} 'type-parameter-0-1' dependent depth 0 index 1 +// CHECK-NEXT: | `-SubstTemplateTypeParmType 0x{{[^ ]*}} 'int' sugar class depth 0 index 0 E1 +// CHECK-NEXT: | |-ClassTemplate 0x{{[^ ]*}} 'E' +// CHECK-NEXT: | `-SubstTemplateTypeParmType 0x{{[^ ]*}} 'int' sugar class depth 0 index 1 D2 +// CHECK-NEXT: | |-TypeAliasTemplate 0x{{[^ ]*}} 'D' // CHECK-NEXT: | `-BuiltinType 0x{{[^ ]*}} 'int' // CHECK-NEXT: `-RecordType 0x{{[^ ]*}} 'subst_default_argument::A' // CHECK-NEXT: `-ClassTemplateSpecialization 0x{{[^ ]*}} 'A' diff --git a/clang/test/AST/deduction-guides.cpp b/clang/test/AST/deduction-guides.cpp --- a/clang/test/AST/deduction-guides.cpp +++ b/clang/test/AST/deduction-guides.cpp @@ -67,9 +67,8 @@ // CHECK-NEXT: ElaboratedType {{.*}} 'typename Derived::type_alias' sugar // CHECK-NEXT: TypedefType {{.*}} 'PR48177::Base::type_alias' sugar // CHECK-NEXT: TypeAlias {{.*}} 'type_alias' -// CHECK-NEXT: SubstTemplateTypeParmType {{.*}} 'int' sugar -// CHECK-NEXT: TemplateTypeParmType {{.*}} 'A' -// CHECK-NEXT: TemplateTypeParm {{.*}} 'A' +// CHECK-NEXT: SubstTemplateTypeParmType {{.*}} 'int' sugar class depth 0 index 0 A +// CHECK-NEXT: ClassTemplateSpecialization {{.*}} 'Base' // CHECK-NEXT: BuiltinType {{.*}} 'int' // CHECK: CXXDeductionGuideDecl {{.*}} implicit 'auto (Derived &&, const typename Derived::type_alias &) -> Derived' diff --git a/clang/test/SemaTemplate/deduction-guide.cpp b/clang/test/SemaTemplate/deduction-guide.cpp --- a/clang/test/SemaTemplate/deduction-guide.cpp +++ b/clang/test/SemaTemplate/deduction-guide.cpp @@ -156,9 +156,8 @@ // CHECK: |-BuiltinType {{.*}} 'int' // CHECK: |-TemplateTypeParmType {{.*}} 'T' dependent contains_unexpanded_pack depth 0 index 0 pack // CHECK: | `-TemplateTypeParm {{.*}} 'T' -// CHECK: `-SubstTemplateTypeParmPackType {{.*}} 'U' dependent contains_unexpanded_pack -// CHECK: |-TemplateTypeParmType {{.*}} 'U' dependent contains_unexpanded_pack depth 1 index 0 pack -// CHECK: | `-TemplateTypeParm {{.*}} 'U' +// CHECK: `-SubstTemplateTypeParmPackType {{.*}} 'U' dependent contains_unexpanded_pack typename depth 1 index 0 ... U +// CHECK: |-TypeAliasTemplate {{.*}} 'B' // CHECK: `-TemplateArgument pack // CHECK: |-TemplateArgument type 'type-parameter-0-1' // CHECK-NOT: Subst diff --git a/clang/test/SemaTemplate/make_integer_seq.cpp b/clang/test/SemaTemplate/make_integer_seq.cpp --- a/clang/test/SemaTemplate/make_integer_seq.cpp +++ b/clang/test/SemaTemplate/make_integer_seq.cpp @@ -15,9 +15,8 @@ // CHECK-NEXT: | `-IntegerLiteral 0x{{[0-9A-Fa-f]+}} 'int' 1 // CHECK-NEXT: `-TemplateSpecializationType 0x{{[0-9A-Fa-f]+}} 'A' sugar A // CHECK-NEXT: |-TemplateArgument type 'int':'int' -// CHECK-NEXT: | `-SubstTemplateTypeParmType 0x{{[0-9A-Fa-f]+}} 'int' sugar -// CHECK-NEXT: | |-TemplateTypeParmType 0x{{[0-9A-Fa-f]+}} 'auto' dependent depth 0 index 1 -// CHECK-NEXT: | | `-TemplateTypeParm 0x{{[0-9A-Fa-f]+}} '' +// CHECK-NEXT: | `-SubstTemplateTypeParmType 0x{{[0-9A-Fa-f]+}} 'int' sugar typename depth 0 index 1 +// CHECK-NEXT: | |-BuiltinTemplate 0x{{[0-9A-Fa-f]+}} '__make_integer_seq' // CHECK-NEXT: | `-BuiltinType 0x{{[0-9A-Fa-f]+}} 'int' // CHECK-NEXT: |-TemplateArgument expr // CHECK-NEXT: | `-ConstantExpr 0x{{[0-9A-Fa-f]+}} 'int' @@ -28,7 +27,7 @@ template using B = __make_integer_seq; using test2 = B; -// CHECK: |-TypeAliasDecl 0x{{[0-9A-Fa-f]+}} col:7 test2 'B':'A' +// CHECK: |-TypeAliasDecl 0x{{[0-9A-Fa-f]+}} col:7 test2 'B':'A' // CHECK-NEXT: `-ElaboratedType 0x{{[0-9A-Fa-f]+}} 'B' sugar // CHECK-NEXT: `-TemplateSpecializationType 0x{{[0-9A-Fa-f]+}} 'B' sugar alias B // CHECK-NEXT: |-TemplateArgument type 'int' @@ -41,21 +40,19 @@ // CHECK-NEXT: `-TemplateSpecializationType 0x{{[0-9A-Fa-f]+}} '__make_integer_seq' sugar alias __make_integer_seq // CHECK-NEXT: |-TemplateArgument template A // CHECK-NEXT: |-TemplateArgument type 'int':'int' -// CHECK-NEXT: | `-SubstTemplateTypeParmType 0x{{[0-9A-Fa-f]+}} 'int' sugar -// CHECK-NEXT: | |-TemplateTypeParmType 0x{{[0-9A-Fa-f]+}} 'B1' dependent depth 0 index 0 -// CHECK-NEXT: | | `-TemplateTypeParm 0x{{[0-9A-Fa-f]+}} 'B1' +// CHECK-NEXT: | `-SubstTemplateTypeParmType 0x{{[0-9A-Fa-f]+}} 'int' sugar class depth 0 index 0 B1 +// CHECK-NEXT: | |-TypeAliasTemplate 0x{{[0-9A-Fa-f]+}} 'B' // CHECK-NEXT: | `-BuiltinType 0x{{[0-9A-Fa-f]+}} 'int' // CHECK-NEXT: |-TemplateArgument expr -// CHECK-NEXT: | `-ConstantExpr 0x{{[0-9A-Fa-f]+}} 'int' +// CHECK-NEXT: | `-ConstantExpr 0x{{[0-9A-Fa-f]+}} 'int' // CHECK-NEXT: | |-value: Int 1 // CHECK-NEXT: | `-SubstNonTypeTemplateParmExpr 0x{{[0-9A-Fa-f]+}} 'int' // CHECK-NEXT: | |-NonTypeTemplateParmDecl 0x{{[0-9A-Fa-f]+}} col:24 referenced 'B1' depth 0 index 1 B2 // CHECK-NEXT: | `-IntegerLiteral 0x{{[0-9A-Fa-f]+}} 'int' 1 // CHECK-NEXT: `-TemplateSpecializationType 0x{{[0-9A-Fa-f]+}} 'A' sugar A // CHECK-NEXT: |-TemplateArgument type 'int':'int' -// CHECK-NEXT: | `-SubstTemplateTypeParmType 0x{{[0-9A-Fa-f]+}} 'int' sugar -// CHECK-NEXT: | |-TemplateTypeParmType 0x{{[0-9A-Fa-f]+}} 'auto' dependent depth 0 index 1 -// CHECK-NEXT: | | `-TemplateTypeParm 0x{{[0-9A-Fa-f]+}} '' +// CHECK-NEXT: | `-SubstTemplateTypeParmType 0x{{[0-9A-Fa-f]+}} 'int' sugar typename depth 0 index 1 +// CHECK-NEXT: | |-BuiltinTemplate 0x{{[0-9A-Fa-f]+}} '__make_integer_seq' // CHECK-NEXT: | `-BuiltinType 0x{{[0-9A-Fa-f]+}} 'int' // CHECK-NEXT: |-TemplateArgument expr // CHECK-NEXT: | `-ConstantExpr 0x{{[0-9A-Fa-f]+}} 'int' @@ -66,7 +63,7 @@ template