https://gcc.gnu.org/bugzilla/show_bug.cgi?id=119466
--- Comment #2 from Jakub Jelinek <jakub at gcc dot gnu.org> --- I think w normally honor the C++17 rules, it can be seen on int foo (int &x, int *&y) { y = &x; x++; return x; } int & bar (int *p) { return *p; } int main () { int a = 4; int b = 9; int *c = &b; bar (c) = foo (a, c); __builtin_printf ("%d %d %d\n", a, *c, b); } which prints 5 5 9 and calls bar after calling foo, including reading the c pointer from memory. Bet this is just that *c has no side-effects. cp_gimplify_expr has for this: /* P0145 says that the RHS is sequenced before the LHS. gimplify_modify_expr gimplifies the RHS before the LHS, but that isn't quite strong enough in two cases: 1) gimplify.cc wants to leave a CALL_EXPR on the RHS, which would mean it's evaluated after the LHS. 2) the value calculation of the RHS is also sequenced before the LHS, so for scalar assignment we need to preevaluate if the RHS could be affected by LHS side-effects even if it has no side-effects of its own. We don't need this for classes because class assignment takes its RHS by reference. */ else if (flag_strong_eval_order > 1 && TREE_CODE (*expr_p) == MODIFY_EXPR && lvalue_has_side_effects (op0) && (TREE_CODE (op1) == CALL_EXPR || (SCALAR_TYPE_P (TREE_TYPE (op1)) && !TREE_CONSTANT (op1)))) TREE_OPERAND (*expr_p, 1) = get_initialized_tmp_var (op1, pre_p);