diff options
author | Patrick Palka <ppalka@redhat.com> | 2020-06-03 16:40:28 -0400 |
---|---|---|
committer | Patrick Palka <ppalka@redhat.com> | 2020-06-03 16:40:28 -0400 |
commit | aee69073cdb8086d393f12474c6177e75467ceaa (patch) | |
tree | 4492342ea2044fcc67e5ea4c1ff117d09be93475 /gcc/cp/pt.c | |
parent | 3fb68f2e666d9de7e0326af9f43b12c9e98f19a6 (diff) | |
download | gcc-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.c | 19 |
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); } } |