Hi! get_range_strlen fails to tell the caller that array_at_struct_end_p has been involved in cases like (&ptr->arr[0]), while it handles (ptr->arr). Fixed thusly, bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
2018-02-12 Jakub Jelinek <ja...@redhat.com> PR tree-optimization/84339 * gimple-fold.c (get_range_strlen): Set *FLEXP to true when handling ARRAY_REF where first operand is array_at_struct_end_p COMPONENT_REF. Formatting fixes. * gcc.c-torture/execute/pr84339.c: New test. --- gcc/gimple-fold.c.jj 2018-01-11 19:01:07.259442879 +0100 +++ gcc/gimple-fold.c 2018-02-12 15:44:41.350214335 +0100 @@ -1380,9 +1380,15 @@ get_range_strlen (tree arg, tree length[ /* Set the minimum size to zero since the string in the array could have zero length. */ *minlen = ssize_int (0); + + if (TREE_CODE (TREE_OPERAND (arg, 0)) == COMPONENT_REF + && type == TREE_TYPE (TREE_OPERAND (arg, 0)) + && array_at_struct_end_p (TREE_OPERAND (arg, 0))) + *flexp = true; } else if (TREE_CODE (arg) == COMPONENT_REF - && TREE_CODE (TREE_TYPE (TREE_OPERAND (arg, 1))) == ARRAY_TYPE) + && (TREE_CODE (TREE_TYPE (TREE_OPERAND (arg, 1))) + == ARRAY_TYPE)) { /* Use the type of the member array to determine the upper bound on the length of the array. This may be overly @@ -1428,7 +1434,7 @@ get_range_strlen (tree arg, tree length[ || integer_zerop (val)) return false; val = wide_int_to_tree (TREE_TYPE (val), - wi::sub(wi::to_wide (val), 1)); + wi::sub (wi::to_wide (val), 1)); /* Set the minimum size to zero since the string in the array could have zero length. */ *minlen = ssize_int (0); --- gcc/testsuite/gcc.c-torture/execute/pr84339.c.jj 2018-02-12 15:47:04.167243039 +0100 +++ gcc/testsuite/gcc.c-torture/execute/pr84339.c 2018-02-12 15:46:48.363239868 +0100 @@ -0,0 +1,30 @@ +/* PR tree-optimization/84339 */ + +struct S { int a; char b[1]; }; + +__attribute__((noipa)) int +foo (struct S *p) +{ + return __builtin_strlen (&p->b[0]); +} + +__attribute__((noipa)) int +bar (struct S *p) +{ + return __builtin_strlen (p->b); +} + +int +main () +{ + struct S *p = __builtin_malloc (sizeof (struct S) + 16); + if (p) + { + p->a = 1; + __builtin_strcpy (p->b, "abcdefg"); + if (foo (p) != 7 || bar (p) != 7) + __builtin_abort (); + __builtin_free (p); + } + return 0; +} Jakub