https://gcc.gnu.org/bugzilla/show_bug.cgi?id=115160

--- Comment #6 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
There is no inc in the last term.

Anyway, simplified example would be
int deref (int *);
int *inc (int *&);

int
baz (int *p)
{
  return deref (inc (p)) | (deref (inc (p)) << 8) | (deref (inc (p)) << 16) |
(deref (p) << 24);
}
and while without the sanitization GCC chooses to evaluate this left to right,
with
sanitization it first turns it into essentially:
  return deref (inc (p)) | ((tmp1 = deref (inc (p))), check_shift (tmp1, 8),
tmp1 << 8) | ((tmp2 = deref (inc (p))), check_shift (tmp2, 16), tmp2 << 16) |
((tmp3 = deref (p)), check_shift (tmp3, 24), tmp3 << 24);
but then further optimizations move the comma expression left hand sides before
the whole |, so it first evaluates the second deref+inc + checks the shift by
8, then
the third deref+inc + checks the shift by 16 etc. and then only the |
expressions and this is still valid due to the unspecified order of | operand
evaluations.

Reply via email to