https://gcc.gnu.org/g:afeef7f0d3537cd978931a5afcbd3d91c144bfeb
commit r15-5955-gafeef7f0d3537cd978931a5afcbd3d91c144bfeb Author: Marek Polacek <pola...@redhat.com> Date: Wed Dec 4 16:58:59 2024 -0500 c++: ICE with pack indexing empty pack [PR117898] 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 tsubst_pack_index, even before we substitute the index. Other erroneous cases can wait until pack_index_element where we have the index. PR c++/117898 gcc/cp/ChangeLog: * pt.cc (tsubst_pack_index): Detect indexing an empty pack. gcc/testsuite/ChangeLog: * g++.dg/cpp26/pack-indexing2.C: Adjust. * g++.dg/cpp26/pack-indexing12.C: New test. Diff: --- gcc/cp/pt.cc | 6 ++++++ gcc/testsuite/g++.dg/cpp26/pack-indexing12.C | 16 ++++++++++++++++ gcc/testsuite/g++.dg/cpp26/pack-indexing2.C | 26 ++++++++++++++++++++------ 3 files changed, 42 insertions(+), 6 deletions(-) diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc index 1f0f02603288..b094d141f3b0 100644 --- a/gcc/cp/pt.cc +++ b/gcc/cp/pt.cc @@ -13984,6 +13984,12 @@ 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); + if (TREE_CODE (pack) == TREE_VEC && TREE_VEC_LENGTH (pack) == 0) + { + if (complain & tf_error) + error ("cannot index an empty pack"); + return error_mark_node; + } tree index = tsubst_expr (PACK_INDEX_INDEX (t), args, complain, in_decl); const bool parenthesized_p = (TREE_CODE (t) == PACK_INDEX_EXPR && PACK_INDEX_PARENTHESIZED_P (t)); 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 000000000000..d958af3620d0 --- /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 +} diff --git a/gcc/testsuite/g++.dg/cpp26/pack-indexing2.C b/gcc/testsuite/g++.dg/cpp26/pack-indexing2.C index ec32527ed80f..fdc8320e2555 100644 --- a/gcc/testsuite/g++.dg/cpp26/pack-indexing2.C +++ b/gcc/testsuite/g++.dg/cpp26/pack-indexing2.C @@ -42,7 +42,7 @@ template<int N> int getT (auto... Ts) { - return Ts...[N]; // { dg-error "pack index is out of range" } + return Ts...[N]; // { dg-error "cannot index an empty pack" } } template<int N> @@ -56,12 +56,26 @@ template<auto N, typename... Ts> void badtype () { - Ts...[N] t; // { dg-error "pack index is out of range" } + Ts...[N] t; // { dg-error "cannot index an empty pack" } } template<auto N, typename... Ts> void badtype2 () +{ + Ts...[N] t; // { dg-error "pack index is out of range" } +} + +template<auto N, typename... Ts> +void +badtype3 () +{ + Ts...[N] t; // { dg-error "cannot index an empty pack" } +} + +template<auto N, typename... Ts> +void +badtype4 () { Ts...[N] t; // { dg-error "pack index is negative" } } @@ -97,12 +111,12 @@ int main() getT<0>(); // { dg-message "required from here" } getT<1>(); // { dg-message "required from here" } - getT2<-1>(); // { dg-message "required from here" } + getT2<-1>(1); // { dg-message "required from here" } badtype<0>(); // { dg-message "required from here" } - badtype<1, int>(); // { dg-message "required from here" } - badtype2<-1>(); // { dg-message "required from here" } - badtype2<-1, int>(); // { dg-message "required from here" } + badtype2<1, int>(); // { dg-message "required from here" } + badtype3<-1>(); // { dg-message "required from here" } + badtype4<-1, int>(); // { dg-message "required from here" } badindex<int, int, int>();