[clang] [clang-tools-extra] [clang] Initialize pattern TypeLoc of PackIndexingTypeLoc (PR #231191)
via cfe-commits
cfe-commits at lists.llvm.org
Thu Oct 15 05:00:41 PDT 2026
https://github.com/max-winkler updated https://github.com/llvm/llvm-project/pull/231191
>From a09b9aa7c5b07677a62dd405fbe4931ac254877f Mon Sep 17 00:00:00 2001
From: Max Winkler <max.winkler at mathematik.tu-chemnitz.de>
Date: Mon, 12 Oct 2026 14:15:12 +0200
Subject: [PATCH 1/3] [clang] Initialize pattern TypeLoc of PackIndexingTypeLoc
For a pack indexing type like 'T...[0] x', the TypeLoc of the pattern was
never initialized, so it carried no valid source location. This caused
clangd's go-to-definition on 'T' to jump to the variable declaration
instead of the template parameter 'T'.
Initialize the pattern TypeLoc when Sema visits a PackIndexingTypeLoc, and
make RecursiveASTVisitor traverse the pattern via its TypeLoc instead of
its Type. A clangd test is added in TargetDeclTest.PackIndexing.
Fixes clangd/clangd#2713
Assisted-by: Claude
---
clang-tools-extra/clangd/unittests/FindTargetTests.cpp | 9 +++++++++
clang/include/clang/AST/RecursiveASTVisitor.h | 2 +-
clang/lib/Sema/SemaType.cpp | 1 +
3 files changed, 11 insertions(+), 1 deletion(-)
diff --git a/clang-tools-extra/clangd/unittests/FindTargetTests.cpp b/clang-tools-extra/clangd/unittests/FindTargetTests.cpp
index cd57eb7d912b8b..388dfe7a0e7aac 100644
--- a/clang-tools-extra/clangd/unittests/FindTargetTests.cpp
+++ b/clang-tools-extra/clangd/unittests/FindTargetTests.cpp
@@ -691,6 +691,15 @@ TEST_F(TargetDeclTest, PackIndexing) {
)cpp";
EXPECT_DECLS("TemplateSpecializationTypeLoc",
"template <typename> class ...X");
+
+ Code = R"cpp(
+ // Indexed type template parameter pack
+ template <typename... X>
+ void foo() {
+ [[X]]...[0] x;
+ }
+ )cpp";
+ EXPECT_DECLS("TemplateTypeParmTypeLoc", "typename ...X");
}
TEST_F(TargetDeclTest, PackIndexedConcept) {
diff --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h
index f144c890f6ee65..13dd5eda84fa65 100644
--- a/clang/include/clang/AST/RecursiveASTVisitor.h
+++ b/clang/include/clang/AST/RecursiveASTVisitor.h
@@ -1469,7 +1469,7 @@ DEF_TRAVERSE_TYPELOC(DecltypeType, {
})
DEF_TRAVERSE_TYPELOC(PackIndexingType, {
- TRY_TO(TraverseType(TL.getPattern()));
+ TRY_TO(TraverseTypeLoc(TL.getPatternLoc()));
TRY_TO(TraverseStmt(TL.getTypePtr()->getIndexExpr()));
})
diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp
index 1cb96b556971ad..46494105ea55d2 100644
--- a/clang/lib/Sema/SemaType.cpp
+++ b/clang/lib/Sema/SemaType.cpp
@@ -6122,6 +6122,7 @@ namespace {
void VisitPackIndexingTypeLoc(PackIndexingTypeLoc TL) {
assert(DS.getTypeSpecType() == DeclSpec::TST_typename_pack_indexing);
TL.setEllipsisLoc(DS.getEllipsisLoc());
+ TL.getPatternLoc().initialize(Context, DS.getTypeSpecTypeLoc());
}
void VisitUnaryTransformTypeLoc(UnaryTransformTypeLoc TL) {
assert(DS.isTransformTypeTrait(DS.getTypeSpecType()));
>From 73b2b038f9fa508e64cd84268566dbcf96bf86bd Mon Sep 17 00:00:00 2001
From: Max Winkler <max.winkler at mathematik.tu-chemnitz.de>
Date: Wed, 14 Oct 2026 11:15:01 +0200
Subject: [PATCH 2/3] [clang] Add PackIndexingTypeLoc tests and FIXME for
ellipsis
Adds RecursiveASTVisitorTests for type locations of pack indexing types
in variable declaration (T...[0] x) and alias definition (using U = T...[0]).
Tests fail without changes in SemaType.cpp and RecursiveASTVisitor.h.
Adds Lang_CXX26 entry in TestVisitor.h to run the test with -std=c++26.
Adds FIXME comment in TypeSpecLocFiller::VisitPackIndexingTypeLoc noting
an invalid EllipsisLoc which is dropped by the parser when annotating
the type.
Assisted-by: Claude
---
clang/lib/Sema/SemaType.cpp | 5 ++
clang/unittests/Tooling/CMakeLists.txt | 1 +
.../PackIndexingTypeLoc.cpp | 48 +++++++++++++++++++
clang/unittests/Tooling/TestVisitor.h | 4 ++
4 files changed, 58 insertions(+)
create mode 100644 clang/unittests/Tooling/RecursiveASTVisitorTests/PackIndexingTypeLoc.cpp
diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp
index 46494105ea55d2..742fb853ce8615 100644
--- a/clang/lib/Sema/SemaType.cpp
+++ b/clang/lib/Sema/SemaType.cpp
@@ -6121,6 +6121,11 @@ namespace {
}
void VisitPackIndexingTypeLoc(PackIndexingTypeLoc TL) {
assert(DS.getTypeSpecType() == DeclSpec::TST_typename_pack_indexing);
+ // FIXME: The location of the ellipsis is not recorded here. The parser
+ // knows it when it first parses the pack indexing type, but it is dropped
+ // when the type is annotated (see
+ // Parser::AnnotateExistingIndexedTypeNamePack), so DS.getEllipsisLoc()
+ // is invalid when this runs.
TL.setEllipsisLoc(DS.getEllipsisLoc());
TL.getPatternLoc().initialize(Context, DS.getTypeSpecTypeLoc());
}
diff --git a/clang/unittests/Tooling/CMakeLists.txt b/clang/unittests/Tooling/CMakeLists.txt
index 4de300fa86385f..44373a57fcf53e 100644
--- a/clang/unittests/Tooling/CMakeLists.txt
+++ b/clang/unittests/Tooling/CMakeLists.txt
@@ -43,6 +43,7 @@ add_clang_unittest(ToolingTests
RecursiveASTVisitorTests/MemberPointerTypeLoc.cpp
RecursiveASTVisitorTests/NestedNameSpecifiers.cpp
RecursiveASTVisitorTests/OffsetOfExpr.cpp
+ RecursiveASTVisitorTests/PackIndexingTypeLoc.cpp
RecursiveASTVisitorTests/ParenExpr.cpp
RecursiveASTVisitorTests/TemplateArgumentLocTraverser.cpp
RecursiveASTVisitorTests/TraversalScope.cpp
diff --git a/clang/unittests/Tooling/RecursiveASTVisitorTests/PackIndexingTypeLoc.cpp b/clang/unittests/Tooling/RecursiveASTVisitorTests/PackIndexingTypeLoc.cpp
new file mode 100644
index 00000000000000..65072ddc3f74db
--- /dev/null
+++ b/clang/unittests/Tooling/RecursiveASTVisitorTests/PackIndexingTypeLoc.cpp
@@ -0,0 +1,48 @@
+//===- unittest/Tooling/RecursiveASTVisitorTests/PackIndexingTypeLoc.cpp --===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "TestVisitor.h"
+
+using namespace clang;
+
+namespace {
+
+class PackIndexingTypeLocVisitor : public ExpectedLocationVisitor {
+public:
+ bool VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc TL) override {
+ if (!TL)
+ return true;
+ Match(TL.getDecl()->getName(), TL.getNameLoc());
+ return true;
+ }
+};
+
+TEST(RecursiveASTVisitor, VisitTypeLocInPackIndexingType) {
+ PackIndexingTypeLocVisitor Visitor;
+ Visitor.ExpectMatch("T", 4, 8);
+ llvm::StringLiteral Code = R"cpp(
+ template <typename... T>
+ void foo() {
+ T...[0] x;
+ }
+ )cpp";
+ EXPECT_TRUE(Visitor.runOver(Code, PackIndexingTypeLocVisitor::Lang_CXX26));
+}
+
+TEST(RecursiveASTVisitor, VisitTypeLocInPackIndexingTypeAlias) {
+ PackIndexingTypeLocVisitor Visitor;
+ Visitor.ExpectMatch("T", 4, 18);
+ llvm::StringLiteral Code = R"cpp(
+ template <typename... T>
+ void foo() {
+ using U = T...[0];
+ }
+ )cpp";
+ EXPECT_TRUE(Visitor.runOver(Code, PackIndexingTypeLocVisitor::Lang_CXX26));
+}
+} // end anonymous namespace
diff --git a/clang/unittests/Tooling/TestVisitor.h b/clang/unittests/Tooling/TestVisitor.h
index fdf57a946a6e2d..f6fe58bc9c4411 100644
--- a/clang/unittests/Tooling/TestVisitor.h
+++ b/clang/unittests/Tooling/TestVisitor.h
@@ -36,6 +36,7 @@ class TestVisitorHelper {
Lang_CXX14,
Lang_CXX17,
Lang_CXX2a,
+ Lang_CXX26,
Lang_OBJC,
Lang_OBJCXX11,
Lang_CXX = Lang_CXX98
@@ -64,6 +65,9 @@ class TestVisitorHelper {
case Lang_CXX2a:
Args.push_back("-std=c++2a");
break;
+ case Lang_CXX26:
+ Args.push_back("-std=c++26");
+ break;
case Lang_OBJC:
Args.push_back("-ObjC");
Args.push_back("-fobjc-runtime=macosx-10.12.0");
>From 5d4a6fa9c9499d434c541def0be0313d22cba697 Mon Sep 17 00:00:00 2001
From: Max Winkler <max.winkler at mathematik.tu-chemnitz.de>
Date: Thu, 15 Oct 2026 13:59:31 +0200
Subject: [PATCH 3/3] Moved PackIndexingType traversal tests to
SourceLocationTest.
---
clang/unittests/AST/SourceLocationTest.cpp | 20 ++++++++
clang/unittests/Tooling/CMakeLists.txt | 1 -
.../PackIndexingTypeLoc.cpp | 48 -------------------
clang/unittests/Tooling/TestVisitor.h | 4 --
4 files changed, 20 insertions(+), 53 deletions(-)
delete mode 100644 clang/unittests/Tooling/RecursiveASTVisitorTests/PackIndexingTypeLoc.cpp
diff --git a/clang/unittests/AST/SourceLocationTest.cpp b/clang/unittests/AST/SourceLocationTest.cpp
index 06993a0270300d..4cc3c7aae9829d 100644
--- a/clang/unittests/AST/SourceLocationTest.cpp
+++ b/clang/unittests/AST/SourceLocationTest.cpp
@@ -1111,6 +1111,26 @@ TEST(PackIndexingTypeLoc, PatternAndEllipsisLoc) {
typeLoc(hasParent(varDecl(hasName("x")))), Lang_CXX26));
}
+TEST(PackIndexingTypeLoc, PatternIsTraversed) {
+ RangeVerifier<TypeLoc> Verifier;
+ Verifier.expectRange(2, 8, 2, 8);
+ EXPECT_TRUE(Verifier.match(
+ R"cpp(template <class... T> void foo() {
+ T...[0] x;
+ })cpp",
+ typeLoc(loc(templateTypeParmType())), Lang_CXX26));
+}
+
+TEST(PackIndexingTypeLoc, PatternIsTraversedInAlias) {
+ RangeVerifier<TypeLoc> Verifier;
+ Verifier.expectRange(2, 18, 2, 18);
+ EXPECT_TRUE(Verifier.match(
+ R"cpp(template <class... T> void foo() {
+ using U = T...[0];
+ })cpp",
+ typeLoc(loc(templateTypeParmType())), Lang_CXX26));
+}
+
class ConceptSpecializationExprConceptReferenceRangeVerifier
: public RangeVerifier<VarTemplateDecl> {
protected:
diff --git a/clang/unittests/Tooling/CMakeLists.txt b/clang/unittests/Tooling/CMakeLists.txt
index 44373a57fcf53e..4de300fa86385f 100644
--- a/clang/unittests/Tooling/CMakeLists.txt
+++ b/clang/unittests/Tooling/CMakeLists.txt
@@ -43,7 +43,6 @@ add_clang_unittest(ToolingTests
RecursiveASTVisitorTests/MemberPointerTypeLoc.cpp
RecursiveASTVisitorTests/NestedNameSpecifiers.cpp
RecursiveASTVisitorTests/OffsetOfExpr.cpp
- RecursiveASTVisitorTests/PackIndexingTypeLoc.cpp
RecursiveASTVisitorTests/ParenExpr.cpp
RecursiveASTVisitorTests/TemplateArgumentLocTraverser.cpp
RecursiveASTVisitorTests/TraversalScope.cpp
diff --git a/clang/unittests/Tooling/RecursiveASTVisitorTests/PackIndexingTypeLoc.cpp b/clang/unittests/Tooling/RecursiveASTVisitorTests/PackIndexingTypeLoc.cpp
deleted file mode 100644
index 65072ddc3f74db..00000000000000
--- a/clang/unittests/Tooling/RecursiveASTVisitorTests/PackIndexingTypeLoc.cpp
+++ /dev/null
@@ -1,48 +0,0 @@
-//===- unittest/Tooling/RecursiveASTVisitorTests/PackIndexingTypeLoc.cpp --===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "TestVisitor.h"
-
-using namespace clang;
-
-namespace {
-
-class PackIndexingTypeLocVisitor : public ExpectedLocationVisitor {
-public:
- bool VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc TL) override {
- if (!TL)
- return true;
- Match(TL.getDecl()->getName(), TL.getNameLoc());
- return true;
- }
-};
-
-TEST(RecursiveASTVisitor, VisitTypeLocInPackIndexingType) {
- PackIndexingTypeLocVisitor Visitor;
- Visitor.ExpectMatch("T", 4, 8);
- llvm::StringLiteral Code = R"cpp(
- template <typename... T>
- void foo() {
- T...[0] x;
- }
- )cpp";
- EXPECT_TRUE(Visitor.runOver(Code, PackIndexingTypeLocVisitor::Lang_CXX26));
-}
-
-TEST(RecursiveASTVisitor, VisitTypeLocInPackIndexingTypeAlias) {
- PackIndexingTypeLocVisitor Visitor;
- Visitor.ExpectMatch("T", 4, 18);
- llvm::StringLiteral Code = R"cpp(
- template <typename... T>
- void foo() {
- using U = T...[0];
- }
- )cpp";
- EXPECT_TRUE(Visitor.runOver(Code, PackIndexingTypeLocVisitor::Lang_CXX26));
-}
-} // end anonymous namespace
diff --git a/clang/unittests/Tooling/TestVisitor.h b/clang/unittests/Tooling/TestVisitor.h
index f6fe58bc9c4411..fdf57a946a6e2d 100644
--- a/clang/unittests/Tooling/TestVisitor.h
+++ b/clang/unittests/Tooling/TestVisitor.h
@@ -36,7 +36,6 @@ class TestVisitorHelper {
Lang_CXX14,
Lang_CXX17,
Lang_CXX2a,
- Lang_CXX26,
Lang_OBJC,
Lang_OBJCXX11,
Lang_CXX = Lang_CXX98
@@ -65,9 +64,6 @@ class TestVisitorHelper {
case Lang_CXX2a:
Args.push_back("-std=c++2a");
break;
- case Lang_CXX26:
- Args.push_back("-std=c++26");
- break;
case Lang_OBJC:
Args.push_back("-ObjC");
Args.push_back("-fobjc-runtime=macosx-10.12.0");
More information about the cfe-commits
mailing list