The following fixes PR85244 where we fail to handle a flex-array
reference as such and constrain it with the appearant size of an external
declaration.  The fix is to handle this case much like the unconstrained
common one and to not regress some cases the patch adjusts the handling
of flex-array detection when visiting component references.

Bootstrapped and tested on x86_64-unknown-linux-gnu, applied to trunk.

Richard.

2018-04-06  Richard Biener  <rguent...@suse.de>

        PR middle-end/85244
        * tree-dfa.c (get_ref_base_and_extent): Reset seen_variable_array_ref
        after seeing a component reference with an adjacent field.  Treat
        refs to arrays at struct end of external decls similar to
        refs to unconstrained commons.

        * gcc.dg/torture/pr85244-1.c: New testcase.
        * gcc.dg/torture/pr85244-2.c: Likewise.

Index: gcc/tree-dfa.c
===================================================================
--- gcc/tree-dfa.c      (revision 259082)
+++ gcc/tree-dfa.c      (working copy)
@@ -438,7 +438,7 @@ get_ref_base_and_extent (tree exp, poly_
                   referenced the last field of a struct or a union member
                   then we have to adjust maxsize by the padding at the end
                   of our field.  */
-               if (seen_variable_array_ref && known_size_p (maxsize))
+               if (seen_variable_array_ref)
                  {
                    tree stype = TREE_TYPE (TREE_OPERAND (exp, 0));
                    tree next = DECL_CHAIN (field);
@@ -454,7 +454,7 @@ get_ref_base_and_extent (tree exp, poly_
                            || ssize == NULL
                            || !poly_int_tree_p (ssize))
                          maxsize = -1;
-                       else
+                       else if (known_size_p (maxsize))
                          {
                            poly_offset_int tem
                              = (wi::to_poly_offset (ssize)
@@ -464,6 +464,11 @@ get_ref_base_and_extent (tree exp, poly_
                            maxsize += tem;
                          }
                      }
+                   /* An component ref with an adjacent field up in the
+                      structure hierarchy constrains the size of any variable
+                      array ref lower in the access hierarchy.  */
+                   else
+                     seen_variable_array_ref = false;
                  }
              }
            else
@@ -622,7 +627,9 @@ get_ref_base_and_extent (tree exp, poly_
 
   if (DECL_P (exp))
     {
-      if (flag_unconstrained_commons && VAR_P (exp) && DECL_COMMON (exp))
+      if (VAR_P (exp)
+         && ((flag_unconstrained_commons && DECL_COMMON (exp))
+             || (DECL_EXTERNAL (exp) && seen_variable_array_ref)))
        {
          tree sz_tree = TYPE_SIZE (TREE_TYPE (exp));
          /* If size is unknown, or we have read to the end, assume there
Index: gcc/testsuite/gcc.dg/torture/pr85244-1.c
===================================================================
--- gcc/testsuite/gcc.dg/torture/pr85244-1.c    (nonexistent)
+++ gcc/testsuite/gcc.dg/torture/pr85244-1.c    (working copy)
@@ -0,0 +1,19 @@
+/* { dg-do run } */
+/* { dg-additional-sources "pr85244-2.c" } */
+
+struct s {
+ long a;
+ int b;
+ int tab[];
+};
+
+extern const struct s val;
+extern int idx;
+extern void abort (void);
+
+int main()
+{
+  if (val.tab[0] != 42 || val.tab[1] != 1337 || val.tab[idx] != 1337)
+    abort ();
+  return 0;
+}
Index: gcc/testsuite/gcc.dg/torture/pr85244-2.c
===================================================================
--- gcc/testsuite/gcc.dg/torture/pr85244-2.c    (nonexistent)
+++ gcc/testsuite/gcc.dg/torture/pr85244-2.c    (working copy)
@@ -0,0 +1,8 @@
+struct s {
+    long a;
+    int b;
+    int tab[];
+};
+
+int idx = 1;
+const struct s val = { 0, 0, { 42, 1337 } };

Reply via email to