The problem in this PR is that we were leaking C_MAYBE_CONST_EXPRs into the
gimplifier.  It was created in the float-cast instrumentation in convert().

Fixed by using the fully-folded EXPR only, thus without C_MAYBE_CONST_EXPR.
Which means that we can drop a parameter of ubsan_instrument_float_cast.
Seems that this doesn't hurt the diagnostics.

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

2016-01-05  Marek Polacek  <pola...@redhat.com>

        PR sanitizer/69099
        * c-convert.c (convert) [INTEGER_TYPE]: Drop ARG.  Don't pass ARG to
        ubsan_instrument_float_cast.  Fold EXPR.

        * convert.c (convert_to_integer_1): Adjust call to
        ubsan_instrument_float_cast.
        * ubsan.c (ubsan_instrument_float_cast): Drop the ARG parameter.  Use
        EXPR instead of ARG.
        * ubsan.h (ubsan_instrument_float_cast): Adjust declaration.

        * gcc.dg/ubsan/float-cast-overflow-atomic.c: New test.

diff --git gcc/c/c-convert.c gcc/c/c-convert.c
index 5ee52eb..4167c34 100644
--- gcc/c/c-convert.c
+++ gcc/c/c-convert.c
@@ -111,20 +111,16 @@ convert (tree type, tree expr)
          && COMPLETE_TYPE_P (type)
          && do_ubsan_in_current_function ())
        {
-         tree arg;
          if (in_late_binary_op)
-           {
-             expr = save_expr (expr);
-             arg = expr;
-           }
+           expr = save_expr (expr);
          else
            {
              expr = c_save_expr (expr);
-             arg = c_fully_fold (expr, false, NULL);
+             expr = c_fully_fold (expr, false, NULL);
            }
-         tree check = ubsan_instrument_float_cast (loc, type, expr, arg);
+         tree check = ubsan_instrument_float_cast (loc, type, expr);
          expr = fold_build1 (FIX_TRUNC_EXPR, type, expr);
-         if (check == NULL)
+         if (check == NULL_TREE)
            return expr;
          return fold_build2 (COMPOUND_EXPR, TREE_TYPE (expr), check, expr);
        }
diff --git gcc/convert.c gcc/convert.c
index 4b1e1f1..dd7d818 100644
--- gcc/convert.c
+++ gcc/convert.c
@@ -920,9 +920,9 @@ convert_to_integer_1 (tree type, tree expr, bool dofold)
          && do_ubsan_in_current_function ())
        {
          expr = save_expr (expr);
-         tree check = ubsan_instrument_float_cast (loc, type, expr, expr);
+         tree check = ubsan_instrument_float_cast (loc, type, expr);
          expr = build1 (FIX_TRUNC_EXPR, type, expr);
-         if (check == NULL)
+         if (check == NULL_TREE)
            return expr;
          return maybe_fold_build2_loc (dofold, loc, COMPOUND_EXPR,
                                        TREE_TYPE (expr), check, expr);
diff --git gcc/testsuite/gcc.dg/ubsan/float-cast-overflow-atomic.c 
gcc/testsuite/gcc.dg/ubsan/float-cast-overflow-atomic.c
index e69de29..0a4fa01 100644
--- gcc/testsuite/gcc.dg/ubsan/float-cast-overflow-atomic.c
+++ gcc/testsuite/gcc.dg/ubsan/float-cast-overflow-atomic.c
@@ -0,0 +1,171 @@
+/* PR sanitizer/69099 */
+/* { dg-do compile } */
+/* { dg-options "-std=c11 -pedantic-errors -fsanitize=float-cast-overflow" } */
+/* This is gcc.dg/atomic/c11-atomic-exec-2.c.  */
+
+extern void abort (void);
+extern void exit (int);
+
+#define CMPLX(X, Y) __builtin_complex ((X), (Y))
+
+#define TEST_COMPOUND(TYPE, LHSVAL, RHSVAL, OP)                                
\
+  do                                                                   \
+    {                                                                  \
+      static volatile _Atomic (TYPE) a = (TYPE) (LHSVAL);              \
+      if ((a OP##= (RHSVAL)) != (TYPE) ((TYPE) (LHSVAL) OP (RHSVAL)))  \
+       abort ();                                                       \
+      if (a != (TYPE) ((TYPE) (LHSVAL) OP (RHSVAL)))                   \
+       abort ();                                                       \
+    }                                                                  \
+  while (0)
+
+#define TEST_COMPOUND_ARITH(LHSVAL, RHSVAL, OP)                                
\
+  do                                                                   \
+    {                                                                  \
+      TEST_COMPOUND (_Bool, (LHSVAL), (RHSVAL), OP);                   \
+      TEST_COMPOUND (char, (LHSVAL), (RHSVAL), OP);                    \
+      TEST_COMPOUND (signed char, (LHSVAL), (RHSVAL), OP);             \
+      TEST_COMPOUND (unsigned char, (LHSVAL), (RHSVAL), OP);           \
+      TEST_COMPOUND (signed short, (LHSVAL), (RHSVAL), OP);            \
+      TEST_COMPOUND (unsigned short, (LHSVAL), (RHSVAL), OP);          \
+      TEST_COMPOUND (signed int, (LHSVAL), (RHSVAL), OP);              \
+      TEST_COMPOUND (unsigned int, (LHSVAL), (RHSVAL), OP);            \
+      TEST_COMPOUND (signed long, (LHSVAL), (RHSVAL), OP);             \
+      TEST_COMPOUND (unsigned long, (LHSVAL), (RHSVAL), OP);           \
+      TEST_COMPOUND (signed long long, (LHSVAL), (RHSVAL), OP);                
\
+      TEST_COMPOUND (unsigned long long, (LHSVAL), (RHSVAL), OP);      \
+      TEST_COMPOUND (float, (LHSVAL), (RHSVAL), OP);                   \
+      TEST_COMPOUND (double, (LHSVAL), (RHSVAL), OP);                  \
+      TEST_COMPOUND (long double, (LHSVAL), (RHSVAL), OP);             \
+      TEST_COMPOUND (_Complex float, (LHSVAL), (RHSVAL), OP);          \
+      TEST_COMPOUND (_Complex double, (LHSVAL), (RHSVAL), OP);         \
+      TEST_COMPOUND (_Complex long double, (LHSVAL), (RHSVAL), OP);    \
+    }                                                                  \
+  while (0)
+
+#define TEST_COMPOUND_INT(LHSVAL, RHSVAL, OP)                          \
+  do                                                                   \
+    {                                                                  \
+      TEST_COMPOUND (_Bool, (LHSVAL), (RHSVAL), OP);                   \
+      TEST_COMPOUND (char, (LHSVAL), (RHSVAL), OP);                    \
+      TEST_COMPOUND (signed char, (LHSVAL), (RHSVAL), OP);             \
+      TEST_COMPOUND (unsigned char, (LHSVAL), (RHSVAL), OP);           \
+      TEST_COMPOUND (signed short, (LHSVAL), (RHSVAL), OP);            \
+      TEST_COMPOUND (unsigned short, (LHSVAL), (RHSVAL), OP);          \
+      TEST_COMPOUND (signed int, (LHSVAL), (RHSVAL), OP);              \
+      TEST_COMPOUND (unsigned int, (LHSVAL), (RHSVAL), OP);            \
+      TEST_COMPOUND (signed long, (LHSVAL), (RHSVAL), OP);             \
+      TEST_COMPOUND (unsigned long, (LHSVAL), (RHSVAL), OP);           \
+      TEST_COMPOUND (signed long long, (LHSVAL), (RHSVAL), OP);                
\
+      TEST_COMPOUND (unsigned long long, (LHSVAL), (RHSVAL), OP);      \
+    }                                                                  \
+  while (0)
+
+static void
+test_mult (void)
+{
+  TEST_COMPOUND_ARITH (1, 2, *);
+  TEST_COMPOUND_ARITH (-3, 5, *);
+  TEST_COMPOUND_ARITH (-7, -20, *);
+  TEST_COMPOUND_ARITH (1.25, 3.5, *);
+  TEST_COMPOUND_ARITH (CMPLX (1.5, 2.5), CMPLX (3.5, 4.5), *);
+  TEST_COMPOUND_ARITH (CMPLX (1.5, 2.5), 2, *);
+}
+
+static void
+test_div (void)
+{
+  TEST_COMPOUND_ARITH (1, 2, /);
+  TEST_COMPOUND_ARITH (-6, 3, /);
+  TEST_COMPOUND_ARITH (-70, -10, /);
+  TEST_COMPOUND_ARITH (1.25, 2.5, /);
+  TEST_COMPOUND_ARITH (CMPLX (1.0, 1.0), CMPLX (0.5, 0.5), /);
+  TEST_COMPOUND_ARITH (CMPLX (1.5, 2.5), 2, /);
+}
+
+static void
+test_mod (void)
+{
+  TEST_COMPOUND_INT (1, 2, %);
+  TEST_COMPOUND_INT (-3, 5, %);
+  TEST_COMPOUND_INT (-7, -2, %);
+}
+
+static void
+test_plus (void)
+{
+  TEST_COMPOUND_ARITH (1, 2, +);
+  TEST_COMPOUND_ARITH (-3, 5, +);
+  TEST_COMPOUND_ARITH (-7, -20, +);
+  TEST_COMPOUND_ARITH (1.25, 3.5, +);
+  TEST_COMPOUND_ARITH (CMPLX (1.5, 2.5), CMPLX (3.5, 4.5), +);
+  TEST_COMPOUND_ARITH (CMPLX (1.5, 2.5), 2, +);
+  static int ia[2];
+  TEST_COMPOUND (int *, &ia[1], 1, +);
+  TEST_COMPOUND (int *, &ia[1], -1, +);
+}
+
+static void
+test_minus (void)
+{
+  TEST_COMPOUND_ARITH (1, 2, -);
+  TEST_COMPOUND_ARITH (-3, 5, -);
+  TEST_COMPOUND_ARITH (-7, -20, -);
+  TEST_COMPOUND_ARITH (3.5, 1.25, -);
+  TEST_COMPOUND_ARITH (CMPLX (3.5, 4.5), CMPLX (1.5, 2.5), -);
+  TEST_COMPOUND_ARITH (CMPLX (3.5, 2.5), 2, -);
+  static int ia[2];
+  TEST_COMPOUND (int *, &ia[1], 1, -);
+  TEST_COMPOUND (int *, &ia[1], -1, -);
+}
+
+static void
+test_lshift (void)
+{
+  TEST_COMPOUND_INT (1, 7, <<);
+  TEST_COMPOUND_INT (15, 3, <<);
+}
+
+static void
+test_rshift (void)
+{
+  TEST_COMPOUND_INT (1, 1, >>);
+  TEST_COMPOUND_INT (127, 4, >>);
+}
+
+static void
+test_and (void)
+{
+  TEST_COMPOUND_INT (0x1234, 0x7856, &);
+  TEST_COMPOUND_INT (-1, 0x12345678, &);
+}
+
+static void
+test_xor (void)
+{
+  TEST_COMPOUND_INT (0x1234, 0x7856, ^);
+  TEST_COMPOUND_INT (-1, 0x12345678, ^);
+}
+
+static void
+test_or (void)
+{
+  TEST_COMPOUND_INT (0x1234, 0x7856, |);
+  TEST_COMPOUND_INT (-12345, 0x12345678, |);
+}
+
+int
+main (void)
+{
+  test_mult ();
+  test_div ();
+  test_mod ();
+  test_plus ();
+  test_minus ();
+  test_lshift ();
+  test_rshift ();
+  test_and ();
+  test_xor ();
+  test_or ();
+  exit (0);
+}
diff --git gcc/ubsan.c gcc/ubsan.c
index e5b49b2..d3fbfd1 100644
--- gcc/ubsan.c
+++ gcc/ubsan.c
@@ -1478,18 +1478,18 @@ ubsan_use_new_style_p (location_t loc)
 }
 
 /* Instrument float point-to-integer conversion.  TYPE is an integer type of
-   destination, EXPR is floating-point expression.  ARG is what to pass
-   the libubsan call as value, often EXPR itself.  */
+   destination, EXPR is floating-point expression.  */
 
 tree
-ubsan_instrument_float_cast (location_t loc, tree type, tree expr, tree arg)
+ubsan_instrument_float_cast (location_t loc, tree type, tree expr)
 {
   tree expr_type = TREE_TYPE (expr);
   tree t, tt, fn, min, max;
   machine_mode mode = TYPE_MODE (expr_type);
   int prec = TYPE_PRECISION (type);
   bool uns_p = TYPE_UNSIGNED (type);
-  if (!loc) loc = input_location;
+  if (loc == UNKNOWN_LOCATION)
+    loc = input_location;
 
   /* Float to integer conversion first truncates toward zero, so
      even signed char c = 127.875f; is not problematic.
@@ -1609,7 +1609,7 @@ ubsan_instrument_float_cast (location_t loc, tree type, 
tree expr, tree arg)
       fn = builtin_decl_explicit (bcode);
       fn = build_call_expr_loc (loc, fn, 2,
                                build_fold_addr_expr_loc (loc, data),
-                               ubsan_encode_value (arg, false));
+                               ubsan_encode_value (expr, false));
     }
 
   return fold_build3 (COND_EXPR, void_type_node, t, fn, integer_zero_node);
diff --git gcc/ubsan.h gcc/ubsan.h
index d272d62..c66d0af 100644
--- gcc/ubsan.h
+++ gcc/ubsan.h
@@ -53,7 +53,7 @@ extern tree ubsan_type_descriptor (tree, enum 
ubsan_print_style = UBSAN_PRINT_NO
 extern tree ubsan_encode_value (tree, bool = false);
 extern bool is_ubsan_builtin_p (tree);
 extern tree ubsan_build_overflow_builtin (tree_code, location_t, tree, tree, 
tree);
-extern tree ubsan_instrument_float_cast (location_t, tree, tree, tree);
+extern tree ubsan_instrument_float_cast (location_t, tree, tree);
 extern tree ubsan_get_source_location_type (void);
 
 #endif  /* GCC_UBSAN_H  */

        Marek

Reply via email to