Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for
trunk?
-- >8 --
This fixes some missed SFINAE in grok_array_decl when checking a C++23
multidimensional subscript operator expression.
Note the existing pedwarn code paths are a backward compability fallback
for treating invalid a[x, y, z] as a[(x, y, z)], but this should only be
done outside of a SFINAE context I think.
PR c++/111493
gcc/cp/ChangeLog:
* decl2.cc (grok_array_decl): Guard errors with tf_error.
In the pedwarn code paths, return error_mark_node when in
a SFINAE context.
gcc/testsuite/ChangeLog:
* g++.dg/cpp23/subscript15.C: New test.
---
gcc/cp/decl2.cc | 36 +++++++++++++++---------
gcc/testsuite/g++.dg/cpp23/subscript15.C | 24 ++++++++++++++++
2 files changed, 47 insertions(+), 13 deletions(-)
create mode 100644 gcc/testsuite/g++.dg/cpp23/subscript15.C
diff --git a/gcc/cp/decl2.cc b/gcc/cp/decl2.cc
index b402befba6d..6eb6d8c57d6 100644
--- a/gcc/cp/decl2.cc
+++ b/gcc/cp/decl2.cc
@@ -477,7 +477,9 @@ grok_array_decl (location_t loc, tree array_expr, tree
index_exp,
{
/* If it would be valid albeit deprecated expression in
C++20, just pedwarn on it and treat it as if wrapped
- in (). */
+ in () unless we're in a SFINAE context. */
+ if (!(complain & tf_error))
+ return error_mark_node;
pedwarn (loc, OPT_Wcomma_subscript,
"top-level comma expression in array subscript "
"changed meaning in C++23");
@@ -487,7 +489,7 @@ grok_array_decl (location_t loc, tree array_expr, tree
index_exp,
= build_x_compound_expr_from_vec (orig_index_exp_list,
NULL, complain);
if (orig_index_exp == error_mark_node)
- expr = error_mark_node;
+ return error_mark_node;
release_tree_vector (orig_index_exp_list);
}
}
@@ -512,22 +514,29 @@ grok_array_decl (location_t loc, tree array_expr, tree
index_exp,
{
if ((*index_exp_list)->is_empty ())
{
- error_at (loc, "built-in subscript operator without expression "
- "list");
+ if (complain & tf_error)
+ error_at (loc, "built-in subscript operator without expression "
+ "list");
return error_mark_node;
}
tree idx = build_x_compound_expr_from_vec (*index_exp_list, NULL,
tf_none);
if (idx != error_mark_node)
- /* If it would be valid albeit deprecated expression in C++20,
- just pedwarn on it and treat it as if wrapped in (). */
- pedwarn (loc, OPT_Wcomma_subscript,
- "top-level comma expression in array subscript "
- "changed meaning in C++23");
+ {
+ /* If it would be valid albeit deprecated expression in C++20,
+ just pedwarn on it and treat it as if wrapped in () unless
+ we're in a SFINAE context. */
+ if (!(complain & tf_error))
+ return error_mark_node;
+ pedwarn (loc, OPT_Wcomma_subscript,
+ "top-level comma expression in array subscript "
+ "changed meaning in C++23");
+ }
else
{
- error_at (loc, "built-in subscript operator with more than one "
- "expression in expression list");
+ if (complain & tf_error)
+ error_at (loc, "built-in subscript operator with more than one "
+ "expression in expression list");
return error_mark_node;
}
index_exp = idx;
@@ -561,8 +570,9 @@ grok_array_decl (location_t loc, tree array_expr, tree
index_exp,
swapped = true, array_expr = p2, index_exp = i1;
else
{
- error_at (loc, "invalid types %<%T[%T]%> for array subscript",
- type, TREE_TYPE (index_exp));
+ if (complain & tf_error)
+ error_at (loc, "invalid types %<%T[%T]%> for array subscript",
+ type, TREE_TYPE (index_exp));
return error_mark_node;
}
diff --git a/gcc/testsuite/g++.dg/cpp23/subscript15.C
b/gcc/testsuite/g++.dg/cpp23/subscript15.C
new file mode 100644
index 00000000000..1528ee71306
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp23/subscript15.C
@@ -0,0 +1,24 @@
+// PR c++/111493
+// { dg-do compile { target c++23 } }
+
+template<class T, class... Ts>
+concept CartesianIndexable = requires(T t, Ts... ts) { t[ts...]; };
+
+static_assert(!CartesianIndexable<int>);
+static_assert(!CartesianIndexable<int, int>);
+static_assert(!CartesianIndexable<int, int, int>);
+
+static_assert(!CartesianIndexable<int*>);
+static_assert(CartesianIndexable<int*, int>);
+static_assert(!CartesianIndexable<int*, int, int>);
+
+template<class... Ts>
+struct A {
+ void operator[](Ts...);
+};
+
+static_assert(!CartesianIndexable<A<>, int>);
+static_assert(CartesianIndexable<A<int>, int>);
+static_assert(!CartesianIndexable<A<int>>);
+static_assert(!CartesianIndexable<A<int>, int, int>);
+static_assert(CartesianIndexable<A<int, int>, int, int>);
--
2.42.0.216.gbda494f404