On 11/15/2017 03:51 AM, Richard Biener wrote:
On Tue, Nov 14, 2017 at 6:45 PM, Martin Sebor <mse...@gmail.com> wrote:
On 11/14/2017 05:28 AM, Richard Biener wrote:

On Mon, Nov 13, 2017 at 6:37 PM, Martin Sebor <mse...@gmail.com> wrote:

Richard, this thread may have been conflated with the one Re:
[PATCH] enhance -Warray-bounds to detect out-of-bounds offsets
(PR 82455) They are about different things.

I'm still looking for approval of:

  https://gcc.gnu.org/ml/gcc-patches/2017-10/msg01208.html


Sorry, I pointed to an outdated version.  This is the latest
version:

  https://gcc.gnu.org/ml/gcc-patches/2017-10/msg01304.html

My bad...



+      tree maxbound
+ = build_int_cst (sizetype, ~(1LLU << (TYPE_PRECISION (sizetype) - 1)));

this looks possibly bogus.  Can you instead use

  up_bound_p1
    = wide_int_to_tree (sizetype, wi::div_trunc (wi::max_value
(TYPE_PRECISION (sizetype), SIGNED), wi::to_wide (eltsize)));

please?  Note you are _not_ computing the proper upper bound here because
that
is what you compute plus low_bound.

+      up_bound_p1 = int_const_binop (TRUNC_DIV_EXPR, maxbound, eltsize);

+
+      tree arg = TREE_OPERAND (ref, 0);
+      tree_code code = TREE_CODE (arg);
+      if (code == COMPONENT_REF)
+ {
+  HOST_WIDE_INT off;
+  if (tree base = get_addr_base_and_unit_offset (ref, &off))
+    {
+      tree size = TYPE_SIZE_UNIT (TREE_TYPE (base));
+      if (TREE_CODE (size) == INTEGER_CST)
+ up_bound_p1 = int_const_binop (MINUS_EXPR, up_bound_p1, size);

I think I asked this multiple times now but given 'ref' is the
variable array-ref
a.b.c[i] when you call get_addr_base_and_unit_offset (ref, &off) you
always
get a NULL_TREE return value.

So I asked you to pass it 'arg' instead ... which gets you the offset of
a.b.c, which looks like what you intended to get anyway.

I also wonder what you compute here - you are looking at the size of
'base'
but that is the size of 'a'.  You don't even use the computed offset!
Which
means you could have used get_base_address instead!?  Also the type
of 'base' may be completely off given MEM[&blk + 8].b.c[i] would return
blk
as base which might be an array of chars and not in any way related to
the type of the innermost structure we access with COMPONENT_REFs.

Why are you only looking at COMPONENT_REF args anyways?  You
don't want to handle a.b[3][i]?

That is, I'd have expected you do

   if (get_addr_base_and_unit_offset (ref, &off))
     up_bound_p1 = wide_int_to_tree (sizetype, wi::sub (wi::to_wide
(up_bound_p1), off));

^^^^^^^^^

Please see the attached update.

Martin
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.

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 0000000..bea36fb
--- /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 089fa00..c9fc461 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 0000000..f66bfb3
--- /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 945b3a9..e248f59 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;
 	}
     }

Reply via email to