c++: adc_unify deduction with constrained auto [PR99365]
authorPatrick Palka <ppalka@redhat.com>
Sat, 6 Mar 2021 05:07:35 +0000 (00:07 -0500)
committerPatrick Palka <ppalka@redhat.com>
Sat, 6 Mar 2021 05:07:35 +0000 (00:07 -0500)
commitb49d23f3e238c08bdbc5b892b2ed0a57b5f5caf9
tree39b2214af8c06e99bf30a142017be583af2fc682
parent7723f569345ae82ba440552251a84e65c2a9dcb5
c++: adc_unify deduction with constrained auto [PR99365]

My recent r11-7454 changed the way do_auto_deduction handles constrained
placeholders during template argument deduction (context == adc_unify)
when processing_template_decl != 0.  Before the patch, we would just
ignore the constraints on the placeholder, and return the deduced type.
After the patch, we now punt and return the original placeholder type

While this change fixed instances where we'd prematurely resolve a
constrained placeholder return or variable type with non-dependent
initializer at template parse time (such as PR96444), it broke the
adc_unify callers that rely on the previous behavior.

This patch restores the previous behavior during adc_unify deduction
while retaining the new behavior only during adc_variable_type or
adc_return_type deduction.

We additionally now need to pass the outer template arguments to
do_auto_deduction during unify, for sake of constraint checking.
But we want to avoid substituting these outer arguments into type
when the caller has already done so, so this patch adds a
TEMPLATE_TYPE_LEVEL check to do_auto_deduction to that effect.

This above is enough to fix partial specialization of non-nested
templates with constrained 'auto' template parameters, but it doesn't
fix the nested template case, ultimately because
most_specialized_partial_spec passes only the innermost template
arguments to get_partial_spec_bindings, and so outer_targs during
do_auto_deduction (called from unify) contains only the innermost
template arguments, and this breaks satisfaction.  Fixing this properly
is perhaps too risky at this stage, so this patch adds a hack to
do_auto_deduction to compensate for callers that don't supply all outer
template arguments.  The goal of this hack is to ensure placeholder type
constraint checking continues to work whenever it worked before
r11-7454, namely whenever the constraint is non-dependent.

Finally, this patch allows do_auto_deduction to resolve a constrained
placeholder type ahead of time (at template parse time), as long as the
constraint is non-dependent.

gcc/cp/ChangeLog:

PR c++/99365
* pt.c (unify) <case TEMPLATE_TYPE_PARM>: Pass targs as
outer_targs to do_auto_deduction.
(placeholder_type_constraint_dependent_p): Define.
(do_auto_deduction): When processing_template_decl != 0
and context is adc_unify and we have constraints, pretend the
constraints are satisfied instead of punting.  Otherwise don't
punt unless placeholder_type_constraint_dependent_p holds.
Add some clarifying sanity checks.  Add a hack to add missing
outermost template levels to outer_args before checking
satisfaction.  Don't substitute outer_targs into type if it's
already been done.

gcc/testsuite/ChangeLog:

PR c++/99365
* g++.dg/cpp2a/concepts-partial-spec9.C: New test.
* g++.dg/cpp2a/concepts-placeholder4.C: New test.
gcc/cp/pt.c
gcc/testsuite/g++.dg/cpp2a/concepts-partial-spec9.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp2a/concepts-placeholder4.C [new file with mode: 0644]