[clang] [clang-tools-extra] [Clang] Unify interface for accessing template arguments as written for class/variable template specializations (PR #81642)
Krystian Stasiowski via cfe-commits
cfe-commits at lists.llvm.org
Fri Apr 19 05:58:58 PDT 2024
https://github.com/sdkrystian updated https://github.com/llvm/llvm-project/pull/81642
>From 348d065b4e8cb58e35e2314765d67673c5f43784 Mon Sep 17 00:00:00 2001
From: Krystian Stasiowski <sdkrystian at gmail.com>
Date: Fri, 9 Feb 2024 14:00:49 -0500
Subject: [PATCH 01/11] [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 e2afff8d445016..ce910a7b76eec3 100644
--- a/clang/include/clang/AST/DeclTemplate.h
+++ b/clang/include/clang/AST/DeclTemplate.h
@@ -1809,10 +1809,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;
@@ -1820,12 +1819,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;
@@ -2002,44 +2003,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 {
@@ -2067,10 +2069,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.
///
@@ -2079,15 +2077,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),
@@ -2102,11 +2096,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 *
@@ -2137,11 +2128,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.
@@ -2613,10 +2599,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;
@@ -2624,12 +2609,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;
@@ -2687,14 +2674,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 {
@@ -2798,44 +2777,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 {
@@ -2863,10 +2843,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.
///
@@ -2879,8 +2855,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,
@@ -2897,8 +2872,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,
DeclID ID);
@@ -2914,11 +2889,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 7eb92e304a3856..f694adfe65320d 100644
--- a/clang/include/clang/AST/RecursiveASTVisitor.h
+++ b/clang/include/clang/AST/RecursiveASTVisitor.h
@@ -2030,6 +2030,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 \
@@ -2039,9 +2048,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) { \
@@ -2061,15 +2073,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 8a2bbfff9e9e6b..073fabc6e514b1 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 47d912c73dd7eb..dca642acfa38bc 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 6aaa34c55ce307..4588d5d2096efd 100644
--- a/clang/lib/AST/ASTImporter.cpp
+++ b/clang/lib/AST/ASTImporter.cpp
@@ -6197,15 +6197,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()))
@@ -6215,7 +6216,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;
@@ -6269,22 +6270,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()))
@@ -6504,7 +6501,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);
}
@@ -6512,14 +6509,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();
@@ -6528,7 +6517,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 =
@@ -6571,7 +6560,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 599d379340abad..e73201ab8a8bce 100644
--- a/clang/lib/AST/DeclPrinter.cpp
+++ b/clang/lib/AST/DeclPrinter.cpp
@@ -1084,14 +1084,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 0ba271c3e04ee5..ab634c60816b4e 100644
--- a/clang/lib/AST/DeclTemplate.cpp
+++ b/clang/lib/AST/DeclTemplate.cpp
@@ -984,8 +984,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 ||
@@ -995,13 +1002,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);
@@ -1021,6 +1027,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
//===----------------------------------------------------------------------===//
@@ -1087,43 +1120,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);
@@ -1370,26 +1389,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
@@ -1401,13 +1433,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();
}
@@ -1417,15 +1447,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 9602f448e94279..364f0343ffe0c8 100644
--- a/clang/lib/AST/TypePrinter.cpp
+++ b/clang/lib/AST/TypePrinter.cpp
@@ -1472,21 +1472,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 1c04aa17d53fb2..8eb88f5a1e94ee 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 a1e32d391ed0cc..0febf4e1d4546c 100644
--- a/clang/lib/Sema/Sema.cpp
+++ b/clang/lib/Sema/Sema.cpp
@@ -1408,7 +1408,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 d4976f9d0d11d8..80cfc854220e91 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -5213,7 +5213,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);
@@ -5231,7 +5232,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);
@@ -9522,7 +9523,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(
@@ -9545,6 +9547,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,
@@ -9628,20 +9631,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
@@ -9658,6 +9651,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,
@@ -10862,18 +10864,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 caa07abb61fe34..65caed75a9338a 100644
--- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -3858,15 +3858,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.
@@ -3920,6 +3921,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.
@@ -3936,21 +3938,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());
@@ -3985,7 +3975,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());
@@ -4043,7 +4033,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);
@@ -4285,19 +4275,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
@@ -4315,28 +4307,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);
@@ -4405,46 +4383,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,
@@ -4464,16 +4402,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);
@@ -5726,7 +5687,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 74d40f7da34cad..f2cc3d500a00de 100644
--- a/clang/lib/Serialization/ASTReaderDecl.cpp
+++ b/clang/lib/Serialization/ASTReaderDecl.cpp
@@ -2552,10 +2552,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;
@@ -2570,7 +2573,6 @@ void ASTDeclReader::VisitClassTemplatePartialSpecializationDecl(
// need them for profiling
TemplateParameterList *Params = Record.readTemplateParameterList();
D->TemplateParams = Params;
- D->ArgsAsWritten = Record.readASTTemplateArgumentListInfo();
RedeclarableResult Redecl = VisitClassTemplateSpecializationDeclImpl(D);
@@ -2621,10 +2623,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;
@@ -2669,7 +2674,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 c6db107e0ca429..4039b1572696c3 100644
--- a/clang/lib/Serialization/ASTWriterDecl.cpp
+++ b/clang/lib/Serialization/ASTWriterDecl.cpp
@@ -1764,8 +1764,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());
}
@@ -1776,7 +1779,6 @@ void ASTDeclWriter::VisitClassTemplateSpecializationDecl(
void ASTDeclWriter::VisitClassTemplatePartialSpecializationDecl(
ClassTemplatePartialSpecializationDecl *D) {
Record.AddTemplateParameterList(D->getTemplateParameters());
- Record.AddASTTemplateArgumentListInfo(D->getTemplateArgsAsWritten());
VisitClassTemplateSpecializationDecl(D);
@@ -1811,8 +1813,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());
}
@@ -1837,7 +1842,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 142bc9e6ad9a0e..37f6d8a0472d30 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 8f9fbc4c8d29c4..de2f6e11f778ae 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 at SpecializationDecl>#I | <no-cgname> | Decl,RelSpecialization | rel: 1
// CHECK-NEXT: RelSpecialization | SpecializationDecl | c:@ST>1#T at SpecializationDecl
-// CHECK: [[@LINE-3]]:7 | class(Gen,TS)/C++ | SpecializationDecl | c:@S at SpecializationDecl>#I | <no-cgname> | Ref | rel: 0
template<>
class SpecializationDecl<int> { };
// CHECK: [[@LINE-1]]:7 | class(Gen,TS)/C++ | SpecializationDecl | c:@S at SpecializationDecl>#I | <no-cgname> | Def,RelSpecialization | rel: 1
// CHECK-NEXT: RelSpecialization | SpecializationDecl | c:@ST>1#T at SpecializationDecl
-// CHECK-NEXT: [[@LINE-3]]:7 | class(Gen,TS)/C++ | SpecializationDecl | c:@S at 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 at PartialSpecilizationClass>#$@S at Cls#t0.0 | <no-cgname> | Decl,RelSpecialization | rel: 1
// CHECK-NEXT: RelSpecialization | PartialSpecilizationClass | c:@ST>2#T#T at PartialSpecilizationClass
-// CHECK: [[@LINE-3]]:7 | class(Gen)/C++ | PartialSpecilizationClass | c:@ST>2#T#T at PartialSpecilizationClass | <no-cgname> | Ref | rel: 0
-// CHECK-NEXT: [[@LINE-4]]:33 | class/C++ | Cls | c:@S at 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 at PartialSpecilizationClass
// CHECK-NEXT: [[@LINE-3]]:45 | class/C++ | Cls | c:@S at Cls | <no-cgname> | Ref,RelBase,RelCont | rel: 1
// CHECK-NEXT: RelBase,RelCont | PartialSpecilizationClass | c:@S at PartialSpecilizationClass>#$@S at Cls#S0_
-// CHECK-NEXT: [[@LINE-5]]:7 | class(Gen,TS)/C++ | PartialSpecilizationClass | c:@S at PartialSpecilizationClass>#$@S at Cls#S0_ | <no-cgname> | Ref | rel: 0
-// CHECK-NEXT: [[@LINE-6]]:33 | class/C++ | Cls | c:@S at Cls | <no-cgname> | Ref | rel: 0
-// CHECK-NEXT: [[@LINE-7]]:38 | class/C++ | Cls | c:@S at 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 at SpecializationDecl | <no-cgname> | Ref | rel: 0
-// CHECK: [[@LINE-2]]:57 | class/C++ | Cls | c:@S at Cls | <no-cgname> | Ref | rel: 0
-// CHECK: [[@LINE-3]]:71 | static-property/C++ | C | c:@S at Record@C | __ZN6Record1CE | Ref,Read | rel: 0
-// CHECK: [[@LINE-4]]:63 | struct/C++ | Record | c:@S at Record | <no-cgname> | Ref | rel: 0
namespace ns {
// CHECK: [[@LINE-1]]:11 | namespace/C++ | ns | c:@N at ns | <no-cgname> | Decl | rel: 0
diff --git a/clang/test/Index/index-refs.cpp b/clang/test/Index/index-refs.cpp
index 0e613e48522b12..14946849777d44 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 at TS>#t0.0#I | {{.*}} | loc: 50:8
// CHECK-NEXT: [indexDeclaration]: kind: typedef | name: MyInt | USR: c:index-refs.cpp at SP>1#T at TS>#t0.0#I at 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 at 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 at TS>#I | {{.*}} | loc: 50:8
[indexDeclaration]: kind: typedef | name: MyInt | USR: c:index-refs.cpp at 593@S at TS>#I at 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 cbc1d85bb33dfc..a437cd081b63d7 100644
--- a/clang/tools/libclang/CIndex.cpp
+++ b/clang/tools/libclang/CIndex.cpp
@@ -743,14 +743,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);
@@ -5611,16 +5607,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 b76627cb9be637..65df513d271372 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 f198dc71eb8337..f52234e9362849 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 8cba3b4a651465d1bc8f09ff2ac8f92211a1e70d Mon Sep 17 00:00:00 2001
From: Krystian Stasiowski <sdkrystian at gmail.com>
Date: Wed, 14 Feb 2024 10:03:57 -0500
Subject: [PATCH 02/11] [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 ce910a7b76eec3..48452992af05ec 100644
--- a/clang/include/clang/AST/DeclTemplate.h
+++ b/clang/include/clang/AST/DeclTemplate.h
@@ -1777,6 +1777,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.
///
@@ -1809,19 +1824,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 *,
@@ -2003,26 +2005,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 *>())
@@ -2031,14 +2022,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);
@@ -2599,19 +2605,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 *,
@@ -2620,7 +2613,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;
@@ -2777,26 +2769,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 *>())
@@ -2805,14 +2786,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 f2cc3d500a00de..bc91306e37fba2 100644
--- a/clang/lib/Serialization/ASTReaderDecl.cpp
+++ b/clang/lib/Serialization/ASTReaderDecl.cpp
@@ -2555,8 +2555,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();
@@ -2626,8 +2625,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 e78a763b754e1bd47724c3bc351f08ea44e06b66 Mon Sep 17 00:00:00 2001
From: Krystian Stasiowski <sdkrystian at gmail.com>
Date: Wed, 14 Feb 2024 12:15:47 -0500
Subject: [PATCH 03/11] [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 de2f6e11f778ae..043e616a1d3664 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 at PartialSpecilizationClass>#$@S at Cls#t0.0 | <no-cgname> | Decl,RelSpecialization | rel: 1
// CHECK-NEXT: RelSpecialization | PartialSpecilizationClass | c:@ST>2#T#T at PartialSpecilizationClass
+// CHECK-NEXT: [[@LINE-3]]:33 | class/C++ | Cls | c:@S at 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 at PartialSpecilizationClass
// CHECK-NEXT: [[@LINE-3]]:45 | class/C++ | Cls | c:@S at Cls | <no-cgname> | Ref,RelBase,RelCont | rel: 1
// CHECK-NEXT: RelBase,RelCont | PartialSpecilizationClass | c:@S at PartialSpecilizationClass>#$@S at Cls#S0_
+// CHECK-NEXT: [[@LINE-5]]:33 | class/C++ | Cls | c:@S at Cls | <no-cgname> | Ref,RelCont | rel: 1
+// CHECK-NEXT: RelCont | PartialSpecilizationClass | c:@S at PartialSpecilizationClass>#$@S at Cls#S0_
+// CHECK-NEXT: [[@LINE-7]]:38 | class/C++ | Cls | c:@S at Cls | <no-cgname> | Ref,RelCont | rel: 1
+// CHECK-NEXT: RelCont | PartialSpecilizationClass | c:@S at PartialSpecilizationClass>#$@S at 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 at SpecializationDecl | <no-cgname> | Ref,RelCont | rel: 1
+// CHECK-NEXT: RelCont | ClassWithCorrectSpecialization | c:@S at ClassWithCorrectSpecialization>#$@S at SpecializationDecl>#$@S at Cls#VI2
+// CHECK-NEXT: [[@LINE-3]]:57 | class/C++ | Cls | c:@S at Cls | <no-cgname> | Ref,RelCont | rel: 1
+// CHECK-NEXT: RelCont | ClassWithCorrectSpecialization | c:@S at ClassWithCorrectSpecialization>#$@S at SpecializationDecl>#$@S at Cls#VI2
+// CHECK-NEXT: [[@LINE-5]]:71 | static-property/C++ | C | c:@S at Record@C | __ZN6Record1CE | Ref,Read,RelCont | rel: 1
+// CHECK-NEXT: RelCont | ClassWithCorrectSpecialization | c:@S at ClassWithCorrectSpecialization>#$@S at SpecializationDecl>#$@S at Cls#VI2
+// CHECK-NEXT: [[@LINE-7]]:63 | struct/C++ | Record | c:@S at Record | <no-cgname> | Ref,RelCont | rel: 1
+// CHECK-NEXT: RelCont | ClassWithCorrectSpecialization | c:@S at ClassWithCorrectSpecialization>#$@S at SpecializationDecl>#$@S at Cls#VI2
namespace ns {
// CHECK: [[@LINE-1]]:11 | namespace/C++ | ns | c:@N at ns | <no-cgname> | Decl | rel: 0
>From 1d3266c2c8f0ae57f00a0c20b938e0aed2ca7302 Mon Sep 17 00:00:00 2001
From: Krystian Stasiowski <sdkrystian at gmail.com>
Date: Mon, 1 Apr 2024 11:00:22 -0400
Subject: [PATCH 04/11] [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 4588d5d2096efd..47c73b92305cc0 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);
@@ -3322,8 +3324,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();
@@ -6264,6 +6267,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 ab634c60816b4e..bff289c0755b19 100644
--- a/clang/lib/AST/DeclTemplate.cpp
+++ b/clang/lib/AST/DeclTemplate.cpp
@@ -984,47 +984,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) {
@@ -1393,6 +1379,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 80cfc854220e91..4fbc423aa944ec 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -5267,7 +5267,6 @@ DeclResult Sema::ActOnVarTemplateSpecialization(
}
}
- Specialization->setTemplateKeywordLoc(TemplateKWLoc);
Specialization->setLexicalDeclContext(CurContext);
// Add the specialization into its lexical context, so that it can
@@ -9631,11 +9630,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.
@@ -11279,6 +11273,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 6661a8adcb372463ebbc3f54a891bd3d3550237b Mon Sep 17 00:00:00 2001
From: Krystian Stasiowski <sdkrystian at gmail.com>
Date: Mon, 1 Apr 2024 11:05:58 -0400
Subject: [PATCH 05/11] [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 47c73b92305cc0..e3ad6abef0a08a 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 bff289c0755b19..b17c0f3c0e1088 100644
--- a/clang/lib/AST/DeclTemplate.cpp
+++ b/clang/lib/AST/DeclTemplate.cpp
@@ -985,23 +985,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())
@@ -1379,10 +1382,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());
}
>From 40c85a2e91f169ec15358d38fe21aac6245830a7 Mon Sep 17 00:00:00 2001
From: Krystian Stasiowski <sdkrystian at gmail.com>
Date: Mon, 1 Apr 2024 12:21:56 -0400
Subject: [PATCH 06/11] [FOLD] only allocate ExplicitInstantiationInfo when
deserializing explicit instantiations
---
clang/lib/Serialization/ASTReaderDecl.cpp | 18 +++++-------
clang/lib/Serialization/ASTWriterDecl.cpp | 36 +++++++++++++++--------
2 files changed, 32 insertions(+), 22 deletions(-)
diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp
index bc91306e37fba2..f66d504a2b7e8c 100644
--- a/clang/lib/Serialization/ASTReaderDecl.cpp
+++ b/clang/lib/Serialization/ASTReaderDecl.cpp
@@ -2551,18 +2551,17 @@ ASTDeclReader::VisitClassTemplateSpecializationDeclImpl(
}
}
- // Explicit info.
+ // extern/template keyword locations for explicit instantiations
if (Record.readBool()) {
- // FIXME: We don't need to allocate this if ExternLoc and TemplateKeywordLoc
- // are invalid!
auto *ExplicitInfo = new (C) ExplicitInstantiationInfo;
- ExplicitInfo->TemplateArgsAsWritten =
- Record.readASTTemplateArgumentListInfo();
ExplicitInfo->ExternLoc = readSourceLocation();
ExplicitInfo->TemplateKeywordLoc = readSourceLocation();
D->ExplicitInfo = ExplicitInfo;
}
+ if (Record.readBool())
+ D->setTemplateArgsAsWritten(Record.readASTTemplateArgumentListInfo());
+
return Redecl;
}
@@ -2621,18 +2620,17 @@ ASTDeclReader::VisitVarTemplateSpecializationDeclImpl(
}
}
- // Explicit info.
+ // extern/template keyword locations for explicit instantiations
if (Record.readBool()) {
- // FIXME: We don't need to allocate this if ExternLoc and TemplateKeywordLoc
- // are invalid!
auto *ExplicitInfo = new (C) ExplicitInstantiationInfo;
- ExplicitInfo->TemplateArgsAsWritten =
- Record.readASTTemplateArgumentListInfo();
ExplicitInfo->ExternLoc = readSourceLocation();
ExplicitInfo->TemplateKeywordLoc = readSourceLocation();
D->ExplicitInfo = ExplicitInfo;
}
+ if (Record.readBool())
+ D->setTemplateArgsAsWritten(Record.readASTTemplateArgumentListInfo());
+
SmallVector<TemplateArgument, 8> TemplArgs;
Record.readTemplateArgumentList(TemplArgs, /*Canonicalize*/ true);
D->TemplateArgs = TemplateArgumentList::CreateCopy(C, TemplArgs);
diff --git a/clang/lib/Serialization/ASTWriterDecl.cpp b/clang/lib/Serialization/ASTWriterDecl.cpp
index 4039b1572696c3..d5a4adcda9cb11 100644
--- a/clang/lib/Serialization/ASTWriterDecl.cpp
+++ b/clang/lib/Serialization/ASTWriterDecl.cpp
@@ -1763,16 +1763,22 @@ void ASTDeclWriter::VisitClassTemplateSpecializationDecl(
Record.AddDeclRef(D->getSpecializedTemplate()->getCanonicalDecl());
}
- // Explicit info.
- const ASTTemplateArgumentListInfo *ArgsWritten =
- D->getTemplateArgsAsWritten();
- Record.push_back(static_cast<bool>(ArgsWritten));
- if (ArgsWritten) {
- Record.AddASTTemplateArgumentListInfo(D->getTemplateArgsAsWritten());
+ bool ExplicitInstantiation =
+ D->getTemplateSpecializationKind() ==
+ TSK_ExplicitInstantiationDeclaration ||
+ D->getTemplateSpecializationKind() == TSK_ExplicitInstantiationDefinition;
+ Record.push_back(ExplicitInstantiation);
+ if (ExplicitInstantiation) {
Record.AddSourceLocation(D->getExternLoc());
Record.AddSourceLocation(D->getTemplateKeywordLoc());
}
+ const ASTTemplateArgumentListInfo *ArgsWritten =
+ D->getTemplateArgsAsWritten();
+ Record.push_back(!!ArgsWritten);
+ if (ArgsWritten)
+ Record.AddASTTemplateArgumentListInfo(ArgsWritten);
+
Code = serialization::DECL_CLASS_TEMPLATE_SPECIALIZATION;
}
@@ -1812,16 +1818,22 @@ void ASTDeclWriter::VisitVarTemplateSpecializationDecl(
Record.AddTemplateArgumentList(&D->getTemplateInstantiationArgs());
}
- // Explicit info.
- const ASTTemplateArgumentListInfo *ArgsWritten =
- D->getTemplateArgsAsWritten();
- Record.push_back(static_cast<bool>(ArgsWritten));
- if (ArgsWritten) {
- Record.AddASTTemplateArgumentListInfo(D->getTemplateArgsAsWritten());
+ bool ExplicitInstantiation =
+ D->getTemplateSpecializationKind() ==
+ TSK_ExplicitInstantiationDeclaration ||
+ D->getTemplateSpecializationKind() == TSK_ExplicitInstantiationDefinition;
+ Record.push_back(ExplicitInstantiation);
+ if (ExplicitInstantiation) {
Record.AddSourceLocation(D->getExternLoc());
Record.AddSourceLocation(D->getTemplateKeywordLoc());
}
+ const ASTTemplateArgumentListInfo *ArgsWritten =
+ D->getTemplateArgsAsWritten();
+ Record.push_back(!!ArgsWritten);
+ if (ArgsWritten)
+ Record.AddASTTemplateArgumentListInfo(ArgsWritten);
+
Record.AddTemplateArgumentList(&D->getTemplateArgs());
Record.AddSourceLocation(D->getPointOfInstantiation());
Record.push_back(D->getSpecializationKind());
>From ffa539daab1ce9bbe11fc36115badbe7f7af43de Mon Sep 17 00:00:00 2001
From: Krystian Stasiowski <sdkrystian at gmail.com>
Date: Mon, 1 Apr 2024 12:48:13 -0400
Subject: [PATCH 07/11] [FOLD] rename ExternLoc -> ExternKeywordLoc
---
clang/include/clang/AST/DeclTemplate.h | 14 +++++++-------
clang/lib/AST/ASTImporter.cpp | 4 ++--
clang/lib/AST/DeclTemplate.cpp | 12 ++++++------
clang/lib/Sema/SemaTemplate.cpp | 4 ++--
clang/lib/Sema/SemaTemplateInstantiateDecl.cpp | 2 +-
clang/lib/Serialization/ASTReaderDecl.cpp | 4 ++--
clang/lib/Serialization/ASTWriterDecl.cpp | 4 ++--
clang/lib/Tooling/Syntax/BuildTree.cpp | 3 ++-
8 files changed, 24 insertions(+), 23 deletions(-)
diff --git a/clang/include/clang/AST/DeclTemplate.h b/clang/include/clang/AST/DeclTemplate.h
index 48452992af05ec..39427c2c0a17e3 100644
--- a/clang/include/clang/AST/DeclTemplate.h
+++ b/clang/include/clang/AST/DeclTemplate.h
@@ -1784,7 +1784,7 @@ struct ExplicitInstantiationInfo {
const ASTTemplateArgumentListInfo *TemplateArgsAsWritten = nullptr;
/// The location of the extern keyword.
- SourceLocation ExternLoc;
+ SourceLocation ExternKeywordLoc;
/// The location of the template keyword.
SourceLocation TemplateKeywordLoc;
@@ -2029,14 +2029,14 @@ class ClassTemplateSpecializationDecl
}
/// Gets the location of the extern keyword, if present.
- SourceLocation getExternLoc() const {
+ SourceLocation getExternKeywordLoc() const {
if (auto *Info = ExplicitInfo.dyn_cast<ExplicitInstantiationInfo *>())
- return Info->ExternLoc;
+ return Info->ExternKeywordLoc;
return SourceLocation();
}
/// Sets the location of the extern keyword.
- void setExternLoc(SourceLocation Loc);
+ void setExternKeywordLoc(SourceLocation Loc);
/// Gets the location of the template keyword, if present.
SourceLocation getTemplateKeywordLoc() const {
@@ -2793,14 +2793,14 @@ class VarTemplateSpecializationDecl : public VarDecl,
}
/// Gets the location of the extern keyword, if present.
- SourceLocation getExternLoc() const {
+ SourceLocation getExternKeywordLoc() const {
if (auto *Info = ExplicitInfo.dyn_cast<ExplicitInstantiationInfo *>())
- return Info->ExternLoc;
+ return Info->ExternKeywordLoc;
return SourceLocation();
}
/// Sets the location of the extern keyword.
- void setExternLoc(SourceLocation Loc);
+ void setExternKeywordLoc(SourceLocation Loc);
/// Gets the location of the template keyword, if present.
SourceLocation getTemplateKeywordLoc() const {
diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp
index e3ad6abef0a08a..03d6316958ab45 100644
--- a/clang/lib/AST/ASTImporter.cpp
+++ b/clang/lib/AST/ASTImporter.cpp
@@ -6283,8 +6283,8 @@ ExpectedDecl ASTNodeImporter::VisitClassTemplateSpecializationDecl(
else
return LocOrErr.takeError();
- if (auto LocOrErr = import(D->getExternLoc()))
- D2->setExternLoc(*LocOrErr);
+ if (auto LocOrErr = import(D->getExternKeywordLoc()))
+ D2->setExternKeywordLoc(*LocOrErr);
else
return LocOrErr.takeError();
diff --git a/clang/lib/AST/DeclTemplate.cpp b/clang/lib/AST/DeclTemplate.cpp
index b17c0f3c0e1088..38c10dad43bf22 100644
--- a/clang/lib/AST/DeclTemplate.cpp
+++ b/clang/lib/AST/DeclTemplate.cpp
@@ -985,7 +985,7 @@ ClassTemplateSpecializationDecl::getSpecializedTemplate() const {
SourceRange
ClassTemplateSpecializationDecl::getSourceRange() const {
if (getSpecializationKind() == TSK_ExplicitInstantiationDeclaration) {
- return SourceRange(getExternLoc(),
+ return SourceRange(getExternKeywordLoc(),
getTemplateArgsAsWritten()->getRAngleLoc());
} else if (getSpecializationKind() == TSK_ExplicitInstantiationDefinition) {
return SourceRange(getTemplateKeywordLoc(),
@@ -1016,7 +1016,7 @@ ClassTemplateSpecializationDecl::getSourceRange() const {
return SourceRange(Begin, End);
}
-void ClassTemplateSpecializationDecl::setExternLoc(SourceLocation Loc) {
+void ClassTemplateSpecializationDecl::setExternKeywordLoc(SourceLocation Loc) {
auto *Info = ExplicitInfo.dyn_cast<ExplicitInstantiationInfo *>();
if (!Info) {
// Don't allocate if the location is invalid.
@@ -1026,7 +1026,7 @@ void ClassTemplateSpecializationDecl::setExternLoc(SourceLocation Loc) {
Info->TemplateArgsAsWritten = getTemplateArgsAsWritten();
ExplicitInfo = Info;
}
- Info->ExternLoc = Loc;
+ Info->ExternKeywordLoc = Loc;
}
void ClassTemplateSpecializationDecl::setTemplateKeywordLoc(
@@ -1385,7 +1385,7 @@ SourceRange VarTemplateSpecializationDecl::getSourceRange() const {
} else if (getTemplateSpecializationKind() ==
TSK_ExplicitInstantiationDeclaration) {
if (const ASTTemplateArgumentListInfo *Info = getTemplateArgsAsWritten())
- return SourceRange(getExternLoc(), Info->getRAngleLoc());
+ return SourceRange(getExternKeywordLoc(), Info->getRAngleLoc());
} else if (getTemplateSpecializationKind() ==
TSK_ExplicitInstantiationDefinition) {
if (const ASTTemplateArgumentListInfo *Info = getTemplateArgsAsWritten())
@@ -1394,7 +1394,7 @@ SourceRange VarTemplateSpecializationDecl::getSourceRange() const {
return VarDecl::getSourceRange();
}
-void VarTemplateSpecializationDecl::setExternLoc(SourceLocation Loc) {
+void VarTemplateSpecializationDecl::setExternKeywordLoc(SourceLocation Loc) {
auto *Info = ExplicitInfo.dyn_cast<ExplicitInstantiationInfo *>();
if (!Info) {
// Don't allocate if the location is invalid.
@@ -1404,7 +1404,7 @@ void VarTemplateSpecializationDecl::setExternLoc(SourceLocation Loc) {
Info->TemplateArgsAsWritten = getTemplateArgsAsWritten();
ExplicitInfo = Info;
}
- Info->ExternLoc = Loc;
+ Info->ExternKeywordLoc = Loc;
}
void VarTemplateSpecializationDecl::setTemplateKeywordLoc(SourceLocation Loc) {
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index 4fbc423aa944ec..a9fd3a437734a3 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -10861,7 +10861,7 @@ DeclResult Sema::ActOnExplicitInstantiation(
Specialization->setTemplateArgsAsWritten(TemplateArgs);
// Set source locations for keywords.
- Specialization->setExternLoc(ExternLoc);
+ Specialization->setExternKeywordLoc(ExternLoc);
Specialization->setTemplateKeywordLoc(TemplateLoc);
Specialization->setBraceRange(SourceRange());
@@ -11274,7 +11274,7 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
// Instantiate static data member or variable template.
Prev->setTemplateSpecializationKind(TSK, D.getIdentifierLoc());
if (auto *VTSD = dyn_cast<VarTemplatePartialSpecializationDecl>(Prev)) {
- VTSD->setExternLoc(ExternLoc);
+ VTSD->setExternKeywordLoc(ExternLoc);
VTSD->setTemplateKeywordLoc(TemplateLoc);
}
diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 65caed75a9338a..49123686667a52 100644
--- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -3941,7 +3941,7 @@ TemplateDeclInstantiator::VisitClassTemplateSpecializationDecl(
InstD->setAccess(D->getAccess());
InstD->setInstantiationOfMemberClass(D, TSK_ImplicitInstantiation);
InstD->setSpecializationKind(D->getSpecializationKind());
- InstD->setExternLoc(D->getExternLoc());
+ InstD->setExternKeywordLoc(D->getExternKeywordLoc());
InstD->setTemplateKeywordLoc(D->getTemplateKeywordLoc());
Owner->addDecl(InstD);
diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp
index f66d504a2b7e8c..1a789e0a49ea58 100644
--- a/clang/lib/Serialization/ASTReaderDecl.cpp
+++ b/clang/lib/Serialization/ASTReaderDecl.cpp
@@ -2554,7 +2554,7 @@ ASTDeclReader::VisitClassTemplateSpecializationDeclImpl(
// extern/template keyword locations for explicit instantiations
if (Record.readBool()) {
auto *ExplicitInfo = new (C) ExplicitInstantiationInfo;
- ExplicitInfo->ExternLoc = readSourceLocation();
+ ExplicitInfo->ExternKeywordLoc = readSourceLocation();
ExplicitInfo->TemplateKeywordLoc = readSourceLocation();
D->ExplicitInfo = ExplicitInfo;
}
@@ -2623,7 +2623,7 @@ ASTDeclReader::VisitVarTemplateSpecializationDeclImpl(
// extern/template keyword locations for explicit instantiations
if (Record.readBool()) {
auto *ExplicitInfo = new (C) ExplicitInstantiationInfo;
- ExplicitInfo->ExternLoc = readSourceLocation();
+ ExplicitInfo->ExternKeywordLoc = readSourceLocation();
ExplicitInfo->TemplateKeywordLoc = readSourceLocation();
D->ExplicitInfo = ExplicitInfo;
}
diff --git a/clang/lib/Serialization/ASTWriterDecl.cpp b/clang/lib/Serialization/ASTWriterDecl.cpp
index d5a4adcda9cb11..c340a2bb223ea3 100644
--- a/clang/lib/Serialization/ASTWriterDecl.cpp
+++ b/clang/lib/Serialization/ASTWriterDecl.cpp
@@ -1769,7 +1769,7 @@ void ASTDeclWriter::VisitClassTemplateSpecializationDecl(
D->getTemplateSpecializationKind() == TSK_ExplicitInstantiationDefinition;
Record.push_back(ExplicitInstantiation);
if (ExplicitInstantiation) {
- Record.AddSourceLocation(D->getExternLoc());
+ Record.AddSourceLocation(D->getExternKeywordLoc());
Record.AddSourceLocation(D->getTemplateKeywordLoc());
}
@@ -1824,7 +1824,7 @@ void ASTDeclWriter::VisitVarTemplateSpecializationDecl(
D->getTemplateSpecializationKind() == TSK_ExplicitInstantiationDefinition;
Record.push_back(ExplicitInstantiation);
if (ExplicitInstantiation) {
- Record.AddSourceLocation(D->getExternLoc());
+ Record.AddSourceLocation(D->getExternKeywordLoc());
Record.AddSourceLocation(D->getTemplateKeywordLoc());
}
diff --git a/clang/lib/Tooling/Syntax/BuildTree.cpp b/clang/lib/Tooling/Syntax/BuildTree.cpp
index cd026198949500..3e50d67f4d6ef0 100644
--- a/clang/lib/Tooling/Syntax/BuildTree.cpp
+++ b/clang/lib/Tooling/Syntax/BuildTree.cpp
@@ -735,7 +735,8 @@ class BuildTreeVisitor : public RecursiveASTVisitor<BuildTreeVisitor> {
auto *Declaration =
cast<syntax::SimpleDeclaration>(handleFreeStandingTagDecl(C));
foldExplicitTemplateInstantiation(
- Builder.getTemplateRange(C), Builder.findToken(C->getExternLoc()),
+ Builder.getTemplateRange(C),
+ Builder.findToken(C->getExternKeywordLoc()),
Builder.findToken(C->getTemplateKeywordLoc()), Declaration, C);
return true;
}
>From 90d486bc3a03ab19be2599f6c561be294b433a05 Mon Sep 17 00:00:00 2001
From: Krystian Stasiowski <sdkrystian at gmail.com>
Date: Wed, 17 Apr 2024 10:23:02 -0400
Subject: [PATCH 08/11] [FOLD] address more review feedback
---
clang/lib/AST/DeclPrinter.cpp | 5 +++--
clang/lib/AST/TypePrinter.cpp | 5 +++--
2 files changed, 6 insertions(+), 4 deletions(-)
diff --git a/clang/lib/AST/DeclPrinter.cpp b/clang/lib/AST/DeclPrinter.cpp
index e73201ab8a8bce..c5868256b440d9 100644
--- a/clang/lib/AST/DeclPrinter.cpp
+++ b/clang/lib/AST/DeclPrinter.cpp
@@ -1083,10 +1083,11 @@ void DeclPrinter::VisitCXXRecordDecl(CXXRecordDecl *D) {
NNS->print(Out, Policy);
Out << *D;
- if (auto S = dyn_cast<ClassTemplateSpecializationDecl>(D)) {
+ if (auto *S = dyn_cast<ClassTemplateSpecializationDecl>(D)) {
const TemplateParameterList *TParams =
S->getSpecializedTemplate()->getTemplateParameters();
- const auto *TArgAsWritten = S->getTemplateArgsAsWritten();
+ const ASTTemplateArgumentListInfo *TArgAsWritten =
+ S->getTemplateArgsAsWritten();
if (TArgAsWritten && !Policy.PrintCanonicalTypes)
printTemplateArguments(TArgAsWritten->arguments(), TParams);
else
diff --git a/clang/lib/AST/TypePrinter.cpp b/clang/lib/AST/TypePrinter.cpp
index 364f0343ffe0c8..87f0a8728d8506 100644
--- a/clang/lib/AST/TypePrinter.cpp
+++ b/clang/lib/AST/TypePrinter.cpp
@@ -1472,10 +1472,11 @@ void TypePrinter::printTag(TagDecl *D, raw_ostream &OS) {
// If this is a class template specialization, print the template
// arguments.
- if (auto S = dyn_cast<ClassTemplateSpecializationDecl>(D)) {
+ if (auto *S = dyn_cast<ClassTemplateSpecializationDecl>(D)) {
const TemplateParameterList *TParams =
S->getSpecializedTemplate()->getTemplateParameters();
- const auto *TArgAsWritten = S->getTemplateArgsAsWritten();
+ const ASTTemplateArgumentListInfo *TArgAsWritten =
+ S->getTemplateArgsAsWritten();
IncludeStrongLifetimeRAII Strong(Policy);
if (TArgAsWritten && !Policy.PrintCanonicalTypes)
printTemplateArgumentList(OS, TArgAsWritten->arguments(), Policy,
>From b64508ed85d7b8c762aeaf42106d50da5e002bcd Mon Sep 17 00:00:00 2001
From: Krystian Stasiowski <sdkrystian at gmail.com>
Date: Wed, 17 Apr 2024 11:36:06 -0400
Subject: [PATCH 09/11] [FOLD] fix uses of template arguments as written in
clangd
---
clang-tools-extra/clangd/AST.cpp | 32 ++++---------------
.../clangd/SemanticHighlighting.cpp | 2 +-
2 files changed, 7 insertions(+), 27 deletions(-)
diff --git a/clang-tools-extra/clangd/AST.cpp b/clang-tools-extra/clangd/AST.cpp
index 1b86ea19cf28da..56edfdbe2a0451 100644
--- a/clang-tools-extra/clangd/AST.cpp
+++ b/clang-tools-extra/clangd/AST.cpp
@@ -50,16 +50,11 @@ getTemplateSpecializationArgLocs(const NamedDecl &ND) {
if (const ASTTemplateArgumentListInfo *Args =
Func->getTemplateSpecializationArgsAsWritten())
return Args->arguments();
- } else if (auto *Cls =
- llvm::dyn_cast<ClassTemplatePartialSpecializationDecl>(&ND)) {
+ } else if (auto *Cls = llvm::dyn_cast<ClassTemplateSpecializationDecl>(&ND)) {
if (auto *Args = Cls->getTemplateArgsAsWritten())
return Args->arguments();
- } else if (auto *Var =
- llvm::dyn_cast<VarTemplatePartialSpecializationDecl>(&ND)) {
- if (auto *Args = Var->getTemplateArgsAsWritten())
- return Args->arguments();
} else if (auto *Var = llvm::dyn_cast<VarTemplateSpecializationDecl>(&ND)) {
- if (auto *Args = Var->getTemplateArgsInfo())
+ if (auto *Args = Var->getTemplateArgsAsWritten())
return Args->arguments();
}
// We return std::nullopt for ClassTemplateSpecializationDecls because it does
@@ -270,22 +265,10 @@ std::string printTemplateSpecializationArgs(const NamedDecl &ND) {
getTemplateSpecializationArgLocs(ND)) {
printTemplateArgumentList(OS, *Args, Policy);
} else if (auto *Cls = llvm::dyn_cast<ClassTemplateSpecializationDecl>(&ND)) {
- if (const TypeSourceInfo *TSI = Cls->getTypeAsWritten()) {
- // ClassTemplateSpecializationDecls do not contain
- // TemplateArgumentTypeLocs, they only have TemplateArgumentTypes. So we
- // create a new argument location list from TypeSourceInfo.
- auto STL = TSI->getTypeLoc().getAs<TemplateSpecializationTypeLoc>();
- llvm::SmallVector<TemplateArgumentLoc> ArgLocs;
- ArgLocs.reserve(STL.getNumArgs());
- for (unsigned I = 0; I < STL.getNumArgs(); ++I)
- ArgLocs.push_back(STL.getArgLoc(I));
- printTemplateArgumentList(OS, ArgLocs, Policy);
- } else {
- // FIXME: Fix cases when getTypeAsWritten returns null inside clang AST,
- // e.g. friend decls. Currently we fallback to Template Arguments without
- // location information.
- printTemplateArgumentList(OS, Cls->getTemplateArgs().asArray(), Policy);
- }
+ // FIXME: Fix cases when getTypeAsWritten returns null inside clang AST,
+ // e.g. friend decls. Currently we fallback to Template Arguments without
+ // location information.
+ printTemplateArgumentList(OS, Cls->getTemplateArgs().asArray(), Policy);
}
OS.flush();
return TemplateArgs;
@@ -453,9 +436,6 @@ bool hasReservedScope(const DeclContext &DC) {
}
QualType declaredType(const TypeDecl *D) {
- if (const auto *CTSD = llvm::dyn_cast<ClassTemplateSpecializationDecl>(D))
- if (const auto *TSI = CTSD->getTypeAsWritten())
- return TSI->getType();
return D->getASTContext().getTypeDeclType(D);
}
diff --git a/clang-tools-extra/clangd/SemanticHighlighting.cpp b/clang-tools-extra/clangd/SemanticHighlighting.cpp
index 08f99e11ac9be1..264ae617166d9b 100644
--- a/clang-tools-extra/clangd/SemanticHighlighting.cpp
+++ b/clang-tools-extra/clangd/SemanticHighlighting.cpp
@@ -703,7 +703,7 @@ class CollectExtraHighlightings
}
bool VisitVarTemplateSpecializationDecl(VarTemplateSpecializationDecl *D) {
- if (auto *Args = D->getTemplateArgsInfo())
+ if (auto *Args = D->getTemplateArgsAsWritten())
H.addAngleBracketTokens(Args->getLAngleLoc(), Args->getRAngleLoc());
return true;
}
>From f9518d3d53d62d12fabaeef8229fdd6fde6d065b Mon Sep 17 00:00:00 2001
From: Krystian Stasiowski <sdkrystian at gmail.com>
Date: Wed, 17 Apr 2024 11:44:58 -0400
Subject: [PATCH 10/11] [FOLD] convert more ASTMatcher tests
---
.../ASTMatchers/ASTMatchersTraversalTest.cpp | 125 ++++++++----------
1 file changed, 52 insertions(+), 73 deletions(-)
diff --git a/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp b/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
index f52234e9362849..541af34a9b3f21 100644
--- a/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
+++ b/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
@@ -6381,24 +6381,13 @@ TEST(HasAnyTemplateArgumentLoc, BindsToExplicitSpecializationWithIntArgument) {
refersToType(asString("int")))))));
}
-#if 0
-TEST(HasAnyTemplateArgumentLoc, BindsToExplicitSpecializationWithIntArgument) {
- EXPECT_TRUE(matches(
- "template<typename T> class A {}; template<> class A<int> {};",
- classTemplateSpecializationDecl(
- hasName("A"),
- hasTypeLoc(templateSpecializationTypeLoc(
- hasAnyTemplateArgumentLoc(hasTypeLoc(loc(asString("int")))))))));
-}
-
TEST(HasAnyTemplateArgumentLoc,
BindsToExplicitSpecializationWithDoubleArgument) {
- EXPECT_TRUE(matches(
- "template<typename T> class A {}; template<> class A<double> {};",
- classTemplateSpecializationDecl(
- hasName("A"),
- hasTypeLoc(templateSpecializationTypeLoc(hasAnyTemplateArgumentLoc(
- hasTypeLoc(loc(asString("double")))))))));
+ EXPECT_TRUE(
+ matches("template<typename T> class A {}; template<> class A<double> {};",
+ classTemplateSpecializationDecl(
+ hasName("A"), hasAnyTemplateArgument(templateArgument(
+ refersToType(asString("double")))))));
}
TEST(HasAnyTemplateArgumentLoc, BindsToSpecializationWithMultipleArguments) {
@@ -6408,36 +6397,31 @@ TEST(HasAnyTemplateArgumentLoc, BindsToSpecializationWithMultipleArguments) {
)";
EXPECT_TRUE(
matches(code, classTemplateSpecializationDecl(
- hasName("A"), hasTypeLoc(templateSpecializationTypeLoc(
- hasAnyTemplateArgumentLoc(hasTypeLoc(
- loc(asString("double")))))))));
- EXPECT_TRUE(matches(
- code,
- classTemplateSpecializationDecl(
- hasName("A"),
- hasTypeLoc(templateSpecializationTypeLoc(
- hasAnyTemplateArgumentLoc(hasTypeLoc(loc(asString("int")))))))));
+ hasName("A"), hasAnyTemplateArgument(templateArgument(
+ refersToType(asString("double")))))));
+
+ EXPECT_TRUE(
+ matches(code, classTemplateSpecializationDecl(
+ hasName("A"), hasAnyTemplateArgument(templateArgument(
+ refersToType(asString("int")))))));
}
TEST(HasAnyTemplateArgumentLoc, DoesNotBindToSpecializationWithIntArgument) {
- EXPECT_TRUE(notMatches(
- "template<typename T> class A {}; A<int> a;",
- classTemplateSpecializationDecl(
- hasName("A"),
- hasTypeLoc(templateSpecializationTypeLoc(hasAnyTemplateArgumentLoc(
- hasTypeLoc(loc(asString("double")))))))));
+ EXPECT_TRUE(
+ notMatches("template<typename T> class A {}; A<int> a;",
+ classTemplateSpecializationDecl(
+ hasName("A"), hasAnyTemplateArgument(templateArgument(
+ refersToType(asString("double")))))));
}
TEST(HasAnyTemplateArgumentLoc,
DoesNotBindToExplicitSpecializationWithIntArgument) {
- EXPECT_TRUE(notMatches(
- "template<typename T> class A {}; template<> class A<int> {};",
- classTemplateSpecializationDecl(
- hasName("A"),
- hasTypeLoc(templateSpecializationTypeLoc(hasAnyTemplateArgumentLoc(
- hasTypeLoc(loc(asString("double")))))))));
+ EXPECT_TRUE(
+ notMatches("template<typename T> class A {}; template<> class A<int> {};",
+ classTemplateSpecializationDecl(
+ hasName("A"), hasAnyTemplateArgument(templateArgument(
+ refersToType(asString("double")))))));
}
-#endif
TEST(HasTemplateArgumentLoc, BindsToSpecializationWithIntArgument) {
EXPECT_TRUE(
@@ -6449,22 +6433,27 @@ TEST(HasTemplateArgumentLoc, BindsToSpecializationWithIntArgument) {
}
TEST(HasTemplateArgumentLoc, BindsToSpecializationWithDoubleArgument) {
- EXPECT_TRUE(
- matches("template<typename T> class A {}; A<double> a;",
- varDecl(hasName("a"),
- hasTypeLoc(elaboratedTypeLoc(hasNamedTypeLoc(
- templateSpecializationTypeLoc(hasTemplateArgumentLoc(
- 0, hasTypeLoc(loc(asString("double")))))))))));
+ EXPECT_TRUE(matches("template<typename T> class A {}; A<double> a;",
+ varDecl(hasName("a"),
+ hasTypeLoc(elaboratedTypeLoc(hasNamedTypeLoc(
+ templateSpecializationTypeLoc(hasTemplateArgumentLoc(
+ 0, hasTypeLoc(loc(asString("double")))))))))));
+}
+
+TEST(HasTemplateArgumentLoc, DoesNotBindToSpecializationWithIntArgument) {
+ EXPECT_TRUE(notMatches("template<typename T> class A {}; A<int> a;",
+ varDecl(hasName("a"),
+ hasTypeLoc(elaboratedTypeLoc(hasNamedTypeLoc(
+ templateSpecializationTypeLoc(hasTemplateArgumentLoc(
+ 0, hasTypeLoc(loc(asString("double")))))))))));
}
-#if 0
TEST(HasTemplateArgumentLoc, BindsToExplicitSpecializationWithIntArgument) {
EXPECT_TRUE(matches(
"template<typename T> class A {}; template<> class A<int> {};",
classTemplateSpecializationDecl(
hasName("A"),
- hasTypeLoc(templateSpecializationTypeLoc(
- hasTemplateArgumentLoc(0, hasTypeLoc(loc(asString("int")))))))));
+ hasTemplateArgument(0, refersToType(asString("int"))))));
}
TEST(HasTemplateArgumentLoc, BindsToExplicitSpecializationWithDoubleArgument) {
@@ -6472,8 +6461,8 @@ TEST(HasTemplateArgumentLoc, BindsToExplicitSpecializationWithDoubleArgument) {
"template<typename T> class A {}; template<> class A<double> {};",
classTemplateSpecializationDecl(
hasName("A"),
- hasTypeLoc(templateSpecializationTypeLoc(hasTemplateArgumentLoc(
- 0, hasTypeLoc(loc(asString("double")))))))));
+ hasTemplateArgument(
+ 0, refersToType(asString("double"))))));
}
TEST(HasTemplateArgumentLoc, BindsToSpecializationWithMultipleArguments) {
@@ -6484,22 +6473,13 @@ TEST(HasTemplateArgumentLoc, BindsToSpecializationWithMultipleArguments) {
EXPECT_TRUE(matches(
code, classTemplateSpecializationDecl(
hasName("A"),
- hasTypeLoc(templateSpecializationTypeLoc(hasTemplateArgumentLoc(
- 0, hasTypeLoc(loc(asString("double")))))))));
+ hasTemplateArgument(
+ 0, refersToType(asString("double"))))));
EXPECT_TRUE(matches(
code, classTemplateSpecializationDecl(
hasName("A"),
- hasTypeLoc(templateSpecializationTypeLoc(hasTemplateArgumentLoc(
- 1, hasTypeLoc(loc(asString("int")))))))));
-}
-
-TEST(HasTemplateArgumentLoc, DoesNotBindToSpecializationWithIntArgument) {
- EXPECT_TRUE(notMatches(
- "template<typename T> class A {}; A<int> a;",
- classTemplateSpecializationDecl(
- hasName("A"),
- hasTypeLoc(templateSpecializationTypeLoc(hasTemplateArgumentLoc(
- 0, hasTypeLoc(loc(asString("double")))))))));
+ hasTemplateArgument(
+ 1, refersToType(asString("int"))))));
}
TEST(HasTemplateArgumentLoc,
@@ -6508,8 +6488,8 @@ TEST(HasTemplateArgumentLoc,
"template<typename T> class A {}; template<> class A<int> {};",
classTemplateSpecializationDecl(
hasName("A"),
- hasTypeLoc(templateSpecializationTypeLoc(hasTemplateArgumentLoc(
- 0, hasTypeLoc(loc(asString("double")))))))));
+ hasTemplateArgument(
+ 0, refersToType(asString("double"))))));
}
TEST(HasTemplateArgumentLoc,
@@ -6521,13 +6501,13 @@ TEST(HasTemplateArgumentLoc,
EXPECT_TRUE(notMatches(
code, classTemplateSpecializationDecl(
hasName("A"),
- hasTypeLoc(templateSpecializationTypeLoc(hasTemplateArgumentLoc(
- 1, hasTypeLoc(loc(asString("double")))))))));
+ hasTemplateArgument(
+ 1, refersToType(asString("double"))))));
EXPECT_TRUE(notMatches(
code, classTemplateSpecializationDecl(
hasName("A"),
- hasTypeLoc(templateSpecializationTypeLoc(hasTemplateArgumentLoc(
- 0, hasTypeLoc(loc(asString("int")))))))));
+ hasTemplateArgument(
+ 0, refersToType(asString("int"))))));
}
TEST(HasTemplateArgumentLoc, DoesNotBindWithBadIndex) {
@@ -6538,15 +6518,14 @@ TEST(HasTemplateArgumentLoc, DoesNotBindWithBadIndex) {
EXPECT_TRUE(notMatches(
code, classTemplateSpecializationDecl(
hasName("A"),
- hasTypeLoc(templateSpecializationTypeLoc(hasTemplateArgumentLoc(
- -1, hasTypeLoc(loc(asString("double")))))))));
+ hasTemplateArgument(
+ -1, refersToType(asString("double"))))));
EXPECT_TRUE(notMatches(
code, classTemplateSpecializationDecl(
hasName("A"),
- hasTypeLoc(templateSpecializationTypeLoc(hasTemplateArgumentLoc(
- 100, hasTypeLoc(loc(asString("int")))))))));
+ hasTemplateArgument(
+ 100, refersToType(asString("int"))))));
}
-#endif
TEST(HasTemplateArgumentLoc, BindsToDeclRefExprWithIntArgument) {
EXPECT_TRUE(matches(R"(
>From a6a4930c5559271355c3e6eac19b06557933d886 Mon Sep 17 00:00:00 2001
From: Krystian Stasiowski <sdkrystian at gmail.com>
Date: Wed, 17 Apr 2024 13:46:08 -0400
Subject: [PATCH 11/11] [FOLD] has(Any)TemplateArgumentLoc supports
specializations
---
clang/include/clang/ASTMatchers/ASTMatchers.h | 35 ++++---
.../clang/ASTMatchers/ASTMatchersInternal.h | 46 ++++++++-
.../ASTMatchers/ASTMatchersTraversalTest.cpp | 99 +++++++++----------
3 files changed, 110 insertions(+), 70 deletions(-)
diff --git a/clang/include/clang/ASTMatchers/ASTMatchers.h b/clang/include/clang/ASTMatchers/ASTMatchers.h
index 073fabc6e514b1..c6b1e4dab0294d 100644
--- a/clang/include/clang/ASTMatchers/ASTMatchers.h
+++ b/clang/include/clang/ASTMatchers/ASTMatchers.h
@@ -788,8 +788,8 @@ AST_POLYMORPHIC_MATCHER(isImplicit,
AST_POLYMORPHIC_MATCHER_P(
hasAnyTemplateArgument,
AST_POLYMORPHIC_SUPPORTED_TYPES(ClassTemplateSpecializationDecl,
- TemplateSpecializationType,
- FunctionDecl),
+ VarTemplateSpecializationDecl, FunctionDecl,
+ TemplateSpecializationType),
internal::Matcher<TemplateArgument>, InnerMatcher) {
ArrayRef<TemplateArgument> List =
internal::getTemplateSpecializationArgs(Node);
@@ -1068,8 +1068,8 @@ AST_MATCHER(Expr, isValueDependent) { return Node.isValueDependent(); }
AST_POLYMORPHIC_MATCHER_P2(
hasTemplateArgument,
AST_POLYMORPHIC_SUPPORTED_TYPES(ClassTemplateSpecializationDecl,
- TemplateSpecializationType,
- FunctionDecl),
+ VarTemplateSpecializationDecl, FunctionDecl,
+ TemplateSpecializationType),
unsigned, N, internal::Matcher<TemplateArgument>, InnerMatcher) {
ArrayRef<TemplateArgument> List =
internal::getTemplateSpecializationArgs(Node);
@@ -6915,15 +6915,15 @@ extern const internal::VariadicDynCastAllOfMatcher<
/// varDecl(hasTypeLoc(templateSpecializationTypeLoc(hasAnyTemplateArgumentLoc(
/// hasTypeLoc(loc(asString("int")))))))
/// matches `A<int> a`.
-AST_MATCHER_P(TemplateSpecializationTypeLoc, hasAnyTemplateArgumentLoc,
- internal::Matcher<TemplateArgumentLoc>, InnerMatcher) {
- for (unsigned Index = 0, N = Node.getNumArgs(); Index < N; ++Index) {
- clang::ast_matchers::internal::BoundNodesTreeBuilder Result(*Builder);
- if (InnerMatcher.matches(Node.getArgLoc(Index), Finder, &Result)) {
- *Builder = std::move(Result);
- return true;
- }
- }
+AST_POLYMORPHIC_MATCHER_P(
+ hasAnyTemplateArgumentLoc,
+ AST_POLYMORPHIC_SUPPORTED_TYPES(ClassTemplateSpecializationDecl,
+ VarTemplateSpecializationDecl, FunctionDecl,
+ DeclRefExpr, TemplateSpecializationTypeLoc),
+ internal::Matcher<TemplateArgumentLoc>, InnerMatcher) {
+ auto Args = internal::getTemplateArgsWritten(Node);
+ return matchesFirstInRange(InnerMatcher, Args.begin(), Args.end(), Finder,
+ Builder) != Args.end();
return false;
}
@@ -6941,10 +6941,13 @@ AST_MATCHER_P(TemplateSpecializationTypeLoc, hasAnyTemplateArgumentLoc,
/// matches `A<double, int> b`, but not `A<int, double> c`.
AST_POLYMORPHIC_MATCHER_P2(
hasTemplateArgumentLoc,
- AST_POLYMORPHIC_SUPPORTED_TYPES(DeclRefExpr, TemplateSpecializationTypeLoc),
+ AST_POLYMORPHIC_SUPPORTED_TYPES(ClassTemplateSpecializationDecl,
+ VarTemplateSpecializationDecl, FunctionDecl,
+ DeclRefExpr, TemplateSpecializationTypeLoc),
unsigned, Index, internal::Matcher<TemplateArgumentLoc>, InnerMatcher) {
- return internal::MatchTemplateArgLocAt(Node, Index, InnerMatcher, Finder,
- Builder);
+ auto Args = internal::getTemplateArgsWritten(Node);
+ return Index < Args.size() &&
+ InnerMatcher.matches(Args[Index], Finder, Builder);
}
/// Matches C or C++ elaborated `TypeLoc`s.
diff --git a/clang/include/clang/ASTMatchers/ASTMatchersInternal.h b/clang/include/clang/ASTMatchers/ASTMatchersInternal.h
index dca642acfa38bc..c1cc63fdb7433f 100644
--- a/clang/include/clang/ASTMatchers/ASTMatchersInternal.h
+++ b/clang/include/clang/ASTMatchers/ASTMatchersInternal.h
@@ -1935,6 +1935,11 @@ getTemplateSpecializationArgs(const ClassTemplateSpecializationDecl &D) {
return D.getTemplateArgs().asArray();
}
+inline ArrayRef<TemplateArgument>
+getTemplateSpecializationArgs(const VarTemplateSpecializationDecl &D) {
+ return D.getTemplateArgs().asArray();
+}
+
inline ArrayRef<TemplateArgument>
getTemplateSpecializationArgs(const TemplateSpecializationType &T) {
return T.template_arguments();
@@ -1944,7 +1949,46 @@ inline ArrayRef<TemplateArgument>
getTemplateSpecializationArgs(const FunctionDecl &FD) {
if (const auto* TemplateArgs = FD.getTemplateSpecializationArgs())
return TemplateArgs->asArray();
- return ArrayRef<TemplateArgument>();
+ return std::nullopt;
+}
+
+inline ArrayRef<TemplateArgumentLoc>
+getTemplateArgsWritten(const ClassTemplateSpecializationDecl &D) {
+ if (const ASTTemplateArgumentListInfo *Args = D.getTemplateArgsAsWritten())
+ return Args->arguments();
+ return std::nullopt;
+}
+
+inline ArrayRef<TemplateArgumentLoc>
+getTemplateArgsWritten(const VarTemplateSpecializationDecl &D) {
+ if (const ASTTemplateArgumentListInfo *Args = D.getTemplateArgsAsWritten())
+ return Args->arguments();
+ return std::nullopt;
+}
+
+inline ArrayRef<TemplateArgumentLoc>
+getTemplateArgsWritten(const FunctionDecl &FD) {
+ if (const auto *Args = FD.getTemplateSpecializationArgsAsWritten())
+ return Args->arguments();
+ return std::nullopt;
+}
+
+inline ArrayRef<TemplateArgumentLoc>
+getTemplateArgsWritten(const DeclRefExpr &DRE) {
+ if (const auto *Args = DRE.getTemplateArgs())
+ return {Args, DRE.getNumTemplateArgs()};
+ return std::nullopt;
+}
+
+inline SmallVector<TemplateArgumentLoc>
+getTemplateArgsWritten(const TemplateSpecializationTypeLoc &T) {
+ SmallVector<TemplateArgumentLoc> Args;
+ if (!T.isNull()) {
+ Args.reserve(T.getNumArgs());
+ for (unsigned I = 0; I < T.getNumArgs(); ++I)
+ Args.emplace_back(T.getArgLoc(I));
+ }
+ return Args;
}
struct NotEqualsBoundNodePredicate {
diff --git a/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp b/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
index 541af34a9b3f21..af99c73f1945f6 100644
--- a/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
+++ b/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
@@ -6374,20 +6374,20 @@ TEST(HasAnyTemplateArgumentLoc, BindsToSpecializationWithDoubleArgument) {
}
TEST(HasAnyTemplateArgumentLoc, BindsToExplicitSpecializationWithIntArgument) {
- EXPECT_TRUE(
- matches("template<typename T> class A {}; template<> class A<int> {};",
- classTemplateSpecializationDecl(
- hasName("A"), hasAnyTemplateArgument(templateArgument(
- refersToType(asString("int")))))));
+ EXPECT_TRUE(matches(
+ "template<typename T> class A {}; template<> class A<int> {};",
+ classTemplateSpecializationDecl(
+ hasName("A"),
+ hasAnyTemplateArgumentLoc(hasTypeLoc(loc(asString("int")))))));
}
TEST(HasAnyTemplateArgumentLoc,
BindsToExplicitSpecializationWithDoubleArgument) {
- EXPECT_TRUE(
- matches("template<typename T> class A {}; template<> class A<double> {};",
- classTemplateSpecializationDecl(
- hasName("A"), hasAnyTemplateArgument(templateArgument(
- refersToType(asString("double")))))));
+ EXPECT_TRUE(matches(
+ "template<typename T> class A {}; template<> class A<double> {};",
+ classTemplateSpecializationDecl(
+ hasName("A"),
+ hasAnyTemplateArgumentLoc(hasTypeLoc(loc(asString("double")))))));
}
TEST(HasAnyTemplateArgumentLoc, BindsToSpecializationWithMultipleArguments) {
@@ -6397,30 +6397,29 @@ TEST(HasAnyTemplateArgumentLoc, BindsToSpecializationWithMultipleArguments) {
)";
EXPECT_TRUE(
matches(code, classTemplateSpecializationDecl(
- hasName("A"), hasAnyTemplateArgument(templateArgument(
- refersToType(asString("double")))))));
+ hasName("A"), hasAnyTemplateArgumentLoc(hasTypeLoc(
+ loc(asString("double")))))));
- EXPECT_TRUE(
- matches(code, classTemplateSpecializationDecl(
- hasName("A"), hasAnyTemplateArgument(templateArgument(
- refersToType(asString("int")))))));
+ EXPECT_TRUE(matches(
+ code, classTemplateSpecializationDecl(
+ hasName("A"),
+ hasAnyTemplateArgumentLoc(hasTypeLoc(loc(asString("int")))))));
}
TEST(HasAnyTemplateArgumentLoc, DoesNotBindToSpecializationWithIntArgument) {
- EXPECT_TRUE(
- notMatches("template<typename T> class A {}; A<int> a;",
- classTemplateSpecializationDecl(
- hasName("A"), hasAnyTemplateArgument(templateArgument(
- refersToType(asString("double")))))));
+ EXPECT_TRUE(notMatches("template<typename T> class A {}; A<int> a;",
+ classTemplateSpecializationDecl(
+ hasName("A"), hasAnyTemplateArgumentLoc(hasTypeLoc(
+ loc(asString("double")))))));
}
TEST(HasAnyTemplateArgumentLoc,
DoesNotBindToExplicitSpecializationWithIntArgument) {
- EXPECT_TRUE(
- notMatches("template<typename T> class A {}; template<> class A<int> {};",
- classTemplateSpecializationDecl(
- hasName("A"), hasAnyTemplateArgument(templateArgument(
- refersToType(asString("double")))))));
+ EXPECT_TRUE(notMatches(
+ "template<typename T> class A {}; template<> class A<int> {};",
+ classTemplateSpecializationDecl(
+ hasName("A"),
+ hasAnyTemplateArgumentLoc(hasTypeLoc(loc(asString("double")))))));
}
TEST(HasTemplateArgumentLoc, BindsToSpecializationWithIntArgument) {
@@ -6433,15 +6432,17 @@ TEST(HasTemplateArgumentLoc, BindsToSpecializationWithIntArgument) {
}
TEST(HasTemplateArgumentLoc, BindsToSpecializationWithDoubleArgument) {
- EXPECT_TRUE(matches("template<typename T> class A {}; A<double> a;",
- varDecl(hasName("a"),
- hasTypeLoc(elaboratedTypeLoc(hasNamedTypeLoc(
- templateSpecializationTypeLoc(hasTemplateArgumentLoc(
- 0, hasTypeLoc(loc(asString("double")))))))))));
+ EXPECT_TRUE(
+ matches("template<typename T> class A {}; A<double> a;",
+ varDecl(hasName("a"),
+ hasTypeLoc(elaboratedTypeLoc(hasNamedTypeLoc(
+ templateSpecializationTypeLoc(hasTemplateArgumentLoc(
+ 0, hasTypeLoc(loc(asString("double")))))))))));
}
TEST(HasTemplateArgumentLoc, DoesNotBindToSpecializationWithIntArgument) {
- EXPECT_TRUE(notMatches("template<typename T> class A {}; A<int> a;",
+ EXPECT_TRUE(notMatches(
+ "template<typename T> class A {}; A<int> a;",
varDecl(hasName("a"),
hasTypeLoc(elaboratedTypeLoc(hasNamedTypeLoc(
templateSpecializationTypeLoc(hasTemplateArgumentLoc(
@@ -6453,7 +6454,7 @@ TEST(HasTemplateArgumentLoc, BindsToExplicitSpecializationWithIntArgument) {
"template<typename T> class A {}; template<> class A<int> {};",
classTemplateSpecializationDecl(
hasName("A"),
- hasTemplateArgument(0, refersToType(asString("int"))))));
+ hasTemplateArgumentLoc(0, hasTypeLoc(loc(asString("int")))))));
}
TEST(HasTemplateArgumentLoc, BindsToExplicitSpecializationWithDoubleArgument) {
@@ -6461,8 +6462,7 @@ TEST(HasTemplateArgumentLoc, BindsToExplicitSpecializationWithDoubleArgument) {
"template<typename T> class A {}; template<> class A<double> {};",
classTemplateSpecializationDecl(
hasName("A"),
- hasTemplateArgument(
- 0, refersToType(asString("double"))))));
+ hasTemplateArgumentLoc(0, hasTypeLoc(loc(asString("double")))))));
}
TEST(HasTemplateArgumentLoc, BindsToSpecializationWithMultipleArguments) {
@@ -6472,14 +6472,12 @@ TEST(HasTemplateArgumentLoc, BindsToSpecializationWithMultipleArguments) {
)";
EXPECT_TRUE(matches(
code, classTemplateSpecializationDecl(
- hasName("A"),
- hasTemplateArgument(
- 0, refersToType(asString("double"))))));
+ hasName("A"), hasTemplateArgumentLoc(
+ 0, hasTypeLoc(loc(asString("double")))))));
EXPECT_TRUE(matches(
code, classTemplateSpecializationDecl(
hasName("A"),
- hasTemplateArgument(
- 1, refersToType(asString("int"))))));
+ hasTemplateArgumentLoc(1, hasTypeLoc(loc(asString("int")))))));
}
TEST(HasTemplateArgumentLoc,
@@ -6488,8 +6486,7 @@ TEST(HasTemplateArgumentLoc,
"template<typename T> class A {}; template<> class A<int> {};",
classTemplateSpecializationDecl(
hasName("A"),
- hasTemplateArgument(
- 0, refersToType(asString("double"))))));
+ hasTemplateArgumentLoc(0, hasTypeLoc(loc(asString("double")))))));
}
TEST(HasTemplateArgumentLoc,
@@ -6500,14 +6497,12 @@ TEST(HasTemplateArgumentLoc,
)";
EXPECT_TRUE(notMatches(
code, classTemplateSpecializationDecl(
- hasName("A"),
- hasTemplateArgument(
- 1, refersToType(asString("double"))))));
+ hasName("A"), hasTemplateArgumentLoc(
+ 1, hasTypeLoc(loc(asString("double")))))));
EXPECT_TRUE(notMatches(
code, classTemplateSpecializationDecl(
hasName("A"),
- hasTemplateArgument(
- 0, refersToType(asString("int"))))));
+ hasTemplateArgumentLoc(0, hasTypeLoc(loc(asString("int")))))));
}
TEST(HasTemplateArgumentLoc, DoesNotBindWithBadIndex) {
@@ -6517,14 +6512,12 @@ TEST(HasTemplateArgumentLoc, DoesNotBindWithBadIndex) {
)";
EXPECT_TRUE(notMatches(
code, classTemplateSpecializationDecl(
- hasName("A"),
- hasTemplateArgument(
- -1, refersToType(asString("double"))))));
+ hasName("A"), hasTemplateArgumentLoc(
+ -1, hasTypeLoc(loc(asString("double")))))));
EXPECT_TRUE(notMatches(
code, classTemplateSpecializationDecl(
- hasName("A"),
- hasTemplateArgument(
- 100, refersToType(asString("int"))))));
+ hasName("A"), hasTemplateArgumentLoc(
+ 100, hasTypeLoc(loc(asString("int")))))));
}
TEST(HasTemplateArgumentLoc, BindsToDeclRefExprWithIntArgument) {
More information about the cfe-commits
mailing list