[gcc/devel/c++-modules] c++: Fix C++17 eval order for virtual op=.

Nathan Sidwell nathan@gcc.gnu.org
Wed Jun 10 16:42:07 GMT 2020


https://gcc.gnu.org/g:b2b8eb6202b83218cf135eebbf992a833057f6bf

commit b2b8eb6202b83218cf135eebbf992a833057f6bf
Author: Jason Merrill <jason@redhat.com>
Date:   Fri May 22 17:06:57 2020 -0400

    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.

Diff:
---
 gcc/cp/cp-gimplify.c                     |  1 +
 gcc/testsuite/g++.dg/cpp1z/eval-order9.C | 18 ++++++++++++++++++
 2 files changed, 19 insertions(+)

diff --git a/gcc/cp/cp-gimplify.c b/gcc/cp/cp-gimplify.c
index 2804958c246..b60a319283f 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 00000000000..7001f5a7b52
--- /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 ();
+}


More information about the Gcc-cvs mailing list