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 } };