On Wed, 4 Dec 2024, Marek Polacek wrote:
> 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.
IIUC this can only happen when called from tsubst_pack_index right?
In that case maybe we should directly diagnose the error there.
That way we make_pack_index remains nice and simple.
> 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
>
>