The following fixes PR81097 but not eventually more latent issues in transforming ~x "back" to -x - 1. I want a testcase before fiddling more with this. The following follows the pattern of previous fixes to this function, making sure to do negation in 'type'.
Bootstrapped and tested on x86_64-unknown-linux-gnu, applied to trunk. Richard. 2017-06-20 Richard Biener <rguent...@suse.de> PR middle-end/81097 * fold-const.c (split_tree): Fold to type before negating. * c-c++-common/ubsan/pr81097.c: New testcase. Index: gcc/fold-const.c =================================================================== --- gcc/fold-const.c (revision 249397) +++ gcc/fold-const.c (working copy) @@ -853,9 +853,9 @@ split_tree (location_t loc, tree in, tre && code == PLUS_EXPR) { /* -X - 1 is folded to ~X, undo that here. Do _not_ do this - when IN is constant. */ - *minus_litp = build_one_cst (TREE_TYPE (in)); - var = negate_expr (TREE_OPERAND (in, 0)); + when IN is constant. Convert to TYPE before negating. */ + *minus_litp = build_one_cst (type); + var = negate_expr (fold_convert_loc (loc, type, TREE_OPERAND (in, 0))); } else var = in; Index: gcc/testsuite/c-c++-common/ubsan/pr81097.c =================================================================== --- gcc/testsuite/c-c++-common/ubsan/pr81097.c (nonexistent) +++ gcc/testsuite/c-c++-common/ubsan/pr81097.c (working copy) @@ -0,0 +1,12 @@ +/* { dg-do run } */ +/* { dg-options "-fsanitize=undefined -fsanitize-undefined-trap-on-error" } */ + +unsigned int a = 3309568; +unsigned int b = -1204857327; +short c = -10871; +short x; +int main() +{ + x = ((short)(~a) | ~c) + ((short)(~b) | ~c); + return 0; +}