aboutsummaryrefslogtreecommitdiff
path: root/gcc/gimple-fold.c
diff options
context:
space:
mode:
authorMartin Sebor <msebor@redhat.com>2020-02-05 16:55:26 -0700
committerMartin Sebor <msebor@redhat.com>2020-02-05 16:55:26 -0700
commite7868dc6a79daec4f46552fa5c99f88e4eb8de4c (patch)
tree0fad493958df5c30eebb8192fd46c5f287379396 /gcc/gimple-fold.c
parentf6bef09771cf93e695cf719fb43db8c43e31acf5 (diff)
downloadgcc-e7868dc6a79daec4f46552fa5c99f88e4eb8de4c.zip
gcc-e7868dc6a79daec4f46552fa5c99f88e4eb8de4c.tar.gz
gcc-e7868dc6a79daec4f46552fa5c99f88e4eb8de4c.tar.bz2
PR tree-optimization/92765 - wrong code for strcmp of a union member
gcc/ChangeLog: PR tree-optimization/92765 * gimple-fold.c (get_range_strlen_tree): Handle MEM_REF and PARM_DECL. * tree-ssa-strlen.c (compute_string_length): Remove. (determine_min_objsize): Remove. (get_len_or_size): Add an argument. Call get_range_strlen_dynamic. Avoid using type size as the upper bound on string length. (handle_builtin_string_cmp): Add an argument. Adjust. (strlen_check_and_optimize_call): Pass additional argument to handle_builtin_string_cmp. gcc/testsuite/ChangeLog: PR tree-optimization/92765 * g++.dg/tree-ssa/strlenopt-1.C: New test. * g++.dg/tree-ssa/strlenopt-2.C: New test. * gcc.dg/Warray-bounds-58.c: New test. * gcc.dg/Wrestrict-20.c: Avoid a valid -Wformat-overflow. * gcc.dg/Wstring-compare.c: Xfail a test. * gcc.dg/strcmpopt_2.c: Disable tests. * gcc.dg/strcmpopt_4.c: Adjust tests. * gcc.dg/strcmpopt_10.c: New test. * gcc.dg/strcmpopt_11.c: New test. * gcc.dg/strlenopt-69.c: Disable tests. * gcc.dg/strlenopt-92.c: New test. * gcc.dg/strlenopt-93.c: New test. * gcc.dg/strlenopt.h: Declare calloc. * gcc.dg/tree-ssa/pr92056.c: Xfail tests until pr93518 is resolved. * gcc.dg/tree-ssa/builtin-sprintf-warn-23.c: Correct test (pr93517).
Diffstat (limited to 'gcc/gimple-fold.c')
-rw-r--r--gcc/gimple-fold.c45
1 files changed, 42 insertions, 3 deletions
diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c
index ed22592..fa7a396 100644
--- a/gcc/gimple-fold.c
+++ b/gcc/gimple-fold.c
@@ -65,6 +65,7 @@ along with GCC; see the file COPYING3. If not see
#include "calls.h"
#include "tree-vector-builder.h"
#include "tree-ssa-strlen.h"
+#include "varasm.h"
enum strlen_range_kind {
/* Compute the exact constant string length. */
@@ -1280,7 +1281,7 @@ get_range_strlen_tree (tree arg, bitmap *visited, strlen_range_kind rkind,
c_strlen_data *pdata, unsigned eltsize)
{
gcc_assert (TREE_CODE (arg) != SSA_NAME);
-
+
/* The length computed by this invocation of the function. */
tree val = NULL_TREE;
@@ -1422,7 +1423,44 @@ get_range_strlen_tree (tree arg, bitmap *visited, strlen_range_kind rkind,
type about the length here. */
tight_bound = true;
}
- else if (VAR_P (arg))
+ else if (TREE_CODE (arg) == MEM_REF
+ && TREE_CODE (TREE_TYPE (arg)) == ARRAY_TYPE
+ && TREE_CODE (TREE_TYPE (TREE_TYPE (arg))) == INTEGER_TYPE
+ && TREE_CODE (TREE_OPERAND (arg, 0)) == ADDR_EXPR)
+ {
+ /* Handle a MEM_REF into a DECL accessing an array of integers,
+ being conservative about references to extern structures with
+ flexible array members that can be initialized to arbitrary
+ numbers of elements as an extension (static structs are okay).
+ FIXME: Make this less conservative -- see
+ component_ref_size in tree.c. */
+ tree ref = TREE_OPERAND (TREE_OPERAND (arg, 0), 0);
+ if ((TREE_CODE (ref) == PARM_DECL || VAR_P (ref))
+ && (decl_binds_to_current_def_p (ref)
+ || !array_at_struct_end_p (arg)))
+ {
+ /* Fail if the offset is out of bounds. Such accesses
+ should be diagnosed at some point. */
+ val = DECL_SIZE_UNIT (ref);
+ if (!val || integer_zerop (val))
+ return false;
+
+ poly_offset_int psiz = wi::to_offset (val);
+ poly_offset_int poff = mem_ref_offset (arg);
+ if (known_le (psiz, poff))
+ return false;
+
+ pdata->minlen = ssize_int (0);
+
+ /* Subtract the offset and one for the terminating nul. */
+ psiz -= poff;
+ psiz -= 1;
+ val = wide_int_to_tree (TREE_TYPE (val), psiz);
+ /* Since VAL reflects the size of a declared object
+ rather the type of the access it is not a tight bound. */
+ }
+ }
+ else if (TREE_CODE (arg) == PARM_DECL || VAR_P (arg))
{
/* Avoid handling pointers to arrays. GCC might misuse
a pointer to an array of one bound to point to an array
@@ -1500,7 +1538,8 @@ get_range_strlen_tree (tree arg, bitmap *visited, strlen_range_kind rkind,
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)))
+ || (TREE_CODE (base) != PARM_DECL && !VAR_P (base))
+ || !(val = DECL_SIZE_UNIT (base)))
val = build_all_ones_cst (size_type_node);
else
{