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

Richard Biener <rguenth at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|UNCONFIRMED                 |NEW
   Last reconfirmed|                            |2017-08-21
                 CC|                            |msebor at gcc dot gnu.org
   Target Milestone|---                         |8.0
     Ever confirmed|0                           |1

--- Comment #1 from Richard Biener <rguenth at gcc dot gnu.org> ---
Probably caused by

  [/tmp/trunk/gcc/testsuite/gfortran.dg/alloc_comp_auto_array_2.f90:33:0] #
RANGE [-2147483648, 0] NONZERO 4294967292
  _260 = ubound.2_35 * 4;
  [/tmp/trunk/gcc/testsuite/gfortran.dg/alloc_comp_auto_array_2.f90:33:0] #
RANGE ~[1, 2147483647] NONZERO 4294967292
  _261 = (character(kind=4)) _260;
...
  __builtin_memcpy (_264, _272, _261);

where the warning machinery simply doesn't consider the valid input _261 == 0.

get_size_range runs into

      else if (wi::eq_p (wzero, min - 1))
        {
          /* EXP is unsigned and not in the range [1, MAX].  That means
             it's either zero or greater than MAX.  Even though 0 would
             normally be detected by -Walloc-zero set the range to
             [MAX, TYPE_MAX] so that when MAX is greater than the limit
             the whole range is diagnosed.  */
          min = max + 1;
          max = wmaxval;

I totally detest this anti-range handling.  It's completely bogus.  For
whatever reason it _does_ want to diagnose here.

So - INVALID, working as designed?!

The comment is wrong btw,  EXP is in the range 0 U [max + 1, wmaxval].
'MAX' is used inconsistently -- nothing is bigger than 'MAX' unless
'MAX' is maximum value that is positive when interpreted signed.  But
wmaxval is unsigned.

Suggested patch:

Index: gcc/calls.c
===================================================================
--- gcc/calls.c (revision 251217)
+++ gcc/calls.c (working copy)
@@ -1327,7 +1327,8 @@ get_size_range (tree exp, tree range[2])
              min = wzero;
            }
        }
-      else if (wi::eq_p (wzero, min - 1))
+      else if (wi::eq_p (wzero, min - 1)
+              && wi::lts_p (max, wi::max_value (expprec, SIGNED)))
        {
          /* EXP is unsigned and not in the range [1, MAX].  That means
             it's either zero or greater than MAX.  Even though 0 would

that (for this sub-case of anit-range handling) tries to preserve
anti-range ^ valid-size-range if not empty.  I think that's a must
to get false positives to a minimum.

Reply via email to