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

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
 	{

Reply via email to