@@ -1291,6 +1291,12 @@ get_range_strlen_tree (tree arg, bitmap *visited,
/* The length computed by this invocation of the function. */
tree val = NULL_TREE;
+ /* True if VAL is an optimistic (tight) bound determined from
+ the size of the character array in which the string may be
+ stored. In that case, the computed VAL is used to set
+ PDATA->MAXBOUND. */
+ bool tight_bound = false;
+
/* We can end up with &(*iftmp_1)[0] here as well, so handle it. */
if (TREE_CODE (arg) == ADDR_EXPR
&& TREE_CODE (TREE_OPERAND (arg, 0)) == ARRAY_REF)
@@ -1384,6 +1390,7 @@ get_range_strlen_tree (tree arg, bitmap *visited,
&& optype == TREE_TYPE (TREE_OPERAND (arg, 0))
&& array_at_struct_end_p (TREE_OPERAND (arg, 0)))
*flexp = true;
+ tight_bound = true;
}
else if (TREE_CODE (arg) == COMPONENT_REF
&& (TREE_CODE (TREE_TYPE (TREE_OPERAND (arg, 1)))
@@ -1419,17 +1426,24 @@ get_range_strlen_tree (tree arg, bitmap *visited,
/* Set the minimum size to zero since the string in
the array could have zero length. */
pdata->minlen = ssize_int (0);
- }
- if (VAR_P (arg))
- {
- tree type = TREE_TYPE (arg);
- if (POINTER_TYPE_P (type))
- type = TREE_TYPE (type);
-
- if (TREE_CODE (type) == ARRAY_TYPE)
+ /* The array size determined above is an optimistic bound
+ on the length. If the array isn't nul-terminated the
+ length computed by the library function would be greater.
+ Even though using strlen to cross the subobject boundary
+ is undefined, avoid drawing conclusions from the member
+ type about the length here. */
+ tight_bound = true;
+ }
+ else if (VAR_P (arg))
+ {
+ /* Avoid handling pointers to arrays. GCC might misuse
+ a pointer to an array of one bound to point to an array
+ object of a greater bound. */
+ tree argtype = TREE_TYPE (arg);
+ if (TREE_CODE (argtype) == ARRAY_TYPE)
{
- val = TYPE_SIZE_UNIT (type);
+ val = TYPE_SIZE_UNIT (argtype);
if (!val
|| TREE_CODE (val) != INTEGER_CST
|| integer_zerop (val))
@@ -1476,6 +1490,43 @@ get_range_strlen_tree (tree arg, bitmap *visited,
else
pdata->maxbound = val;
+ if (tight_bound)
+ {
+ /* VAL computed above represents an optimistically tight bound
+ on the length of the string based on the referenced object's
+ or subobject's type. Determine the conservative upper bound
+ based on the enclosing object's size if possible. */
+ if (rkind == SRK_LENRANGE || rkind == SRK_LENRANGE_2)
+ {
+ poly_int64 offset;
+ tree base = get_addr_base_and_unit_offset (arg, &offset);
+ if (!base)
+ {
+ /* When the call above fails due to a non-constant offset
+ assume the offset is zero and use the size of the whole
+ enclosing object instead. */
+ base = get_base_address (arg);
+ offset = 0;
+ }
+ /* If the base object is a pointer no upper bound on the length
+ can be determined. Otherwise the maximum length is equal to
+ the size of the enclosing object minus the offset of
+ the referenced subobject minus 1 (for the terminating nul). */
+ tree type = TREE_TYPE (base);
+ if (TREE_CODE (type) == POINTER_TYPE
+ || !VAR_P (base) || !(val = DECL_SIZE_UNIT (base)))
+ val = build_all_ones_cst (size_type_node);
+ else
+ {
+ val = DECL_SIZE_UNIT (base);
+ val = fold_build2 (MINUS_EXPR, TREE_TYPE (val), val,
+ size_int (offset + 1));
+ }
+ }
+ else
+ return false;
+ }
+
if (pdata->maxlen)
{
/* Adjust the more conservative bound if possible/necessary
@@ -105,20 +105,23 @@ 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 (a7_3[0]) < sizeof a7_3);
+ ELIM_TRUE (strlen (a7_3[1]) < sizeof a7_3 - sizeof *a7_3);
+ ELIM_TRUE (strlen (a7_3[6]) < sizeof a7_3 - 5 * sizeof *a7_3);
+ ELIM_TRUE (strlen (a7_3[i]) < sizeof a7_3);
+
+ ELIM_TRUE (strlen (a5_7[0]) < sizeof a5_7);
+ ELIM_TRUE (strlen (a5_7[1]) < sizeof a5_7 - sizeof *a5_7);
+ ELIM_TRUE (strlen (a5_7[4]) < sizeof a5_7 - 3 * sizeof *a5_7);
+ ELIM_TRUE (strlen (a5_7[i]) < sizeof a5_7);
+
+ /* Even when treating a multi-dimensional array as a single string
+ the length must be less DIFF_MAX - (ax_3[i] - ax_3[0]) but GCC
+ doesn't do that computation yet so avoid testing it. */
+ ELIM_TRUE (strlen (ax_3[0]) < DIFF_MAX);
+ ELIM_TRUE (strlen (ax_3[1]) < DIFF_MAX);
+ ELIM_TRUE (strlen (ax_3[9]) < DIFF_MAX);
+ ELIM_TRUE (strlen (ax_3[i]) < DIFF_MAX);
ELIM_TRUE (strlen (a3) < sizeof a3);
ELIM_TRUE (strlen (a7) < sizeof a7);
@@ -130,21 +133,25 @@ void elim_global_arrays (int i)
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);
+ /* Unfortunately, GCC cannot be trusted not to misuse a pointer
+ to a smaller array to point to an object of a bigger type so
+ the strlen range optimization must assume each array pointer
+ points effectively to an array of an unknown bound. */
+ ELIM_TRUE (strlen (*pa7) < DIFF_MAX);
+ ELIM_TRUE (strlen (*pa5) < DIFF_MAX);
+ ELIM_TRUE (strlen (*pa3) < DIFF_MAX);
+
+ ELIM_TRUE (strlen ((*pa7_3)[0]) < DIFF_MAX);
+ ELIM_TRUE (strlen ((*pa7_3)[1]) < DIFF_MAX);
+ ELIM_TRUE (strlen ((*pa7_3)[6]) < DIFF_MAX);
+
+ ELIM_TRUE (strlen ((*pax_3)[0]) < DIFF_MAX);
+ ELIM_TRUE (strlen ((*pax_3)[1]) < DIFF_MAX);
+ ELIM_TRUE (strlen ((*pax_3)[9]) < DIFF_MAX);
+
+ ELIM_TRUE (strlen ((*pa5_7)[0]) < DIFF_MAX);
+ ELIM_TRUE (strlen ((*pa5_7)[1]) < DIFF_MAX);
+ ELIM_TRUE (strlen ((*pa5_7)[4]) < DIFF_MAX);
}
void elim_global_arrays_and_strings (int i)
@@ -176,65 +183,33 @@ void elim_global_arrays_and_strings (int i)
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[0][0][0].a3) < sizeof ma0_3_5_7);
+ ELIM_TRUE (strlen (ma0_3_5_7[0][0][1].a3) < sizeof ma0_3_5_7);
+ ELIM_TRUE (strlen (ma0_3_5_7[0][0][2].a3) < sizeof ma0_3_5_7);
+ ELIM_TRUE (strlen (ma0_3_5_7[0][0][6].a3) < sizeof ma0_3_5_7);
- 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][0][0].a3) < sizeof ma0_3_5_7);
+ ELIM_TRUE (strlen (ma0_3_5_7[2][0][1].a3) < sizeof ma0_3_5_7);
- 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[1][1][0].a3) < sizeof ma0_3_5_7);
+ ELIM_TRUE (strlen (ma0_3_5_7[2][4][6].a3) < sizeof ma0_3_5_7);
- 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[0][0][0].a5) < sizeof ma0_3_5_7);
+ ELIM_TRUE (strlen (ma0_3_5_7[0][0][1].a5) < sizeof ma0_3_5_7);
+ ELIM_TRUE (strlen (ma0_3_5_7[0][0][2].a5) < sizeof ma0_3_5_7);
+ ELIM_TRUE (strlen (ma0_3_5_7[0][0][6].a5) < sizeof ma0_3_5_7);
- 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][0][0].a5) < sizeof ma0_3_5_7);
+ ELIM_TRUE (strlen (ma0_3_5_7[2][0][1].a5) < sizeof ma0_3_5_7);
- 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[1][1][0].a5) < sizeof ma0_3_5_7);
+ ELIM_TRUE (strlen (ma0_3_5_7[2][4][6].a5) < sizeof ma0_3_5_7);
- 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].a7_3[0]) < sizeof ma0_3_5_7);
+ ELIM_TRUE (strlen (ma0_3_5_7[2][4][6].a7_3[2]) < sizeof ma0_3_5_7);
- 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);
+ ELIM_TRUE (strlen (ma0_3_5_7[0][0][0].a5_7[0]) < sizeof ma0_3_5_7);
+ ELIM_TRUE (strlen (ma0_3_5_7[2][4][6].a5_7[4]) < sizeof ma0_3_5_7);
}
@@ -255,11 +230,27 @@ void keep_global_arrays (int i)
KEEP (strlen (a5_7[4]) < 6);
KEEP (strlen (a5_7[i]) < 6);
+ /* Verify also that tests (and strlen calls) are not eliminated
+ for results greater than what would the size of the innermost
+ array suggest might be possible (in case the element array is
+ not nul-terminated), even though such calls are undefined. */
+ KEEP (strlen (a5_7[0]) > sizeof a5_7 - 2);
+ KEEP (strlen (a5_7[1]) > sizeof a5_7 - sizeof a5_7[1] - 2);
+ KEEP (strlen (a5_7[i]) > sizeof a5_7 - 2);
+
KEEP (strlen (ax_3[0]) < 2);
KEEP (strlen (ax_3[1]) < 2);
KEEP (strlen (ax_3[2]) < 2);
KEEP (strlen (ax_3[i]) < 2);
+ /* Here again, verify that the ax_3 matrix is treated essentially
+ as a flat array of unknown bound for the benefit of all the
+ undefined code out there that might rely on it. */
+ KEEP (strlen (ax_3[0]) > 3);
+ KEEP (strlen (ax_3[1]) > 9);
+ KEEP (strlen (ax_3[2]) > 99);
+ KEEP (strlen (ax_3[i]) > 999);
+
KEEP (strlen (a3) < 2);
KEEP (strlen (a7) < 6);
@@ -274,24 +265,48 @@ void keep_global_arrays (int i)
KEEP (strlen (ax) < 1);
}
-void keep_pointer_to_arrays (void)
+void keep_pointer_to_arrays (int i)
{
KEEP (strlen (*pa7) < 6);
KEEP (strlen (*pa5) < 4);
KEEP (strlen (*pa3) < 2);
+ /* Since GCC cannot be trusted not to misuse a pointer to a smaller
+ array to point to an object of a larger type verify that the bound
+ in a pointer to an array of a known bound isn't relied on for
+ the strlen range optimization. If GCC is fixed to avoid these
+ misuses these tests can be removed. */
+ KEEP (strlen (*pa7) > sizeof *pa7);
+ KEEP (strlen (*pa5) > sizeof *pa5);
+ KEEP (strlen (*pa3) > sizeof *pa3);
+
KEEP (strlen ((*pa7_3)[0]) < 2);
KEEP (strlen ((*pa7_3)[1]) < 2);
KEEP (strlen ((*pa7_3)[6]) < 2);
+ KEEP (strlen ((*pa7_3)[i]) < 2);
+
+ /* Same as above. */
+ KEEP (strlen ((*pa7_3)[0]) > sizeof *pa7_3);
+ KEEP (strlen ((*pa7_3)[i]) > sizeof *pa7_3);
KEEP (strlen ((*pax_3)[0]) < 2);
KEEP (strlen ((*pax_3)[1]) < 2);
KEEP (strlen ((*pax_3)[9]) < 2);
+ KEEP (strlen ((*pax_3)[i]) < 2);
+
+ /* Same as above. */
+ KEEP (strlen ((*pax_3)[0]) > 3);
+ KEEP (strlen ((*pax_3)[i]) > 333);
KEEP (strlen ((*pa5_7)[0]) < 6);
KEEP (strlen ((*pa5_7)[1]) < 6);
KEEP (strlen ((*pa5_7)[4]) < 6);
-}
+ KEEP (strlen ((*pa5_7)[i]) < 6);
+
+ /* Same as above. */
+ KEEP (strlen ((*pa5_7)[0]) > sizeof *pa5_7);
+ KEEP (strlen ((*pa5_7)[i]) > sizeof *pa5_7);
+ }
void keep_global_arrays_and_strings (int i)
{
@@ -306,6 +321,12 @@ void keep_global_arrays_and_strings (int i)
KEEP (strlen (i < 0 ? a7 : "123") < 5);
KEEP (strlen (i < 0 ? a7 : "123456") < 6);
KEEP (strlen (i < 0 ? a7 : "1234567") < 6);
+
+ /* Verify that a matrix is treated as a flat array even in a conditional
+ expression (i.e., don't assume that a7_3[0] is nul-terminated, even
+ though calling strlen() on such an array is undefined). */
+ KEEP (strlen (i < 0 ? a7_3[0] : "") > 7);
+ KEEP (strlen (i < 0 ? a7_3[i] : "") > 7);
}
void keep_member_arrays_obj (int i)
@@ -337,6 +358,12 @@ void keep_member_arrays_obj (int i)
KEEP (strlen (ma0_3_5_7[0][0][0].a5_7[0]) < 6);
KEEP (strlen (ma0_3_5_7[2][4][6].a5_7[4]) < 6);
+
+ /* Again, verify that the .a3 array isn't assumed to necessarily
+ be nul-terminated. */
+ KEEP (strlen (ma0_3_5_7[0][0][0].a3) > 2);
+ KEEP (strlen (ma0_3_5_7[0][0][6].a3) > 2);
+ KEEP (strlen (ma0_3_5_7[0][0][i].a3) > 2);
}
void keep_member_arrays_ptr (struct MemArrays0 *ma0,
@@ -353,6 +380,11 @@ void keep_member_arrays_ptr (struct MemArrays0 *ma0,
KEEP (strlen (ma0->a7_3[i]) < 2);
KEEP (strlen (ma0->a7_3[i]) < 2);
+ /* Again, verify that the member array isn't assumed to necessarily
+ be nul-terminated. */
+ KEEP (strlen (ma0->a7_3[0]) > sizeof ma0->a7_3);
+ KEEP (strlen (ma0->a7_3[i]) > sizeof ma0->a7_3);
+
KEEP (strlen (ma0->a5_7[0]) < 5);
KEEP (strlen (ma0[0].a5_7[0]) < 5);
KEEP (strlen (ma0[1].a5_7[0]) < 5);
@@ -361,6 +393,9 @@ void keep_member_arrays_ptr (struct MemArrays0 *ma0,
KEEP (strlen (ma0[i].a5_7[4]) < 5);
KEEP (strlen (ma0[i].a5_7[i]) < 5);
+ /* Same as above. */
+ KEEP (strlen (ma0[i].a5_7[i]) > sizeof ma0[i].a5_7);
+
KEEP (strlen (ma0->a0) < DIFF_MAX - 2);
KEEP (strlen (ma0->a0) < 999);
KEEP (strlen (ma0->a0) < 1);
@@ -389,5 +424,5 @@ void keep_pointers (const char *s)
/* { dg-final { scan-tree-dump-times "call_in_true_branch_not_eliminated_" 0 "optimized" } }
{ dg-final { scan-tree-dump-times "call_in_false_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\]" 92 "optimized" } }
- { dg-final { scan-tree-dump-times "call_made_in_false_branch_on_line_1\[0-9\]\[0-9\]\[0-9\]" 92 "optimized" } } */
+ { dg-final { scan-tree-dump-times "call_made_in_true_branch_on_line_1\[0-9\]\[0-9\]\[0-9\]" 119 "optimized" } }
+ { dg-final { scan-tree-dump-times "call_made_in_false_branch_on_line_1\[0-9\]\[0-9\]\[0-9\]" 119 "optimized" } } */
@@ -1,16 +1,17 @@
/* PR tree-optimization/77357 - strlen of constant strings not folded
{ dg-do compile }
- { dg-options "-O2 -Wall -fdump-tree-gimple -fdump-tree-optimized" } */
+ { dg-options "-O0 -Wall -fdump-tree-gimple" } */
#include "strlenopt.h"
#define CONCAT(x, y) x ## y
#define CAT(x, y) CONCAT (x, y)
-#define FAILNAME(name) CAT (call_ ## name ##_on_line_, __LINE__)
+#define FAILNAME(name, counter) \
+ CAT (CAT (CAT (call_ ## name ##_on_line_, __LINE__), _), counter)
-#define FAIL(name) do { \
- extern void FAILNAME (name) (void); \
- FAILNAME (name)(); \
+#define FAIL(name, counter) do { \
+ extern void FAILNAME (name, counter) (void); \
+ FAILNAME (name, counter)(); \
} while (0)
/* Macro to emit a call to funcation named
@@ -19,19 +20,7 @@
scan-tree-dump-time directive at the bottom of the test verifies
that no such call appears in output. */
#define ELIM(expr) \
- if (!(expr)) FAIL (in_true_branch_not_eliminated); else (void)0
-
-/* Macro to emit a call to a function named
- call_made_in_{true,false}_branch_on_line_NNN()
- for each call that's expected to be retained. The dg-final
- scan-tree-dump-time directive at the bottom of the test verifies
- that the expected number of both kinds of calls appears in output
- (a pair for each line with the invocation of the KEEP() macro. */
-#define KEEP(expr) \
- if (expr) \
- FAIL (made_in_true_branch); \
- else \
- FAIL (made_in_false_branch)
+ if (!(expr)) FAIL (in_true_branch_not_eliminated, __COUNTER__); else (void)0
#define T(s, n) ELIM (strlen (s) == n)
@@ -53,7 +42,7 @@ struct S
const char a9[][9] = { S0, S1, S2, S3, S4, S5, S6, S7, S8 };
-void test_elim_a9 (int i)
+void test_elim_a9 (unsigned i)
{
ELIM (strlen (&a9[0][i]) > 0);
ELIM (strlen (&a9[1][i]) > 1);
@@ -75,10 +64,10 @@ const char a9_9[][9][9] = {
{ S5, S6, S7, S8, S0, S1, S2, S3, S4 },
{ S6, S7, S8, S0, S1, S2, S3, S4, S5 },
{ S7, S8, S0, S1, S2, S3, S4, S5, S6 },
- { S8, S0, S2, S2, S3, S4, S5, S6, S7 }
+ { S8, S0, S1, S2, S3, S4, S5, S6, S7 }
};
-void test_elim_a9_9 (int i)
+void test_elim_a9_9 (unsigned i)
{
#undef T
#define T(I) \
@@ -95,27 +84,4 @@ void test_elim_a9_9 (int i)
T (0); T (1); T (2); T (3); T (4); T (5); T (6); T (7); T (8);
}
-#line 1000
-
-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][1]) > (1 + I) % 9); \
- KEEP (strlen (&a9_9[i][I][2]) > (2 + I) % 9); \
- KEEP (strlen (&a9_9[i][I][3]) > (3 + I) % 9); \
- KEEP (strlen (&a9_9[i][I][4]) > (4 + I) % 9); \
- KEEP (strlen (&a9_9[i][I][5]) > (5 + I) % 9); \
- KEEP (strlen (&a9_9[i][I][6]) > (6 + I) % 9); \
- KEEP (strlen (&a9_9[i][I][7]) > (7 + I) % 9); \
- KEEP (strlen (&a9_9[i][I][8]) > (8 + I) % 9)
-
- T (0); T (1); T (2); T (3); T (4); T (5); T (6); T (7); T (8);
-}
-
-/* { dg-final { scan-tree-dump-times "strlen" 72 "gimple" } }
- { dg-final { scan-tree-dump-times "strlen" 63 "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_false_branch_on_line_1\[0-9\]\[0-9\]\[0-9\]" 81 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "strlen" 0 "gimple" } } */
@@ -40,7 +40,18 @@ void test_arrays (int i, struct Arrays *a)
int n = __builtin_snprintf (0, 0, "%-s", s);
- ASSERT (0 <= n && n < 3);
+ /* Since it's undefined to pass an unterminated array to a %s
+ directive it would be valid to assume that S above is not
+ longer than sizeof (A->A3) but the optimization isn't done
+ because the GIMPLE representation of the %s argument isn't
+ suffficiently reliable not to confuse it for some other
+ array. The argument length is therefore assumed to be in
+ the range [0, PTRDIFF_MAX - 2] and the sprintf result to be
+ as big as INT_MAX and possibly even negative if the function
+ were to fail due to a single directive resulting in more than
+ the 4,095 byte maximum required to be supported.
+ ASSERT (0 <= n && n < 3);
+ */
ASSERT_MAYBE (0 == n);
ASSERT_MAYBE (1 == n);
@@ -52,7 +63,7 @@ void test_arrays (int i, struct Arrays *a)
int n = __builtin_snprintf (0, 0, "%-s", s);
- ASSERT (0 <= n && n < 5);
+ /* ASSERT (0 <= n && n < 5); */
ASSERT_MAYBE (0 == n);
ASSERT_MAYBE (1 == n);
@@ -69,7 +80,7 @@ void test_string_and_array (int i, struct Arrays *a)
int n = __builtin_snprintf (0, 0, "%-s", s);
- ASSERT (0 <= n && n < 3);
+ /* ASSERT (0 <= n && n < 3); */
ASSERT_MAYBE (0 == n);
ASSERT_MAYBE (1 == n);
@@ -81,7 +92,7 @@ void test_string_and_array (int i, struct Arrays *a)
int n = __builtin_snprintf (0, 0, "%-s", s);
- ASSERT (0 <= n && n < 5);
+ /* ASSERT (0 <= n && n < 5); */
ASSERT_MAYBE (0 == n);
ASSERT_MAYBE (1 == n);
@@ -95,7 +106,7 @@ void test_string_and_array (int i, struct Arrays *a)
int n = __builtin_snprintf (0, 0, "%-s", s);
- ASSERT (0 <= n && n < 5);
+ /* ASSERT (0 <= n && n < 5); */
ASSERT_MAYBE (0 == n);
ASSERT_MAYBE (1 == n);