While match.pd has been changed to not transform -(-A) to A when the overflow does not wrap or the signed integer ovreflow checking is enabled, fold_negate_expr still happily does such a transformation. That's bad because then we can't detect an overflow, as on the following testcase. But I allowed this transformation for constants, because VRP seems to rely on that (abs_extent_range calls fold_unary).
Bootstrapped/regtested on x86_64-linux, ok for trunk? 2014-11-11 Marek Polacek <pola...@redhat.com> * fold-const.c (fold_unary_loc): Don't call fold_negate_expr when doing signed integer sanitization or when the type overflow wraps. * c-c++-common/ubsan/overflow-negate-3.c: New test. diff --git gcc/fold-const.c gcc/fold-const.c index f3562ff..33311fb 100644 --- gcc/fold-const.c +++ gcc/fold-const.c @@ -7862,9 +7862,15 @@ fold_unary_loc (location_t loc, enum tree_code code, tree type, tree op0) return fold_view_convert_expr (type, op0); case NEGATE_EXPR: - tem = fold_negate_expr (loc, arg0); - if (tem) - return fold_convert_loc (loc, type, tem); + if (TREE_CODE (arg0) == INTEGER_CST + || TREE_CODE (arg0) == REAL_CST + || TYPE_OVERFLOW_WRAPS (type) + || (flag_sanitize & SANITIZE_SI_OVERFLOW) == 0) + { + tem = fold_negate_expr (loc, arg0); + if (tem) + return fold_convert_loc (loc, type, tem); + } return NULL_TREE; case ABS_EXPR: diff --git gcc/testsuite/c-c++-common/ubsan/overflow-negate-3.c gcc/testsuite/c-c++-common/ubsan/overflow-negate-3.c index e69de29..cf4f9bc 100644 --- gcc/testsuite/c-c++-common/ubsan/overflow-negate-3.c +++ gcc/testsuite/c-c++-common/ubsan/overflow-negate-3.c @@ -0,0 +1,17 @@ +/* { dg-do run } */ +/* { dg-options "-fsanitize=signed-integer-overflow" } */ + +#define INT_MIN (-__INT_MAX__ - 1) + +int +main () +{ + volatile int x = INT_MIN; + int y = x; + y = -(-y); + x = y; + return 0; +} + +/* { dg-output "negation of -2147483648 cannot be represented in type 'int'\[^\n\r]*; cast to an unsigned type to negate this value to itself\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*negation of -2147483648 cannot be represented in type 'int'\[^\n\r]*; cast to an unsigned type to negate this value to itself\[^\n\r]*(\n|\r\n|\r)" } */ Marek