From 931631924b3726db31f2f723e6c7d2d0d9de084f Mon Sep 17 00:00:00 2001
From: Martin Sebor <msebor@redhat.com>
Date: Tue, 24 Sep 2019 19:04:54 +0000
Subject: [PATCH] PR tree-optimization/91570 - ICE in get_range_strlen_dynamic
 on a conditional

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

gcc/Changelog:
	* tree-ssa-strlen.c (get_range_strlen_dynamic): Handle null and
	non-constant minlen, maxlen and maxbound.

gcc/testsuite/Changelog:
	* gcc.dg/pr91570.c: New test.

From-SVN: r276105
---
 gcc/ChangeLog                  |  6 ++++++
 gcc/testsuite/ChangeLog        |  5 +++++
 gcc/testsuite/gcc.dg/pr91570.c | 30 ++++++++++++++++++++++++++++++
 gcc/tree-ssa-strlen.c          | 26 ++++++++++++++++++--------
 4 files changed, 59 insertions(+), 8 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/pr91570.c

diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 47f3a006a325..ab0cef72f2b2 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,9 @@
+2019-09-23  Martin Sebor  <msebor@redhat.com>
+
+	PR tree-optimization/91570
+	* tree-ssa-strlen.c (get_range_strlen_dynamic): Handle null and
+	non-constant minlen, maxlen and maxbound.
+
 2019-09-24  Richard Biener  <rguenther@suse.de>
 
 	* tree-vectorizer.h (_stmt_vec_info::const_cond_reduc_code):
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index b90eb6d13ca0..f1f670bf0cfd 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2019-09-23  Martin Sebor  <msebor@redhat.com>
+
+	PR tree-optimization/91570
+	* gcc.dg/pr91570.c: New test.
+
 2019-09-24  Marek Polacek  <polacek@redhat.com>
 
 	PR c++/91868 - improve -Wshadow location.
diff --git a/gcc/testsuite/gcc.dg/pr91570.c b/gcc/testsuite/gcc.dg/pr91570.c
new file mode 100644
index 000000000000..03f268619e97
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr91570.c
@@ -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);
+}
diff --git a/gcc/tree-ssa-strlen.c b/gcc/tree-ssa-strlen.c
index 5e1054be48e2..c82bc7c48155 100644
--- a/gcc/tree-ssa-strlen.c
+++ b/gcc/tree-ssa-strlen.c
@@ -896,7 +896,8 @@ get_range_strlen_dynamic (tree src, c_strlen_data *pdata, bitmap *visited,
 
 		      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 *pdata, bitmap *visited,
 			  || 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;
 		    }
@@ -944,8 +947,7 @@ get_range_strlen_dynamic (tree src, c_strlen_data *pdata, bitmap *visited,
   if (strinfo *si = get_strinfo (idx))
     {
       pdata->minlen = get_string_length (si);
-      if (!pdata->minlen
-	  && si->nonzero_chars)
+      if (!pdata->minlen && si->nonzero_chars)
 	{
 	  if (TREE_CODE (si->nonzero_chars) == INTEGER_CST)
 	    pdata->minlen = si->nonzero_chars;
@@ -989,7 +991,7 @@ get_range_strlen_dynamic (tree src, c_strlen_data *pdata, bitmap *visited,
 	  else
 	    pdata->maxlen = build_all_ones_cst (size_type_node);
 	}
-      else if (TREE_CODE (pdata->minlen) == SSA_NAME)
+      else if (pdata->minlen && TREE_CODE (pdata->minlen) == SSA_NAME)
 	{
 	  const value_range *vr
 	    = CONST_CAST (class vr_values *, rvals)
@@ -1007,11 +1009,19 @@ get_range_strlen_dynamic (tree src, c_strlen_data *pdata, bitmap *visited,
 	      pdata->maxlen = build_all_ones_cst (size_type_node);
 	    }
 	}
-      else
+      else if (pdata->minlen && 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;
     }
-- 
GitLab