The code in fold_comparison calls save_expr on an expression and then tries to
set a location of the expression.  But since save_expr calls fold, it can
produce an integer constant, so we must be more careful when setting its
location.  In this case we had

  (int) a > 646

where 'a' is signed char so we fold it to 0.

Bootstrapped/regtested on x86_64-linux, ok for trunk/6?

2017-03-27  Marek Polacek  <pola...@redhat.com>

        PR sanitizer/80067
        * fold-const.c (fold_comparison): Use protected_set_expr_location
        instead of SET_EXPR_LOCATION.

        * c-c++-common/ubsan/shift-10.c: New test.

diff --git gcc/fold-const.c gcc/fold-const.c
index 1a9a264..6db16b5 100644
--- gcc/fold-const.c
+++ gcc/fold-const.c
@@ -8704,7 +8704,7 @@ fold_comparison (location_t loc, enum tree_code code, 
tree type,
              if (save_p)
                {
                  tem = save_expr (build2 (code, type, cval1, cval2));
-                 SET_EXPR_LOCATION (tem, loc);
+                 protected_set_expr_location (tem, loc);
                  return tem;
                }
              return fold_build2_loc (loc, code, type, cval1, cval2);
diff --git gcc/testsuite/c-c++-common/ubsan/shift-10.c 
gcc/testsuite/c-c++-common/ubsan/shift-10.c
index e69de29..9202fcc 100644
--- gcc/testsuite/c-c++-common/ubsan/shift-10.c
+++ gcc/testsuite/c-c++-common/ubsan/shift-10.c
@@ -0,0 +1,10 @@
+/* PR sanitizer/80067 */
+/* { dg-do compile } */
+/* { dg-options "-fsanitize=shift" } */
+
+extern signed char a;
+void
+foo ()
+{
+  0 << ((647 > a) - 1);
+}

        Marek

Reply via email to