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); +}