On 3/12/21 6:27 AM, Jakub Jelinek wrote:
On Mon, Mar 08, 2021 at 07:37:46PM -0700, Martin Sebor via Gcc-patches wrote:
Accesses to zero-length arrays continue to be diagnosed (except for
trailing arrays of unknown objects), as are nonempty accesses to empty
types.

The warning message for (3) remains unchanged, i.e., for the following:

   struct S { } a[3];

   void g (int n)
   {
     ((int*)a)[0] = 0;
   }

it's:

   warning: array subscript 0 is outside array bounds of ‘struct S[3]’
[-Warray-bounds]

As I tried to explain several times, this is completely unacceptable to me.
We want to warn, I agree with that, but we don't care that we emit completely
nonsensical warning?
The user will be just confused by that, will (rightly) think it is a bug in
the compiler and might not fix the actual bug.
Array subscript 0 is not outside of those array bounds.

You're being unreasonable.  As I explained, I'm open to improving
the text of the warning but consider tweaking it outside the scope
of this bug.


If you don't want a shortcut that for arrays with zero sized elements
and for non-array objects with zero size uses a different code path
that would just warn
"access outside of zero sized object %qD"

You're quibbling over a minute difference in the phrasing of a warning
for an obscure case that will probably never even come up.  But if it
did, the text is secondary to issuing it since it detects a bug.  So
again, I'm open to rewording the warning for GCC 12 but I'm not willing
to start rewriting the code in stage 4 just because you don't like how
the warning is phrased.

Martin

(which is what I'd prefer, any non-zero sized access to object of zero size
unless it is flexible array member or decl with flexible array member
is undefined, whatever offset you use)
and want to reuse the current code, at least please change reftype
to build_printable_array_type (TREE_TYPE (ref), 0);
so that it prints
warning: array subscript 0 is outside array bounds of ‘int[0]’ [-Warray-bounds]
You'll need to redo the:
           || !COMPLETE_TYPE_P (reftype)
           || TREE_CODE (TYPE_SIZE_UNIT (reftype)) != INTEGER_CST)
         return false;
check on the new reftype.
It should be done not just where you currently do:
                       nelts = integer_zero_node;
                       eltsize = 1;
but also somewhere in:
           eltsize = 1;
           tree size = TYPE_SIZE_UNIT (reftype);
           if (VAR_P (arg))
             if (tree initsize = DECL_SIZE_UNIT (arg))
               if (tree_int_cst_lt (size, initsize))
                 size = initsize;

           arrbounds[1] = wi::to_offset (size);
below that for the case where integer_zerop (size) && TYPE_EMPTY_P (reftype).
There should be also:

   struct S { } a;

   void g (int n)
   {
     ((int*)&a)[0] = 0;
   }

testcase that covers that.

BTW, what is the reason behind the POINTER_TYPE_P check in:
       /* The type of the object being referred to.  It can be an array,
          string literal, or a non-array type when the MEM_REF represents
          a reference/subscript via a pointer to an object that is not
          an element of an array.  Incomplete types are excluded as well
          because their size is not known.  */
       reftype = TREE_TYPE (arg);
       if (POINTER_TYPE_P (reftype)
?
It disables the second warning on:
   __UINTPTR_TYPE__ a;
   void *b;

   void g (int n)
   {
     ((int*)&a)[4] = 0;
     ((int*)&b)[4] = 0;
   }

I really don't see what is different on vars with pointer type vs. vars with
non-pointer type of the same size for this warning.

        Jakub


Reply via email to