c++: Distinguish unsatisfaction vs errors during satisfaction [PR97093]
During satisfaction, the flag info.noisy() controls three things:
whether to diagnose ill-formed satisfaction (such as the satisfaction
value of an atom being non-bool or non-constant); whether to diagnose
unsatisfaction; and whether to bypass the satisfaction cache.
The flag turns out to be too coarse however, because in some cases we
want to diagnose ill-formed satisfaction (and bypass the satisfaction
cache) but not diagnose unsatisfaction, for instance when replaying an
erroneous satisfaction result from constraint_satisfaction_value,
evaluate_concept_check and tsubst_nested_requirement.
And when noisily evaluating a disjunction, we want to first evaluate its
branches noisily (bypassing the satisfaction cache) but suppress
unsatisfaction diagnostics. We currently work around this by instead
first evaluating each branch quietly, but that means the recursive calls
to satisfy_atom will use the satisfaction cache.
To fix this, this patch adds the info.diagnose_unsatisfaction_p() flag,
which refines the info.noisy() flag as part of a new sat_info class that
derives from subst_info. During satisfaction, info.noisy() now controls
whether to diagnose ill-formed satisfaction, and
info.diagnose_unsatisfaction_p() controls whether to additionally
diagnose unsatisfaction. This enables us to address the above two
issues straightforwardly.
Incidentally, the change to satisfy_disjunction suppresses the ICE in
the PR97093 testcase because we no longer insert atoms into the
satisfaction cache that have been incorrectly re-normalized in
diagnose_nested_requirement (after losing the necessary template
context). But the underlying re-normalization issue remains, and will
be fixed in a subsequent patch.
gcc/cp/ChangeLog:
PR c++/97093
* constraint.cc (struct sat_info): Define.
(tsubst_nested_requirement): Pass a sat_info object to
satisfy_constraint.
(satisfy_constraint_r): Take a sat_info argument instead of
subst_info.
(satisfy_conjunction): Likewise.
(satisfy_disjunction): Likewise. Instead of first evaluating
each branch quietly, evaluate each branch only with
unsatisfaction diagnostics disabled. Exit early if evaluation
of a branch returns error_mark_node.
(satisfy_atom): Take a sat_info argument instead of subst_info.
Fix a comment. Check diagnose_unsatisfaction_p() instead of
noisy() before replaying a substitution failure.
(satisfy_constraint): Take a sat_info argument instead of
subst_info.
(satisfy_associated_constraints): Likewise.
(satisfy_constraint_expression): Likewise.
(satisfy_declaration_constraints): Likewise.
(constraint_satisfaction_value): Likewise and adjust
accordingly. Fix formatting.
(constraints_satisfied_p): Pass a sat_info object to
constraint_satisfaction_value.
(evaluate_concept_check): Pass a sat_info object to
satisfy_constraint_expression.
(diagnose_nested_requirement): Likewise.
(diagnose_constraints): Pass an appropriate sat_info object to
constraint_satisfaction_value.
gcc/testsuite/ChangeLog:
PR c++/97093
* g++.dg/concepts/pr94252.C: Verify we no longer issue a
spurious unsatisfaction note when diagnosing ill-formed
satisfaction.
* g++.dg/cpp2a/concepts-requires18.C: No longer expect a
spurious unsatisfaction diagnostic when evaluating the
nested-requirement subst<void&> of a requires-expression that
appears outside of a template.
* g++.dg/cpp2a/concepts-requires21.C: Verify we no longer issue
a spurious unsatisfaction note when evaluating a
nested-requirement of a requires-expression that appears outside
of a template.
* g++.dg/cpp2a/concepts-nonbool3.C: New test.
* g++.dg/cpp2a/concepts-pr97093.C: New test.