]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR sanitizer/70683 (-fcompare-debug bug with -fsanitize=address)
authorJakub Jelinek <jakub@redhat.com>
Wed, 27 Apr 2016 07:45:57 +0000 (09:45 +0200)
committerJakub Jelinek <jakub@gcc.gnu.org>
Wed, 27 Apr 2016 07:45:57 +0000 (09:45 +0200)
PR sanitizer/70683
* tree.h (inchash::add_expr): Add FLAGS argument.
* tree.c (inchash::add_expr): Likewise.  If not OEP_ADDRESS_OF,
use STRIP_NOPS first.  For INTEGER_CST assert not OEP_ADDRESS_OF.
For REAL_CST and !HONOR_SIGNED_ZEROS (t) hash +/- 0 the same.
Formatting fix.  Adjust recursive calls.  For tcc_comparison,
if swap_tree_comparison (code) is smaller than code, hash that
and arguments in the other order.  Hash CONVERT_EXPR the same
as NOP_EXPR.  For OEP_ADDRESS_OF hash MEM_REF with 0 offset
of ADDR_EXPR of decl as the decl itself.  Add or remove
OEP_ADDRESS_OF from recursive flags as needed.  For
FMA_EXPR, WIDEN_MULT_{PLUS,MINUS}_EXPR hash the first two
operands commutatively and only the third one normally.
For internal CALL_EXPR hash in CALL_EXPR_IFN.

From-SVN: r235469

gcc/ChangeLog
gcc/tree.c
gcc/tree.h

index 245c929839edc5fa45036b5235e117d2c5169b40..2ed5c25bc4f1d77dd3348b2521aba6a8ef0e9b52 100644 (file)
@@ -1,3 +1,20 @@
+2016-04-27  Jakub Jelinek  <jakub@redhat.com>
+
+       PR sanitizer/70683
+       * tree.h (inchash::add_expr): Add FLAGS argument.
+       * tree.c (inchash::add_expr): Likewise.  If not OEP_ADDRESS_OF,
+       use STRIP_NOPS first.  For INTEGER_CST assert not OEP_ADDRESS_OF.
+       For REAL_CST and !HONOR_SIGNED_ZEROS (t) hash +/- 0 the same.
+       Formatting fix.  Adjust recursive calls.  For tcc_comparison,
+       if swap_tree_comparison (code) is smaller than code, hash that
+       and arguments in the other order.  Hash CONVERT_EXPR the same
+       as NOP_EXPR.  For OEP_ADDRESS_OF hash MEM_REF with 0 offset
+       of ADDR_EXPR of decl as the decl itself.  Add or remove
+       OEP_ADDRESS_OF from recursive flags as needed.  For
+       FMA_EXPR, WIDEN_MULT_{PLUS,MINUS}_EXPR hash the first two
+       operands commutatively and only the third one normally.
+       For internal CALL_EXPR hash in CALL_EXPR_IFN.
+
 2016-04-27  Sebastian Huber  <sebastian.huber@embedded-brains.de>
 
        * config/rtems.h (LIB_SPEC): Add -latomic.
index 6de46a84695fccbb3d93ee2fc97aeab998a9857f..869218207b7d39b2e38c07be0449d9070a0e3d51 100644 (file)
@@ -7769,7 +7769,7 @@ namespace inchash
    This function is intended to produce the same hash for expressions which
    would compare equal using operand_equal_p.  */
 void
-add_expr (const_tree t, inchash::hash &hstate)
+add_expr (const_tree t, inchash::hash &hstate, unsigned int flags)
 {
   int i;
   enum tree_code code;
@@ -7781,6 +7781,9 @@ add_expr (const_tree t, inchash::hash &hstate)
       return;
     }
 
+  if (!(flags & OEP_ADDRESS_OF))
+    STRIP_NOPS (t);
+
   code = TREE_CODE (t);
 
   switch (code)
@@ -7791,12 +7794,17 @@ add_expr (const_tree t, inchash::hash &hstate)
       hstate.merge_hash (0);
       return;
     case INTEGER_CST:
-      for (i = 0; i < TREE_INT_CST_NUNITS (t); i++)
+      gcc_checking_assert (!(flags & OEP_ADDRESS_OF));
+      for (i = 0; i < TREE_INT_CST_EXT_NUNITS (t); i++)
        hstate.add_wide_int (TREE_INT_CST_ELT (t, i));
       return;
     case REAL_CST:
       {
-       unsigned int val2 = real_hash (TREE_REAL_CST_PTR (t));
+       unsigned int val2;
+       if (!HONOR_SIGNED_ZEROS (t) && real_zerop (t))
+         val2 = rvc_zero;
+       else
+         val2 = real_hash (TREE_REAL_CST_PTR (t));
        hstate.merge_hash (val2);
        return;
       }
@@ -7807,17 +7815,18 @@ add_expr (const_tree t, inchash::hash &hstate)
        return;
       }
     case STRING_CST:
-      hstate.add ((const void *) TREE_STRING_POINTER (t), TREE_STRING_LENGTH (t));
+      hstate.add ((const void *) TREE_STRING_POINTER (t),
+                 TREE_STRING_LENGTH (t));
       return;
     case COMPLEX_CST:
-      inchash::add_expr (TREE_REALPART (t), hstate);
-      inchash::add_expr (TREE_IMAGPART (t), hstate);
+      inchash::add_expr (TREE_REALPART (t), hstate, flags);
+      inchash::add_expr (TREE_IMAGPART (t), hstate, flags);
       return;
     case VECTOR_CST:
       {
        unsigned i;
        for (i = 0; i < VECTOR_CST_NELTS (t); ++i)
-         inchash::add_expr (VECTOR_CST_ELT (t, i), hstate);
+         inchash::add_expr (VECTOR_CST_ELT (t, i), hstate, flags);
        return;
       }
     case SSA_NAME:
@@ -7831,16 +7840,17 @@ add_expr (const_tree t, inchash::hash &hstate)
       /* A list of expressions, for a CALL_EXPR or as the elements of a
         VECTOR_CST.  */
       for (; t; t = TREE_CHAIN (t))
-       inchash::add_expr (TREE_VALUE (t), hstate);
+       inchash::add_expr (TREE_VALUE (t), hstate, flags);
       return;
     case CONSTRUCTOR:
       {
        unsigned HOST_WIDE_INT idx;
        tree field, value;
+       flags &= ~OEP_ADDRESS_OF;
        FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (t), idx, field, value)
          {
-           inchash::add_expr (field, hstate);
-           inchash::add_expr (value, hstate);
+           inchash::add_expr (field, hstate, flags);
+           inchash::add_expr (value, hstate, flags);
          }
        return;
       }
@@ -7865,21 +7875,102 @@ add_expr (const_tree t, inchash::hash &hstate)
          /* DECL's have a unique ID */
          hstate.add_wide_int (DECL_UID (t));
        }
+      else if (tclass == tcc_comparison && !commutative_tree_code (code))
+       {
+         /* For comparisons that can be swapped, use the lower
+            tree code.  */
+         enum tree_code ccode = swap_tree_comparison (code);
+         if (code < ccode)
+           ccode = code;
+         hstate.add_object (ccode);
+         inchash::add_expr (TREE_OPERAND (t, ccode != code), hstate, flags);
+         inchash::add_expr (TREE_OPERAND (t, ccode == code), hstate, flags);
+       }
+      else if (CONVERT_EXPR_CODE_P (code))
+       {
+         /* NOP_EXPR and CONVERT_EXPR are considered equal by
+            operand_equal_p.  */
+         enum tree_code ccode = NOP_EXPR;
+         hstate.add_object (ccode);
+
+         /* Don't hash the type, that can lead to having nodes which
+            compare equal according to operand_equal_p, but which
+            have different hash codes.  Make sure to include signedness
+            in the hash computation.  */
+         hstate.add_int (TYPE_UNSIGNED (TREE_TYPE (t)));
+         inchash::add_expr (TREE_OPERAND (t, 0), hstate, flags);
+       }
+      /* For OEP_ADDRESS_OF, hash MEM_EXPR[&decl, 0] the same as decl.  */
+      else if (code == MEM_REF
+              && (flags & OEP_ADDRESS_OF) != 0
+              && TREE_CODE (TREE_OPERAND (t, 0)) == ADDR_EXPR
+              && DECL_P (TREE_OPERAND (TREE_OPERAND (t, 0), 0))
+              && integer_zerop (TREE_OPERAND (t, 1)))
+       inchash::add_expr (TREE_OPERAND (TREE_OPERAND (t, 0), 0),
+                          hstate, flags);
       else
        {
          gcc_assert (IS_EXPR_CODE_CLASS (tclass));
+         unsigned int sflags = flags;
 
          hstate.add_object (code);
 
+         switch (code)
+           {
+           case ADDR_EXPR:
+             gcc_checking_assert (!(flags & OEP_ADDRESS_OF));
+             flags |= OEP_ADDRESS_OF;
+             sflags = flags;
+             break;
+
+           case INDIRECT_REF:
+           case MEM_REF:
+           case TARGET_MEM_REF:
+             flags &= ~OEP_ADDRESS_OF;
+             sflags = flags;
+             break;
+
+           case ARRAY_REF:
+           case ARRAY_RANGE_REF:
+           case COMPONENT_REF:
+           case BIT_FIELD_REF:
+             sflags &= ~OEP_ADDRESS_OF;
+             break;
+
+           case COND_EXPR:
+             flags &= ~OEP_ADDRESS_OF;
+             break;
+
+           case FMA_EXPR:
+           case WIDEN_MULT_PLUS_EXPR:
+           case WIDEN_MULT_MINUS_EXPR:
+             {
+               /* The multiplication operands are commutative.  */
+               inchash::hash one, two;
+               inchash::add_expr (TREE_OPERAND (t, 0), one, flags);
+               inchash::add_expr (TREE_OPERAND (t, 1), two, flags);
+               hstate.add_commutative (one, two);
+               inchash::add_expr (TREE_OPERAND (t, 2), two, flags);
+               return;
+             }
+
+           case CALL_EXPR:
+             if (CALL_EXPR_FN (t) == NULL_TREE)
+               hstate.add_int (CALL_EXPR_IFN (t));
+             break;
+
+           default:
+             break;
+           }
+
          /* Don't hash the type, that can lead to having nodes which
             compare equal according to operand_equal_p, but which
             have different hash codes.  */
-         if (CONVERT_EXPR_CODE_P (code)
-             || code == NON_LVALUE_EXPR)
+         if (code == NON_LVALUE_EXPR)
            {
              /* Make sure to include signness in the hash computation.  */
              hstate.add_int (TYPE_UNSIGNED (TREE_TYPE (t)));
-             inchash::add_expr (TREE_OPERAND (t, 0), hstate);
+             inchash::add_expr (TREE_OPERAND (t, 0), hstate, flags);
            }
 
          else if (commutative_tree_code (code))
@@ -7889,13 +7980,14 @@ add_expr (const_tree t, inchash::hash &hstate)
                 and then rehashing based on the order of their independent
                 hashes.  */
              inchash::hash one, two;
-             inchash::add_expr (TREE_OPERAND (t, 0), one);
-             inchash::add_expr (TREE_OPERAND (t, 1), two);
+             inchash::add_expr (TREE_OPERAND (t, 0), one, flags);
+             inchash::add_expr (TREE_OPERAND (t, 1), two, flags);
              hstate.add_commutative (one, two);
            }
          else
            for (i = TREE_OPERAND_LENGTH (t) - 1; i >= 0; --i)
-             inchash::add_expr (TREE_OPERAND (t, i), hstate);
+             inchash::add_expr (TREE_OPERAND (t, i), hstate,
+                                i == 0 ? flags : sflags);
        }
       return;
     }
index 33833a7abe65322bdb14457cf3e7412d1df272f8..259a2bff6883734d3fc286b8092aac01202bbff8 100644 (file)
@@ -4759,7 +4759,7 @@ extern int simple_cst_equal (const_tree, const_tree);
 namespace inchash
 {
 
-extern void add_expr (const_tree, hash &);
+extern void add_expr (const_tree, hash &, unsigned int = 0);
 
 }