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