On Mon, Nov 20, 2017 at 12:15:09PM -0700, Martin Sebor wrote:
> PR tree-optimization/83075
> * tree-ssa-strlen.c (handle_builtin_stxncpy): Avoid assuming
> strncat/strncpy don't change length of source string.
>
> gcc/testsuite/ChangeLog:
>
> PR tree-optimization/83075
> * gcc.dg/tree-ssa/strncat.c: New test.
> * gcc.dg/tree-ssa/strncpy-2.c: Same.
>
> Index: gcc/testsuite/gcc.dg/tree-ssa/strncat.c
> ===================================================================
> --- gcc/testsuite/gcc.dg/tree-ssa/strncat.c (nonexistent)
> +++ gcc/testsuite/gcc.dg/tree-ssa/strncat.c (working copy)
> @@ -0,0 +1,22 @@
> +/* PR tree-optimization/83075 - Invalid strncpy optimization
> + { dg-do compile }
> + { dg-options "-O2 -Wno-stringop-overflow -fdump-tree-optimized" } */
> +
> +void test_overlapping_strncpy (void)
> +{
> + char a[8] = "";
> +
> + __builtin_strcpy (a, "123");
> +
> + unsigned n0 = __builtin_strlen (a);
> +
> + __builtin_strncat (a + 3, a, n0);
> +
> + unsigned n1 = __builtin_strlen (a);
> +
> + if (n1 == n0)
> + __builtin_abort ();
> +}
> +
> +/* Verify the call to abort hasn't been eliminated.
> + { dg-final { scan-tree-dump-times "abort" 1 "optimized" } } */
> Index: gcc/testsuite/gcc.dg/tree-ssa/strncpy-2.c
> ===================================================================
> --- gcc/testsuite/gcc.dg/tree-ssa/strncpy-2.c (nonexistent)
> +++ gcc/testsuite/gcc.dg/tree-ssa/strncpy-2.c (working copy)
> @@ -0,0 +1,22 @@
> +/* PR tree-optimization/83075 - Invalid strncpy optimization
> + { dg-do compile }
> + { dg-options "-O2 -Wno-stringop-overflow -fdump-tree-optimized" } */
> +
> +void test_overlapping_strncpy (void)
> +{
> + char a[8] = "";
> +
> + __builtin_strcpy (a, "123");
> +
> + unsigned n0 = __builtin_strlen (a);
> +
> + __builtin_strncpy (a + 3, a, n0);
> +
> + unsigned n1 = __builtin_strlen (a);
> +
> + if (n1 == n0)
> + __builtin_abort ();
> +}
> +
> +/* Verify the call to abort hasn't been eliminated.
> + { dg-final { scan-tree-dump-times "abort" 1 "optimized" } } */
I think it is better to have a dg-do run testcase and not scan for abort.
We can be able to optimize at some point n0 to 3 and n1 to 6 and optimize
away the abort. In the testcase I've added to the PR there was a separate
function, you could add __attribute__((noipa)) to it to make sure that
it isn't IPA optimized.
Similarly for the strncat test.
> Index: gcc/tree-ssa-strlen.c
> ===================================================================
> --- gcc/tree-ssa-strlen.c (revision 254961)
> +++ gcc/tree-ssa-strlen.c (working copy)
> @@ -1931,10 +1931,9 @@ handle_builtin_stxncpy (built_in_function, gimple_
> int sidx = get_stridx (src);
> strinfo *sisrc = sidx > 0 ? get_strinfo (sidx) : NULL;
>
> - /* Strncpy() et al. cannot modify the source string. Prevent the rest
> - of the pass from invalidating the strinfo data. */
> - if (sisrc)
> - sisrc->dont_invalidate = true;
> + /* Strncat() and strncpy() can modify the source string by specifying
> + as a destination SRC + strlen(SRC) and a bound <= strlen(SRC) so
> + SISRC->DONT_INVALIDATE must be left clear. */
The destination could be SRC + N and as long as LEN <= N, you shouldn't
invalidate SRC. Though, if LEN < strlen(SRC) I think you return early.
Jakub