aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorMarek Polacek <polacek@redhat.com>2024-12-19 17:26:27 -0500
committerMarek Polacek <polacek@redhat.com>2025-01-10 09:14:42 -0500
commitd64447946b0c8964dfd9731c3792af0fe4158cda (patch)
tree6b404358df0fa989ad23e2bbc54ba079b2c41800 /gcc
parent8a2d5bc28089b2660310b964ef75fb05eb387f88 (diff)
downloadgcc-d64447946b0c8964dfd9731c3792af0fe4158cda.zip
gcc-d64447946b0c8964dfd9731c3792af0fe4158cda.tar.gz
gcc-d64447946b0c8964dfd9731c3792af0fe4158cda.tar.bz2
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.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/pt.cc8
-rw-r--r--gcc/testsuite/g++.dg/cpp26/pack-indexing13.C23
-rw-r--r--gcc/testsuite/g++.dg/cpp26/pack-indexing14.C18
3 files changed, 49 insertions, 0 deletions
diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 67964d4..ff0a3a4 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 0000000..e0dd9c2
--- /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 0000000..c8a67ee
--- /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);
+}