PR c++/92268 - hard error satisfying return-type-requirement
authorJason Merrill <jason@redhat.com>
Thu, 31 Oct 2019 02:01:16 +0000 (22:01 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Thu, 31 Oct 2019 02:01:16 +0000 (22:01 -0400)
Previously we would put the template arguments for the concept-check in a
TEMPLATE_ID and then also pass them to constraints_satisfied_p, which meant
that we would try to normalize the concept-check with the fully instantiated
arguments, leading to sadness.  Simply not passing the args to
constraints_satisfied_p fixes the problem.

I also noticed that we weren't detecting substitution failure in the
constraints, but were silently treating it as success.

* constraint.cc (type_deducible_p): Check for substitution failure.
(diagnose_compound_requirement): Adjust diagnostic.
* pt.c (do_auto_deduction): Don't pass cargs to
constraints_satisfied_p.

From-SVN: r277654

gcc/cp/ChangeLog
gcc/cp/constraint.cc
gcc/cp/pt.c
gcc/testsuite/g++.dg/concepts/diagnostic1.C
gcc/testsuite/g++.dg/concepts/placeholder3.C
gcc/testsuite/g++.dg/concepts/placeholder4.C
gcc/testsuite/g++.dg/cpp2a/concepts-pr67178.C
gcc/testsuite/g++.dg/cpp2a/concepts-requires6.C
gcc/testsuite/g++.dg/cpp2a/concepts-return-req1.C [new file with mode: 0644]

index efb135e..585420a 100644 (file)
@@ -1,3 +1,11 @@
+2019-10-30  Jason Merrill  <jason@redhat.com>
+
+       PR c++/92268 - hard error satisfying return-type-requirement
+       * constraint.cc (type_deducible_p): Check for substitution failure.
+       (diagnose_compound_requirement): Adjust diagnostic.
+       * pt.c (do_auto_deduction): Don't pass cargs to
+       constraints_satisfied_p.
+
 2019-10-30  Jakub Jelinek  <jakub@redhat.com>
 
        PR c++/91369 - Implement P0784R7: constexpr new
index b8a2645..db2a30c 100644 (file)
@@ -1822,10 +1822,7 @@ tsubst_type_requirement (tree t, tree args, subst_info info)
   return finish_type_requirement (EXPR_LOCATION (t), type);
 }
 
-/* True if TYPE can be deduced from EXPR.
-
-   FIXME: C++20 compound requirement constraints should be normalized and then
-   satisfied rather than substituted.  */
+/* True if TYPE can be deduced from EXPR.  */
 
 static bool
 type_deducible_p (tree expr, tree type, tree placeholder, tree args,
@@ -1839,12 +1836,17 @@ type_deducible_p (tree expr, tree type, tree placeholder, tree args,
      substitutes args into any template parameters in the trailing
      result type.  */
   tree saved_constr = PLACEHOLDER_TYPE_CONSTRAINTS (placeholder);
-  PLACEHOLDER_TYPE_CONSTRAINTS (placeholder)
+  tree subst_constr
     = tsubst_constraint (saved_constr,
                         args,
                         info.complain | tf_partial,
                         info.in_decl);
 
+  if (subst_constr == error_mark_node)
+    return false;
+
+  PLACEHOLDER_TYPE_CONSTRAINTS (placeholder) = subst_constr;
+
   /* Temporarily unlink the canonical type.  */
   tree saved_type = TYPE_CANONICAL (placeholder);
   TYPE_CANONICAL (placeholder) = NULL_TREE;
@@ -3139,7 +3141,8 @@ diagnose_compound_requirement (tree req, tree args, tree in_decl)
          if (!type_deducible_p (expr, type, placeholder, args, quiet))
            {
              tree orig_expr = TREE_OPERAND (req, 0);
-             inform (loc, "type deduction from %qE failed", orig_expr);
+             inform (loc, "%qE does not satisfy return-type-requirement",
+                     orig_expr);
 
              /* Further explain the reason for the error.  */
              type_deducible_p (expr, type, placeholder, args, noisy);
index c5675dd..414140a 100644 (file)
@@ -28138,7 +28138,7 @@ do_auto_deduction (tree type, tree init, tree auto_node,
        /* Rebuild the check using the deduced arguments.  */
        check = build_concept_check (cdecl, cargs, tf_none);
 
-       if (!constraints_satisfied_p (check, cargs))
+       if (!constraints_satisfied_p (check))
           {
             if (complain & tf_warning_or_error)
               {
index ced56d4..7da08db 100644 (file)
@@ -8,12 +8,12 @@ concept bool SameAs = __is_same_as(T, U);
 template <class T>
 concept bool R1 = requires (T& t) { // { dg-message "in requirements" }
   { t.begin() } -> T;          // { dg-error "no match" }
-  { t.end() } -> SameAs<T*>;   // { dg-error "does not satisfy" }
+  { t.end() } -> SameAs<T*>;   // { dg-message "does not satisfy" }
 };
 
 template <class T>
 concept bool R2 = requires (T& t) { // { dg-message "in requirements" }
-  { t.end() } -> SameAs<T*>;   // { dg-error "does not satisfy" }
+  { t.end() } -> SameAs<T*>;   // { dg-message "does not satisfy" }
 };
 
 struct foo {
index 4f8600b..d90e5cf 100644 (file)
@@ -8,7 +8,7 @@ concept bool Same = __is_same_as(T, U);
 template <class T>
 concept bool C =
   requires { // { dg-message "in requirements" }
-    { 0 } -> Same<T>;          // { dg-error "does not satisfy" }
+    { 0 } -> Same<T>;          // { dg-message "does not satisfy" }
   };
 
 template <C c>
index 2b5afbb..ab9d8e6 100644 (file)
@@ -8,7 +8,7 @@ concept bool Same = __is_same_as(T, U);
 template <class T>
 concept bool C =
   requires { // { dg-message "in requirements" }
-    { 0 } -> Same<T>;          // { dg-error "does not satisfy" }
+    { 0 } -> Same<T>;          // { dg-message "does not satisfy" }
   };
 
 template <class T>
index f76f2e3..264b873 100644 (file)
@@ -12,7 +12,7 @@ concept C0 = requires (auto x) { // { dg-error "placeholder type" }
 template<typename T>
 concept C1 = requires (C1 auto x) { // { dg-error "not been declared|placeholder|two or more|in requirements" }
   x; // { dg-error "not declared" }
-  { x } -> c; // { dg-error "not declared|does not satisfy" }
+  { x } -> c; // { dg-message "not declared|does not satisfy" }
 };
 
 template<typename T>
index 20df78b..065876e 100644 (file)
@@ -10,7 +10,7 @@ concept SameAs = __is_same_as(T, U);
 template <typename T>
 concept C1 = requires(T t) { // { dg-message "in requirements" }
   { t } -> SameAs<T>; // NOTE: t deduced as decltype((t))
-  // { dg-error "does not satisfy placeholder constraints" "" { target *-*-* } .-1 }
+  // { dg-message "does not satisfy" "" { target *-*-* } .-1 }
 };
 
 template <typename T>
diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-return-req1.C b/gcc/testsuite/g++.dg/cpp2a/concepts-return-req1.C
new file mode 100644 (file)
index 0000000..1d005f0
--- /dev/null
@@ -0,0 +1,19 @@
+// PR c++/92268
+// { dg-do compile { target c++2a } }
+
+template <class T> concept Two = true;
+template <class T> concept One = Two<typename T::type>;
+template <class T> concept Zero = requires
+  {
+   { T() } -> One;
+  };
+
+template <class T>
+void f() requires Zero<T>;
+template <class T>
+int f(...);
+
+int main()
+{
+  f<int>();
+}