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.
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));
--- /dev/null
+// { 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 ();
+}