PR tree-optimization/83671 - Fix for false positive reported by -Wstringop-overflow does not work with inlining
gcc/testsuite/ChangeLog: PR tree-optimization/83671 * gcc.dg/strlenopt-40.c: New test. * gcc.dg/strlenopt-41.c: New test. gcc/ChangeLog: PR tree-optimization/83671 * builtins.c (c_strlen): Unconditionally return zero for the empty string. Use -Warray-bounds for warnings. * gimple-fold.c (get_range_strlen): Handle non-constant lengths for non-constant array indices with COMPONENT_REF, arrays of arrays, and pointers to arrays. (gimple_fold_builtin_strlen): Determine and set length range for non-constant character arrays. From-SVN: r256457
This commit is contained in:
parent
e7c6abad7f
commit
c42d0aa089
|
@ -1,3 +1,15 @@
|
|||
2018-01-10 Martin Sebor <msebor@redhat.com>
|
||||
|
||||
PR tree-optimization/83671
|
||||
* builtins.c (c_strlen): Unconditionally return zero for the empty
|
||||
string.
|
||||
Use -Warray-bounds for warnings.
|
||||
* gimple-fold.c (get_range_strlen): Handle non-constant lengths
|
||||
for non-constant array indices with COMPONENT_REF, arrays of
|
||||
arrays, and pointers to arrays.
|
||||
(gimple_fold_builtin_strlen): Determine and set length range for
|
||||
non-constant character arrays.
|
||||
|
||||
2018-01-10 Aldy Hernandez <aldyh@redhat.com>
|
||||
|
||||
PR middle-end/81897
|
||||
|
|
|
@ -621,6 +621,9 @@ c_strlen (tree src, int only_value)
|
|||
return NULL_TREE;
|
||||
}
|
||||
|
||||
if (!maxelts)
|
||||
return ssize_int (0);
|
||||
|
||||
/* We don't know the starting offset, but we do know that the string
|
||||
has no internal zero bytes. We can assume that the offset falls
|
||||
within the bounds of the string; otherwise, the programmer deserves
|
||||
|
@ -651,7 +654,8 @@ c_strlen (tree src, int only_value)
|
|||
if (only_value != 2
|
||||
&& !TREE_NO_WARNING (src))
|
||||
{
|
||||
warning_at (loc, 0, "offset %qwi outside bounds of constant string",
|
||||
warning_at (loc, OPT_Warray_bounds,
|
||||
"offset %qwi outside bounds of constant string",
|
||||
eltoff);
|
||||
TREE_NO_WARNING (src) = 1;
|
||||
}
|
||||
|
|
|
@ -1299,7 +1299,7 @@ static bool
|
|||
get_range_strlen (tree arg, tree length[2], bitmap *visited, int type,
|
||||
bool fuzzy, bool *flexp)
|
||||
{
|
||||
tree var, val;
|
||||
tree var, val = NULL_TREE;
|
||||
gimple *def_stmt;
|
||||
|
||||
/* The minimum and maximum length. The MAXLEN pointer stays unchanged
|
||||
|
@ -1311,14 +1311,33 @@ get_range_strlen (tree arg, tree length[2], bitmap *visited, int type,
|
|||
{
|
||||
/* 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
|
||||
&& integer_zerop (TREE_OPERAND (TREE_OPERAND (arg, 0), 1)))
|
||||
&& TREE_CODE (TREE_OPERAND (arg, 0)) == ARRAY_REF)
|
||||
{
|
||||
tree aop0 = TREE_OPERAND (TREE_OPERAND (arg, 0), 0);
|
||||
if (TREE_CODE (aop0) == INDIRECT_REF
|
||||
&& TREE_CODE (TREE_OPERAND (aop0, 0)) == SSA_NAME)
|
||||
return get_range_strlen (TREE_OPERAND (aop0, 0),
|
||||
length, visited, type, fuzzy, flexp);
|
||||
tree op = TREE_OPERAND (arg, 0);
|
||||
if (integer_zerop (TREE_OPERAND (op, 1)))
|
||||
{
|
||||
tree aop0 = TREE_OPERAND (op, 0);
|
||||
if (TREE_CODE (aop0) == INDIRECT_REF
|
||||
&& TREE_CODE (TREE_OPERAND (aop0, 0)) == SSA_NAME)
|
||||
return get_range_strlen (TREE_OPERAND (aop0, 0),
|
||||
length, visited, type, fuzzy, flexp);
|
||||
}
|
||||
else if (TREE_CODE (TREE_OPERAND (op, 0)) == COMPONENT_REF && fuzzy)
|
||||
{
|
||||
/* Fail if an array is the last member of a struct object
|
||||
since it could be treated as a (fake) flexible array
|
||||
member. */
|
||||
tree idx = TREE_OPERAND (op, 1);
|
||||
|
||||
arg = TREE_OPERAND (op, 0);
|
||||
tree optype = TREE_TYPE (arg);
|
||||
if (tree dom = TYPE_DOMAIN (optype))
|
||||
if (tree bound = TYPE_MAX_VALUE (dom))
|
||||
if (TREE_CODE (bound) == INTEGER_CST
|
||||
&& TREE_CODE (idx) == INTEGER_CST
|
||||
&& tree_int_cst_lt (bound, idx))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (type == 2)
|
||||
|
@ -1337,21 +1356,48 @@ get_range_strlen (tree arg, tree length[2], bitmap *visited, int type,
|
|||
return get_range_strlen (TREE_OPERAND (arg, 0), length,
|
||||
visited, type, fuzzy, flexp);
|
||||
|
||||
if (TREE_CODE (arg) == COMPONENT_REF
|
||||
if (TREE_CODE (arg) == ARRAY_REF)
|
||||
{
|
||||
tree type = TREE_TYPE (TREE_OPERAND (arg, 0));
|
||||
|
||||
while (TREE_CODE (type) == ARRAY_TYPE
|
||||
&& TREE_CODE (TREE_TYPE (type)) == ARRAY_TYPE)
|
||||
type = TREE_TYPE (type);
|
||||
|
||||
val = TYPE_SIZE_UNIT (type);
|
||||
if (!val || 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);
|
||||
}
|
||||
else if (TREE_CODE (arg) == COMPONENT_REF
|
||||
&& TREE_CODE (TREE_TYPE (TREE_OPERAND (arg, 1))) == ARRAY_TYPE)
|
||||
{
|
||||
/* 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
|
||||
the caller relies on the subsequent member to contain
|
||||
the NUL.
|
||||
the NUL but that would only be considered valid if
|
||||
the array were the last member of a struct.
|
||||
Set *FLEXP to true if the array whose bound is being
|
||||
used is at the end of a struct. */
|
||||
if (array_at_struct_end_p (arg))
|
||||
*flexp = true;
|
||||
|
||||
arg = TREE_OPERAND (arg, 1);
|
||||
val = TYPE_SIZE_UNIT (TREE_TYPE (arg));
|
||||
|
||||
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))
|
||||
return false;
|
||||
val = fold_build2 (MINUS_EXPR, TREE_TYPE (val), val,
|
||||
|
@ -1361,17 +1407,25 @@ get_range_strlen (tree arg, tree length[2], bitmap *visited, int type,
|
|||
*minlen = ssize_int (0);
|
||||
}
|
||||
|
||||
if (VAR_P (arg)
|
||||
&& TREE_CODE (TREE_TYPE (arg)) == ARRAY_TYPE)
|
||||
if (VAR_P (arg))
|
||||
{
|
||||
val = TYPE_SIZE_UNIT (TREE_TYPE (arg));
|
||||
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));
|
||||
/* Set the minimum size to zero since the string in
|
||||
the array could have zero length. */
|
||||
*minlen = ssize_int (0);
|
||||
tree type = TREE_TYPE (arg);
|
||||
if (POINTER_TYPE_P (type))
|
||||
type = TREE_TYPE (type);
|
||||
|
||||
if (TREE_CODE (type) == ARRAY_TYPE)
|
||||
{
|
||||
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));
|
||||
/* Set the minimum size to zero since the string in
|
||||
the array could have zero length. */
|
||||
*minlen = ssize_int (0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3462,12 +3516,44 @@ static bool
|
|||
gimple_fold_builtin_strlen (gimple_stmt_iterator *gsi)
|
||||
{
|
||||
gimple *stmt = gsi_stmt (*gsi);
|
||||
tree len = get_maxval_strlen (gimple_call_arg (stmt, 0), 0);
|
||||
if (!len)
|
||||
return false;
|
||||
len = force_gimple_operand_gsi (gsi, len, true, NULL, true, GSI_SAME_STMT);
|
||||
replace_call_with_value (gsi, len);
|
||||
return true;
|
||||
|
||||
wide_int minlen;
|
||||
wide_int maxlen;
|
||||
|
||||
tree lenrange[2];
|
||||
if (!get_range_strlen (gimple_call_arg (stmt, 0), lenrange)
|
||||
&& lenrange[0] && TREE_CODE (lenrange[0]) == INTEGER_CST
|
||||
&& lenrange[1] && TREE_CODE (lenrange[1]) == INTEGER_CST)
|
||||
{
|
||||
/* The range of lengths refers to either a single constant
|
||||
string or to the longest and shortest constant string
|
||||
referenced by the argument of the strlen() call, or to
|
||||
the strings that can possibly be stored in the arrays
|
||||
the argument refers to. */
|
||||
minlen = wi::to_wide (lenrange[0]);
|
||||
maxlen = wi::to_wide (lenrange[1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned prec = TYPE_PRECISION (sizetype);
|
||||
|
||||
minlen = wi::shwi (0, prec);
|
||||
maxlen = wi::to_wide (max_object_size (), prec) - 2;
|
||||
}
|
||||
|
||||
if (minlen == maxlen)
|
||||
{
|
||||
lenrange[0] = force_gimple_operand_gsi (gsi, lenrange[0], true, NULL,
|
||||
true, GSI_SAME_STMT);
|
||||
replace_call_with_value (gsi, lenrange[0]);
|
||||
return true;
|
||||
}
|
||||
|
||||
tree lhs = gimple_call_lhs (stmt);
|
||||
if (lhs && TREE_CODE (lhs) == SSA_NAME)
|
||||
set_range_info (lhs, VR_RANGE, minlen, maxlen);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Fold a call to __builtin_acc_on_device. */
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
2018-01-10 Martin Sebor <msebor@redhat.com>
|
||||
|
||||
PR tree-optimization/83671
|
||||
* gcc.dg/strlenopt-40.c: New test.
|
||||
* gcc.dg/strlenopt-41.c: New test.
|
||||
|
||||
2018-01-10 Steven G. Kargl <kargl@gcc.gnu.org>
|
||||
|
||||
PR fortran/83093
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// PR c++/35652
|
||||
// { dg-options "-O" }
|
||||
// { dg-options "-O -Wall" }
|
||||
|
||||
#include <string>
|
||||
int test() {
|
||||
|
|
|
@ -0,0 +1,393 @@
|
|||
/* 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" } */
|
||||
|
||||
#include "strlenopt.h"
|
||||
|
||||
#define DIFF_MAX __PTRDIFF_MAX__
|
||||
|
||||
#define CAT(x, y) x ## y
|
||||
#define CONCAT(x, y) CAT (x, y)
|
||||
#define FAILNAME(name) CONCAT (call_ ## name ##_on_line_, __LINE__)
|
||||
|
||||
#define FAIL(name) do { \
|
||||
extern void FAILNAME (name) (void); \
|
||||
FAILNAME (name)(); \
|
||||
} while (0)
|
||||
|
||||
/* Macros to emit a call to funcation named
|
||||
call_in_{true,false}_branch_not_eliminated_on_line_NNN()
|
||||
for each call that's expected to be eliminated. The dg-final
|
||||
scan-tree-dump-time directive at the bottom of the test verifies
|
||||
that no such call appears in output. */
|
||||
#define ELIM_TRUE(expr) \
|
||||
if (!(expr)) FAIL (in_true_branch_not_eliminated); else (void)0
|
||||
|
||||
#define ELIM_FALSE(expr) \
|
||||
if (!!(expr)) FAIL (in_false_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)
|
||||
|
||||
typedef char A3[3], A5[5], A7[7], AX[];
|
||||
|
||||
typedef A3 A7_3[7];
|
||||
typedef A3 AX_3[];
|
||||
typedef A5 A7_5[7];
|
||||
typedef A7 A5_7[5];
|
||||
|
||||
extern A7_3 a7_3;
|
||||
extern A5_7 a5_7;
|
||||
extern AX_3 ax_3;
|
||||
|
||||
extern A3 a3;
|
||||
extern A7 a5;
|
||||
extern A7 a7;
|
||||
extern AX ax;
|
||||
|
||||
extern A3 *pa3;
|
||||
extern A5 *pa5;
|
||||
extern A7 *pa7;
|
||||
|
||||
extern A7_3 *pa7_3;
|
||||
extern AX_3 *pax_3;
|
||||
extern A5_7 *pa5_7;
|
||||
extern A7_5 *pa7_5;
|
||||
|
||||
extern char *ptr;
|
||||
|
||||
struct MemArrays0 {
|
||||
A7_3 a7_3;
|
||||
A5_7 a5_7;
|
||||
char a3[3], a5[5], a0[0];
|
||||
};
|
||||
struct MemArraysX { char a3[3], a5[5], ax[]; };
|
||||
struct MemArrays7 { char a3[3], a5[5], a7[7]; };
|
||||
|
||||
struct MemArrays0 ma0_3_5_7[3][5][7];
|
||||
|
||||
void elim_strings (int i)
|
||||
{
|
||||
ELIM_TRUE (strlen (i < 0 ? "123" : "321") == 3);
|
||||
ELIM_FALSE (strlen (i < 0 ? "123" : "321") > 3);
|
||||
ELIM_FALSE (strlen (i < 0 ? "123" : "321") < 3);
|
||||
|
||||
ELIM_TRUE (strlen (i < 0 ? "123" : "4321") >= 3);
|
||||
ELIM_FALSE (strlen (i < 0 ? "123" : "4321") > 4);
|
||||
ELIM_FALSE (strlen (i < 0 ? "123" : "4321") < 3);
|
||||
|
||||
ELIM_TRUE (strlen (i < 0 ? "1234" : "321") >= 3);
|
||||
ELIM_FALSE (strlen (i < 0 ? "1234" : "321") < 3);
|
||||
ELIM_FALSE (strlen (i < 0 ? "1234" : "321") > 4);
|
||||
|
||||
ELIM_TRUE (strlen (i < 0 ? "123" : "4321") <= 4);
|
||||
ELIM_TRUE (strlen (i < 0 ? "1234" : "321") <= 4);
|
||||
|
||||
ELIM_TRUE (strlen (i < 0 ? "1" : "123456789") <= 9);
|
||||
ELIM_TRUE (strlen (i < 0 ? "1" : "123456789") >= 1);
|
||||
}
|
||||
|
||||
/* Verify that strlen calls involving uninitialized global arrays
|
||||
of known size are eliminated when they appear in expressions
|
||||
that test for results that must be true. */
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
#line 1000
|
||||
|
||||
/* Verify that strlen calls involving uninitialized global arrays
|
||||
of unknown size are not eliminated when they appear in expressions
|
||||
that test for results that need not be true. */
|
||||
void keep_global_arrays (int i)
|
||||
{
|
||||
KEEP (strlen (a7_3[0]) < 2);
|
||||
KEEP (strlen (a7_3[1]) < 2);
|
||||
KEEP (strlen (a7_3[6]) < 2);
|
||||
KEEP (strlen (a7_3[i]) < 2);
|
||||
|
||||
KEEP (strlen (a5_7[0]) < 6);
|
||||
KEEP (strlen (a5_7[1]) < 6);
|
||||
KEEP (strlen (a5_7[4]) < 6);
|
||||
KEEP (strlen (a5_7[i]) < 6);
|
||||
|
||||
KEEP (strlen (ax_3[0]) < 2);
|
||||
KEEP (strlen (ax_3[1]) < 2);
|
||||
KEEP (strlen (ax_3[2]) < 2);
|
||||
KEEP (strlen (ax_3[i]) < 2);
|
||||
|
||||
KEEP (strlen (a3) < 2);
|
||||
KEEP (strlen (a7) < 6);
|
||||
|
||||
KEEP (strlen (a3 + i) < 2);
|
||||
KEEP (strlen (a7 + i) < 2);
|
||||
|
||||
/* The length of an array of unknown size may be as large as
|
||||
DIFF_MAX - 2. */
|
||||
KEEP (strlen (ax) != DIFF_MAX - 2);
|
||||
KEEP (strlen (ax) < DIFF_MAX - 2);
|
||||
KEEP (strlen (ax) < 999);
|
||||
KEEP (strlen (ax) < 1);
|
||||
}
|
||||
|
||||
void keep_pointer_to_arrays (void)
|
||||
{
|
||||
KEEP (strlen (*pa7) < 6);
|
||||
KEEP (strlen (*pa5) < 4);
|
||||
KEEP (strlen (*pa3) < 2);
|
||||
|
||||
KEEP (strlen ((*pa7_3)[0]) < 2);
|
||||
KEEP (strlen ((*pa7_3)[1]) < 2);
|
||||
KEEP (strlen ((*pa7_3)[6]) < 2);
|
||||
|
||||
KEEP (strlen ((*pax_3)[0]) < 2);
|
||||
KEEP (strlen ((*pax_3)[1]) < 2);
|
||||
KEEP (strlen ((*pax_3)[9]) < 2);
|
||||
|
||||
KEEP (strlen ((*pa5_7)[0]) < 6);
|
||||
KEEP (strlen ((*pa5_7)[1]) < 6);
|
||||
KEEP (strlen ((*pa5_7)[4]) < 6);
|
||||
}
|
||||
|
||||
void keep_global_arrays_and_strings (int i)
|
||||
{
|
||||
KEEP (strlen (i < 0 ? a3 : "") < 2);
|
||||
KEEP (strlen (i < 0 ? a3 : "1") < 2);
|
||||
KEEP (strlen (i < 0 ? a3 : "12") < 2);
|
||||
KEEP (strlen (i < 0 ? a3 : "123") < 3);
|
||||
|
||||
KEEP (strlen (i < 0 ? a7 : "") < 5);
|
||||
KEEP (strlen (i < 0 ? a7 : "1") < 5);
|
||||
KEEP (strlen (i < 0 ? a7 : "12") < 5);
|
||||
KEEP (strlen (i < 0 ? a7 : "123") < 5);
|
||||
KEEP (strlen (i < 0 ? a7 : "123456") < 6);
|
||||
KEEP (strlen (i < 0 ? a7 : "1234567") < 6);
|
||||
}
|
||||
|
||||
void keep_member_arrays_obj (int i)
|
||||
{
|
||||
KEEP (strlen (ma0_3_5_7[0][0][0].a3) < 2);
|
||||
KEEP (strlen (ma0_3_5_7[0][0][1].a3) < 2);
|
||||
KEEP (strlen (ma0_3_5_7[0][0][2].a3) < 2);
|
||||
KEEP (strlen (ma0_3_5_7[0][0][6].a3) < 2);
|
||||
|
||||
KEEP (strlen (ma0_3_5_7[1][0][0].a3) < 2);
|
||||
KEEP (strlen (ma0_3_5_7[2][0][1].a3) < 2);
|
||||
|
||||
KEEP (strlen (ma0_3_5_7[1][1][0].a3) < 2);
|
||||
KEEP (strlen (ma0_3_5_7[2][4][6].a3) < 2);
|
||||
|
||||
KEEP (strlen (ma0_3_5_7[0][0][0].a5) < 4);
|
||||
KEEP (strlen (ma0_3_5_7[0][0][1].a5) < 4);
|
||||
KEEP (strlen (ma0_3_5_7[0][0][2].a5) < 4);
|
||||
KEEP (strlen (ma0_3_5_7[0][0][6].a5) < 4);
|
||||
|
||||
KEEP (strlen (ma0_3_5_7[1][0][0].a5) < 4);
|
||||
KEEP (strlen (ma0_3_5_7[2][0][1].a5) < 4);
|
||||
|
||||
KEEP (strlen (ma0_3_5_7[1][1][0].a5) < 4);
|
||||
KEEP (strlen (ma0_3_5_7[2][4][6].a5) < 4);
|
||||
|
||||
KEEP (strlen (ma0_3_5_7[0][0][0].a7_3[0]) < 2);
|
||||
KEEP (strlen (ma0_3_5_7[2][4][6].a7_3[2]) < 2);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
void keep_member_arrays_ptr (struct MemArrays0 *ma0,
|
||||
struct MemArraysX *max,
|
||||
struct MemArrays7 *ma7,
|
||||
int i)
|
||||
{
|
||||
KEEP (strlen (ma0->a7_3[0]) > 0);
|
||||
KEEP (strlen (ma0->a7_3[0]) < 2);
|
||||
KEEP (strlen (ma0->a7_3[1]) < 2);
|
||||
KEEP (strlen (ma0->a7_3[6]) < 2);
|
||||
KEEP (strlen (ma0->a7_3[6]) < 2);
|
||||
KEEP (strlen (ma0->a7_3[i]) > 0);
|
||||
KEEP (strlen (ma0->a7_3[i]) < 2);
|
||||
KEEP (strlen (ma0->a7_3[i]) < 2);
|
||||
|
||||
KEEP (strlen (ma0->a5_7[0]) < 5);
|
||||
KEEP (strlen (ma0[0].a5_7[0]) < 5);
|
||||
KEEP (strlen (ma0[1].a5_7[0]) < 5);
|
||||
KEEP (strlen (ma0[9].a5_7[0]) < 5);
|
||||
KEEP (strlen (ma0[9].a5_7[4]) < 5);
|
||||
KEEP (strlen (ma0[i].a5_7[4]) < 5);
|
||||
KEEP (strlen (ma0[i].a5_7[i]) < 5);
|
||||
|
||||
KEEP (strlen (ma0->a0) < DIFF_MAX - 2);
|
||||
KEEP (strlen (ma0->a0) < 999);
|
||||
KEEP (strlen (ma0->a0) < 1);
|
||||
|
||||
KEEP (strlen (max->ax) < DIFF_MAX - 2);
|
||||
KEEP (strlen (max->ax) < 999);
|
||||
KEEP (strlen (max->ax) < 1);
|
||||
|
||||
KEEP (strlen (ma7->a7) < DIFF_MAX - 2);
|
||||
KEEP (strlen (ma7->a7) < 999);
|
||||
KEEP (strlen (ma7->a7) < 1);
|
||||
}
|
||||
|
||||
void keep_pointers (const char *s)
|
||||
{
|
||||
KEEP (strlen (ptr) < DIFF_MAX - 2);
|
||||
KEEP (strlen (ptr) < 999);
|
||||
KEEP (strlen (ptr) < 1);
|
||||
|
||||
KEEP (strlen (s) < DIFF_MAX - 2);
|
||||
KEEP (strlen (s) < 999);
|
||||
KEEP (strlen (s) < 1);
|
||||
}
|
||||
|
||||
|
||||
/* { 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" } } */
|
|
@ -0,0 +1,34 @@
|
|||
/* PR tree-optimization/83671 - fix for false positive reported by
|
||||
-Wstringop-overflow does not work with inlining
|
||||
Verify that the length the empty string is folded to zero even at -O1
|
||||
regardless of offset into it.
|
||||
Also verify that the length of a non-empty string isn't folded given
|
||||
a variable offset.
|
||||
{ dg-do compile }
|
||||
{ dg-options "-O1 -fdump-tree-optimized" } */
|
||||
|
||||
#include "strlenopt.h"
|
||||
|
||||
inline unsigned length (const char *s)
|
||||
{
|
||||
return __builtin_strlen (s);
|
||||
}
|
||||
|
||||
void check_length_cst (int i)
|
||||
{
|
||||
unsigned len = length (&""[i]);
|
||||
|
||||
if (len)
|
||||
__builtin_abort ();
|
||||
}
|
||||
|
||||
void check_length_var (int i)
|
||||
{
|
||||
unsigned len = length (&"1"[i]);
|
||||
|
||||
if (len != 1)
|
||||
__builtin_abort ();
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "abort" 1 "optimized" } }
|
||||
{ dg-final { scan-tree-dump-times "strlen" 1 "optimized" } } */
|
Loading…
Reference in New Issue