Commit 2d7744d4 by Richard Biener Committed by Richard Biener

re PR sanitizer/81148 (UBSAN: two more false positives)

2017-08-03 Richard Biener  <rguenther@suse.de>

	PR middle-end/81148
	* fold-const.c (split_tree): Add minus_var and minus_con
	arguments, remove unused loc arg.  Never generate NEGATE_EXPRs
	here but always use minus_*.
	(associate_trees): Assert we never associate with MINUS_EXPR
	and NULL first operand.  Do not recurse for PLUS_EXPR operands
	when associating as MINUS_EXPR either.
	(fold_binary_loc): Track minus_var and minus_con.

	* c-c++-common/ubsan/pr81148.c: New testcase.

From-SVN: r250853
parent 3cd36125
2017-08-03 Richard Biener <rguenther@suse.de>
PR middle-end/81148
* fold-const.c (split_tree): Add minus_var and minus_con
arguments, remove unused loc arg. Never generate NEGATE_EXPRs
here but always use minus_*.
(associate_trees): Assert we never associate with MINUS_EXPR
and NULL first operand. Do not recurse for PLUS_EXPR operands
when associating as MINUS_EXPR either.
(fold_binary_loc): Track minus_var and minus_con.
2017-08-03 Tom de Vries <tom@codesourcery.com> 2017-08-03 Tom de Vries <tom@codesourcery.com>
PR lto/81430 PR lto/81430
......
...@@ -108,8 +108,6 @@ enum comparison_code { ...@@ -108,8 +108,6 @@ enum comparison_code {
static bool negate_expr_p (tree); static bool negate_expr_p (tree);
static tree negate_expr (tree); static tree negate_expr (tree);
static tree split_tree (location_t, tree, tree, enum tree_code,
tree *, tree *, tree *, int);
static tree associate_trees (location_t, tree, tree, enum tree_code, tree); static tree associate_trees (location_t, tree, tree, enum tree_code, tree);
static enum comparison_code comparison_to_compcode (enum tree_code); static enum comparison_code comparison_to_compcode (enum tree_code);
static enum tree_code compcode_to_comparison (enum comparison_code); static enum tree_code compcode_to_comparison (enum comparison_code);
...@@ -775,12 +773,14 @@ negate_expr (tree t) ...@@ -775,12 +773,14 @@ negate_expr (tree t)
same type as IN, but they will have the same signedness and mode. */ same type as IN, but they will have the same signedness and mode. */
static tree static tree
split_tree (location_t loc, tree in, tree type, enum tree_code code, split_tree (tree in, tree type, enum tree_code code,
tree *conp, tree *litp, tree *minus_litp, int negate_p) tree *minus_varp, tree *conp, tree *minus_conp,
tree *litp, tree *minus_litp, int negate_p)
{ {
tree var = 0; tree var = 0;
*minus_varp = 0;
*conp = 0; *conp = 0;
*minus_conp = 0;
*litp = 0; *litp = 0;
*minus_litp = 0; *minus_litp = 0;
...@@ -834,27 +834,19 @@ split_tree (location_t loc, tree in, tree type, enum tree_code code, ...@@ -834,27 +834,19 @@ split_tree (location_t loc, tree in, tree type, enum tree_code code,
if (neg_litp_p) if (neg_litp_p)
*minus_litp = *litp, *litp = 0; *minus_litp = *litp, *litp = 0;
if (neg_conp_p && *conp) if (neg_conp_p && *conp)
{ *minus_conp = *conp, *conp = 0;
/* Convert to TYPE before negating. */
*conp = fold_convert_loc (loc, type, *conp);
*conp = negate_expr (*conp);
}
if (neg_var_p && var) if (neg_var_p && var)
{ *minus_varp = var, var = 0;
/* Convert to TYPE before negating. */
var = fold_convert_loc (loc, type, var);
var = negate_expr (var);
}
} }
else if (TREE_CONSTANT (in)) else if (TREE_CONSTANT (in))
*conp = in; *conp = in;
else if (TREE_CODE (in) == BIT_NOT_EXPR else if (TREE_CODE (in) == BIT_NOT_EXPR
&& code == PLUS_EXPR) && code == PLUS_EXPR)
{ {
/* -X - 1 is folded to ~X, undo that here. Do _not_ do this /* -1 - X is folded to ~X, undo that here. Do _not_ do this
when IN is constant. Convert to TYPE before negating. */ when IN is constant. */
*minus_litp = build_one_cst (type); *litp = build_minus_one_cst (type);
var = negate_expr (fold_convert_loc (loc, type, TREE_OPERAND (in, 0))); *minus_varp = TREE_OPERAND (in, 0);
} }
else else
var = in; var = in;
...@@ -866,17 +858,13 @@ split_tree (location_t loc, tree in, tree type, enum tree_code code, ...@@ -866,17 +858,13 @@ split_tree (location_t loc, tree in, tree type, enum tree_code code,
else if (*minus_litp) else if (*minus_litp)
*litp = *minus_litp, *minus_litp = 0; *litp = *minus_litp, *minus_litp = 0;
if (*conp) if (*conp)
{ *minus_conp = *conp, *conp = 0;
/* Convert to TYPE before negating. */ else if (*minus_conp)
*conp = fold_convert_loc (loc, type, *conp); *conp = *minus_conp, *minus_conp = 0;
*conp = negate_expr (*conp);
}
if (var) if (var)
{ *minus_varp = var, var = 0;
/* Convert to TYPE before negating. */ else if (*minus_varp)
var = fold_convert_loc (loc, type, var); var = *minus_varp, *minus_varp = 0;
var = negate_expr (var);
}
} }
if (*litp if (*litp
...@@ -898,7 +886,10 @@ static tree ...@@ -898,7 +886,10 @@ static tree
associate_trees (location_t loc, tree t1, tree t2, enum tree_code code, tree type) associate_trees (location_t loc, tree t1, tree t2, enum tree_code code, tree type)
{ {
if (t1 == 0) if (t1 == 0)
return t2; {
gcc_assert (t2 == 0 || code != MINUS_EXPR);
return t2;
}
else if (t2 == 0) else if (t2 == 0)
return t1; return t1;
...@@ -906,6 +897,7 @@ associate_trees (location_t loc, tree t1, tree t2, enum tree_code code, tree typ ...@@ -906,6 +897,7 @@ associate_trees (location_t loc, tree t1, tree t2, enum tree_code code, tree typ
try to fold this since we will have infinite recursion. But do try to fold this since we will have infinite recursion. But do
deal with any NEGATE_EXPRs. */ deal with any NEGATE_EXPRs. */
if (TREE_CODE (t1) == code || TREE_CODE (t2) == code if (TREE_CODE (t1) == code || TREE_CODE (t2) == code
|| TREE_CODE (t1) == PLUS_EXPR || TREE_CODE (t2) == PLUS_EXPR
|| TREE_CODE (t1) == MINUS_EXPR || TREE_CODE (t2) == MINUS_EXPR) || TREE_CODE (t1) == MINUS_EXPR || TREE_CODE (t2) == MINUS_EXPR)
{ {
if (code == PLUS_EXPR) if (code == PLUS_EXPR)
...@@ -9560,8 +9552,8 @@ fold_binary_loc (location_t loc, ...@@ -9560,8 +9552,8 @@ fold_binary_loc (location_t loc,
if ((! FLOAT_TYPE_P (type) || flag_associative_math) if ((! FLOAT_TYPE_P (type) || flag_associative_math)
&& !TYPE_SATURATING (type)) && !TYPE_SATURATING (type))
{ {
tree var0, con0, lit0, minus_lit0; tree var0, minus_var0, con0, minus_con0, lit0, minus_lit0;
tree var1, con1, lit1, minus_lit1; tree var1, minus_var1, con1, minus_con1, lit1, minus_lit1;
tree atype = type; tree atype = type;
bool ok = true; bool ok = true;
...@@ -9570,10 +9562,12 @@ fold_binary_loc (location_t loc, ...@@ -9570,10 +9562,12 @@ fold_binary_loc (location_t loc,
then the result with variables. This increases the chances of then the result with variables. This increases the chances of
literals being recombined later and of generating relocatable literals being recombined later and of generating relocatable
expressions for the sum of a constant and literal. */ expressions for the sum of a constant and literal. */
var0 = split_tree (loc, arg0, type, code, var0 = split_tree (arg0, type, code,
&con0, &lit0, &minus_lit0, 0); &minus_var0, &con0, &minus_con0,
var1 = split_tree (loc, arg1, type, code, &lit0, &minus_lit0, 0);
&con1, &lit1, &minus_lit1, code == MINUS_EXPR); var1 = split_tree (arg1, type, code,
&minus_var1, &con1, &minus_con1,
&lit1, &minus_lit1, code == MINUS_EXPR);
/* Recombine MINUS_EXPR operands by using PLUS_EXPR. */ /* Recombine MINUS_EXPR operands by using PLUS_EXPR. */
if (code == MINUS_EXPR) if (code == MINUS_EXPR)
...@@ -9600,6 +9594,8 @@ fold_binary_loc (location_t loc, ...@@ -9600,6 +9594,8 @@ fold_binary_loc (location_t loc,
{ {
if (var0 && var1) if (var0 && var1)
{ {
/* ??? If split_tree would handle NEGATE_EXPR we could
simplify this down to the var0/minus_var1 cases. */
tree tmp0 = var0; tree tmp0 = var0;
tree tmp1 = var1; tree tmp1 = var1;
bool one_neg = false; bool one_neg = false;
...@@ -9630,22 +9626,46 @@ fold_binary_loc (location_t loc, ...@@ -9630,22 +9626,46 @@ fold_binary_loc (location_t loc,
|| !operand_equal_p (tmp0, tmp1, 0)) || !operand_equal_p (tmp0, tmp1, 0))
ok = false; ok = false;
} }
else if ((var0 && minus_var1
&& ! operand_equal_p (var0, minus_var1, 0))
|| (minus_var0 && var1
&& ! operand_equal_p (minus_var0, var1, 0)))
ok = false;
} }
/* Only do something if we found more than two objects. Otherwise, /* Only do something if we found more than two objects. Otherwise,
nothing has changed and we risk infinite recursion. */ nothing has changed and we risk infinite recursion. */
if (ok if (ok
&& (2 < ((var0 != 0) + (var1 != 0) && (2 < ((var0 != 0) + (var1 != 0)
+ (minus_var0 != 0) + (minus_var1 != 0)
+ (con0 != 0) + (con1 != 0) + (con0 != 0) + (con1 != 0)
+ (minus_con0 != 0) + (minus_con1 != 0)
+ (lit0 != 0) + (lit1 != 0) + (lit0 != 0) + (lit1 != 0)
+ (minus_lit0 != 0) + (minus_lit1 != 0)))) + (minus_lit0 != 0) + (minus_lit1 != 0))))
{ {
var0 = associate_trees (loc, var0, var1, code, atype); var0 = associate_trees (loc, var0, var1, code, atype);
minus_var0 = associate_trees (loc, minus_var0, minus_var1,
code, atype);
con0 = associate_trees (loc, con0, con1, code, atype); con0 = associate_trees (loc, con0, con1, code, atype);
minus_con0 = associate_trees (loc, minus_con0, minus_con1,
code, atype);
lit0 = associate_trees (loc, lit0, lit1, code, atype); lit0 = associate_trees (loc, lit0, lit1, code, atype);
minus_lit0 = associate_trees (loc, minus_lit0, minus_lit1, minus_lit0 = associate_trees (loc, minus_lit0, minus_lit1,
code, atype); code, atype);
if (minus_var0 && var0)
{
var0 = associate_trees (loc, var0, minus_var0,
MINUS_EXPR, atype);
minus_var0 = 0;
}
if (minus_con0 && con0)
{
con0 = associate_trees (loc, con0, minus_con0,
MINUS_EXPR, atype);
minus_con0 = 0;
}
/* Preserve the MINUS_EXPR if the negative part of the literal is /* Preserve the MINUS_EXPR if the negative part of the literal is
greater than the positive part. Otherwise, the multiplicative greater than the positive part. Otherwise, the multiplicative
folding code (i.e extract_muldiv) may be fooled in case folding code (i.e extract_muldiv) may be fooled in case
...@@ -9655,7 +9675,9 @@ fold_binary_loc (location_t loc, ...@@ -9655,7 +9675,9 @@ fold_binary_loc (location_t loc,
{ {
if (TREE_CODE (lit0) == INTEGER_CST if (TREE_CODE (lit0) == INTEGER_CST
&& TREE_CODE (minus_lit0) == INTEGER_CST && TREE_CODE (minus_lit0) == INTEGER_CST
&& tree_int_cst_lt (lit0, minus_lit0)) && tree_int_cst_lt (lit0, minus_lit0)
/* But avoid ending up with only negated parts. */
&& (var0 || con0))
{ {
minus_lit0 = associate_trees (loc, minus_lit0, lit0, minus_lit0 = associate_trees (loc, minus_lit0, lit0,
MINUS_EXPR, atype); MINUS_EXPR, atype);
...@@ -9674,25 +9696,38 @@ fold_binary_loc (location_t loc, ...@@ -9674,25 +9696,38 @@ fold_binary_loc (location_t loc,
|| (minus_lit0 && TREE_OVERFLOW_P (minus_lit0))) || (minus_lit0 && TREE_OVERFLOW_P (minus_lit0)))
return NULL_TREE; return NULL_TREE;
if (minus_lit0) /* Eliminate lit0 and minus_lit0 to con0 and minus_con0. */
con0 = associate_trees (loc, con0, lit0, code, atype);
lit0 = 0;
minus_con0 = associate_trees (loc, minus_con0, minus_lit0,
code, atype);
minus_lit0 = 0;
/* Eliminate minus_con0. */
if (minus_con0)
{ {
if (con0 == 0) if (con0)
return con0 = associate_trees (loc, con0, minus_con0,
fold_convert_loc (loc, type, MINUS_EXPR, atype);
associate_trees (loc, var0, minus_lit0, else if (var0)
MINUS_EXPR, atype)); var0 = associate_trees (loc, var0, minus_con0,
MINUS_EXPR, atype);
else else
{ gcc_unreachable ();
con0 = associate_trees (loc, con0, minus_lit0, minus_con0 = 0;
MINUS_EXPR, atype); }
return
fold_convert_loc (loc, type, /* Eliminate minus_var0. */
associate_trees (loc, var0, con0, if (minus_var0)
PLUS_EXPR, atype)); {
} if (con0)
con0 = associate_trees (loc, con0, minus_var0,
MINUS_EXPR, atype);
else
gcc_unreachable ();
minus_var0 = 0;
} }
con0 = associate_trees (loc, con0, lit0, code, atype);
return return
fold_convert_loc (loc, type, associate_trees (loc, var0, con0, fold_convert_loc (loc, type, associate_trees (loc, var0, con0,
code, atype)); code, atype));
......
2017-08-03 Richard Biener <rguenther@suse.de>
PR middle-end/81148
* c-c++-common/ubsan/pr81148.c: New testcase.
2017-08-03 Tom de Vries <tom@codesourcery.com> 2017-08-03 Tom de Vries <tom@codesourcery.com>
PR target/81662 PR target/81662
......
/* { dg-do run } */
/* { dg-options "-fsanitize=undefined -fsanitize-undefined-trap-on-error" } */
int x = -106;
int main()
{
// -123 - (0x8000000000000000 - -1)
return (-123 - ((9223372036854775806LL ^ ~(x && 1)) - -1)) == 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