summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog10
-rw-r--r--gcc/c-common.c56
-rw-r--r--gcc/c-typeck.c15
-rw-r--r--gcc/cp/ChangeLog6
-rw-r--r--gcc/cp/semantics.c4
-rw-r--r--gcc/testsuite/ChangeLog8
-rw-r--r--gcc/testsuite/g++.dg/warn/multiple-overflow-warn-1.C13
-rw-r--r--gcc/testsuite/gcc.dg/multiple-overflow-warn-1.c13
-rw-r--r--gcc/testsuite/gcc.dg/multiple-overflow-warn-2.c12
-rw-r--r--gcc/testsuite/gcc.dg/overflow-warn-6.c18
-rw-r--r--gcc/tree.h5
11 files changed, 128 insertions, 32 deletions
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 <manu@gcc.gnu.org>
+ 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 <manu@gcc.gnu.org>
+
* 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 <manu@gcc.gnu.org>
+
+ PR c/19978
+ * semantics.c (finish_unary_op_expr): Warn only if result
+ overflowed and operands did not.
+
2007-01-05 Ian Lance Taylor <iant@google.com>
* 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 <manu@gcc.gnu.org>
+
+ 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 <roger@eyesopen.com>
* 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 <limits.h>
+
+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 <limits.h>
+
+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 <limits.h>
+
+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 <limits.h>
+
+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