[clang] 5e64eb8 - [Clang] Improve error recovery for indexed template names (#222328)

via cfe-commits cfe-commits at lists.llvm.org
Fri Sep 11 00:50:24 PDT 2026


Author: Corentin Jabot
Date: 2026-09-11T09:50:19+02:00
New Revision: 5e64eb8ffffa3e845ca01d81c1e45ef68d07d306

URL: https://github.com/llvm/llvm-project/commit/5e64eb8ffffa3e845ca01d81c1e45ef68d07d306
DIFF: https://github.com/llvm/llvm-project/commit/5e64eb8ffffa3e845ca01d81c1e45ef68d07d306.diff

LOG: [Clang] Improve error recovery for indexed template names (#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

Co-authored-by: Cursor <cursoragent at cursor.com>

Added: 
    

Modified: 
    clang/lib/Parse/ParseDeclCXX.cpp
    clang/lib/Sema/SemaTemplateVariadic.cpp
    clang/test/SemaCXX/cxx2d-pack-indexing-template.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp
index ed995398f597d..dbc1b85acd143 100644
--- a/clang/lib/Parse/ParseDeclCXX.cpp
+++ b/clang/lib/Parse/ParseDeclCXX.cpp
@@ -1225,8 +1225,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:
@@ -1247,11 +1252,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 {
@@ -1266,7 +1274,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 625aa198c2ea1..0f5c4d41c3295 100644
--- a/clang/lib/Sema/SemaTemplateVariadic.cpp
+++ b/clang/lib/Sema/SemaTemplateVariadic.cpp
@@ -1404,6 +1404,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 f1d9b1b8ce3d0..83fb5e94071a9 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