This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
[Bug c++/84322] -fstrong-eval-order violated on assignment with function call
- From: "jakub at gcc dot gnu.org" <gcc-bugzilla at gcc dot gnu dot org>
- To: gcc-bugs at gcc dot gnu dot org
- Date: Wed, 14 Feb 2018 14:06:23 +0000
- Subject: [Bug c++/84322] -fstrong-eval-order violated on assignment with function call
- Auto-submitted: auto-generated
- References: <bug-84322-4@http.gcc.gnu.org/bugzilla/>
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?