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