[PATCH] Fix PR35593, over-eager ARRAY_REF re-construction
Richard Guenther
rguenther@suse.de
Sat Mar 15 14:32:00 GMT 2008
For
struct A {
long x;
char d[0];
} *a;
(char *)a - 4
we shouldn't fold this to a->d[-8]. This may affect correctness
both as it will emit bogus warnings about out-of-bounds array accesses.
Bootstrapped and tested on x86_64-unknown-linux-gnu, applied to trunk
(and 4.3 somewhat later).
Richard.
2008-03-14 Richard Guenther <rguenther@suse.de>
PR middle-end/35593
* tree-ssa-ccp.c (maybe_fold_offset_to_array_ref): Make sure
to not produce negative array indices if not allowed. Add
parameter to indicate that.
(maybe_fold_offset_to_component_ref): Allow negative array
indices only for the first member of a structure.
(maybe_fold_offset_to_reference): Allow negative array indices.
(maybe_fold_stmt_addition): Likewise.
* g++.dg/warn/Warray-bounds-3.C: New testcase.
Index: testsuite/g++.dg/warn/Warray-bounds-3.C
===================================================================
*** testsuite/g++.dg/warn/Warray-bounds-3.C (revision 0)
--- testsuite/g++.dg/warn/Warray-bounds-3.C (revision 0)
***************
*** 0 ****
--- 1,15 ----
+ /* { dg-do compile } */
+ /* { dg-options "-O2 -Wall" } */
+
+ extern void function(void * x);
+
+ struct A {
+ long x;
+ char d[0];
+ };
+
+
+ void test(A * a) {
+ function((char *)a - 4); /* { dg-bogus "below array bounds" } */
+ }
+
Index: tree-ssa-ccp.c
===================================================================
*** tree-ssa-ccp.c (revision 133243)
--- tree-ssa-ccp.c (working copy)
*************** widen_bitfield (tree val, tree field, tr
*** 1593,1599 ****
is the desired result type. */
static tree
! maybe_fold_offset_to_array_ref (tree base, tree offset, tree orig_type)
{
tree min_idx, idx, idx_type, elt_offset = integer_zero_node;
tree array_type, elt_type, elt_size;
--- 1593,1600 ----
is the desired result type. */
static tree
! maybe_fold_offset_to_array_ref (tree base, tree offset, tree orig_type,
! bool allow_negative_idx)
{
tree min_idx, idx, idx_type, elt_offset = integer_zero_node;
tree array_type, elt_type, elt_size;
*************** maybe_fold_offset_to_array_ref (tree bas
*** 1693,1703 ****
idx = fold_convert (idx_type, idx);
/* We don't want to construct access past array bounds. For example
! char *(c[4]);
!
! c[3][2]; should not be simplified into (*c)[14] or tree-vrp will give false
! warning. */
! if (domain_type && TYPE_MAX_VALUE (domain_type)
&& TREE_CODE (TYPE_MAX_VALUE (domain_type)) == INTEGER_CST)
{
tree up_bound = TYPE_MAX_VALUE (domain_type);
--- 1694,1708 ----
idx = fold_convert (idx_type, idx);
/* We don't want to construct access past array bounds. For example
! char *(c[4]);
! c[3][2];
! should not be simplified into (*c)[14] or tree-vrp will
! give false warnings. The same is true for
! struct A { long x; char d[0]; } *a;
! (char *)a - 4;
! which should be not folded to &a->d[-8]. */
! if (domain_type
! && TYPE_MAX_VALUE (domain_type)
&& TREE_CODE (TYPE_MAX_VALUE (domain_type)) == INTEGER_CST)
{
tree up_bound = TYPE_MAX_VALUE (domain_type);
*************** maybe_fold_offset_to_array_ref (tree bas
*** 1709,1714 ****
--- 1714,1730 ----
&& compare_tree_int (up_bound, 1) > 0)
return NULL_TREE;
}
+ if (domain_type
+ && TYPE_MIN_VALUE (domain_type))
+ {
+ if (!allow_negative_idx
+ && TREE_CODE (TYPE_MIN_VALUE (domain_type)) == INTEGER_CST
+ && tree_int_cst_lt (idx, TYPE_MIN_VALUE (domain_type)))
+ return NULL_TREE;
+ }
+ else if (!allow_negative_idx
+ && compare_tree_int (idx, 0) < 0)
+ return NULL_TREE;
return build4 (ARRAY_REF, elt_type, base, idx, NULL_TREE, NULL_TREE);
}
*************** maybe_fold_offset_to_component_ref (tree
*** 1805,1811 ****
new_base = build3 (COMPONENT_REF, field_type, new_base, f, NULL_TREE);
/* Recurse to possibly find the match. */
! ret = maybe_fold_offset_to_array_ref (new_base, t, orig_type);
if (ret)
return ret;
ret = maybe_fold_offset_to_component_ref (field_type, new_base, t,
--- 1821,1828 ----
new_base = build3 (COMPONENT_REF, field_type, new_base, f, NULL_TREE);
/* Recurse to possibly find the match. */
! ret = maybe_fold_offset_to_array_ref (new_base, t, orig_type,
! f == TYPE_FIELDS (record_type));
if (ret)
return ret;
ret = maybe_fold_offset_to_component_ref (field_type, new_base, t,
*************** maybe_fold_offset_to_component_ref (tree
*** 1827,1833 ****
base = build1 (INDIRECT_REF, record_type, base);
base = build3 (COMPONENT_REF, field_type, base, f, NULL_TREE);
! t = maybe_fold_offset_to_array_ref (base, offset, orig_type);
if (t)
return t;
return maybe_fold_offset_to_component_ref (field_type, base, offset,
--- 1844,1851 ----
base = build1 (INDIRECT_REF, record_type, base);
base = build3 (COMPONENT_REF, field_type, base, f, NULL_TREE);
! t = maybe_fold_offset_to_array_ref (base, offset, orig_type,
! f == TYPE_FIELDS (record_type));
if (t)
return t;
return maybe_fold_offset_to_component_ref (field_type, base, offset,
*************** maybe_fold_offset_to_reference (tree bas
*** 1893,1899 ****
{
if (base_is_ptr)
base = build1 (INDIRECT_REF, type, base);
! ret = maybe_fold_offset_to_array_ref (base, offset, orig_type);
}
return ret;
}
--- 1911,1917 ----
{
if (base_is_ptr)
base = build1 (INDIRECT_REF, type, base);
! ret = maybe_fold_offset_to_array_ref (base, offset, orig_type, true);
}
return ret;
}
*************** maybe_fold_stmt_addition (tree expr)
*** 2070,2076 ****
ptd_type = TREE_TYPE (ptr_type);
/* At which point we can try some of the same things as for indirects. */
! t = maybe_fold_offset_to_array_ref (op0, op1, ptd_type);
if (!t)
t = maybe_fold_offset_to_component_ref (TREE_TYPE (op0), op0, op1,
ptd_type, false);
--- 2088,2094 ----
ptd_type = TREE_TYPE (ptr_type);
/* At which point we can try some of the same things as for indirects. */
! t = maybe_fold_offset_to_array_ref (op0, op1, ptd_type, true);
if (!t)
t = maybe_fold_offset_to_component_ref (TREE_TYPE (op0), op0, op1,
ptd_type, false);
More information about the Gcc-patches
mailing list