c-common.c (c_fully_fold_internal): Issue a warning if a binary operation overflows.
authorRichard Sandiford <rdsandiford@googlemail.com>
Sun, 9 Aug 2009 18:38:04 +0000 (18:38 +0000)
committerRichard Sandiford <rsandifo@gcc.gnu.org>
Sun, 9 Aug 2009 18:38:04 +0000 (18:38 +0000)
gcc/
* c-common.c (c_fully_fold_internal): Issue a warning if a binary
operation overflows.  Likewise non-cast unary arithmetic.
If one arm of a conditional expression is always taken,
inhibit evaluation warnings for the other arm.  Likewise inhibit
evaluation warnings for the second && or || operand if the first
operand is enough to determine the result.
* c-typeck.c (build_conditional_expr): Apply the same inhibition
rules here.
(build_binary_op): Prevent duplicate evaluation warnings.

gcc/testsuite/
* gcc.dg/overflow-warn-8.c: New test.

From-SVN: r150594

gcc/ChangeLog
gcc/c-common.c
gcc/c-typeck.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/overflow-warn-8.c [new file with mode: 0644]

index 0be934b5755dd3b487d981d40d151d3aac22de76..c1a92de2ee967fb2708c2a410fa6611301d2d727 100644 (file)
@@ -1,3 +1,15 @@
+2009-08-09  Richard Sandiford  <rdsandiford@googlemail.com>
+
+       * c-common.c (c_fully_fold_internal): Issue a warning if a binary
+       operation overflows.  Likewise non-cast unary arithmetic.
+       If one arm of a conditional expression is always taken,
+       inhibit evaluation warnings for the other arm.  Likewise inhibit
+       evaluation warnings for the second && or || operand if the first
+       operand is enough to determine the result.
+       * c-typeck.c (build_conditional_expr): Apply the same inhibition
+       rules here.
+       (build_binary_op): Prevent duplicate evaluation warnings.
+
 2009-08-09  Richard Sandiford  <rdsandiford@googlemail.com>
 
        * tree-out-of-ssa.c (insert_value_copy_on_edge): If the source
index 0ebb9f1b1f59cc5d3fbc90073ea3a072f61bde31..ee4991ad6238db6f2036b12ca19dd44b91a5731f 100644 (file)
@@ -1133,6 +1133,7 @@ c_fully_fold_internal (tree expr, bool in_init, bool *maybe_const_operands,
   bool op0_const = true, op1_const = true, op2_const = true;
   bool op0_const_self = true, op1_const_self = true, op2_const_self = true;
   bool nowarning = TREE_NO_WARNING (expr);
+  int unused_p;
 
   /* This function is not relevant to C++ because C++ folds while
      parsing, and may need changes to be correct for C++ when C++
@@ -1308,6 +1309,10 @@ c_fully_fold_internal (tree expr, bool in_init, bool *maybe_const_operands,
          : fold_build2_loc (loc, code, TREE_TYPE (expr), op0, op1);
       else
        ret = fold (expr);
+      if (TREE_OVERFLOW_P (ret)
+         && !TREE_OVERFLOW_P (op0)
+         && !TREE_OVERFLOW_P (op1))
+       overflow_warning (EXPR_LOCATION (expr), ret);
       goto out;
 
     case INDIRECT_REF:
@@ -1342,6 +1347,20 @@ c_fully_fold_internal (tree expr, bool in_init, bool *maybe_const_operands,
          TREE_SIDE_EFFECTS (ret) = TREE_SIDE_EFFECTS (expr);
          TREE_THIS_VOLATILE (ret) = TREE_THIS_VOLATILE (expr);
        }
+      switch (code)
+       {
+       case FIX_TRUNC_EXPR:
+       case FLOAT_EXPR:
+       CASE_CONVERT:
+         /* Don't warn about explicit conversions.  We will already
+            have warned about suspect implicit conversions.  */
+         break;
+
+       default:
+         if (TREE_OVERFLOW_P (ret) && !TREE_OVERFLOW_P (op0))
+           overflow_warning (EXPR_LOCATION (expr), ret);
+         break;
+       }
       goto out;
 
     case TRUTH_ANDIF_EXPR:
@@ -1351,7 +1370,14 @@ c_fully_fold_internal (tree expr, bool in_init, bool *maybe_const_operands,
       orig_op0 = op0 = TREE_OPERAND (expr, 0);
       orig_op1 = op1 = TREE_OPERAND (expr, 1);
       op0 = c_fully_fold_internal (op0, in_init, &op0_const, &op0_const_self);
+
+      unused_p = (op0 == (code == TRUTH_ANDIF_EXPR
+                         ? truthvalue_false_node
+                         : truthvalue_true_node));
+      c_inhibit_evaluation_warnings += unused_p;
       op1 = c_fully_fold_internal (op1, in_init, &op1_const, &op1_const_self);
+      c_inhibit_evaluation_warnings -= unused_p;
+
       if (op0 != orig_op0 || op1 != orig_op1 || in_init)
        ret = in_init
          ? fold_build2_initializer_loc (loc, code, TREE_TYPE (expr), op0, op1)
@@ -1380,8 +1406,15 @@ c_fully_fold_internal (tree expr, bool in_init, bool *maybe_const_operands,
       orig_op1 = op1 = TREE_OPERAND (expr, 1);
       orig_op2 = op2 = TREE_OPERAND (expr, 2);
       op0 = c_fully_fold_internal (op0, in_init, &op0_const, &op0_const_self);
+
+      c_inhibit_evaluation_warnings += (op0 == truthvalue_false_node);
       op1 = c_fully_fold_internal (op1, in_init, &op1_const, &op1_const_self);
+      c_inhibit_evaluation_warnings -= (op0 == truthvalue_false_node);
+
+      c_inhibit_evaluation_warnings += (op0 == truthvalue_true_node);
       op2 = c_fully_fold_internal (op2, in_init, &op2_const, &op2_const_self);
+      c_inhibit_evaluation_warnings -= (op0 == truthvalue_true_node);
+
       if (op0 != orig_op0 || op1 != orig_op1 || op2 != orig_op2)
        ret = fold_build3_loc (loc, code, TREE_TYPE (expr), op0, op1, op2);
       else
index 42bebe3543cbc04a8bd091a9c7d604317ee7d1ef..01cdcd201fe042af249298791ad7060347f0a922 100644 (file)
@@ -3912,10 +3912,19 @@ build_conditional_expr (location_t colon_loc, tree ifexp, bool ifexp_bcp,
                     that folding in this case even without
                     warn_sign_compare to avoid warning options
                     possibly affecting code generation.  */
+                 c_inhibit_evaluation_warnings
+                   += (ifexp == truthvalue_false_node);
                  op1 = c_fully_fold (op1, require_constant_value,
                                      &op1_maybe_const);
+                 c_inhibit_evaluation_warnings
+                   -= (ifexp == truthvalue_false_node);
+
+                 c_inhibit_evaluation_warnings
+                   += (ifexp == truthvalue_true_node);
                  op2 = c_fully_fold (op2, require_constant_value,
                                      &op2_maybe_const);
+                 c_inhibit_evaluation_warnings
+                   -= (ifexp == truthvalue_true_node);
 
                  if (warn_sign_compare)
                    {
@@ -9509,10 +9518,12 @@ build_binary_op (location_t location, enum tree_code code,
                     build_conditional_expr.  This requires the
                     "original" values to be folded, not just op0 and
                     op1.  */
+                 c_inhibit_evaluation_warnings++;
                  op0 = c_fully_fold (op0, require_constant_value,
                                      &op0_maybe_const);
                  op1 = c_fully_fold (op1, require_constant_value,
                                      &op1_maybe_const);
+                 c_inhibit_evaluation_warnings--;
                  orig_op0_folded = c_fully_fold (orig_op0,
                                                  require_constant_value,
                                                  NULL);
index 346cc709133e5abd6ae9f59f7876bb8843cbabe4..dbb473d1b9658bd8ee88ea1736e7a9d2cb31882f 100644 (file)
@@ -1,3 +1,7 @@
+2009-08-09  Richard Sandiford  <rdsandiford@googlemail.com>
+
+       * gcc.dg/overflow-warn-8.c: New test.
+
 2009-08-09  Ira Rosen  <irar@il.ibm.com>
 
        PR tree-optimization/41008
diff --git a/gcc/testsuite/gcc.dg/overflow-warn-8.c b/gcc/testsuite/gcc.dg/overflow-warn-8.c
new file mode 100644 (file)
index 0000000..43ecda0
--- /dev/null
@@ -0,0 +1,23 @@
+#include <limits.h>
+
+void foo (int j)
+{
+  int i1 = (int)(double)1.0 + INT_MAX; /* { dg-warning "integer overflow" } */
+  int i2 = (int)(double)1 + INT_MAX; /* { dg-warning "integer overflow" } */
+  int i3 = 1 + INT_MAX; /* { dg-warning "integer overflow" } */
+  int i4 = +1 + INT_MAX; /* { dg-warning "integer overflow" } */
+  int i5 = (int)((double)1.0 + INT_MAX);
+  int i6 = (double)1.0 + INT_MAX; /* { dg-warning "overflow in implicit constant" } */
+  int i7 = 0 ? (int)(double)1.0 + INT_MAX : 1;
+  int i8 = 1 ? 1 : (int)(double)1.0 + INT_MAX;
+  int i9 = j ? (int)(double)1.0 + INT_MAX : 1; /* { dg-warning "integer overflow" } */
+  unsigned int i10 = 0 ? (int)(double)1.0 + INT_MAX : 9U;
+  unsigned int i11 = 1 ? 9U : (int)(double)1.0 + INT_MAX;
+  unsigned int i12 = j ? (int)(double)1.0 + INT_MAX : 9U; /* { dg-warning "integer overflow" } */
+  int i13 = 1 || (int)(double)1.0 + INT_MAX < 0;
+  int i14 = 0 && (int)(double)1.0 + INT_MAX < 0;
+  int i15 = 0 || (int)(double)1.0 + INT_MAX < 0; /* { dg-warning "integer overflow" } */
+  int i16 = 1 && (int)(double)1.0 + INT_MAX < 0; /* { dg-warning "integer overflow" } */
+  int i17 = j || (int)(double)1.0 + INT_MAX < 0; /* { dg-warning "integer overflow" } */
+  int i18 = j && (int)(double)1.0 + INT_MAX < 0; /* { dg-warning "integer overflow" } */
+}