re PR c/19978 (overflow in expression of constants should not cause multiple warnings)

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.

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.

From-SVN: r120505
parent c2658540
2007-01-05 Manuel Lopez-Ibanez <manu@gcc.gnu.org> 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 * c-typeck.c (store_init_value): Split over two lines to follow
the GNU coding style. the GNU coding style.
......
...@@ -920,39 +920,45 @@ constant_expression_warning (tree value) ...@@ -920,39 +920,45 @@ constant_expression_warning (tree value)
pedwarn ("overflow in constant expression"); 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 Invoke this function on every expression that
(1) appears in the source code, and (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; (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 void
overflow_warning (tree value) overflow_warning (tree value)
{ {
if ((TREE_CODE (value) == INTEGER_CST if (skip_evaluation) return;
|| (TREE_CODE (value) == COMPLEX_CST
&& TREE_CODE (TREE_REALPART (value)) == INTEGER_CST)) switch (TREE_CODE (value))
&& 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))
{ {
TREE_OVERFLOW (value) = 0; case INTEGER_CST:
if (skip_evaluation == 0) warning (OPT_Woverflow, "integer overflow in expression");
warning (OPT_Woverflow, "vector 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;
} }
} }
......
...@@ -2601,7 +2601,10 @@ parser_build_unary_op (enum tree_code code, struct c_expr arg) ...@@ -2601,7 +2601,10 @@ parser_build_unary_op (enum tree_code code, struct c_expr arg)
result.original_code = ERROR_MARK; result.original_code = ERROR_MARK;
result.value = build_unary_op (code, arg.value, 0); 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; return result;
} }
...@@ -2645,7 +2648,10 @@ parser_build_binary_op (enum tree_code code, struct c_expr arg1, ...@@ -2645,7 +2648,10 @@ parser_build_binary_op (enum tree_code code, struct c_expr arg1,
warning (OPT_Wstring_literal_comparison, warning (OPT_Wstring_literal_comparison,
"comparison with string literal"); "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; return result;
} }
...@@ -3827,10 +3833,7 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv errtype, ...@@ -3827,10 +3833,7 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv errtype,
} }
if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (rhstype)) if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (rhstype))
{ return rhs;
overflow_warning (rhs);
return rhs;
}
if (coder == VOID_TYPE) if (coder == VOID_TYPE)
{ {
......
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> 2007-01-05 Ian Lance Taylor <iant@google.com>
* typeck.c (build_binary_op): Warn about comparing a non-weak * typeck.c (build_binary_op): Warn about comparing a non-weak
......
...@@ -2000,7 +2000,9 @@ finish_unary_op_expr (enum tree_code code, tree expr) ...@@ -2000,7 +2000,9 @@ finish_unary_op_expr (enum tree_code code, tree expr)
result = copy_node (result); result = copy_node (result);
TREE_NEGATED_INT (result) = 1; TREE_NEGATED_INT (result) = 1;
} }
overflow_warning (result); if (TREE_OVERFLOW_P (result) && !TREE_OVERFLOW_P (expr))
overflow_warning (result);
return result; return result;
} }
......
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> 2007-01-05 Roger Sayle <roger@eyesopen.com>
* gfortran.dg/array_memcpy_1.f90: New test case. * gfortran.dg/array_memcpy_1.f90: New test case.
/* 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 } */
}
/* 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 } */
}
/* 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 } */
}
/* 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" } */
}
...@@ -1156,6 +1156,11 @@ extern void omp_clause_range_check_failed (const tree, const char *, int, ...@@ -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) #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, /* In a VAR_DECL, FUNCTION_DECL, NAMESPACE_DECL or TYPE_DECL,
nonzero means name is to be accessible from outside this module. nonzero means name is to be accessible from outside this module.
In an IDENTIFIER_NODE, nonzero means an external declaration In an IDENTIFIER_NODE, nonzero means an external declaration
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment