From: Patrick Palka Date: Wed, 15 Nov 2023 17:17:55 +0000 (-0500) Subject: c++: partially inst requires-expr in noexcept-spec [PR101043] X-Git-Tag: basepoints/gcc-15~4635 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=40a7707a7ea3568cee2cd80cd7e83b7eda678410;p=thirdparty%2Fgcc.git c++: partially inst requires-expr in noexcept-spec [PR101043] Here we're ICEing from strip_typedefs for the partially instantiated requires-expression when walking its REQUIRES_EXPR_EXTRA_ARGS which in this case is a TREE_LIST with non-empty TREE_PURPOSE (to hold the captured local specialization 't' as per build_extra_args) which strip_typedefs doesn't expect. We can probably skip walking REQUIRES_EXPR_EXTRA_ARGS at all since it shouldn't contain any typedefs in the first place, but it seems safer and more generally useful to just teach strip_typedefs to handle non-empty TREE_PURPOSE the obvious way. (The code asserts TREE_PURPOSE was empty even since since its inception i.e. r189298.) PR c++/101043 gcc/cp/ChangeLog: * tree.cc (strip_typedefs_expr) : Handle non-empty TREE_PURPOSE. gcc/testsuite/ChangeLog: * g++.dg/cpp2a/concepts-requires37.C: New test. --- diff --git a/gcc/cp/tree.cc b/gcc/cp/tree.cc index dc4126f935c3..0736e8d8f485 100644 --- a/gcc/cp/tree.cc +++ b/gcc/cp/tree.cc @@ -1911,19 +1911,24 @@ strip_typedefs_expr (tree t, bool *remove_attributes, unsigned int flags) case TREE_LIST: { bool changed = false; - releasing_vec vec; + auto_vec vec; r = t; for (; t; t = TREE_CHAIN (t)) { - gcc_assert (!TREE_PURPOSE (t)); - tree elt = strip_typedefs (TREE_VALUE (t), - remove_attributes, flags); - if (elt != TREE_VALUE (t)) + tree purpose = strip_typedefs (TREE_PURPOSE (t), + remove_attributes, flags); + tree value = strip_typedefs (TREE_VALUE (t), + remove_attributes, flags); + if (purpose != TREE_PURPOSE (t) || value != TREE_VALUE (t)) changed = true; - vec_safe_push (vec, elt); + vec.safe_push ({purpose, value}); } if (changed) - r = build_tree_list_vec (vec); + { + r = NULL_TREE; + for (int i = vec.length () - 1; i >= 0; i--) + r = tree_cons (vec[i].first, vec[i].second, r); + } return r; } diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-requires37.C b/gcc/testsuite/g++.dg/cpp2a/concepts-requires37.C new file mode 100644 index 000000000000..fa4095ed494f --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/concepts-requires37.C @@ -0,0 +1,11 @@ +// PR c++/101043 +// { dg-do compile { target c++20 } } + +template +void f(T t) { + [&](auto) noexcept(requires { t.g(); }) { }(0); +} + +int main() { + f(0); +}