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.

Reply via email to