https://github.com/sdkrystian updated https://github.com/llvm/llvm-project/pull/81642
>From b45a42322682f3b872e6753965c4e4a7edb68333 Mon Sep 17 00:00:00 2001 From: Krystian Stasiowski <sdkryst...@gmail.com> Date: Fri, 9 Feb 2024 14:00:49 -0500 Subject: [PATCH 1/5] [Clang] Unify interface for accessing template arguments as written for class/variable template specializations --- clang/include/clang/AST/DeclTemplate.h | 186 ++++++++---------- clang/include/clang/AST/RecursiveASTVisitor.h | 27 +-- clang/include/clang/ASTMatchers/ASTMatchers.h | 7 +- .../clang/ASTMatchers/ASTMatchersInternal.h | 4 - clang/lib/AST/ASTImporter.cpp | 55 +++--- clang/lib/AST/DeclPrinter.cpp | 15 +- clang/lib/AST/DeclTemplate.cpp | 145 ++++++++------ clang/lib/AST/TypePrinter.cpp | 24 +-- clang/lib/Index/IndexDecl.cpp | 9 +- clang/lib/Sema/Sema.cpp | 2 +- clang/lib/Sema/SemaTemplate.cpp | 47 ++--- .../lib/Sema/SemaTemplateInstantiateDecl.cpp | 155 ++++++--------- clang/lib/Serialization/ASTReaderDecl.cpp | 20 +- clang/lib/Serialization/ASTWriterDecl.cpp | 16 +- clang/test/AST/ast-dump-template-decls.cpp | 18 +- clang/test/Index/Core/index-source.cpp | 11 -- clang/test/Index/index-refs.cpp | 1 - clang/tools/libclang/CIndex.cpp | 29 ++- .../ASTMatchers/ASTMatchersNodeTest.cpp | 12 -- .../ASTMatchers/ASTMatchersTraversalTest.cpp | 18 +- 20 files changed, 360 insertions(+), 441 deletions(-) diff --git a/clang/include/clang/AST/DeclTemplate.h b/clang/include/clang/AST/DeclTemplate.h index e3b6a7efb1127af..b5c2d4597151205 100644 --- a/clang/include/clang/AST/DeclTemplate.h +++ b/clang/include/clang/AST/DeclTemplate.h @@ -1792,10 +1792,9 @@ class ClassTemplateSpecializationDecl llvm::PointerUnion<ClassTemplateDecl *, SpecializedPartialSpecialization *> SpecializedTemplate; - /// Further info for explicit template specialization/instantiation. - struct ExplicitSpecializationInfo { - /// The type-as-written. - TypeSourceInfo *TypeAsWritten = nullptr; + struct ExplicitInstantiationInfo { + /// The template arguments as written.. + const ASTTemplateArgumentListInfo *TemplateArgsAsWritten = nullptr; /// The location of the extern keyword. SourceLocation ExternLoc; @@ -1803,12 +1802,14 @@ class ClassTemplateSpecializationDecl /// The location of the template keyword. SourceLocation TemplateKeywordLoc; - ExplicitSpecializationInfo() = default; + ExplicitInstantiationInfo() = default; }; /// Further info for explicit template specialization/instantiation. /// Does not apply to implicit specializations. - ExplicitSpecializationInfo *ExplicitInfo = nullptr; + llvm::PointerUnion<const ASTTemplateArgumentListInfo *, + ExplicitInstantiationInfo *> + ExplicitInfo = nullptr; /// The template arguments used to describe this specialization. const TemplateArgumentList *TemplateArgs; @@ -1985,44 +1986,45 @@ class ClassTemplateSpecializationDecl SpecializedTemplate = TemplDecl; } - /// Sets the type of this specialization as it was written by - /// the user. This will be a class template specialization type. - void setTypeAsWritten(TypeSourceInfo *T) { - if (!ExplicitInfo) - ExplicitInfo = new (getASTContext()) ExplicitSpecializationInfo; - ExplicitInfo->TypeAsWritten = T; - } - - /// Gets the type of this specialization as it was written by - /// the user, if it was so written. - TypeSourceInfo *getTypeAsWritten() const { - return ExplicitInfo ? ExplicitInfo->TypeAsWritten : nullptr; + const ASTTemplateArgumentListInfo *getTemplateArgsAsWritten() const { + if (auto *Info = ExplicitInfo.dyn_cast<ExplicitInstantiationInfo *>()) + return Info->TemplateArgsAsWritten; + return ExplicitInfo.get<const ASTTemplateArgumentListInfo *>(); } /// Gets the location of the extern keyword, if present. SourceLocation getExternLoc() const { - return ExplicitInfo ? ExplicitInfo->ExternLoc : SourceLocation(); + if (auto *Info = ExplicitInfo.dyn_cast<ExplicitInstantiationInfo *>()) + return Info->ExternLoc; + return SourceLocation(); } - /// Sets the location of the extern keyword. - void setExternLoc(SourceLocation Loc) { - if (!ExplicitInfo) - ExplicitInfo = new (getASTContext()) ExplicitSpecializationInfo; - ExplicitInfo->ExternLoc = Loc; + /// Gets the location of the template keyword, if present. + SourceLocation getTemplateKeywordLoc() const { + if (auto *Info = ExplicitInfo.dyn_cast<ExplicitInstantiationInfo *>()) + return Info->TemplateKeywordLoc; + return SourceLocation(); } - /// Sets the location of the template keyword. - void setTemplateKeywordLoc(SourceLocation Loc) { - if (!ExplicitInfo) - ExplicitInfo = new (getASTContext()) ExplicitSpecializationInfo; - ExplicitInfo->TemplateKeywordLoc = Loc; + void + setTemplateArgsAsWritten(const ASTTemplateArgumentListInfo *ArgsWritten) { + if (auto *Info = ExplicitInfo.dyn_cast<ExplicitInstantiationInfo *>()) + Info->TemplateArgsAsWritten = ArgsWritten; + else + ExplicitInfo = ArgsWritten; } - /// Gets the location of the template keyword, if present. - SourceLocation getTemplateKeywordLoc() const { - return ExplicitInfo ? ExplicitInfo->TemplateKeywordLoc : SourceLocation(); + void setTemplateArgsAsWritten(const TemplateArgumentListInfo &ArgsInfo) { + setTemplateArgsAsWritten( + ASTTemplateArgumentListInfo::Create(getASTContext(), ArgsInfo)); } + /// Sets the location of the extern keyword. + void setExternLoc(SourceLocation Loc); + + /// Sets the location of the template keyword. + void setTemplateKeywordLoc(SourceLocation Loc); + SourceRange getSourceRange() const override LLVM_READONLY; void Profile(llvm::FoldingSetNodeID &ID) const { @@ -2050,10 +2052,6 @@ class ClassTemplatePartialSpecializationDecl /// The list of template parameters TemplateParameterList* TemplateParams = nullptr; - /// The source info for the template arguments as written. - /// FIXME: redundant with TypeAsWritten? - const ASTTemplateArgumentListInfo *ArgsAsWritten = nullptr; - /// The class template partial specialization from which this /// class template partial specialization was instantiated. /// @@ -2062,15 +2060,11 @@ class ClassTemplatePartialSpecializationDecl llvm::PointerIntPair<ClassTemplatePartialSpecializationDecl *, 1, bool> InstantiatedFromMember; - ClassTemplatePartialSpecializationDecl(ASTContext &Context, TagKind TK, - DeclContext *DC, - SourceLocation StartLoc, - SourceLocation IdLoc, - TemplateParameterList *Params, - ClassTemplateDecl *SpecializedTemplate, - ArrayRef<TemplateArgument> Args, - const ASTTemplateArgumentListInfo *ArgsAsWritten, - ClassTemplatePartialSpecializationDecl *PrevDecl); + ClassTemplatePartialSpecializationDecl( + ASTContext &Context, TagKind TK, DeclContext *DC, SourceLocation StartLoc, + SourceLocation IdLoc, TemplateParameterList *Params, + ClassTemplateDecl *SpecializedTemplate, ArrayRef<TemplateArgument> Args, + ClassTemplatePartialSpecializationDecl *PrevDecl); ClassTemplatePartialSpecializationDecl(ASTContext &C) : ClassTemplateSpecializationDecl(C, ClassTemplatePartialSpecialization), @@ -2085,11 +2079,8 @@ class ClassTemplatePartialSpecializationDecl static ClassTemplatePartialSpecializationDecl * Create(ASTContext &Context, TagKind TK, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, - TemplateParameterList *Params, - ClassTemplateDecl *SpecializedTemplate, - ArrayRef<TemplateArgument> Args, - const TemplateArgumentListInfo &ArgInfos, - QualType CanonInjectedType, + TemplateParameterList *Params, ClassTemplateDecl *SpecializedTemplate, + ArrayRef<TemplateArgument> Args, QualType CanonInjectedType, ClassTemplatePartialSpecializationDecl *PrevDecl); static ClassTemplatePartialSpecializationDecl * @@ -2120,11 +2111,6 @@ class ClassTemplatePartialSpecializationDecl return TemplateParams->hasAssociatedConstraints(); } - /// Get the template arguments as written. - const ASTTemplateArgumentListInfo *getTemplateArgsAsWritten() const { - return ArgsAsWritten; - } - /// Retrieve the member class template partial specialization from /// which this particular class template partial specialization was /// instantiated. @@ -2596,10 +2582,9 @@ class VarTemplateSpecializationDecl : public VarDecl, llvm::PointerUnion<VarTemplateDecl *, SpecializedPartialSpecialization *> SpecializedTemplate; - /// Further info for explicit template specialization/instantiation. - struct ExplicitSpecializationInfo { - /// The type-as-written. - TypeSourceInfo *TypeAsWritten = nullptr; + struct ExplicitInstantiationInfo { + /// The template arguments as written.. + const ASTTemplateArgumentListInfo *TemplateArgsAsWritten = nullptr; /// The location of the extern keyword. SourceLocation ExternLoc; @@ -2607,12 +2592,14 @@ class VarTemplateSpecializationDecl : public VarDecl, /// The location of the template keyword. SourceLocation TemplateKeywordLoc; - ExplicitSpecializationInfo() = default; + ExplicitInstantiationInfo() = default; }; /// Further info for explicit template specialization/instantiation. /// Does not apply to implicit specializations. - ExplicitSpecializationInfo *ExplicitInfo = nullptr; + llvm::PointerUnion<const ASTTemplateArgumentListInfo *, + ExplicitInstantiationInfo *> + ExplicitInfo = nullptr; /// The template arguments used to describe this specialization. const TemplateArgumentList *TemplateArgs; @@ -2670,14 +2657,6 @@ class VarTemplateSpecializationDecl : public VarDecl, /// specialization. const TemplateArgumentList &getTemplateArgs() const { return *TemplateArgs; } - // TODO: Always set this when creating the new specialization? - void setTemplateArgsInfo(const TemplateArgumentListInfo &ArgsInfo); - void setTemplateArgsInfo(const ASTTemplateArgumentListInfo *ArgsInfo); - - const ASTTemplateArgumentListInfo *getTemplateArgsInfo() const { - return TemplateArgsInfo; - } - /// Determine the kind of specialization that this /// declaration represents. TemplateSpecializationKind getSpecializationKind() const { @@ -2781,44 +2760,45 @@ class VarTemplateSpecializationDecl : public VarDecl, SpecializedTemplate = TemplDecl; } - /// Sets the type of this specialization as it was written by - /// the user. - void setTypeAsWritten(TypeSourceInfo *T) { - if (!ExplicitInfo) - ExplicitInfo = new (getASTContext()) ExplicitSpecializationInfo; - ExplicitInfo->TypeAsWritten = T; - } - - /// Gets the type of this specialization as it was written by - /// the user, if it was so written. - TypeSourceInfo *getTypeAsWritten() const { - return ExplicitInfo ? ExplicitInfo->TypeAsWritten : nullptr; + const ASTTemplateArgumentListInfo *getTemplateArgsAsWritten() const { + if (auto *Info = ExplicitInfo.dyn_cast<ExplicitInstantiationInfo *>()) + return Info->TemplateArgsAsWritten; + return ExplicitInfo.get<const ASTTemplateArgumentListInfo *>(); } /// Gets the location of the extern keyword, if present. SourceLocation getExternLoc() const { - return ExplicitInfo ? ExplicitInfo->ExternLoc : SourceLocation(); + if (auto *Info = ExplicitInfo.dyn_cast<ExplicitInstantiationInfo *>()) + return Info->ExternLoc; + return SourceLocation(); } - /// Sets the location of the extern keyword. - void setExternLoc(SourceLocation Loc) { - if (!ExplicitInfo) - ExplicitInfo = new (getASTContext()) ExplicitSpecializationInfo; - ExplicitInfo->ExternLoc = Loc; + /// Gets the location of the template keyword, if present. + SourceLocation getTemplateKeywordLoc() const { + if (auto *Info = ExplicitInfo.dyn_cast<ExplicitInstantiationInfo *>()) + return Info->TemplateKeywordLoc; + return SourceLocation(); } - /// Sets the location of the template keyword. - void setTemplateKeywordLoc(SourceLocation Loc) { - if (!ExplicitInfo) - ExplicitInfo = new (getASTContext()) ExplicitSpecializationInfo; - ExplicitInfo->TemplateKeywordLoc = Loc; + void + setTemplateArgsAsWritten(const ASTTemplateArgumentListInfo *ArgsWritten) { + if (auto *Info = ExplicitInfo.dyn_cast<ExplicitInstantiationInfo *>()) + Info->TemplateArgsAsWritten = ArgsWritten; + else + ExplicitInfo = ArgsWritten; } - /// Gets the location of the template keyword, if present. - SourceLocation getTemplateKeywordLoc() const { - return ExplicitInfo ? ExplicitInfo->TemplateKeywordLoc : SourceLocation(); + void setTemplateArgsAsWritten(const TemplateArgumentListInfo &ArgsInfo) { + setTemplateArgsAsWritten( + ASTTemplateArgumentListInfo::Create(getASTContext(), ArgsInfo)); } + /// Sets the location of the extern keyword. + void setExternLoc(SourceLocation Loc); + + /// Sets the location of the template keyword. + void setTemplateKeywordLoc(SourceLocation Loc); + SourceRange getSourceRange() const override LLVM_READONLY; void Profile(llvm::FoldingSetNodeID &ID) const { @@ -2846,10 +2826,6 @@ class VarTemplatePartialSpecializationDecl /// The list of template parameters TemplateParameterList *TemplateParams = nullptr; - /// The source info for the template arguments as written. - /// FIXME: redundant with TypeAsWritten? - const ASTTemplateArgumentListInfo *ArgsAsWritten = nullptr; - /// The variable template partial specialization from which this /// variable template partial specialization was instantiated. /// @@ -2862,8 +2838,7 @@ class VarTemplatePartialSpecializationDecl ASTContext &Context, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, TemplateParameterList *Params, VarTemplateDecl *SpecializedTemplate, QualType T, TypeSourceInfo *TInfo, - StorageClass S, ArrayRef<TemplateArgument> Args, - const ASTTemplateArgumentListInfo *ArgInfos); + StorageClass S, ArrayRef<TemplateArgument> Args); VarTemplatePartialSpecializationDecl(ASTContext &Context) : VarTemplateSpecializationDecl(VarTemplatePartialSpecialization, @@ -2880,8 +2855,8 @@ class VarTemplatePartialSpecializationDecl Create(ASTContext &Context, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, TemplateParameterList *Params, VarTemplateDecl *SpecializedTemplate, QualType T, - TypeSourceInfo *TInfo, StorageClass S, ArrayRef<TemplateArgument> Args, - const TemplateArgumentListInfo &ArgInfos); + TypeSourceInfo *TInfo, StorageClass S, + ArrayRef<TemplateArgument> Args); static VarTemplatePartialSpecializationDecl *CreateDeserialized(ASTContext &C, unsigned ID); @@ -2897,11 +2872,6 @@ class VarTemplatePartialSpecializationDecl return TemplateParams; } - /// Get the template arguments as written. - const ASTTemplateArgumentListInfo *getTemplateArgsAsWritten() const { - return ArgsAsWritten; - } - /// \brief All associated constraints of this partial specialization, /// including the requires clause and any constraints derived from /// constrained-parameters. diff --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h index 4a1ff222ecadcda..c925c1f7a4856c7 100644 --- a/clang/include/clang/AST/RecursiveASTVisitor.h +++ b/clang/include/clang/AST/RecursiveASTVisitor.h @@ -2018,6 +2018,15 @@ DEF_TRAVERSE_DECL(RecordDecl, { TRY_TO(TraverseRecordHelper(D)); }) DEF_TRAVERSE_DECL(CXXRecordDecl, { TRY_TO(TraverseCXXRecordHelper(D)); }) +template <typename Derived> +bool RecursiveASTVisitor<Derived>::TraverseTemplateArgumentLocsHelper( + const TemplateArgumentLoc *TAL, unsigned Count) { + for (unsigned I = 0; I < Count; ++I) { + TRY_TO(TraverseTemplateArgumentLoc(TAL[I])); + } + return true; +} + #define DEF_TRAVERSE_TMPL_SPEC_DECL(TMPLDECLKIND, DECLKIND) \ DEF_TRAVERSE_DECL(TMPLDECLKIND##TemplateSpecializationDecl, { \ /* For implicit instantiations ("set<int> x;"), we don't want to \ @@ -2027,9 +2036,12 @@ DEF_TRAVERSE_DECL(CXXRecordDecl, { TRY_TO(TraverseCXXRecordHelper(D)); }) TemplateSpecializationType). For explicit instantiations \ ("template set<int>;"), we do need a callback, since this \ is the only callback that's made for this instantiation. \ - We use getTypeAsWritten() to distinguish. */ \ - if (TypeSourceInfo *TSI = D->getTypeAsWritten()) \ - TRY_TO(TraverseTypeLoc(TSI->getTypeLoc())); \ + We use getTemplateArgsAsWritten() to distinguish. */ \ + if (const auto *ArgsWritten = D->getTemplateArgsAsWritten()) { \ + /* The args that remains unspecialized. */ \ + TRY_TO(TraverseTemplateArgumentLocsHelper( \ + ArgsWritten->getTemplateArgs(), ArgsWritten->NumTemplateArgs)); \ + } \ \ if (getDerived().shouldVisitTemplateInstantiations() || \ D->getTemplateSpecializationKind() == TSK_ExplicitSpecialization) { \ @@ -2049,15 +2061,6 @@ DEF_TRAVERSE_DECL(CXXRecordDecl, { TRY_TO(TraverseCXXRecordHelper(D)); }) DEF_TRAVERSE_TMPL_SPEC_DECL(Class, CXXRecord) DEF_TRAVERSE_TMPL_SPEC_DECL(Var, Var) -template <typename Derived> -bool RecursiveASTVisitor<Derived>::TraverseTemplateArgumentLocsHelper( - const TemplateArgumentLoc *TAL, unsigned Count) { - for (unsigned I = 0; I < Count; ++I) { - TRY_TO(TraverseTemplateArgumentLoc(TAL[I])); - } - return true; -} - #define DEF_TRAVERSE_TMPL_PART_SPEC_DECL(TMPLDECLKIND, DECLKIND) \ DEF_TRAVERSE_DECL(TMPLDECLKIND##TemplatePartialSpecializationDecl, { \ /* The partial specialization. */ \ diff --git a/clang/include/clang/ASTMatchers/ASTMatchers.h b/clang/include/clang/ASTMatchers/ASTMatchers.h index 2f71053d030f688..044d4a07e5bd6f7 100644 --- a/clang/include/clang/ASTMatchers/ASTMatchers.h +++ b/clang/include/clang/ASTMatchers/ASTMatchers.h @@ -4066,7 +4066,7 @@ AST_POLYMORPHIC_MATCHER_P_OVERLOAD( /// Matcher<CXXCtorInitializer>, Matcher<CXXFunctionalCastExpr>, /// Matcher<CXXNewExpr>, Matcher<CXXTemporaryObjectExpr>, /// Matcher<CXXUnresolvedConstructExpr>, -/// Matcher<ClassTemplateSpecializationDecl>, Matcher<CompoundLiteralExpr>, +/// Matcher<CompoundLiteralExpr>, /// Matcher<DeclaratorDecl>, Matcher<ExplicitCastExpr>, /// Matcher<ObjCPropertyDecl>, Matcher<TemplateArgumentLoc>, /// Matcher<TypedefNameDecl> @@ -4075,9 +4075,8 @@ AST_POLYMORPHIC_MATCHER_P( AST_POLYMORPHIC_SUPPORTED_TYPES( BlockDecl, CXXBaseSpecifier, CXXCtorInitializer, CXXFunctionalCastExpr, CXXNewExpr, CXXTemporaryObjectExpr, CXXUnresolvedConstructExpr, - ClassTemplateSpecializationDecl, CompoundLiteralExpr, DeclaratorDecl, - ExplicitCastExpr, ObjCPropertyDecl, TemplateArgumentLoc, - TypedefNameDecl), + CompoundLiteralExpr, DeclaratorDecl, ExplicitCastExpr, ObjCPropertyDecl, + TemplateArgumentLoc, TypedefNameDecl), internal::Matcher<TypeLoc>, Inner) { TypeSourceInfo *source = internal::GetTypeSourceInfo(Node); if (source == nullptr) { diff --git a/clang/include/clang/ASTMatchers/ASTMatchersInternal.h b/clang/include/clang/ASTMatchers/ASTMatchersInternal.h index 47d912c73dd7eb4..dca642acfa38bcf 100644 --- a/clang/include/clang/ASTMatchers/ASTMatchersInternal.h +++ b/clang/include/clang/ASTMatchers/ASTMatchersInternal.h @@ -186,10 +186,6 @@ inline TypeSourceInfo *GetTypeSourceInfo(const BlockDecl &Node) { inline TypeSourceInfo *GetTypeSourceInfo(const CXXNewExpr &Node) { return Node.getAllocatedTypeSourceInfo(); } -inline TypeSourceInfo * -GetTypeSourceInfo(const ClassTemplateSpecializationDecl &Node) { - return Node.getTypeAsWritten(); -} /// Unifies obtaining the FunctionProtoType pointer from both /// FunctionProtoType and FunctionDecl nodes.. diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp index 786695f00fadccc..1705fcc25213b0f 100644 --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -6170,15 +6170,16 @@ ExpectedDecl ASTNodeImporter::VisitClassTemplateSpecializationDecl( if (!IdLocOrErr) return IdLocOrErr.takeError(); + // Import TemplateArgumentListInfo. + TemplateArgumentListInfo ToTAInfo; + if (const auto *ASTTemplateArgs = D->getTemplateArgsAsWritten()) { + if (Error Err = ImportTemplateArgumentListInfo(*ASTTemplateArgs, ToTAInfo)) + return std::move(Err); + } + // Create the specialization. ClassTemplateSpecializationDecl *D2 = nullptr; if (PartialSpec) { - // Import TemplateArgumentListInfo. - TemplateArgumentListInfo ToTAInfo; - const auto &ASTTemplateArgs = *PartialSpec->getTemplateArgsAsWritten(); - if (Error Err = ImportTemplateArgumentListInfo(ASTTemplateArgs, ToTAInfo)) - return std::move(Err); - QualType CanonInjType; if (Error Err = importInto( CanonInjType, PartialSpec->getInjectedSpecializationType())) @@ -6188,7 +6189,7 @@ ExpectedDecl ASTNodeImporter::VisitClassTemplateSpecializationDecl( if (GetImportedOrCreateDecl<ClassTemplatePartialSpecializationDecl>( D2, D, Importer.getToContext(), D->getTagKind(), DC, *BeginLocOrErr, *IdLocOrErr, ToTPList, ClassTemplate, - llvm::ArrayRef(TemplateArgs.data(), TemplateArgs.size()), ToTAInfo, + llvm::ArrayRef(TemplateArgs.data(), TemplateArgs.size()), CanonInjType, cast_or_null<ClassTemplatePartialSpecializationDecl>(PrevDecl))) return D2; @@ -6242,22 +6243,18 @@ ExpectedDecl ASTNodeImporter::VisitClassTemplateSpecializationDecl( else return LocOrErr.takeError(); - if (auto *TSI = D->getTypeAsWritten()) { - if (auto TInfoOrErr = import(TSI)) - D2->setTypeAsWritten(*TInfoOrErr); - else - return TInfoOrErr.takeError(); + if (D->getTemplateArgsAsWritten()) + D2->setTemplateArgsAsWritten(ToTAInfo); - if (auto LocOrErr = import(D->getTemplateKeywordLoc())) - D2->setTemplateKeywordLoc(*LocOrErr); - else - return LocOrErr.takeError(); + if (auto LocOrErr = import(D->getTemplateKeywordLoc())) + D2->setTemplateKeywordLoc(*LocOrErr); + else + return LocOrErr.takeError(); - if (auto LocOrErr = import(D->getExternLoc())) - D2->setExternLoc(*LocOrErr); - else - return LocOrErr.takeError(); - } + if (auto LocOrErr = import(D->getExternLoc())) + D2->setExternLoc(*LocOrErr); + else + return LocOrErr.takeError(); if (D->getPointOfInstantiation().isValid()) { if (auto POIOrErr = import(D->getPointOfInstantiation())) @@ -6477,7 +6474,7 @@ ExpectedDecl ASTNodeImporter::VisitVarTemplateSpecializationDecl( VarTemplateSpecializationDecl *D2 = nullptr; TemplateArgumentListInfo ToTAInfo; - if (const ASTTemplateArgumentListInfo *Args = D->getTemplateArgsInfo()) { + if (const auto *Args = D->getTemplateArgsAsWritten()) { if (Error Err = ImportTemplateArgumentListInfo(*Args, ToTAInfo)) return std::move(Err); } @@ -6485,14 +6482,6 @@ ExpectedDecl ASTNodeImporter::VisitVarTemplateSpecializationDecl( using PartVarSpecDecl = VarTemplatePartialSpecializationDecl; // Create a new specialization. if (auto *FromPartial = dyn_cast<PartVarSpecDecl>(D)) { - // Import TemplateArgumentListInfo - TemplateArgumentListInfo ArgInfos; - const auto *FromTAArgsAsWritten = FromPartial->getTemplateArgsAsWritten(); - // NOTE: FromTAArgsAsWritten and template parameter list are non-null. - if (Error Err = - ImportTemplateArgumentListInfo(*FromTAArgsAsWritten, ArgInfos)) - return std::move(Err); - auto ToTPListOrErr = import(FromPartial->getTemplateParameters()); if (!ToTPListOrErr) return ToTPListOrErr.takeError(); @@ -6501,7 +6490,7 @@ ExpectedDecl ASTNodeImporter::VisitVarTemplateSpecializationDecl( if (GetImportedOrCreateDecl(ToPartial, D, Importer.getToContext(), DC, *BeginLocOrErr, *IdLocOrErr, *ToTPListOrErr, VarTemplate, QualType(), nullptr, - D->getStorageClass(), TemplateArgs, ArgInfos)) + D->getStorageClass(), TemplateArgs)) return ToPartial; if (Expected<PartVarSpecDecl *> ToInstOrErr = @@ -6544,7 +6533,9 @@ ExpectedDecl ASTNodeImporter::VisitVarTemplateSpecializationDecl( } D2->setSpecializationKind(D->getSpecializationKind()); - D2->setTemplateArgsInfo(ToTAInfo); + + if (D->getTemplateArgsAsWritten()) + D2->setTemplateArgsAsWritten(ToTAInfo); if (auto LocOrErr = import(D->getQualifierLoc())) D2->setQualifierInfo(*LocOrErr); diff --git a/clang/lib/AST/DeclPrinter.cpp b/clang/lib/AST/DeclPrinter.cpp index edbcdfe4d55bc94..f1ff90083e24464 100644 --- a/clang/lib/AST/DeclPrinter.cpp +++ b/clang/lib/AST/DeclPrinter.cpp @@ -1156,14 +1156,13 @@ void DeclPrinter::VisitCXXRecordDecl(CXXRecordDecl *D) { Out << *D; if (auto S = dyn_cast<ClassTemplateSpecializationDecl>(D)) { - ArrayRef<TemplateArgument> Args = S->getTemplateArgs().asArray(); - if (!Policy.PrintCanonicalTypes) - if (const auto* TSI = S->getTypeAsWritten()) - if (const auto *TST = - dyn_cast<TemplateSpecializationType>(TSI->getType())) - Args = TST->template_arguments(); - printTemplateArguments( - Args, S->getSpecializedTemplate()->getTemplateParameters()); + const TemplateParameterList *TParams = + S->getSpecializedTemplate()->getTemplateParameters(); + const auto *TArgAsWritten = S->getTemplateArgsAsWritten(); + if (TArgAsWritten && !Policy.PrintCanonicalTypes) + printTemplateArguments(TArgAsWritten->arguments(), TParams); + else + printTemplateArguments(S->getTemplateArgs().asArray(), TParams); } } diff --git a/clang/lib/AST/DeclTemplate.cpp b/clang/lib/AST/DeclTemplate.cpp index 3c217d6a6a5ae31..9a91e050512c741 100644 --- a/clang/lib/AST/DeclTemplate.cpp +++ b/clang/lib/AST/DeclTemplate.cpp @@ -986,8 +986,15 @@ ClassTemplateSpecializationDecl::getSpecializedTemplate() const { SourceRange ClassTemplateSpecializationDecl::getSourceRange() const { + using CTPSDecl = ClassTemplatePartialSpecializationDecl; if (ExplicitInfo) { SourceLocation Begin = getTemplateKeywordLoc(); + if (Begin.isInvalid()) { + if (getNumTemplateParameterLists()) + Begin = getTemplateParameterList(0)->getTemplateLoc(); + else if (const auto *CTPSD = dyn_cast<CTPSDecl>(this)) + Begin = CTPSD->getTemplateParameters()->getTemplateLoc(); + } if (Begin.isValid()) { // Here we have an explicit (partial) specialization or instantiation. assert(getSpecializationKind() == TSK_ExplicitSpecialization || @@ -997,13 +1004,12 @@ ClassTemplateSpecializationDecl::getSourceRange() const { Begin = getExternLoc(); SourceLocation End = getBraceRange().getEnd(); if (End.isInvalid()) - End = getTypeAsWritten()->getTypeLoc().getEndLoc(); + End = getTemplateArgsAsWritten()->getRAngleLoc(); return SourceRange(Begin, End); } // An implicit instantiation of a class template partial specialization // uses ExplicitInfo to record the TypeAsWritten, but the source // locations should be retrieved from the instantiation pattern. - using CTPSDecl = ClassTemplatePartialSpecializationDecl; auto *ctpsd = const_cast<CTPSDecl *>(cast<CTPSDecl>(this)); CTPSDecl *inst_from = ctpsd->getInstantiatedFromMember(); assert(inst_from != nullptr); @@ -1023,6 +1029,33 @@ ClassTemplateSpecializationDecl::getSourceRange() const { } } +void ClassTemplateSpecializationDecl::setExternLoc(SourceLocation Loc) { + auto *Info = ExplicitInfo.dyn_cast<ExplicitInstantiationInfo *>(); + if (!Info) { + // Don't allocate if the location is invalid. + if (Loc.isInvalid()) + return; + Info = new (getASTContext()) ExplicitInstantiationInfo; + Info->TemplateArgsAsWritten = getTemplateArgsAsWritten(); + ExplicitInfo = Info; + } + Info->ExternLoc = Loc; +} + +void ClassTemplateSpecializationDecl::setTemplateKeywordLoc( + SourceLocation Loc) { + auto *Info = ExplicitInfo.dyn_cast<ExplicitInstantiationInfo *>(); + if (!Info) { + // Don't allocate if the location is invalid. + if (Loc.isInvalid()) + return; + Info = new (getASTContext()) ExplicitInstantiationInfo; + Info->TemplateArgsAsWritten = getTemplateArgsAsWritten(); + ExplicitInfo = Info; + } + Info->TemplateKeywordLoc = Loc; +} + //===----------------------------------------------------------------------===// // ConceptDecl Implementation //===----------------------------------------------------------------------===// @@ -1089,43 +1122,29 @@ void ImplicitConceptSpecializationDecl::setTemplateArguments( //===----------------------------------------------------------------------===// void ClassTemplatePartialSpecializationDecl::anchor() {} -ClassTemplatePartialSpecializationDecl:: -ClassTemplatePartialSpecializationDecl(ASTContext &Context, TagKind TK, - DeclContext *DC, - SourceLocation StartLoc, - SourceLocation IdLoc, - TemplateParameterList *Params, - ClassTemplateDecl *SpecializedTemplate, - ArrayRef<TemplateArgument> Args, - const ASTTemplateArgumentListInfo *ArgInfos, - ClassTemplatePartialSpecializationDecl *PrevDecl) - : ClassTemplateSpecializationDecl(Context, - ClassTemplatePartialSpecialization, - TK, DC, StartLoc, IdLoc, - SpecializedTemplate, Args, PrevDecl), - TemplateParams(Params), ArgsAsWritten(ArgInfos), - InstantiatedFromMember(nullptr, false) { +ClassTemplatePartialSpecializationDecl::ClassTemplatePartialSpecializationDecl( + ASTContext &Context, TagKind TK, DeclContext *DC, SourceLocation StartLoc, + SourceLocation IdLoc, TemplateParameterList *Params, + ClassTemplateDecl *SpecializedTemplate, ArrayRef<TemplateArgument> Args, + ClassTemplatePartialSpecializationDecl *PrevDecl) + : ClassTemplateSpecializationDecl( + Context, ClassTemplatePartialSpecialization, TK, DC, StartLoc, IdLoc, + SpecializedTemplate, Args, PrevDecl), + TemplateParams(Params), InstantiatedFromMember(nullptr, false) { if (AdoptTemplateParameterList(Params, this)) setInvalidDecl(); } ClassTemplatePartialSpecializationDecl * -ClassTemplatePartialSpecializationDecl:: -Create(ASTContext &Context, TagKind TK,DeclContext *DC, - SourceLocation StartLoc, SourceLocation IdLoc, - TemplateParameterList *Params, - ClassTemplateDecl *SpecializedTemplate, - ArrayRef<TemplateArgument> Args, - const TemplateArgumentListInfo &ArgInfos, - QualType CanonInjectedType, - ClassTemplatePartialSpecializationDecl *PrevDecl) { - const ASTTemplateArgumentListInfo *ASTArgInfos = - ASTTemplateArgumentListInfo::Create(Context, ArgInfos); - - auto *Result = new (Context, DC) - ClassTemplatePartialSpecializationDecl(Context, TK, DC, StartLoc, IdLoc, - Params, SpecializedTemplate, Args, - ASTArgInfos, PrevDecl); +ClassTemplatePartialSpecializationDecl::Create( + ASTContext &Context, TagKind TK, DeclContext *DC, SourceLocation StartLoc, + SourceLocation IdLoc, TemplateParameterList *Params, + ClassTemplateDecl *SpecializedTemplate, ArrayRef<TemplateArgument> Args, + QualType CanonInjectedType, + ClassTemplatePartialSpecializationDecl *PrevDecl) { + auto *Result = new (Context, DC) ClassTemplatePartialSpecializationDecl( + Context, TK, DC, StartLoc, IdLoc, Params, SpecializedTemplate, Args, + PrevDecl); Result->setSpecializationKind(TSK_ExplicitSpecialization); Result->setMayHaveOutOfDateDef(false); @@ -1372,26 +1391,39 @@ VarTemplateDecl *VarTemplateSpecializationDecl::getSpecializedTemplate() const { return SpecializedTemplate.get<VarTemplateDecl *>(); } -void VarTemplateSpecializationDecl::setTemplateArgsInfo( - const TemplateArgumentListInfo &ArgsInfo) { - TemplateArgsInfo = - ASTTemplateArgumentListInfo::Create(getASTContext(), ArgsInfo); -} - -void VarTemplateSpecializationDecl::setTemplateArgsInfo( - const ASTTemplateArgumentListInfo *ArgsInfo) { - TemplateArgsInfo = - ASTTemplateArgumentListInfo::Create(getASTContext(), ArgsInfo); -} - SourceRange VarTemplateSpecializationDecl::getSourceRange() const { if (isExplicitSpecialization() && !hasInit()) { - if (const ASTTemplateArgumentListInfo *Info = getTemplateArgsInfo()) + if (const ASTTemplateArgumentListInfo *Info = getTemplateArgsAsWritten()) return SourceRange(getOuterLocStart(), Info->getRAngleLoc()); } return VarDecl::getSourceRange(); } +void VarTemplateSpecializationDecl::setExternLoc(SourceLocation Loc) { + auto *Info = ExplicitInfo.dyn_cast<ExplicitInstantiationInfo *>(); + if (!Info) { + // Don't allocate if the location is invalid. + if (Loc.isInvalid()) + return; + Info = new (getASTContext()) ExplicitInstantiationInfo; + Info->TemplateArgsAsWritten = getTemplateArgsAsWritten(); + ExplicitInfo = Info; + } + Info->ExternLoc = Loc; +} + +void VarTemplateSpecializationDecl::setTemplateKeywordLoc(SourceLocation Loc) { + auto *Info = ExplicitInfo.dyn_cast<ExplicitInstantiationInfo *>(); + if (!Info) { + // Don't allocate if the location is invalid. + if (Loc.isInvalid()) + return; + Info = new (getASTContext()) ExplicitInstantiationInfo; + Info->TemplateArgsAsWritten = getTemplateArgsAsWritten(); + ExplicitInfo = Info; + } + Info->TemplateKeywordLoc = Loc; +} //===----------------------------------------------------------------------===// // VarTemplatePartialSpecializationDecl Implementation @@ -1403,13 +1435,11 @@ VarTemplatePartialSpecializationDecl::VarTemplatePartialSpecializationDecl( ASTContext &Context, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, TemplateParameterList *Params, VarTemplateDecl *SpecializedTemplate, QualType T, TypeSourceInfo *TInfo, - StorageClass S, ArrayRef<TemplateArgument> Args, - const ASTTemplateArgumentListInfo *ArgInfos) + StorageClass S, ArrayRef<TemplateArgument> Args) : VarTemplateSpecializationDecl(VarTemplatePartialSpecialization, Context, DC, StartLoc, IdLoc, SpecializedTemplate, T, TInfo, S, Args), - TemplateParams(Params), ArgsAsWritten(ArgInfos), - InstantiatedFromMember(nullptr, false) { + TemplateParams(Params), InstantiatedFromMember(nullptr, false) { if (AdoptTemplateParameterList(Params, DC)) setInvalidDecl(); } @@ -1419,15 +1449,10 @@ VarTemplatePartialSpecializationDecl::Create( ASTContext &Context, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, TemplateParameterList *Params, VarTemplateDecl *SpecializedTemplate, QualType T, TypeSourceInfo *TInfo, - StorageClass S, ArrayRef<TemplateArgument> Args, - const TemplateArgumentListInfo &ArgInfos) { - const ASTTemplateArgumentListInfo *ASTArgInfos - = ASTTemplateArgumentListInfo::Create(Context, ArgInfos); - - auto *Result = - new (Context, DC) VarTemplatePartialSpecializationDecl( - Context, DC, StartLoc, IdLoc, Params, SpecializedTemplate, T, TInfo, - S, Args, ASTArgInfos); + StorageClass S, ArrayRef<TemplateArgument> Args) { + auto *Result = new (Context, DC) VarTemplatePartialSpecializationDecl( + Context, DC, StartLoc, IdLoc, Params, SpecializedTemplate, T, TInfo, S, + Args); Result->setSpecializationKind(TSK_ExplicitSpecialization); return Result; } diff --git a/clang/lib/AST/TypePrinter.cpp b/clang/lib/AST/TypePrinter.cpp index 7032ff2f18468c2..7703db77e6b3e01 100644 --- a/clang/lib/AST/TypePrinter.cpp +++ b/clang/lib/AST/TypePrinter.cpp @@ -1455,21 +1455,17 @@ void TypePrinter::printTag(TagDecl *D, raw_ostream &OS) { // If this is a class template specialization, print the template // arguments. - if (const auto *Spec = dyn_cast<ClassTemplateSpecializationDecl>(D)) { - ArrayRef<TemplateArgument> Args; - TypeSourceInfo *TAW = Spec->getTypeAsWritten(); - if (!Policy.PrintCanonicalTypes && TAW) { - const TemplateSpecializationType *TST = - cast<TemplateSpecializationType>(TAW->getType()); - Args = TST->template_arguments(); - } else { - const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs(); - Args = TemplateArgs.asArray(); - } + if (auto S = dyn_cast<ClassTemplateSpecializationDecl>(D)) { + const TemplateParameterList *TParams = + S->getSpecializedTemplate()->getTemplateParameters(); + const auto *TArgAsWritten = S->getTemplateArgsAsWritten(); IncludeStrongLifetimeRAII Strong(Policy); - printTemplateArgumentList( - OS, Args, Policy, - Spec->getSpecializedTemplate()->getTemplateParameters()); + if (TArgAsWritten && !Policy.PrintCanonicalTypes) + printTemplateArgumentList(OS, TArgAsWritten->arguments(), Policy, + TParams); + else + printTemplateArgumentList(OS, S->getTemplateArgs().asArray(), Policy, + TParams); } spaceBeforePlaceHolder(OS); diff --git a/clang/lib/Index/IndexDecl.cpp b/clang/lib/Index/IndexDecl.cpp index 1c04aa17d53fb2d..8eb88f5a1e94ee9 100644 --- a/clang/lib/Index/IndexDecl.cpp +++ b/clang/lib/Index/IndexDecl.cpp @@ -673,9 +673,12 @@ class IndexingDeclVisitor : public ConstDeclVisitor<IndexingDeclVisitor, bool> { IndexCtx.indexTagDecl( D, SymbolRelation(SymbolRoleSet(SymbolRole::RelationSpecializationOf), SpecializationOf)); - if (TypeSourceInfo *TSI = D->getTypeAsWritten()) - IndexCtx.indexTypeSourceInfo(TSI, /*Parent=*/nullptr, - D->getLexicalDeclContext()); + // Template specialization arguments. + if (const ASTTemplateArgumentListInfo *TemplateArgInfo = + D->getTemplateArgsAsWritten()) { + for (const auto &Arg : TemplateArgInfo->arguments()) + handleTemplateArgumentLoc(Arg, D, D->getLexicalDeclContext()); + } return true; } diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp index b4a47898cd17fc9..ae1034979516013 100644 --- a/clang/lib/Sema/Sema.cpp +++ b/clang/lib/Sema/Sema.cpp @@ -1399,7 +1399,7 @@ void Sema::ActOnEndOfTranslationUnit() { SourceRange DiagRange = DiagD->getLocation(); if (const auto *VTSD = dyn_cast<VarTemplateSpecializationDecl>(DiagD)) { if (const ASTTemplateArgumentListInfo *ASTTAL = - VTSD->getTemplateArgsInfo()) + VTSD->getTemplateArgsAsWritten()) DiagRange.setEnd(ASTTAL->RAngleLoc); } if (DiagD->isReferenced()) { diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 005529a53270c30..ab8bf26b4fc769c 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -5066,7 +5066,8 @@ DeclResult Sema::ActOnVarTemplateSpecialization( VarTemplatePartialSpecializationDecl::Create( Context, VarTemplate->getDeclContext(), TemplateKWLoc, TemplateNameLoc, TemplateParams, VarTemplate, DI->getType(), DI, SC, - CanonicalConverted, TemplateArgs); + CanonicalConverted); + Partial->setTemplateArgsAsWritten(TemplateArgs); if (!PrevPartial) VarTemplate->AddPartialSpecialization(Partial, InsertPos); @@ -5084,7 +5085,7 @@ DeclResult Sema::ActOnVarTemplateSpecialization( Specialization = VarTemplateSpecializationDecl::Create( Context, VarTemplate->getDeclContext(), TemplateKWLoc, TemplateNameLoc, VarTemplate, DI->getType(), DI, SC, CanonicalConverted); - Specialization->setTemplateArgsInfo(TemplateArgs); + Specialization->setTemplateArgsAsWritten(TemplateArgs); if (!PrevDecl) VarTemplate->AddSpecialization(Specialization, InsertPos); @@ -9370,7 +9371,8 @@ DeclResult Sema::ActOnClassTemplateSpecialization( ClassTemplatePartialSpecializationDecl::Create( Context, Kind, ClassTemplate->getDeclContext(), KWLoc, TemplateNameLoc, TemplateParams, ClassTemplate, CanonicalConverted, - TemplateArgs, CanonType, PrevPartial); + CanonType, PrevPartial); + Partial->setTemplateArgsAsWritten(TemplateArgs); SetNestedNameSpecifier(*this, Partial, SS); if (TemplateParameterLists.size() > 1 && SS.isSet()) { Partial->setTemplateParameterListsInfo( @@ -9393,6 +9395,7 @@ DeclResult Sema::ActOnClassTemplateSpecialization( Specialization = ClassTemplateSpecializationDecl::Create( Context, Kind, ClassTemplate->getDeclContext(), KWLoc, TemplateNameLoc, ClassTemplate, CanonicalConverted, PrevDecl); + Specialization->setTemplateArgsAsWritten(TemplateArgs); SetNestedNameSpecifier(*this, Specialization, SS); if (TemplateParameterLists.size() > 0) { Specialization->setTemplateParameterListsInfo(Context, @@ -9476,20 +9479,10 @@ DeclResult Sema::ActOnClassTemplateSpecialization( << (isPartialSpecialization? 1 : 0) << FixItHint::CreateRemoval(ModulePrivateLoc); - // Build the fully-sugared type for this class template - // specialization as the user wrote in the specialization - // itself. This means that we'll pretty-print the type retrieved - // from the specialization's declaration the way that the user - // actually wrote the specialization, rather than formatting the - // name based on the "canonical" representation used to store the - // template arguments in the specialization. - TypeSourceInfo *WrittenTy - = Context.getTemplateSpecializationTypeInfo(Name, TemplateNameLoc, - TemplateArgs, CanonType); - if (TUK != TUK_Friend) { - Specialization->setTypeAsWritten(WrittenTy); + if (TUK != TUK_Friend) + // FIXME: We really shouldn't be setting this unless this is an explicit + // instantiation. We already store the outer template parameter lists. Specialization->setTemplateKeywordLoc(TemplateKWLoc); - } // C++ [temp.expl.spec]p9: // A template explicit specialization is in the scope of the @@ -9506,6 +9499,15 @@ DeclResult Sema::ActOnClassTemplateSpecialization( Specialization->startDefinition(); if (TUK == TUK_Friend) { + // Build the fully-sugared type for this class template + // specialization as the user wrote in the specialization + // itself. This means that we'll pretty-print the type retrieved + // from the specialization's declaration the way that the user + // actually wrote the specialization, rather than formatting the + // name based on the "canonical" representation used to store the + // template arguments in the specialization. + TypeSourceInfo *WrittenTy = Context.getTemplateSpecializationTypeInfo( + Name, TemplateNameLoc, TemplateArgs, CanonType); FriendDecl *Friend = FriendDecl::Create(Context, CurContext, TemplateNameLoc, WrittenTy, @@ -10711,18 +10713,7 @@ DeclResult Sema::ActOnExplicitInstantiation( } } - // Build the fully-sugared type for this explicit instantiation as - // the user wrote in the explicit instantiation itself. This means - // that we'll pretty-print the type retrieved from the - // specialization's declaration the way that the user actually wrote - // the explicit instantiation, rather than formatting the name based - // on the "canonical" representation used to store the template - // arguments in the specialization. - TypeSourceInfo *WrittenTy - = Context.getTemplateSpecializationTypeInfo(Name, TemplateNameLoc, - TemplateArgs, - Context.getTypeDeclType(Specialization)); - Specialization->setTypeAsWritten(WrittenTy); + Specialization->setTemplateArgsAsWritten(TemplateArgs); // Set source locations for keywords. Specialization->setExternLoc(ExternLoc); diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index dc972018e7b2815..653659f3f4b6f3c 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -3841,15 +3841,16 @@ TemplateDeclInstantiator::VisitClassTemplateSpecializationDecl( // Substitute into the template arguments of the class template explicit // specialization. - TemplateSpecializationTypeLoc Loc = D->getTypeAsWritten()->getTypeLoc(). - castAs<TemplateSpecializationTypeLoc>(); - TemplateArgumentListInfo InstTemplateArgs(Loc.getLAngleLoc(), - Loc.getRAngleLoc()); - SmallVector<TemplateArgumentLoc, 4> ArgLocs; - for (unsigned I = 0; I != Loc.getNumArgs(); ++I) - ArgLocs.push_back(Loc.getArgLoc(I)); - if (SemaRef.SubstTemplateArguments(ArgLocs, TemplateArgs, InstTemplateArgs)) - return nullptr; + TemplateArgumentListInfo InstTemplateArgs; + if (const ASTTemplateArgumentListInfo *TemplateArgsInfo = + D->getTemplateArgsAsWritten()) { + InstTemplateArgs.setLAngleLoc(TemplateArgsInfo->getLAngleLoc()); + InstTemplateArgs.setRAngleLoc(TemplateArgsInfo->getRAngleLoc()); + + if (SemaRef.SubstTemplateArguments(TemplateArgsInfo->arguments(), + TemplateArgs, InstTemplateArgs)) + return nullptr; + } // Check that the template argument list is well-formed for this // class template. @@ -3903,6 +3904,7 @@ TemplateDeclInstantiator::VisitClassTemplateSpecializationDecl( ClassTemplateSpecializationDecl::Create( SemaRef.Context, D->getTagKind(), Owner, D->getBeginLoc(), D->getLocation(), InstClassTemplate, CanonicalConverted, PrevDecl); + InstD->setTemplateArgsAsWritten(InstTemplateArgs); // Add this partial specialization to the set of class template partial // specializations. @@ -3919,21 +3921,9 @@ TemplateDeclInstantiator::VisitClassTemplateSpecializationDecl( TemplateName(InstClassTemplate), CanonicalConverted, SemaRef.Context.getRecordType(InstD)); - // Build the fully-sugared type for this class template - // specialization as the user wrote in the specialization - // itself. This means that we'll pretty-print the type retrieved - // from the specialization's declaration the way that the user - // actually wrote the specialization, rather than formatting the - // name based on the "canonical" representation used to store the - // template arguments in the specialization. - TypeSourceInfo *WrittenTy = SemaRef.Context.getTemplateSpecializationTypeInfo( - TemplateName(InstClassTemplate), D->getLocation(), InstTemplateArgs, - CanonType); - InstD->setAccess(D->getAccess()); InstD->setInstantiationOfMemberClass(D, TSK_ImplicitInstantiation); InstD->setSpecializationKind(D->getSpecializationKind()); - InstD->setTypeAsWritten(WrittenTy); InstD->setExternLoc(D->getExternLoc()); InstD->setTemplateKeywordLoc(D->getTemplateKeywordLoc()); @@ -3968,7 +3958,7 @@ Decl *TemplateDeclInstantiator::VisitVarTemplateSpecializationDecl( // Substitute the current template arguments. if (const ASTTemplateArgumentListInfo *TemplateArgsInfo = - D->getTemplateArgsInfo()) { + D->getTemplateArgsAsWritten()) { VarTemplateArgsInfo.setLAngleLoc(TemplateArgsInfo->getLAngleLoc()); VarTemplateArgsInfo.setRAngleLoc(TemplateArgsInfo->getRAngleLoc()); @@ -4026,7 +4016,7 @@ Decl *TemplateDeclInstantiator::VisitVarTemplateSpecializationDecl( VarTemplateSpecializationDecl *Var = VarTemplateSpecializationDecl::Create( SemaRef.Context, Owner, D->getInnerLocStart(), D->getLocation(), VarTemplate, DI->getType(), DI, D->getStorageClass(), Converted); - Var->setTemplateArgsInfo(TemplateArgsInfo); + Var->setTemplateArgsAsWritten(TemplateArgsInfo); if (!PrevDecl) { void *InsertPos = nullptr; VarTemplate->findSpecialization(Converted, InsertPos); @@ -4268,19 +4258,21 @@ TemplateDeclInstantiator::InstantiateClassTemplatePartialSpecialization( QualType CanonType = SemaRef.Context.getTemplateSpecializationType( TemplateName(ClassTemplate), CanonicalConverted); - // Build the fully-sugared type for this class template - // specialization as the user wrote in the specialization - // itself. This means that we'll pretty-print the type retrieved - // from the specialization's declaration the way that the user - // actually wrote the specialization, rather than formatting the - // name based on the "canonical" representation used to store the - // template arguments in the specialization. - TypeSourceInfo *WrittenTy - = SemaRef.Context.getTemplateSpecializationTypeInfo( - TemplateName(ClassTemplate), - PartialSpec->getLocation(), - InstTemplateArgs, - CanonType); + // Create the class template partial specialization declaration. + ClassTemplatePartialSpecializationDecl *InstPartialSpec = + ClassTemplatePartialSpecializationDecl::Create( + SemaRef.Context, PartialSpec->getTagKind(), Owner, + PartialSpec->getBeginLoc(), PartialSpec->getLocation(), InstParams, + ClassTemplate, CanonicalConverted, CanonType, + /*PrevDecl=*/nullptr); + + InstPartialSpec->setTemplateArgsAsWritten(InstTemplateArgs); + + // Substitute the nested name specifier, if any. + if (SubstQualifier(PartialSpec, InstPartialSpec)) + return nullptr; + + InstPartialSpec->setInstantiatedFromMember(PartialSpec); if (PrevDecl) { // We've already seen a partial specialization with the same template @@ -4298,28 +4290,14 @@ TemplateDeclInstantiator::InstantiateClassTemplatePartialSpecialization( // // Outer<int, int> outer; // error: the partial specializations of Inner // // have the same signature. - SemaRef.Diag(PartialSpec->getLocation(), diag::err_partial_spec_redeclared) - << WrittenTy->getType(); + SemaRef.Diag(InstPartialSpec->getLocation(), + diag::err_partial_spec_redeclared) + << InstPartialSpec; SemaRef.Diag(PrevDecl->getLocation(), diag::note_prev_partial_spec_here) << SemaRef.Context.getTypeDeclType(PrevDecl); return nullptr; } - - // Create the class template partial specialization declaration. - ClassTemplatePartialSpecializationDecl *InstPartialSpec = - ClassTemplatePartialSpecializationDecl::Create( - SemaRef.Context, PartialSpec->getTagKind(), Owner, - PartialSpec->getBeginLoc(), PartialSpec->getLocation(), InstParams, - ClassTemplate, CanonicalConverted, InstTemplateArgs, CanonType, - nullptr); - // Substitute the nested name specifier, if any. - if (SubstQualifier(PartialSpec, InstPartialSpec)) - return nullptr; - - InstPartialSpec->setInstantiatedFromMember(PartialSpec); - InstPartialSpec->setTypeAsWritten(WrittenTy); - // Check the completed partial specialization. SemaRef.CheckTemplatePartialSpecialization(InstPartialSpec); @@ -4388,46 +4366,6 @@ TemplateDeclInstantiator::InstantiateVarTemplatePartialSpecialization( VarTemplate->findPartialSpecialization(CanonicalConverted, InstParams, InsertPos); - // Build the canonical type that describes the converted template - // arguments of the variable template partial specialization. - QualType CanonType = SemaRef.Context.getTemplateSpecializationType( - TemplateName(VarTemplate), CanonicalConverted); - - // Build the fully-sugared type for this variable template - // specialization as the user wrote in the specialization - // itself. This means that we'll pretty-print the type retrieved - // from the specialization's declaration the way that the user - // actually wrote the specialization, rather than formatting the - // name based on the "canonical" representation used to store the - // template arguments in the specialization. - TypeSourceInfo *WrittenTy = SemaRef.Context.getTemplateSpecializationTypeInfo( - TemplateName(VarTemplate), PartialSpec->getLocation(), InstTemplateArgs, - CanonType); - - if (PrevDecl) { - // We've already seen a partial specialization with the same template - // parameters and template arguments. This can happen, for example, when - // substituting the outer template arguments ends up causing two - // variable template partial specializations of a member variable template - // to have identical forms, e.g., - // - // template<typename T, typename U> - // struct Outer { - // template<typename X, typename Y> pair<X,Y> p; - // template<typename Y> pair<T, Y> p; - // template<typename Y> pair<U, Y> p; - // }; - // - // Outer<int, int> outer; // error: the partial specializations of Inner - // // have the same signature. - SemaRef.Diag(PartialSpec->getLocation(), - diag::err_var_partial_spec_redeclared) - << WrittenTy->getType(); - SemaRef.Diag(PrevDecl->getLocation(), - diag::note_var_prev_partial_spec_here); - return nullptr; - } - // Do substitution on the type of the declaration TypeSourceInfo *DI = SemaRef.SubstType( PartialSpec->getTypeSourceInfo(), TemplateArgs, @@ -4447,16 +4385,39 @@ TemplateDeclInstantiator::InstantiateVarTemplatePartialSpecialization( VarTemplatePartialSpecializationDecl::Create( SemaRef.Context, Owner, PartialSpec->getInnerLocStart(), PartialSpec->getLocation(), InstParams, VarTemplate, DI->getType(), - DI, PartialSpec->getStorageClass(), CanonicalConverted, - InstTemplateArgs); + DI, PartialSpec->getStorageClass(), CanonicalConverted); + + InstPartialSpec->setTemplateArgsAsWritten(InstTemplateArgs); // Substitute the nested name specifier, if any. if (SubstQualifier(PartialSpec, InstPartialSpec)) return nullptr; InstPartialSpec->setInstantiatedFromMember(PartialSpec); - InstPartialSpec->setTypeAsWritten(WrittenTy); + if (PrevDecl) { + // We've already seen a partial specialization with the same template + // parameters and template arguments. This can happen, for example, when + // substituting the outer template arguments ends up causing two + // variable template partial specializations of a member variable template + // to have identical forms, e.g., + // + // template<typename T, typename U> + // struct Outer { + // template<typename X, typename Y> pair<X,Y> p; + // template<typename Y> pair<T, Y> p; + // template<typename Y> pair<U, Y> p; + // }; + // + // Outer<int, int> outer; // error: the partial specializations of Inner + // // have the same signature. + SemaRef.Diag(PartialSpec->getLocation(), + diag::err_var_partial_spec_redeclared) + << InstPartialSpec; + SemaRef.Diag(PrevDecl->getLocation(), + diag::note_var_prev_partial_spec_here); + return nullptr; + } // Check the completed partial specialization. SemaRef.CheckTemplatePartialSpecialization(InstPartialSpec); @@ -5710,7 +5671,7 @@ void Sema::InstantiateVariableDefinition(SourceLocation PointOfInstantiation, TemplateArgumentListInfo TemplateArgInfo; if (const ASTTemplateArgumentListInfo *ArgInfo = - VarSpec->getTemplateArgsInfo()) { + VarSpec->getTemplateArgsAsWritten()) { TemplateArgInfo.setLAngleLoc(ArgInfo->getLAngleLoc()); TemplateArgInfo.setRAngleLoc(ArgInfo->getRAngleLoc()); for (const TemplateArgumentLoc &Arg : ArgInfo->arguments()) diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp index a22f760408c634f..15defab3e8ee2d9 100644 --- a/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/clang/lib/Serialization/ASTReaderDecl.cpp @@ -2549,10 +2549,13 @@ ASTDeclReader::VisitClassTemplateSpecializationDeclImpl( } // Explicit info. - if (TypeSourceInfo *TyInfo = readTypeSourceInfo()) { + if (Record.readBool()) { + // FIXME: We don't need to allocate this if ExternLoc and TemplateKeywordLoc + // are invalid! auto *ExplicitInfo = - new (C) ClassTemplateSpecializationDecl::ExplicitSpecializationInfo; - ExplicitInfo->TypeAsWritten = TyInfo; + new (C) ClassTemplateSpecializationDecl::ExplicitInstantiationInfo; + ExplicitInfo->TemplateArgsAsWritten = + Record.readASTTemplateArgumentListInfo(); ExplicitInfo->ExternLoc = readSourceLocation(); ExplicitInfo->TemplateKeywordLoc = readSourceLocation(); D->ExplicitInfo = ExplicitInfo; @@ -2567,7 +2570,6 @@ void ASTDeclReader::VisitClassTemplatePartialSpecializationDecl( // need them for profiling TemplateParameterList *Params = Record.readTemplateParameterList(); D->TemplateParams = Params; - D->ArgsAsWritten = Record.readASTTemplateArgumentListInfo(); RedeclarableResult Redecl = VisitClassTemplateSpecializationDeclImpl(D); @@ -2618,10 +2620,13 @@ ASTDeclReader::VisitVarTemplateSpecializationDeclImpl( } // Explicit info. - if (TypeSourceInfo *TyInfo = readTypeSourceInfo()) { + if (Record.readBool()) { + // FIXME: We don't need to allocate this if ExternLoc and TemplateKeywordLoc + // are invalid! auto *ExplicitInfo = - new (C) VarTemplateSpecializationDecl::ExplicitSpecializationInfo; - ExplicitInfo->TypeAsWritten = TyInfo; + new (C) VarTemplateSpecializationDecl::ExplicitInstantiationInfo; + ExplicitInfo->TemplateArgsAsWritten = + Record.readASTTemplateArgumentListInfo(); ExplicitInfo->ExternLoc = readSourceLocation(); ExplicitInfo->TemplateKeywordLoc = readSourceLocation(); D->ExplicitInfo = ExplicitInfo; @@ -2666,7 +2671,6 @@ void ASTDeclReader::VisitVarTemplatePartialSpecializationDecl( VarTemplatePartialSpecializationDecl *D) { TemplateParameterList *Params = Record.readTemplateParameterList(); D->TemplateParams = Params; - D->ArgsAsWritten = Record.readASTTemplateArgumentListInfo(); RedeclarableResult Redecl = VisitVarTemplateSpecializationDeclImpl(D); diff --git a/clang/lib/Serialization/ASTWriterDecl.cpp b/clang/lib/Serialization/ASTWriterDecl.cpp index 86f64bf2a24250b..06e9817af1eb1b9 100644 --- a/clang/lib/Serialization/ASTWriterDecl.cpp +++ b/clang/lib/Serialization/ASTWriterDecl.cpp @@ -1749,8 +1749,11 @@ void ASTDeclWriter::VisitClassTemplateSpecializationDecl( } // Explicit info. - Record.AddTypeSourceInfo(D->getTypeAsWritten()); - if (D->getTypeAsWritten()) { + const ASTTemplateArgumentListInfo *ArgsWritten = + D->getTemplateArgsAsWritten(); + Record.push_back(static_cast<bool>(ArgsWritten)); + if (ArgsWritten) { + Record.AddASTTemplateArgumentListInfo(D->getTemplateArgsAsWritten()); Record.AddSourceLocation(D->getExternLoc()); Record.AddSourceLocation(D->getTemplateKeywordLoc()); } @@ -1761,7 +1764,6 @@ void ASTDeclWriter::VisitClassTemplateSpecializationDecl( void ASTDeclWriter::VisitClassTemplatePartialSpecializationDecl( ClassTemplatePartialSpecializationDecl *D) { Record.AddTemplateParameterList(D->getTemplateParameters()); - Record.AddASTTemplateArgumentListInfo(D->getTemplateArgsAsWritten()); VisitClassTemplateSpecializationDecl(D); @@ -1796,8 +1798,11 @@ void ASTDeclWriter::VisitVarTemplateSpecializationDecl( } // Explicit info. - Record.AddTypeSourceInfo(D->getTypeAsWritten()); - if (D->getTypeAsWritten()) { + const ASTTemplateArgumentListInfo *ArgsWritten = + D->getTemplateArgsAsWritten(); + Record.push_back(static_cast<bool>(ArgsWritten)); + if (ArgsWritten) { + Record.AddASTTemplateArgumentListInfo(D->getTemplateArgsAsWritten()); Record.AddSourceLocation(D->getExternLoc()); Record.AddSourceLocation(D->getTemplateKeywordLoc()); } @@ -1822,7 +1827,6 @@ void ASTDeclWriter::VisitVarTemplateSpecializationDecl( void ASTDeclWriter::VisitVarTemplatePartialSpecializationDecl( VarTemplatePartialSpecializationDecl *D) { Record.AddTemplateParameterList(D->getTemplateParameters()); - Record.AddASTTemplateArgumentListInfo(D->getTemplateArgsAsWritten()); VisitVarTemplateSpecializationDecl(D); diff --git a/clang/test/AST/ast-dump-template-decls.cpp b/clang/test/AST/ast-dump-template-decls.cpp index 142bc9e6ad9a0e7..37f6d8a0472d30e 100644 --- a/clang/test/AST/ast-dump-template-decls.cpp +++ b/clang/test/AST/ast-dump-template-decls.cpp @@ -1,12 +1,12 @@ // Test without serialization: // RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-unknown -ast-dump %s \ -// RUN: | FileCheck -strict-whitespace %s --check-prefix=DIRECT +// RUN: | FileCheck -strict-whitespace %s // // Test with serialization: // RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-unknown -emit-pch -o %t %s // RUN: %clang_cc1 -x c++ -std=c++17 -triple x86_64-unknown-unknown -include-pch %t -ast-dump-all /dev/null \ // RUN: | sed -e "s/ <undeserialized declarations>//" -e "s/ imported//" \ -// RUN: | FileCheck --strict-whitespace %s --check-prefix=SERIALIZED +// RUN: | FileCheck --strict-whitespace %s template <typename Ty> // CHECK: FunctionTemplateDecl 0x{{[^ ]*}} <{{.*}}:1, line:[[@LINE+2]]:10> col:6 a @@ -189,15 +189,13 @@ T unTempl = 1; template<> int unTempl<int>; -// FIXME (#61680) - serializing and loading AST should not affect reported source range -// DIRECT: VarTemplateSpecializationDecl 0x{{[^ ]*}} <line:{{[0-9]+}}:1, line:{{[0-9]+}}:16> col:5 unTempl 'int' -// SERIALIZED: VarTemplateSpecializationDecl 0x{{[^ ]*}} <line:{{[0-9]+}}:1, line:{{[0-9]+}}:5> col:5 unTempl 'int' +// CHECK: VarTemplateSpecializationDecl 0x{{[^ ]*}} <line:{{[0-9]+}}:1, line:{{[0-9]+}}:16> col:5 unTempl 'int' // CHECK-NEXT: `-TemplateArgument type 'int' // CHECK-NEXT: `-BuiltinType 0x{{[^ ]*}} 'int' template<> float unTempl<float> = 1; -// CHECK: VarTemplateSpecializationDecl 0x{{[^ ]*}} <line:{{[0-9]+}}:1, line:{{[0-9]+}}:24> col:7 unTempl 'float' cinit +// CHECK: VarTemplateSpecializationDecl 0x{{[^ ]*}} <line:{{[0-9]+}}:1, line:{{[0-9]+}}:24> col:7 unTempl 'float' // CHECK-NEXT: |-TemplateArgument type 'float' // CHECK-NEXT: | `-BuiltinType 0x{{[^ ]*}} 'float' // CHECK-NEXT: `-ImplicitCastExpr 0x{{[^ ]*}} <col:24> 'float' <IntegralToFloating> @@ -222,7 +220,7 @@ int binTempl<int, U>; template<class U> float binTempl<float, U> = 1; -// CHECK: VarTemplatePartialSpecializationDecl 0x{{[^ ]*}} <line:{{[0-9]+}}:1, line:{{[0-9]+}}:24> col:7 binTempl 'float' cinit +// CHECK: VarTemplatePartialSpecializationDecl 0x{{[^ ]*}} <line:{{[0-9]+}}:1, line:{{[0-9]+}}:28> col:7 binTempl 'float' // CHECK-NEXT: |-TemplateTypeParmDecl 0x{{[^ ]*}} <line:{{[0-9]+}}:10, col:16> col:16 referenced class depth 0 index 0 U // CHECK-NEXT: |-TemplateArgument type 'float' // CHECK-NEXT: | `-BuiltinType 0x{{[^ ]*}} 'float' @@ -233,9 +231,7 @@ float binTempl<float, U> = 1; template<> int binTempl<int, int>; -// FIXME (#61680) - serializing and loading AST should not affect reported source range -// DIRECT: VarTemplateSpecializationDecl 0x{{[^ ]*}} <line:{{[0-9]+}}:1, line:{{[0-9]+}}:22> col:5 binTempl 'int' -// SERIALIZED: VarTemplateSpecializationDecl 0x{{[^ ]*}} <line:{{[0-9]+}}:1, line:{{[0-9]+}}:5> col:5 binTempl 'int' +// CHECK: VarTemplateSpecializationDecl 0x{{[^ ]*}} <line:{{[0-9]+}}:1, line:{{[0-9]+}}:22> col:5 binTempl 'int' // CHECK-NEXT: |-TemplateArgument type 'int' // CHECK-NEXT: | `-BuiltinType 0x{{[^ ]*}} 'int' // CHECK-NEXT: `-TemplateArgument type 'int' @@ -243,7 +239,7 @@ int binTempl<int, int>; template<> float binTempl<float, float> = 1; -// CHECK: VarTemplateSpecializationDecl 0x{{[^ ]*}} <line:{{[0-9]+}}:1, line:{{[0-9]+}}:32> col:7 binTempl 'float' cinit +// CHECK: VarTemplateSpecializationDecl 0x{{[^ ]*}} <line:{{[0-9]+}}:1, line:{{[0-9]+}}:32> col:7 binTempl 'float' // CHECK-NEXT: |-TemplateArgument type 'float' // CHECK-NEXT: | `-BuiltinType 0x{{[^ ]*}} 'float' // CHECK-NEXT: |-TemplateArgument type 'float' diff --git a/clang/test/Index/Core/index-source.cpp b/clang/test/Index/Core/index-source.cpp index 8f9fbc4c8d29c4a..de2f6e11f778ae1 100644 --- a/clang/test/Index/Core/index-source.cpp +++ b/clang/test/Index/Core/index-source.cpp @@ -285,20 +285,16 @@ template<> class SpecializationDecl<int>; // CHECK: [[@LINE-1]]:7 | class(Gen,TS)/C++ | SpecializationDecl | c:@S@SpecializationDecl>#I | <no-cgname> | Decl,RelSpecialization | rel: 1 // CHECK-NEXT: RelSpecialization | SpecializationDecl | c:@ST>1#T@SpecializationDecl -// CHECK: [[@LINE-3]]:7 | class(Gen,TS)/C++ | SpecializationDecl | c:@S@SpecializationDecl>#I | <no-cgname> | Ref | rel: 0 template<> class SpecializationDecl<int> { }; // CHECK: [[@LINE-1]]:7 | class(Gen,TS)/C++ | SpecializationDecl | c:@S@SpecializationDecl>#I | <no-cgname> | Def,RelSpecialization | rel: 1 // CHECK-NEXT: RelSpecialization | SpecializationDecl | c:@ST>1#T@SpecializationDecl -// CHECK-NEXT: [[@LINE-3]]:7 | class(Gen,TS)/C++ | SpecializationDecl | c:@S@SpecializationDecl>#I | <no-cgname> | Ref | rel: 0 template<typename T> class PartialSpecilizationClass<Cls, T>; // CHECK: [[@LINE-1]]:7 | class(Gen,TPS)/C++ | PartialSpecilizationClass | c:@SP>1#T@PartialSpecilizationClass>#$@S@Cls#t0.0 | <no-cgname> | Decl,RelSpecialization | rel: 1 // CHECK-NEXT: RelSpecialization | PartialSpecilizationClass | c:@ST>2#T#T@PartialSpecilizationClass -// CHECK: [[@LINE-3]]:7 | class(Gen)/C++ | PartialSpecilizationClass | c:@ST>2#T#T@PartialSpecilizationClass | <no-cgname> | Ref | rel: 0 -// CHECK-NEXT: [[@LINE-4]]:33 | class/C++ | Cls | c:@S@Cls | <no-cgname> | Ref | rel: 0 template<> class PartialSpecilizationClass<Cls, Cls> : Cls { }; @@ -306,9 +302,6 @@ class PartialSpecilizationClass<Cls, Cls> : Cls { }; // CHECK-NEXT: RelSpecialization | PartialSpecilizationClass | c:@ST>2#T#T@PartialSpecilizationClass // CHECK-NEXT: [[@LINE-3]]:45 | class/C++ | Cls | c:@S@Cls | <no-cgname> | Ref,RelBase,RelCont | rel: 1 // CHECK-NEXT: RelBase,RelCont | PartialSpecilizationClass | c:@S@PartialSpecilizationClass>#$@S@Cls#S0_ -// CHECK-NEXT: [[@LINE-5]]:7 | class(Gen,TS)/C++ | PartialSpecilizationClass | c:@S@PartialSpecilizationClass>#$@S@Cls#S0_ | <no-cgname> | Ref | rel: 0 -// CHECK-NEXT: [[@LINE-6]]:33 | class/C++ | Cls | c:@S@Cls | <no-cgname> | Ref | rel: 0 -// CHECK-NEXT: [[@LINE-7]]:38 | class/C++ | Cls | c:@S@Cls | <no-cgname> | Ref | rel: 0 template<typename T, int x> void functionSp() { } @@ -332,10 +325,6 @@ class ClassWithCorrectSpecialization { }; template<> class ClassWithCorrectSpecialization<SpecializationDecl<Cls>, Record::C> { }; -// CHECK: [[@LINE-1]]:38 | class(Gen)/C++ | SpecializationDecl | c:@ST>1#T@SpecializationDecl | <no-cgname> | Ref | rel: 0 -// CHECK: [[@LINE-2]]:57 | class/C++ | Cls | c:@S@Cls | <no-cgname> | Ref | rel: 0 -// CHECK: [[@LINE-3]]:71 | static-property/C++ | C | c:@S@Record@C | __ZN6Record1CE | Ref,Read | rel: 0 -// CHECK: [[@LINE-4]]:63 | struct/C++ | Record | c:@S@Record | <no-cgname> | Ref | rel: 0 namespace ns { // CHECK: [[@LINE-1]]:11 | namespace/C++ | ns | c:@N@ns | <no-cgname> | Decl | rel: 0 diff --git a/clang/test/Index/index-refs.cpp b/clang/test/Index/index-refs.cpp index 0e613e48522b125..14946849777d44e 100644 --- a/clang/test/Index/index-refs.cpp +++ b/clang/test/Index/index-refs.cpp @@ -108,7 +108,6 @@ int ginitlist[] = {EnumVal}; // CHECK: [indexDeclaration]: kind: c++-class-template | name: TS | {{.*}} | loc: 47:8 // CHECK-NEXT: [indexDeclaration]: kind: struct-template-partial-spec | name: TS | USR: c:@SP>1#T@TS>#t0.0#I | {{.*}} | loc: 50:8 // CHECK-NEXT: [indexDeclaration]: kind: typedef | name: MyInt | USR: c:index-refs.cpp@SP>1#T@TS>#t0.0#I@T@MyInt | {{.*}} | loc: 51:15 | semantic-container: [TS:50:8] | lexical-container: [TS:50:8] -// CHECK-NEXT: [indexEntityReference]: kind: c++-class-template | name: TS | USR: c:@ST>2#T#T@TS | lang: C++ | cursor: TemplateRef=TS:47:8 | loc: 50:8 | <parent>:: <<NULL>> | container: [TU] | refkind: direct | role: ref /* when indexing implicit instantiations [indexDeclaration]: kind: struct-template-spec | name: TS | USR: c:@S@TS>#I | {{.*}} | loc: 50:8 [indexDeclaration]: kind: typedef | name: MyInt | USR: c:index-refs.cpp@593@S@TS>#I@T@MyInt | {{.*}} | loc: 51:15 | semantic-container: [TS:50:8] | lexical-container: [TS:50:8] diff --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp index 454ee1e42aed1d7..3f338f255c860ba 100644 --- a/clang/tools/libclang/CIndex.cpp +++ b/clang/tools/libclang/CIndex.cpp @@ -742,14 +742,10 @@ bool CursorVisitor::VisitClassTemplateSpecializationDecl( } // Visit the template arguments used in the specialization. - if (TypeSourceInfo *SpecType = D->getTypeAsWritten()) { - TypeLoc TL = SpecType->getTypeLoc(); - if (TemplateSpecializationTypeLoc TSTLoc = - TL.getAs<TemplateSpecializationTypeLoc>()) { - for (unsigned I = 0, N = TSTLoc.getNumArgs(); I != N; ++I) - if (VisitTemplateArgumentLoc(TSTLoc.getArgLoc(I))) - return true; - } + if (const auto *ArgsWritten = D->getTemplateArgsAsWritten()) { + for (const TemplateArgumentLoc &Arg : ArgsWritten->arguments()) + if (VisitTemplateArgumentLoc(Arg)) + return true; } return ShouldVisitBody && VisitCXXRecordDecl(D); @@ -5556,16 +5552,19 @@ CXString clang_getCursorDisplayName(CXCursor C) { if (const ClassTemplateSpecializationDecl *ClassSpec = dyn_cast<ClassTemplateSpecializationDecl>(D)) { - // If the type was explicitly written, use that. - if (TypeSourceInfo *TSInfo = ClassSpec->getTypeAsWritten()) - return cxstring::createDup(TSInfo->getType().getAsString(Policy)); - SmallString<128> Str; llvm::raw_svector_ostream OS(Str); OS << *ClassSpec; - printTemplateArgumentList( - OS, ClassSpec->getTemplateArgs().asArray(), Policy, - ClassSpec->getSpecializedTemplate()->getTemplateParameters()); + // If the template arguments were written explicitly, use them.. + if (const auto *ArgsWritten = ClassSpec->getTemplateArgsAsWritten()) { + printTemplateArgumentList( + OS, ArgsWritten->arguments(), Policy, + ClassSpec->getSpecializedTemplate()->getTemplateParameters()); + } else { + printTemplateArgumentList( + OS, ClassSpec->getTemplateArgs().asArray(), Policy, + ClassSpec->getSpecializedTemplate()->getTemplateParameters()); + } return cxstring::createDup(OS.str()); } diff --git a/clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp b/clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp index 0edc65162fbe3f8..270135f35c88932 100644 --- a/clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp +++ b/clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp @@ -2213,18 +2213,6 @@ TEST_P(ASTMatchersTest, ReferenceTypeLocTest_BindsToAnyRvalueReferenceTypeLoc) { EXPECT_TRUE(matches("float&& r = 3.0;", matcher)); } -TEST_P( - ASTMatchersTest, - TemplateSpecializationTypeLocTest_BindsToTemplateSpecializationExplicitInstantiation) { - if (!GetParam().isCXX()) { - return; - } - EXPECT_TRUE( - matches("template <typename T> class C {}; template class C<int>;", - classTemplateSpecializationDecl( - hasName("C"), hasTypeLoc(templateSpecializationTypeLoc())))); -} - TEST_P(ASTMatchersTest, TemplateSpecializationTypeLocTest_BindsToVarDeclTemplateSpecialization) { if (!GetParam().isCXX()) { diff --git a/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp b/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp index f198dc71eb8337c..f52234e93628496 100644 --- a/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp +++ b/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp @@ -430,12 +430,6 @@ TEST(HasTypeLoc, MatchesCXXUnresolvedConstructExpr) { cxxUnresolvedConstructExpr(hasTypeLoc(loc(asString("T")))))); } -TEST(HasTypeLoc, MatchesClassTemplateSpecializationDecl) { - EXPECT_TRUE(matches( - "template <typename T> class Foo; template <> class Foo<int> {};", - classTemplateSpecializationDecl(hasTypeLoc(loc(asString("Foo<int>")))))); -} - TEST(HasTypeLoc, MatchesCompoundLiteralExpr) { EXPECT_TRUE( matches("int* x = (int[2]) { 0, 1 };", @@ -6379,6 +6373,15 @@ TEST(HasAnyTemplateArgumentLoc, BindsToSpecializationWithDoubleArgument) { hasTypeLoc(loc(asString("double"))))))))))); } +TEST(HasAnyTemplateArgumentLoc, BindsToExplicitSpecializationWithIntArgument) { + EXPECT_TRUE( + matches("template<typename T> class A {}; template<> class A<int> {};", + classTemplateSpecializationDecl( + hasName("A"), hasAnyTemplateArgument(templateArgument( + refersToType(asString("int"))))))); +} + +#if 0 TEST(HasAnyTemplateArgumentLoc, BindsToExplicitSpecializationWithIntArgument) { EXPECT_TRUE(matches( "template<typename T> class A {}; template<> class A<int> {};", @@ -6434,6 +6437,7 @@ TEST(HasAnyTemplateArgumentLoc, hasTypeLoc(templateSpecializationTypeLoc(hasAnyTemplateArgumentLoc( hasTypeLoc(loc(asString("double"))))))))); } +#endif TEST(HasTemplateArgumentLoc, BindsToSpecializationWithIntArgument) { EXPECT_TRUE( @@ -6453,6 +6457,7 @@ TEST(HasTemplateArgumentLoc, BindsToSpecializationWithDoubleArgument) { 0, hasTypeLoc(loc(asString("double"))))))))))); } +#if 0 TEST(HasTemplateArgumentLoc, BindsToExplicitSpecializationWithIntArgument) { EXPECT_TRUE(matches( "template<typename T> class A {}; template<> class A<int> {};", @@ -6541,6 +6546,7 @@ TEST(HasTemplateArgumentLoc, DoesNotBindWithBadIndex) { hasTypeLoc(templateSpecializationTypeLoc(hasTemplateArgumentLoc( 100, hasTypeLoc(loc(asString("int"))))))))); } +#endif TEST(HasTemplateArgumentLoc, BindsToDeclRefExprWithIntArgument) { EXPECT_TRUE(matches(R"( >From 2ea3df57a2b24b25364c138f6ad0c42799fcbda7 Mon Sep 17 00:00:00 2001 From: Krystian Stasiowski <sdkryst...@gmail.com> Date: Wed, 14 Feb 2024 10:03:57 -0500 Subject: [PATCH 2/5] [FOLD] --- clang/include/clang/AST/DeclTemplate.h | 106 +++++++++++----------- clang/lib/Serialization/ASTReaderDecl.cpp | 6 +- 2 files changed, 53 insertions(+), 59 deletions(-) diff --git a/clang/include/clang/AST/DeclTemplate.h b/clang/include/clang/AST/DeclTemplate.h index b5c2d4597151205..447399d733f1b17 100644 --- a/clang/include/clang/AST/DeclTemplate.h +++ b/clang/include/clang/AST/DeclTemplate.h @@ -1760,6 +1760,21 @@ class BuiltinTemplateDecl : public TemplateDecl { BuiltinTemplateKind getBuiltinTemplateKind() const { return BTK; } }; +/// Provides information about an explicit instantiation of a variable or class +/// template. +struct ExplicitInstantiationInfo { + /// The template arguments as written.. + const ASTTemplateArgumentListInfo *TemplateArgsAsWritten = nullptr; + + /// The location of the extern keyword. + SourceLocation ExternLoc; + + /// The location of the template keyword. + SourceLocation TemplateKeywordLoc; + + ExplicitInstantiationInfo() = default; +}; + /// Represents a class template specialization, which refers to /// a class template with a given set of template arguments. /// @@ -1792,19 +1807,6 @@ class ClassTemplateSpecializationDecl llvm::PointerUnion<ClassTemplateDecl *, SpecializedPartialSpecialization *> SpecializedTemplate; - struct ExplicitInstantiationInfo { - /// The template arguments as written.. - const ASTTemplateArgumentListInfo *TemplateArgsAsWritten = nullptr; - - /// The location of the extern keyword. - SourceLocation ExternLoc; - - /// The location of the template keyword. - SourceLocation TemplateKeywordLoc; - - ExplicitInstantiationInfo() = default; - }; - /// Further info for explicit template specialization/instantiation. /// Does not apply to implicit specializations. llvm::PointerUnion<const ASTTemplateArgumentListInfo *, @@ -1986,26 +1988,15 @@ class ClassTemplateSpecializationDecl SpecializedTemplate = TemplDecl; } + /// Retrieve the template argument list as written in the sources, + /// if any. const ASTTemplateArgumentListInfo *getTemplateArgsAsWritten() const { if (auto *Info = ExplicitInfo.dyn_cast<ExplicitInstantiationInfo *>()) return Info->TemplateArgsAsWritten; return ExplicitInfo.get<const ASTTemplateArgumentListInfo *>(); } - /// Gets the location of the extern keyword, if present. - SourceLocation getExternLoc() const { - if (auto *Info = ExplicitInfo.dyn_cast<ExplicitInstantiationInfo *>()) - return Info->ExternLoc; - return SourceLocation(); - } - - /// Gets the location of the template keyword, if present. - SourceLocation getTemplateKeywordLoc() const { - if (auto *Info = ExplicitInfo.dyn_cast<ExplicitInstantiationInfo *>()) - return Info->TemplateKeywordLoc; - return SourceLocation(); - } - + /// Set the template argument list as written in the sources. void setTemplateArgsAsWritten(const ASTTemplateArgumentListInfo *ArgsWritten) { if (auto *Info = ExplicitInfo.dyn_cast<ExplicitInstantiationInfo *>()) @@ -2014,14 +2005,29 @@ class ClassTemplateSpecializationDecl ExplicitInfo = ArgsWritten; } + /// Set the template argument list as written in the sources. void setTemplateArgsAsWritten(const TemplateArgumentListInfo &ArgsInfo) { setTemplateArgsAsWritten( ASTTemplateArgumentListInfo::Create(getASTContext(), ArgsInfo)); } + /// Gets the location of the extern keyword, if present. + SourceLocation getExternLoc() const { + if (auto *Info = ExplicitInfo.dyn_cast<ExplicitInstantiationInfo *>()) + return Info->ExternLoc; + return SourceLocation(); + } + /// Sets the location of the extern keyword. void setExternLoc(SourceLocation Loc); + /// Gets the location of the template keyword, if present. + SourceLocation getTemplateKeywordLoc() const { + if (auto *Info = ExplicitInfo.dyn_cast<ExplicitInstantiationInfo *>()) + return Info->TemplateKeywordLoc; + return SourceLocation(); + } + /// Sets the location of the template keyword. void setTemplateKeywordLoc(SourceLocation Loc); @@ -2582,19 +2588,6 @@ class VarTemplateSpecializationDecl : public VarDecl, llvm::PointerUnion<VarTemplateDecl *, SpecializedPartialSpecialization *> SpecializedTemplate; - struct ExplicitInstantiationInfo { - /// The template arguments as written.. - const ASTTemplateArgumentListInfo *TemplateArgsAsWritten = nullptr; - - /// The location of the extern keyword. - SourceLocation ExternLoc; - - /// The location of the template keyword. - SourceLocation TemplateKeywordLoc; - - ExplicitInstantiationInfo() = default; - }; - /// Further info for explicit template specialization/instantiation. /// Does not apply to implicit specializations. llvm::PointerUnion<const ASTTemplateArgumentListInfo *, @@ -2603,7 +2596,6 @@ class VarTemplateSpecializationDecl : public VarDecl, /// The template arguments used to describe this specialization. const TemplateArgumentList *TemplateArgs; - const ASTTemplateArgumentListInfo *TemplateArgsInfo = nullptr; /// The point where this template was instantiated (if any). SourceLocation PointOfInstantiation; @@ -2760,26 +2752,15 @@ class VarTemplateSpecializationDecl : public VarDecl, SpecializedTemplate = TemplDecl; } + /// Retrieve the template argument list as written in the sources, + /// if any. const ASTTemplateArgumentListInfo *getTemplateArgsAsWritten() const { if (auto *Info = ExplicitInfo.dyn_cast<ExplicitInstantiationInfo *>()) return Info->TemplateArgsAsWritten; return ExplicitInfo.get<const ASTTemplateArgumentListInfo *>(); } - /// Gets the location of the extern keyword, if present. - SourceLocation getExternLoc() const { - if (auto *Info = ExplicitInfo.dyn_cast<ExplicitInstantiationInfo *>()) - return Info->ExternLoc; - return SourceLocation(); - } - - /// Gets the location of the template keyword, if present. - SourceLocation getTemplateKeywordLoc() const { - if (auto *Info = ExplicitInfo.dyn_cast<ExplicitInstantiationInfo *>()) - return Info->TemplateKeywordLoc; - return SourceLocation(); - } - + /// Set the template argument list as written in the sources. void setTemplateArgsAsWritten(const ASTTemplateArgumentListInfo *ArgsWritten) { if (auto *Info = ExplicitInfo.dyn_cast<ExplicitInstantiationInfo *>()) @@ -2788,14 +2769,29 @@ class VarTemplateSpecializationDecl : public VarDecl, ExplicitInfo = ArgsWritten; } + /// Set the template argument list as written in the sources. void setTemplateArgsAsWritten(const TemplateArgumentListInfo &ArgsInfo) { setTemplateArgsAsWritten( ASTTemplateArgumentListInfo::Create(getASTContext(), ArgsInfo)); } + /// Gets the location of the extern keyword, if present. + SourceLocation getExternLoc() const { + if (auto *Info = ExplicitInfo.dyn_cast<ExplicitInstantiationInfo *>()) + return Info->ExternLoc; + return SourceLocation(); + } + /// Sets the location of the extern keyword. void setExternLoc(SourceLocation Loc); + /// Gets the location of the template keyword, if present. + SourceLocation getTemplateKeywordLoc() const { + if (auto *Info = ExplicitInfo.dyn_cast<ExplicitInstantiationInfo *>()) + return Info->TemplateKeywordLoc; + return SourceLocation(); + } + /// Sets the location of the template keyword. void setTemplateKeywordLoc(SourceLocation Loc); diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp index 15defab3e8ee2d9..44d3d6329c788c3 100644 --- a/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/clang/lib/Serialization/ASTReaderDecl.cpp @@ -2552,8 +2552,7 @@ ASTDeclReader::VisitClassTemplateSpecializationDeclImpl( if (Record.readBool()) { // FIXME: We don't need to allocate this if ExternLoc and TemplateKeywordLoc // are invalid! - auto *ExplicitInfo = - new (C) ClassTemplateSpecializationDecl::ExplicitInstantiationInfo; + auto *ExplicitInfo = new (C) ExplicitInstantiationInfo; ExplicitInfo->TemplateArgsAsWritten = Record.readASTTemplateArgumentListInfo(); ExplicitInfo->ExternLoc = readSourceLocation(); @@ -2623,8 +2622,7 @@ ASTDeclReader::VisitVarTemplateSpecializationDeclImpl( if (Record.readBool()) { // FIXME: We don't need to allocate this if ExternLoc and TemplateKeywordLoc // are invalid! - auto *ExplicitInfo = - new (C) VarTemplateSpecializationDecl::ExplicitInstantiationInfo; + auto *ExplicitInfo = new (C) ExplicitInstantiationInfo; ExplicitInfo->TemplateArgsAsWritten = Record.readASTTemplateArgumentListInfo(); ExplicitInfo->ExternLoc = readSourceLocation(); >From 9259c11cd3397059de565bd9373eaf324bede565 Mon Sep 17 00:00:00 2001 From: Krystian Stasiowski <sdkryst...@gmail.com> Date: Wed, 14 Feb 2024 12:15:47 -0500 Subject: [PATCH 3/5] [FOLD] update index tests --- clang/test/Index/Core/index-source.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/clang/test/Index/Core/index-source.cpp b/clang/test/Index/Core/index-source.cpp index de2f6e11f778ae1..043e616a1d36645 100644 --- a/clang/test/Index/Core/index-source.cpp +++ b/clang/test/Index/Core/index-source.cpp @@ -295,6 +295,7 @@ template<typename T> class PartialSpecilizationClass<Cls, T>; // CHECK: [[@LINE-1]]:7 | class(Gen,TPS)/C++ | PartialSpecilizationClass | c:@SP>1#T@PartialSpecilizationClass>#$@S@Cls#t0.0 | <no-cgname> | Decl,RelSpecialization | rel: 1 // CHECK-NEXT: RelSpecialization | PartialSpecilizationClass | c:@ST>2#T#T@PartialSpecilizationClass +// CHECK-NEXT: [[@LINE-3]]:33 | class/C++ | Cls | c:@S@Cls | <no-cgname> | Ref,RelCont | rel: 1 template<> class PartialSpecilizationClass<Cls, Cls> : Cls { }; @@ -302,6 +303,10 @@ class PartialSpecilizationClass<Cls, Cls> : Cls { }; // CHECK-NEXT: RelSpecialization | PartialSpecilizationClass | c:@ST>2#T#T@PartialSpecilizationClass // CHECK-NEXT: [[@LINE-3]]:45 | class/C++ | Cls | c:@S@Cls | <no-cgname> | Ref,RelBase,RelCont | rel: 1 // CHECK-NEXT: RelBase,RelCont | PartialSpecilizationClass | c:@S@PartialSpecilizationClass>#$@S@Cls#S0_ +// CHECK-NEXT: [[@LINE-5]]:33 | class/C++ | Cls | c:@S@Cls | <no-cgname> | Ref,RelCont | rel: 1 +// CHECK-NEXT: RelCont | PartialSpecilizationClass | c:@S@PartialSpecilizationClass>#$@S@Cls#S0_ +// CHECK-NEXT: [[@LINE-7]]:38 | class/C++ | Cls | c:@S@Cls | <no-cgname> | Ref,RelCont | rel: 1 +// CHECK-NEXT: RelCont | PartialSpecilizationClass | c:@S@PartialSpecilizationClass>#$@S@Cls#S0_ template<typename T, int x> void functionSp() { } @@ -325,6 +330,14 @@ class ClassWithCorrectSpecialization { }; template<> class ClassWithCorrectSpecialization<SpecializationDecl<Cls>, Record::C> { }; +// CHECK: [[@LINE-1]]:38 | class(Gen)/C++ | SpecializationDecl | c:@ST>1#T@SpecializationDecl | <no-cgname> | Ref,RelCont | rel: 1 +// CHECK-NEXT: RelCont | ClassWithCorrectSpecialization | c:@S@ClassWithCorrectSpecialization>#$@S@SpecializationDecl>#$@S@Cls#VI2 +// CHECK-NEXT: [[@LINE-3]]:57 | class/C++ | Cls | c:@S@Cls | <no-cgname> | Ref,RelCont | rel: 1 +// CHECK-NEXT: RelCont | ClassWithCorrectSpecialization | c:@S@ClassWithCorrectSpecialization>#$@S@SpecializationDecl>#$@S@Cls#VI2 +// CHECK-NEXT: [[@LINE-5]]:71 | static-property/C++ | C | c:@S@Record@C | __ZN6Record1CE | Ref,Read,RelCont | rel: 1 +// CHECK-NEXT: RelCont | ClassWithCorrectSpecialization | c:@S@ClassWithCorrectSpecialization>#$@S@SpecializationDecl>#$@S@Cls#VI2 +// CHECK-NEXT: [[@LINE-7]]:63 | struct/C++ | Record | c:@S@Record | <no-cgname> | Ref,RelCont | rel: 1 +// CHECK-NEXT: RelCont | ClassWithCorrectSpecialization | c:@S@ClassWithCorrectSpecialization>#$@S@SpecializationDecl>#$@S@Cls#VI2 namespace ns { // CHECK: [[@LINE-1]]:11 | namespace/C++ | ns | c:@N@ns | <no-cgname> | Decl | rel: 0 >From 01858345a1146f761dec8e5d0a5a36dc0507ec48 Mon Sep 17 00:00:00 2001 From: Krystian Stasiowski <sdkryst...@gmail.com> Date: Mon, 1 Apr 2024 11:00:22 -0400 Subject: [PATCH 4/5] [FOLD] only call setTemplateKeywordLoc for explicit instantiations --- clang/lib/AST/ASTImporter.cpp | 14 +++++--- clang/lib/AST/DeclTemplate.cpp | 62 ++++++++++++++------------------- clang/lib/Sema/SemaTemplate.cpp | 11 +++--- 3 files changed, 42 insertions(+), 45 deletions(-) diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp index 1705fcc25213b0f..7bfd54c3335b176 100644 --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -443,8 +443,10 @@ namespace clang { Expected<FunctionTemplateAndArgsTy> ImportFunctionTemplateWithTemplateArgsFromSpecialization( FunctionDecl *FromFD); - Error ImportTemplateParameterLists(const DeclaratorDecl *FromD, - DeclaratorDecl *ToD); + + template <typename DeclTy> + Error ImportTemplateParameterLists(const DeclTy *FromD, + DeclTy *ToD); Error ImportTemplateInformation(FunctionDecl *FromFD, FunctionDecl *ToFD); @@ -3313,8 +3315,9 @@ ExpectedDecl ASTNodeImporter::VisitEnumConstantDecl(EnumConstantDecl *D) { return ToEnumerator; } -Error ASTNodeImporter::ImportTemplateParameterLists(const DeclaratorDecl *FromD, - DeclaratorDecl *ToD) { +template <typename DeclTy> +Error ASTNodeImporter::ImportTemplateParameterLists(const DeclTy *FromD, + DeclTy *ToD) { unsigned int Num = FromD->getNumTemplateParameterLists(); if (Num == 0) return Error::success(); @@ -6237,6 +6240,9 @@ ExpectedDecl ASTNodeImporter::VisitClassTemplateSpecializationDecl( else return BraceRangeOrErr.takeError(); + if (Error Err = ImportTemplateParameterLists(D, D2)) + return std::move(Err); + // Import the qualifier, if any. if (auto LocOrErr = import(D->getQualifierLoc())) D2->setQualifierInfo(*LocOrErr); diff --git a/clang/lib/AST/DeclTemplate.cpp b/clang/lib/AST/DeclTemplate.cpp index 9a91e050512c741..f1fb5ba3787eeed 100644 --- a/clang/lib/AST/DeclTemplate.cpp +++ b/clang/lib/AST/DeclTemplate.cpp @@ -986,47 +986,33 @@ ClassTemplateSpecializationDecl::getSpecializedTemplate() const { SourceRange ClassTemplateSpecializationDecl::getSourceRange() const { - using CTPSDecl = ClassTemplatePartialSpecializationDecl; - if (ExplicitInfo) { - SourceLocation Begin = getTemplateKeywordLoc(); - if (Begin.isInvalid()) { - if (getNumTemplateParameterLists()) - Begin = getTemplateParameterList(0)->getTemplateLoc(); - else if (const auto *CTPSD = dyn_cast<CTPSDecl>(this)) - Begin = CTPSD->getTemplateParameters()->getTemplateLoc(); - } - if (Begin.isValid()) { - // Here we have an explicit (partial) specialization or instantiation. - assert(getSpecializationKind() == TSK_ExplicitSpecialization || - getSpecializationKind() == TSK_ExplicitInstantiationDeclaration || - getSpecializationKind() == TSK_ExplicitInstantiationDefinition); - if (getExternLoc().isValid()) - Begin = getExternLoc(); - SourceLocation End = getBraceRange().getEnd(); - if (End.isInvalid()) - End = getTemplateArgsAsWritten()->getRAngleLoc(); - return SourceRange(Begin, End); - } - // An implicit instantiation of a class template partial specialization - // uses ExplicitInfo to record the TypeAsWritten, but the source - // locations should be retrieved from the instantiation pattern. - auto *ctpsd = const_cast<CTPSDecl *>(cast<CTPSDecl>(this)); - CTPSDecl *inst_from = ctpsd->getInstantiatedFromMember(); - assert(inst_from != nullptr); - return inst_from->getSourceRange(); - } - else { + if (getSpecializationKind() == TSK_ExplicitInstantiationDeclaration) { + return SourceRange(getExternLoc(), getTemplateArgsAsWritten()->getRAngleLoc()); + } else if (getSpecializationKind() == TSK_ExplicitInstantiationDefinition) { + return SourceRange(getTemplateKeywordLoc(), getTemplateArgsAsWritten()->getRAngleLoc()); + } else if (!isExplicitSpecialization()) { // No explicit info available. llvm::PointerUnion<ClassTemplateDecl *, ClassTemplatePartialSpecializationDecl *> - inst_from = getInstantiatedFrom(); - if (inst_from.isNull()) + InstFrom = getInstantiatedFrom(); + if (InstFrom.isNull()) return getSpecializedTemplate()->getSourceRange(); - if (const auto *ctd = inst_from.dyn_cast<ClassTemplateDecl *>()) - return ctd->getSourceRange(); - return inst_from.get<ClassTemplatePartialSpecializationDecl *>() + if (const auto *CTD = InstFrom.dyn_cast<ClassTemplateDecl *>()) + return CTD->getSourceRange(); + return InstFrom.get<ClassTemplatePartialSpecializationDecl *>() ->getSourceRange(); } + SourceLocation Begin = TagDecl::getOuterLocStart(); + if (const auto *CTPSD = dyn_cast<ClassTemplatePartialSpecializationDecl>(this)) { + if (const auto *InstFrom = CTPSD->getInstantiatedFromMember()) + return InstFrom->getSourceRange(); + else if (!getNumTemplateParameterLists()) + Begin = CTPSD->getTemplateParameters()->getTemplateLoc(); + } + SourceLocation End = getBraceRange().getEnd(); + if (End.isInvalid()) + End = getTemplateArgsAsWritten()->getRAngleLoc(); + return SourceRange(Begin, End); } void ClassTemplateSpecializationDecl::setExternLoc(SourceLocation Loc) { @@ -1395,6 +1381,12 @@ SourceRange VarTemplateSpecializationDecl::getSourceRange() const { if (isExplicitSpecialization() && !hasInit()) { if (const ASTTemplateArgumentListInfo *Info = getTemplateArgsAsWritten()) return SourceRange(getOuterLocStart(), Info->getRAngleLoc()); + } else if (getTemplateSpecializationKind() == TSK_ExplicitInstantiationDeclaration ) { + if (const ASTTemplateArgumentListInfo *Info = getTemplateArgsAsWritten()) + return SourceRange(getExternLoc(), Info->getRAngleLoc()); + } else if (getTemplateSpecializationKind() == TSK_ExplicitInstantiationDefinition) { + if (const ASTTemplateArgumentListInfo *Info = getTemplateArgsAsWritten()) + return SourceRange(getTemplateKeywordLoc(), Info->getRAngleLoc()); } return VarDecl::getSourceRange(); } diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index ab8bf26b4fc769c..e2c103549a43696 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -5120,7 +5120,6 @@ DeclResult Sema::ActOnVarTemplateSpecialization( } } - Specialization->setTemplateKeywordLoc(TemplateKWLoc); Specialization->setLexicalDeclContext(CurContext); // Add the specialization into its lexical context, so that it can @@ -9479,11 +9478,6 @@ DeclResult Sema::ActOnClassTemplateSpecialization( << (isPartialSpecialization? 1 : 0) << FixItHint::CreateRemoval(ModulePrivateLoc); - if (TUK != TUK_Friend) - // FIXME: We really shouldn't be setting this unless this is an explicit - // instantiation. We already store the outer template parameter lists. - Specialization->setTemplateKeywordLoc(TemplateKWLoc); - // C++ [temp.expl.spec]p9: // A template explicit specialization is in the scope of the // namespace in which the template was defined. @@ -11128,6 +11122,11 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S, if (!HasNoEffect) { // Instantiate static data member or variable template. Prev->setTemplateSpecializationKind(TSK, D.getIdentifierLoc()); + if (auto *VTSD = dyn_cast<VarTemplatePartialSpecializationDecl>(Prev)) { + VTSD->setExternLoc(ExternLoc); + VTSD->setTemplateKeywordLoc(TemplateLoc); + } + // Merge attributes. ProcessDeclAttributeList(S, Prev, D.getDeclSpec().getAttributes()); if (PrevTemplate) >From e1860e3fb3dd9156115a7533e73302549b0ecde9 Mon Sep 17 00:00:00 2001 From: Krystian Stasiowski <sdkryst...@gmail.com> Date: Mon, 1 Apr 2024 11:05:58 -0400 Subject: [PATCH 5/5] [FOLD] format --- clang/lib/AST/ASTImporter.cpp | 3 +-- clang/lib/AST/DeclTemplate.cpp | 19 ++++++++++++------- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp index 7bfd54c3335b176..3844cafb5ce0885 100644 --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -445,8 +445,7 @@ namespace clang { FunctionDecl *FromFD); template <typename DeclTy> - Error ImportTemplateParameterLists(const DeclTy *FromD, - DeclTy *ToD); + Error ImportTemplateParameterLists(const DeclTy *FromD, DeclTy *ToD); Error ImportTemplateInformation(FunctionDecl *FromFD, FunctionDecl *ToFD); diff --git a/clang/lib/AST/DeclTemplate.cpp b/clang/lib/AST/DeclTemplate.cpp index f1fb5ba3787eeed..adcf9188a9a93a3 100644 --- a/clang/lib/AST/DeclTemplate.cpp +++ b/clang/lib/AST/DeclTemplate.cpp @@ -987,23 +987,26 @@ ClassTemplateSpecializationDecl::getSpecializedTemplate() const { SourceRange ClassTemplateSpecializationDecl::getSourceRange() const { if (getSpecializationKind() == TSK_ExplicitInstantiationDeclaration) { - return SourceRange(getExternLoc(), getTemplateArgsAsWritten()->getRAngleLoc()); + return SourceRange(getExternLoc(), + getTemplateArgsAsWritten()->getRAngleLoc()); } else if (getSpecializationKind() == TSK_ExplicitInstantiationDefinition) { - return SourceRange(getTemplateKeywordLoc(), getTemplateArgsAsWritten()->getRAngleLoc()); + return SourceRange(getTemplateKeywordLoc(), + getTemplateArgsAsWritten()->getRAngleLoc()); } else if (!isExplicitSpecialization()) { // No explicit info available. llvm::PointerUnion<ClassTemplateDecl *, ClassTemplatePartialSpecializationDecl *> - InstFrom = getInstantiatedFrom(); + InstFrom = getInstantiatedFrom(); if (InstFrom.isNull()) return getSpecializedTemplate()->getSourceRange(); if (const auto *CTD = InstFrom.dyn_cast<ClassTemplateDecl *>()) return CTD->getSourceRange(); return InstFrom.get<ClassTemplatePartialSpecializationDecl *>() - ->getSourceRange(); + ->getSourceRange(); } SourceLocation Begin = TagDecl::getOuterLocStart(); - if (const auto *CTPSD = dyn_cast<ClassTemplatePartialSpecializationDecl>(this)) { + if (const auto *CTPSD = + dyn_cast<ClassTemplatePartialSpecializationDecl>(this)) { if (const auto *InstFrom = CTPSD->getInstantiatedFromMember()) return InstFrom->getSourceRange(); else if (!getNumTemplateParameterLists()) @@ -1381,10 +1384,12 @@ SourceRange VarTemplateSpecializationDecl::getSourceRange() const { if (isExplicitSpecialization() && !hasInit()) { if (const ASTTemplateArgumentListInfo *Info = getTemplateArgsAsWritten()) return SourceRange(getOuterLocStart(), Info->getRAngleLoc()); - } else if (getTemplateSpecializationKind() == TSK_ExplicitInstantiationDeclaration ) { + } else if (getTemplateSpecializationKind() == + TSK_ExplicitInstantiationDeclaration) { if (const ASTTemplateArgumentListInfo *Info = getTemplateArgsAsWritten()) return SourceRange(getExternLoc(), Info->getRAngleLoc()); - } else if (getTemplateSpecializationKind() == TSK_ExplicitInstantiationDefinition) { + } else if (getTemplateSpecializationKind() == + TSK_ExplicitInstantiationDefinition) { if (const ASTTemplateArgumentListInfo *Info = getTemplateArgsAsWritten()) return SourceRange(getTemplateKeywordLoc(), Info->getRAngleLoc()); } _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits