mirror of git://gcc.gnu.org/git/gcc.git
re PR sanitizer/70683 (-fcompare-debug bug with -fsanitize=address)
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
This commit is contained in:
parent
1ee806d8d7
commit
108b7b2901
|
|
@ -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>
|
2016-04-27 Sebastian Huber <sebastian.huber@embedded-brains.de>
|
||||||
|
|
||||||
* config/rtems.h (LIB_SPEC): Add -latomic.
|
* config/rtems.h (LIB_SPEC): Add -latomic.
|
||||||
|
|
|
||||||
124
gcc/tree.c
124
gcc/tree.c
|
|
@ -7769,7 +7769,7 @@ namespace inchash
|
||||||
This function is intended to produce the same hash for expressions which
|
This function is intended to produce the same hash for expressions which
|
||||||
would compare equal using operand_equal_p. */
|
would compare equal using operand_equal_p. */
|
||||||
void
|
void
|
||||||
add_expr (const_tree t, inchash::hash &hstate)
|
add_expr (const_tree t, inchash::hash &hstate, unsigned int flags)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
enum tree_code code;
|
enum tree_code code;
|
||||||
|
|
@ -7781,6 +7781,9 @@ add_expr (const_tree t, inchash::hash &hstate)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!(flags & OEP_ADDRESS_OF))
|
||||||
|
STRIP_NOPS (t);
|
||||||
|
|
||||||
code = TREE_CODE (t);
|
code = TREE_CODE (t);
|
||||||
|
|
||||||
switch (code)
|
switch (code)
|
||||||
|
|
@ -7791,12 +7794,17 @@ add_expr (const_tree t, inchash::hash &hstate)
|
||||||
hstate.merge_hash (0);
|
hstate.merge_hash (0);
|
||||||
return;
|
return;
|
||||||
case INTEGER_CST:
|
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));
|
hstate.add_wide_int (TREE_INT_CST_ELT (t, i));
|
||||||
return;
|
return;
|
||||||
case REAL_CST:
|
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);
|
hstate.merge_hash (val2);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -7807,17 +7815,18 @@ add_expr (const_tree t, inchash::hash &hstate)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
case STRING_CST:
|
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;
|
return;
|
||||||
case COMPLEX_CST:
|
case COMPLEX_CST:
|
||||||
inchash::add_expr (TREE_REALPART (t), hstate);
|
inchash::add_expr (TREE_REALPART (t), hstate, flags);
|
||||||
inchash::add_expr (TREE_IMAGPART (t), hstate);
|
inchash::add_expr (TREE_IMAGPART (t), hstate, flags);
|
||||||
return;
|
return;
|
||||||
case VECTOR_CST:
|
case VECTOR_CST:
|
||||||
{
|
{
|
||||||
unsigned i;
|
unsigned i;
|
||||||
for (i = 0; i < VECTOR_CST_NELTS (t); ++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;
|
return;
|
||||||
}
|
}
|
||||||
case SSA_NAME:
|
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
|
/* A list of expressions, for a CALL_EXPR or as the elements of a
|
||||||
VECTOR_CST. */
|
VECTOR_CST. */
|
||||||
for (; t; t = TREE_CHAIN (t))
|
for (; t; t = TREE_CHAIN (t))
|
||||||
inchash::add_expr (TREE_VALUE (t), hstate);
|
inchash::add_expr (TREE_VALUE (t), hstate, flags);
|
||||||
return;
|
return;
|
||||||
case CONSTRUCTOR:
|
case CONSTRUCTOR:
|
||||||
{
|
{
|
||||||
unsigned HOST_WIDE_INT idx;
|
unsigned HOST_WIDE_INT idx;
|
||||||
tree field, value;
|
tree field, value;
|
||||||
|
flags &= ~OEP_ADDRESS_OF;
|
||||||
FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (t), idx, field, value)
|
FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (t), idx, field, value)
|
||||||
{
|
{
|
||||||
inchash::add_expr (field, hstate);
|
inchash::add_expr (field, hstate, flags);
|
||||||
inchash::add_expr (value, hstate);
|
inchash::add_expr (value, hstate, flags);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -7865,21 +7875,102 @@ add_expr (const_tree t, inchash::hash &hstate)
|
||||||
/* DECL's have a unique ID */
|
/* DECL's have a unique ID */
|
||||||
hstate.add_wide_int (DECL_UID (t));
|
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
|
else
|
||||||
{
|
{
|
||||||
gcc_assert (IS_EXPR_CODE_CLASS (tclass));
|
gcc_assert (IS_EXPR_CODE_CLASS (tclass));
|
||||||
|
unsigned int sflags = flags;
|
||||||
|
|
||||||
hstate.add_object (code);
|
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
|
/* Don't hash the type, that can lead to having nodes which
|
||||||
compare equal according to operand_equal_p, but which
|
compare equal according to operand_equal_p, but which
|
||||||
have different hash codes. */
|
have different hash codes. */
|
||||||
if (CONVERT_EXPR_CODE_P (code)
|
if (code == NON_LVALUE_EXPR)
|
||||||
|| code == NON_LVALUE_EXPR)
|
|
||||||
{
|
{
|
||||||
/* Make sure to include signness in the hash computation. */
|
/* Make sure to include signness in the hash computation. */
|
||||||
hstate.add_int (TYPE_UNSIGNED (TREE_TYPE (t)));
|
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))
|
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
|
and then rehashing based on the order of their independent
|
||||||
hashes. */
|
hashes. */
|
||||||
inchash::hash one, two;
|
inchash::hash one, two;
|
||||||
inchash::add_expr (TREE_OPERAND (t, 0), one);
|
inchash::add_expr (TREE_OPERAND (t, 0), one, flags);
|
||||||
inchash::add_expr (TREE_OPERAND (t, 1), two);
|
inchash::add_expr (TREE_OPERAND (t, 1), two, flags);
|
||||||
hstate.add_commutative (one, two);
|
hstate.add_commutative (one, two);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
for (i = TREE_OPERAND_LENGTH (t) - 1; i >= 0; --i)
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4759,7 +4759,7 @@ extern int simple_cst_equal (const_tree, const_tree);
|
||||||
namespace inchash
|
namespace inchash
|
||||||
{
|
{
|
||||||
|
|
||||||
extern void add_expr (const_tree, hash &);
|
extern void add_expr (const_tree, hash &, unsigned int = 0);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue