[clang] [Clang] Improve error recovery for indexed template names (PR #222328)

Corentin Jabot via cfe-commits cfe-commits at lists.llvm.org
Wed Sep 9 06:03:59 PDT 2026


https://github.com/cor3ntin created https://github.com/llvm/llvm-project/pull/222328

There were a few issues here:
 - Names that are not templates were not diagnosed and led to a crash (in part because clang think they can be template names that will be later resolved by ADL)
 - Names that refer to a variable template decl, etc also led to a crash.

Fixes #220502

>From 72df3adf241326b150e6d38d343512c0de3dd925 Mon Sep 17 00:00:00 2001
From: Corentin Jabot <corentinjabot at gmail.com>
Date: Wed, 9 Sep 2026 14:41:45 +0200
Subject: [PATCH] [Clang] Improve error recovery for indexed template names

There were a few issues here:
 - Names that are not templates were not diagnosed and led to a crash
(in part because clang think they can be template names that will be later resolved by ADL)
 - Names that refer to a variable template decl, etc also led to a crash.

Fixes #220502

Co-authored-by: Cursor <cursoragent at cursor.com>
---
 clang/lib/Parse/ParseDeclCXX.cpp              | 20 +++++++++++++------
 clang/lib/Sema/SemaTemplateVariadic.cpp       |  5 +++++
 .../SemaCXX/cxx2d-pack-indexing-template.cpp  | 20 +++++++++++++++++--
 3 files changed, 37 insertions(+), 8 deletions(-)

diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp
index d701cbaa43bdd..14adeeaad7a4d 100644
--- a/clang/lib/Parse/ParseDeclCXX.cpp
+++ b/clang/lib/Parse/ParseDeclCXX.cpp
@@ -1251,8 +1251,13 @@ bool Parser::AnnotatePackIndexingTemplateName(CXXScopeSpec &SS,
 
   TemplateName Indexed = Actions.ActOnPackIndexingTemplateName(
       Template.get(), NameLoc, IndexExpr.get());
+
+  // If we are unable to index a template name, treat is as a non
+  // template and recover by eating the arguments and producing a
+  // TypeError annotation.
   if (Indexed.isNull())
-    return true;
+    TNK = TNK_Non_template;
+
   Template = TemplateTy::make(Indexed);
 
   // C++29 [temp.names]p7:
@@ -1273,11 +1278,14 @@ bool Parser::AnnotatePackIndexingTemplateName(CXXScopeSpec &SS,
   // C++29 [dcl.type.simple]p1:
   //   A type specifier is a placeholder for a deduced class type if [...] it
   //   is of the form typename pack-index-template-name.
-  if ((TNK == TNK_Type_template || TNK == TNK_Dependent_template_name) &&
-      getLangOpts().CPlusPlus17) {
+  if (Indexed.isNull() ||
+      ((TNK == TNK_Type_template || TNK == TNK_Dependent_template_name) &&
+       getLangOpts().CPlusPlus17)) {
     TypeResult Type =
-        Actions.ActOnPackIndexingDeducedTemplateSpecializationType(Indexed,
-                                                                   NameLoc);
+        Indexed.isNull()
+            ? TypeError()
+            : Actions.ActOnPackIndexingDeducedTemplateSpecializationType(
+                  Indexed, NameLoc);
     Tok.setKind(tok::annot_typename);
     setTypeAnnotation(Tok, Type);
   } else {
@@ -1292,7 +1300,7 @@ bool Parser::AnnotatePackIndexingTemplateName(CXXScopeSpec &SS,
   Tok.setLocation(NameLoc);
   Tok.setAnnotationEndLoc(T.getCloseLocation());
   PP.AnnotateCachedTokens(Tok);
-  return false;
+  return Indexed.isNull();
 }
 
 void Parser::AnnotateExistingIndexedTypeNamePack(ParsedType T,
diff --git a/clang/lib/Sema/SemaTemplateVariadic.cpp b/clang/lib/Sema/SemaTemplateVariadic.cpp
index fb03591f70583..9b30832dc9d12 100644
--- a/clang/lib/Sema/SemaTemplateVariadic.cpp
+++ b/clang/lib/Sema/SemaTemplateVariadic.cpp
@@ -1406,6 +1406,11 @@ TemplateName Sema::ActOnPackIndexingTemplateName(TemplateName Pattern,
   // C++29 [temp.names]p3:
   //   The simple-template-name P in a pack-index-template-name shall denote a
   //   pack.
+  if (!Pattern.getAsTemplateTemplateParmDecl()) {
+    Diag(NameLoc, diag::err_expected_name_of_pack) << Pattern;
+    return TemplateName();
+  }
+
   bool DenotesPack = Pattern.containsUnexpandedParameterPack();
   if (!DenotesPack)
     Diag(NameLoc, diag::err_expected_name_of_pack) << Pattern;
diff --git a/clang/test/SemaCXX/cxx2d-pack-indexing-template.cpp b/clang/test/SemaCXX/cxx2d-pack-indexing-template.cpp
index 0298be66b1a86..3ccdcb9bb59b9 100644
--- a/clang/test/SemaCXX/cxx2d-pack-indexing-template.cpp
+++ b/clang/test/SemaCXX/cxx2d-pack-indexing-template.cpp
@@ -18,6 +18,24 @@ template <template <class> auto VV>
 constexpr int X = VV...[0]<int>; // expected-error {{'VV' does not refer to the name of a parameter pack}}
 }
 
+namespace GH220502 {
+void fn() {}
+void nontemplate(fn...[0]) {} // expected-error {{'fn' does not refer to the name of a parameter pack}}
+
+template <class T> concept Concept = true;
+template <class T> constexpr int Variable = 0;
+template <class T> void Function();
+template <class T> void Overloaded(T);
+template <class T> void Overloaded(T *);
+
+void f() {
+  (void)Concept...[0]<int>;  // expected-error {{'Concept' does not refer to the name of a parameter pack}}
+  (void)Variable...[0]<int>; // expected-error {{'Variable' does not refer to the name of a parameter pack}}
+  Function...[0]<int>();     // expected-error {{'Function' does not refer to the name of a parameter pack}}
+  Overloaded...[0]<int>(0);  // expected-error {{'Overloaded' does not refer to the name of a parameter pack}}
+}
+}
+
 namespace index {
 template <template <class> class... TT>
 struct S {
@@ -32,12 +50,10 @@ using E1 = OutOfBounds<A, B>;      // expected-note {{in instantiation of templa
 template <template <class> class... TT>
 using Negative = TT...[-1]<int>;
 // expected-error at -1 {{pack index evaluates to -1, which cannot be narrowed to type '__size_t'}}
-// expected-error at -2 {{expected ';' after alias declaration}}
 
 template <template <class> class... TT>
 using Narrowing = TT...[1.0]<int>;
 // expected-error at -1 {{conversion from 'double' to '__size_t' (aka 'unsigned long') is not allowed in a converted constant expression}}
-// expected-error at -2 {{expected ';' after alias declaration}}
 
 template <template <class> class... TT>
 using NonConstant = TT...[x]<int>;



More information about the cfe-commits mailing list