summaryrefslogtreecommitdiff
path: root/gcc/fold-const.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/fold-const.c')
-rw-r--r--gcc/fold-const.c42
1 files changed, 30 insertions, 12 deletions
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index f96427f411c..5d38aabf312 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -418,9 +418,11 @@ negate_expr_p (tree t)
&& TYPE_OVERFLOW_WRAPS (type));
case FIXED_CST:
- case NEGATE_EXPR:
return true;
+ case NEGATE_EXPR:
+ return !TYPE_OVERFLOW_SANITIZED (type);
+
case REAL_CST:
/* We want to canonicalize to positive real constants. Pretend
that only negative ones can be easily negated. */
@@ -566,7 +568,9 @@ fold_negate_expr (location_t loc, tree t)
case INTEGER_CST:
tem = fold_negate_const (t, type);
if (TREE_OVERFLOW (tem) == TREE_OVERFLOW (t)
- || !TYPE_OVERFLOW_TRAPS (type))
+ || (!TYPE_OVERFLOW_TRAPS (type)
+ && TYPE_OVERFLOW_WRAPS (type))
+ || (flag_sanitize & SANITIZE_SI_OVERFLOW) == 0)
return tem;
break;
@@ -623,7 +627,9 @@ fold_negate_expr (location_t loc, tree t)
break;
case NEGATE_EXPR:
- return TREE_OPERAND (t, 0);
+ if (!TYPE_OVERFLOW_SANITIZED (type))
+ return TREE_OPERAND (t, 0);
+ break;
case PLUS_EXPR:
if (!HONOR_SIGN_DEPENDENT_ROUNDING (TYPE_MODE (type))
@@ -4732,8 +4738,7 @@ fold_cond_expr_with_comparison (location_t loc, tree type,
case GE_EXPR:
case GT_EXPR:
if (TYPE_UNSIGNED (TREE_TYPE (arg1)))
- arg1 = fold_convert_loc (loc, signed_type_for
- (TREE_TYPE (arg1)), arg1);
+ break;
tem = fold_build1_loc (loc, ABS_EXPR, TREE_TYPE (arg1), arg1);
return pedantic_non_lvalue_loc (loc, fold_convert_loc (loc, type, tem));
case UNLE_EXPR:
@@ -4743,8 +4748,7 @@ fold_cond_expr_with_comparison (location_t loc, tree type,
case LE_EXPR:
case LT_EXPR:
if (TYPE_UNSIGNED (TREE_TYPE (arg1)))
- arg1 = fold_convert_loc (loc, signed_type_for
- (TREE_TYPE (arg1)), arg1);
+ break;
tem = fold_build1_loc (loc, ABS_EXPR, TREE_TYPE (arg1), arg1);
return negate_expr (fold_convert_loc (loc, type, tem));
default:
@@ -8322,9 +8326,14 @@ fold_unary_loc (location_t loc, enum tree_code code, tree type, tree op0)
&& integer_onep (TREE_OPERAND (arg0, 1)))
|| (TREE_CODE (arg0) == PLUS_EXPR
&& integer_all_onesp (TREE_OPERAND (arg0, 1)))))
- return fold_build1_loc (loc, NEGATE_EXPR, type,
- fold_convert_loc (loc, type,
- TREE_OPERAND (arg0, 0)));
+ {
+ /* Perform the negation in ARG0's type and only then convert
+ to TYPE as to avoid introducing undefined behavior. */
+ tree t = fold_build1_loc (loc, NEGATE_EXPR,
+ TREE_TYPE (TREE_OPERAND (arg0, 0)),
+ TREE_OPERAND (arg0, 0));
+ return fold_convert_loc (loc, type, t);
+ }
/* Convert ~(X ^ Y) to ~X ^ Y or X ^ ~Y if ~X or ~Y simplify. */
else if (TREE_CODE (arg0) == BIT_XOR_EXPR
&& (tem = fold_unary_loc (loc, BIT_NOT_EXPR, type,
@@ -10870,14 +10879,20 @@ fold_binary_loc (location_t loc,
}
}
/* A - (-B) -> A + B */
- if (TREE_CODE (arg1) == NEGATE_EXPR)
+ if (TREE_CODE (arg1) == NEGATE_EXPR
+ && (!INTEGRAL_TYPE_P (type)
+ || TYPE_OVERFLOW_WRAPS (type)
+ || (flag_sanitize & SANITIZE_SI_OVERFLOW) == 0))
return fold_build2_loc (loc, PLUS_EXPR, type, op0,
fold_convert_loc (loc, type,
TREE_OPERAND (arg1, 0)));
/* (-A) - B -> (-B) - A where B is easily negated and we can swap. */
if (TREE_CODE (arg0) == NEGATE_EXPR
&& negate_expr_p (arg1)
- && reorder_operands_p (arg0, arg1))
+ && reorder_operands_p (arg0, arg1)
+ && (!INTEGRAL_TYPE_P (type)
+ || TYPE_OVERFLOW_WRAPS (type)
+ || (flag_sanitize & SANITIZE_SI_OVERFLOW) == 0))
return fold_build2_loc (loc, MINUS_EXPR, type,
fold_convert_loc (loc, type,
negate_expr (arg1)),
@@ -11021,6 +11036,9 @@ fold_binary_loc (location_t loc,
/* A - B -> A + (-B) if B is easily negatable. */
if (negate_expr_p (arg1)
+ && (!INTEGRAL_TYPE_P (type)
+ || TYPE_OVERFLOW_WRAPS (type)
+ || (flag_sanitize & SANITIZE_SI_OVERFLOW) == 0)
&& ((FLOAT_TYPE_P (type)
/* Avoid this transformation if B is a positive REAL_CST. */
&& (TREE_CODE (arg1) != REAL_CST