Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk? -- >8 -- 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 make_pack_index. Other erroneous cases can wait until pack_index_element where we have the index.
PR c++/117898 gcc/cp/ChangeLog: * cp-tree.h (make_pack_index): Add a complain parameter with a default argument. * pt.cc (make_pack_index): Detect indexing an empty pack. (tsubst_pack_index): Pass COMPLAIN down to make_pack_index. gcc/testsuite/ChangeLog: * g++.dg/cpp26/pack-indexing12.C: New test. --- gcc/cp/cp-tree.h | 3 ++- gcc/cp/pt.cc | 14 +++++++++++--- gcc/testsuite/g++.dg/cpp26/pack-indexing12.C | 16 ++++++++++++++++ 3 files changed, 29 insertions(+), 4 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp26/pack-indexing12.C diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 29f28d5e383..8be4aafff8f 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -7602,7 +7602,8 @@ extern bool template_parameter_pack_p (const_tree); extern bool function_parameter_pack_p (const_tree); extern bool function_parameter_expanded_from_pack_p (tree, tree); extern tree make_pack_expansion (tree, tsubst_flags_t = tf_warning_or_error); -extern tree make_pack_index (tree, tree); +extern tree make_pack_index (tree, tree, + tsubst_flags_t = tf_warning_or_error); extern bool check_for_bare_parameter_packs (tree, location_t = UNKNOWN_LOCATION); extern tree build_template_info (tree, tree); extern tree get_template_info (const_tree); diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc index 182f18d0e24..242ad0d2012 100644 --- a/gcc/cp/pt.cc +++ b/gcc/cp/pt.cc @@ -4273,7 +4273,8 @@ make_pack_expansion (tree arg, tsubst_flags_t complain) /* Create a PACK_INDEX_* using the pack expansion PACK and index INDEX. */ tree -make_pack_index (tree pack, tree index) +make_pack_index (tree pack, tree index, + tsubst_flags_t complain/*=tf_warning_or_error*/) { if (pack == error_mark_node) return error_mark_node; @@ -4287,7 +4288,14 @@ make_pack_index (tree pack, tree index) { /* Maybe we've already partially substituted the pack. */ gcc_checking_assert (TREE_CODE (pack) == TREE_VEC); - for_types = TYPE_P (TREE_VEC_ELT (pack, 0)); + if (TREE_VEC_LENGTH (pack) == 0) + { + if (complain & tf_error) + error ("cannot index an empty pack"); + return error_mark_node; + } + else + for_types = TYPE_P (TREE_VEC_ELT (pack, 0)); } tree t = (for_types @@ -13990,7 +13998,7 @@ tsubst_pack_index (tree t, tree args, tsubst_flags_t complain, tree in_decl) if (!value_dependent_expression_p (index) && TREE_CODE (pack) == TREE_VEC) return pack_index_element (index, pack, parenthesized_p, complain); else - return make_pack_index (pack, index); + return make_pack_index (pack, index, complain); } /* Make an argument pack out of the TREE_VEC VEC. */ diff --git a/gcc/testsuite/g++.dg/cpp26/pack-indexing12.C b/gcc/testsuite/g++.dg/cpp26/pack-indexing12.C new file mode 100644 index 00000000000..d958af3620d --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp26/pack-indexing12.C @@ -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 +} base-commit: 68aefc6988dc34d4b9a2194f9fb08bccfe7a076b -- 2.47.1