[clang] [clang-tools-extra] [clang] NFC: use ArrayRef for getTemplateParameterLists (PR #194701)
Matheus Izvekov via cfe-commits
cfe-commits at lists.llvm.org
Tue Apr 28 11:48:24 PDT 2026
https://github.com/mizvekov updated https://github.com/llvm/llvm-project/pull/194701
>From 5ed245fd4f8d32078dd47b9c3ebca0af0e9edde3 Mon Sep 17 00:00:00 2001
From: Matheus Izvekov <mizvekov at gmail.com>
Date: Tue, 28 Apr 2026 12:58:27 -0300
Subject: [PATCH] [clang] NFC: use ArrayRef for getTemplateParameterLists
---
.../llvmlibc/InlineFunctionDeclCheck.cpp | 9 ++++---
.../clangd/SemanticHighlighting.cpp | 12 ++++------
clang/include/clang/AST/Decl.h | 24 ++++++++-----------
clang/include/clang/AST/RecursiveASTVisitor.h | 4 +---
clang/lib/AST/ASTImporter.cpp | 12 +++++-----
clang/lib/AST/Comment.cpp | 7 +++---
clang/lib/AST/Decl.cpp | 6 +++--
clang/lib/AST/DeclPrinter.cpp | 13 ++++------
clang/lib/AST/DeclTemplate.cpp | 4 ++--
clang/lib/Sema/SemaDecl.cpp | 5 ++--
clang/lib/Sema/SemaDeclCXX.cpp | 10 ++++----
.../lib/Sema/SemaTemplateInstantiateDecl.cpp | 17 ++++++-------
clang/lib/Tooling/Syntax/BuildTree.cpp | 6 ++---
clang/tools/libclang/CIndex.cpp | 14 ++++-------
clang/unittests/AST/ASTImporterTest.cpp | 4 ++--
15 files changed, 63 insertions(+), 84 deletions(-)
diff --git a/clang-tools-extra/clang-tidy/llvmlibc/InlineFunctionDeclCheck.cpp b/clang-tools-extra/clang-tidy/llvmlibc/InlineFunctionDeclCheck.cpp
index ddb3551bcc8f7..f00b07019d21e 100644
--- a/clang-tools-extra/clang-tidy/llvmlibc/InlineFunctionDeclCheck.cpp
+++ b/clang-tools-extra/clang-tidy/llvmlibc/InlineFunctionDeclCheck.cpp
@@ -22,12 +22,11 @@ getLastTemplateParameterList(const FunctionDecl *FuncDecl) {
FuncDecl->getDescribedTemplateParams();
if (!ReturnList) {
- const unsigned NumberOfTemplateParameterLists =
- FuncDecl->getNumTemplateParameterLists();
+ ArrayRef<TemplateParameterList *> TPLs =
+ FuncDecl->getTemplateParameterLists();
- if (NumberOfTemplateParameterLists > 0)
- ReturnList = FuncDecl->getTemplateParameterList(
- NumberOfTemplateParameterLists - 1);
+ if (!TPLs.empty())
+ ReturnList = TPLs.back();
}
return ReturnList;
diff --git a/clang-tools-extra/clangd/SemanticHighlighting.cpp b/clang-tools-extra/clangd/SemanticHighlighting.cpp
index 79446a166d0d8..751ee254d3623 100644
--- a/clang-tools-extra/clangd/SemanticHighlighting.cpp
+++ b/clang-tools-extra/clangd/SemanticHighlighting.cpp
@@ -583,10 +583,8 @@ class CollectExtraHighlightings
}
bool VisitTagDecl(TagDecl *D) {
- for (unsigned i = 0; i < D->getNumTemplateParameterLists(); ++i) {
- if (auto *TPL = D->getTemplateParameterList(i))
- H.addAngleBracketTokens(TPL->getLAngleLoc(), TPL->getRAngleLoc());
- }
+ for (TemplateParameterList *TPL : D->getTemplateParameterLists())
+ H.addAngleBracketTokens(TPL->getLAngleLoc(), TPL->getRAngleLoc());
return true;
}
@@ -824,10 +822,8 @@ class CollectExtraHighlightings
}
bool VisitDeclaratorDecl(DeclaratorDecl *D) {
- for (unsigned i = 0; i < D->getNumTemplateParameterLists(); ++i) {
- if (auto *TPL = D->getTemplateParameterList(i))
- H.addAngleBracketTokens(TPL->getLAngleLoc(), TPL->getRAngleLoc());
- }
+ for (TemplateParameterList *TPL : D->getTemplateParameterLists())
+ H.addAngleBracketTokens(TPL->getLAngleLoc(), TPL->getRAngleLoc());
auto *AT = D->getType()->getContainedAutoType();
if (!AT)
return true;
diff --git a/clang/include/clang/AST/Decl.h b/clang/include/clang/AST/Decl.h
index e45a6dae56d9b..3d1d298479d90 100644
--- a/clang/include/clang/AST/Decl.h
+++ b/clang/include/clang/AST/Decl.h
@@ -859,13 +859,11 @@ class DeclaratorDecl : public ValueDecl {
void setTrailingRequiresClause(const AssociatedConstraint &AC);
- unsigned getNumTemplateParameterLists() const {
- return hasExtInfo() ? getExtInfo()->NumTemplParamLists : 0;
- }
-
- TemplateParameterList *getTemplateParameterList(unsigned index) const {
- assert(index < getNumTemplateParameterLists());
- return getExtInfo()->TemplParamLists[index];
+ ArrayRef<TemplateParameterList *> getTemplateParameterLists() const {
+ if (!hasExtInfo())
+ return {};
+ return {/*data=*/getExtInfo()->TemplParamLists,
+ /*length=*/getExtInfo()->NumTemplParamLists};
}
void setTemplateParameterListsInfo(ASTContext &Context,
@@ -3990,13 +3988,11 @@ class TagDecl : public TypeDecl,
void setQualifierInfo(NestedNameSpecifierLoc QualifierLoc);
- unsigned getNumTemplateParameterLists() const {
- return hasExtInfo() ? getExtInfo()->NumTemplParamLists : 0;
- }
-
- TemplateParameterList *getTemplateParameterList(unsigned i) const {
- assert(i < getNumTemplateParameterLists());
- return getExtInfo()->TemplParamLists[i];
+ ArrayRef<TemplateParameterList *> getTemplateParameterLists() const {
+ if (!hasExtInfo())
+ return {};
+ return {/*data=*/getExtInfo()->TemplParamLists,
+ /*length=*/getExtInfo()->NumTemplParamLists};
}
// These types are created lazily, use the ASTContext methods to obtain them.
diff --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h
index 8b1a7bae94d46..b5be0910194bd 100644
--- a/clang/include/clang/AST/RecursiveASTVisitor.h
+++ b/clang/include/clang/AST/RecursiveASTVisitor.h
@@ -1976,10 +1976,8 @@ bool RecursiveASTVisitor<Derived>::TraverseTemplateParameterListHelper(
template <typename Derived>
template <typename T>
bool RecursiveASTVisitor<Derived>::TraverseDeclTemplateParameterLists(T *D) {
- for (unsigned i = 0; i < D->getNumTemplateParameterLists(); i++) {
- TemplateParameterList *TPL = D->getTemplateParameterList(i);
+ for (TemplateParameterList *TPL : D->getTemplateParameterLists())
TraverseTemplateParameterListHelper(TPL);
- }
return true;
}
diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp
index 41ba98c53247d..4c8cc31421200 100644
--- a/clang/lib/AST/ASTImporter.cpp
+++ b/clang/lib/AST/ASTImporter.cpp
@@ -3579,13 +3579,13 @@ ExpectedDecl ASTNodeImporter::VisitEnumConstantDecl(EnumConstantDecl *D) {
template <typename DeclTy>
Error ASTNodeImporter::ImportTemplateParameterLists(const DeclTy *FromD,
DeclTy *ToD) {
- unsigned int Num = FromD->getNumTemplateParameterLists();
- if (Num == 0)
+ ArrayRef<TemplateParameterList *> FromTPLs =
+ FromD->getTemplateParameterLists();
+ if (FromTPLs.empty())
return Error::success();
- SmallVector<TemplateParameterList *, 2> ToTPLists(Num);
- for (unsigned int I = 0; I < Num; ++I)
- if (Expected<TemplateParameterList *> ToTPListOrErr =
- import(FromD->getTemplateParameterList(I)))
+ SmallVector<TemplateParameterList *, 2> ToTPLists(FromTPLs.size());
+ for (unsigned int I = 0; I < FromTPLs.size(); ++I)
+ if (Expected<TemplateParameterList *> ToTPListOrErr = import(FromTPLs[I]))
ToTPLists[I] = *ToTPListOrErr;
else
return ToTPListOrErr.takeError();
diff --git a/clang/lib/AST/Comment.cpp b/clang/lib/AST/Comment.cpp
index 361a8a7e68990..3ea7288231c97 100644
--- a/clang/lib/AST/Comment.cpp
+++ b/clang/lib/AST/Comment.cpp
@@ -233,11 +233,10 @@ void DeclInfo::fill() {
Kind = FunctionKind;
ParamVars = FD->parameters();
ReturnType = FD->getReturnType();
- unsigned NumLists = FD->getNumTemplateParameterLists();
- if (NumLists != 0) {
+ ArrayRef<TemplateParameterList *> TPLs = FD->getTemplateParameterLists();
+ if (!TPLs.empty()) {
TemplateKind = TemplateSpecialization;
- TemplateParameters =
- FD->getTemplateParameterList(NumLists - 1);
+ TemplateParameters = TPLs.back();
}
if (K == Decl::CXXMethod || K == Decl::CXXConstructor ||
diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp
index 14b3af1d9e66c..a7722aa0be3a4 100644
--- a/clang/lib/AST/Decl.cpp
+++ b/clang/lib/AST/Decl.cpp
@@ -1993,8 +1993,10 @@ bool NamedDecl::isCXXInstanceMember() const {
template <typename DeclT>
static SourceLocation getTemplateOrInnerLocStart(const DeclT *decl) {
- if (decl->getNumTemplateParameterLists() > 0)
- return decl->getTemplateParameterList(0)->getTemplateLoc();
+ if (ArrayRef<TemplateParameterList *> TPLs =
+ decl->getTemplateParameterLists();
+ !TPLs.empty())
+ return TPLs.front()->getTemplateLoc();
return decl->getInnerLocStart();
}
diff --git a/clang/lib/AST/DeclPrinter.cpp b/clang/lib/AST/DeclPrinter.cpp
index d215202aa7deb..7e4c1100dbe32 100644
--- a/clang/lib/AST/DeclPrinter.cpp
+++ b/clang/lib/AST/DeclPrinter.cpp
@@ -680,9 +680,8 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
if (D->isFunctionTemplateSpecialization())
Out << "template<> ";
else if (!D->getDescribedFunctionTemplate()) {
- for (unsigned I = 0, NumTemplateParams = D->getNumTemplateParameterLists();
- I < NumTemplateParams; ++I)
- printTemplateParameters(D->getTemplateParameterList(I));
+ for (TemplateParameterList *TPL : D->getTemplateParameterLists())
+ printTemplateParameters(TPL);
}
CXXConstructorDecl *CDecl = dyn_cast<CXXConstructorDecl>(D);
@@ -1291,11 +1290,9 @@ void DeclPrinter::VisitTemplateDecl(const TemplateDecl *D) {
void DeclPrinter::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
prettyPrintPragmas(D->getTemplatedDecl());
// Print any leading template parameter lists.
- if (const FunctionDecl *FD = D->getTemplatedDecl()) {
- for (unsigned I = 0, NumTemplateParams = FD->getNumTemplateParameterLists();
- I < NumTemplateParams; ++I)
- printTemplateParameters(FD->getTemplateParameterList(I));
- }
+ if (const FunctionDecl *FD = D->getTemplatedDecl())
+ for (TemplateParameterList *TPL : FD->getTemplateParameterLists())
+ printTemplateParameters(TPL);
VisitRedeclarableTemplateDecl(D);
// Declare target attribute is special one, natural spelling for the pragma
// assumes "ending" construct so print it here.
diff --git a/clang/lib/AST/DeclTemplate.cpp b/clang/lib/AST/DeclTemplate.cpp
index 6567c8fa4d783..f5d3c7b6f1c33 100644
--- a/clang/lib/AST/DeclTemplate.cpp
+++ b/clang/lib/AST/DeclTemplate.cpp
@@ -1218,7 +1218,7 @@ SourceRange ClassTemplatePartialSpecializationDecl::getSourceRange() const {
return MT->getSourceRange();
SourceRange Range = ClassTemplateSpecializationDecl::getSourceRange();
if (const TemplateParameterList *TPL = getTemplateParameters();
- TPL && !getNumTemplateParameterLists())
+ TPL && getTemplateParameterLists().empty())
Range.setBegin(TPL->getTemplateLoc());
return Range;
}
@@ -1571,7 +1571,7 @@ SourceRange VarTemplatePartialSpecializationDecl::getSourceRange() const {
return MT->getSourceRange();
SourceRange Range = VarTemplateSpecializationDecl::getSourceRange();
if (const TemplateParameterList *TPL = getTemplateParameters();
- TPL && !getNumTemplateParameterLists())
+ TPL && getTemplateParameterLists().empty())
Range.setBegin(TPL->getTemplateLoc());
return Range;
}
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 36538e18f297c..22e85e213c5db 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -4996,7 +4996,8 @@ bool Sema::checkVarDeclRedefinition(VarDecl *Old, VarDecl *New) {
if (!hasVisibleDefinition(Old) &&
(New->getFormalLinkage() == Linkage::Internal || New->isInline() ||
isa<VarTemplateSpecializationDecl>(New) ||
- New->getDescribedVarTemplate() || New->getNumTemplateParameterLists() ||
+ New->getDescribedVarTemplate() ||
+ !New->getTemplateParameterLists().empty() ||
New->getDeclContext()->isDependentContext() ||
New->hasAttr<SelectAnyAttr>())) {
// The previous definition is hidden, and multiple definitions are
@@ -16157,7 +16158,7 @@ Sema::CheckForFunctionRedefinition(FunctionDecl *FD,
if (SkipBody && isRedefinitionAllowedFor(Definition, DefinitionVisible) &&
(Definition->getFormalLinkage() == Linkage::Internal ||
Definition->isInlined() || Definition->getDescribedFunctionTemplate() ||
- Definition->getNumTemplateParameterLists())) {
+ !Definition->getTemplateParameterLists().empty())) {
SkipBody->ShouldSkip = true;
SkipBody->Previous = const_cast<FunctionDecl*>(Definition);
if (!DefinitionVisible) {
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 90919d48f0d15..159afdacdd110 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -10979,8 +10979,8 @@ Sema::ActOnReenterTemplateScope(Decl *D,
DeclContext *LookupDC = dyn_cast<DeclContext>(D);
if (DeclaratorDecl *DD = dyn_cast<DeclaratorDecl>(D)) {
- for (unsigned i = 0; i < DD->getNumTemplateParameterLists(); ++i)
- ParameterLists.push_back(DD->getTemplateParameterList(i));
+ for (TemplateParameterList *TPL : DD->getTemplateParameterLists())
+ ParameterLists.push_back(TPL);
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
if (FunctionTemplateDecl *FTD = FD->getDescribedFunctionTemplate())
@@ -10994,8 +10994,8 @@ Sema::ActOnReenterTemplateScope(Decl *D,
ParameterLists.push_back(PSD->getTemplateParameters());
}
} else if (TagDecl *TD = dyn_cast<TagDecl>(D)) {
- for (unsigned i = 0; i < TD->getNumTemplateParameterLists(); ++i)
- ParameterLists.push_back(TD->getTemplateParameterList(i));
+ for (TemplateParameterList *TPL : TD->getTemplateParameterLists())
+ ParameterLists.push_back(TPL);
if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(TD)) {
if (ClassTemplateDecl *CTD = RD->getDescribedClassTemplate())
@@ -18613,7 +18613,7 @@ NamedDecl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D,
}
// Mark templated-scope function declarations as unsupported.
- if (FD->getNumTemplateParameterLists() && SS.isValid()) {
+ if (!FD->getTemplateParameterLists().empty() && SS.isValid()) {
Diag(FD->getLocation(), diag::warn_template_qualified_friend_unsupported)
<< SS.getScopeRep() << SS.getRange()
<< cast<CXXRecordDecl>(CurContext);
diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 821844251d832..c5b192373b358 100644
--- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -3149,12 +3149,11 @@ Decl *TemplateDeclInstantiator::VisitCXXMethodDecl(
// Instantiate enclosing template arguments for friends.
SmallVector<TemplateParameterList *, 4> TempParamLists;
- unsigned NumTempParamLists = 0;
- if (isFriend && (NumTempParamLists = D->getNumTemplateParameterLists())) {
- TempParamLists.resize(NumTempParamLists);
- for (unsigned I = 0; I != NumTempParamLists; ++I) {
- TemplateParameterList *TempParams = D->getTemplateParameterList(I);
- TemplateParameterList *InstParams = SubstTemplateParams(TempParams);
+ ArrayRef<TemplateParameterList *> TPLs = D->getTemplateParameterLists();
+ if (isFriend && !TPLs.empty()) {
+ TempParamLists.resize(TPLs.size());
+ for (unsigned I = 0; I != TPLs.size(); ++I) {
+ TemplateParameterList *InstParams = SubstTemplateParams(TPLs[I]);
if (!InstParams)
return nullptr;
TempParamLists[I] = InstParams;
@@ -3333,10 +3332,8 @@ Decl *TemplateDeclInstantiator::VisitCXXMethodDecl(
// out-of-line, the instantiation will have the same lexical
// context (which will be a namespace scope) as the template.
if (isFriend) {
- if (NumTempParamLists)
- Method->setTemplateParameterListsInfo(
- SemaRef.Context,
- llvm::ArrayRef(TempParamLists.data(), NumTempParamLists));
+ if (!TempParamLists.empty())
+ Method->setTemplateParameterListsInfo(SemaRef.Context, TempParamLists);
Method->setLexicalDeclContext(Owner);
Method->setObjectOfFriendDecl();
diff --git a/clang/lib/Tooling/Syntax/BuildTree.cpp b/clang/lib/Tooling/Syntax/BuildTree.cpp
index 4fd5c009353fa..3d3acea89d170 100644
--- a/clang/lib/Tooling/Syntax/BuildTree.cpp
+++ b/clang/lib/Tooling/Syntax/BuildTree.cpp
@@ -756,7 +756,7 @@ class BuildTreeVisitor : public RecursiveASTVisitor<BuildTreeVisitor> {
bool WalkUpFromTagDecl(TagDecl *C) {
// FIXME: build the ClassSpecifier node.
if (!C->isFreeStanding()) {
- assert(C->getNumTemplateParameterLists() == 0);
+ assert(C->getTemplateParameterLists().empty());
return true;
}
handleFreeStandingTagDecl(C);
@@ -780,8 +780,8 @@ class BuildTreeVisitor : public RecursiveASTVisitor<BuildTreeVisitor> {
};
if (auto *S = dyn_cast<ClassTemplatePartialSpecializationDecl>(C))
ConsumeTemplateParameters(*S->getTemplateParameters());
- for (unsigned I = C->getNumTemplateParameterLists(); 0 < I; --I)
- ConsumeTemplateParameters(*C->getTemplateParameterList(I - 1));
+ for (TemplateParameterList *TPL : C->getTemplateParameterLists())
+ ConsumeTemplateParameters(*TPL);
return Result;
}
diff --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp
index 207bb86c6052e..350cd2135657d 100644
--- a/clang/tools/libclang/CIndex.cpp
+++ b/clang/tools/libclang/CIndex.cpp
@@ -792,12 +792,9 @@ bool CursorVisitor::VisitEnumConstantDecl(EnumConstantDecl *D) {
}
bool CursorVisitor::VisitDeclaratorDecl(DeclaratorDecl *DD) {
- unsigned NumParamList = DD->getNumTemplateParameterLists();
- for (unsigned i = 0; i < NumParamList; i++) {
- TemplateParameterList *Params = DD->getTemplateParameterList(i);
- if (VisitTemplateParameters(Params))
+ for (TemplateParameterList *TPL : DD->getTemplateParameterLists())
+ if (VisitTemplateParameters(TPL))
return true;
- }
if (TypeSourceInfo *TSInfo = DD->getTypeSourceInfo())
if (Visit(TSInfo->getTypeLoc()))
@@ -828,12 +825,9 @@ static int CompareCXXCtorInitializers(CXXCtorInitializer *const *X,
}
bool CursorVisitor::VisitFunctionDecl(FunctionDecl *ND) {
- unsigned NumParamList = ND->getNumTemplateParameterLists();
- for (unsigned i = 0; i < NumParamList; i++) {
- TemplateParameterList *Params = ND->getTemplateParameterList(i);
- if (VisitTemplateParameters(Params))
+ for (TemplateParameterList *TPL : ND->getTemplateParameterLists())
+ if (VisitTemplateParameters(TPL))
return true;
- }
if (TypeSourceInfo *TSInfo = ND->getTypeSourceInfo()) {
// Visit the function declaration's syntactic components in the order
diff --git a/clang/unittests/AST/ASTImporterTest.cpp b/clang/unittests/AST/ASTImporterTest.cpp
index d1d6ea94d3154..f96f2a8429b89 100644
--- a/clang/unittests/AST/ASTImporterTest.cpp
+++ b/clang/unittests/AST/ASTImporterTest.cpp
@@ -5253,11 +5253,11 @@ TEST_P(ASTImporterOptionSpecificTestBase, ImportTemplateParameterLists) {
Decl *FromTU = getTuDecl(Code, Lang_CXX03);
auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU,
functionDecl(hasName("f"), isExplicitTemplateSpecialization()));
- ASSERT_EQ(FromD->getNumTemplateParameterLists(), 1u);
+ ASSERT_EQ(FromD->getTemplateParameterLists().size(), 1u);
auto *ToD = Import(FromD, Lang_CXX03);
// The template parameter list should exist.
- EXPECT_EQ(ToD->getNumTemplateParameterLists(), 1u);
+ EXPECT_EQ(ToD->getTemplateParameterLists().size(), 1u);
}
const internal::VariadicDynCastAllOfMatcher<Decl, VarTemplateDecl>
More information about the cfe-commits
mailing list