]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
c++: ICE with pack indexing empty pack [PR117898]
authorMarek Polacek <polacek@redhat.com>
Wed, 4 Dec 2024 21:58:59 +0000 (16:58 -0500)
committerMarek Polacek <polacek@redhat.com>
Fri, 6 Dec 2024 01:12:02 +0000 (20:12 -0500)
Here we ICE with a partially-substituted pack indexing.  The pack
expanded to an empty pack, which we can't index.  It seems reasonable
to detect this case in tsubst_pack_index, even before we substitute
the index.  Other erroneous cases can wait until pack_index_element
where we have the index.

PR c++/117898

gcc/cp/ChangeLog:

* pt.cc (tsubst_pack_index): Detect indexing an empty pack.

gcc/testsuite/ChangeLog:

* g++.dg/cpp26/pack-indexing2.C: Adjust.
* g++.dg/cpp26/pack-indexing12.C: New test.

gcc/cp/pt.cc
gcc/testsuite/g++.dg/cpp26/pack-indexing12.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp26/pack-indexing2.C

index 1f0f0260328840191217aefc4bf3e8c3479a48c0..b094d141f3b0b60a7b54a69870ab2375dd64c69f 100644 (file)
@@ -13984,6 +13984,12 @@ tsubst_pack_index (tree t, tree args, tsubst_flags_t complain, tree in_decl)
   tree pack = PACK_INDEX_PACK (t);
   if (PACK_EXPANSION_P (pack))
     pack = tsubst_pack_expansion (pack, args, complain, in_decl);
+  if (TREE_CODE (pack) == TREE_VEC && TREE_VEC_LENGTH (pack) == 0)
+    {
+      if (complain & tf_error)
+       error ("cannot index an empty pack");
+      return error_mark_node;
+    }
   tree index = tsubst_expr (PACK_INDEX_INDEX (t), args, complain, in_decl);
   const bool parenthesized_p = (TREE_CODE (t) == PACK_INDEX_EXPR
                                && PACK_INDEX_PARENTHESIZED_P (t));
diff --git a/gcc/testsuite/g++.dg/cpp26/pack-indexing12.C b/gcc/testsuite/g++.dg/cpp26/pack-indexing12.C
new file mode 100644 (file)
index 0000000..d958af3
--- /dev/null
@@ -0,0 +1,16 @@
+// PR c++/117898
+// { dg-do compile { target c++26 } }
+
+void
+ICE (auto... args)
+{
+  [&]<int idx>() {
+    using R = decltype(args...[idx]); // { dg-error "cannot index an empty pack" }
+  }.template operator()<0>();
+}
+
+void
+g ()
+{
+  ICE(); // empty pack
+}
index ec32527ed80fa379edac441fa12809c39d1fed6a..fdc8320e2555ba43ca6fcd33088d015350a6347b 100644 (file)
@@ -42,7 +42,7 @@ template<int N>
 int
 getT (auto... Ts)
 {
-  return Ts...[N]; // { dg-error "pack index is out of range" }
+  return Ts...[N]; // { dg-error "cannot index an empty pack" }
 }
 
 template<int N>
@@ -56,12 +56,26 @@ template<auto N, typename... Ts>
 void
 badtype ()
 {
-  Ts...[N] t; // { dg-error "pack index is out of range" }
+  Ts...[N] t; // { dg-error "cannot index an empty pack" }
 }
 
 template<auto N, typename... Ts>
 void
 badtype2 ()
+{
+  Ts...[N] t; // { dg-error "pack index is out of range" }
+}
+
+template<auto N, typename... Ts>
+void
+badtype3 ()
+{
+  Ts...[N] t; // { dg-error "cannot index an empty pack" }
+}
+
+template<auto N, typename... Ts>
+void
+badtype4 ()
 {
   Ts...[N] t; // { dg-error "pack index is negative" }
 }
@@ -97,12 +111,12 @@ int main()
 
   getT<0>(); // { dg-message "required from here" }
   getT<1>();  // { dg-message "required from here" }
-  getT2<-1>();  // { dg-message "required from here" }
+  getT2<-1>(1);  // { dg-message "required from here" }
 
   badtype<0>(); // { dg-message "required from here" }
-  badtype<1, int>(); // { dg-message "required from here" }
-  badtype2<-1>(); // { dg-message "required from here" }
-  badtype2<-1, int>(); // { dg-message "required from here" }
+  badtype2<1, int>(); // { dg-message "required from here" }
+  badtype3<-1>(); // { dg-message "required from here" }
+  badtype4<-1, int>(); // { dg-message "required from here" }
 
   badindex<int, int, int>();