From: mpolacek Date: Thu, 23 Oct 2014 13:02:02 +0000 (+0000) Subject: * c-ubsan.c (ubsan_instrument_shift): Perform the MINUS_EXPR X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=e7ec033a9fac71f3f8d95adb2b404738b5c0a616;p=thirdparty%2Fgcc.git * c-ubsan.c (ubsan_instrument_shift): Perform the MINUS_EXPR in unsigned type. * c-c++-common/ubsan/undefined-2.c: New test. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@216593 138bc75d-0d04-0410-961f-82ee72b054a4 --- diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog index f95866c729a9..05254c81a1ea 100644 --- a/gcc/c-family/ChangeLog +++ b/gcc/c-family/ChangeLog @@ -1,3 +1,8 @@ +2014-10-23 Marek Polacek + + * c-ubsan.c (ubsan_instrument_shift): Perform the MINUS_EXPR + in unsigned type. + 2014-10-22 Jakub Jelinek Yury Gribov diff --git a/gcc/c-family/c-ubsan.c b/gcc/c-family/c-ubsan.c index 5a42303c14ab..7f4dc258e01c 100644 --- a/gcc/c-family/c-ubsan.c +++ b/gcc/c-family/c-ubsan.c @@ -128,19 +128,19 @@ ubsan_instrument_shift (location_t loc, enum tree_code code, tree op1_utype = unsigned_type_for (type1); HOST_WIDE_INT op0_prec = TYPE_PRECISION (type0); tree uprecm1 = build_int_cst (op1_utype, op0_prec - 1); - tree precm1 = build_int_cst (type1, op0_prec - 1); t = fold_convert_loc (loc, op1_utype, op1); t = fold_build2 (GT_EXPR, boolean_type_node, t, uprecm1); /* For signed x << y, in C99/C11, the following: - (unsigned) x >> (precm1 - y) + (unsigned) x >> (uprecm1 - y) if non-zero, is undefined. */ if (code == LSHIFT_EXPR && !TYPE_UNSIGNED (type0) && flag_isoc99) { - tree x = fold_build2 (MINUS_EXPR, integer_type_node, precm1, op1); + tree x = fold_build2 (MINUS_EXPR, unsigned_type_node, uprecm1, + fold_convert (op1_utype, op1)); tt = fold_convert_loc (loc, unsigned_type_for (type0), op0); tt = fold_build2 (RSHIFT_EXPR, TREE_TYPE (tt), tt, x); tt = fold_build2 (NE_EXPR, boolean_type_node, tt, @@ -148,13 +148,14 @@ ubsan_instrument_shift (location_t loc, enum tree_code code, } /* For signed x << y, in C++11 and later, the following: - x < 0 || ((unsigned) x >> (precm1 - y)) + x < 0 || ((unsigned) x >> (uprecm1 - y)) if > 1, is undefined. */ if (code == LSHIFT_EXPR && !TYPE_UNSIGNED (TREE_TYPE (op0)) && (cxx_dialect >= cxx11)) { - tree x = fold_build2 (MINUS_EXPR, integer_type_node, precm1, op1); + tree x = fold_build2 (MINUS_EXPR, unsigned_type_node, uprecm1, + fold_convert (op1_utype, op1)); tt = fold_convert_loc (loc, unsigned_type_for (type0), op0); tt = fold_build2 (RSHIFT_EXPR, TREE_TYPE (tt), tt, x); tt = fold_build2 (GT_EXPR, boolean_type_node, tt, diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index a3f1308ebc49..701fadbd26e6 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2014-10-23 Marek Polacek + + * c-c++-common/ubsan/undefined-2.c: New test. + 2014-10-10 Kirill Yukhin * gcc.target/i386/pr63600.c: New. diff --git a/gcc/testsuite/c-c++-common/ubsan/undefined-2.c b/gcc/testsuite/c-c++-common/ubsan/undefined-2.c new file mode 100644 index 000000000000..05dea4467452 --- /dev/null +++ b/gcc/testsuite/c-c++-common/ubsan/undefined-2.c @@ -0,0 +1,22 @@ +/* { dg-do run } */ +/* { dg-options "-fsanitize=undefined -fno-sanitize-recover=signed-integer-overflow" } */ +/* { dg-additional-options "-std=gnu11" { target c } } */ +/* { dg-additional-options "-std=c++11" { target c++ } } */ + +volatile int w, z; + +__attribute__ ((noinline, noclone)) int +foo (int x, int y) +{ + z++; + return x << y; +} + +int +main () +{ + w = foo (0, -__INT_MAX__); + return 0; +} + +/* { dg-output "shift exponent -\[^\n\r]* is negative\[^\n\r]*(\n|\r\n|\r)" } */