diff options
author | Richard Sandiford <rdsandiford@googlemail.com> | 2009-08-09 18:38:04 +0000 |
---|---|---|
committer | Richard Sandiford <rsandifo@gcc.gnu.org> | 2009-08-09 18:38:04 +0000 |
commit | f517845606b6b8290b52f2068775a9325eceff6b (patch) | |
tree | 4f384af8342874e6f72150b4b11a160bb03fa4be | |
parent | 8f048d2f21ea75e65fe9000cd9f7c1cfbbb7788a (diff) | |
download | gcc-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/ChangeLog | 12 | ||||
-rw-r--r-- | gcc/c-common.c | 33 | ||||
-rw-r--r-- | gcc/c-typeck.c | 11 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 4 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/overflow-warn-8.c | 23 |
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" } */ +} |