aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Sandiford <rdsandiford@googlemail.com>2009-08-09 18:38:04 +0000
committerRichard Sandiford <rsandifo@gcc.gnu.org>2009-08-09 18:38:04 +0000
commitf517845606b6b8290b52f2068775a9325eceff6b (patch)
tree4f384af8342874e6f72150b4b11a160bb03fa4be
parent8f048d2f21ea75e65fe9000cd9f7c1cfbbb7788a (diff)
downloadgcc-f517845606b6b8290b52f2068775a9325eceff6b.zip
gcc-f517845606b6b8290b52f2068775a9325eceff6b.tar.gz
gcc-f517845606b6b8290b52f2068775a9325eceff6b.tar.bz2
c-common.c (c_fully_fold_internal): Issue a warning if a binary operation overflows.
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
-rw-r--r--gcc/ChangeLog12
-rw-r--r--gcc/c-common.c33
-rw-r--r--gcc/c-typeck.c11
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/gcc.dg/overflow-warn-8.c23
5 files changed, 83 insertions, 0 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 0be934b..c1a92de 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,17 @@
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
and destination have different modes, Use promote_mode to
determine the signedness of the conversion. Assert that the
diff --git a/gcc/c-common.c b/gcc/c-common.c
index 0ebb9f1..ee4991a 100644
--- a/gcc/c-common.c
+++ b/gcc/c-common.c
@@ -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
diff --git a/gcc/c-typeck.c b/gcc/c-typeck.c
index 42bebe3..01cdcd2 100644
--- a/gcc/c-typeck.c
+++ b/gcc/c-typeck.c
@@ -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);
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 346cc70..dbb473d 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
index 0000000..43ecda0
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/overflow-warn-8.c
@@ -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" } */
+}