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.