c++: Diagnose unstable satisfaction
This implements lightweight heuristical detection and diagnosing of
satisfaction whose result changes at different points in the program,
which renders the program ill-formed NDR as of P2104. We've recently
started to more aggressively cache satisfaction results, and so the goal
with this patch is to make this caching behavior more transparent to
the user.
A satisfaction result is flagged as "potentially unstable" (at the atom
granularity) if during its computation, some type completion failure
occurs. This is detected by making complete_type_or_maybe_complain
increment a counter upon failure and comparing the value of the counter
before and after satisfaction. (We don't instrument complete_type
directly because it's used "opportunistically" in many spots where type
completion failure doesn't necessary lead to substitution failure.)
Such flagged satisfaction results are always recomputed from scratch,
even when performing satisfaction quietly. When saving a satisfaction
result, we now compare the computed result with the cached result, and
if they differ, proceed with diagnosing the instability.
Most of the implementation is confined to the satisfaction_cache class,
which has been completely rewritten.
gcc/cp/ChangeLog:
* constraint.cc (failed_type_completion_count): New.
(note_failed_type_completion_for_satisfaction): New.
(sat_entry::constr): Rename to ...
(sat_entry::atom): ... this.
(sat_entry::location): New member.
(sat_entry::maybe_unstable): New member.
(sat_entry::diagnose_instability): New member.
(struct sat_hasher): Adjust after the above renaming.
(get_satisfaction, save_satisfaction): Remove.
(satisfaction_cache): Rewrite completely.
(satisfy_atom): When instantiation of the parameter mapping
fails, set diagnose_instability. Propagate location from
inst_cache.entry to cache.entry if the secondary lookup
succeeded.
(satisfy_declaration_constraints): When
failed_type_completion_count differs before and after
satisfaction, then don't cache the satisfaction result.
* cp-tree.h (note_failed_type_completion_for_satisfaction):
Declare.
* pt.c (tsubst) <case TYPENAME_TYPE>: Use
complete_type_or_maybe_complain instead of open-coding it.
* typeck.c (complete_type_or_maybe_complain): Call
note_failed_type_completion_for_satisfaction when type
completion fails.
gcc/testsuite/ChangeLog:
* g++.dg/cpp2a/concepts-complete1.C: New test.
* g++.dg/cpp2a/concepts-complete2.C: New test.
* g++.dg/cpp2a/concepts-complete3.C: New test.