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 @@ -727,8 +727,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,11 @@ QualType getBTFTagAttributedType(const BTFTypeTagAttr *BTFAttr, QualType Wrapped); - QualType getSubstTemplateTypeParmType(const TemplateTypeParmType *Replaced, - QualType Replacement, + QualType getSubstTemplateTypeParmType(QualType Replacement, + Decl *ReplacedDecl, unsigned Index, Optional PackIndex) const; - QualType - getSubstTemplateTypeParmPackType(const TemplateTypeParmType *Replaced, - const TemplateArgument &ArgPack); + QualType getSubstTemplateTypeParmPackType(Decl *ReplacedDecl, unsigned Index, + const TemplateArgument &ArgPack); QualType getTemplateTypeParmType(unsigned Depth, unsigned Index, 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/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/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 @@ -1818,6 +1818,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. @@ -1831,14 +1834,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 { @@ -5034,18 +5037,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 { @@ -5054,6 +5051,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; @@ -5064,14 +5073,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); } @@ -5095,24 +5106,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; @@ -5124,9 +5141,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 @@ -724,20 +724,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<"replacedDecl", 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, replacedDecl, Index, PackIndex); }]>; } @@ -756,8 +759,11 @@ } let Class = SubstTemplateTypeParmPackType in { - def : Property<"replacedParameter", QualType> { - let Read = [{ QualType(node->getReplacedParameter(), 0) }]; + def : Property<"replacedDecl", DeclRef> { + let Read = [{ node->getAssociatedDecl() }]; + } + def : Property<"Index", UInt32> { + let Read = [{ node->getIndex() }]; } def : Property<"replacementPack", TemplateArgument> { let Read = [{ node->getArgumentPack() }]; @@ -765,8 +771,7 @@ def : Creator<[{ return ctx.getSubstTemplateTypeParmPackType( - cast(replacedParameter), - replacementPack); + replacedDecl, 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); + explicit 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 @@ -4787,21 +4787,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); } @@ -4811,33 +4812,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); @@ -12902,14 +12900,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 @@ -1524,8 +1524,7 @@ ExpectedType ASTNodeImporter::VisitSubstTemplateTypeParmType( const SubstTemplateTypeParmType *T) { - Expected ReplacedOrErr = - import(T->getReplacedParameter()); + Expected ReplacedOrErr = import(T->getAssociatedDecl()); if (!ReplacedOrErr) return ReplacedOrErr.takeError(); @@ -1534,13 +1533,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(); @@ -1549,7 +1548,7 @@ return ToArgumentPack.takeError(); return Importer.getToContext().getSubstTemplateTypeParmPackType( - *ReplacedOrErr, *ToArgumentPack); + *ReplacedOrErr, T->getIndex(), *ToArgumentPack); } ExpectedType ASTNodeImporter::VisitTemplateSpecializationType( @@ -3750,6 +3749,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); @@ -3771,10 +3774,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)) @@ -5994,6 +5993,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); @@ -6157,15 +6180,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)) @@ -6190,7 +6204,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; @@ -6211,11 +6225,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); 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 @@ -1061,13 +1061,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 +1077,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/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/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++ @@ -3658,28 +3659,111 @@ return isCanonicalUnqualified() ? nullptr : getDecl()->getIdentifier(); } +static const TemplateParameterList * +getReplacedTemplateParameterList(const 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: + D->dumpColor(); + llvm_unreachable("Unhandled templated declaration kind"); + } +} + +static const TemplateTypeParmDecl *getReplacedParameter(const 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); + assert(getReplacedParameter() != 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); + assert(getReplacedParameter() != nullptr); +} + +const TemplateTypeParmDecl * +SubstTemplateTypeParmPackType::getReplacedParameter() const { + return ::getReplacedParameter(getAssociatedDecl(), getIndex()); +} + +IdentifierInfo *SubstTemplateTypeParmPackType::getIdentifier() const { + return getReplacedParameter()->getIdentifier(); } TemplateArgument SubstTemplateTypeParmPackType::getArgumentPack() const { @@ -3687,13 +3771,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 @@ -1462,14 +1462,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 @@ -327,8 +327,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); @@ -435,7 +436,7 @@ MultiLevelTemplateArgumentList MLTAL; // FIXME: This will be replaced with some logic to get all the template // arguments when we switch to deferred template instantiation. - MLTAL.addOuterTemplateArguments(TemplateArgs); + MLTAL.addOuterTemplateArguments(Decl, TemplateArgs); // If this is not an explicit specialization - we need to get the instantiated // version of the template arguments and add them to scope for the @@ -447,7 +448,7 @@ if (Inst.isInvalid()) return true; MultiLevelTemplateArgumentList MLTAL( - *Decl->getTemplateSpecializationArgs()); + Decl, Decl->getTemplateSpecializationArgs()->asArray()); if (addInstantiatedParametersToScope( Decl, Decl->getPrimaryTemplate()->getTemplatedDecl(), Scope, MLTAL)) return true; @@ -749,7 +750,7 @@ AtomicConstraint &Atomic = *N.getAtomicConstraint(); TemplateArgumentListInfo SubstArgs; MultiLevelTemplateArgumentList MLTAL; - MLTAL.addOuterTemplateArguments(TemplateArgs); + MLTAL.addOuterTemplateArguments(Concept, TemplateArgs); if (!Atomic.ParameterMapping) { llvm::SmallBitVector OccurringIndices(TemplateParams->size()); S.MarkUsedTemplateParameters(Atomic.ConstraintExpr, /*OnlyDeduced=*/false, 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 @@ -8926,13 +8926,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 @@ -3509,11 +3509,8 @@ // 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()) { @@ -3795,7 +3792,8 @@ // Only substitute for the innermost template argument list. MultiLevelTemplateArgumentList TemplateArgLists; - TemplateArgLists.addOuterTemplateArguments(&StackTemplateArgs); + TemplateArgLists.addOuterTemplateArguments(Template, + StackTemplateArgs.asArray()); TemplateArgLists.addOuterRetainedLevels( AliasTemplate->getTemplateParameters()->getDepth()); @@ -3920,7 +3918,7 @@ InstantiatingTemplate Inst(*this, TemplateLoc, Decl); if (!Inst.isInvalid()) { MultiLevelTemplateArgumentList TemplateArgLists; - TemplateArgLists.addOuterTemplateArguments(Converted); + TemplateArgLists.addOuterTemplateArguments(Template, Converted); InstantiateAttrsForDecl(TemplateArgLists, ClassTemplate->getTemplatedDecl(), Decl); } @@ -4789,7 +4787,7 @@ TemplateSpecializationType::anyDependentTemplateArguments(*TemplateArgs, Converted); MultiLevelTemplateArgumentList MLTAL; - MLTAL.addOuterTemplateArguments(Converted); + MLTAL.addOuterTemplateArguments(NamedConcept, Converted); LocalInstantiationScope Scope(*this); if (!AreArgsDependent && CheckConstraintSatisfaction( @@ -5199,8 +5197,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); @@ -5255,8 +5253,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); @@ -5308,8 +5306,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); @@ -5493,18 +5491,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()); } @@ -5647,15 +5642,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; } @@ -6017,7 +6012,7 @@ // FIXME: This will be changed a bit once deferred concept instantiation is // implemented. MultiLevelTemplateArgumentList MLTAL; - MLTAL.addOuterTemplateArguments(Converted); + MLTAL.addOuterTemplateArguments(Template, Converted); if (EnsureTemplateArgumentListConstraints( Template, MLTAL, SourceRange(TemplateLoc, TemplateArgs.getRAngleLoc()))) { 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, @@ -2859,7 +2859,7 @@ // FIXME: This will change quite a bit once deferred concept instantiation is // implemented. MultiLevelTemplateArgumentList MLTAL; - MLTAL.addOuterTemplateArguments(DeducedArgs); + MLTAL.addOuterTemplateArguments(Template, DeducedArgs); if (S.CheckConstraintSatisfaction(Template, AssociatedConstraints, MLTAL, Info.getLocation(), @@ -2914,9 +2914,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; @@ -3253,7 +3254,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; } @@ -3279,7 +3281,8 @@ ResultType = SubstType(Proto->getReturnType(), - MultiLevelTemplateArgumentList(*ExplicitArgumentList), + MultiLevelTemplateArgumentList( + FunctionTemplate, ExplicitArgumentList->asArray()), Function->getTypeSpecStartLoc(), Function->getDeclName()); if (ResultType.isNull() || Trap.hasErrorOccurred()) return TDK_SubstitutionFailure; @@ -3297,7 +3300,8 @@ if (!Proto->hasTrailingReturn() && SubstParmTypes(Function->getLocation(), Function->parameters(), Proto->getExtParameterInfosOrNull(), - MultiLevelTemplateArgumentList(*ExplicitArgumentList), + MultiLevelTemplateArgumentList( + FunctionTemplate, ExplicitArgumentList->asArray()), ParamTypes, /*params*/ nullptr, ExtParamInfos)) return TDK_SubstitutionFailure; @@ -3312,7 +3316,8 @@ if (getLangOpts().CPlusPlus17 && SubstExceptionSpec( Function->getLocation(), EPI.ExceptionSpec, ExceptionStorage, - MultiLevelTemplateArgumentList(*ExplicitArgumentList))) + MultiLevelTemplateArgumentList(FunctionTemplate, + ExplicitArgumentList->asArray()))) return TDK_SubstitutionFailure; *FunctionType = BuildFunctionType(ResultType, ParamTypes, @@ -3552,7 +3557,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()) @@ -4609,7 +4615,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)) @@ -5881,9 +5887,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 @@ -64,7 +64,8 @@ MultiLevelTemplateArgumentList Result; if (Innermost) - Result.addOuterTemplateArguments(Innermost); + Result.addOuterTemplateArguments(const_cast(D), + Innermost->asArray()); const auto *Ctx = dyn_cast(D); if (!Ctx) { @@ -80,8 +81,6 @@ !isa(Spec)) return Result; - Result.addOuterTemplateArguments(&Spec->getTemplateInstantiationArgs()); - // If this variable template specialization was instantiated from a // specialized member that is a variable template, we're done. assert(Spec->getSpecializedTemplate() && "No variable template?"); @@ -90,10 +89,14 @@ = Spec->getSpecializedTemplateOrPartial(); if (VarTemplatePartialSpecializationDecl *Partial = Specialized.dyn_cast()) { + Result.addOuterTemplateArguments( + Partial, Spec->getTemplateInstantiationArgs().asArray()); if (Partial->isMemberSpecialization()) return Result; } else { VarTemplateDecl *Tmpl = Specialized.get(); + Result.addOuterTemplateArguments( + Tmpl, Spec->getTemplateInstantiationArgs().asArray()); if (Tmpl->isMemberSpecialization()) return Result; } @@ -123,7 +126,9 @@ !isa(Spec)) break; - Result.addOuterTemplateArguments(&Spec->getTemplateInstantiationArgs()); + Result.addOuterTemplateArguments( + const_cast(Spec), + Spec->getTemplateInstantiationArgs().asArray()); // If this class template specialization was instantiated from a // specialized member that is a class template, we're done. @@ -146,7 +151,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. @@ -1813,6 +1819,7 @@ return NewT; } + Decl *AssociatedDecl = TemplateArgs.getAssociatedDecl(T->getDepth()); Optional PackIndex; if (T->isParameterPack()) { assert(Arg.getKind() == TemplateArgument::Pack && @@ -1822,8 +1829,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()); @@ -1842,7 +1849,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()); @@ -1856,8 +1863,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); @@ -1866,27 +1872,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 @@ -4775,7 +4775,7 @@ return nullptr; ContextRAII SavedContext(*this, FD); - MultiLevelTemplateArgumentList MArgs(*Args); + MultiLevelTemplateArgumentList MArgs(FTD, Args->asArray()); return cast_or_null(SubstDecl(FD, FD->getParent(), MArgs)); } @@ -5121,9 +5121,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 @@ -5142,7 +5139,8 @@ if (!IsMemberSpec) FromVar = FromVar->getFirstDecl(); - MultiLevelTemplateArgumentList MultiLevelList(TemplateArgList); + MultiLevelTemplateArgumentList MultiLevelList(VarTemplate, + TemplateArgList.asArray()); 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 @@ -4852,8 +4852,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(); @@ -6400,6 +6400,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. @@ -6409,7 +6412,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 @@ -886,75 +886,18 @@ 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->setCachedLinkage(static_cast(Record.readInt())); - FD->EndRangeLoc = 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)); - } - } + std::tuple Merge = {}; + auto doMerge = [&Merge](FunctionDecl *Existing = nullptr) { + Merge = {true, Existing}; + }; switch ((FunctionDecl::TemplatedKind)Record.readInt()) { case FunctionDecl::TK_NonTemplate: - mergeRedeclarable(FD, Redecl); + doMerge(); break; case FunctionDecl::TK_DependentNonTemplate: - mergeRedeclarable(FD, Redecl); + doMerge(); FD->setInstantiatedFromDecl(readDeclAs()); break; case FunctionDecl::TK_FunctionTemplate: @@ -967,7 +910,7 @@ SourceLocation POI = readSourceLocation(); FD->setInstantiationOfMemberFunction(Reader.getContext(), InstFD, TSK); FD->getMemberSpecializationInfo()->setPointOfInstantiation(POI); - mergeRedeclarable(FD, Redecl); + doMerge(); break; } case FunctionDecl::TK_FunctionTemplateSpecialization: { @@ -1038,7 +981,7 @@ else { assert(Reader.getContext().getLangOpts().Modules && "already deserialized this template specialization"); - mergeRedeclarable(FD, ExistingInfo->getFunction(), Redecl); + doMerge(ExistingInfo->getFunction()); } } break; @@ -1066,6 +1009,78 @@ } } + 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->setCachedLinkage(static_cast(Record.readInt())); + FD->EndRangeLoc = 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 (auto [DoIt, Existing] = Merge; DoIt) { + if (Existing) + mergeRedeclarable(FD, Existing, Redecl); + 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); @@ -2390,8 +2405,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)) { @@ -2428,6 +2441,8 @@ D->SpecializationKind = (TemplateSpecializationKind)Record.readInt(); D->IsCompleteDefinition = Record.readInt(); + RedeclarableResult Redecl = VisitVarDeclImpl(D); + bool writtenAsCanonicalDecl = Record.readInt(); if (writtenAsCanonicalDecl) { auto *CanonPattern = readDeclAs(); 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 @@ -540,46 +540,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->getLinkageInternal()); - Record.AddSourceLocation(D->getEndLoc()); - - 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()) { @@ -660,6 +620,48 @@ } } + 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->getLinkageInternal()); + Record.AddSourceLocation(D->getEndLoc()); + + 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); @@ -1404,14 +1406,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; @@ -1607,8 +1607,6 @@ VarTemplateSpecializationDecl *D) { RegisterTemplateSpecialization(D->getSpecializedTemplate(), D); - VisitVarDecl(D); - llvm::PointerUnion InstFrom = D->getSpecializedTemplateOrPartial(); if (Decl *InstFromD = InstFrom.dyn_cast()) { @@ -1629,6 +1627,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()) { @@ -2233,6 +2234,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 @@ -2278,11 +2281,10 @@ Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); // Linkage Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // LocEnd 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/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