This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Fix PR35593, over-eager ARRAY_REF re-construction


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);


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]