From 8a5ee94a082b3d485b5cf7acc2b40b26cccb129f Mon Sep 17 00:00:00 2001 From: Martin Sebor Date: Thu, 16 Nov 2017 16:12:36 +0000 Subject: [PATCH] PR tree-optimization/82588 - missing -Warray-bounds on a excessively large index PR tree-optimization/82588 - missing -Warray-bounds on a excessively large index PR tree-optimization/82583 - missing -Warray-bounds on out-of-bounds inner indic gcc/ChangeLog: PR tree-optimization/82588 PR tree-optimization/82583 * tree-vrp.c (check_array_ref): Handle flexible array members, string literals, and inner indices. (search_for_addr_array): Add detail to diagnostics. gcc/testsuite/ChangeLog: PR tree-optimization/82588 PR tree-optimization/82583 * c-c++-common/Warray-bounds.c: New test. * gcc.dg/Warray-bounds-11.c: Adjust. * gcc.dg/Warray-bounds-22.c: New test. From-SVN: r254830 --- gcc/ChangeLog | 8 + gcc/testsuite/ChangeLog | 8 + gcc/testsuite/c-c++-common/Warray-bounds.c | 259 +++++++++++++++++++++ gcc/testsuite/gcc.dg/Warray-bounds-11.c | 18 +- gcc/testsuite/gcc.dg/Warray-bounds-22.c | 96 ++++++++ gcc/tree-vrp.c | 64 +++-- 6 files changed, 428 insertions(+), 25 deletions(-) create mode 100644 gcc/testsuite/c-c++-common/Warray-bounds.c create mode 100644 gcc/testsuite/gcc.dg/Warray-bounds-22.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index de9c6df23ed..f6e0f181ccf 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2017-11-16 Martin Sebor + + PR tree-optimization/82588 + PR tree-optimization/82583 + * tree-vrp.c (check_array_ref): Handle flexible array members, + string literals, and inner indices. + (search_for_addr_array): Add detail to diagnostics. + 2017-11-16 Nathan Sidwell PR c++/82836 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 158605a76f7..30082bf1821 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,11 @@ +2017-11-16 Martin Sebor + + PR tree-optimization/82588 + PR tree-optimization/82583 + * c-c++-common/Warray-bounds.c: New test. + * gcc.dg/Warray-bounds-11.c: Adjust. + * gcc.dg/Warray-bounds-22.c: New test. + 2017-11-16 Nathan Sidwell PR c++/82836 diff --git a/gcc/testsuite/c-c++-common/Warray-bounds.c b/gcc/testsuite/c-c++-common/Warray-bounds.c new file mode 100644 index 00000000000..bea36fb04b7 --- /dev/null +++ b/gcc/testsuite/c-c++-common/Warray-bounds.c @@ -0,0 +1,259 @@ +/* PR tree-optimization/82588 - missing -Warray-bounds on an excessively + large index + { dg-do compile } + { dg-require-effective-target alloca } + { dg-options "-O2 -Warray-bounds -ftrack-macro-expansion=0" } */ + +#define SIZE_MAX __SIZE_MAX__ +#define DIFF_MAX __PTRDIFF_MAX__ +#define DIFF_MIN (-DIFF_MAX - 1) + +#define offsetof(T, m) __builtin_offsetof (T, m) + +typedef __PTRDIFF_TYPE__ ssize_t; +typedef __SIZE_TYPE__ size_t; + +extern ssize_t signed_value (void) +{ + extern volatile ssize_t signed_value_source; + return signed_value_source; +} + +extern size_t unsigned_value (void) +{ + extern volatile size_t unsigned_value_source; + return unsigned_value_source; +} + +ssize_t signed_range (ssize_t min, ssize_t max) +{ + ssize_t val = signed_value (); + return val < min || max < val ? min : val; +} + +typedef struct AX { int n; char ax[]; } AX; + +typedef struct A1 { int i; char a1[1]; } A1; +typedef struct B { int i; struct A1 a1x[]; } B; + +void sink (int, ...); + +#define R(min, max) signed_range (min, max) +#define T(expr) sink (0, expr) + +struct __attribute__ ((packed)) S16 { unsigned i: 16; }; + +void farr_char (void) +{ + extern char ac[]; + + T (ac[DIFF_MIN]); /* { dg-warning "array subscript -\[0-9\]+ is below array bounds of .char *\\\[]." } */ + T (ac[-1]); /* { dg-warning "array subscript -1 is below array bounds" } */ + T (ac[0]); + + T (ac[DIFF_MAX - 1]); + T (ac[DIFF_MAX]); /* { dg-warning "array subscript \[0-9\]+ is above array bounds" } */ + T (ac[DIFF_MAX + (size_t)1]); /* { dg-warning "array subscript \[0-9\]+ is above array bounds" } */ + T (ac[SIZE_MAX]); /* { dg-warning "array subscript \[0-9\]+ is above array bounds" } */ + T (ac[R (DIFF_MAX - 1, DIFF_MAX)]); + T (ac[R (DIFF_MIN + 1, -1)]); /* { dg-warning "array subscript -1 is below array bounds" } */ + T (ac[R (DIFF_MIN + 1, 0)]); + T (ac[R (-1, 0)]); + T (ac[R (-1, 1)]); +} + +void farr_s16 (void) +{ + extern struct S16 ax[]; + + T (ax[DIFF_MIN]); /* { dg-warning "array subscript -\[0-9\]+ is below array bounds of .(struct )?S16 *\\\[]." } */ + T (ax[-1]); /* { dg-warning "array subscript -1 is below array bounds" } */ + T (ax[0]); + + T (ax[DIFF_MAX / 2 - 1]); + T (ax[DIFF_MAX / 2]); /* { dg-warning "array subscript \[0-9\]+ is above array bounds" } */ + T (ax[DIFF_MAX / 2 + (size_t)1]); /* { dg-warning "array subscript \[0-9\]+ is above array bounds" } */ + T (ax[SIZE_MAX]); /* { dg-warning "array subscript \[0-9\]+ is above array bounds" } */ + T (ax[R (DIFF_MIN, -1)]); /* { dg-warning "array subscript -1 is below array bounds" } */ + T (ax[R (DIFF_MAX / 2 - 1, DIFF_MAX)]); + T (ax[R (DIFF_MAX / 2, DIFF_MAX)]); /* { dg-warning "array subscript \[0-9\]+ is above array bounds" } */ +} + +void farr_s16_7 (void) +{ + extern struct S16 ax_7[][7]; + + T (ax_7[0][DIFF_MIN]); /* { dg-warning "array subscript -\[0-9\]+ is below array bounds of .(struct )?S16 *\\\[7]." } */ + T (ax_7[0][-1]); /* { dg-warning "array subscript -1 is below array bounds" } */ + T (ax_7[0][0]); + T (ax_7[0][7]); /* { dg-warning "array subscript 7 is above array bounds of .(struct )?S16 *\\\[7]." } */ + T (ax_7[0][8]); /* { dg-warning "array subscript 8 is above array bounds of .(struct )?S16 *\\\[7]." } */ + + T (ax_7[0][DIFF_MAX / 2]); /* { dg-warning "array subscript \[0-9\]+ is above array bounds" } */ + T (ax_7[0][SIZE_MAX]); /* { dg-warning "array subscript \[0-9\]+ is above array bounds" } */ + + T (ax_7[DIFF_MIN][0]); /* { dg-warning "array subscript -\[0-9\]+ is below array bounds of .(struct )?S16 *\\\[]\\\[7]." } */ + T (ax_7[-1][0]); /* { dg-warning "array subscript -1 is below array bounds" } */ + + T (ax_7[DIFF_MAX / 2][0]); /* { dg-warning "array subscript \[0-9\]+ is above array bounds" } */ + T (ax_7[SIZE_MAX][0]); /* { dg-warning "array subscript \[0-9\]+ is above array bounds" } */ + + ssize_t i = R (DIFF_MIN, -1); + T (ax_7[i][0]); /* { dg-warning "array subscript -1 is below array bounds" } */ + + T (ax_7[R (DIFF_MIN, -1)][0]); /* { dg-warning "array subscript -1 is below array bounds" } */ + T (ax_7[R (DIFF_MIN, 0)][0]); + T (ax_7[R (-2, -1)][0]); /* { dg-warning "array subscript -1 is below array bounds" } */ + T (ax_7[R (-1, 0)][0]); + T (ax_7[R (-1, 1)][0]); + T (ax_7[R (-1, 7)][0]); + T (ax_7[R (-1, DIFF_MAX)][0]); + + T (ax_7[R ( 1, DIFF_MAX)][0]); + T (ax_7[R (DIFF_MAX / 14 - 1, DIFF_MAX)][0]); + + i = R (DIFF_MAX / 14, DIFF_MAX); + T (ax_7[i][0]); /* { dg-warning "array subscript \[0-9\]+ is above array bounds" } */ + + T (ax_7[0][R (DIFF_MIN, 0)]); + T (ax_7[0][R (-1, 0)]); + T (ax_7[0][R (-1, 1)]); + T (ax_7[0][R (-1, 7)]); + T (ax_7[0][R (-1, DIFF_MAX)]); + T (ax_7[0][R (-1, DIFF_MAX)]); + + T (ax_7[0][R (1, DIFF_MAX)]); + T (ax_7[0][R (7, DIFF_MAX)]); /* { dg-warning "array subscript 7 is above array bounds" } */ + +} + +void farr_x_5_7 (void) +{ + extern struct S16 a[][5][7]; + + T (a[0][0][-3]); /* { dg-warning "array subscript -3 is below array bounds of .(struct )?S16 *\\\[7]." } */ + T (a[0][-2][0]); /* { dg-warning "array subscript -2 is below array bounds of .(struct )?S16 *\\\[5]\\\[7]." } */ + T (a[-1][0][0]); /* { dg-warning "array subscript -1 is below array bounds of .(struct )?S16 *\\\[]\\\[5]\\\[7]." } */ + T (a[R (-4, -3)][0][0]); /* { dg-warning "array subscript -3 is below array bounds" } */ + T (a[0][R (-3, -2)][0]); /* { dg-warning "array subscript -2 is below array bounds" } */ + T (a[0][0][R (-2, -1)]); /* { dg-warning "array subscript -1 is below array bounds" } */ +} + + +void fax (struct AX *p) +{ + T (p->ax[DIFF_MIN]); /* { dg-warning "array subscript -\[0-9\]+ is below array bounds" } */ + T (p->ax[-1]); /* { dg-warning "array subscript -1 is below array bounds" } */ + T (p->ax[0]); + T (p->ax[DIFF_MAX - sizeof *p - 1]); + T (p->ax[DIFF_MAX - sizeof *p]); /* { dg-warning "array subscript \[0-9\]+ is above array bounds" } */ + T (p->ax[DIFF_MAX - sizeof *p + 1]); /* { dg-warning "array subscript \[0-9\]+ is above array bounds" } */ + T (p->ax[SIZE_MAX]); /* { dg-warning "array subscript \[0-9\]+ is above array bounds" } */ + T (p->ax[R (DIFF_MIN, -1)]); /* { dg-warning "array subscript -1 is below array bounds" } */ + T (p->ax[R (-1, 1)]); + T (p->ax[R (0, DIFF_MAX - 1)]); + T (p->ax[R (DIFF_MAX - 1, DIFF_MAX)]);/* { dg-warning "array subscript \[0-9\]+ is above array bounds" } */ +} + +void fa1 (struct A1 *p) +{ + T (p->a1[DIFF_MIN]); /* { dg-warning "array subscript -\[0-9\]+ is below array bounds" } */ + T (p->a1[-1]); /* { dg-warning "array subscript -1 is below array bounds" } */ + T (p->a1[0]); + T (p->a1[9]); + T (p->a1[DIFF_MAX - offsetof (A1, a1) - 1]); + T (p->a1[DIFF_MAX - offsetof (A1, a1)]);/* { dg-warning "array subscript \[0-9\]+ is above array bounds" } */ + T (p->a1[DIFF_MAX - offsetof (A1, a1) + 1]); /* { dg-warning "array subscript \[0-9\]+ is above array bounds" } */ + T (p->a1[SIZE_MAX]); /* { dg-warning "array subscript \[0-9\]+ is above array bounds" } */ +} + +void fb (struct B *p) +{ + T (p->a1x->a1[DIFF_MIN]); /* { dg-warning "array subscript -\[0-9\]+ is below array bounds" } */ + T (p->a1x->a1[-1]); /* { dg-warning "array subscript -1 is below array bounds" } */ + T (p->a1x->a1[0]); + T (p->a1x->a1[9]); /* { dg-warning "array subscript \[0-9\]+ is above array bounds" } */ + T (p->a1x->a1[DIFF_MAX - sizeof *p]); /* { dg-warning "array subscript \[0-9\]+ is above array bounds" } */ + T (p->a1x->a1[DIFF_MAX - sizeof *p + 1]); /* { dg-warning "array subscript \[0-9\]+ is above array bounds" } */ + T (p->a1x->a1[SIZE_MAX]); /* { dg-warning "array subscript \[0-9\]+ is above array bounds" } */ + + T (p->a1x[1].a1[DIFF_MIN]); /* { dg-warning "array subscript -\[0-9\]+ is below array bounds" } */ + T (p->a1x[1].a1[-1]); /* { dg-warning "array subscript -1 is below array bounds" } */ + T (p->a1x[1].a1[0]); + T (p->a1x[1].a1[9]); /* { dg-warning "array subscript \[0-9\]+ is above array bounds" } */ + T (p->a1x[1].a1[DIFF_MAX - sizeof *p]); /* { dg-warning "array subscript \[0-9\]+ is above array bounds" } */ + T (p->a1x[1].a1[DIFF_MAX - sizeof *p + 1]); /* { dg-warning "array subscript \[0-9\]+ is above array bounds" } */ + T (p->a1x[1].a1[SIZE_MAX]); /* { dg-warning "array subscript \[0-9\]+ is above array bounds" } */ + + T (p->a1x[2].a1[DIFF_MIN]); /* { dg-warning "array subscript -\[0-9\]+ is below array bounds" } */ + T (p->a1x[2].a1[-1]); /* { dg-warning "array subscript -1 is below array bounds" } */ + T (p->a1x[2].a1[0]); + T (p->a1x[2].a1[9]); /* { dg-warning "array subscript \[0-9\]+ is above array bounds" } */ + T (p->a1x[2].a1[DIFF_MAX - sizeof *p]);/* { dg-warning "array subscript \[0-9\]+ is above array bounds" } */ + T (p->a1x[2].a1[DIFF_MAX - sizeof *p + 1]); /* { dg-warning "array subscript \[0-9\]+ is above array bounds" } */ + T (p->a1x[2].a1[SIZE_MAX]); /* { dg-warning "array subscript \[0-9\]+ is above array bounds" } */ + + T (p->a1x[3].a1[DIFF_MIN]); /* { dg-warning "array subscript -\[0-9\]+ is below array bounds" } */ + T (p->a1x[3].a1[-1]); /* { dg-warning "array subscript -1 is below array bounds" } */ + T (p->a1x[3].a1[0]); + T (p->a1x[3].a1[9]); /* { dg-warning "array subscript \[0-9\]+ is above array bounds" } */ + + T (p->a1x[9].a1[0]); + + enum { MAX = DIFF_MAX / sizeof *p->a1x - sizeof *p }; + + T (p->a1x[DIFF_MIN].a1); /* { dg-warning "array subscript -\[0-9\]+ is below array bounds" } */ + T (p->a1x[-1].a1); /* { dg-warning "array subscript -1 is below array bounds" } */ + T (p->a1x[MAX].a1); + T (p->a1x[MAX + 2].a1); /* { dg-warning "array subscript \[0-9\]+ is above array bounds" } */ + + T (p->a1x[DIFF_MAX].a1); /* { dg-warning "array subscript \[0-9\]+ is above array bounds" } */ + T (p->a1x[SIZE_MAX].a1); /* { dg-warning "array subscript \[0-9\]+ is above array bounds" } */ + + T (p->a1x[DIFF_MIN].a1[0]); /* { dg-warning "array subscript -\[0-9\]+ is below array bounds" } */ + T (p->a1x[-1].a1[0]) /* { dg-warning "array subscript -1 is below array bounds" } */; + T (p->a1x[MAX - 1].a1[0]); + T (p->a1x[MAX].a1[0]); /* { dg-warning "array subscript \[0-9\]+ is above array bounds" } */ + T (p->a1x[MAX + 1].a1[0]); /* { dg-warning "array subscript \[0-9\]+ is above array bounds" } */ + + T (p->a1x[DIFF_MAX].a1[0]); /* { dg-warning "array subscript \[0-9\]+ is above array bounds" } */ + T (p->a1x[SIZE_MAX].a1[0]); /* { dg-warning "array subscript \[0-9\]+ is above array bounds" } */ +} + +void f_cststring (int i) +{ + T (""[DIFF_MIN]); /* { dg-warning "array subscript -\[0-9\]+ is below array bounds of .(const )?char *\\\[1]" "string" { xfail lp64 } } */ + T (""[DIFF_MIN + 1]); /* { dg-warning "array subscript -\[0-9\]+ is below array bounds of .(const )?char *\\\[1]" "string" } */ + T (""[-1]); /* { dg-warning "array subscript -1 is below array bounds of .(const )?char *\\\[1]" "string" } */ + T (""[0]); + T (""[1]); /* { dg-warning "array subscript 1 is above array bounds of .(const )?char *\\\[1]" "string" } */ + T ("0"[2]); /* { dg-warning "array subscript 2 is above array bounds of .(const )?char *\\\[2]" "string" } */ + T ("012"[2]); + T ("012"[3]); + T ("012"[4]); /* { dg-warning "array subscript 4 is above array bounds of .(const )?char *\\\[4]" "string" } */ + T ("0123"[DIFF_MAX]); /* { dg-warning "array subscript \[0-9\]+ is above array bounds of .(const )?char *\\\[5]" "string" } */ + T ("0123"[SIZE_MAX]); /* { dg-warning "array subscript \[0-9\]+ is above array bounds of .(const )?char *\\\[5]" "string" } */ +} + +void fb_strlen (struct B *p) +{ +#define strlen __builtin_strlen + + T (strlen (&p->a1x[0].a1[2])); /* { dg-warning "array subscript \[0-9\]+ is above array bounds" "strlen" } */ + T (strlen (p->a1x[0].a1 + 2)); /* { dg-warning "array subscript \[0-9\]+ is above array bounds" "strlen" { xfail *-*-* } } */ +} + + +void f_vla (unsigned n) +{ + char vla[n]; + + T (vla[DIFF_MIN]); /* { dg-warning "array subscript -\[0-9\]+ is below array bounds" "vla" } */ + T (vla[-1]); /* { dg-warning "array subscript -1 is below array bounds" "vla" } */ + T (vla[0]); + T (vla[1]); + T (vla[n - 1]); + /* It would be nice to diagnose this. */ + T (vla[n]); /* { dg-warning "array subscript \[0-9\]+ is above array bounds" "bug 82608" { xfail *-*-*} } */ + T (vla[DIFF_MAX]); /* { dg-warning "array subscript \[0-9\]+ is above array bounds" "vla" } */ +} diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-11.c b/gcc/testsuite/gcc.dg/Warray-bounds-11.c index 089fa00f35a..c9fc461942f 100644 --- a/gcc/testsuite/gcc.dg/Warray-bounds-11.c +++ b/gcc/testsuite/gcc.dg/Warray-bounds-11.c @@ -57,19 +57,19 @@ struct h3b { void foo(int (*a)[3]) { - (*a)[4] = 1; /* { dg-warning "subscript is above array bound" } */ + (*a)[4] = 1; /* { dg-warning "subscript 4 is above array bound" } */ a[0][0] = 1; // ok a[1][0] = 1; // ok - a[1][4] = 1; /* { dg-warning "subscript is above array bound" } */ + a[1][4] = 1; /* { dg-warning "subscript 4 is above array bound" } */ int c[3] = { 0 }; - c[4] = 1; /* { dg-warning "subscript is above array bound" } */ + c[4] = 1; /* { dg-warning "subscript 4 is above array bound" } */ - e[4] = 1; /* { dg-warning "subscript is above array bound" } */ + e[4] = 1; /* { dg-warning "subscript 4 is above array bound" } */ struct f f; - f.f[4] = 1; /* { dg-warning "subscript is above array bound" } */ + f.f[4] = 1; /* { dg-warning "subscript 4 is above array bound" } */ struct h* h = malloc(sizeof(struct h) + 3 * sizeof(int)); struct h0* h0 = malloc(sizeof(struct h0) + 3 * sizeof(int)); @@ -78,15 +78,15 @@ void foo(int (*a)[3]) h->j[4] = 1; // flexible array member h0->j[4] = 1; // zero-sized array extension - h1->j[4] = 1; /* { dg-warning "subscript is above array bound" } */ - h3->j[4] = 1; /* { dg-warning "subscript is above array bound" } */ + h1->j[4] = 1; /* { dg-warning "subscript 4 is above array bound" } */ + h3->j[4] = 1; /* { dg-warning "subscript 4 is above array bound" } */ struct h0b* h0b = malloc(sizeof(struct h) + 3 * sizeof(int)); struct h1b* h1b = malloc(sizeof(struct h1b) + 3 * sizeof(int)); struct h3b* h3b = malloc(sizeof(struct h3b)); // h0b->j[4] = 1; - h1b->j[4] = 1;; /* { dg-warning "subscript is above array bound" } */ - h3b->j[4] = 1;; /* { dg-warning "subscript is above array bound" } */ + h1b->j[4] = 1;; /* { dg-warning "subscript 4 is above array bound" } */ + h3b->j[4] = 1;; /* { dg-warning "subscript 4 is above array bound" } */ // make sure nothing gets optimized away bar(*a); diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-22.c b/gcc/testsuite/gcc.dg/Warray-bounds-22.c new file mode 100644 index 00000000000..f66bfb3d70b --- /dev/null +++ b/gcc/testsuite/gcc.dg/Warray-bounds-22.c @@ -0,0 +1,96 @@ +/* PR tree-optimization/82588 - missing -Warray-bounds on an excessively + large index + { dg-do compile } + { dg-require-effective-target alloca } + { dg-options "-O2 -Warray-bounds -ftrack-macro-expansion=0" } */ + +#define SIZE_MAX __SIZE_MAX__ +#define DIFF_MAX __PTRDIFF_MAX__ +#define DIFF_MIN (-DIFF_MAX - 1) + +typedef __PTRDIFF_TYPE__ ptrdiff_t; +typedef __SIZE_TYPE__ size_t; + +extern ptrdiff_t signed_value (void) +{ + extern volatile ptrdiff_t signed_value_source; + return signed_value_source; +} + +ptrdiff_t signed_range (ptrdiff_t min, ptrdiff_t max) +{ + ptrdiff_t val = signed_value (); + return val < min || max < val ? min : val; +} + +typedef struct AX { int n; char ax[]; } AX; + +typedef struct A1 { int i; char a1[1]; } A1; +typedef struct B { int i; struct A1 a1x[]; } B; + +void sink (int, ...); + +#define T(expr) sink (0, (expr)) + +void test_vla (unsigned m, unsigned n) +{ + char vla1[m]; + + T (vla1[DIFF_MIN]); /* { dg-warning "array subscript -\[0-9\]+ is below array bounds" "vla" } */ + T (vla1[-1]); /* { dg-warning "array subscript -1 is below array bounds" "vla" } */ + T (vla1[0]); + T (vla1[1]); + T (vla1[m - 1]); + /* It would be nice to diagnose this. */ + T (vla1[m]); /* { dg-warning "array subscript \[0-9\]+ is above array bounds" "bug 82608" { xfail *-*-*} } */ + T (vla1[DIFF_MAX - 1]); + T (vla1[DIFF_MAX]); /* { dg-warning "array subscript \[0-9\]+ is above array bounds" "vla" } */ + + ptrdiff_t i = signed_range (DIFF_MAX - 1, DIFF_MAX); + T (vla1[i]); + + char vla2[m][n]; + + T (vla2[0][DIFF_MIN]); /* { dg-warning "array subscript -\[0-9\]+ is below array bounds" "vla" } */ + T (vla2[0][-1]); /* { dg-warning "array subscript -1 is below array bounds" "vla" } */ + T (vla2[0][0]); + T (vla2[1][1]); + T (vla2[m - 1][n - 1]); + /* It would be nice to diagnose this. */ + T (vla2[m][0]); /* { dg-warning "array subscript \[0-9\]+ is above array bounds" "bug 82608" { xfail *-*-*} } */ + T (vla2[m + 1][0]); /* { dg-warning "array subscript \[0-9\]+ is above array bounds" "bug 82608" { xfail *-*-*} } */ + T (vla2[0][n]); /* { dg-warning "array subscript \[0-9\]+ is above array bounds" "bug 82608" { xfail *-*-*} } */ + T (vla2[0][n + 1]); /* { dg-warning "array subscript \[0-9\]+ is above array bounds" "bug 82608" { xfail *-*-*} } */ + T (vla2[m][n]); /* { dg-warning "array subscript \[0-9\]+ is above array bounds" "bug 82608" { xfail *-*-*} } */ + T (vla2[m + 1][n + 1]); /* { dg-warning "array subscript \[0-9\]+ is above array bounds" "bug 82608" { xfail *-*-*} } */ + + T (vla2[0][DIFF_MAX]); /* { dg-warning "array subscript \[0-9\]+ is above array bounds" "vla" } */ + T (vla2[DIFF_MAX][0]); /* { dg-warning "array subscript \[0-9\]+ is above array bounds" "vla" { xfail *-*-* } } */ + T (vla2[DIFF_MAX][DIFF_MAX]); /* { dg-warning "array subscript \[0-9\]+ is above array bounds" "vla" } */ + + struct S256 { char a[256]; } vla3[m]; + + T (vla3[DIFF_MIN].a[0]); /* { dg-warning "array subscript -\[0-9\]+ is below array bounds" "vla" } */ + T (vla3[-1].a[0]); /* { dg-warning "array subscript -1 is below array bounds" "vla" } */ + T (vla3[0].a[0]); + T (vla3[1].a[0]); + T (vla3[m - 1].a[0]); + T (vla3[DIFF_MAX / 256 - 1].a[0]); + T (vla3[DIFF_MAX / 256].a[0]); /* { dg-warning "array subscript \[0-9\]+ is above array bounds" "vla" } */ + + i = signed_range (DIFF_MAX / 256 - 1, DIFF_MAX); + T (vla3[i].a[0]); + + i = signed_range (DIFF_MAX / 256, DIFF_MAX); + T (vla3[i].a[0]); /* { dg-warning "array subscript \[0-9\]+ is above array bounds" "vla" } */ + + struct VLA { char vla[n]; } x; + + T (x.vla[DIFF_MIN]); /* { dg-warning "array subscript -\[0-9\]+ is below array bounds" "vla" } */ + T (x.vla[-1]); /* { dg-warning "array subscript -1 is below array bounds" "vla" } */ + T (x.vla[0]); + T (x.vla[1]); + T (x.vla[n - 1]); + T (x.vla[DIFF_MAX - 1]); + T (x.vla[DIFF_MAX]); /* { dg-warning "array subscript \[0-9\]+ is above array bounds" "vla" } */ +} diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c index 945b3a9935e..e248f59a67f 100644 --- a/gcc/tree-vrp.c +++ b/gcc/tree-vrp.c @@ -42,6 +42,7 @@ along with GCC; see the file COPYING3. If not see #include "gimple-iterator.h" #include "gimple-walk.h" #include "tree-cfg.h" +#include "tree-dfa.h" #include "tree-ssa-loop-manip.h" #include "tree-ssa-loop-niter.h" #include "tree-ssa-loop.h" @@ -65,6 +66,7 @@ along with GCC; see the file COPYING3. If not see #include "stringpool.h" #include "attribs.h" #include "vr-values.h" +#include "builtins.h" /* Set of SSA names found live during the RPO traversal of the function for still active basic-blocks. */ @@ -4781,26 +4783,51 @@ vrp_prop::check_array_ref (location_t location, tree ref, low_sub = up_sub = TREE_OPERAND (ref, 1); up_bound = array_ref_up_bound (ref); - /* Can not check flexible arrays. */ if (!up_bound - || TREE_CODE (up_bound) != INTEGER_CST) - return; + || TREE_CODE (up_bound) != INTEGER_CST + || (warn_array_bounds < 2 + && array_at_struct_end_p (ref))) + { + /* Accesses to trailing arrays via pointers may access storage + beyond the types array bounds. For such arrays, or for flexible + array members, as well as for other arrays of an unknown size, + replace the upper bound with a more permissive one that assumes + the size of the largest object is PTRDIFF_MAX. */ + tree eltsize = array_ref_element_size (ref); + + /* FIXME: Handle VLAs. */ + if (TREE_CODE (eltsize) != INTEGER_CST) + return; - /* Accesses to trailing arrays via pointers may access storage - beyond the types array bounds. */ - if (warn_array_bounds < 2 - && array_at_struct_end_p (ref)) - return; + tree maxbound = TYPE_MAX_VALUE (ptrdiff_type_node); + + up_bound_p1 = int_const_binop (TRUNC_DIV_EXPR, maxbound, eltsize); + + tree arg = TREE_OPERAND (ref, 0); + + HOST_WIDE_INT off; + if (get_addr_base_and_unit_offset (arg, &off)) + up_bound_p1 = wide_int_to_tree (sizetype, + wi::sub (wi::to_wide (up_bound_p1), + off)); + + up_bound = int_const_binop (MINUS_EXPR, up_bound_p1, + build_int_cst (ptrdiff_type_node, 1)); + } + else + up_bound_p1 = int_const_binop (PLUS_EXPR, up_bound, + build_int_cst (TREE_TYPE (up_bound), 1)); low_bound = array_ref_low_bound (ref); - up_bound_p1 = int_const_binop (PLUS_EXPR, up_bound, - build_int_cst (TREE_TYPE (up_bound), 1)); + + tree artype = TREE_TYPE (TREE_OPERAND (ref, 0)); /* Empty array. */ if (tree_int_cst_equal (low_bound, up_bound_p1)) { warning_at (location, OPT_Warray_bounds, - "array subscript is above array bounds"); + "array subscript %E is above array bounds of %qT", + low_bound, artype); TREE_NO_WARNING (ref) = 1; } @@ -4824,7 +4851,8 @@ vrp_prop::check_array_ref (location_t location, tree ref, && tree_int_cst_le (low_sub, low_bound)) { warning_at (location, OPT_Warray_bounds, - "array subscript is outside array bounds"); + "array subscript [%E, %E] is outside array bounds of %qT", + low_sub, up_sub, artype); TREE_NO_WARNING (ref) = 1; } } @@ -4840,7 +4868,8 @@ vrp_prop::check_array_ref (location_t location, tree ref, fprintf (dump_file, "\n"); } warning_at (location, OPT_Warray_bounds, - "array subscript is above array bounds"); + "array subscript %E is above array bounds of %qT", + up_sub, artype); TREE_NO_WARNING (ref) = 1; } else if (TREE_CODE (low_sub) == INTEGER_CST @@ -4853,7 +4882,8 @@ vrp_prop::check_array_ref (location_t location, tree ref, fprintf (dump_file, "\n"); } warning_at (location, OPT_Warray_bounds, - "array subscript is below array bounds"); + "array subscript %E is below array bounds of %qT", + low_sub, artype); TREE_NO_WARNING (ref) = 1; } } @@ -4908,7 +4938,8 @@ vrp_prop::search_for_addr_array (tree t, location_t location) fprintf (dump_file, "\n"); } warning_at (location, OPT_Warray_bounds, - "array subscript is below array bounds"); + "array subscript %wi is below array bounds of %qT", + idx.to_shwi (), TREE_TYPE (tem)); TREE_NO_WARNING (t) = 1; } else if (idx > (wi::to_offset (up_bound) @@ -4921,7 +4952,8 @@ vrp_prop::search_for_addr_array (tree t, location_t location) fprintf (dump_file, "\n"); } warning_at (location, OPT_Warray_bounds, - "array subscript is above array bounds"); + "array subscript %wu is above array bounds of %qT", + idx.to_uhwi (), TREE_TYPE (tem)); TREE_NO_WARNING (t) = 1; } } -- 2.30.2