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.