https://gcc.gnu.org/bugzilla/show_bug.cgi?id=118521
--- Comment #7 from Jeffrey A. Law <law at gcc dot gnu.org> --- In the simplified testcase we have: <bb 3> [local count: 131235111]: MEM <unsigned char[2]> [(char * {ref-all})_53] = MEM <unsigned char[2]> [(char * {ref-all})&C.0]; __result_46 = _53 + 2; _150 = operator new (4); goto <bb 5>; [100.00%] So _150 points to a 4 byte chunk of memory. (gdb) p debug_bb_n (5) <bb 5> [local count: 131235112]: _97 = _150 + 2; [ ... ] So _97 points two bytes into that chunk of memory. <bb 6> [local count: 108360832]: MEM[(char *)_97 + 2B] = 1; Two more bytes in would be offset 4. Writing to that byte is out of bounds. The original testcase as the same basic structure: (gdb) p debug_bb_n (3) <bb 3> [local count: 131235111]: MEM <unsigned char[2]> [(char * {ref-all})_46] = MEM <unsigned char[2]> [(char * {ref-all})&C.0]; __result_39 = _46 + 2; _143 = operator new (4); goto <bb 5>; [100.00%] <bb 5> [local count: 131235112]: _90 = _143 + 2; [ ... ] <bb 6> [local count: 108360832]: MEM[(char *)_90 + 2B] = 1; So I think that answers most of the questions in c#4. With the presented IL the warning is reasonable. The real issue here is a failure to optimize the conditional at the end of bb5. <bb 5> [local count: 131235112]: _90 = _143 + 2; __builtin_memset (_90, 0, 2); MEM <unsigned short> [(char * {ref-all})_143] = 513; __result_188 = _143 + 1; __new_finish_99 = __result_188 + 3; operator delete (_46, 2); _108 = _143 + 4; if (__new_finish_99 != _108) goto <bb 6>; [82.57%] else goto <bb 7>; [17.43%] __new_finish_99 != _108 is statically computable. Substituting on the LHS we get (_143 + 1) + 3 != _108 And substiuting on the LHS: (_143 + 1) + 3 != _143 + 4 Which are obviously equivalent. That would make bb5 always transfer control to bb7 and avoid the bogus warning.