get_range_strlen() returns non-constant type sizes for VLAs that
the new get_range_strlen_dynamic() function isn't prepared to deal
with and ICEs.  Extending the functions to deal with VLAs (and
other dynamically allocated objects) is on my list of things to
do for GCC 11.  For GCC 10, the attached patch has both functions
fail when the size of an array isn't constant.

Martin
PR tree-optimization/94131 - ICE on printf with a VLA string and -fno-tree-ccp

gcc/testsuite/ChangeLog:

	PR tree-optimization/94131
	* gcc.dg/pr94131.c: New test.

gcc/ChangeLog:

	PR tree-optimization/94131
	* gimple-fold.c (get_range_strlen_tree): Fail for variable-length
	types and decls.
	* tree-ssa-strlen.c (get_range_strlen_dynamic): Avoid assuming
	types have constant sizes.

diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c
index fa7a396a361..c85b4f2662b 100644
--- a/gcc/gimple-fold.c
+++ b/gcc/gimple-fold.c
@@ -1372,7 +1372,9 @@ get_range_strlen_tree (tree arg, bitmap *visited, strlen_range_kind rkind,
 
 	  /* Fail when the array bound is unknown or zero.  */
 	  val = TYPE_SIZE_UNIT (optype);
-	  if (!val || integer_zerop (val))
+	  if (!val
+	      || TREE_CODE (val) != INTEGER_CST
+	      || integer_zerop (val))
 	    return false;
 
 	  val = fold_build2 (MINUS_EXPR, TREE_TYPE (val), val,
@@ -1406,7 +1408,9 @@ get_range_strlen_tree (tree arg, bitmap *visited, strlen_range_kind rkind,
 
 	  /* Fail when the array bound is unknown or zero.  */
 	  val = TYPE_SIZE_UNIT (optype);
-	  if (!val || integer_zerop (val))
+	  if (!val
+	      || TREE_CODE (val) != INTEGER_CST
+	      || integer_zerop (val))
 	    return false;
 	  val = fold_build2 (MINUS_EXPR, TREE_TYPE (val), val,
 			     integer_one_node);
@@ -1442,7 +1446,9 @@ get_range_strlen_tree (tree arg, bitmap *visited, strlen_range_kind rkind,
 	      /* Fail if the offset is out of bounds.  Such accesses
 		 should be diagnosed at some point.  */
 	      val = DECL_SIZE_UNIT (ref);
-	      if (!val || integer_zerop (val))
+	      if (!val
+		  || TREE_CODE (val) != INTEGER_CST
+		  || integer_zerop (val))
 		return false;
 
 	      poly_offset_int psiz = wi::to_offset (val);
diff --git a/gcc/testsuite/gcc.dg/pr84131.c b/gcc/testsuite/gcc.dg/pr84131.c
new file mode 100644
index 00000000000..19de5685224
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr94131.c
@@ -0,0 +1,29 @@
+/* PR 94131 - ICE on printf with a VLA string and -fno-tree-ccp
+   -fno-tree-forwprop
+   { dg-do compile }
+   { dg-options "-O1 -fno-tree-ccp -fno-tree-forwprop" } */
+
+void rv1 (int n)
+{
+  char a[n];
+  __INTPTR_TYPE__ i = (__INTPTR_TYPE__ )&a[0];
+  i &= 3;
+
+  __builtin_memset (a, '\0', sizeof a);
+  __builtin_printf ("%s", i ? &a[0] : "");
+}
+
+
+void sink (void*);
+
+void rv2 (int n)
+{
+  char a[n];
+  __INTPTR_TYPE__ i = (__INTPTR_TYPE__)&a[0];
+  i &= 3;
+
+  __builtin_memset (a, '\0', sizeof a);
+  __builtin_printf ("%s", i ? &a[0] : "");
+
+  sink (a);
+}
diff --git a/gcc/tree-ssa-strlen.c b/gcc/tree-ssa-strlen.c
index 8815cdbc9ca..e1589f68806 100644
--- a/gcc/tree-ssa-strlen.c
+++ b/gcc/tree-ssa-strlen.c
@@ -1139,10 +1139,16 @@ get_range_strlen_dynamic (tree src, c_strlen_data *pdata, bitmap *visited,
 	    {
 	      tree basetype = TREE_TYPE (base);
 	      tree size = TYPE_SIZE_UNIT (basetype);
-	      ++off;   /* Increment for the terminating nul.  */
-	      pdata->maxlen = fold_build2 (MINUS_EXPR, size_type_node, size,
-					   build_int_cst (size_type_node, off));
-	      pdata->maxbound = pdata->maxlen;
+	      if (TREE_CODE (size) == INTEGER_CST)
+		{
+		  ++off;   /* Increment for the terminating nul.  */
+		  tree toffset = build_int_cst (size_type_node, off);
+		  pdata->maxlen = fold_build2 (MINUS_EXPR, size_type_node, size,
+					       toffset);
+		  pdata->maxbound = pdata->maxlen;
+		}
+	      else	
+		pdata->maxlen = build_all_ones_cst (size_type_node);
 	    }
 	  else
 	    pdata->maxlen = build_all_ones_cst (size_type_node);

Reply via email to