aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp/pt.c
diff options
context:
space:
mode:
authorPatrick Palka <ppalka@redhat.com>2020-06-03 16:40:28 -0400
committerPatrick Palka <ppalka@redhat.com>2020-06-03 16:40:28 -0400
commitaee69073cdb8086d393f12474c6177e75467ceaa (patch)
tree4492342ea2044fcc67e5ea4c1ff117d09be93475 /gcc/cp/pt.c
parent3fb68f2e666d9de7e0326af9f43b12c9e98f19a6 (diff)
downloadgcc-aee69073cdb8086d393f12474c6177e75467ceaa.zip
gcc-aee69073cdb8086d393f12474c6177e75467ceaa.tar.gz
gcc-aee69073cdb8086d393f12474c6177e75467ceaa.tar.bz2
c++: constrained nested partial specialization [PR92103]
When determining the most specialized partial specialization of a primary template that is nested inside a class template, we first tsubst the outer template arguments into the TEMPLATE_DECL of each partial specialization, and then check for satisfaction of each of the new TEMPLATE_DECL's constraints. But tsubst_template_decl does not currently guarantee that constraints from the original DECL_TEMPLATE_RESULT get reattached to the new DECL_TEMPLATE_RESULT. In the testcase below, this leads to the constraints_satisfied_p check in most_specialized_partial_spec to trivially return true for each of the partial specializations. I'm not sure if such a guarantee would be desirable, but in this case we can just check constraints_satisfied_p on the original TEMPLATE_DECL instead of on the tsubsted TEMPLATE_DECL here, which is what this patch does (alongside some reorganizing). gcc/cp/ChangeLog: PR c++/92103 * pt.c (most_specialized_partial_spec): Reorganize the loop over DECL_TEMPLATE_SPECIALIZATIONS. Check constraints_satisfied_p on the original template declaration, not on the tsubsted one. gcc/testsuite/ChangeLog: PR c++/92103 * g++.dg/cpp2a/concepts-partial-spec7.C: New test.
Diffstat (limited to 'gcc/cp/pt.c')
-rw-r--r--gcc/cp/pt.c19
1 files changed, 10 insertions, 9 deletions
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 38a771b..f5d1442 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -24488,21 +24488,22 @@ most_specialized_partial_spec (tree target, tsubst_flags_t complain)
for (t = DECL_TEMPLATE_SPECIALIZATIONS (main_tmpl); t; t = TREE_CHAIN (t))
{
- tree spec_args;
- tree spec_tmpl = TREE_VALUE (t);
+ const tree ospec_tmpl = TREE_VALUE (t);
+ tree spec_tmpl;
if (outer_args)
{
/* Substitute in the template args from the enclosing class. */
++processing_template_decl;
- spec_tmpl = tsubst (spec_tmpl, outer_args, tf_none, NULL_TREE);
+ spec_tmpl = tsubst (ospec_tmpl, outer_args, tf_none, NULL_TREE);
--processing_template_decl;
+ if (spec_tmpl == error_mark_node)
+ return error_mark_node;
}
+ else
+ spec_tmpl = ospec_tmpl;
- if (spec_tmpl == error_mark_node)
- return error_mark_node;
-
- spec_args = get_partial_spec_bindings (tmpl, spec_tmpl, args);
+ tree spec_args = get_partial_spec_bindings (tmpl, spec_tmpl, args);
if (spec_args)
{
if (outer_args)
@@ -24511,9 +24512,9 @@ most_specialized_partial_spec (tree target, tsubst_flags_t complain)
/* Keep the candidate only if the constraints are satisfied,
or if we're not compiling with concepts. */
if (!flag_concepts
- || constraints_satisfied_p (spec_tmpl, spec_args))
+ || constraints_satisfied_p (ospec_tmpl, spec_args))
{
- list = tree_cons (spec_args, TREE_VALUE (t), list);
+ list = tree_cons (spec_args, ospec_tmpl, list);
TREE_TYPE (list) = TREE_TYPE (t);
}
}