c++: Fix invalid pointer-to-member in requires [PR67825]
authorJason Merrill <jason@redhat.com>
Sat, 4 Apr 2020 15:04:55 +0000 (11:04 -0400)
committerJason Merrill <jason@redhat.com>
Sat, 4 Apr 2020 15:06:31 +0000 (11:06 -0400)
A recent change to cmcstl2 led to two tests failing due to this bug: our
valid expression checking in the context of a requires-expression wasn't
catching that an expression of member function type can only appear as the
function operand of a call expression.  Fixed by using convert_to_void to do
the same checking as a discarded-value expression.

This patch also fixes 67825, which already had a testcase, but the testcase
was testing for the wrong behavior.

gcc/cp/ChangeLog
2020-04-04  Jason Merrill  <jason@redhat.com>

PR c++/67825
* constraint.cc (tsubst_valid_expression_requirement): Call
convert_to_void.

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

index f8229368eb984a74978c3339860e11538c5a9a98..860d5d36cf6fe9bae43befff6834c764fdcd866c 100644 (file)
@@ -1,3 +1,9 @@
+2020-04-04  Jason Merrill  <jason@redhat.com>
+
+       PR c++/67825
+       * constraint.cc (tsubst_valid_expression_requirement): Call
+       convert_to_void.
+
 2020-04-04  Jason Merrill  <jason@redhat.com>
 
        PR c++/94453
index 9c21ce80256d6a638f4bcc48e5c966c143bc66d7..e53084148798bf769f6ff13b855d4b33848e729f 100644 (file)
@@ -1864,7 +1864,10 @@ hash_placeholder_constraint (tree c)
 static tree
 tsubst_valid_expression_requirement (tree t, tree args, subst_info info)
 {
-  return tsubst_expr (t, args, info.complain, info.in_decl, false);
+  tree r = tsubst_expr (t, args, info.complain, info.in_decl, false);
+  if (convert_to_void (r, ICV_STATEMENT, info.complain) == error_mark_node)
+    return error_mark_node;
+  return r;
 }
 
 
diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-pmf1.C b/gcc/testsuite/g++.dg/cpp2a/concepts-pmf1.C
new file mode 100644 (file)
index 0000000..30d2b2d
--- /dev/null
@@ -0,0 +1,22 @@
+// Make sure that the requirement fails because a .* expression of function
+// type can only be used in a call.
+
+// { dg-do compile { target concepts } }
+
+template<class D, class T>
+constexpr decltype(auto) invoke(D (T::*pmd), T&& t)
+  noexcept(noexcept(t.*pmd))
+  requires requires { t.*pmd; }
+ { return t.*pmd; }
+
+char invoke(...);
+
+struct A
+{
+  int f();
+};
+
+int main()
+{
+  static_assert(sizeof(invoke (&A::f, A())) == 1);
+}
index 95698e99978ad94689bc006ca60acb18046933a5..fff414b8eb245825545481fd619d3025320998ae 100644 (file)
@@ -15,6 +15,6 @@ template <class X> concept bool C() {
 }
 
 int main() {
-  static_assert(C<A>());
+  static_assert(!C<A>());
   return 0;
 }