aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp/constraint.cc
diff options
context:
space:
mode:
authorPatrick Palka <ppalka@redhat.com>2020-12-17 22:18:07 -0500
committerPatrick Palka <ppalka@redhat.com>2020-12-17 22:18:07 -0500
commit79f57d5cb070bb02ea0a34b5f42658d6659b19a8 (patch)
treeb7dba72ed8e157d1c7895c62e038be36cba7a903 /gcc/cp/constraint.cc
parent20f292863f6ed230335c443893d4db664a8140d0 (diff)
downloadgcc-79f57d5cb070bb02ea0a34b5f42658d6659b19a8.zip
gcc-79f57d5cb070bb02ea0a34b5f42658d6659b19a8.tar.gz
gcc-79f57d5cb070bb02ea0a34b5f42658d6659b19a8.tar.bz2
c++: Diagnose self-recursive satisfaction
This patch further extends the satisfaction_cache class to diagnose self-recursive satisfaction. gcc/cp/ChangeLog: * constraint.cc (sat_entry::evaluating): New member. (satisfaction_cache::get): If entry->evaluating, diagnose self-recursive satisfaction. Otherwise, set entry->evaluating if we're not reusing a cached satisfaction result. (satisfaction_cache::save): Clear entry->evaluating. (satisfy_atom): Set up diagnosing_failed_constraint before the first call to get(). gcc/testsuite/ChangeLog: PR c++/96840 * g++.dg/cpp2a/concepts-pr88395.C: Adjust to expect the self-recursive satisfaction to get directly diagnosed. * g++.dg/cpp2a/concepts-recursive-sat2.C: Likewise. * g++.dg/cpp2a/concepts-recursive-sat4.C: New test.
Diffstat (limited to 'gcc/cp/constraint.cc')
-rw-r--r--gcc/cp/constraint.cc39
1 files changed, 31 insertions, 8 deletions
diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
index 47cf882..40e499b 100644
--- a/gcc/cp/constraint.cc
+++ b/gcc/cp/constraint.cc
@@ -2428,6 +2428,11 @@ struct GTY((for_user)) sat_entry
We don't always want to do so, in order to avoid emitting duplicate
diagnostics in some cases. */
bool diagnose_instability;
+
+ /* True if we're in the middle of computing this satisfaction result.
+ Used during both quiet and noisy satisfaction to detect self-recursive
+ satisfaction. */
+ bool evaluating;
};
struct sat_hasher : ggc_ptr_hash<sat_entry>
@@ -2572,6 +2577,7 @@ satisfaction_cache
mapping, we set this flag (in satisfy_atom) only if substitution
into its mapping previously failed. */
entry->diagnose_instability = true;
+ entry->evaluating = false;
*slot = entry;
}
else
@@ -2590,9 +2596,23 @@ satisfaction_cache::get ()
if (!entry)
return NULL_TREE;
- if (info.noisy () || entry->maybe_unstable)
- /* We're recomputing the satisfaction result from scratch. */
- return NULL_TREE;
+ if (entry->evaluating)
+ {
+ /* If we get here, it means satisfaction is self-recursive. */
+ gcc_checking_assert (!entry->result);
+ if (info.noisy ())
+ error_at (EXPR_LOCATION (ATOMIC_CONSTR_EXPR (entry->atom)),
+ "satisfaction of atomic constraint %qE depends on itself",
+ entry->atom);
+ return error_mark_node;
+ }
+
+ if (info.noisy () || entry->maybe_unstable || !entry->result)
+ {
+ /* We're computing the satisfaction result from scratch. */
+ entry->evaluating = true;
+ return NULL_TREE;
+ }
else
return entry->result;
}
@@ -2607,6 +2627,9 @@ satisfaction_cache::save (tree result)
if (!entry)
return result;
+ gcc_checking_assert (entry->evaluating);
+ entry->evaluating = false;
+
if (entry->result && result != entry->result)
{
if (info.quiet ())
@@ -2856,6 +2879,11 @@ static void diagnose_atomic_constraint (tree, tree, tree, subst_info);
static tree
satisfy_atom (tree t, tree args, sat_info info)
{
+ /* In case there is a diagnostic, we want to establish the context
+ prior to printing errors. If no errors occur, this context is
+ removed before returning. */
+ diagnosing_failed_constraint failure (t, args, info.noisy ());
+
satisfaction_cache cache (t, args, info);
if (tree r = cache.get ())
return r;
@@ -2863,11 +2891,6 @@ satisfy_atom (tree t, tree args, sat_info info)
/* Perform substitution quietly. */
subst_info quiet (tf_none, NULL_TREE);
- /* In case there is a diagnostic, we want to establish the context
- prior to printing errors. If no errors occur, this context is
- removed before returning. */
- diagnosing_failed_constraint failure (t, args, info.noisy ());
-
/* Instantiate the parameter mapping. */
tree map = tsubst_parameter_mapping (ATOMIC_CONSTR_MAP (t), args, quiet);
if (map == error_mark_node)