c++: checking ICE with diagnosed constraint recursion [PR100288]
authorPatrick Palka <ppalka@redhat.com>
Thu, 16 Mar 2023 18:22:54 +0000 (14:22 -0400)
committerPatrick Palka <ppalka@redhat.com>
Thu, 16 Mar 2023 18:22:54 +0000 (14:22 -0400)
When satisfaction_cache::get detects constraint recursion, it asserts
that entry->result is empty.  This makes sense when we're initially
detecting/diagnosing recursion from the inner recursive call, but
afterwards from the outer recursive call the recursion error is treated
like any other unrelated constraint failure encountered during
satisfaction, and we set entry->result to whatever the satisfaction
value ended up being.

Perhaps we should keep entry->result cleared in this case, but that'd
require the inner recursive call to communicate to the outer recursive
call that constraint recursion occurred, likely via setting entry->result
to some sentinel value, which doesn't seem to be worth the complexity.
So this patch just relaxes the problematic assert to accept non-empty
entry->result as long as we've already issued an error.

PR c++/100288

gcc/cp/ChangeLog:

* constraint.cc (satisfaction_cache::get): Relax overly strict
checking assert in the constraint recursion case.

gcc/testsuite/ChangeLog:

* g++.dg/cpp2a/concepts-recursive-sat5.C: New test.

gcc/cp/constraint.cc
gcc/testsuite/g++.dg/cpp2a/concepts-recursive-sat5.C [new file with mode: 0644]

index a28c851..273d15a 100644 (file)
@@ -2705,7 +2705,7 @@ satisfaction_cache::get ()
   if (entry->evaluating)
     {
       /* If we get here, it means satisfaction is self-recursive.  */
-      gcc_checking_assert (!entry->result);
+      gcc_checking_assert (!entry->result || seen_error ());
       if (info.noisy ())
        error_at (EXPR_LOCATION (ATOMIC_CONSTR_EXPR (entry->atom)),
                  "satisfaction of atomic constraint %qE depends on itself",
diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-recursive-sat5.C b/gcc/testsuite/g++.dg/cpp2a/concepts-recursive-sat5.C
new file mode 100644 (file)
index 0000000..ba56487
--- /dev/null
@@ -0,0 +1,13 @@
+// PR c++/100288
+// { dg-do compile { target c++20 } }
+
+struct A { };
+
+template<typename T> concept pipeable = requires(A a, T t) { a | t; }; // { dg-error "depends on itself" }
+
+template<pipeable T> void operator|(A, T);
+
+void f(A tab) {
+  tab | 1; // { dg-error "no match" }
+  tab | 1; // { dg-error "no match" }
+}