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

--- Comment #13 from Martin Sebor <msebor at gcc dot gnu.org> ---
(In reply to Jakub Jelinek from comment #9)

Thanks for the nice test case!  The assumptions the warning makes aren't
accidental: it tries to detect bugs that would otherwise go undetected, and it
relies on the fact that the IL, although ambiguous (as in: matching both valid
code injected by GCC itself, as well as accidental bugs introduced by careless
programmers), corresponds to the source code more often than not.  It's a
trade-off between false negatives and false positives, with the balance
shifting each time a new transformation is added that breaks the assumption. 
The only way to do better is to make the IL reflect the distinction between the
two classes of uses).

The GIMPLE in the test case in comment #10 that causes the warning is this:

  p_2(D)->l = l_3(D);
  vectp.5_21 = &p_2(D)->t.a;
  MEM <vector(8) char> [(char *)vectp.5_21] = { 2, 3, 4, 5, 6, 7, 8, 9 };

and the warning sees that vectp.5_21 is just a pointer to p->t.a.  If, for
example, the IL instead looked like this:

  p_2(D)->l = l_3(D);
  MEM[(Vec8 *)p_2(D) + 8B] = { 2, 3, 4, 5, 6, 7, 8, 9 };
  vectp.10_14 = &p_2(D)->t.i;

the warning (as it is today) wouldn't trigger (Vec8 is a typedef for
__attribute__ ((vector_size (8))) char) because it doesn't know how to convert
offsets into structs into members (but that's just a limitation that I hope to
remove).  But even this IL is still ambiguous because it corresponds to this
assignment:

  *((Vec8*)&p->t.a) = (Vec8){ 2, 3, 4, 5, 6, 7, 8, 9 };

Here the overflow is intended to be detected but won't be.  Worse, a trivial
change to the code like so results in the former IL, bringing the warning back:

  *((__attribute__ ((vector_size (8))) char*)&p->t.a) = (__attribute__
((vector_size (8))) char){ 2, 3, 4, 5, 6, 7, 8, 9 };

To avoid this problem we just need to "encode" the cast in the MEM_REF
destination argument (or maybe the type of the offset) used by optimizers in a
way that doesn't correspond to a valid source code construct.  Or, more
generally, just use some unused bit in the MEM_REF representation to
distinguish the two cases.  I'm not an expert on GIMPLE so I don't have a good
sense of what would work or work best, but if the idea is sound I'll try to
look into it for GCC 11.

Reply via email to