From: manu Date: Fri, 5 Jan 2007 21:57:01 +0000 (+0000) Subject: 2007-01-05 Manuel Lopez-Ibanez X-Git-Url: http://git.sourceforge.jp/view?p=pf3gnuchains%2Fgcc-fork.git;a=commitdiff_plain;h=f170d67f55d3a7c6d2025fb2d4e1e743c00cd83e 2007-01-05 Manuel Lopez-Ibanez PR c/19978 * tree.h (TREE_OVERFLOW_P): New. * c-typeck.c (parser_build_unary_op): Warn only if result overflowed and operands did not. (parser_build_binary_op): Likewise. (convert_for_assignment): Remove redundant overflow_warning. * c-common.c (overflow_warning): Don't check or set TREE_OVERFLOW. cp/ * semantics.c (finish_unary_op_expr): Warn only if result overflowed and operands did not. testsuite/ * gcc.dg/multiple-overflow-warn-1.c: New. * gcc.dg/multiple-overflow-warn-2.c: New. * gcc.dg/overflow-warn-6.c: New. * g++.dg/warn/multiple-overflow-warn-1.C: New. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@120505 138bc75d-0d04-0410-961f-82ee72b054a4 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 5838242a17e..7b0bbd5b3fa 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,15 @@ 2007-01-05 Manuel Lopez-Ibanez + PR c/19978 + * tree.h (TREE_OVERFLOW_P): New. + * c-typeck.c (parser_build_unary_op): Warn only if result + overflowed and operands did not. + (parser_build_binary_op): Likewise. + (convert_for_assignment): Remove redundant overflow_warning. + * c-common.c (overflow_warning): Don't check or set TREE_OVERFLOW. + +2007-01-05 Manuel Lopez-Ibanez + * c-typeck.c (store_init_value): Split over two lines to follow the GNU coding style. diff --git a/gcc/c-common.c b/gcc/c-common.c index 1794bd8642e..8fb9541f168 100644 --- a/gcc/c-common.c +++ b/gcc/c-common.c @@ -920,39 +920,45 @@ constant_expression_warning (tree value) pedwarn ("overflow in constant expression"); } -/* Print a warning if an expression had overflow in folding. +/* Print a warning if an expression had overflow in folding and its + operands hadn't. + Invoke this function on every expression that (1) appears in the source code, and - (2) might be a constant expression that overflowed, and + (2) is a constant expression that overflowed, and (3) is not already checked by convert_and_check; - however, do not invoke this function on operands of explicit casts. */ + however, do not invoke this function on operands of explicit casts + or when the expression is the result of an operator and any operand + already overflowed. */ void overflow_warning (tree value) { - if ((TREE_CODE (value) == INTEGER_CST - || (TREE_CODE (value) == COMPLEX_CST - && TREE_CODE (TREE_REALPART (value)) == INTEGER_CST)) - && TREE_OVERFLOW (value)) - { - TREE_OVERFLOW (value) = 0; - if (skip_evaluation == 0) - warning (OPT_Woverflow, "integer overflow in expression"); - } - else if ((TREE_CODE (value) == REAL_CST - || (TREE_CODE (value) == COMPLEX_CST - && TREE_CODE (TREE_REALPART (value)) == REAL_CST)) - && TREE_OVERFLOW (value)) - { - TREE_OVERFLOW (value) = 0; - if (skip_evaluation == 0) - warning (OPT_Woverflow, "floating point overflow in expression"); - } - else if (TREE_CODE (value) == VECTOR_CST && TREE_OVERFLOW (value)) + if (skip_evaluation) return; + + switch (TREE_CODE (value)) { - TREE_OVERFLOW (value) = 0; - if (skip_evaluation == 0) - warning (OPT_Woverflow, "vector overflow in expression"); + case INTEGER_CST: + warning (OPT_Woverflow, "integer overflow in expression"); + break; + + case REAL_CST: + warning (OPT_Woverflow, "floating point overflow in expression"); + break; + + case VECTOR_CST: + warning (OPT_Woverflow, "vector overflow in expression"); + break; + + case COMPLEX_CST: + if (TREE_CODE (TREE_REALPART (value)) == INTEGER_CST) + warning (OPT_Woverflow, "complex integer overflow in expression"); + else if (TREE_CODE (TREE_REALPART (value)) == REAL_CST) + warning (OPT_Woverflow, "complex floating point overflow in expression"); + break; + + default: + break; } } diff --git a/gcc/c-typeck.c b/gcc/c-typeck.c index e8e2f6944ac..8119e7f17b1 100644 --- a/gcc/c-typeck.c +++ b/gcc/c-typeck.c @@ -2601,7 +2601,10 @@ parser_build_unary_op (enum tree_code code, struct c_expr arg) result.original_code = ERROR_MARK; result.value = build_unary_op (code, arg.value, 0); - overflow_warning (result.value); + + if (TREE_OVERFLOW_P (result.value) && !TREE_OVERFLOW_P (arg.value)) + overflow_warning (result.value); + return result; } @@ -2645,7 +2648,10 @@ parser_build_binary_op (enum tree_code code, struct c_expr arg1, warning (OPT_Wstring_literal_comparison, "comparison with string literal"); - overflow_warning (result.value); + if (TREE_OVERFLOW_P (result.value) + && !TREE_OVERFLOW_P (arg1.value) + && !TREE_OVERFLOW_P (arg2.value)) + overflow_warning (result.value); return result; } @@ -3827,10 +3833,7 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv errtype, } if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (rhstype)) - { - overflow_warning (rhs); - return rhs; - } + return rhs; if (coder == VOID_TYPE) { diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 1f7945d9b1f..3c35e5825bf 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,9 @@ +2007-01-05 Manuel Lopez-Ibanez + + PR c/19978 + * semantics.c (finish_unary_op_expr): Warn only if result + overflowed and operands did not. + 2007-01-05 Ian Lance Taylor * typeck.c (build_binary_op): Warn about comparing a non-weak diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 5b8906eb020..538f7b4ec15 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -2000,7 +2000,9 @@ finish_unary_op_expr (enum tree_code code, tree expr) result = copy_node (result); TREE_NEGATED_INT (result) = 1; } - overflow_warning (result); + if (TREE_OVERFLOW_P (result) && !TREE_OVERFLOW_P (expr)) + overflow_warning (result); + return result; } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 18909655fb5..5372427a7cf 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,11 @@ +2007-01-05 Manuel Lopez-Ibanez + + PR c/19978 + * gcc.dg/multiple-overflow-warn-1.c: New. + * gcc.dg/multiple-overflow-warn-2.c: New. + * gcc.dg/overflow-warn-6.c: New. + * g++.dg/warn/multiple-overflow-warn-1.C: New. + 2007-01-05 Roger Sayle * gfortran.dg/array_memcpy_1.f90: New test case. diff --git a/gcc/testsuite/g++.dg/warn/multiple-overflow-warn-1.C b/gcc/testsuite/g++.dg/warn/multiple-overflow-warn-1.C new file mode 100644 index 00000000000..489930211e4 --- /dev/null +++ b/gcc/testsuite/g++.dg/warn/multiple-overflow-warn-1.C @@ -0,0 +1,13 @@ +/* PR c/19978 : Test for duplicated warnings (unary operators). */ +/* { dg-do compile } */ +/* { dg-options "-Woverflow" } */ + +#include + +int +g (void) +{ + return - - - - -INT_MIN; /* { dg-bogus "integer overflow in expression.*integer overflow in expression" } */ + /* { dg-warning "integer overflow in expression" "" { target *-*-* } 10 } */ +} + diff --git a/gcc/testsuite/gcc.dg/multiple-overflow-warn-1.c b/gcc/testsuite/gcc.dg/multiple-overflow-warn-1.c new file mode 100644 index 00000000000..be7b3b85685 --- /dev/null +++ b/gcc/testsuite/gcc.dg/multiple-overflow-warn-1.c @@ -0,0 +1,13 @@ +/* PR c/19978 : Test for duplicated warnings (unary operators). */ +/* { dg-do compile } */ +/* { dg-options "-std=c99 -Woverflow" } */ + +#include + +int +g (void) +{ + return - - - - -INT_MIN; /* { dg-bogus "integer overflow in expression.*integer overflow in expression" } */ + /* { dg-warning "integer overflow in expression" "" { target *-*-* } 10 } */ +} + diff --git a/gcc/testsuite/gcc.dg/multiple-overflow-warn-2.c b/gcc/testsuite/gcc.dg/multiple-overflow-warn-2.c new file mode 100644 index 00000000000..8a4e9e5c274 --- /dev/null +++ b/gcc/testsuite/gcc.dg/multiple-overflow-warn-2.c @@ -0,0 +1,12 @@ +/* PR c/19978 : Test for duplicated warnings (binary operators). */ +/* { dg-do compile } */ +/* { dg-options "-std=c99 -Woverflow" } */ + +#include + +int +g1 (void) +{ + return INT_MAX + 1 - INT_MAX; /* { dg-bogus "integer overflow in expression.*integer overflow in expression" } */ + /* { dg-warning "integer overflow in expression" "" { target *-*-* } 10 } */ +} diff --git a/gcc/testsuite/gcc.dg/overflow-warn-6.c b/gcc/testsuite/gcc.dg/overflow-warn-6.c new file mode 100644 index 00000000000..da8cb0140a9 --- /dev/null +++ b/gcc/testsuite/gcc.dg/overflow-warn-6.c @@ -0,0 +1,18 @@ +/* Test non-constant operands in overflowed expressions. */ +/* { dg-do compile } */ +/* { dg-options "-std=c99 -Woverflow" } */ + +#include + +int +h1 (int x) +{ + return x * (0 * (INT_MAX + 1)); /* { dg-warning "warning: integer overflow in expression" } */ +} + +int +h2 (int x) +{ + return ((INT_MAX + 1) * 0) * x; /* { dg-warning "warning: integer overflow in expression" } */ +} + diff --git a/gcc/tree.h b/gcc/tree.h index 3a226287107..9f2d7076c45 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -1156,6 +1156,11 @@ extern void omp_clause_range_check_failed (const tree, const char *, int, #define TREE_OVERFLOW(NODE) (CST_CHECK (NODE)->base.public_flag) +/* TREE_OVERFLOW can only be true for EXPR of CONSTANT_CLASS_P. */ + +#define TREE_OVERFLOW_P(EXPR) \ + (CONSTANT_CLASS_P (EXPR) && TREE_OVERFLOW (EXPR)) + /* In a VAR_DECL, FUNCTION_DECL, NAMESPACE_DECL or TYPE_DECL, nonzero means name is to be accessible from outside this module. In an IDENTIFIER_NODE, nonzero means an external declaration