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. 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" (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