The new get_range_strlen_dynamic function has a couple of bugs
where it assumes that the length range bounds it gets back from
get_range_strlen are non-null integer constants.  The attached
"quick and dirty" fix removes those assumptions.  Since it's
apparently causing package failures in Jeff's GCC buildbot
I will commit the patch on Monday to get those builds to pass.
But I'm not too happy with how fragile this seems to be so I
will try to do some further cleanup here in the near future
to make it more robust.

Martin
PR tree-optimization/91570 - ICE in get_range_strlen_dynamic on a conditional of two strings

gcc/testsuite/ChangeLog:

	PR tree-optimization/91570
	* gcc.dg/pr91570.c: New test.

gcc/ChangeLog:

	PR tree-optimization/91570
	* tree-ssa-strlen.c (get_range_strlen_dynamic): Handle null and
	non-constant maxlen and maxbound.

Index: gcc/testsuite/gcc.dg/pr91570.c
===================================================================
--- gcc/testsuite/gcc.dg/pr91570.c	(nonexistent)
+++ gcc/testsuite/gcc.dg/pr91570.c	(working copy)
@@ -0,0 +1,30 @@
+/* PR tree-optimization/91570 - ICE in get_range_strlen_dynamic on
+   a conditional of two strings
+   { dg-do compile }
+   { dg-options "-O2 -Wall" } */
+
+extern char a[], b[];
+
+/* Test case from comment #0 on the bug.  */
+
+void comment_0 (int i)
+{
+  a[0] = 0;
+  b[0] = '1';
+
+  const char *p = i ? b : a;
+
+  if (__builtin_snprintf (0, 0, "%s", p) < 4)
+    __builtin_abort ();
+}
+
+
+/* Test case from comment #2 on the bug.  */
+
+void comment_2 (char *s)
+{
+  char *t = __builtin_strrchr (s, '/');
+  __builtin_strcat (s, ".SIF");
+  t = t ? t : s;
+  __builtin_printf ("%s", t);
+}
Index: gcc/tree-ssa-strlen.c
===================================================================
--- gcc/tree-ssa-strlen.c	(revision 276021)
+++ gcc/tree-ssa-strlen.c	(working copy)
@@ -896,7 +896,8 @@ get_range_strlen_dynamic (tree src, c_strlen_data
 
 		      if (!argdata.minlen
 			  || (integer_zerop (argdata.minlen)
-			      && integer_all_onesp (argdata.maxbound)
+			      && (!argdata.maxbound
+				  || integer_all_onesp (argdata.maxbound))
 			      && integer_all_onesp (argdata.maxlen)))
 			{
 			  /* Set the upper bound of the length to unbounded.  */
@@ -910,11 +911,13 @@ get_range_strlen_dynamic (tree src, c_strlen_data
 			  || tree_int_cst_lt (argdata.minlen, pdata->minlen))
 			pdata->minlen = argdata.minlen;
 		      if (!pdata->maxlen
-			  || tree_int_cst_lt (pdata->maxlen, argdata.maxlen))
+			  || (argdata.maxlen
+			      && tree_int_cst_lt (pdata->maxlen, argdata.maxlen)))
 			pdata->maxlen = argdata.maxlen;
 		      if (!pdata->maxbound
-			  || (tree_int_cst_lt (pdata->maxbound,
-					       argdata.maxbound)
+			  || (argdata.maxbound
+			      && tree_int_cst_lt (pdata->maxbound,
+						  argdata.maxbound)
 			      && !integer_all_onesp (argdata.maxbound)))
 			pdata->maxbound = argdata.maxbound;
 		    }
@@ -1007,11 +1010,19 @@ get_range_strlen_dynamic (tree src, c_strlen_data
 	      pdata->maxlen = build_all_ones_cst (size_type_node);
 	    }
 	}
-      else
+      else if (TREE_CODE (pdata->minlen) == INTEGER_CST)
 	{
 	  pdata->maxlen = pdata->minlen;
 	  pdata->maxbound = pdata->minlen;
 	}
+      else
+	{
+	  /* For PDATA->MINLEN that's a non-constant expression such
+	     as PLUS_EXPR whose value range is unknown, set the bounds
+	     to zero and SIZE_MAX.  */
+	  pdata->minlen = build_zero_cst (size_type_node);
+	  pdata->maxlen = build_all_ones_cst (size_type_node);
+	}
 
       return true;
     }

Reply via email to