https://gcc.gnu.org/g:d64447946b0c8964dfd9731c3792af0fe4158cda

commit r15-6792-gd64447946b0c8964dfd9731c3792af0fe4158cda
Author: Marek Polacek <pola...@redhat.com>
Date:   Thu Dec 19 17:26:27 2024 -0500

    c++: ICE with pack indexing and partial inst [PR117937]
    
    Here we ICE in expand_expr_real_1:
    
          if (exp)
            {
              tree context = decl_function_context (exp);
              gcc_assert (SCOPE_FILE_SCOPE_P (context)
                          || context == current_function_decl
    
    on something like this test:
    
      void
      f (auto... args)
      {
        [&]<size_t... i>(seq<i...>) {
            g(args...[i]...);
        }(seq<0>());
      }
    
    because while current_function_decl is:
    
      f<int>(int)::<lambda(seq<i ...>)> [with long unsigned int ...i = {0}]
    
    (correct), context is:
    
      f<int>(int)::<lambda(seq<i ...>)>
    
    which is only the partial instantiation.
    
    I think that when tsubst_pack_index gets a partial instantiation, e.g.
    {*args#0} as the pack, we should still tsubst it.  The args#0's value-expr
    can be __closure->__args#0 where the closure's context is the partially
    instantiated operator().  So we should let retrieve_local_specialization
    find the right args#0.
    
            PR c++/117937
    
    gcc/cp/ChangeLog:
    
            * pt.cc (tsubst_pack_index): tsubst the pack even when it's not
            PACK_EXPANSION_P.
    
    gcc/testsuite/ChangeLog:
    
            * g++.dg/cpp26/pack-indexing13.C: New test.
            * g++.dg/cpp26/pack-indexing14.C: New test.

Diff:
---
 gcc/cp/pt.cc                                 |  8 ++++++++
 gcc/testsuite/g++.dg/cpp26/pack-indexing13.C | 23 +++++++++++++++++++++++
 gcc/testsuite/g++.dg/cpp26/pack-indexing14.C | 18 ++++++++++++++++++
 3 files changed, 49 insertions(+)

diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 67964d41ab8b..ff0a3a4f7d81 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -14063,6 +14063,14 @@ 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);
+  else
+    {
+      /* PACK can be {*args#0} whose args#0's value-expr refers to
+        a partially instantiated closure.  Let tsubst find the
+        fully-instantiated one.  */
+      gcc_assert (TREE_CODE (pack) == TREE_VEC);
+      pack = tsubst (pack, args, complain, in_decl);
+    }
   if (TREE_CODE (pack) == TREE_VEC && TREE_VEC_LENGTH (pack) == 0)
     {
       if (complain & tf_error)
diff --git a/gcc/testsuite/g++.dg/cpp26/pack-indexing13.C 
b/gcc/testsuite/g++.dg/cpp26/pack-indexing13.C
new file mode 100644
index 000000000000..e0dd9c21c67b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp26/pack-indexing13.C
@@ -0,0 +1,23 @@
+// PR c++/117937
+// { dg-do compile { target c++26 } }
+
+using size_t = decltype(sizeof(0));
+
+template<size_t...>
+struct seq {};
+
+void g(auto...) {}
+
+void
+f (auto... args)
+{
+  [&]<size_t... i>(seq<i...>) {
+      g(args...[i]...);
+  }(seq<0>());
+}
+
+int
+main ()
+{
+  f(0);
+}
diff --git a/gcc/testsuite/g++.dg/cpp26/pack-indexing14.C 
b/gcc/testsuite/g++.dg/cpp26/pack-indexing14.C
new file mode 100644
index 000000000000..c8a67ee16edb
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp26/pack-indexing14.C
@@ -0,0 +1,18 @@
+// PR c++/117937
+// { dg-do compile { target c++26 } }
+
+void operate_one(const int) {}
+
+template<typename ...T>
+void operate_multi(T... args)
+{
+    [&]<int idx>()
+    {
+       ::operate_one(args...[idx]);
+    }.template operator()<0>();
+}
+
+int main()
+{
+    ::operate_multi(0);
+}

Reply via email to