Commit 108b7b29 by Jakub Jelinek Committed by Jakub Jelinek

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
parent 1ee806d8
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.
......
...@@ -7769,7 +7769,7 @@ namespace inchash ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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); ...@@ -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);
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment