From b2b8eb6202b83218cf135eebbf992a833057f6bf Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Fri, 22 May 2020 17:06:57 -0400 Subject: [PATCH] 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. --- gcc/cp/cp-gimplify.c | 1 + gcc/testsuite/g++.dg/cpp1z/eval-order9.C | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+) create mode 100644 gcc/testsuite/g++.dg/cpp1z/eval-order9.C 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 (); +} -- 2.30.2