Fix get_range_strlen (PR tree-optimization/84339)

Message ID 20180212214923.GJ5867@tucnak
State New
Headers show
Series
  • Fix get_range_strlen (PR tree-optimization/84339)
Related show

Commit Message

Jakub Jelinek Feb. 12, 2018, 9:49 p.m.
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  <jakub@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.


	Jakub

Comments

Richard Biener Feb. 13, 2018, 8 a.m. | #1
On Mon, 12 Feb 2018, Jakub Jelinek wrote:

> 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?

Ok.

Richard.

> 2018-02-12  Jakub Jelinek  <jakub@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
> 
>

Patch

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