PR 120618

gcc/cp/ChangeLog:

        * constraint.cc (tsubst_compound_requirement): Return NULL_TREE when t1
        is not a TEMPLATE_TYPE_PARM
        (tsubst_requires_expr): Propagate failure when the compound
        requirement has an ill-formed type-constraint

gcc/testsuite/ChangeLog:

        * g++.dg/concepts/pr120618.C: New test.

This testcase caused an ICE in mangle.cc when attempting to mangle the
compound requirement
`requires (!requires(T t) { { t } -> bool; })`, since
write_type_constraint expects a TEMPLATE_TYPE_PARM.

When instantiating the call `foo(b)`, the constraint `requires(T t) {
{ t } -> bool; }` seems to be
cached as a boolean_false_node, so the constraints were met due to the
TRUTH_NOT_EXPR even though
the type-constraint was invalid. This was Andrew's hypothesis which we
discussed on irc, and it seems to be correct from what I
tried to do here.

This patch attempts to bail out when building a call for a function
with an ill-formed type-constraint in a
compound requirement.

Bootstrapped and tested with check-gcc-c++ on x86_64-linux-gnu  (I did
not see new regressions with compare_tests). Could someone help
review?

Thanks.

Suggested-by: Andrew Pinski <quic_apin...@quicinc.com>

---
 gcc/cp/constraint.cc                     |  8 ++++++++
 gcc/testsuite/g++.dg/concepts/pr120618.C | 13 +++++++++++++
 2 files changed, 21 insertions(+)
 create mode 100644 gcc/testsuite/g++.dg/concepts/pr120618.C

diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
index cbdfafc90c0..a9f6bcc9c69 100644
--- a/gcc/cp/constraint.cc
+++ b/gcc/cp/constraint.cc
@@ -1478,6 +1478,9 @@ tsubst_compound_requirement (tree t, tree args,
sat_info info)
 {
   tree t0 = TREE_OPERAND (t, 0);
   tree t1 = TREE_OPERAND (t, 1);
+  if (t1 && TREE_CODE (t1) != TEMPLATE_TYPE_PARM)
+    return NULL_TREE;
+
   tree expr = tsubst_valid_expression_requirement (t0, args, info);
   if (expr == error_mark_node)
     return error_mark_node;
@@ -1744,6 +1747,11 @@ tsubst_requires_expr (tree t, tree args, sat_info info)
          else
            break;
        }
+      else if (req == NULL_TREE)
+        {
+          result = error_mark_node;
+          break;
+        }
       else if (processing_template_decl)
        result = tree_cons (NULL_TREE, req, result);
     }
diff --git a/gcc/testsuite/g++.dg/concepts/pr120618.C
b/gcc/testsuite/g++.dg/concepts/pr120618.C
new file mode 100644
index 00000000000..13f390a7aa0
--- /dev/null
+++ b/gcc/testsuite/g++.dg/concepts/pr120618.C
@@ -0,0 +1,13 @@
+// { dg-do compile { target c++17 } }
+// { dg-options "-fconcepts" }
+
+class B{};
+
+template <typename T>
+requires (!requires(T t) { { t } -> bool; }) // { dg-error
"return-type-requirement is not a type-constraint" }
+void foo(T t) {}
+
+int main() {
+  B b;
+  foo(b); // { dg-error "no matching function" }
+}
--
2.43.0

Reply via email to