OSDN Git Service

2010-04-07 Richard Guenther <rguenther@suse.de>
authorrguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 7 Apr 2010 12:31:32 +0000 (12:31 +0000)
committerrguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 7 Apr 2010 12:31:32 +0000 (12:31 +0000)
PR tree-optimization/43270
* tree-vrp.c (check_array_ref): Fix flexible array member
detection.
* tree-ssa-sccvn.h (fully_constant_vn_reference_p): Declare.
* tree-ssa-pre.c (phi_translate_1): Adjust.
(fully_constant_expression): Split out vn_reference handling to ...
* tree-ssa-sccvn.c (fully_constant_vn_reference_p): ... here.
Fold reads from constant strings.
(vn_reference_lookup): Handle fully constant references.
(vn_reference_lookup_pieces): Likewise.
* Makefile.in (expmed.o-warn): Add -Wno-error.

* g++.dg/warn/Warray-bounds-4.C: New testcase.
* gcc.dg/Warray-bounds-7.c: Likewise.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@158058 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/Makefile.in
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/warn/Warray-bounds-4.C [new file with mode: 0644]
gcc/testsuite/gcc.dg/Warray-bounds-7.c [new file with mode: 0644]
gcc/tree-ssa-pre.c
gcc/tree-ssa-sccvn.c
gcc/tree-ssa-sccvn.h
gcc/tree-vrp.c

index 3121c99..ca2b7f6 100644 (file)
@@ -1,3 +1,17 @@
+2010-04-07  Richard Guenther  <rguenther@suse.de>
+
+       PR tree-optimization/43270
+       * tree-vrp.c (check_array_ref): Fix flexible array member
+       detection.
+       * tree-ssa-sccvn.h (fully_constant_vn_reference_p): Declare.
+       * tree-ssa-pre.c (phi_translate_1): Adjust.
+       (fully_constant_expression): Split out vn_reference handling to ...
+       * tree-ssa-sccvn.c (fully_constant_vn_reference_p): ... here.
+       Fold reads from constant strings.
+       (vn_reference_lookup): Handle fully constant references.
+       (vn_reference_lookup_pieces): Likewise.
+       * Makefile.in (expmed.o-warn): Add -Wno-error.
+
 2010-04-07  Martin Jambor  <mjambor@suse.cz>
 
        * tree-sra.c (find_param_candidates): Allow scalar va_list types.
index a1ad1d4..20529d0 100644 (file)
@@ -183,6 +183,7 @@ GCC_WARN_CXXFLAGS = $(LOOSE_WARN) $($(@D)-warn) $(NOCOMMON_FLAG) $($@-warn)
 build/gengtype-lex.o-warn = -Wno-error
 # mips-tfile.c contains -Wcast-qual warnings.
 mips-tfile.o-warn = -Wno-error
+expmed.o-warn = -Wno-error
 
 # All warnings have to be shut off in stage1 if the compiler used then
 # isn't gcc; configure determines that.  WARN_CFLAGS will be either
index 5f8db2c..a2faaf5 100644 (file)
@@ -1,3 +1,9 @@
+2010-04-07  Richard Guenther  <rguenther@suse.de>
+
+       PR tree-optimization/43270
+       * g++.dg/warn/Warray-bounds-4.C: New testcase.
+       * gcc.dg/Warray-bounds-7.c: Likewise.
+
 2010-04-07  Eric Botcazou  <ebotcazou@adacore.com>
 
        * gnat.dg/bit_packed_array.ad[sb]: Rename into...
diff --git a/gcc/testsuite/g++.dg/warn/Warray-bounds-4.C b/gcc/testsuite/g++.dg/warn/Warray-bounds-4.C
new file mode 100644 (file)
index 0000000..319038a
--- /dev/null
@@ -0,0 +1,37 @@
+// { dg-do compile }
+// { dg-options "-O2 -Warray-bounds" }
+
+class String
+{
+public:
+  virtual unsigned long length() const = 0;
+  virtual char get(unsigned long index) const = 0;
+  virtual void set(unsigned long index, char value) = 0;
+  virtual char& operator[] (unsigned long value) = 0;
+  virtual ~String() {};
+};
+
+template<unsigned long size> class FixedString : public String
+{
+private:
+  char contents[size];
+
+public:
+  virtual unsigned long length() const { return size; }
+  virtual char get(unsigned long index) const { return contents[index]; }
+  virtual void set(unsigned long index, char value) { contents[index] = value; }
+  virtual char& operator[] (unsigned long index) { return contents[index]; }
+
+  FixedString() { contents[0] = '\0'; } // { dg-warning "above array bounds" }
+};
+
+void print_length (const String& string);
+
+int main()
+{
+  const FixedString<0> empty;
+
+  print_length(empty);
+
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-7.c b/gcc/testsuite/gcc.dg/Warray-bounds-7.c
new file mode 100644 (file)
index 0000000..fdd9578
--- /dev/null
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -Warray-bounds" } */
+
+char *p;
+
+int main()
+{
+  p = "";
+  if (p[0] == 0
+      || (p[0] == '_' && p[1] == 0))  /* { dg-bogus "array bounds" "" } */
+    return 0;
+  return 1;
+}
index 24172f7..2331e7b 100644 (file)
@@ -1231,49 +1231,11 @@ do_unary:
     case REFERENCE:
       {
        vn_reference_t ref = PRE_EXPR_REFERENCE (e);
-       VEC (vn_reference_op_s, heap) *operands = ref->operands;
-       vn_reference_op_t op;
-
-       /* Try to simplify the translated expression if it is
-          a call to a builtin function with at most two arguments.  */
-       op = VEC_index (vn_reference_op_s, operands, 0);
-       if (op->opcode == CALL_EXPR
-           && TREE_CODE (op->op0) == ADDR_EXPR
-           && TREE_CODE (TREE_OPERAND (op->op0, 0)) == FUNCTION_DECL
-           && DECL_BUILT_IN (TREE_OPERAND (op->op0, 0))
-           && VEC_length (vn_reference_op_s, operands) >= 2
-           && VEC_length (vn_reference_op_s, operands) <= 3)
-         {
-           vn_reference_op_t arg0, arg1 = NULL;
-           bool anyconst = false;
-           arg0 = VEC_index (vn_reference_op_s, operands, 1);
-           if (VEC_length (vn_reference_op_s, operands) > 2)
-             arg1 = VEC_index (vn_reference_op_s, operands, 2);
-           if (TREE_CODE_CLASS (arg0->opcode) == tcc_constant
-               || (arg0->opcode == ADDR_EXPR
-                   && is_gimple_min_invariant (arg0->op0)))
-             anyconst = true;
-           if (arg1
-               && (TREE_CODE_CLASS (arg1->opcode) == tcc_constant
-                   || (arg1->opcode == ADDR_EXPR
-                       && is_gimple_min_invariant (arg1->op0))))
-             anyconst = true;
-           if (anyconst)
-             {
-               tree folded = build_call_expr (TREE_OPERAND (op->op0, 0),
-                                              arg1 ? 2 : 1,
-                                              arg0->op0,
-                                              arg1 ? arg1->op0 : NULL);
-               if (folded
-                   && TREE_CODE (folded) == NOP_EXPR)
-                 folded = TREE_OPERAND (folded, 0);
-               if (folded
-                   && is_gimple_min_invariant (folded))
-                 return get_or_alloc_expr_for_constant (folded);
-             }
-         }
-         return e;
-       }
+       tree folded;
+       if ((folded = fully_constant_vn_reference_p (ref)))
+         return get_or_alloc_expr_for_constant (folded);
+       return e;
+      }
     default:
       return e;
     }
@@ -1702,7 +1664,7 @@ phi_translate_1 (pre_expr expr, bitmap_set_t set1, bitmap_set_t set2,
                                                      ref->type,
                                                      newoperands,
                                                      &newref, true);
-           if (newref)
+           if (result)
              VEC_free (vn_reference_op_s, heap, newoperands);
 
            if (result && is_gimple_min_invariant (result))
index 5282978..f965c51 100644 (file)
@@ -889,6 +889,76 @@ vn_reference_fold_indirect (VEC (vn_reference_op_s, heap) **ops,
   *i_p = i;
 }
 
+/* Optimize the reference REF to a constant if possible or return
+   NULL_TREE if not.  */
+
+tree
+fully_constant_vn_reference_p (vn_reference_t ref)
+{
+  VEC (vn_reference_op_s, heap) *operands = ref->operands;
+  vn_reference_op_t op;
+
+  /* Try to simplify the translated expression if it is
+     a call to a builtin function with at most two arguments.  */
+  op = VEC_index (vn_reference_op_s, operands, 0);
+  if (op->opcode == CALL_EXPR
+      && TREE_CODE (op->op0) == ADDR_EXPR
+      && TREE_CODE (TREE_OPERAND (op->op0, 0)) == FUNCTION_DECL
+      && DECL_BUILT_IN (TREE_OPERAND (op->op0, 0))
+      && VEC_length (vn_reference_op_s, operands) >= 2
+      && VEC_length (vn_reference_op_s, operands) <= 3)
+    {
+      vn_reference_op_t arg0, arg1 = NULL;
+      bool anyconst = false;
+      arg0 = VEC_index (vn_reference_op_s, operands, 1);
+      if (VEC_length (vn_reference_op_s, operands) > 2)
+       arg1 = VEC_index (vn_reference_op_s, operands, 2);
+      if (TREE_CODE_CLASS (arg0->opcode) == tcc_constant
+         || (arg0->opcode == ADDR_EXPR
+             && is_gimple_min_invariant (arg0->op0)))
+       anyconst = true;
+      if (arg1
+         && (TREE_CODE_CLASS (arg1->opcode) == tcc_constant
+             || (arg1->opcode == ADDR_EXPR
+                 && is_gimple_min_invariant (arg1->op0))))
+       anyconst = true;
+      if (anyconst)
+       {
+         tree folded = build_call_expr (TREE_OPERAND (op->op0, 0),
+                                        arg1 ? 2 : 1,
+                                        arg0->op0,
+                                        arg1 ? arg1->op0 : NULL);
+         if (folded
+             && TREE_CODE (folded) == NOP_EXPR)
+           folded = TREE_OPERAND (folded, 0);
+         if (folded
+             && is_gimple_min_invariant (folded))
+           return folded;
+       }
+    }
+
+  /* Simplify reads from constant strings.  */
+  else if (op->opcode == ARRAY_REF
+          && TREE_CODE (op->op0) == INTEGER_CST
+          && integer_zerop (op->op1)
+          && VEC_length (vn_reference_op_s, operands) == 2)
+    {
+      vn_reference_op_t arg0;
+      arg0 = VEC_index (vn_reference_op_s, operands, 1);
+      if (arg0->opcode == STRING_CST
+         && (TYPE_MODE (op->type)
+             == TYPE_MODE (TREE_TYPE (TREE_TYPE (arg0->op0))))
+         && GET_MODE_CLASS (TYPE_MODE (op->type)) == MODE_INT
+         && GET_MODE_SIZE (TYPE_MODE (op->type)) == 1
+         && compare_tree_int (op->op0, TREE_STRING_LENGTH (arg0->op0)) < 0)
+       return build_int_cst_type (op->type,
+                                  (TREE_STRING_POINTER (arg0->op0)
+                                   [TREE_INT_CST_LOW (op->op0)]));
+    }
+
+  return NULL_TREE;
+}
+
 /* Transform any SSA_NAME's in a vector of vn_reference_op_s
    structures into their value numbers.  This is done in-place, and
    the vector passed in is returned.  */
@@ -1194,6 +1264,7 @@ vn_reference_lookup_pieces (tree vuse, alias_set_type set, tree type,
 {
   struct vn_reference_s vr1;
   vn_reference_t tmp;
+  tree cst;
 
   if (!vnresult)
     vnresult = &tmp;
@@ -1212,8 +1283,10 @@ vn_reference_lookup_pieces (tree vuse, alias_set_type set, tree type,
   vr1.type = type;
   vr1.set = set;
   vr1.hashcode = vn_reference_compute_hash (&vr1);
-  vn_reference_lookup_1 (&vr1, vnresult);
+  if ((cst = fully_constant_vn_reference_p (&vr1)))
+    return cst;
 
+  vn_reference_lookup_1 (&vr1, vnresult);
   if (!*vnresult
       && maywalk
       && vr1.vuse)
@@ -1246,6 +1319,7 @@ vn_reference_lookup (tree op, tree vuse, bool maywalk,
 {
   VEC (vn_reference_op_s, heap) *operands;
   struct vn_reference_s vr1;
+  tree cst;
 
   if (vnresult)
     *vnresult = NULL;
@@ -1255,6 +1329,8 @@ vn_reference_lookup (tree op, tree vuse, bool maywalk,
   vr1.type = TREE_TYPE (op);
   vr1.set = get_alias_set (op);
   vr1.hashcode = vn_reference_compute_hash (&vr1);
+  if ((cst = fully_constant_vn_reference_p (&vr1)))
+    return cst;
 
   if (maywalk
       && vr1.vuse)
index c60c28a..8f93b0b 100644 (file)
@@ -204,4 +204,5 @@ unsigned int get_next_value_id (void);
 unsigned int get_constant_value_id (tree);
 unsigned int get_or_alloc_constant_value_id (tree);
 bool value_id_constant_p (unsigned int);
+tree fully_constant_vn_reference_p (vn_reference_t);
 #endif /* TREE_SSA_SCCVN_H  */
index c84004e..3b22948 100644 (file)
@@ -4998,23 +4998,46 @@ check_array_ref (location_t location, tree ref, bool ignore_off_by_one)
 {
   value_range_t* vr = NULL;
   tree low_sub, up_sub;
-  tree low_bound, up_bound = array_ref_up_bound (ref);
+  tree low_bound, up_bound, up_bound_p1;
+  tree base;
+
+  if (TREE_NO_WARNING (ref))
+    return;
 
   low_sub = up_sub = TREE_OPERAND (ref, 1);
+  up_bound = array_ref_up_bound (ref);
 
-  if (!up_bound || TREE_NO_WARNING (ref)
-      || TREE_CODE (up_bound) != INTEGER_CST
-      /* Can not check flexible arrays.  */
-      || (TYPE_SIZE (TREE_TYPE (ref)) == NULL_TREE
-          && TYPE_DOMAIN (TREE_TYPE (ref)) != NULL_TREE
-          && TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (ref))) == NULL_TREE)
-      /* Accesses after the end of arrays of size 0 (gcc
-         extension) and 1 are likely intentional ("struct
-         hack").  */
-      || compare_tree_int (up_bound, 1) <= 0)
+  /* Can not check flexible arrays.  */
+  if (!up_bound
+      || TREE_CODE (up_bound) != INTEGER_CST)
     return;
 
+  /* Accesses to trailing arrays via pointers may access storage
+     beyond the types array bounds.  */
+  base = get_base_address (ref);
+  if (base
+      && INDIRECT_REF_P (base))
+    {
+      tree cref, next = NULL_TREE;
+
+      if (TREE_CODE (TREE_OPERAND (ref, 0)) != COMPONENT_REF)
+       return;
+
+      cref = TREE_OPERAND (ref, 0);
+      if (TREE_CODE (TREE_TYPE (TREE_OPERAND (cref, 0))) == RECORD_TYPE)
+       for (next = TREE_CHAIN (TREE_OPERAND (cref, 1));
+            next && TREE_CODE (next) != FIELD_DECL;
+            next = TREE_CHAIN (next))
+         ;
+
+      /* If this is the last field in a struct type or a field in a
+        union type do not warn.  */
+      if (!next)
+       return;
+    }
+
   low_bound = array_ref_low_bound (ref);
+  up_bound_p1 = int_const_binop (PLUS_EXPR, up_bound, integer_one_node, 0);
 
   if (TREE_CODE (low_sub) == SSA_NAME)
     {
@@ -5039,14 +5062,11 @@ check_array_ref (location_t location, tree ref, bool ignore_off_by_one)
         }
     }
   else if (TREE_CODE (up_sub) == INTEGER_CST
-           && tree_int_cst_lt (up_bound, up_sub)
-           && !tree_int_cst_equal (up_bound, up_sub)
-           && (!ignore_off_by_one
-               || !tree_int_cst_equal (int_const_binop (PLUS_EXPR,
-                                                        up_bound,
-                                                        integer_one_node,
-                                                        0),
-                                       up_sub)))
+          && (ignore_off_by_one
+              ? (tree_int_cst_lt (up_bound, up_sub)
+                 && !tree_int_cst_equal (up_bound_p1, up_sub))
+              : (tree_int_cst_lt (up_bound, up_sub)
+                 || tree_int_cst_equal (up_bound_p1, up_sub))))
     {
       warning_at (location, OPT_Warray_bounds,
                  "array subscript is above array bounds");