This is primarily Martin's work.  My changes:

First, this picks up the last bit of stuff from patch #1 of the 6 series
kit to handle unterminated strings -- I was mistaken last night when I
said the prior patch wrapped up the bits from patch #1 that we needed.

I made NONSTR simply passed through get_range_strlen, eliminating one
small block of changes.  That allows it to work better with the way
c_strlen and friends accumulate values in *NONSTR and prevents
unexpected failures in the new test.

In gimple_fold_builtin_strcpy we test NONSTR before checking the return
value of get_maxval_strlen  which allows us to detect missing NUL
terminations even when get_maxval_strlen returns NULL.

And the xfails on the new tests were removed for tests which pass now.

Bootstrapped and regression tested on the trunk.  Installing on the
trunk momentarily.

Jeff
commit cd05ac910c0336ae2c066ad90c962d58bfde68dc
Author: Jeff Law <l...@torsion.usersys.redhat.com>
Date:   Wed Sep 12 18:41:43 2018 -0400

            * builtins.c (unterminated_array): New.
            (expand_builtin_strcpy): Adjust.
            (expand_builtin_strcpy_args): Detect unterminated arrays.
            * gimple-fold.c (get_maxval_strlen): Add argument.  Detect
            unterminated arrays.
            * gimple-fold.h (get_maxval_strlen): Add argument.
            (gimple_fold_builtin_strcpy): Detec unterminated arrays.
    
            * gimple-fold.c (get_range_strlen): Add argument.
            (get_maxval_strlen): Adjust.
            * gimple-fold.h (get_range_strlen): Add argument.
    
            * gcc.dg/warn-strcpy-no-nul.c: New test.

diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 71dc508d219..84578a331d7 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,18 @@
+2018-09-14  Martin Sebor  <mse...@redhat.com>
+           Jeff Law  <l...@redhat.com>
+
+       * builtins.c (unterminated_array): New.
+       (expand_builtin_strcpy): Adjust.
+       (expand_builtin_strcpy_args): Detect unterminated arrays.
+       * gimple-fold.c (get_maxval_strlen): Add argument.  Detect
+       unterminated arrays.
+       * gimple-fold.h (get_maxval_strlen): Add argument.
+       (gimple_fold_builtin_strcpy): Detec unterminated arrays.
+
+       * gimple-fold.c (get_range_strlen): Add argument.
+       (get_maxval_strlen): Adjust.
+       * gimple-fold.h (get_range_strlen): Add argument.
+
 2018-09-14  Wei Xiao  <wei3.x...@intel.com>
 
        * config/i386/movdirintrin.h: Fix copyright year.
diff --git a/gcc/builtins.c b/gcc/builtins.c
index a345704a8f8..be813db46b8 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -132,7 +132,7 @@ static rtx expand_builtin_mempcpy (tree, rtx);
 static rtx expand_builtin_mempcpy_args (tree, tree, tree, rtx, tree, int);
 static rtx expand_builtin_strcat (tree, rtx);
 static rtx expand_builtin_strcpy (tree, rtx);
-static rtx expand_builtin_strcpy_args (tree, tree, rtx);
+static rtx expand_builtin_strcpy_args (tree, tree, tree, rtx);
 static rtx expand_builtin_stpcpy (tree, rtx, machine_mode);
 static rtx expand_builtin_stpncpy (tree, rtx);
 static rtx expand_builtin_strncat (tree, rtx);
@@ -563,6 +563,34 @@ warn_string_no_nul (location_t loc, const char *fn, tree 
arg, tree decl)
     }
 }
 
+/* If EXP refers to an unterminated constant character array return
+   the declaration of the object of which the array is a member or
+   element.  Otherwise return null.  */
+
+static tree
+unterminated_array (tree exp)
+{
+  if (TREE_CODE (exp) == SSA_NAME)
+    {
+      gimple *stmt = SSA_NAME_DEF_STMT (exp);
+      if (!is_gimple_assign (stmt))
+       return NULL_TREE;
+
+      tree rhs1 = gimple_assign_rhs1 (stmt);
+      tree_code code = gimple_assign_rhs_code (stmt);
+      if (code != POINTER_PLUS_EXPR)
+       return NULL_TREE;
+
+      exp = rhs1;
+    }
+
+  tree nonstr = NULL;
+  if (c_strlen (exp, 1, &nonstr, 1) == NULL && nonstr)
+    return nonstr;
+
+  return NULL_TREE;
+}
+
 /* Compute the length of a null-terminated character string or wide
    character string handling character sizes of 1, 2, and 4 bytes.
    TREE_STRING_LENGTH is not the right way because it evaluates to
@@ -3879,7 +3907,7 @@ expand_builtin_strcpy (tree exp, rtx target)
                    src, destsize);
     }
 
-  if (rtx ret = expand_builtin_strcpy_args (dest, src, target))
+  if (rtx ret = expand_builtin_strcpy_args (exp, dest, src, target))
     {
       /* Check to see if the argument was declared attribute nonstring
         and if so, issue a warning since at this point it's not known
@@ -3899,8 +3927,17 @@ expand_builtin_strcpy (tree exp, rtx target)
    expand_builtin_strcpy.  */
 
 static rtx
-expand_builtin_strcpy_args (tree dest, tree src, rtx target)
+expand_builtin_strcpy_args (tree exp, tree dest, tree src, rtx target)
 {
+  /* Detect strcpy calls with unterminated arrays..  */
+  if (tree nonstr = unterminated_array (src))
+    {
+      /* NONSTR refers to the non-nul terminated constant array.  */
+      if (!TREE_NO_WARNING (exp))
+       warn_string_no_nul (EXPR_LOCATION (exp), "strcpy", src, nonstr);
+      return NULL_RTX;
+    }
+
   return expand_movstr (dest, src, target, /*endp=*/0);
 }
 
@@ -3960,7 +3997,7 @@ expand_builtin_stpcpy_1 (tree exp, rtx target, 
machine_mode mode)
 
          if (CONST_INT_P (len_rtx))
            {
-             ret = expand_builtin_strcpy_args (dst, src, target);
+             ret = expand_builtin_strcpy_args (exp, dst, src, target);
 
              if (ret)
                {
diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c
index 36a85c7eb7f..e8733204b44 100644
--- a/gcc/gimple-fold.c
+++ b/gcc/gimple-fold.c
@@ -1280,12 +1280,13 @@ gimple_fold_builtin_memset (gimple_stmt_iterator *gsi, 
tree c, tree len)
    obtained from the upper bound of an array at the end of a struct.
    Such an array may hold a string that's longer than its upper bound
    due to it being used as a poor-man's flexible array member.
+   Pass NONSTR through to children.
    ELTSIZE is 1 for normal single byte character strings, and 2 or
    4 for wide characer strings.  ELTSIZE is by default 1.  */
 
 static bool
 get_range_strlen (tree arg, tree length[2], bitmap *visited, int type,
-                 int fuzzy, bool *flexp, unsigned eltsize = 1)
+                 int fuzzy, bool *flexp, unsigned eltsize, tree *nonstr)
 {
   tree var, val = NULL_TREE;
   gimple *def_stmt;
@@ -1307,7 +1308,8 @@ get_range_strlen (tree arg, tree length[2], bitmap 
*visited, int type,
              if (TREE_CODE (aop0) == INDIRECT_REF
                  && TREE_CODE (TREE_OPERAND (aop0, 0)) == SSA_NAME)
                return get_range_strlen (TREE_OPERAND (aop0, 0), length,
-                                        visited, type, fuzzy, flexp, eltsize);
+                                        visited, type, fuzzy, flexp,
+                                        eltsize, nonstr);
            }
          else if (TREE_CODE (TREE_OPERAND (op, 0)) == COMPONENT_REF && fuzzy)
            {
@@ -1335,13 +1337,14 @@ get_range_strlen (tree arg, tree length[2], bitmap 
*visited, int type,
            return false;
        }
       else
-       val = c_strlen (arg, 1, NULL, eltsize);
+       val = c_strlen (arg, 1, nonstr, eltsize);
 
       if (!val && fuzzy)
        {
          if (TREE_CODE (arg) == ADDR_EXPR)
            return get_range_strlen (TREE_OPERAND (arg, 0), length,
-                                    visited, type, fuzzy, flexp, eltsize);
+                                    visited, type, fuzzy, flexp,
+                                    eltsize, nonstr);
 
          if (TREE_CODE (arg) == ARRAY_REF)
            {
@@ -1484,7 +1487,7 @@ get_range_strlen (tree arg, tree length[2], bitmap 
*visited, int type,
           {
             tree rhs = gimple_assign_rhs1 (def_stmt);
            return get_range_strlen (rhs, length, visited, type, fuzzy, flexp,
-                                    eltsize);
+                                    eltsize, nonstr);
           }
        else if (gimple_assign_rhs_code (def_stmt) == COND_EXPR)
          {
@@ -1493,7 +1496,7 @@ get_range_strlen (tree arg, tree length[2], bitmap 
*visited, int type,
 
            for (unsigned int i = 0; i < 2; i++)
              if (!get_range_strlen (ops[i], length, visited, type, fuzzy,
-                                    flexp, eltsize))
+                                    flexp, eltsize, nonstr))
                {
                  if (fuzzy == 2)
                    *maxlen = build_all_ones_cst (size_type_node);
@@ -1521,7 +1524,7 @@ get_range_strlen (tree arg, tree length[2], bitmap 
*visited, int type,
               continue;
 
            if (!get_range_strlen (arg, length, visited, type, fuzzy, flexp,
-                                  eltsize))
+                                  eltsize, nonstr))
              {
                if (fuzzy == 2)
                  *maxlen = build_all_ones_cst (size_type_node);
@@ -1554,21 +1557,30 @@ get_range_strlen (tree arg, tree length[2], bitmap 
*visited, int type,
    if we can determine string length minimum and maximum; it will use
    the minimum from the ones where it can be determined.
    STRICT false should be only used for warning code.
+   When non-null, clear *NONSTR if ARG refers to a constant array
+   that is known not be nul-terminated.  Otherwise set it to
+   the declaration of the constant non-terminated array.
 
    ELTSIZE is 1 for normal single byte character strings, and 2 or
    4 for wide characer strings.  ELTSIZE is by default 1.  */
 
 bool
-get_range_strlen (tree arg, tree minmaxlen[2], unsigned eltsize, bool strict)
+get_range_strlen (tree arg, tree minmaxlen[2], unsigned eltsize,
+                 bool strict, tree *nonstr /* = NULL */)
 {
   bitmap visited = NULL;
 
   minmaxlen[0] = NULL_TREE;
   minmaxlen[1] = NULL_TREE;
 
+  tree nonstrbuf;
+  if (!nonstr)
+    nonstr = &nonstrbuf;
+  *nonstr = NULL_TREE;
+
   bool flexarray = false;
   if (!get_range_strlen (arg, minmaxlen, &visited, 1, strict ? 1 : 2,
-                        &flexarray, eltsize))
+                        &flexarray, eltsize, nonstr))
     {
       minmaxlen[0] = NULL_TREE;
       minmaxlen[1] = NULL_TREE;
@@ -1580,19 +1592,39 @@ get_range_strlen (tree arg, tree minmaxlen[2], unsigned 
eltsize, bool strict)
   return flexarray;
 }
 
+/* Return the maximum string length for ARG, counting by TYPE
+   (1, 2 or 4 for normal or wide chars).  NONSTR indicates
+   if the caller is prepared to handle unterminated strings.
+
+   If an unterminated string is discovered and our caller handles
+   unterminated strings, then bubble up the offending DECL and
+   return the maximum size.  Otherwise return NULL.  */
+
 tree
-get_maxval_strlen (tree arg, int type)
+get_maxval_strlen (tree arg, int type, tree *nonstr /* = NULL */)
 {
   bitmap visited = NULL;
   tree len[2] = { NULL_TREE, NULL_TREE };
 
   bool dummy;
-  if (!get_range_strlen (arg, len, &visited, type, 0, &dummy))
+  /* Set to non-null if ARG refers to an untermianted array.  */
+  tree mynonstr = NULL_TREE;
+  if (!get_range_strlen (arg, len, &visited, type, 0, &dummy, 1, &mynonstr))
     len[1] = NULL_TREE;
   if (visited)
     BITMAP_FREE (visited);
 
-  return len[1];
+  if (nonstr)
+    {
+      /* For callers prepared to handle unterminated arrays set
+        *NONSTR to point to the declaration of the array and return
+        the maximum length/size. */
+      *nonstr = mynonstr;
+      return len[1];
+    }
+
+  /* Fail if the constant array isn't nul-terminated.  */
+  return mynonstr ? NULL_TREE : len[1];
 }
 
 
@@ -1635,7 +1667,19 @@ gimple_fold_builtin_strcpy (gimple_stmt_iterator *gsi,
   if (!fn)
     return false;
 
-  tree len = get_maxval_strlen (src, 0);
+  /* Set to non-null if ARG refers to an unterminated array.  */
+  tree nonstr = NULL;
+  tree len = get_maxval_strlen (src, 0, &nonstr);
+
+  if (nonstr)
+    {
+      /* Avoid folding calls with unterminated arrays.  */
+      if (!gimple_no_warning_p (stmt))
+       warn_string_no_nul (loc, "strcpy", src, nonstr);
+      gimple_set_no_warning (stmt, true);
+      return false;
+    }
+
   if (!len)
     return false;
 
@@ -3506,12 +3550,15 @@ static bool
 gimple_fold_builtin_strlen (gimple_stmt_iterator *gsi)
 {
   gimple *stmt = gsi_stmt (*gsi);
+  tree arg = gimple_call_arg (stmt, 0);
 
   wide_int minlen;
   wide_int maxlen;
 
+  /* Set to non-null if ARG refers to an unterminated array.  */
+  tree nonstr;
   tree lenrange[2];
-  if (!get_range_strlen (gimple_call_arg (stmt, 0), lenrange, 1, true)
+  if (!get_range_strlen (arg, lenrange, 1, true, &nonstr)
       && lenrange[0] && TREE_CODE (lenrange[0]) == INTEGER_CST
       && lenrange[1] && TREE_CODE (lenrange[1]) == INTEGER_CST)
     {
diff --git a/gcc/gimple-fold.h b/gcc/gimple-fold.h
index fcb0d31bef3..26e27272249 100644
--- a/gcc/gimple-fold.h
+++ b/gcc/gimple-fold.h
@@ -25,8 +25,9 @@ along with GCC; see the file COPYING3.  If not see
 extern tree create_tmp_reg_or_ssa_name (tree, gimple *stmt = NULL);
 extern tree canonicalize_constructor_val (tree, tree);
 extern tree get_symbol_constant_value (tree);
-extern bool get_range_strlen (tree, tree[2], unsigned = 1, bool = false);
-extern tree get_maxval_strlen (tree, int);
+extern bool get_range_strlen (tree, tree[2], unsigned = 1,
+                             bool = false, tree * = NULL);
+extern tree get_maxval_strlen (tree, int, tree * = NULL);
 extern void gimplify_and_update_call_from_tree (gimple_stmt_iterator *, tree);
 extern bool fold_stmt (gimple_stmt_iterator *);
 extern bool fold_stmt (gimple_stmt_iterator *, tree (*) (tree));
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index a5ea71e88a6..df6c9046c29 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2018-09-14  Martin Sebor  <mse...@redhat.com>
+           Jeff Law  <l...@redhat.com>
+
+       * gcc.dg/warn-strcpy-no-nul.c: New test.
+
 2018-09-14  Martin Sebor  <mse...@redhat.com>
 
        c++/61941
diff --git a/gcc/testsuite/gcc.dg/warn-strcpy-no-nul.c 
b/gcc/testsuite/gcc.dg/warn-strcpy-no-nul.c
new file mode 100644
index 00000000000..b5ed21dc195
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/warn-strcpy-no-nul.c
@@ -0,0 +1,324 @@
+/* PR tree-optimization/86552 - missing warning for reading past the end
+   of non-string arrays
+   { dg-do compile }
+   { dg-options "-O2 -Wall -Wno-array-bounds -ftrack-macro-expansion=0" } */
+
+extern char* strcpy (char*, const char*);
+
+const char a[5] = "12345";   /* { dg-message "declared here" } */
+
+int v0 = 0;
+int v1 = 1;
+int v2 = 1;
+int v3 = 1;
+
+void sink (char*, ...);
+
+#define T(str) sink (strcpy (d, str))
+
+void test_one_dim_array (char *d)
+{
+  T (a);                /* { dg-warning "argument missing terminating nul" } */
+  T (&a[0]);            /* { dg-warning "nul" } */
+  T (&a[0] + 1);        /* { dg-warning "nul" } */
+  T (&a[1]);            /* { dg-warning "nul" } */
+
+  int i0 = 0;
+  int i1 = i0 + 1;
+
+  T (&a[i0]);           /* { dg-warning "nul" } */
+  T (&a[i0] + 1);       /* { dg-warning "nul" } */
+  T (&a[i1]);           /* { dg-warning "nul" } */
+
+  T (&a[v0]);           /* { dg-warning "nul" } */
+  T (&a[v0] + 1);       /* { dg-warning "nul" } */
+  T (&a[v0] + v1);      /* { dg-warning "nul" } */
+}
+
+const char b[][5] = { /* { dg-message "declared here" } */
+  "12", "123", "1234", "54321"
+};
+
+void test_two_dim_array (char *d)
+{
+  int i0 = 0;
+  int i1 = i0 + 1;
+  int i2 = i1 + 1;
+  int i3 = i2 + 1;
+
+  T (b[0]);
+  T (b[1]);
+  T (b[2]);
+  T (b[3]);             /* { dg-warning "nul" } */
+  T (b[i0]);
+  T (b[i1]);
+  T (b[i2]);
+  T (b[i3]);            /* { dg-warning "nul" } */
+  T (b[v0]);
+  T (b[v3]);
+
+  T (&b[2][1]);
+  T (&b[2][1] + 1);
+  T (&b[2][v0]);
+  T (&b[2][1] + v0);
+
+  T (&b[i2][i1]);
+  T (&b[i2][i1] + i1);
+  T (&b[i2][v0]);
+  T (&b[i2][i1] + v0);
+
+  T (&b[3][1]);         /* { dg-warning "nul" } */
+  T (&b[3][1] + 1);     /* { dg-warning "nul" } */
+  T (&b[3][v0]);        /* { dg-warning "nul" } */
+  T (&b[3][1] + v0);    /* { dg-warning "nul" } */
+  T (&b[3][v0] + v1);   /* { dg-warning "nul" "bug ???" { xfail *-*-* } } */
+
+  T (&b[i3][i1]);       /* { dg-warning "nul" } */
+  T (&b[i3][i1] + i1);  /* { dg-warning "nul" } */
+  T (&b[i3][v0]);       /* { dg-warning "nul" } */
+  T (&b[i3][i1] + v0);  /* { dg-warning "nul" } */
+  T (&b[i3][v0] + v1);  /* { dg-warning "nul" "bug ???" { xfail *-*-* } } */
+
+  T (v0 ? "" : b[0]);
+  T (v0 ? "" : b[1]);
+  T (v0 ? "" : b[2]);
+  T (v0 ? "" : b[3]);               /* { dg-warning "nul" } */
+  T (v0 ? b[0] : "");
+  T (v0 ? b[1] : "");
+  T (v0 ? b[2] : "");
+  T (v0 ? b[3] : "");               /* { dg-warning "nul" } */
+
+  T (v0 ? "1234" : b[3]);           /* { dg-warning "nul" } */
+  T (v0 ? b[3] : "1234");           /* { dg-warning "nul" } */
+
+  T (v0 ? a : b[3]);                /* { dg-warning "nul" } */
+  T (v0 ? b[0] : b[2]);
+  T (v0 ? b[2] : b[3]);             /* { dg-warning "nul" } */
+  T (v0 ? b[3] : b[2]);             /* { dg-warning "nul" } */
+
+  T (v0 ? b[0] : &b[3][0] + 1);     /* { dg-warning "nul" } */
+  T (v0 ? b[1] : &b[3][1] + v0);    /* { dg-warning "nul" } */
+
+  /* It's possible to detect the missing nul in the following
+     expression but GCC doesn't do it yet.  */
+  T (v0 ? &b[3][1] + v0 : b[2]);    /* { dg-warning "nul" "bug ???" { xfail 
*-*-* } } */
+  T (v0 ? &b[3][v0] : &b[3][v1]);   /* { dg-warning "nul" } */
+}
+
+struct A { char a[5], b[5]; };
+
+const struct A s = { "1234", "12345" };
+
+void test_struct_member (char *d)
+{
+  int i0 = 0;
+  int i1 = i0 + 1;
+
+  T (s.a);
+  T (&s.a[0]);
+  T (&s.a[0] + 1);
+  T (&s.a[0] + i0);
+  T (&s.a[1]);
+  T (&s.a[1] + 1);
+  T (&s.a[1] + i0);
+
+  T (&s.a[i0]);
+  T (&s.a[i0] + 1);
+  T (&s.a[i0] + v0);
+  T (&s.a[i1]);
+  T (&s.a[i1] + 1);
+  T (&s.a[i1] + v0);
+
+  T (s.a);
+  T (&s.a[0]);
+  T (&s.a[0] + 1);
+  T (&s.a[0] + v0);
+  T (&s.a[1]);
+  T (&s.a[1] + 1);
+  T (&s.a[1] + v0);
+
+  T (&s.a[i0]);
+  T (&s.a[i0] + 1);
+  T (&s.a[i0] + v0);
+  T (&s.a[i1]);
+  T (&s.a[i1] + 1);
+  T (&s.a[i1] + v0);
+
+  T (&s.a[v0]);
+  T (&s.a[v0] + 1);
+  T (&s.a[v0] + v0);
+  T (&s.a[v1]);
+  T (&s.a[v1] + 1);
+  T (&s.a[v1] + v0);
+
+  T (s.b);              /* { dg-warning "nul" } */
+  T (&s.b[0]);          /* { dg-warning "nul" } */
+  T (&s.b[0] + 1);      /* { dg-warning "nul" } */
+  T (&s.b[0] + i0);     /* { dg-warning "nul" } */
+  T (&s.b[1]);          /* { dg-warning "nul" } */
+  T (&s.b[1] + 1);      /* { dg-warning "nul" } */
+  T (&s.b[1] + i0);     /* { dg-warning "nul" } */
+
+  T (s.b);              /* { dg-warning "nul" } */
+  T (&s.b[0]);          /* { dg-warning "nul" } */
+  T (&s.b[0] + 1);      /* { dg-warning "nul" } */
+  T (&s.b[0] + v0);     /* { dg-warning "nul" } */
+  T (&s.b[1]);          /* { dg-warning "nul" } */
+  T (&s.b[1] + 1);      /* { dg-warning "nul" } */
+  T (&s.b[1] + v0);     /* { dg-warning "nul" } */
+
+  T (s.b);              /* { dg-warning "nul" } */
+  T (&s.b[v0]);         /* { dg-warning "nul" "bug ???" { xfail *-*-* } } */
+  T (&s.b[v0] + 1);     /* { dg-warning "nul" "bug ???" { xfail *-*-* } } */
+  T (&s.b[v0] + v0);    /* { dg-warning "nul" "bug ???" { xfail *-*-* } } */
+  T (&s.b[v1]);         /* { dg-warning "nul" "bug ???" { xfail *-*-* } } */
+  T (&s.b[v1] + 1);     /* { dg-warning "nul" "bug ???" { xfail *-*-* } } */
+  T (&s.b[v1] + v0);    /* { dg-warning "nul" "bug ???" { xfail *-*-* } } */
+}
+
+struct B { struct A a[2]; };
+
+const struct B ba[] = {
+  { { { "123", "12345" }, { "12345", "123" } } },
+  { { { "12345", "123" }, { "123", "12345" } } },
+  { { { "1", "12" },      { "123", "1234" } } },
+  { { { "123", "1234" },  { "12345", "12" } } }
+};
+
+void test_array_of_structs (char *d)
+{
+  T (ba[0].a[0].a);
+  T (&ba[0].a[0].a[0]);
+  T (&ba[0].a[0].a[0] + 1);
+  T (&ba[0].a[0].a[0] + v0);
+  T (&ba[0].a[0].a[1]);
+  T (&ba[0].a[0].a[1] + 1);
+  T (&ba[0].a[0].a[1] + v0);
+
+  T (ba[0].a[0].b);           /* { dg-warning "nul" } */
+  T (&ba[0].a[0].b[0]);       /* { dg-warning "nul" } */
+  T (&ba[0].a[0].b[0] + 1);   /* { dg-warning "nul" } */
+  T (&ba[0].a[0].b[0] + v0);  /* { dg-warning "nul" } */
+  T (&ba[0].a[0].b[1]);       /* { dg-warning "nul" } */
+  T (&ba[0].a[0].b[1] + 1);   /* { dg-warning "nul" } */
+  T (&ba[0].a[0].b[1] + v0);  /* { dg-warning "nul" } */
+
+  T (ba[0].a[1].a);           /* { dg-warning "nul" } */
+  T (&ba[0].a[1].a[0]);       /* { dg-warning "nul" } */
+  T (&ba[0].a[1].a[0] + 1);   /* { dg-warning "nul" } */
+  T (&ba[0].a[1].a[0] + v0);  /* { dg-warning "nul" } */
+  T (&ba[0].a[1].a[1]);       /* { dg-warning "nul" } */
+  T (&ba[0].a[1].a[1] + 1);   /* { dg-warning "nul" } */
+  T (&ba[0].a[1].a[1] + v0);  /* { dg-warning "nul" } */
+
+  T (ba[0].a[1].b);
+  T (&ba[0].a[1].b[0]);
+  T (&ba[0].a[1].b[0] + 1);
+  T (&ba[0].a[1].b[0] + v0);
+  T (&ba[0].a[1].b[1]);
+  T (&ba[0].a[1].b[1] + 1);
+  T (&ba[0].a[1].b[1] + v0);
+
+
+  T (ba[1].a[0].a);           /* { dg-warning "nul" } */
+  T (&ba[1].a[0].a[0]);       /* { dg-warning "nul" } */
+  T (&ba[1].a[0].a[0] + 1);   /* { dg-warning "nul" } */
+  T (&ba[1].a[0].a[0] + v0);  /* { dg-warning "nul" } */
+  T (&ba[1].a[0].a[1]);       /* { dg-warning "nul" } */
+  T (&ba[1].a[0].a[1] + 1);   /* { dg-warning "nul" } */
+  T (&ba[1].a[0].a[1] + v0);  /* { dg-warning "nul" } */
+
+  T (ba[1].a[0].b);
+  T (&ba[1].a[0].b[0]);
+  T (&ba[1].a[0].b[0] + 1);
+  T (&ba[1].a[0].b[0] + v0);
+  T (&ba[1].a[0].b[1]);
+  T (&ba[1].a[0].b[1] + 1);
+  T (&ba[1].a[0].b[1] + v0);
+
+  T (ba[1].a[1].a);
+  T (&ba[1].a[1].a[0]);
+  T (&ba[1].a[1].a[0] + 1);
+  T (&ba[1].a[1].a[0] + v0);
+  T (&ba[1].a[1].a[1]);
+  T (&ba[1].a[1].a[1] + 1);
+  T (&ba[1].a[1].a[1] + v0);
+
+  T (ba[1].a[1].b);           /* { dg-warning "nul" } */
+  T (&ba[1].a[1].b[0]);       /* { dg-warning "nul" } */
+  T (&ba[1].a[1].b[0] + 1);   /* { dg-warning "nul" } */
+  T (&ba[1].a[1].b[0] + v0);  /* { dg-warning "nul" } */
+  T (&ba[1].a[1].b[1]);       /* { dg-warning "nul" } */
+  T (&ba[1].a[1].b[1] + 1);   /* { dg-warning "nul" } */
+  T (&ba[1].a[1].b[1] + v0);  /* { dg-warning "nul" } */
+
+
+  T (ba[2].a[0].a);
+  T (&ba[2].a[0].a[0]);
+  T (&ba[2].a[0].a[0] + 1);
+  T (&ba[2].a[0].a[0] + v0);
+  T (&ba[2].a[0].a[1]);
+  T (&ba[2].a[0].a[1] + 1);
+  T (&ba[2].a[0].a[1] + v0);
+
+  T (ba[2].a[0].b);
+  T (&ba[2].a[0].b[0]);
+  T (&ba[2].a[0].b[0] + 1);
+  T (&ba[2].a[0].b[0] + v0);
+  T (&ba[2].a[0].b[1]);
+  T (&ba[2].a[0].b[1] + 1);
+  T (&ba[2].a[0].b[1] + v0);
+
+  T (ba[2].a[1].a);
+  T (&ba[2].a[1].a[0]);
+  T (&ba[2].a[1].a[0] + 1);
+  T (&ba[2].a[1].a[0] + v0);
+  T (&ba[2].a[1].a[1]);
+  T (&ba[2].a[1].a[1] + 1);
+  T (&ba[2].a[1].a[1] + v0);
+
+
+  T (ba[3].a[0].a);
+  T (&ba[3].a[0].a[0]);
+  T (&ba[3].a[0].a[0] + 1);
+  T (&ba[3].a[0].a[0] + v0);
+  T (&ba[3].a[0].a[1]);
+  T (&ba[3].a[0].a[1] + 1);
+  T (&ba[3].a[0].a[1] + v0);
+
+  T (ba[3].a[0].b);
+  T (&ba[3].a[0].b[0]);
+  T (&ba[3].a[0].b[0] + 1);
+  T (&ba[3].a[0].b[0] + v0);
+  T (&ba[3].a[0].b[1]);
+  T (&ba[3].a[0].b[1] + 1);
+  T (&ba[3].a[0].b[1] + v0);
+
+  T (ba[3].a[1].a);           /* { dg-warning "nul" } */
+  T (&ba[3].a[1].a[0]);              /* { dg-warning "nul" } */
+  T (&ba[3].a[1].a[0] + 1);   /* { dg-warning "nul" } */
+  T (&ba[3].a[1].a[0] + v0);  /* { dg-warning "nul" } */
+  T (&ba[3].a[1].a[1]);              /* { dg-warning "nul" } */
+  T (&ba[3].a[1].a[1] + 1);   /* { dg-warning "nul" } */
+  T (&ba[3].a[1].a[1] + v0);  /* { dg-warning "nul" } */
+
+  T (ba[3].a[1].b);
+  T (&ba[3].a[1].b[0]);        
+  T (&ba[3].a[1].b[0] + 1);
+  T (&ba[3].a[1].b[0] + v0);
+  T (&ba[3].a[1].b[1]);        
+  T (&ba[3].a[1].b[1] + 1);
+  T (&ba[3].a[1].b[1] + v0);
+
+
+  T (v0 ? ba[0].a[0].a : ba[0].a[0].b);           /* { dg-warning "nul" "bug 
???" } */
+  T (v0 ? ba[0].a[0].a : ba[0].a[0].b);           /* { dg-warning "nul" "bug 
???" } */
+
+  T (v0 ? &ba[0].a[0].a[0] : &ba[3].a[1].a[0]);   /* { dg-warning "nul" "bug 
???" } */
+  T (v0 ? &ba[3].a[1].a[1] :  ba[0].a[0].a);      /* { dg-warning "nul" "bug 
???" } */
+
+  T (v0 ? ba[0].a[0].a : ba[0].a[1].b);
+  T (v0 ? ba[0].a[1].b : ba[0].a[0].a);
+}
+
+/* { dg-prune-output " reading \[1-9\]\[0-9\]? bytes from a region " } */

Reply via email to