https://gcc.gnu.org/bugzilla/show_bug.cgi?id=84322
Jakub Jelinek <jakub at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |jakub at gcc dot gnu.org, | |jason at gcc dot gnu.org --- Comment #2 from Jakub Jelinek <jakub at gcc dot gnu.org> --- We have: 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_formal_tmp_var (op1, pre_p); but lvalue_has_side_effects does nothing if TREE_SIDE_EFFECTS is 0: static bool lvalue_has_side_effects (tree e) { if (!TREE_SIDE_EFFECTS (e)) return false; while (handled_component_p (e)) { if (TREE_CODE (e) == ARRAY_REF && TREE_SIDE_EFFECTS (TREE_OPERAND (e, 1))) return true; e = TREE_OPERAND (e, 0); } if (DECL_P (e)) /* Just naming a variable has no side-effects. */ return false; else if (INDIRECT_REF_P (e)) /* Similarly, indirection has no side-effects. */ return TREE_SIDE_EFFECTS (TREE_OPERAND (e, 0)); else /* For anything else, trust TREE_SIDE_EFFECTS. */ return TREE_SIDE_EFFECTS (e); } A mere read from memory is not accounted for in TREE_SIDE_EFFECTS, but as the testcase shows, we probably need to consider it as a side-effect too. What about: extern int a[10]; int g (); void f () { *(a + a[1]) = g (); } or any other arbitrary expressions on the LHS which can read from needs_to_live_in_memory variables? I'm also wondering about if (!error_operand_p (op0) && !error_operand_p (op1) && (TYPE_STRUCTURAL_EQUALITY_P (TREE_TYPE (op0)) || TYPE_STRUCTURAL_EQUALITY_P (TREE_TYPE (op1))) && !useless_type_conversion_p (TREE_TYPE (op1), TREE_TYPE (op0))) TREE_OPERAND (*expr_p, 1) = build1 (VIEW_CONVERT_EXPR, TREE_TYPE (op0), op1); after which the P0145 checks aren't done, can it ever happen that op1 is a CALL_EXPR in this case?