More testing of my -Warray-bounds patch for pr82588 et al. exposed a missing warning on the following corner case (and similar cases like it). $ cat a.c && gcc -O2 -S -Warray-bounds a.c int g (int i) { int *p = &i; return p[2]; } To detect this the implementation could check the operand of the address-of operator and trigger if it's a non-array object. It should even be possible to detect the out-of-bounds index in the following: int a[3]; int b[5]; int f (int i) { int *p = i < 0 ? a : b; return p[7]; }
But we are not even having an ARRAY_REF in the IL ... So try int g (int i) { int (*p)[2] = (int (*)[2])&i; return (*p)[2]; } where we also do not warn. Or the VLA variant: int g (int i, int n) { int (*p)[n] = (int (*)[n])&i; return (*p)[2]; } Basically the warning code blindly trusts the ARRAY_TYPE domain even if there's an underlying decl where that array wouldn't fit. So the warning you are requesting is more an out-of-bound object access in general. To warn for this substitute each variable offset with its minimum range value, call get_ref_base_and_extent and see if offset/size are within the base object.
I realize there's no ARRAY_REF but users unfamiliar with GCC internals don't, nor would they care. I'm less concerned about code that defeats the type system by using casts (though it would be nice to diagnose those as well if possible). What I think is important to try to diagnose is mistakes in otherwise good, clean code. Here's another example: struct A { char a[4]; }; struct B { struct A a[2]; }; int f (struct B *b) { char *p = b[0].a[1].a; return p[13]; // invalid: MEM[(char *)b_2(D) + 17B]; } int g (struct B *b) { char *p = b[1].a[1].a; return p[1]; // valid: MEM[(char *)b_2(D) + 17B]; } There's no way to diagnose this in tree-vrp.c because there's no way to distinguish the two MEM_REFs at that point (same as in pr82585). This isn't a shortcoming of the warning code in tree-vrp.c But it is a deficiency in the -Warray-bounds warning. This coding bug could be detected before the pointer addition that still has access to the array bounds is folded into a MEM_REF (in tree-ssa-forwprop.c).
The warning was enhanced in GCC 9.1 (r262893) to detect this bug, except that due to my own oversight it doesn't handle the PARAM_DECL case. It's trivial to add it. Let me take care of it for GCC 10.0. $ cat pr82612.c && gcc -O2 -S -Wall pr82612.c int i; int f0 (void) { int *p = &i; return p[2]; // -Warray-bounds (good) } int f1 (void) { int i; int *p = &i; return p[2]; // -Warray-bounds (good) } int f2 (int i) { int *p = &i; return p[2]; // missing -Warray-bounds } pr82612.c: In function ‘f0’: pr82612.c:5:11: warning: array subscript 2 is outside array bounds of ‘int[1]’ [-Warray-bounds] 5 | return p[2]; // -Warray-bounds (good) | ~^~~ pr82612.c:1:5: note: while referencing ‘i’ 1 | int i; | ^ pr82612.c: In function ‘f1’: pr82612.c:12:11: warning: array subscript 2 is outside array bounds of ‘int[1]’ [-Warray-bounds] 12 | return p[2]; // -Warray-bounds (good) | ~^~~ pr82612.c:10:7: note: while referencing ‘i’ 10 | int i; | ^
Author: msebor Date: Tue Nov 5 16:20:44 2019 New Revision: 277851 URL: https://gcc.gnu.org/viewcvs?rev=277851&root=gcc&view=rev Log: PR middle-end/92341 - missing -Warray-bounds indexing past the end of a compound literal PR middle-end/82612 - missing -Warray-bounds on a non-zero offset from the address of a non-array object gcc/testsuite/ChangeLog: PR middle-end/92341 PR middle-end/82612 * g++.dg/warn/Warray-bounds-4.C: Adjust text of expected warning. * gcc.dg/Warray-bounds-53.c: New test. * gcc.dg/Warray-bounds-54.c: New test. gcc/ChangeLog: PR middle-end/92341 PR middle-end/82612 * tree-sra.c (get_access_for_expr): Fail for out-of-bounds offsets. * tree-vrp.c (vrp_prop::check_array_ref): Correct index and text of message printed in a warning for empty arrays. (vrp_prop::check_mem_ref): Also handle function parameters and empty arrays. Added: trunk/gcc/testsuite/gcc.dg/Warray-bounds-53.c trunk/gcc/testsuite/gcc.dg/Warray-bounds-54.c Modified: trunk/gcc/ChangeLog trunk/gcc/testsuite/ChangeLog trunk/gcc/testsuite/g++.dg/warn/Warray-bounds-4.C trunk/gcc/tree-sra.c trunk/gcc/tree-vrp.c
With r277851 check in, the PARM_DECL case is detected as well.