Left shifts into the sign bit is a kind of overflow, and the standard chooses to treat left shifts of negative values the same way.
However, the -fwrapv option modifies the language to one where integers are defined as two's complement---which also defines entirely the behavior of shifts. Disable sanitization of left shifts when -fwrapv is in effect. The same change was proposed for LLVM at https://llvm.org/bugs/show_bug.cgi?id=25552. Bootstrapped/regtested x86_64-pc-linux-gnu. Ok for trunk, and for GCC 5 branch after 5.3 is released? Thanks, Paolo gcc: PR sanitizer/68418 * c-family/c-ubsan.c (ubsan_instrument_shift): Disable sanitization of left shifts for wrapping signed types as well. gcc/testsuite: PR sanitizer/68418 * gcc.dg/ubsan/c99-wrapv-shift-1.c, gcc.dg/ubsan/c99-wrapv-shift-2.c: New testcases. Index: c-family/c-ubsan.c =================================================================== --- c-family/c-ubsan.c (revision 230466) +++ c-family/c-ubsan.c (working copy) @@ -128,7 +128,7 @@ (unsigned) x >> (uprecm1 - y) if non-zero, is undefined. */ if (code == LSHIFT_EXPR - && !TYPE_UNSIGNED (type0) + && !TYPE_OVERFLOW_WRAPS (type0) && flag_isoc99) { tree x = fold_build2 (MINUS_EXPR, op1_utype, uprecm1, @@ -143,7 +143,7 @@ x < 0 || ((unsigned) x >> (uprecm1 - y)) if > 1, is undefined. */ if (code == LSHIFT_EXPR - && !TYPE_UNSIGNED (type0) + && !TYPE_OVERFLOW_WRAPS (type0) && (cxx_dialect >= cxx11)) { tree x = fold_build2 (MINUS_EXPR, op1_utype, uprecm1, Index: testsuite/gcc.dg/ubsan/c99-wrapv-shift-1.c =================================================================== --- testsuite/gcc.dg/ubsan/c99-wrapv-shift-1.c (revision 0) +++ testsuite/gcc.dg/ubsan/c99-wrapv-shift-1.c (working copy) @@ -0,0 +1,9 @@ +/* { dg-do run } */ +/* { dg-options "-fsanitize=shift -fwrapv -w -std=c99" } */ + +int +main (void) +{ + int a = -42; + a << 1; +} Index: testsuite/gcc.dg/ubsan/c99-wrapv-shift-2.c =================================================================== --- testsuite/gcc.dg/ubsan/c99-wrapv-shift-2.c (revision 0) +++ testsuite/gcc.dg/ubsan/c99-wrapv-shift-2.c (working copy) @@ -0,0 +1,9 @@ +/* { dg-do run } */ +/* { dg-options "-fsanitize=shift -fwrapv -w -std=c99" } */ + +int +main (void) +{ + int a = 1; + a <<= 31; +}