aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2020-04-04 11:04:55 -0400
committerJason Merrill <jason@redhat.com>2020-04-04 11:06:31 -0400
commitf1ad7bac76b662577e3bde78c530954099361a66 (patch)
tree004cc66d52a4f6c00c0f39cfce25b563cb6a8421
parent9f143008c73c60e02634d6b433139a035ef7bb65 (diff)
downloadgcc-f1ad7bac76b662577e3bde78c530954099361a66.zip
gcc-f1ad7bac76b662577e3bde78c530954099361a66.tar.gz
gcc-f1ad7bac76b662577e3bde78c530954099361a66.tar.bz2
c++: Fix invalid pointer-to-member in requires [PR67825]
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.
-rw-r--r--gcc/cp/ChangeLog6
-rw-r--r--gcc/cp/constraint.cc5
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/concepts-pmf1.C22
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/concepts-pr67825.C2
4 files changed, 33 insertions, 2 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index f822936..860d5d3 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,5 +1,11 @@
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
* constexpr.c (maybe_constant_value): Use break_out_target_exprs.
* expr.c (mark_use) [VIEW_CONVERT_EXPR]: Don't wrap a TARGET_EXPR in
diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
index 9c21ce8..e530841 100644
--- a/gcc/cp/constraint.cc
+++ b/gcc/cp/constraint.cc
@@ -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
index 0000000..30d2b2d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/concepts-pmf1.C
@@ -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);
+}
diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-pr67825.C b/gcc/testsuite/g++.dg/cpp2a/concepts-pr67825.C
index 95698e9..fff414b 100644
--- a/gcc/testsuite/g++.dg/cpp2a/concepts-pr67825.C
+++ b/gcc/testsuite/g++.dg/cpp2a/concepts-pr67825.C
@@ -15,6 +15,6 @@ template <class X> concept bool C() {
}
int main() {
- static_assert(C<A>());
+ static_assert(!C<A>());
return 0;
}