aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2020-05-22 17:06:57 -0400
committerJason Merrill <jason@redhat.com>2020-05-22 20:50:31 -0400
commitb2b8eb6202b83218cf135eebbf992a833057f6bf (patch)
tree3e09437f142519248dbb6f0d7bd4039c3b6284bc /gcc
parentfabd4f16a15690d38b335c0471d1b1ca94ed1b34 (diff)
downloadgcc-b2b8eb6202b83218cf135eebbf992a833057f6bf.zip
gcc-b2b8eb6202b83218cf135eebbf992a833057f6bf.tar.gz
gcc-b2b8eb6202b83218cf135eebbf992a833057f6bf.tar.bz2
c++: Fix C++17 eval order for virtual op=.
In a function call expression in C++17 evaluation of the function pointer is sequenced before evaluation of the function arguments, but that doesn't apply to function calls that were written using operator syntax. In particular, for operators with right-to-left ordering like assignment, we must not evaluate the LHS to find a virtual function before we evaluate the RHS. gcc/cp/ChangeLog: * cp-gimplify.c (cp_gimplify_expr) [CALL_EXPR]: Don't preevaluate the function address if the call used operator syntax. gcc/testsuite/ChangeLog: * g++.dg/cpp1z/eval-order9.C: New test.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/cp-gimplify.c1
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/eval-order9.C18
2 files changed, 19 insertions, 0 deletions
diff --git a/gcc/cp/cp-gimplify.c b/gcc/cp/cp-gimplify.c
index 2804958..b60a319 100644
--- a/gcc/cp/cp-gimplify.c
+++ b/gcc/cp/cp-gimplify.c
@@ -852,6 +852,7 @@ cp_gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)
ret = GS_OK;
if (flag_strong_eval_order == 2
&& CALL_EXPR_FN (*expr_p)
+ && !CALL_EXPR_OPERATOR_SYNTAX (*expr_p)
&& cp_get_callee_fndecl_nofold (*expr_p) == NULL_TREE)
{
tree fnptrtype = TREE_TYPE (CALL_EXPR_FN (*expr_p));
diff --git a/gcc/testsuite/g++.dg/cpp1z/eval-order9.C b/gcc/testsuite/g++.dg/cpp1z/eval-order9.C
new file mode 100644
index 0000000..7001f5a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/eval-order9.C
@@ -0,0 +1,18 @@
+// { dg-do run }
+// { dg-additional-options -fstrong-eval-order=all }
+
+struct A
+{
+ virtual A& operator=(const A&) { return *this; }
+};
+
+int i;
+
+A& f() { if (i != 1) __builtin_abort (); i = 2; static A a; return a; }
+A& g() { if (i != 0) __builtin_abort (); i = 1; static A a; return a; }
+
+int main()
+{
+ f() = g();
+ if (i != 2) __builtin_abort ();
+}