diff mbox series

use TYPE_SIZE instead of TYPE_DOMAIN to compute array size (PR 86400)

Message ID 351e6b7f-4f16-fd67-2228-72d938dc1f56@gmail.com
State New
Headers show
Series use TYPE_SIZE instead of TYPE_DOMAIN to compute array size (PR 86400) | expand

Commit Message

Martin Sebor July 5, 2018, 2:17 a.m. UTC
A change of mine to the strlen pass assumes that the strlen
argument points to an object of the correct type and does
not correctly handle GIMPLE where the argument has the wrong
type such as in:

   extern char a[1][2];
   n = strlen (*a);

where the strlen pass actually sees

   n = strlen (a);

The attached patch corrects the code to use TYPE_SIZE to
determine the size of the array argument rather than using
TYPE_DOMAIN.

Tested on x86_64-linux.

Martin

Comments

Richard Biener July 5, 2018, 8:05 a.m. UTC | #1
On Thu, Jul 5, 2018 at 4:17 AM Martin Sebor <msebor@gmail.com> wrote:
>
> A change of mine to the strlen pass assumes that the strlen
> argument points to an object of the correct type and does
> not correctly handle GIMPLE where the argument has the wrong
> type such as in:
>
>    extern char a[1][2];
>    n = strlen (*a);
>
> where the strlen pass actually sees
>
>    n = strlen (a);
>
> The attached patch corrects the code to use TYPE_SIZE to
> determine the size of the array argument rather than using
> TYPE_DOMAIN.
>
> Tested on x86_64-linux.

OK.

Richard.

> Martin
>
diff mbox series

Patch

PR tree-optimization/86400 - set<string>::set<char (*)[2]) constructor does not work with array argument

gcc/ChangeLog:

	PR c++/86400
	* tree-ssa-strlen.c (maybe_set_strlen_range): Use type size rather
	than its domain to compute its the upper bound of a char array.

gcc/testsuite/ChangeLog:

	PR c++/86400
	* gcc.dg/strlenopt-47.c: New test.

Index: gcc/testsuite/gcc.dg/strlenopt-47.c
===================================================================
--- gcc/testsuite/gcc.dg/strlenopt-47.c	(nonexistent)
+++ gcc/testsuite/gcc.dg/strlenopt-47.c	(working copy)
@@ -0,0 +1,18 @@ 
+/* PR tree-optimization/86400 - set<string>::set<char (*)[2]) constructor
+   does not work with array argument - wrong strlen result after prior
+   strnlen
+   { dg-do compile }
+   { dg-options "-O2 -Wall -fdump-tree-optimized" } */
+
+#include "strlenopt.h"
+
+void f (void)
+{
+  static char root[1][2] = { "/" };
+  int len = strlen (*root);
+  if (len != 1)
+    abort();
+}
+
+/* { dg-final { scan-tree-dump-times "= strlen" 1 "optimized" } }
+   { dg-final { scan-tree-dump-times "abort" 1 "optimized" } } */
Index: gcc/tree-ssa-strlen.c
===================================================================
--- gcc/tree-ssa-strlen.c	(revision 262418)
+++ gcc/tree-ssa-strlen.c	(working copy)
@@ -1156,22 +1156,17 @@  maybe_set_strlen_range (tree lhs, tree src, tree b
       if (src_is_array && !array_at_struct_end_p (src))
 	{
 	  tree type = TREE_TYPE (src);
-	  if (tree dom = TYPE_DOMAIN (type))
-	    {
-	      tree maxval = TYPE_MAX_VALUE (dom);
-	      if (maxval)
-		max = wi::to_wide (maxval);
-	      else
-		max = wi::zero (min.get_precision ());
+	  if (tree size = TYPE_SIZE_UNIT (type))
+	    if (size && TREE_CODE (size) == INTEGER_CST)
+	      max = wi::to_wide (size);
 
-	      /* For strlen() the upper bound above is equal to
-		 the longest string that can be stored in the array
-		 (i.e., it accounts for the terminating nul.  For
-		 strnlen() bump up the maximum by one since the array
-		 need not be nul-terminated.  */
-	      if (bound)
-		++max;
-	    }
+	  /* For strlen() the upper bound above is equal to
+	     the longest string that can be stored in the array
+	     (i.e., it accounts for the terminating nul.  For
+	     strnlen() bump up the maximum by one since the array
+	     need not be nul-terminated.  */
+	  if (!bound && max != 0)
+	    --max;
 	}
       else
 	{