Bug 91457 - FAIL: g++.dg/warn/Warray-bounds-4.C -std=gnu++98 (test for warnings, line 25)
Summary: FAIL: g++.dg/warn/Warray-bounds-4.C -std=gnu++98 (test for warnings, line 25)
Status: ASSIGNED
Alias: None
Product: gcc
Classification: Unclassified
Component: tree-optimization (show other bugs)
Version: 10.0
: P3 normal
Target Milestone: 10.0
Assignee: Martin Sebor
URL:
Keywords: diagnostic, patch
Depends on:
Blocks: Warray-bounds
  Show dependency treegraph
 
Reported: 2019-08-15 14:07 UTC by John David Anglin
Modified: 2019-10-09 16:58 UTC (History)
4 users (show)

See Also:
Host: hppa2.0w-hp-hpux11.11,*-*-darwin*
Target: hppa2.0w-hp-hpux11.11,*-*-darwin*
Build: hppa2.0w-hp-hpux11.11,*-*-darwin*
Known to work:
Known to fail:
Last reconfirmed: 2019-08-15 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description John David Anglin 2019-08-15 14:07:24 UTC
I see the following fails:

FAIL: g++.dg/warn/Warray-bounds-4.C  -std=gnu++98  (test for warnings, line 25)
FAIL: g++.dg/warn/Warray-bounds-4.C  -std=gnu++98 (test for excess errors)
FAIL: g++.dg/warn/Warray-bounds-4.C  -std=gnu++14  (test for warnings, line 25)
FAIL: g++.dg/warn/Warray-bounds-4.C  -std=gnu++14 (test for excess errors)
FAIL: g++.dg/warn/Warray-bounds-4.C  -std=gnu++17  (test for warnings, line 25)
FAIL: g++.dg/warn/Warray-bounds-4.C  -std=gnu++17 (test for excess errors)

spawn /test/gnu/gcc/objdir/gcc/testsuite/g++/../../xg++ -B/test/gnu/gcc/objdir/g
cc/testsuite/g++/../../ /test/gnu/gcc/gcc/gcc/testsuite/g++.dg/warn/Warray-bounds-4.C -fno-diagnostics-show-caret -fno-diagnostics-show-line-numbers -fdiagnostics-color=never -nostdinc++ -I/test/gnu/gcc/objdir/hppa2.0w-hp-hpux11.11/libstdc++-v3/include/hppa2.0w-hp-hpux11.11 -I/test/gnu/gcc/objdir/hppa2.0w-hp-hpux11.11/libstdc++-v3/include -I/test/gnu/gcc/gcc/libstdc++-v3/libsupc++ -I/test/gnu/gcc/gcc/libstdc++-v3/include/backward -I/test/gnu/gcc/gcc/libstdc++-v3/testsuite/util -fmessage-length=0 -std=gnu++98 -O2 -Warray-bounds -S -o Warray-bounds-4.s
In constructor 'FixedString<size>::FixedString() [with long unsigned int size = 0]',
    inlined from 'int main()' at /test/gnu/gcc/gcc/gcc/testsuite/g++.dg/warn/Warray-bounds-4.C:32:24:
/test/gnu/gcc/gcc/gcc/testsuite/g++.dg/warn/Warray-bounds-4.C:25:19: warning: writing 1 byte into a region of size 0 [-Wstringop-overflow=]
output is:
In constructor 'FixedString<size>::FixedString() [with long unsigned int size = 0]',
    inlined from 'int main()' at /test/gnu/gcc/gcc/gcc/testsuite/g++.dg/warn/Warray-bounds-4.C:32:24:
/test/gnu/gcc/gcc/gcc/testsuite/g++.dg/warn/Warray-bounds-4.C:25:19: warning: writing 1 byte into a region of size 0 [-Wstringop-overflow=]

FAIL: g++.dg/warn/Warray-bounds-4.C  -std=gnu++98  (test for warnings, line 25)
FAIL: g++.dg/warn/Warray-bounds-4.C  -std=gnu++98 (test for excess errors)
Excess errors:
/test/gnu/gcc/gcc/gcc/testsuite/g++.dg/warn/Warray-bounds-4.C:25:19: warning: writing 1 byte into a region of size 0 [-Wstringop-overflow=]

It looks like these fails may be related to fails on darwin:
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91006

[tag] [reply] [−] Comment 2
Comment 1 John David Anglin 2019-08-15 14:09:08 UTC
Martin Sebor wrote on 2019-08-14:

I don't know about the flifetime-dse2.C test but the Warray-bounds-4.C warning is the result of a recent enhancement to the strlen optimization, either r274486 or r273783.  On the hppa2.0w-hp-hpux11.11 target the warning newly added in r273783 sees the following code:

  main ()
  {
    const struct FixedString empty;

    <bb 2> [local count: 1073741824]:
    MEM[(int (*) () * *)&empty] = &MEM <int (*) ()[8]> [(void *)&_ZTV11FixedStringILm0EE + 8B];
    MEM[(char *)&empty + 4B] = 0;
    print_length (&empty.D.2009);   <<<
    empty ={v} {CLOBBER};
    empty ={v} {CLOBBER};
    return 0;
  }

and diagnoses the invalid store at <<< before VRP gets to it and issues -Warray-bounds.  On other targets like sparc-solaris2.11, the strlen pass sees the following code:

main ()
{
  const struct FixedString empty;

  <bb 2> [local count: 1073741824]:
  MEM[(struct FixedString *)&empty] ={v} {CLOBBER};
  MEM[(struct FixedString *)&empty].D.2008._vptr.String = &MEM <int (*) ()[8]> [(void *)&_ZTV11FixedStringILm0EE + 8B];
  MEM[(struct FixedString *)&empty].contents[0] = 0;   <<<
  print_length (&empty.D.2008);
  empty ={v} {CLOBBER};
  empty ={v} {CLOBBER};
  return 0;

}

and it doesn't handle this form of the assignment (it doesn't know how to determine the size of the referenced object).  Ideally, both kinds would be handled and the same warning would be issued.  It means enhancing the object size detection (compute_objsize in builtins.c).
Comment 2 Martin Sebor 2019-08-15 15:42:56 UTC
Confirmed.  Here's a slightly simplified/modified test case showing the difference in output between an x86_64 native GCC and an hppa2.0w-hp-hpux11.11 cross.  Here too compute_objsize fails because it doesn't handle the ARRAY_REF argument in the assignment a.a[0] = 0.

$ (set -x && cat t.C && gcc -O2 -S -Wall -fdump-tree-dom3=/dev/stdout t.C && /build/hppa2.0w-hp-hpux11.11/gcc-svn/gcc/xgcc -B /build/hppa2.0w-hp-hpux11.11/gcc-svn/gcc -O2 -S -Wall -fdump-tree-dom3=/dev/stdout t.C)
+ cat t.C
struct A
{
  char n, a[0];

  A () { a[0] = 0; }
};

void f (struct A*);

void g (void)
{
  struct A a;
  f (&a);
}
+ /build/gcc-svn/gcc/xgcc -B /build/gcc-svn/gcc -O2 -S -Wall -fdump-tree-dom3=/dev/stdout t.C
t.C: In function ‘void g()’:
t.C:5:13: warning: array subscript 0 is above array bounds of ‘char [0]’ [-Warray-bounds]
    5 |   A () { a[0] = 0; }
      |          ~~~^

;; Function g (_Z1gv, funcdef_no=3, decl_uid=2317, cgraph_uid=4, symbol_order=3)

;; 1 loops found
;;
;; Loop 0
;;  header 0, latch 1
;;  depth 0, outer -1
;;  nodes: 0 1 2
;; 2 succs { 1 }
g ()
{
  struct A a;

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

}


+ /build/hppa2.0w-hp-hpux11.11/gcc-svn/gcc/xgcc -B /build/hppa2.0w-hp-hpux11.11/gcc-svn/gcc -O2 -S -Wall -fdump-tree-dom3=/dev/stdout t.C

;; Function g (_Z1gv, funcdef_no=3, decl_uid=1911, cgraph_uid=4, symbol_order=3)

;; 1 loops found
;;
;; Loop 0
;;  header 0, latch 1
;;  depth 0, outer -1
;;  nodes: 0 1 2
;; 2 succs { 1 }
g ()
{
  struct A a;

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

}


In constructor ‘A::A()’,
    inlined from ‘void g()’ at t.C:12:12:
t.C:5:15: warning: writing 1 byte into a region of size 0 [-Wstringop-overflow=]
    5 |   A () { a[0] = 0; }
      |          ~~~~~^~~
Comment 3 Martin Sebor 2019-08-15 15:43:20 UTC
Let me enhance the function.
Comment 4 Martin Sebor 2019-08-16 22:44:35 UTC
Patch: https://gcc.gnu.org/ml/gcc-patches/2019-08/msg01202.html
Comment 5 Martin Sebor 2019-08-28 16:44:27 UTC
Author: msebor
Date: Wed Aug 28 16:43:56 2019
New Revision: 274997

URL: https://gcc.gnu.org/viewcvs?rev=274997&root=gcc&view=rev
Log:
PR tree-optimization/91457 - inconsistent warning for writing past the end of an array member

gcc/ChangeLog:

	PR tree-optimization/91457
	* builtins.c (component_size): New function.
	(compute_objsize): Add argument. Handle ARRAY_REF and COMPONENT_REF.
	* builtins.h (compute_objsize): Add argument.
	* tree-ssa-strlen.c (handle_store): Handle no-warning bit.
	* tree-vrp.c (vrp_prop::check_array_ref): Return warning result.
	(vrp_prop::check_mem_ref): Same.
	(vrp_prop::search_for_addr_array): Set no-warning bit.
	(check_array_bounds): Same.

gcc/testsuite/ChangeLog:

	PR tree-optimization/91457
	* c-c++-common/Wstringop-overflow-2.c: New test.
	* g++.dg/warn/Warray-bounds-8.C: New test.
	* g++.dg/warn/Wstringop-overflow-3.C: New test.
	* gcc.dg/Wstringop-overflow-15.c: New test.


Added:
    trunk/gcc/testsuite/c-c++-common/Wstringop-overflow-2.c
    trunk/gcc/testsuite/g++.dg/warn/Warray-bounds-8.C
    trunk/gcc/testsuite/g++.dg/warn/Wstringop-overflow-3.C
    trunk/gcc/testsuite/gcc.dg/Wstringop-overflow-15.c
Modified:
    trunk/gcc/ChangeLog
    trunk/gcc/builtins.c
    trunk/gcc/builtins.h
    trunk/gcc/testsuite/ChangeLog
    trunk/gcc/tree-ssa-strlen.c
    trunk/gcc/tree-vrp.c
Comment 6 Martin Sebor 2019-08-28 18:27:08 UTC
The enhancement has been committed but it doesn't actually resolve the problem.  As it turns out, it's caused by VRP not issuing a -Warray-bounds for this case.  VRP runs before (not after as I suggested in comment #1) strlen (the source of the -Wstringop-overflow).

For the test case in comment #2 VRP sees:

  g ()
  {
    struct A a;

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

and it gives up.  There's a comment that explains why:

  /* ... References to members of structs and
     unions are excluded because MEM_REF doesn't make it possible
     to identify the member where the reference originated.
     Incomplete types are excluded as well because their size is
     not known.  */

It seems to me it could do better and handle struct member accesses that are outside of the bounds of the enclosing declared object.  I.e., those where no matter which member the MEM_REF refers to the access is definitely out-of-bounds.

I'm wondering if this test passed on hppa before r273783.  Did GCC actually issue the expecting -Warray-bounds there?
Comment 7 dave.anglin 2019-08-28 19:08:57 UTC
On 2019-08-28 2:27 p.m., msebor at gcc dot gnu.org wrote:
> I'm wondering if this test passed on hppa before r273783.  Did GCC actually
> issue the expecting -Warray-bounds there?
Looking at test results for hppa64-hp-hpux11.11 and hppa2.0w-hp-hpux11.11, the test passed in r272545 and failed in r272623.
Comment 8 Christophe Lyon 2019-08-29 08:59:09 UTC
(In reply to Martin Sebor from comment #5)
> Author: msebor
> Date: Wed Aug 28 16:43:56 2019
> New Revision: 274997
> 
> URL: https://gcc.gnu.org/viewcvs?rev=274997&root=gcc&view=rev
> Log:
> PR tree-optimization/91457 - inconsistent warning for writing past the end
> of an array member
> 
> gcc/ChangeLog:
> 
> 	PR tree-optimization/91457
> 	* builtins.c (component_size): New function.
> 	(compute_objsize): Add argument. Handle ARRAY_REF and COMPONENT_REF.
> 	* builtins.h (compute_objsize): Add argument.
> 	* tree-ssa-strlen.c (handle_store): Handle no-warning bit.
> 	* tree-vrp.c (vrp_prop::check_array_ref): Return warning result.
> 	(vrp_prop::check_mem_ref): Same.
> 	(vrp_prop::search_for_addr_array): Set no-warning bit.
> 	(check_array_bounds): Same.
> 
> gcc/testsuite/ChangeLog:
> 
> 	PR tree-optimization/91457
> 	* c-c++-common/Wstringop-overflow-2.c: New test.
> 	* g++.dg/warn/Warray-bounds-8.C: New test.
> 	* g++.dg/warn/Wstringop-overflow-3.C: New test.
> 	* gcc.dg/Wstringop-overflow-15.c: New test.
> 
> 
> Added:
>     trunk/gcc/testsuite/c-c++-common/Wstringop-overflow-2.c
>     trunk/gcc/testsuite/g++.dg/warn/Warray-bounds-8.C
>     trunk/gcc/testsuite/g++.dg/warn/Wstringop-overflow-3.C
>     trunk/gcc/testsuite/gcc.dg/Wstringop-overflow-15.c
> Modified:
>     trunk/gcc/ChangeLog
>     trunk/gcc/builtins.c
>     trunk/gcc/builtins.h
>     trunk/gcc/testsuite/ChangeLog
>     trunk/gcc/tree-ssa-strlen.c
>     trunk/gcc/tree-vrp.c


Hi,

After this was committed, I'm seeing glibc (2.29) build errors for arm and aarch64, but that's probably true on other targets:
programs/ld-ctype.c: In function 'ctype_finish':
cc1: error: writing 1 byte into a region of size 0 [-Werror=stringop-overflow=]
In file included from programs/repertoire.h:24,
                 from programs/localedef.h:32,
                 from programs/ld-ctype.c:35:
programs/charmap.h:63:17: note: destination object declared here
   63 |   unsigned char bytes[0];
      |                 ^~~~~
cc1: error: writing 1 byte into a region of size 0 [-Werror=stringop-overflow=]
programs/charmap.h:63:17: note: destination object declared here
cc1: error: writing 1 byte into a region of size 0 [-Werror=stringop-overflow=]
programs/charmap.h:63:17: note: destination object declared here
cc1: error: writing 1 byte into a region of size 0 [-Werror=stringop-overflow=]
programs/charmap.h:63:17: note: destination object declared here
Comment 9 Martin Sebor 2019-08-30 02:03:44 UTC
The Glibc warning is being discussed on libc-alpha:
https://sourceware.org/ml/libc-alpha/2019-08/msg00774.html
Comment 10 Christophe Lyon 2019-08-30 07:21:44 UTC
Thanks for the pointer to the glibc discussion.

My understanding is that GCC's warning is legitimate, and won't be removed?
Since this breaks all my validations, I guess the best course of action on my side is to build glibc with --disable-werror?
Comment 11 Iain Sandoe 2019-09-03 14:47:57 UTC
on Darwin, the Warray-bounds-4 is failing for c++98,14,17

Warray-bounds-8 has started failing between 274983 and 275034 with the same kind of pattern - I can file a new PR if you regard the second as distinct.
Comment 12 Iain Sandoe 2019-09-03 15:13:47 UTC
it looks like Wstringop-overflow-3.C also started failing at the same time as Warray-bounds-8, presumably these are all connected.
Comment 13 Martin Sebor 2019-09-03 15:22:32 UTC
(In reply to Christophe Lyon from comment #10)

Yes, the warning is intended and Glibc was just patched to avoid it:
https://sourceware.org/ml/glibc-cvs/2019-q3/msg00459.html

(In reply to Iain Sandoe from comment #11)

I haven't gone back to understand why r273783 makes the difference on hppa2.0w-hp-hpux11.11 and answer my question in comment #6.

The warnings in this area (-Warray-bounds and the new -Wstringop-overflow for [multi]character assignments) are sensitive to subtle differences in the IL, which in turn seems to change from target to target depending on what the folder decides to transform the assignments to.  As each warning is implemented differently and runs at part of a different pass, getting them to trigger consistently across all targets is like herding cats.  Figuring out what the folder does on each target and parameterizing the tests on the variables that influence its decisions is also not trivial.

Anyway, since this bug is specific to Warray-bounds-4.C on hppa2.0w-hp-hpux11.11, opening a searate issue for the Warray-bounds-8.C failures on Darwin might be best.
Comment 14 Iain Sandoe 2019-09-06 23:07:25 UTC
(In reply to Martin Sebor from comment #13)
> (In reply to Christophe Lyon from comment #10)
> 
> Yes, the warning is intended and Glibc was just patched to avoid it:
> https://sourceware.org/ml/glibc-cvs/2019-q3/msg00459.html
> 
> (In reply to Iain Sandoe from comment #11)

> Anyway, since this bug is specific to Warray-bounds-4.C on
> hppa2.0w-hp-hpux11.11, 

We have found a number of cases over the years where hpux and darwin shared test behaviour - so I'll monitor this; if the Darwin case isn't fixed by whatever resolution we apply for hpux, we can raise a new PR then.
Comment 15 Iain Sandoe 2019-10-08 19:56:20 UTC
this is fixed for Darwin.
Comment 16 Martin Sebor 2019-10-09 16:58:28 UTC
The warning code hasn't changed.  What's different is that the MEM_REF that -Warray-bounds doesn't handle isn't in the IL anymore.  The hppa2.0w-hp-hpux11.11 IL for the test case in comment #6 looks just like the x86_64 IL and so the same warning is issued for both (see below).  I don't know what commit is behind the change.

$ cat pr91457.C && /build/hppa2.0w-hp-hpux11.11/gcc-svn/gcc/xgcc -B /build/hppa2.0w-hp-hpux11.11/gcc-svn/gcc -S -O2 -Wall -fdump-tree-dom3=/dev/stdout pr91457.C
struct A
{
  char n, a[0];

  A () { a[0] = 0; }
};

void f (struct A*);

void g (void)
{
  struct A a;
  f (&a);
}
pr91457.C: In function 'void g()':
pr91457.C:5:13: warning: array subscript 0 is above array bounds of 'char [0]' [-Warray-bounds]
    5 |   A () { a[0] = 0; }
      |          ~~~^
pr91457.C:3:11: note: while referencing 'A::a'
    3 |   char n, a[0];
      |           ^

;; Function g (_Z1gv, funcdef_no=3, decl_uid=1937, cgraph_uid=4, symbol_order=3)

;; 1 loops found
;;
;; Loop 0
;;  header 0, latch 1
;;  depth 0, outer -1
;;  nodes: 0 1 2
;; 2 succs { 1 }
g ()
{
  struct A a;

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

}