Message ID | 20141111174025.GI10852@redhat.com |
---|---|
State | New |
Headers | show |
On Tue, Nov 11, 2014 at 06:40:25PM +0100, Marek Polacek wrote: > --- 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); > + } a) if arg0 is INTEGER_CST, but e.g. INT_MIN, should we really fold it for -fsanitize=signed-integer-overflow (I'd say in that case we should fold only if it is not the minimum value) b) if the argument is not INTEGRAL_TYPE_P (type), shouldn't we fold no matter what flag_sanitize says? Is the REAL_CST case needed in that case? Jakub
On November 11, 2014 6:49:34 PM CET, Jakub Jelinek <jakub@redhat.com> wrote: >On Tue, Nov 11, 2014 at 06:40:25PM +0100, Marek Polacek wrote: >> --- 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); >> + } > >a) if arg0 is INTEGER_CST, but e.g. INT_MIN, should we > really fold it for -fsanitize=signed-integer-overflow > (I'd say in that case we should fold only if it is not > the minimum value) Right. I think you should fix VRP instead. >b) if the argument is not INTEGRAL_TYPE_P (type), shouldn't > we fold no matter what flag_sanitize says? Is the REAL_CST > case needed in that case? Yes and no I guess. Richard. > Jakub
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)" } */