c++: Fix satisfaction of placeholder type constraints [PR96443]
authorPatrick Palka <ppalka@redhat.com>
Tue, 2 Mar 2021 12:49:29 +0000 (07:49 -0500)
committerPatrick Palka <ppalka@redhat.com>
Tue, 2 Mar 2021 12:49:29 +0000 (07:49 -0500)
commite52f8ec25c0e58ebd083e8370e2fbc8af4120d87
tree406045a67c67f70d3ff1ebbe6525feaeed3ddfce
parent276cb81bec63906543b79915d9ff542a34910b2d
c++: Fix satisfaction of placeholder type constraints [PR96443]

This fixes the way we check satisfaction of constraints on placeholder
types in various deduction contexts, and in particular when the
constraint is dependent.

Firstly, when evaluating the return type requirement of a compound
requirement, we currently substitute the outer template arguments into
the constraint before checking satisfaction. But we should instead be
passing in the complete set of template arguments to satisfaction and
not do a prior separate substitution.  Our current approach leads to us
incorrectly rejecting the testcase concepts-return-req2.C below.

Secondly, when checking the constraints on a placeholder variable or
return type, we don't consider the template arguments of the enclosing
context at all.  This leads to bogus errors during satisfaction when the
constraint is dependent as in the testcase concepts-placeholder3.C
below.

In order to fix these two issues, we need to be able to normalize the
constraints on a placeholder 'auto' on demand, which in turn requires us
to know the template parameters that were in scope where the 'auto' was
introduced.  This information currently doesn't seem to be easily available
when we need it, so this patch turns PLACEHOLDER_TYPE_CONSTRAINTS into a
TREE_LIST whose TREE_PURPOSE additionally holds the value of
current_template_parms whence a constrained 'auto' was formed.

This patch also removes some seemingly wrong handling of placeholder
type arguments from tsubst_parameter_mapping.  The code doesn't trigger
with the example used in the comments, because type_uses_auto doesn't
look inside non-deduced contexts such as the operand of decltype.  And
the call to do_auto_deduction seems confused because if 'arg' is a type,
then so is 'parm', and therefore 'init' too is a type, but
do_auto_deduction expects it to be an expression.  Before this patch,
this code was dead (as far as our testsuite can tell), but now it breaks
other parts of this patch, so let's remove it.

gcc/cp/ChangeLog:

PR c++/96443
PR c++/96960
* constraint.cc (type_deducible_p): Don't substitute into the
constraints, and instead just pass 'args' to do_auto_deduction
as the outer template arguments.
(tsubst_parameter_mapping): Remove confused code for handling
placeholder type arguments.
(normalize_placeholder_type_constraint): Define.
(satisfy_constraint_expression): Use it to handle placeholder
'auto' types.
* cp-tree.h (PLACEHOLDER_TYPE_CONSTRAINTS_INFO): Define.
(PLACEHOLDER_TYPE_CONSTRAINTS): Redefine in terms of the above.
* pt.c (tsubst) <case TEMPLATE_TYPE_PARM>: Use
PLACEHOLDER_TYPE_CONSTRAINTS_INFO instead.
(make_constrained_placeholder_type): Set
PLACEHOLDER_TYPE_CONSTRAINTS_INFO instead.
(do_auto_deduction): Clarify comments about the outer_targs
parameter.  Rework satisfaction of a placeholder type constraint
to pass in the complete set of template arguments directly to
constraints_satisfied_p.
(splice_late_return_type): Use PLACEHOLDER_TYPE_CONSTRAINTS_INFO
instead.  Also rebuild the the constraint info on the new auto.

gcc/testsuite/ChangeLog:

PR c++/96443
PR c++/96960
* g++.dg/concepts/abbrev9.C: New test.
* g++.dg/cpp2a/concepts-lambda15.C: New test.
* g++.dg/cpp2a/concepts-placeholder3.C: New test.
* g++.dg/cpp2a/concepts-return-req2.C: New test.
* g++.dg/cpp2a/concepts-ts1.C: Add dg-bogus directive to the
call to f15 that we expect to accept.
gcc/cp/constraint.cc
gcc/cp/cp-tree.h
gcc/cp/pt.c
gcc/testsuite/g++.dg/concepts/abbrev9.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp2a/concepts-lambda15.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp2a/concepts-placeholder3.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp2a/concepts-return-req2.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp2a/concepts-ts1.C