c++: Check constraints before instantiation from mark_used [PR95132]
authorPatrick Palka <ppalka@redhat.com>
Wed, 28 Oct 2020 15:47:26 +0000 (11:47 -0400)
committerPatrick Palka <ppalka@redhat.com>
Wed, 28 Oct 2020 15:47:26 +0000 (11:47 -0400)
This makes mark_used check constraints of a function _before_ calling
maybe_instantiate_decl, so that we don't try instantiating a function
(as part of return type deduction) with unsatisfied constraints.

gcc/cp/ChangeLog:

PR c++/95132
* decl2.c (mark_used): Move up the constraints_satisfied_p check
so that we check constraints before calling maybe_instantiate_decl.

gcc/testsuite/ChangeLog:

PR c++/95132
* g++.dg/cpp2a/concepts-fn7.C: New test.

gcc/cp/decl2.c
gcc/testsuite/g++.dg/cpp2a/concepts-fn7.C [new file with mode: 0644]

index 6fd081463f7b00c000ab304efc50e468f5dfb58c..71107e03010983602e66bf0179acda0198eec276 100644 (file)
@@ -5588,16 +5588,6 @@ mark_used (tree decl, tsubst_flags_t complain)
   if (DECL_ODR_USED (decl))
     return true;
 
-  /* Normally, we can wait until instantiation-time to synthesize DECL.
-     However, if DECL is a static data member initialized with a constant
-     or a constexpr function, we need it right now because a reference to
-     such a data member or a call to such function is not value-dependent.
-     For a function that uses auto in the return type, we need to instantiate
-     it to find out its type.  For OpenMP user defined reductions, we need
-     them instantiated for reduction clauses which inline them by hand
-     directly.  */
-  maybe_instantiate_decl (decl);
-
   if (flag_concepts && TREE_CODE (decl) == FUNCTION_DECL
       && !constraints_satisfied_p (decl))
     {
@@ -5613,6 +5603,16 @@ mark_used (tree decl, tsubst_flags_t complain)
       return false;
     }
 
+  /* Normally, we can wait until instantiation-time to synthesize DECL.
+     However, if DECL is a static data member initialized with a constant
+     or a constexpr function, we need it right now because a reference to
+     such a data member or a call to such function is not value-dependent.
+     For a function that uses auto in the return type, we need to instantiate
+     it to find out its type.  For OpenMP user defined reductions, we need
+     them instantiated for reduction clauses which inline them by hand
+     directly.  */
+  maybe_instantiate_decl (decl);
+
   if (processing_template_decl || in_template_function ())
     return true;
 
diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-fn7.C b/gcc/testsuite/g++.dg/cpp2a/concepts-fn7.C
new file mode 100644 (file)
index 0000000..62111df
--- /dev/null
@@ -0,0 +1,11 @@
+// PR c++/95132
+// { dg-do compile { target c++20 } }
+
+template <class T> struct A {
+  static auto f() requires false { return T::fail; }
+};
+
+template <class T>
+concept C = requires { A<T>::f(); };
+
+static_assert(!C<int>);