From: Marek Polacek Date: Thu, 23 Oct 2014 13:02:02 +0000 (+0000) Subject: c-ubsan.c (ubsan_instrument_shift): Perform the MINUS_EXPR in unsigned type. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=59d7607aec61d173914f2af06097cd46d10d3504;p=gcc.git c-ubsan.c (ubsan_instrument_shift): Perform the MINUS_EXPR in unsigned type. * c-ubsan.c (ubsan_instrument_shift): Perform the MINUS_EXPR in unsigned type. * c-c++-common/ubsan/undefined-2.c: New test. From-SVN: r216593 --- diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog index f95866c729a..05254c81a1e 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 5a42303c14a..7f4dc258e01 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 a3f1308ebc4..701fadbd26e 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 00000000000..05dea446745 --- /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)" } */