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

--- Comment #7 from Martin Sebor <msebor at gcc dot gnu.org> ---
Thanks, the trailing 10 in x86_64-apple-darwin10 makes the difference!

Here's a small test case copied from the one around line 335 in
g++.dg/warn/Warray-bounds-8.C, and its output with the cross:

  void sink (void*);

  struct B0
  {
    char n;
    char a[0];                    // { dg-message "destination object declared
here" }

    B0 () { a[0] = 0; }           // { dg-warning "\\\[-Wstringop-overflow" }
  };

  void gb0 (void)
  {
    struct B0 b0;
    sink (&b0);
  }

$ /build/x86_64-apple-darwin10/gcc-svn/gcc/xgcc -B
/build/x86_64-apple-darwin10/gcc-svn/gcc -O2 -S -Wall -Wextra t.C
In constructor 'B0::B0()',
    inlined from 'void gb0()' at t.C:16:13:
t.C:10:16: warning: writing 1 byte into a region of size 0
[-Wstringop-overflow=]
   10 |   B0 () { a[0] = 0; }           // { dg-warning
"\\\[-Wstringop-overflow" }
      |           ~~~~~^~~

and with a Linux native GCC:

$ /build/gcc-svn/gcc/xgcc -B /build/gcc-svn/gcc -O2 -S -Wall -Wextra t.C
t.C: In function ‘void gb0()’:
t.C:10:14: warning: array subscript 0 is above array bounds of ‘char [0]’
[-Warray-bounds]
   10 |   B0 () { a[0] = 0; }           // { dg-warning
"\\\[-Wstringop-overflow" }
      |           ~~~^
t.C:8:8: note: while referencing ‘B0::a’
    8 |   char a[0];                    // { dg-message "destination object
declared here" }
      |        ^


The difference between the two is that with the cross the store is a MEM_REF
that the -Warray-bounds warning doesn't handle:

gb0 ()
{
  struct B0 b0;

  <bb 2> [local count: 1073741824]:
  MEM[(char *)&b0 + 1B] = 0;
  sink (&b0);
  b0 ={v} {CLOBBER};
  return;

}

while with the native GCC the store is an ARRAY_REF that -Warray-bounds does
handle:

gb0 ()
{
  struct B0 b0;

  <bb 2> [local count: 1073741824]:
  b0 ={v} {CLOBBER};
  b0.a[0] = 0;
  sink (&b0);
  b0 ={v} {CLOBBER};
  return;

}

The MEM_REF is introduced during the early sra pass which the native compiler
decides not to run because the B0 ctor doesn't pass the
ipa_sra_preliminary_function_checks: it thinks the function cannot be local. 
This is based on the result of cgraph_node_cannot_be_local_p_1, specifically
the value of node->same_comdat_group which is null with the native GCC and
non-null with darwin:

cgraph_node_cannot_be_local_p_1 (cgraph_node *node, void *)
{
  return !(!node->force_output
           && ((DECL_COMDAT (node->decl)
                && !node->forced_by_abi
                && !node->used_from_object_file_p ()
                && !node->same_comdat_group)
               || !node->externally_visible));
}

I can't say I know why that is but the difference seems gratuitous.

That aside, ideally, both warnings would handle both forms of accesses but as
they don't share code so they improve independently, leading to these kinds of
inconsistencies.  I will look into improving -Warray-bounds to handle the
MEM_REF case as well.

Reply via email to