Hi,
this is an update on my strlen range patch (V6).  Again re-based and
retested to current trunk.

It finally removes the -ffassume-zero-terminated-char-arrays flag.
And is more careful to preserve existing strlen optimization tests.

I did not see the need to change the interface of get_range_string
yet, as this would make the patch much larger, and might as well be
done in a follow-up patch.  I might suggest to rename one of the two
get_range_strlen functions at the same time as it is rather confusing
to have to count the parameters in order to tell which function is
meant.


This hunk in tree-ssa-strlen.c really needs some explanations:

@@ -3192,7 +3156,13 @@ get_min_string_length (tree rhs, bool *f
        && TREE_READONLY (rhs))
      rhs = DECL_INITIAL (rhs);

-  if (rhs && TREE_CODE (rhs) == STRING_CST)
+  if (rhs && TREE_CODE (rhs) == STRING_CST
+      && tree_fits_uhwi_p (TYPE_SIZE_UNIT (TREE_TYPE (rhs)))
+      && compare_tree_int (TYPE_SIZE_UNIT (TREE_TYPE (rhs)),
+                          TREE_STRING_LENGTH (rhs)) >= 0
+      && tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (rhs)))) == 1
+      && TREE_STRING_LENGTH (rhs) > 0
+      && TREE_STRING_POINTER (rhs) [TREE_STRING_LENGTH (rhs) - 1] == '\0')
      {
        *full_string_p = true;
        return strlen (TREE_STRING_POINTER (rhs));

This is responsible for the removed xfail on c-c++-common/attr-nonstring-3.c
and is tested in gcc.dg/strlenopt-57.c where an invalid call to strlen
is not folded, while in gcc.dg/strlenopt-58.c a valid call to strlen is
folded and finally completely removed.

This hunk depends a lot on the STRING_CST semantics.
In the V1 of the proposed STRING_CST semantics, this part is tautological, and
could be removed, or changed to an assertion:
+      && TREE_STRING_LENGTH (rhs) > 0
+      && TREE_STRING_POINTER (rhs) [TREE_STRING_LENGTH (rhs) - 1] == '\0')

In the V2 of the proposed STRING_CST semantics, this part is tautlological:
+      && tree_fits_uhwi_p (TYPE_SIZE_UNIT (TREE_TYPE (rhs)))
+      && compare_tree_int (TYPE_SIZE_UNIT (TREE_TYPE (rhs)),
+                          TREE_STRING_LENGTH (rhs)) >= 0

Currently due the the way the braced initializer to string folding works, there
are now initializer strings that are not zero-terminated and some that are.

What is interesting to note, is that this is another path where the initializer
STRING_CST and literal STRING_CST seem to mix with their different semantics.

And the change in string_constant to return initializer elements seems not
to be responsible for this confusion here.


Bootstrapped and reg-tested on x86_64-pc-linux-gnu.
Is it OK for trunk?


Thanks
Bernd.
gcc:
2018-08-26  Bernd Edlinger  <bernd.edlin...@hotmail.de>

        * gimple-fold.c (looks_like_a_char_array_without_typecast_p): New
        helper function for strlen range estimations.
        (get_range_strlen): Use looks_like_a_char_array_without_typecast_p
        for warnings, but use GIMPLE semantics otherwise.
        * tree-ssa-strlen.c (maybe_set_strlen_range): Use GIMPLE semantics.
        (get_min_string_length): Avoid not NUL terminated string literals.

testsuite:
2018-08-26  Bernd Edlinger  <bernd.edlin...@hotmail.de>

        * c-c++-common/attr-nonstring-3.c: Remove xfail.
        * gcc.dg/pr83373.c: Add xfail.
        * gcc.dg/strlenopt-36.c: Add xfail.
        * gcc.dg/strlenopt-40.c: Adjust test expectations.
        * gcc.dg/strlenopt-45.c: Adjust test expectations.
        * gcc.dg/strlenopt-48.c: Add xfail.
        * gcc.dg/strlenopt-51.c: Adjust test expectations.
        * gcc.dg/strlenopt-57.c: New test.
        * gcc.dg/strlenopt-58.c: New test.

diff -Npur gcc/gimple-fold.c gcc/gimple-fold.c
--- gcc/gimple-fold.c	2018-08-23 12:35:17.000000000 +0200
+++ gcc/gimple-fold.c	2018-08-25 21:50:18.354332301 +0200
@@ -1257,6 +1257,40 @@ gimple_fold_builtin_memset (gimple_stmt_
   return true;
 }
 
+/* Determine if a char array is suitable for strlen range estimations.
+   Return false if ARG is not a char array, or if the inner reference
+   chain appears to go through a type cast, otherwise return true.
+   Note that the gimple type informations are not 100% guaranteed
+   to be accurate, therefore this function shall only be used for
+   warnings.  */
+
+static bool
+looks_like_a_char_array_without_typecast_p (tree arg)
+{
+  /* We handle arrays of integer types.  */
+  if (TREE_CODE (TREE_TYPE (arg)) != ARRAY_TYPE
+      || TREE_CODE (TREE_TYPE (TREE_TYPE (arg))) != INTEGER_TYPE
+      || TYPE_MODE (TREE_TYPE (TREE_TYPE (arg))) != TYPE_MODE (char_type_node)
+      || TYPE_PRECISION (TREE_TYPE (TREE_TYPE (arg)))
+	 != TYPE_PRECISION (char_type_node))
+    return false;
+
+  tree base = arg;
+  while (TREE_CODE (base) == ARRAY_REF
+	 || TREE_CODE (base) == ARRAY_RANGE_REF
+	 || TREE_CODE (base) == COMPONENT_REF)
+    base = TREE_OPERAND (base, 0);
+
+  /* If this looks like a type cast don't assume anything.  */
+  if ((TREE_CODE (base) == MEM_REF
+       && (! integer_zerop (TREE_OPERAND (base, 1))
+	   || TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (TREE_OPERAND (base, 0))))
+	      != TYPE_MAIN_VARIANT (TREE_TYPE (base))))
+      || handled_component_p (base))
+    return false;
+
+  return true;
+}
 
 /* Obtain the minimum and maximum string length or minimum and maximum
    value of ARG in LENGTH[0] and LENGTH[1], respectively.
@@ -1272,6 +1306,7 @@ gimple_fold_builtin_memset (gimple_stmt_
    PHIs and COND_EXPRs optimistically, if we can determine string length
    minimum and maximum, it will use the minimum from the ones where it
    can be determined.
+   TYPE == 2 and FUZZY != 0 cannot be used together.
    Set *FLEXP to true if the range of the string lengths has been
    obtained from the upper bound of an array at the end of a struct.
    Such an array may hold a string that's longer than its upper bound
@@ -1312,8 +1347,8 @@ get_range_strlen (tree arg, tree length[
 		 member.  */
 	      tree idx = TREE_OPERAND (op, 1);
 
-	      arg = TREE_OPERAND (op, 0);
-	      tree optype = TREE_TYPE (arg);
+	      op = TREE_OPERAND (op, 0);
+	      tree optype = TREE_TYPE (op);
 	      if (tree dom = TYPE_DOMAIN (optype))
 		if (tree bound = TYPE_MAX_VALUE (dom))
 		  if (TREE_CODE (bound) == INTEGER_CST
@@ -1339,23 +1374,21 @@ get_range_strlen (tree arg, tree length[
 	    return get_range_strlen (TREE_OPERAND (arg, 0), length,
 				     visited, type, fuzzy, flexp, eltsize);
 
+	  if (eltsize != 1 || fuzzy != 2)
+	    return false;
+
 	  if (TREE_CODE (arg) == ARRAY_REF)
 	    {
-	      tree type = TREE_TYPE (TREE_OPERAND (arg, 0));
-
-	      /* Determine the "innermost" array type.  */
-	      while (TREE_CODE (type) == ARRAY_TYPE
-		     && TREE_CODE (TREE_TYPE (type)) == ARRAY_TYPE)
-		type = TREE_TYPE (type);
-
-	      /* Avoid arrays of pointers.  */
-	      tree eltype = TREE_TYPE (type);
-	      if (TREE_CODE (type) != ARRAY_TYPE
-		  || !INTEGRAL_TYPE_P (eltype))
+	      if (!looks_like_a_char_array_without_typecast_p (arg))
 		return false;
 
+	      tree type = TREE_TYPE (arg);
+
+	      /* Fail when the array bound is unknown or zero.  */
 	      val = TYPE_SIZE_UNIT (type);
-	      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,
@@ -1364,15 +1397,16 @@ get_range_strlen (tree arg, tree length[
 		 the array could have zero length.  */
 	      *minlen = ssize_int (0);
 
-	      if (TREE_CODE (TREE_OPERAND (arg, 0)) == COMPONENT_REF
-		  && type == TREE_TYPE (TREE_OPERAND (arg, 0))
-		  && array_at_struct_end_p (TREE_OPERAND (arg, 0)))
+	      if (TREE_CODE (arg) == COMPONENT_REF
+		  && type == TREE_TYPE (arg)
+		  && array_at_struct_end_p (arg))
 		*flexp = true;
 	    }
-	  else if (TREE_CODE (arg) == COMPONENT_REF
-		   && (TREE_CODE (TREE_TYPE (TREE_OPERAND (arg, 1)))
-		       == ARRAY_TYPE))
+	  else if (TREE_CODE (arg) == COMPONENT_REF)
 	    {
+	      if (!looks_like_a_char_array_without_typecast_p (arg))
+		return false;
+
 	      /* Use the type of the member array to determine the upper
 		 bound on the length of the array.  This may be overly
 		 optimistic if the array itself isn't NUL-terminated and
@@ -1388,22 +1422,20 @@ get_range_strlen (tree arg, tree length[
 
 	      tree type = TREE_TYPE (arg);
 
-	      while (TREE_CODE (type) == ARRAY_TYPE
-		     && TREE_CODE (TREE_TYPE (type)) == ARRAY_TYPE)
-		type = TREE_TYPE (type);
-
 	      /* Fail when the array bound is unknown or zero.  */
 	      val = TYPE_SIZE_UNIT (type);
-	      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);
 	      /* Set the minimum size to zero since the string in
 		 the array could have zero length.  */
 	      *minlen = ssize_int (0);
 	    }
-
-	  if (VAR_P (arg))
+	  else if (VAR_P (arg))
 	    {
 	      tree type = TREE_TYPE (arg);
 	      if (POINTER_TYPE_P (type))
@@ -1411,13 +1443,23 @@ get_range_strlen (tree arg, tree length[
 
 	      if (TREE_CODE (type) == ARRAY_TYPE)
 		{
+		  /* We handle arrays of integer types.  */
+		  if (TREE_CODE (TREE_TYPE (type)) != INTEGER_TYPE
+		      || TYPE_MODE (TREE_TYPE (type))
+			 != TYPE_MODE (char_type_node)
+		      || TYPE_PRECISION (TREE_TYPE (type))
+			 != TYPE_PRECISION (char_type_node))
+		    return false;
+
+		  /* Fail when the array bound is unknown or zero.  */
 		  val = TYPE_SIZE_UNIT (type);
 		  if (!val
 		      || TREE_CODE (val) != INTEGER_CST
 		      || integer_zerop (val))
 		    return false;
-		  val = wide_int_to_tree (TREE_TYPE (val),
-					  wi::sub (wi::to_wide (val), 1));
+
+		  val = fold_build2 (MINUS_EXPR, TREE_TYPE (val), val,
+				     integer_one_node);
 		  /* Set the minimum size to zero since the string in
 		     the array could have zero length.  */
 		  *minlen = ssize_int (0);
@@ -1550,6 +1592,7 @@ get_range_strlen (tree arg, tree length[
    if we can determine string length minimum and maximum; it will use
    the minimum from the ones where it can be determined.
    STRICT false should be only used for warning code.
+   STRICT is by default false.
 
    ELTSIZE is 1 for normal single byte character strings, and 2 or
    4 for wide characer strings.  ELTSIZE is by default 1.  */
diff -Npur gcc/tree-ssa-strlen.c gcc/tree-ssa-strlen.c
--- gcc/tree-ssa-strlen.c	2018-08-23 12:35:14.000000000 +0200
+++ gcc/tree-ssa-strlen.c	2018-08-25 21:00:29.659409820 +0200
@@ -1154,42 +1154,6 @@ maybe_set_strlen_range (tree lhs, tree s
   wide_int max = wi::to_wide (TYPE_MAX_VALUE (ptrdiff_type_node));
   wide_int min = wi::zero (max.get_precision ());
 
-  if (TREE_CODE (src) == ADDR_EXPR)
-    {
-      /* The last array member of a struct can be bigger than its size
-	 suggests if it's treated as a poor-man's flexible array member.  */
-      src = TREE_OPERAND (src, 0);
-      bool src_is_array = TREE_CODE (TREE_TYPE (src)) == ARRAY_TYPE;
-      if (src_is_array && !array_at_struct_end_p (src))
-	{
-	  tree type = TREE_TYPE (src);
-	  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 != 0)
-	    --max;
-	}
-      else
-	{
-	  if (TREE_CODE (src) == COMPONENT_REF && !src_is_array)
-	    src = TREE_OPERAND (src, 1);
-	  if (DECL_P (src))
-	    {
-	      /* Handle the unlikely case of strlen (&c) where c is some
-		 variable.  */
-	      if (tree size = DECL_SIZE_UNIT (src))
-		if (TREE_CODE (size) == INTEGER_CST)
-		  max = wi::to_wide (size);
-	    }
-	}
-    }
-
   if (bound)
     {
       /* For strnlen, adjust MIN and MAX as necessary.  If the bound
@@ -3192,7 +3156,13 @@ get_min_string_length (tree rhs, bool *f
       && TREE_READONLY (rhs))
     rhs = DECL_INITIAL (rhs);
 
-  if (rhs && TREE_CODE (rhs) == STRING_CST)
+  if (rhs && TREE_CODE (rhs) == STRING_CST
+      && tree_fits_uhwi_p (TYPE_SIZE_UNIT (TREE_TYPE (rhs)))
+      && compare_tree_int (TYPE_SIZE_UNIT (TREE_TYPE (rhs)),
+			   TREE_STRING_LENGTH (rhs)) >= 0
+      && tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (rhs)))) == 1
+      && TREE_STRING_LENGTH (rhs) > 0
+      && TREE_STRING_POINTER (rhs) [TREE_STRING_LENGTH (rhs) - 1] == '\0')
     {
       *full_string_p = true;
       return strlen (TREE_STRING_POINTER (rhs));
diff -Npur gcc/testsuite/c-c++-common/attr-nonstring-3.c gcc/testsuite/c-c++-common/attr-nonstring-3.c
--- gcc/testsuite/c-c++-common/attr-nonstring-3.c	2018-08-23 12:35:15.000000000 +0200
+++ gcc/testsuite/c-c++-common/attr-nonstring-3.c	2018-08-25 20:45:51.835677067 +0200
@@ -406,7 +406,7 @@ void test_strlen (struct MemArrays *p, c
   {
     char a[] __attribute__ ((nonstring)) = { 1, 2, 3 };
 
-    T (strlen (a));             /* { dg-warning "argument 1 declared attribute .nonstring." "pr86688" { xfail *-*-* } } */
+    T (strlen (a));             /* { dg-warning "argument 1 declared attribute .nonstring." } */
   }
 
   {
diff -Npur gcc/testsuite/gcc.dg/pr83373.c gcc/testsuite/gcc.dg/pr83373.c
--- gcc/testsuite/gcc.dg/pr83373.c	2018-08-22 22:34:01.000000000 +0200
+++ gcc/testsuite/gcc.dg/pr83373.c	2018-08-25 14:41:59.649419917 +0200
@@ -16,7 +16,7 @@ inline char* my_strcpy (char* dst, const
     __builtin_memcpy (dst, src, len + 1);
   else
     {
-      __builtin_memcpy (dst, src, size - 1); /* { dg-bogus "\\\[-Wstringop-oveflow]" } */
+      __builtin_memcpy (dst, src, size - 1); /* { dg-bogus "\\\[-Wstringop-overflow=]" "" { xfail *-*-* } } */
       dst[size - 1] = '\0';
     }
 
diff -Npur gcc/testsuite/gcc.dg/strlenopt-36.c gcc/testsuite/gcc.dg/strlenopt-36.c
--- gcc/testsuite/gcc.dg/strlenopt-36.c	2018-08-22 22:34:01.000000000 +0200
+++ gcc/testsuite/gcc.dg/strlenopt-36.c	2018-08-25 18:10:54.475978390 +0200
@@ -83,4 +83,4 @@ void test_nested_memarray (struct Nested
   T (strlen (ma->ma1.a1) == 0);  */
 }
 
-/* { dg-final { scan-tree-dump-not "failure_on_line" "optimized" } } */
+/* { dg-final { scan-tree-dump-not "failure_on_line" "optimized" { xfail *-*-* } } } */
diff -Npur gcc/testsuite/gcc.dg/strlenopt-40.c gcc/testsuite/gcc.dg/strlenopt-40.c
--- gcc/testsuite/gcc.dg/strlenopt-40.c	2018-08-22 22:34:01.000000000 +0200
+++ gcc/testsuite/gcc.dg/strlenopt-40.c	2018-08-25 18:27:38.573627934 +0200
@@ -105,135 +105,20 @@ void elim_global_arrays (int i)
   /* Verify that the expression involving the strlen call as well
      as whatever depends on it is eliminated  from the test output.
      All these expressions must be trivially true.  */
-  ELIM_TRUE (strlen (a7_3[0]) < sizeof a7_3[0]);
-  ELIM_TRUE (strlen (a7_3[1]) < sizeof a7_3[1]);
-  ELIM_TRUE (strlen (a7_3[6]) < sizeof a7_3[6]);
-  ELIM_TRUE (strlen (a7_3[i]) < sizeof a7_3[i]);
-
-  ELIM_TRUE (strlen (a5_7[0]) < sizeof a5_7[0]);
-  ELIM_TRUE (strlen (a5_7[1]) < sizeof a5_7[1]);
-  ELIM_TRUE (strlen (a5_7[4]) < sizeof a5_7[4]);
-  ELIM_TRUE (strlen (a5_7[i]) < sizeof a5_7[0]);
-
-  ELIM_TRUE (strlen (ax_3[0]) < sizeof ax_3[0]);
-  ELIM_TRUE (strlen (ax_3[1]) < sizeof ax_3[1]);
-  ELIM_TRUE (strlen (ax_3[9]) < sizeof ax_3[9]);
-  ELIM_TRUE (strlen (ax_3[i]) < sizeof ax_3[i]);
-
-  ELIM_TRUE (strlen (a3) < sizeof a3);
-  ELIM_TRUE (strlen (a7) < sizeof a7);
-
   ELIM_TRUE (strlen (ax) != DIFF_MAX);
   ELIM_TRUE (strlen (ax) != DIFF_MAX - 1);
   ELIM_TRUE (strlen (ax) < DIFF_MAX - 1);
 }
 
-void elim_pointer_to_arrays (void)
-{
-  ELIM_TRUE (strlen (*pa7) < 7);
-  ELIM_TRUE (strlen (*pa5) < 5);
-  ELIM_TRUE (strlen (*pa3) < 3);
-
-  ELIM_TRUE (strlen ((*pa7_3)[0]) < 3);
-  ELIM_TRUE (strlen ((*pa7_3)[1]) < 3);
-  ELIM_TRUE (strlen ((*pa7_3)[6]) < 3);
-
-  ELIM_TRUE (strlen ((*pax_3)[0]) < 3);
-  ELIM_TRUE (strlen ((*pax_3)[1]) < 3);
-  ELIM_TRUE (strlen ((*pax_3)[9]) < 3);
-
-  ELIM_TRUE (strlen ((*pa5_7)[0]) < 7);
-  ELIM_TRUE (strlen ((*pa5_7)[1]) < 7);
-  ELIM_TRUE (strlen ((*pa5_7)[4]) < 7);
-}
-
-void elim_global_arrays_and_strings (int i)
-{
-  ELIM_TRUE (strlen (i < 0 ? a3 : "") < 3);
-  ELIM_TRUE (strlen (i < 0 ? a3 : "1") < 3);
-  ELIM_TRUE (strlen (i < 0 ? a3 : "12") < 3);
-  ELIM_TRUE (strlen (i < 0 ? a3 : "123") < 4);
-
-  ELIM_FALSE (strlen (i < 0 ? a3 : "") > 3);
-  ELIM_FALSE (strlen (i < 0 ? a3 : "1") > 3);
-  ELIM_FALSE (strlen (i < 0 ? a3 : "12") > 3);
-  ELIM_FALSE (strlen (i < 0 ? a3 : "123") > 4);
-
-  ELIM_TRUE (strlen (i < 0 ? a7 : "") < 7);
-  ELIM_TRUE (strlen (i < 0 ? a7 : "1") < 7);
-  ELIM_TRUE (strlen (i < 0 ? a7 : "12") < 7);
-  ELIM_TRUE (strlen (i < 0 ? a7 : "123") < 7);
-  ELIM_TRUE (strlen (i < 0 ? a7 : "123456") < 7);
-  ELIM_TRUE (strlen (i < 0 ? a7 : "1234567") < 8);
-
-  ELIM_FALSE (strlen (i < 0 ? a7 : "") > 6);
-  ELIM_FALSE (strlen (i < 0 ? a7 : "1") > 6);
-  ELIM_FALSE (strlen (i < 0 ? a7 : "12") > 6);
-  ELIM_FALSE (strlen (i < 0 ? a7 : "123") > 6);
-  ELIM_FALSE (strlen (i < 0 ? a7 : "123456") > 7);
-  ELIM_FALSE (strlen (i < 0 ? a7 : "1234567") > 8);
-}
-
-void elim_member_arrays_obj (int i)
-{
-  ELIM_TRUE (strlen (ma0_3_5_7[0][0][0].a3) < 3);
-  ELIM_TRUE (strlen (ma0_3_5_7[0][0][1].a3) < 3);
-  ELIM_TRUE (strlen (ma0_3_5_7[0][0][2].a3) < 3);
-  ELIM_TRUE (strlen (ma0_3_5_7[0][0][6].a3) < 3);
-
-  ELIM_TRUE (strlen (ma0_3_5_7[1][0][0].a3) < 3);
-  ELIM_TRUE (strlen (ma0_3_5_7[2][0][1].a3) < 3);
-
-  ELIM_TRUE (strlen (ma0_3_5_7[1][1][0].a3) < 3);
-  ELIM_TRUE (strlen (ma0_3_5_7[2][4][6].a3) < 3);
-
-  ELIM_TRUE (strlen (ma0_3_5_7[0][0][0].a5) < 5);
-  ELIM_TRUE (strlen (ma0_3_5_7[0][0][1].a5) < 5);
-  ELIM_TRUE (strlen (ma0_3_5_7[0][0][2].a5) < 5);
-  ELIM_TRUE (strlen (ma0_3_5_7[0][0][6].a5) < 5);
-
-  ELIM_TRUE (strlen (ma0_3_5_7[1][0][0].a5) < 5);
-  ELIM_TRUE (strlen (ma0_3_5_7[2][0][1].a5) < 5);
-
-  ELIM_TRUE (strlen (ma0_3_5_7[1][1][0].a5) < 5);
-  ELIM_TRUE (strlen (ma0_3_5_7[2][4][6].a5) < 5);
-
-  ELIM_TRUE (strlen (ma0_3_5_7[0][0][0].a7_3[0]) < 3);
-  ELIM_TRUE (strlen (ma0_3_5_7[2][4][6].a7_3[2]) < 3);
-
-  ELIM_TRUE (strlen (ma0_3_5_7[0][0][0].a5_7[0]) < 7);
-  ELIM_TRUE (strlen (ma0_3_5_7[2][4][6].a5_7[4]) < 7);
-}
-
 void elim_member_arrays_ptr (struct MemArrays0 *ma0,
 			     struct MemArraysX *max,
 			     struct MemArrays7 *ma7,
 			     int i)
 {
-  ELIM_TRUE (strlen (ma0->a7_3[0]) < 3);
-  ELIM_TRUE (strlen (ma0->a7_3[1]) < 3);
-  ELIM_TRUE (strlen (ma0->a7_3[6]) < 3);
-  ELIM_TRUE (strlen (ma0->a7_3[6]) < 3);
-  ELIM_TRUE (strlen (ma0->a7_3[i]) < 3);
-  ELIM_TRUE (strlen (ma0->a7_3[i]) < 3);
-
-  ELIM_TRUE (strlen (ma0->a5_7[0]) < 7);
-  ELIM_TRUE (strlen (ma0[0].a5_7[0]) < 7);
-  ELIM_TRUE (strlen (ma0[1].a5_7[0]) < 7);
-  ELIM_TRUE (strlen (ma0[1].a5_7[4]) < 7);
-  ELIM_TRUE (strlen (ma0[9].a5_7[0]) < 7);
-  ELIM_TRUE (strlen (ma0[9].a5_7[4]) < 7);
-
-  ELIM_TRUE (strlen (ma0->a3) < sizeof ma0->a3);
-  ELIM_TRUE (strlen (ma0->a5) < sizeof ma0->a5);
   ELIM_TRUE (strlen (ma0->a0) < DIFF_MAX - 1);
 
-  ELIM_TRUE (strlen (max->a3) < sizeof max->a3);
-  ELIM_TRUE (strlen (max->a5) < sizeof max->a5);
   ELIM_TRUE (strlen (max->ax) < DIFF_MAX - 1);
 
-  ELIM_TRUE (strlen (ma7->a3) < sizeof max->a3);
-  ELIM_TRUE (strlen (ma7->a5) < sizeof max->a5);
   ELIM_TRUE (strlen (ma7->a7) < DIFF_MAX - 1);
 }
 
diff -Npur gcc/testsuite/gcc.dg/strlenopt-45.c gcc/testsuite/gcc.dg/strlenopt-45.c
--- gcc/testsuite/gcc.dg/strlenopt-45.c	2018-08-22 22:34:01.000000000 +0200
+++ gcc/testsuite/gcc.dg/strlenopt-45.c	2018-08-25 18:46:19.901932755 +0200
@@ -58,46 +58,24 @@ void elim_strnlen_arr_cst (void)
      be one).  */
   ELIM (strnlen (&c, 0) == 0);
   ELIM (strnlen (&c, 1) < 2);
-  ELIM (strnlen (&c, 2) == 0);
-  ELIM (strnlen (&c, 9) == 0);
-  ELIM (strnlen (&c, PTRDIFF_MAX) == 0);
-  ELIM (strnlen (&c, SIZE_MAX) == 0);
-  ELIM (strnlen (&c, -1) == 0);
 
   ELIM (strnlen (a1, 0) == 0);
   ELIM (strnlen (a1, 1) < 2);
-  ELIM (strnlen (a1, 2) == 0);
-  ELIM (strnlen (a1, 9) == 0);
-  ELIM (strnlen (a1, PTRDIFF_MAX) == 0);
-  ELIM (strnlen (a1, SIZE_MAX) == 0);
-  ELIM (strnlen (a1, -1) == 0);
 
   ELIM (strnlen (a3, 0) == 0);
   ELIM (strnlen (a3, 1) < 2);
   ELIM (strnlen (a3, 2) < 3);
   ELIM (strnlen (a3, 3) < 4);
-  ELIM (strnlen (a3, 9) < 4);
-  ELIM (strnlen (a3, PTRDIFF_MAX) < 4);
-  ELIM (strnlen (a3, SIZE_MAX) < 4);
-  ELIM (strnlen (a3, -1) < 4);
 
   ELIM (strnlen (a3_7[0], 0) == 0);
   ELIM (strnlen (a3_7[0], 1) < 2);
   ELIM (strnlen (a3_7[0], 2) < 3);
   ELIM (strnlen (a3_7[0], 3) < 4);
-  ELIM (strnlen (a3_7[0], 9) < 8);
-  ELIM (strnlen (a3_7[0], PTRDIFF_MAX) < 8);
-  ELIM (strnlen (a3_7[0], SIZE_MAX) < 8);
-  ELIM (strnlen (a3_7[0], -1) < 8);
 
   ELIM (strnlen (a3_7[2], 0) == 0);
   ELIM (strnlen (a3_7[2], 1) < 2);
   ELIM (strnlen (a3_7[2], 2) < 3);
   ELIM (strnlen (a3_7[2], 3) < 4);
-  ELIM (strnlen (a3_7[2], 9) < 8);
-  ELIM (strnlen (a3_7[2], PTRDIFF_MAX) < 8);
-  ELIM (strnlen (a3_7[2], SIZE_MAX) < 8);
-  ELIM (strnlen (a3_7[2], -1) < 8);
 
   ELIM (strnlen ((char*)a3_7, 0) == 0);
   ELIM (strnlen ((char*)a3_7, 1) < 2);
@@ -106,10 +84,6 @@ void elim_strnlen_arr_cst (void)
   ELIM (strnlen ((char*)a3_7, 9) < 10);
   ELIM (strnlen ((char*)a3_7, 19) < 20);
   ELIM (strnlen ((char*)a3_7, 21) < 22);
-  ELIM (strnlen ((char*)a3_7, 23) < 22);
-  ELIM (strnlen ((char*)a3_7, PTRDIFF_MAX) < 22);
-  ELIM (strnlen ((char*)a3_7, SIZE_MAX) < 22);
-  ELIM (strnlen ((char*)a3_7, -1) < 22);
 
   ELIM (strnlen (ax, 0) == 0);
   ELIM (strnlen (ax, 1) < 2);
@@ -135,56 +109,32 @@ void elim_strnlen_memarr_cst (struct Mem
 {
   ELIM (strnlen (&p->c, 0) == 0);
   ELIM (strnlen (&p->c, 1) < 2);
-  ELIM (strnlen (&p->c, 9) == 0);
-  ELIM (strnlen (&p->c, PTRDIFF_MAX) == 0);
-  ELIM (strnlen (&p->c, SIZE_MAX) == 0);
-  ELIM (strnlen (&p->c, -1) == 0);
 
   /* Other accesses to internal zero-length arrays are undefined.  */
   ELIM (strnlen (p->a0, 0) == 0);
 
   ELIM (strnlen (p->a1, 0) == 0);
   ELIM (strnlen (p->a1, 1) < 2);
-  ELIM (strnlen (p->a1, 9) == 0);
-  ELIM (strnlen (p->a1, PTRDIFF_MAX) == 0);
-  ELIM (strnlen (p->a1, SIZE_MAX) == 0);
-  ELIM (strnlen (p->a1, -1) == 0);
 
   ELIM (strnlen (p->a3, 0) == 0);
   ELIM (strnlen (p->a3, 1) < 2);
   ELIM (strnlen (p->a3, 2) < 3);
   ELIM (strnlen (p->a3, 3) < 4);
-  ELIM (strnlen (p->a3, 9) < 4);
-  ELIM (strnlen (p->a3, PTRDIFF_MAX) < 4);
-  ELIM (strnlen (p->a3, SIZE_MAX) < 4);
-  ELIM (strnlen (p->a3, -1) < 4);
 
   ELIM (strnlen (p[i].a3, 0) == 0);
   ELIM (strnlen (p[i].a3, 1) < 2);
   ELIM (strnlen (p[i].a3, 2) < 3);
   ELIM (strnlen (p[i].a3, 3) < 4);
-  ELIM (strnlen (p[i].a3, 9) < 4);
-  ELIM (strnlen (p[i].a3, PTRDIFF_MAX) < 4);
-  ELIM (strnlen (p[i].a3, SIZE_MAX) < 4);
-  ELIM (strnlen (p[i].a3, -1) < 4);
 
   ELIM (strnlen (p->a3_7[0], 0) == 0);
   ELIM (strnlen (p->a3_7[0], 1) < 2);
   ELIM (strnlen (p->a3_7[0], 2) < 3);
   ELIM (strnlen (p->a3_7[0], 3) < 4);
-  ELIM (strnlen (p->a3_7[0], 9) < 8);
-  ELIM (strnlen (p->a3_7[0], PTRDIFF_MAX) < 8);
-  ELIM (strnlen (p->a3_7[0], SIZE_MAX) < 8);
-  ELIM (strnlen (p->a3_7[0], -1) < 8);
 
   ELIM (strnlen (p->a3_7[2], 0) == 0);
   ELIM (strnlen (p->a3_7[2], 1) < 2);
   ELIM (strnlen (p->a3_7[2], 2) < 3);
   ELIM (strnlen (p->a3_7[2], 3) < 4);
-  ELIM (strnlen (p->a3_7[2], 9) < 8);
-  ELIM (strnlen (p->a3_7[2], PTRDIFF_MAX) < 8);
-  ELIM (strnlen (p->a3_7[2], SIZE_MAX) < 8);
-  ELIM (strnlen (p->a3_7[2], -1) < 8);
 
   ELIM (strnlen (p->a3_7[i], 0) == 0);
   ELIM (strnlen (p->a3_7[i], 1) < 2);
@@ -210,10 +160,6 @@ void elim_strnlen_memarr_cst (struct Mem
   ELIM (strnlen ((char*)p->a3_7, 9) < 10);
   ELIM (strnlen ((char*)p->a3_7, 19) < 20);
   ELIM (strnlen ((char*)p->a3_7, 21) < 22);
-  ELIM (strnlen ((char*)p->a3_7, 23) < 22);
-  ELIM (strnlen ((char*)p->a3_7, PTRDIFF_MAX) < 22);
-  ELIM (strnlen ((char*)p->a3_7, SIZE_MAX) < 22);
-  ELIM (strnlen ((char*)p->a3_7, -1) < 22);
 
   ELIM (strnlen (p->ax, 0) == 0);
   ELIM (strnlen (p->ax, 1) < 2);
diff -Npur gcc/testsuite/gcc.dg/strlenopt-48.c gcc/testsuite/gcc.dg/strlenopt-48.c
--- gcc/testsuite/gcc.dg/strlenopt-48.c	2018-08-22 22:34:01.000000000 +0200
+++ gcc/testsuite/gcc.dg/strlenopt-48.c	2018-08-25 18:50:25.483526060 +0200
@@ -31,5 +31,5 @@ void h (void)
     abort();
 }
 
-/* { dg-final { scan-tree-dump-times "strlen" 0 "optimized" } }
-   { dg-final { scan-tree-dump-times "abort" 0 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "strlen" 0 "optimized" { xfail *-*-* } } }
+   { dg-final { scan-tree-dump-times "abort" 0 "optimized" { xfail *-*-* } } } */
diff -Npur gcc/testsuite/gcc.dg/strlenopt-51.c gcc/testsuite/gcc.dg/strlenopt-51.c
--- gcc/testsuite/gcc.dg/strlenopt-51.c	2018-08-22 22:34:01.000000000 +0200
+++ gcc/testsuite/gcc.dg/strlenopt-51.c	2018-08-25 14:41:59.649419917 +0200
@@ -101,7 +101,7 @@ void test_keep_a9_9 (int i)
 {
 #undef T
 #define T(I)					\
-  KEEP (strlen (&a9_9[i][I][0]) > (1 + I) % 9);	\
+  KEEP (strlen (&a9_9[i][I][0]) > (0 + I) % 9);	\
   KEEP (strlen (&a9_9[i][I][1]) > (1 + I) % 9);	\
   KEEP (strlen (&a9_9[i][I][2]) > (2 + I) % 9);	\
   KEEP (strlen (&a9_9[i][I][3]) > (3 + I) % 9);	\
@@ -115,7 +115,7 @@ void test_keep_a9_9 (int i)
 }
 
 /* { dg-final { scan-tree-dump-times "strlen" 72 "gimple" } }
-   { dg-final { scan-tree-dump-times "strlen" 63 "optimized" } }
+   { dg-final { scan-tree-dump-times "strlen" 72 "optimized" } }
 
-   { dg-final { scan-tree-dump-times "call_made_in_true_branch_on_line_1\[0-9\]\[0-9\]\[0-9\]" 72 "optimized" } }
+   { dg-final { scan-tree-dump-times "call_made_in_true_branch_on_line_1\[0-9\]\[0-9\]\[0-9\]" 81 "optimized" } }
    { dg-final { scan-tree-dump-times "call_made_in_false_branch_on_line_1\[0-9\]\[0-9\]\[0-9\]" 81 "optimized" } } */
diff -Npur gcc/testsuite/gcc.dg/strlenopt-57.c gcc/testsuite/gcc.dg/strlenopt-57.c
--- gcc/testsuite/gcc.dg/strlenopt-57.c	1970-01-01 01:00:00.000000000 +0100
+++ gcc/testsuite/gcc.dg/strlenopt-57.c	2018-08-25 14:41:59.649419917 +0200
@@ -0,0 +1,25 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -fdump-tree-optimized" } */
+
+#define assert(x) do { if (!(x)) __builtin_abort (); } while (0)
+extern int system (const char *);
+static int fun (char *p)
+{
+  char buf[16];
+
+  assert (__builtin_strlen (p) < 4);
+
+  __builtin_sprintf (buf, "echo %s - %s", p, p);
+  return system (buf);
+}
+
+void test (void)
+{
+  char b[2] = "ab";
+  fun (b);
+}
+
+/* { dg-final { scan-tree-dump-times "__builtin_strlen" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "__builtin_abort" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "__builtin_sprintf" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "system" 1 "optimized" } } */
diff -Npur gcc/testsuite/gcc.dg/strlenopt-58.c gcc/testsuite/gcc.dg/strlenopt-58.c
--- gcc/testsuite/gcc.dg/strlenopt-58.c	1970-01-01 01:00:00.000000000 +0100
+++ gcc/testsuite/gcc.dg/strlenopt-58.c	2018-08-25 15:26:13.653767630 +0200
@@ -0,0 +1,25 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -fdump-tree-optimized" } */
+
+#define assert(x) do { if (!(x)) __builtin_abort (); } while (0)
+extern int system (const char *);
+static int fun (char *p)
+{
+  char buf[16];
+
+  assert (__builtin_strlen (p) < 4);
+
+  __builtin_sprintf (buf, "echo %s - %s", p, p);
+  return system (buf);
+}
+
+void test (void)
+{
+  char b[3] = "ab";
+  fun (b);
+}
+
+/* { dg-final { scan-tree-dump-times "__builtin_strlen" 0 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "__builtin_abort" 0 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "__builtin_sprintf" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "system" 1 "optimized" } } */

Reply via email to