From bde31a76ba48be49dbe26317ce5e19d10ae9f310 Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Wed, 11 Mar 2020 00:53:01 -0400 Subject: [PATCH] c++: Fix ICE with concepts and aliases [PR93907]. The problem here was that we were checking satisfaction once with 'e', a typedef of 'void', and another time with 'void' directly, and treated them as different for hashing based on the assumption that canonicalize_type_argument would have already removed a typedef that wasn't a complex dependent alias. But that wasn't happening here, so let's add a call. gcc/cp/ChangeLog 2020-03-11 Jason Merrill PR c++/93907 * constraint.cc (tsubst_parameter_mapping): Canonicalize type argument. --- gcc/cp/ChangeLog | 6 +++ gcc/cp/constraint.cc | 6 ++- gcc/cp/cp-tree.h | 1 + gcc/cp/pt.c | 2 +- gcc/testsuite/g++.dg/cpp2a/concepts-using2.C | 45 ++++++++++++++++++++ 5 files changed, 58 insertions(+), 2 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp2a/concepts-using2.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index da768cd2bbe..8cde3000e8d 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,9 @@ +2020-03-11 Jason Merrill + + PR c++/93907 + * constraint.cc (tsubst_parameter_mapping): Canonicalize type + argument. + 2020-03-11 Marek Polacek Jason Merrill diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc index 4bb4a3f7252..697ed6726b8 100644 --- a/gcc/cp/constraint.cc +++ b/gcc/cp/constraint.cc @@ -2232,7 +2232,11 @@ tsubst_parameter_mapping (tree map, tree args, subst_info info) else if (ARGUMENT_PACK_P (arg)) new_arg = tsubst_argument_pack (arg, args, complain, in_decl); if (!new_arg) - new_arg = tsubst_template_arg (arg, args, complain, in_decl); + { + new_arg = tsubst_template_arg (arg, args, complain, in_decl); + if (TYPE_P (new_arg)) + new_arg = canonicalize_type_argument (new_arg, complain); + } if (new_arg == error_mark_node) return error_mark_node; diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 0a7381cee3f..757cdd8168a 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -7016,6 +7016,7 @@ extern tree resolve_nondeduced_context_or_error (tree, tsubst_flags_t); extern hashval_t iterative_hash_template_arg (tree arg, hashval_t val); extern tree coerce_template_parms (tree, tree, tree); extern tree coerce_template_parms (tree, tree, tree, tsubst_flags_t); +extern tree canonicalize_type_argument (tree, tsubst_flags_t); extern void register_local_specialization (tree, tree); extern tree retrieve_local_specialization (tree); extern tree extract_fnparm_pack (tree, tree *); diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index cb237ba0d9d..789ccdbbbd1 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -7943,7 +7943,7 @@ template_template_parm_bindings_ok_p (tree tparms, tree targs) /* Since type attributes aren't mangled, we need to strip them from template type arguments. */ -static tree +tree canonicalize_type_argument (tree arg, tsubst_flags_t complain) { if (!arg || arg == error_mark_node || arg == TYPE_CANONICAL (arg)) diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-using2.C b/gcc/testsuite/g++.dg/cpp2a/concepts-using2.C new file mode 100644 index 00000000000..b1a45d5e595 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/concepts-using2.C @@ -0,0 +1,45 @@ +// PR c++/93907 +// { dg-options -std=gnu++20 } + +template struct c { + static constexpr int d = a; + typedef c e; +}; +template struct f; +template using g = typename f::e; +struct b; +template struct f { using e = b; }; +template struct m { typedef g aj; }; +template class n { typedef typename m::aj e; }; +template using an = typename n::e; +template constexpr bool ao = c::d; +template constexpr bool i = c<1>::d; +template concept bb = i; +using cc = __int128; +template concept cd = bb; +template concept ce = requires { requires cd; }; +template concept h = ce; +template concept l = h; +template concept cl = ao; +template concept cp = requires(b j) { + requires h>; +}; +struct o { + template requires cp auto operator()(b) {} +}; +template using cm = decltype(o{}(b())); +template concept ct = l; +template concept dd = ct>; +template concept de = dd; +struct { + template void operator()(da, b); +} di; +class p { + void begin(); +}; +template using df = p; +template void q() { + df k; + int d; + di(k, d); +} -- 2.30.2