On 12/5/24 5:15 PM, Marek Polacek wrote:
On Thu, Dec 05, 2024 at 09:29:41AM -0500, Patrick Palka wrote:
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.
I think I agree. I think I wanted to stay around that TREE_VEC
assert in make_pack_index, but with the patch below I don't have
to bother with the complain parameter and I can also bail sooner,
before substituting the index.
Thanks,
Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?
OK.
-- >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 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.
---
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(-)
create mode 100644 gcc/testsuite/g++.dg/cpp26/pack-indexing12.C
diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 1f0f0260328..b094d141f3b 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 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
+}
diff --git a/gcc/testsuite/g++.dg/cpp26/pack-indexing2.C
b/gcc/testsuite/g++.dg/cpp26/pack-indexing2.C
index ec32527ed80..fdc8320e255 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>();
base-commit: b3cb0c3302a7c16e661a08c15c897c8f7bbb5d23