Hi,

I rebased my range computation patch to current trunk,
and updated it according to what was discussed here.

That means get_range_strlen has already a parameter
that is used to differentiate between ranges for warnings
and ranges for code-gen.

That is called "strict", in the 4-parameter overload
and "fuzzy" in the internally used 7-parameter overload.

So I added an "optimistic" parameter to my
get_inner_char_array_unless_typecast helper function.
That's it.

Therefore at this time, there is only one warning regression
in one test case and one xfailed warning test case fixed.

So that is par on the warning regression side.

The failed test case is gcc/testsuite/gcc.dg/pr83373.c which
uses -fassume-zero-terminated-char-arrays, to enable the
(unsafe) feedback from string-length information to VRP to
suppress the warning.

The 5 test cases that were designed to check the optimized
tree dump have to use the new -fassume-zero-terminated-char-arrays
option, but that is what we agreed upon.

The patch is not dependent on any other patches.


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


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

        * common.opt: Add new optimization option
        -fassume-zero-terminated-char-arrays.
        * opts.c (default_options): Enable -fassume-zero-terminated-char-arrays
        with -Ofast.
        * gimple-fold.c (get_inner_char_array_unless_typecast): Helper
        function for strlen range estimations.
        (get_range_strlen): Use get_inner_char_array_unless_typecast.
        * gimple-fold.h (get_inner_char_array_unless_typecast): Declare.
        * tree-ssa-strlen.c (maybe_set_strlen_range): Likewise.
        (adjust_last_stmt): Avoid folding away undefined behaviour.
        (get_min_string_length): Avoid not NUL terminated string literals.
        * doc/invoke.texi: Document -fassume-zero-terminated-char-arrays.
        * tree-ssa-dse.c (compute_trims): Avoid folding away undefined
        behaviour.

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

        * gcc.dg/pr83373.c: Add  -fassume-zero-terminated-char-arrays.
        * gcc.dg/Wstringop-overflow-6.c: Remove xfail.
        * gcc.dg/strlenopt-36.c: Adjust test expectations.
        * gcc.dg/strlenopt-40.c: Likewise.
        * gcc.dg/strlenopt-45.c: Likewise.
        * gcc.dg/strlenopt-48.c: Likewise.
        * gcc.dg/strlenopt-51.c: Likewise.
        * gcc.dg/strlenopt-57.c: New test.
        * gcc.dg/strlenopt-58.c: New test.
        * gcc.dg/strlenopt-59.c: New test.

diff -Npur gcc/common.opt gcc/common.opt
--- gcc/common.opt	2018-08-18 06:59:47.000000000 +0200
+++ gcc/common.opt	2018-08-18 23:31:11.241191079 +0200
@@ -1025,6 +1025,10 @@ fsanitize-undefined-trap-on-error
 Common Driver Report Var(flag_sanitize_undefined_trap_on_error) Init(0)
 Use trap instead of a library function for undefined behavior sanitization.
 
+fassume-zero-terminated-char-arrays
+Common Var(flag_assume_zero_terminated_char_arrays) Optimization Init(0)
+Optimize under the assumption that char arrays must always be zero terminated.
+
 fasynchronous-unwind-tables
 Common Report Var(flag_asynchronous_unwind_tables) Optimization
 Generate unwind tables that are exact at each instruction boundary.
diff -Npur gcc/doc/invoke.texi gcc/doc/invoke.texi
--- gcc/doc/invoke.texi	2018-08-18 06:59:32.000000000 +0200
+++ gcc/doc/invoke.texi	2018-08-18 23:31:11.248190982 +0200
@@ -388,7 +388,8 @@ Objective-C and Objective-C++ Dialects}.
 -falign-jumps[=@var{n}[:@var{m}:[@var{n2}[:@var{m2}]]]] @gol
 -falign-labels[=@var{n}[:@var{m}:[@var{n2}[:@var{m2}]]]] @gol
 -falign-loops[=@var{n}[:@var{m}:[@var{n2}[:@var{m2}]]]] @gol
--fassociative-math  -fauto-profile  -fauto-profile[=@var{path}] @gol
+-fassociative-math  -fassume-zero-terminated-char-arrays @gol
+-fauto-profile  -fauto-profile[=@var{path}] @gol
 -fauto-inc-dec  -fbranch-probabilities @gol
 -fbranch-target-load-optimize  -fbranch-target-load-optimize2 @gol
 -fbtr-bb-exclusive  -fcaller-saves @gol
@@ -9977,6 +9978,17 @@ is automatically enabled when both @opti
 
 The default is @option{-fno-associative-math}.
 
+@item -fassume-zero-terminated-char-arrays
+@opindex fassume-zero-terminated-char-arrays
+
+Optimize under the assumption that char arrays must always be zero
+terminated.  This may have an effect on code that uses strlen to
+check the string length, for instance in assertions.  Under certain
+conditions such checks can be optimized away.  This option is enabled
+by default at optimization level @option{-Ofast}.
+
+The default is @option{-fno-assume-zero-terminated-char-arrays}.
+
 @item -freciprocal-math
 @opindex freciprocal-math
 
diff -Npur gcc/gimple-fold.c gcc/gimple-fold.c
--- gcc/gimple-fold.c	2018-08-17 05:00:53.000000000 +0200
+++ gcc/gimple-fold.c	2018-08-19 08:06:47.597624090 +0200
@@ -1257,6 +1257,45 @@ gimple_fold_builtin_memset (gimple_stmt_
   return true;
 }
 
+/* Obtain the inner char array for strlen range estimations.
+   Return NULL if ARG is not a char array, or if the inner reference
+   chain goes through a type cast.
+   OPTIMISTIC is true when the result is used for warnings only.  */
+
+tree
+get_inner_char_array_unless_typecast (tree arg, bool optimistic)
+{
+  if (!flag_assume_zero_terminated_char_arrays && !optimistic)
+    return NULL_TREE;
+
+  /* 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 NULL_TREE;
+
+  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))))
+      || TREE_CODE (base) == VIEW_CONVERT_EXPR
+      /* Or other stuff that would be handled by get_inner_reference.  */
+      || TREE_CODE (base) == BIT_FIELD_REF
+      || TREE_CODE (base) == REALPART_EXPR
+      || TREE_CODE (base) == IMAGPART_EXPR)
+    return NULL_TREE;
+
+  return arg;
+}
 
 /* Obtain the minimum and maximum string length or minimum and maximum
    value of ARG in LENGTH[0] and LENGTH[1], respectively.
@@ -1272,6 +1311,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 +1352,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 +1379,22 @@ get_range_strlen (tree arg, tree length[
 	    return get_range_strlen (TREE_OPERAND (arg, 0), length,
 				     visited, type, fuzzy, flexp, eltsize);
 
+	  if (eltsize != 1)
+	    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))
+	      arg = get_inner_char_array_unless_typecast (arg, fuzzy == 2);
+	      if (!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 +1403,17 @@ 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)
 	    {
+	      arg = get_inner_char_array_unless_typecast (arg, fuzzy == 2);
+	      if (!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 +1429,21 @@ 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)
+		   && (flag_assume_zero_terminated_char_arrays || fuzzy == 2))
 	    {
 	      tree type = TREE_TYPE (arg);
 	      if (POINTER_TYPE_P (type))
@@ -1411,13 +1451,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 +1600,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/gimple-fold.h gcc/gimple-fold.h
--- gcc/gimple-fold.h	2018-08-17 05:00:53.000000000 +0200
+++ gcc/gimple-fold.h	2018-08-18 23:32:00.962501815 +0200
@@ -61,6 +61,7 @@ extern bool gimple_fold_builtin_snprintf
 extern bool arith_code_with_undefined_signed_overflow (tree_code);
 extern gimple_seq rewrite_to_defined_overflow (gimple *);
 extern void replace_call_with_value (gimple_stmt_iterator *, tree);
+extern tree get_inner_char_array_unless_typecast (tree, bool);
 
 /* gimple_build, functionally matching fold_buildN, outputs stmts
    int the provided sequence, matching and simplifying them on-the-fly.
diff -Npur gcc/opts.c gcc/opts.c
--- gcc/opts.c	2018-08-17 05:02:32.000000000 +0200
+++ gcc/opts.c	2018-08-18 23:31:11.245191023 +0200
@@ -547,6 +547,7 @@ static const struct default_options defa
 
     /* -Ofast adds optimizations to -O3.  */
     { OPT_LEVELS_FAST, OPT_ffast_math, NULL, 1 },
+    { OPT_LEVELS_FAST, OPT_fassume_zero_terminated_char_arrays, NULL, 1 },
 
     { OPT_LEVELS_NONE, 0, NULL, 0 }
   };
diff -Npur gcc/tree-ssa-dse.c gcc/tree-ssa-dse.c
--- gcc/tree-ssa-dse.c	2018-07-18 21:21:34.000000000 +0200
+++ gcc/tree-ssa-dse.c	2018-08-19 14:29:32.344498771 +0200
@@ -248,6 +248,12 @@ compute_trims (ao_ref *ref, sbitmap live
 	 residual handling in mem* and str* functions is usually
 	 reasonably efficient.  */
       *trim_tail = last_orig - last_live;
+      /* Don't fold away an out of bounds access, as this defeats proper
+	 warnings.  */
+      if (*trim_tail
+	  && compare_tree_int (TYPE_SIZE_UNIT (TREE_TYPE (ref->base)),
+			       last_orig) <= 0)
+	*trim_tail = 0;
     }
   else
     *trim_tail = 0;
diff -Npur gcc/tree-ssa-strlen.c gcc/tree-ssa-strlen.c
--- gcc/tree-ssa-strlen.c	2018-08-10 15:15:29.000000000 +0200
+++ gcc/tree-ssa-strlen.c	2018-08-19 10:56:24.331470762 +0200
@@ -1107,6 +1107,13 @@ adjust_last_stmt (strinfo *si, gimple *s
 	 to store the extra '\0' in that case.  */
       if ((tree_to_uhwi (len) & 3) == 0)
 	return;
+
+      /* Don't fold away an out of bounds access, as this defeats proper
+	 warnings.  */
+      tree dst = gimple_call_arg (last.stmt, 0);
+      tree size = compute_objsize (dst, 0);
+      if (size && tree_int_cst_lt (size, len))
+	return;
     }
   else if (TREE_CODE (len) == SSA_NAME)
     {
@@ -1149,11 +1156,15 @@ maybe_set_strlen_range (tree lhs, tree s
 
   if (TREE_CODE (src) == ADDR_EXPR)
     {
+      src = TREE_OPERAND (src, 0);
+
+      src = get_inner_char_array_unless_typecast (src, false);
+
+      if (!src)
+	;
       /* 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))
+      else if (!array_at_struct_end_p (src))
 	{
 	  tree type = TREE_TYPE (src);
 	  if (tree size = TYPE_SIZE_UNIT (type))
@@ -1170,8 +1181,6 @@ maybe_set_strlen_range (tree lhs, tree s
 	}
       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
@@ -3185,7 +3194,9 @@ 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
+      && compare_tree_int (TYPE_SIZE_UNIT (TREE_TYPE (rhs)),
+			   TREE_STRING_LENGTH (rhs)) >= 0)
     {
       *full_string_p = true;
       return strlen (TREE_STRING_POINTER (rhs));
diff -Npur gcc/testsuite/gcc.dg/pr83373.c gcc/testsuite/gcc.dg/pr83373.c
--- gcc/testsuite/gcc.dg/pr83373.c	2018-08-08 20:46:22.000000000 +0200
+++ gcc/testsuite/gcc.dg/pr83373.c	2018-08-19 09:28:37.938079391 +0200
@@ -1,6 +1,6 @@
 /* PR middle-end/83373 - False positive reported by -Wstringop-overflow
    { dg-do compile }
-   { dg-options "-O2 -Wstringop-overflow" }  */
+   { dg-options "-O2 -Wstringop-overflow -fassume-zero-terminated-char-arrays" }  */
 
 typedef __SIZE_TYPE__ size_t;
 
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-08 20:46:22.000000000 +0200
+++ gcc/testsuite/gcc.dg/strlenopt-36.c	2018-08-19 09:21:09.425298094 +0200
@@ -1,7 +1,7 @@
 /* PR tree-optimization/78450 - strlen(s) return value can be assumed
    to be less than the size of s
    { dg-do compile }
-   { dg-options "-O2 -fdump-tree-optimized" } */
+   { dg-options "-O2 -fassume-zero-terminated-char-arrays -fdump-tree-optimized" } */
 
 #include "strlenopt.h"
 
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-08 20:46:22.000000000 +0200
+++ gcc/testsuite/gcc.dg/strlenopt-40.c	2018-08-18 23:31:11.249190968 +0200
@@ -1,7 +1,7 @@
 /* PR tree-optimization/83671 - fix for false positive reported by
    -Wstringop-overflow does not work with inlining
    { dg-do compile }
-   { dg-options "-O1 -fdump-tree-optimized" } */
+   { dg-options "-O1 -fassume-zero-terminated-char-arrays -fdump-tree-optimized" } */
 
 #include "strlenopt.h"
 
@@ -219,10 +219,15 @@ void elim_member_arrays_ptr (struct MemA
 
   ELIM_TRUE (strlen (ma0->a5_7[0]) < 7);
   ELIM_TRUE (strlen (ma0[0].a5_7[0]) < 7);
+#if 0
+  /* This is transformed into strlen ((const char *) &(ma0 + 64)->a5_7[0])
+     which looks like a type cast and fails the check in
+     get_inner_char_array_unless_typecast.  */
   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);
+#endif
 
   ELIM_TRUE (strlen (ma0->a3) < sizeof ma0->a3);
   ELIM_TRUE (strlen (ma0->a5) < sizeof ma0->a5);
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-08 20:46:22.000000000 +0200
+++ gcc/testsuite/gcc.dg/strlenopt-45.c	2018-08-18 23:31:11.249190968 +0200
@@ -2,7 +2,7 @@
    Test to verify that strnlen built-in expansion works correctly
    in the absence of tree strlen optimization.
    { dg-do compile }
-   { dg-options "-O2 -Wall -fdump-tree-optimized" } */
+   { dg-options "-O2 -Wall -fassume-zero-terminated-char-arrays -fdump-tree-optimized" } */
 
 #include "strlenopt.h"
 
@@ -43,7 +43,6 @@ extern size_t strnlen (const char *, siz
   else						\
     FAIL (made_in_false_branch)
 
-extern char c;
 extern char a1[1];
 extern char a3[3];
 extern char a5[5];
@@ -52,18 +51,6 @@ extern char ax[];
 
 void elim_strnlen_arr_cst (void)
 {
-  /* The length of a string stored in a one-element array must be zero.
-     The result reported by strnlen() for such an array can be non-zero
-     only when the bound is equal to 1 (in which case the result must
-     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);
@@ -99,17 +86,18 @@ void elim_strnlen_arr_cst (void)
   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);
-  ELIM (strnlen ((char*)a3_7, 2) < 3);
-  ELIM (strnlen ((char*)a3_7, 3) < 4);
-  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 ((char*)a3_7[0], 0) == 0);
+  ELIM (strnlen ((char*)a3_7[0], 1) < 2);
+  ELIM (strnlen ((char*)a3_7[0], 2) < 3);
+  ELIM (strnlen ((char*)a3_7[0], 3) < 4);
+  ELIM (strnlen ((char*)a3_7[0], 7) < 8);
+  ELIM (strnlen ((char*)a3_7[0], 9) < 7);
+  ELIM (strnlen ((char*)a3_7[0], 19) < 7);
+  ELIM (strnlen ((char*)a3_7[0], 21) < 7);
+  ELIM (strnlen ((char*)a3_7[0], 23) < 7);
+  ELIM (strnlen ((char*)a3_7[0], PTRDIFF_MAX) < 7);
+  ELIM (strnlen ((char*)a3_7[0], SIZE_MAX) < 7);
+  ELIM (strnlen ((char*)a3_7[0], -1) < 7);
 
   ELIM (strnlen (ax, 0) == 0);
   ELIM (strnlen (ax, 1) < 2);
@@ -122,7 +110,6 @@ void elim_strnlen_arr_cst (void)
 
 struct MemArrays
 {
-  char c;
   char a0[0];
   char a1[1];
   char a3[3];
@@ -133,13 +120,6 @@ struct MemArrays
 
 void elim_strnlen_memarr_cst (struct MemArrays *p, int i)
 {
-  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);
 
@@ -154,19 +134,19 @@ void elim_strnlen_memarr_cst (struct Mem
   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->a3, 9) < 3);
+  ELIM (strnlen (p->a3, PTRDIFF_MAX) < 3);
+  ELIM (strnlen (p->a3, SIZE_MAX) < 3);
+  ELIM (strnlen (p->a3, -1) < 3);
 
   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[i].a3, 9) < 3);
+  ELIM (strnlen (p[i].a3, PTRDIFF_MAX) < 3);
+  ELIM (strnlen (p[i].a3, SIZE_MAX) < 3);
+  ELIM (strnlen (p[i].a3, -1) < 3);
 
   ELIM (strnlen (p->a3_7[0], 0) == 0);
   ELIM (strnlen (p->a3_7[0], 1) < 2);
@@ -203,17 +183,18 @@ void elim_strnlen_memarr_cst (struct Mem
   ELIM (strnlen (p->a3_7[i], 19) < 20);
 #endif
 
-  ELIM (strnlen ((char*)p->a3_7, 0) == 0);
-  ELIM (strnlen ((char*)p->a3_7, 1) < 2);
-  ELIM (strnlen ((char*)p->a3_7, 2) < 3);
-  ELIM (strnlen ((char*)p->a3_7, 3) < 4);
-  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 ((char*)p->a3_7[0], 0) == 0);
+  ELIM (strnlen ((char*)p->a3_7[0], 1) < 2);
+  ELIM (strnlen ((char*)p->a3_7[0], 2) < 3);
+  ELIM (strnlen ((char*)p->a3_7[0], 3) < 4);
+  ELIM (strnlen ((char*)p->a3_7[0], 7) < 8);
+  ELIM (strnlen ((char*)p->a3_7[0], 9) < 7);
+  ELIM (strnlen ((char*)p->a3_7[0], 19) < 7);
+  ELIM (strnlen ((char*)p->a3_7[0], 21) < 7);
+  ELIM (strnlen ((char*)p->a3_7[0], 23) < 7);
+  ELIM (strnlen ((char*)p->a3_7[0], PTRDIFF_MAX) < 7);
+  ELIM (strnlen ((char*)p->a3_7[0], SIZE_MAX) < 7);
+  ELIM (strnlen ((char*)p->a3_7[0], -1) < 7);
 
   ELIM (strnlen (p->ax, 0) == 0);
   ELIM (strnlen (p->ax, 1) < 2);
@@ -290,9 +271,6 @@ void elim_strnlen_range (char *s)
 
 void keep_strnlen_arr_cst (void)
 {
-  KEEP (strnlen (&c, 1) == 0);
-  KEEP (strnlen (&c, 1) == 1);
-
   KEEP (strnlen (a1, 1) == 0);
   KEEP (strnlen (a1, 1) == 1);
 
@@ -301,16 +279,12 @@ void keep_strnlen_arr_cst (void)
 
 struct FlexArrays
 {
-  char c;
   char a0[0];   /* Access to internal zero-length arrays are undefined.  */
   char a1[1];
 };
 
 void keep_strnlen_memarr_cst (struct FlexArrays *p)
 {
-  KEEP (strnlen (&p->c, 1) == 0);
-  KEEP (strnlen (&p->c, 1) == 1);
-
 #if 0
   /* Accesses to internal zero-length arrays are undefined so avoid
      exercising them.  */
@@ -331,5 +305,5 @@ void keep_strnlen_memarr_cst (struct Fle
 
 /* { dg-final { scan-tree-dump-times "call_in_true_branch_not_eliminated_" 0 "optimized" } }
 
-   { dg-final { scan-tree-dump-times "call_made_in_true_branch_on_line_1\[0-9\]\[0-9\]\[0-9\]" 13 "optimized" } }
-   { dg-final { scan-tree-dump-times "call_made_in_false_branch_on_line_1\[0-9\]\[0-9\]\[0-9\]" 13 "optimized" } } */
+   { dg-final { scan-tree-dump-times "call_made_in_true_branch_on_line_1\[0-9\]\[0-9\]\[0-9\]" 9 "optimized" } }
+   { dg-final { scan-tree-dump-times "call_made_in_false_branch_on_line_1\[0-9\]\[0-9\]\[0-9\]" 9 "optimized" } } */
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-08 20:46:22.000000000 +0200
+++ gcc/testsuite/gcc.dg/strlenopt-48.c	2018-08-19 09:22:35.473103694 +0200
@@ -3,7 +3,7 @@
    Verify that strlen() calls with one-character array elements of
    multidimensional arrays are still folded.
    { dg-do compile }
-   { dg-options "-O2 -Wall -fdump-tree-optimized" } */
+   { dg-options "-O2 -Wall -fassume-zero-terminated-char-arrays -fdump-tree-optimized" } */
 
 #include "strlenopt.h"
 
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-08 20:46:22.000000000 +0200
+++ gcc/testsuite/gcc.dg/strlenopt-51.c	2018-08-18 23:31:11.249190968 +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-18 23:31:11.250190954 +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-19 08:00:34.462811696 +0200
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-options "-Ofast -fdump-tree-optimized" } */
+
+typedef char A[6];
+typedef char B[2][3];
+
+A a;
+
+void test (void)
+{
+  B* b = (B*) a;
+  if (__builtin_strlen ((*b)[0]) > 2)
+    __builtin_abort ();
+}
+
+/* { dg-final { scan-tree-dump-times "__builtin_strlen" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "__builtin_abort" 1 "optimized" } } */
diff -Npur gcc/testsuite/gcc.dg/strlenopt-59.c gcc/testsuite/gcc.dg/strlenopt-59.c
--- gcc/testsuite/gcc.dg/strlenopt-59.c	1970-01-01 01:00:00.000000000 +0100
+++ gcc/testsuite/gcc.dg/strlenopt-59.c	2018-08-19 08:00:47.832625824 +0200
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-options "-Ofast -fdump-tree-optimized" } */
+
+typedef char B[2][3];
+
+B b;
+
+void test (void)
+{
+  if (__builtin_strlen (b[0]) > 2)
+    __builtin_abort ();
+}
+
+/* { dg-final { scan-tree-dump-not "__builtin_strlen" "optimized" } } */
+/* { dg-final { scan-tree-dump-not "__builtin_abort" "optimized" } } */
diff -Npur gcc/testsuite/gcc.dg/Wstringop-overflow-6.c gcc/testsuite/gcc.dg/Wstringop-overflow-6.c
--- gcc/testsuite/gcc.dg/Wstringop-overflow-6.c	2018-06-15 21:13:15.000000000 +0200
+++ gcc/testsuite/gcc.dg/Wstringop-overflow-6.c	2018-08-19 14:07:49.267391775 +0200
@@ -25,7 +25,7 @@ void test_strcpy_strcat_1 (void)
 
 void test_strcpy_strcat_2 (void)
 {
-  strcpy (a2, "12"), strcat (a2, "3");   /* { dg-warning "\\\[-Wstringop-overflow=]" "bug 86121" { xfail *-*-* } } */
+  strcpy (a2, "12"), strcat (a2, "3");   /* { dg-warning "\\\[-Wstringop-overflow=]" } */
 }
 
 void test_strcpy_strcat_3 (void)

Reply via email to