common.opt: Add Wstrict-overflow and Wstrict-overflow=.

./:	* common.opt: Add Wstrict-overflow and Wstrict-overflow=.
	* flags.h (warn_strict_overflow): Declare.
	(enum warn_strict_overflow_code): Define.
	(issue_strict_overflow_warning): New static inline function.
	* opts.c (warn_strict_overflow): New variable.
	(common_handle_option): Handle OPT_Wstrict_overflow and
	OPT_Wstrict_overflow_.
	* c-opts.c (c_common_handle_option): Set warn_strict_overflow for
	OPT_Wall.
	* fold-const.c: Include intl.h.
	(fold_deferring_overflow_warnings): New static variable.
	(fold_deferred_overflow_warning): New static variable.
	(fold_deferred_overflow_code): New static variable.
	(fold_defer_overflow_warnings): New function.
	(fold_undefer_overflow_warnings): New function.
	(fold_undefer_and_ignore_overflow_warnings): New function.
	(fold_deferring_overflow_warnings_p): New function.
	(fold_overflow_warning): New static function.
	(make_range): Add strict_overflow_p parameter.  Change all
	callers.
	(extract_muldiv, extract_muldiv_1): Likewise.
	(fold_unary) [ABS_EXPR]: Check ABS_EXPR before calling
	tree_expr_nonnegative_p.
	(fold_negate_expr): Call fold_overflow_warning.
	(fold_range_test): Likewise.
	(fold_comparison): Likewise.
	(fold_binary): Likewise.  Call tree_expr_nonnegative_warnv_p
	instead of tree_expr_nonnegative_p.
	(tree_expr_nonnegative_warnv_p): Rename from
	tree_expr_nonnegative_p, add strict_overflow_p parameter.
	(tree_expr_nonnegative_p): New function.
	(tree_expr_nonzero_warnv_p): Rename from tree_expr_nonzero_p, add
	strict_overflow_p parameter.
	(tree_expr_nonzero_p): New function.
	* passes.c (verify_interpass_invariants): New static function.
	(execute_one_pass): Call it.
	* tree-ssa-loop-niter.c (expand_simple_operations): Ignore fold
	warnings.
	(number_of_iterations_exit, loop_niter_by_eval): Likewise.
	(estimate_numbers_of_iterations): Likewise.
	(scev_probably_wraps_p): Likewise.
	* tree-ssa-ccp.c: Include "toplev.h".
	(evaluate_stmt): Defer fold overflow warnings until we know we are
	going to optimize.
	(struct fold_stmt_r_data): Add stmt field.
	(fold_stmt_r): Defer fold overflow warnings until we know we
	optimized.
	(fold_stmt): Initialize stmt field of fold_stmt_r_data.
	(fold_stmt_inplace): Likewise.
	* tree-cfgcleanup.c: Include "toplev.h" rather than "errors.h".
	(cleanup_control_expr_graph): Defer fold overflow warnings until
	we know we are going to optimize.
	* tree-cfg.c (fold_cond_expr_cond): Likewise.
	* tree-ssa-threadedge.c (simplify_control_stmt_condition):
	Likewise.
	* tree-vrp.c (vrp_expr_computes_nonnegative): Call
	tree_expr_nonnegative_warnv_p instead of tree_expr_nonnegative_p.
	* tree-ssa-loop-manip.c (create_iv): Likewise.
	* c-typeck.c (build_conditional_expr): Likewise.
	(build_binary_op): Likewise.
	* tree-vrp.c (vrp_expr_computes_nonzero): Call
	tree_expr_nonzero_warnv_p instead of tree_expr_nonzero_p.
	(extract_range_from_unary_expr): Likewise.
	* simplify-rtx.c (simplify_const_relational_operation): Warn when
	assuming that signed overflow does not occur.
	* c-common.c (pointer_int_sum): Ignore fold overflow warnings.
	* tree.h (tree_expr_nonnegative_warnv_p): Declare.
	(fold_defer_overflow_warnings): Declare.
	(fold_undefer_overflow_warnings): Declare.
	(fold_undefer_and_ignore_overflow_warnings): Declare.
	(fold_deferring_overflow_warnings_p): Declare.
	(tree_expr_nonzero_warnv_p): Declare.
	* doc/invoke.texi (Option Summary): Add -Wstrict-overflow to list
	of warning options.
	(Warning Options): Document -Wstrict-overflow.
	* Makefile.in (tree-ssa-threadedge.o): Depend on toplev.h.
	(tree-ssa-ccp.o): Likewise.
	(tree-cfgcleanup.o): Change errors.h dependency to toplev.h.
	(fold-const.o): Depend on intl.h.
testsuite/:
	* gcc.dg/Wstrict-overflow-1.c: New test.
	* gcc.dg/Wstrict-overflow-2.c: New test.
	* gcc.dg/Wstrict-overflow-3.c: New test.
	* gcc.dg/Wstrict-overflow-4.c: New test.
	* gcc.dg/Wstrict-overflow-5.c: New test.
	* gcc.dg/Wstrict-overflow-6.c: New test.
	* gcc.dg/Wstrict-overflow-7.c: New test.
	* gcc.dg/Wstrict-overflow-8.c: New test.
	* gcc.dg/Wstrict-overflow-9.c: New test.
	* gcc.dg/Wstrict-overflow-10.c: New test.

From-SVN: r121895
This commit is contained in:
Ian Lance Taylor 2007-02-13 22:34:45 +00:00 committed by Ian Lance Taylor
parent 30d18db484
commit 6ac015100f
31 changed files with 1141 additions and 181 deletions

View File

@ -1,3 +1,85 @@
2007-02-13 Ian Lance Taylor <iant@google.com>
* common.opt: Add Wstrict-overflow and Wstrict-overflow=.
* flags.h (warn_strict_overflow): Declare.
(enum warn_strict_overflow_code): Define.
(issue_strict_overflow_warning): New static inline function.
* opts.c (warn_strict_overflow): New variable.
(common_handle_option): Handle OPT_Wstrict_overflow and
OPT_Wstrict_overflow_.
* c-opts.c (c_common_handle_option): Set warn_strict_overflow for
OPT_Wall.
* fold-const.c: Include intl.h.
(fold_deferring_overflow_warnings): New static variable.
(fold_deferred_overflow_warning): New static variable.
(fold_deferred_overflow_code): New static variable.
(fold_defer_overflow_warnings): New function.
(fold_undefer_overflow_warnings): New function.
(fold_undefer_and_ignore_overflow_warnings): New function.
(fold_deferring_overflow_warnings_p): New function.
(fold_overflow_warning): New static function.
(make_range): Add strict_overflow_p parameter. Change all
callers.
(extract_muldiv, extract_muldiv_1): Likewise.
(fold_unary) [ABS_EXPR]: Check ABS_EXPR before calling
tree_expr_nonnegative_p.
(fold_negate_expr): Call fold_overflow_warning.
(fold_range_test): Likewise.
(fold_comparison): Likewise.
(fold_binary): Likewise. Call tree_expr_nonnegative_warnv_p
instead of tree_expr_nonnegative_p.
(tree_expr_nonnegative_warnv_p): Rename from
tree_expr_nonnegative_p, add strict_overflow_p parameter.
(tree_expr_nonnegative_p): New function.
(tree_expr_nonzero_warnv_p): Rename from tree_expr_nonzero_p, add
strict_overflow_p parameter.
(tree_expr_nonzero_p): New function.
* passes.c (verify_interpass_invariants): New static function.
(execute_one_pass): Call it.
* tree-ssa-loop-niter.c (expand_simple_operations): Ignore fold
warnings.
(number_of_iterations_exit, loop_niter_by_eval): Likewise.
(estimate_numbers_of_iterations): Likewise.
(scev_probably_wraps_p): Likewise.
* tree-ssa-ccp.c: Include "toplev.h".
(evaluate_stmt): Defer fold overflow warnings until we know we are
going to optimize.
(struct fold_stmt_r_data): Add stmt field.
(fold_stmt_r): Defer fold overflow warnings until we know we
optimized.
(fold_stmt): Initialize stmt field of fold_stmt_r_data.
(fold_stmt_inplace): Likewise.
* tree-cfgcleanup.c: Include "toplev.h" rather than "errors.h".
(cleanup_control_expr_graph): Defer fold overflow warnings until
we know we are going to optimize.
* tree-cfg.c (fold_cond_expr_cond): Likewise.
* tree-ssa-threadedge.c (simplify_control_stmt_condition):
Likewise.
* tree-vrp.c (vrp_expr_computes_nonnegative): Call
tree_expr_nonnegative_warnv_p instead of tree_expr_nonnegative_p.
* tree-ssa-loop-manip.c (create_iv): Likewise.
* c-typeck.c (build_conditional_expr): Likewise.
(build_binary_op): Likewise.
* tree-vrp.c (vrp_expr_computes_nonzero): Call
tree_expr_nonzero_warnv_p instead of tree_expr_nonzero_p.
(extract_range_from_unary_expr): Likewise.
* simplify-rtx.c (simplify_const_relational_operation): Warn when
assuming that signed overflow does not occur.
* c-common.c (pointer_int_sum): Ignore fold overflow warnings.
* tree.h (tree_expr_nonnegative_warnv_p): Declare.
(fold_defer_overflow_warnings): Declare.
(fold_undefer_overflow_warnings): Declare.
(fold_undefer_and_ignore_overflow_warnings): Declare.
(fold_deferring_overflow_warnings_p): Declare.
(tree_expr_nonzero_warnv_p): Declare.
* doc/invoke.texi (Option Summary): Add -Wstrict-overflow to list
of warning options.
(Warning Options): Document -Wstrict-overflow.
* Makefile.in (tree-ssa-threadedge.o): Depend on toplev.h.
(tree-ssa-ccp.o): Likewise.
(tree-cfgcleanup.o): Change errors.h dependency to toplev.h.
(fold-const.o): Depend on intl.h.
2007-02-13 Ian Lance Taylor <iant@google.com>
PR middle-end/30751

View File

@ -2059,7 +2059,7 @@ tree-cfg.o : tree-cfg.c $(TREE_FLOW_H) $(CONFIG_H) $(SYSTEM_H) \
tree-ssa-propagate.h
tree-cfgcleanup.o : tree-cfgcleanup.c $(TREE_FLOW_H) $(CONFIG_H) $(SYSTEM_H) \
$(RTL_H) $(TREE_H) $(TM_P_H) $(EXPR_H) $(GGC_H) $(FLAGS_H) output.h \
$(DIAGNOSTIC_H) errors.h $(FUNCTION_H) $(TIMEVAR_H) $(TM_H) coretypes.h \
$(DIAGNOSTIC_H) toplev.h $(FUNCTION_H) $(TIMEVAR_H) $(TM_H) coretypes.h \
$(TREE_DUMP_H) except.h langhooks.h $(CFGLOOP_H) tree-pass.h \
$(CFGLAYOUT_H) $(BASIC_BLOCK_H) hard-reg-set.h $(HASHTAB_H) toplev.h \
tree-ssa-propagate.h
@ -2256,7 +2256,7 @@ tree-pretty-print.o : tree-pretty-print.c $(CONFIG_H) $(SYSTEM_H) \
value-prof.h
fold-const.o : fold-const.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
$(TREE_H) $(FLAGS_H) $(REAL_H) toplev.h $(HASHTAB_H) $(EXPR_H) $(RTL_H) \
$(GGC_H) $(TM_P_H) langhooks.h $(MD5_H)
$(GGC_H) $(TM_P_H) langhooks.h $(MD5_H) intl.h
diagnostic.o : diagnostic.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
$(TREE_H) version.h $(TM_P_H) $(FLAGS_H) input.h toplev.h intl.h \
$(DIAGNOSTIC_H) langhooks.h $(LANGHOOKS_DEF_H) diagnostic.def opts.h
@ -2507,7 +2507,7 @@ tree-ssa-ccp.o : tree-ssa-ccp.c $(TREE_FLOW_H) $(CONFIG_H) \
$(SYSTEM_H) $(RTL_H) $(TREE_H) $(TM_P_H) $(EXPR_H) $(GGC_H) output.h \
$(DIAGNOSTIC_H) $(FUNCTION_H) $(TIMEVAR_H) $(TM_H) coretypes.h \
$(TREE_DUMP_H) $(BASIC_BLOCK_H) tree-pass.h langhooks.h \
tree-ssa-propagate.h $(FLAGS_H) $(TARGET_H)
tree-ssa-propagate.h $(FLAGS_H) $(TARGET_H) toplev.h
tree-sra.o : tree-sra.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(RTL_H) \
$(TM_P_H) $(TREE_FLOW_H) $(DIAGNOSTIC_H) $(TREE_INLINE_H) \
$(TIMEVAR_H) $(TM_H) coretypes.h $(TREE_DUMP_H) $(TREE_GIMPLE_H) \

View File

@ -2543,7 +2543,7 @@ shorten_compare (tree *op0_ptr, tree *op1_ptr, tree *restype_ptr,
tree
pointer_int_sum (enum tree_code resultcode, tree ptrop, tree intop)
{
tree size_exp;
tree size_exp, ret;
/* The result is a pointer of the same type that is being added. */
@ -2570,6 +2570,12 @@ pointer_int_sum (enum tree_code resultcode, tree ptrop, tree intop)
else
size_exp = size_in_bytes (TREE_TYPE (result_type));
/* We are manipulating pointer values, so we don't need to warn
about relying on undefined signed overflow. We disable the
warning here because we use integer types so fold won't know that
they are really pointers. */
fold_defer_overflow_warnings ();
/* If what we are about to multiply by the size of the elements
contains a constant term, apply distributive law
and multiply that constant term separately.
@ -2618,7 +2624,11 @@ pointer_int_sum (enum tree_code resultcode, tree ptrop, tree intop)
convert (TREE_TYPE (intop), size_exp), 1));
/* Create the sum or difference. */
return fold_build2 (resultcode, result_type, ptrop, intop);
ret = fold_build2 (resultcode, result_type, ptrop, intop);
fold_undefer_and_ignore_overflow_warnings ();
return ret;
}
/* Return whether EXPR is a declaration whose address can never be

View File

@ -1,5 +1,6 @@
/* C/ObjC/C++ command line option handling.
Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007
Free Software Foundation, Inc.
Contributed by Neil Booth.
This file is part of GCC.
@ -394,6 +395,7 @@ c_common_handle_option (size_t scode, const char *arg, int value)
warn_sign_compare = value;
warn_switch = value;
warn_strict_aliasing = value;
warn_strict_overflow = value;
warn_string_literal_comparison = value;
warn_always_true = value;
warn_array_bounds = value;

View File

@ -3270,6 +3270,8 @@ build_conditional_expr (tree ifexp, tree op1, tree op2)
if (unsigned_op1 ^ unsigned_op2)
{
bool ovf;
/* Do not warn if the result type is signed, since the
signed type will only be chosen if it can represent
all the values of the unsigned type. */
@ -3278,8 +3280,10 @@ build_conditional_expr (tree ifexp, tree op1, tree op2)
/* Do not warn if the signed quantity is an unsuffixed
integer literal (or some static constant expression
involving such literals) and it is non-negative. */
else if ((unsigned_op2 && tree_expr_nonnegative_p (op1))
|| (unsigned_op1 && tree_expr_nonnegative_p (op2)))
else if ((unsigned_op2
&& tree_expr_nonnegative_warnv_p (op1, &ovf))
|| (unsigned_op1
&& tree_expr_nonnegative_warnv_p (op2, &ovf)))
/* OK */;
else
warning (0, "signed and unsigned type in conditional expression");
@ -8303,6 +8307,7 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
else
{
tree sop, uop;
bool ovf;
if (op0_signed)
sop = xop0, uop = xop1;
@ -8314,7 +8319,7 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
constant expression involving such literals or a
conditional expression involving such literals)
and it is non-negative. */
if (tree_expr_nonnegative_p (sop))
if (tree_expr_nonnegative_warnv_p (sop, &ovf))
/* OK */;
/* Do not warn if the comparison is an equality operation,
the unsigned quantity is an integral constant, and it

View File

@ -158,6 +158,14 @@ Wstrict-aliasing=
Common Joined UInteger Warning
Warn about code which might break strict aliasing rules
Wstrict-overflow
Common
Warn about optimizations that assume that signed overflow is undefined
Wstrict-overflow=
Common Joined UInteger
Warn about optimizations that assume that signed overflow is undefined
Wstring-literal-comparison
Common Var(warn_string_literal_comparison) Warning
Warn about comparisons to constant string literals

View File

@ -248,6 +248,7 @@ Objective-C and Objective-C++ Dialects}.
-Wreturn-type -Wsequence-point -Wshadow @gol
-Wsign-compare -Wstack-protector @gol
-Wstrict-aliasing -Wstrict-aliasing=2 @gol
-Wstrict-overflow -Wstrict-overflow=@var{n} @gol
-Wstring-literal-comparison @gol
-Wswitch -Wswitch-default -Wswitch-enum @gol
-Wsystem-headers -Wtrigraphs -Wundef -Wuninitialized @gol
@ -2972,6 +2973,56 @@ compiler is using for optimization. This warning catches more cases than
@option{-Wstrict-aliasing}, but it will also give a warning for some ambiguous
cases that are safe.
@item -Wstrict-overflow
@item -Wstrict-overflow=@var{n}
@opindex -Wstrict-overflow
This option is only active when @option{-fstrict-overflow} is active.
It warns about cases where the compiler optimizes based on the
assumption that signed overflow does not occur. Note that it does not
warn about all cases where the code might overflow: it only warns
about cases where the compiler implements some optimization. Thus
this warning depends on the optimization level.
An optimization which assumes that signed overflow does not occur is
perfectly safe if the values of the variables involved are such that
overflow never does, in fact, occur. Therefore this warning can
easily give a false positive: a warning about code which is not
actually a problem. To help focus on important issues, several
warning levels are defined.
@table @option
@item -Wstrict-overflow=1
Warn about cases which are both questionable and easy to avoid. For
example: @code{x + 1 > x}; with @option{-fstrict-overflow}, the
compiler will simplify this to @code{1}. @option{-Wstrict-overflow}
(with no level) is the same as @option{-Wstrict-overflow=1}. This
level of @option{-Wstrict-overflow} is enabled by @option{-Wall};
higher levels are not, and must be explicitly requested.
@item -Wstrict-overflow=2
Also warn about other cases where a comparison is simplified to a
constant. For example: @code{abs (x) >= 0}. This can only be
simplified when @option{-fstrict-overflow} is in effect, because
@code{abs (INT_MIN)} overflows to @code{INT_MIN}, which is less than
zero.
@item -Wstrict-overflow=3
Also warn about other cases where a comparison is simplified. For
example: @code{x + 1 > 1} will be simplified to @code{x > 0}.
@item -Wstrict-overflow=4
Also warn about other simplifications not covered by the above cases.
For example: @code{(x * 10) / 5} will be simplified to @code{x * 2}.
@item -Wstrict-overflow=5
Also warn about cases where the compiler reduces the magnitude of a
constant involved in a comparison. For example: @code{x + 2 > y} will
be simplified to @code{x + 1 >= y}. This is reported only at the
highest warning level because this simplification applies to many
comparisons, so this warning level will give a very large number of
false positives.
@end table
@item -Warray-bounds
@opindex Wno-array-bounds
@opindex Warray-bounds

View File

@ -114,6 +114,11 @@ extern HOST_WIDE_INT larger_than_size;
extern int warn_strict_aliasing;
/* Nonzero means warn about optimizations which rely on undefined
signed overflow. */
extern int warn_strict_overflow;
/* Temporarily suppress certain warnings.
This is set while reading code from a system header file. */
@ -289,8 +294,13 @@ extern const char *flag_random_seed;
(TYPE_UNSIGNED (TYPE) || flag_wrapv)
/* True if overflow is undefined for the given integral type. We may
optimize on the assumption that values in the type never
overflow. */
optimize on the assumption that values in the type never overflow.
IMPORTANT NOTE: Any optimization based on TYPE_OVERFLOW_UNDEFINED
must issue a warning based on warn_strict_overflow. In some cases
it will be appropriate to issue the warning immediately, and in
other cases it will be appropriate to simply set a flag and let the
caller decide whether a warning is appropriate or not. */
#define TYPE_OVERFLOW_UNDEFINED(TYPE) \
(!TYPE_UNSIGNED (TYPE) && !flag_wrapv && !flag_trapv && flag_strict_overflow)
@ -299,4 +309,37 @@ extern const char *flag_random_seed;
#define TYPE_OVERFLOW_TRAPS(TYPE) \
(!TYPE_UNSIGNED (TYPE) && flag_trapv)
/* Names for the different levels of -Wstrict-overflow=N. The numeric
values here correspond to N. */
enum warn_strict_overflow_code
{
/* Overflow warning that should be issued with -Wall: a questionable
construct that is easy to avoid even when using macros. Example:
folding (x + CONSTANT > x) to 1. */
WARN_STRICT_OVERFLOW_ALL = 1,
/* Overflow warning about folding a comparison to a constant because
of undefined signed overflow, other than cases covered by
WARN_STRICT_OVERFLOW_ALL. Example: folding (abs (x) >= 0) to 1
(this is false when x == INT_MIN). */
WARN_STRICT_OVERFLOW_CONDITIONAL = 2,
/* Overflow warning about changes to comparisons other than folding
them to a constant. Example: folding (x + 1 > 1) to (x > 0). */
WARN_STRICT_OVERFLOW_COMPARISON = 3,
/* Overflow warnings not covered by the above cases. Example:
folding ((x * 10) / 5) to (x * 2). */
WARN_STRICT_OVERFLOW_MISC = 4,
/* Overflow warnings about reducing magnitude of constants in
comparison. Example: folding (x + 2 > y) to (x + 1 >= y). */
WARN_STRICT_OVERFLOW_MAGNITUDE = 5
};
/* Whether to emit an overflow warning whose code is C. */
static inline bool
issue_strict_overflow_warning (enum warn_strict_overflow_code c)
{
return warn_strict_overflow >= (int) c;
}
#endif /* ! GCC_FLAGS_H */

File diff suppressed because it is too large Load Diff

View File

@ -61,6 +61,10 @@ HOST_WIDE_INT larger_than_size;
strict-aliasing safe. */
int warn_strict_aliasing;
/* Nonzero means warn about optimizations which rely on undefined
signed overflow. */
int warn_strict_overflow;
/* Hack for cooperation between set_Wunused and set_Wextra. */
static bool maybe_warn_unused_parameter;
@ -1104,6 +1108,11 @@ common_handle_option (size_t scode, const char *arg, int value,
warn_strict_aliasing = value;
break;
case OPT_Wstrict_overflow:
case OPT_Wstrict_overflow_:
warn_strict_overflow = value;
break;
case OPT_Wunused:
set_Wunused (value);
break;

View File

@ -952,6 +952,17 @@ execute_todo (unsigned int flags)
}
}
/* Verify invariants that should hold between passes. This is a place
to put simple sanity checks. */
static void
verify_interpass_invariants (void)
{
#ifdef ENABLE_CHECKING
gcc_assert (!fold_deferring_overflow_warnings_p ());
#endif
}
/* Clear the last verified flag. */
static void
@ -1063,6 +1074,7 @@ execute_one_pass (struct tree_opt_pass *pass)
/* Run post-pass cleanup and verification. */
execute_todo (todo_after | pass->todo_flags_finish);
verify_interpass_invariants ();
if (!current_function_decl)
cgraph_process_new_functions ();

View File

@ -4086,7 +4086,15 @@ simplify_const_relational_operation (enum rtx_code code,
tem = GET_CODE (trueop0) == FLOAT_EXTEND ? XEXP (trueop0, 0)
: trueop0;
if (GET_CODE (tem) == ABS)
return const0_rtx;
{
if (INTEGRAL_MODE_P (mode)
&& (issue_strict_overflow_warning
(WARN_STRICT_OVERFLOW_CONDITIONAL)))
warning (OPT_Wstrict_overflow,
("assuming signed overflow does not occur when "
"assuming abs (x) < 0 is false"));
return const0_rtx;
}
}
/* Optimize popcount (x) < 0. */
@ -4104,7 +4112,15 @@ simplify_const_relational_operation (enum rtx_code code,
tem = GET_CODE (trueop0) == FLOAT_EXTEND ? XEXP (trueop0, 0)
: trueop0;
if (GET_CODE (tem) == ABS)
return const_true_rtx;
{
if (INTEGRAL_MODE_P (mode)
&& (issue_strict_overflow_warning
(WARN_STRICT_OVERFLOW_CONDITIONAL)))
warning (OPT_Wstrict_overflow,
("assuming signed overflow does not occur when "
"assuming abs (x) >= 0 is true"));
return const_true_rtx;
}
}
/* Optimize popcount (x) >= 0. */

View File

@ -1,3 +1,16 @@
2007-02-13 Ian Lance Taylor <iant@google.com>
* gcc.dg/Wstrict-overflow-1.c: New test.
* gcc.dg/Wstrict-overflow-2.c: New test.
* gcc.dg/Wstrict-overflow-3.c: New test.
* gcc.dg/Wstrict-overflow-4.c: New test.
* gcc.dg/Wstrict-overflow-5.c: New test.
* gcc.dg/Wstrict-overflow-6.c: New test.
* gcc.dg/Wstrict-overflow-7.c: New test.
* gcc.dg/Wstrict-overflow-8.c: New test.
* gcc.dg/Wstrict-overflow-9.c: New test.
* gcc.dg/Wstrict-overflow-10.c: New test.
2007-02-13 Roger Sayle <roger@eyesopen.com>
* gcc.target/ia64/builtin-bswap-2.c: New test case.

View File

@ -0,0 +1,13 @@
/* { dg-do compile } */
/* { dg-options "-fstrict-overflow -O2 -Wstrict-overflow=3" } */
/* Source: Ian Lance Taylor. Based on strict-overflow-1.c. */
/* We can only simplify the conditional when using strict overflow
semantics. */
int
foo (int i)
{
return i - 5 < 10; /* { dg-warning "assuming signed overflow does not occur" "correct warning" } */
}

View File

@ -0,0 +1,10 @@
/* { dg-do compile } */
/* { dg-options "-fstrict-overflow -O2 -Wstrict-overflow=1" } */
/* Source: Ian Lance Taylor. */
int
foo (int i)
{
return __builtin_abs (i) >= 0;
}

View File

@ -0,0 +1,13 @@
/* { dg-do compile } */
/* { dg-options "-fstrict-overflow -O2 -Wstrict-overflow=2" } */
/* Source: Ian Lance Taylor. Based on strict-overflow-1.c. */
/* We can only simplify the conditional when using strict overflow
semantics. */
int
foo (int i)
{
return i - 5 < 10;
}

View File

@ -0,0 +1,13 @@
/* { dg-do compile } */
/* { dg-options "-fstrict-overflow -O2 -Wstrict-overflow=4" } */
/* Source: Ian Lance Taylor. Based on strict-overflow-2.c. */
/* We can only simplify the division when using strict overflow
semantics. */
int
foo (int i)
{
return (i * 100) / 10; /* { dg-warning "assuming signed overflow does not occur" "correct warning" } */
}

View File

@ -0,0 +1,13 @@
/* { dg-do compile } */
/* { dg-options "-fstrict-overflow -O2 -Wstrict-overflow=3" } */
/* Source: Ian Lance Taylor. Based on strict-overflow-2.c. */
/* We can only simplify the division when using strict overflow
semantics. */
int
foo (int i)
{
return (i * 100) / 10;
}

View File

@ -0,0 +1,13 @@
/* { dg-do compile } */
/* { dg-options "-fstrict-overflow -O2 -Wstrict-overflow=3" } */
/* Source: Ian Lance Taylor. Based on strict-overflow-3.c. */
/* We can only simplify the conditional when using strict overflow
semantics. */
int
foo (int i, int j)
{
return i + 100 < j + 1000; /* { dg-warning "assuming signed overflow does not occur" "correct warning" } */
}

View File

@ -0,0 +1,13 @@
/* { dg-do compile } */
/* { dg-options "-fstrict-overflow -O2 -Wstrict-overflow=2" } */
/* Source: Ian Lance Taylor. Based on strict-overflow-3.c. */
/* We can only simplify the conditional when using strict overflow
semantics. */
int
foo (int i, int j)
{
return i + 100 < j + 1000;
}

View File

@ -0,0 +1,10 @@
/* { dg-do compile } */
/* { dg-options "-fstrict-overflow -O2 -Wstrict-overflow" } */
/* Source: Ian Lance Taylor. */
int
foo (int i)
{
return i + 10 > i; /* { dg-warning "assuming signed overflow does not occur" "correct warning" } */
}

View File

@ -0,0 +1,10 @@
/* { dg-do compile } */
/* { dg-options "-fstrict-overflow -O2 -Wall -Wno-strict-overflow" } */
/* Source: Ian Lance Taylor. */
int
foo (int i)
{
return i + 10 > i;
}

View File

@ -0,0 +1,10 @@
/* { dg-do compile } */
/* { dg-options "-fstrict-overflow -O2 -Wstrict-overflow=2" } */
/* Source: Ian Lance Taylor. */
int
foo (int i)
{
return __builtin_abs (i) >= 0; /* { dg-warning "assuming signed overflow does not occur" "correct warning" } */
}

View File

@ -408,10 +408,18 @@ fold_cond_expr_cond (void)
if (stmt
&& TREE_CODE (stmt) == COND_EXPR)
{
tree cond = fold (COND_EXPR_COND (stmt));
if (integer_zerop (cond))
tree cond;
bool zerop, onep;
fold_defer_overflow_warnings ();
cond = fold (COND_EXPR_COND (stmt));
zerop = integer_zerop (cond);
onep = integer_onep (cond);
fold_undefer_overflow_warnings (zerop || onep, stmt,
WARN_STRICT_OVERFLOW_CONDITIONAL);
if (zerop)
COND_EXPR_COND (stmt) = boolean_false_node;
else if (integer_onep (cond))
else if (onep)
COND_EXPR_COND (stmt) = boolean_true_node;
}
}

View File

@ -1,5 +1,6 @@
/* CFG cleanup for trees.
Copyright (C) 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007
Free Software Foundation, Inc.
This file is part of GCC.
@ -28,7 +29,7 @@ Boston, MA 02110-1301, USA. */
#include "hard-reg-set.h"
#include "basic-block.h"
#include "output.h"
#include "errors.h"
#include "toplev.h"
#include "flags.h"
#include "function.h"
#include "expr.h"
@ -78,6 +79,9 @@ cleanup_control_expr_graph (basic_block bb, block_stmt_iterator bsi)
{
edge e;
edge_iterator ei;
bool warned;
fold_defer_overflow_warnings ();
switch (TREE_CODE (expr))
{
@ -88,7 +92,10 @@ cleanup_control_expr_graph (basic_block bb, block_stmt_iterator bsi)
case SWITCH_EXPR:
val = fold (SWITCH_COND (expr));
if (TREE_CODE (val) != INTEGER_CST)
return false;
{
fold_undefer_and_ignore_overflow_warnings ();
return false;
}
break;
default:
@ -97,13 +104,24 @@ cleanup_control_expr_graph (basic_block bb, block_stmt_iterator bsi)
taken_edge = find_taken_edge (bb, val);
if (!taken_edge)
return false;
{
fold_undefer_and_ignore_overflow_warnings ();
return false;
}
/* Remove all the edges except the one that is always executed. */
warned = false;
for (ei = ei_start (bb->succs); (e = ei_safe_edge (ei)); )
{
if (e != taken_edge)
{
if (!warned)
{
fold_undefer_overflow_warnings
(true, expr, WARN_STRICT_OVERFLOW_CONDITIONAL);
warned = true;
}
taken_edge->probability += e->probability;
taken_edge->count += e->count;
remove_edge (e);
@ -112,6 +130,8 @@ cleanup_control_expr_graph (basic_block bb, block_stmt_iterator bsi)
else
ei_next (&ei);
}
if (!warned)
fold_undefer_and_ignore_overflow_warnings ();
if (taken_edge->probability > REG_BR_PROB_BASE)
taken_edge->probability = REG_BR_PROB_BASE;
}

View File

@ -1,5 +1,5 @@
/* Conditional constant propagation pass for the GNU compiler.
Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006
Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
Free Software Foundation, Inc.
Adapted from original RTL SSA-CCP by Daniel Berlin <dberlin@dberlin.org>
Adapted to GIMPLE trees by Diego Novillo <dnovillo@redhat.com>
@ -207,6 +207,7 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
#include "tree-ssa-propagate.h"
#include "langhooks.h"
#include "target.h"
#include "toplev.h"
/* Possible lattice values. */
@ -1132,9 +1133,12 @@ evaluate_stmt (tree stmt)
prop_value_t val;
tree simplified = NULL_TREE;
ccp_lattice_t likelyvalue = likely_value (stmt);
bool is_constant;
val.mem_ref = NULL_TREE;
fold_defer_overflow_warnings ();
/* If the statement is likely to have a CONSTANT result, then try
to fold the statement to determine the constant value. */
if (likelyvalue == CONSTANT)
@ -1151,7 +1155,11 @@ evaluate_stmt (tree stmt)
else if (!simplified)
simplified = fold_const_aggregate_ref (get_rhs (stmt));
if (simplified && is_gimple_min_invariant (simplified))
is_constant = simplified && is_gimple_min_invariant (simplified);
fold_undefer_overflow_warnings (is_constant, stmt, 0);
if (is_constant)
{
/* The statement produced a constant value. */
val.lattice_val = CONSTANT;
@ -1966,8 +1974,9 @@ maybe_fold_stmt_addition (tree expr)
struct fold_stmt_r_data
{
bool *changed_p;
bool *inside_addr_expr_p;
tree stmt;
bool *changed_p;
bool *inside_addr_expr_p;
};
/* Subroutine of fold_stmt called via walk_tree. We perform several
@ -2063,10 +2072,16 @@ fold_stmt_r (tree *expr_p, int *walk_subtrees, void *data)
if (COMPARISON_CLASS_P (TREE_OPERAND (expr, 0)))
{
tree op0 = TREE_OPERAND (expr, 0);
tree tem = fold_binary (TREE_CODE (op0), TREE_TYPE (op0),
TREE_OPERAND (op0, 0),
TREE_OPERAND (op0, 1));
if (tem && set_rhs (expr_p, tem))
tree tem;
bool set;
fold_defer_overflow_warnings ();
tem = fold_binary (TREE_CODE (op0), TREE_TYPE (op0),
TREE_OPERAND (op0, 0),
TREE_OPERAND (op0, 1));
set = tem && set_rhs (expr_p, tem);
fold_undefer_overflow_warnings (set, fold_stmt_r_data->stmt, 0);
if (set)
{
t = *expr_p;
break;
@ -2373,11 +2388,12 @@ fold_stmt (tree *stmt_p)
bool changed = false;
bool inside_addr_expr = false;
stmt = *stmt_p;
fold_stmt_r_data.stmt = stmt;
fold_stmt_r_data.changed_p = &changed;
fold_stmt_r_data.inside_addr_expr_p = &inside_addr_expr;
stmt = *stmt_p;
/* If we replaced constants and the statement makes pointer dereferences,
then we may need to fold instances of *&VAR into VAR, etc. */
if (walk_tree (stmt_p, fold_stmt_r, &fold_stmt_r_data, NULL))
@ -2472,6 +2488,7 @@ fold_stmt_inplace (tree stmt)
bool changed = false;
bool inside_addr_expr = false;
fold_stmt_r_data.stmt = stmt;
fold_stmt_r_data.changed_p = &changed;
fold_stmt_r_data.inside_addr_expr_p = &inside_addr_expr;

View File

@ -1,5 +1,5 @@
/* High-level loop manipulation functions.
Copyright (C) 2004, 2005 Free Software Foundation, Inc.
Copyright (C) 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
This file is part of GCC.
@ -86,7 +86,9 @@ create_iv (tree base, tree step, tree var, struct loop *loop,
}
else
{
if (!tree_expr_nonnegative_p (step)
bool ovf;
if (!tree_expr_nonnegative_warnv_p (step, &ovf)
&& may_negate_without_overflow_p (step))
{
incr_op = MINUS_EXPR;

View File

@ -705,7 +705,13 @@ expand_simple_operations (tree expr)
TREE_OPERAND (ret, i) = ee;
}
return (ret ? fold (ret) : expr);
if (!ret)
return expr;
fold_defer_overflow_warnings ();
ret = fold (ret);
fold_undefer_and_ignore_overflow_warnings ();
return ret;
}
if (TREE_CODE (expr) != SSA_NAME)
@ -1053,11 +1059,18 @@ number_of_iterations_exit (struct loop *loop, edge exit,
if (!simple_iv (loop, stmt, op1, &iv1, false))
return false;
/* We don't want to see undefined signed overflow warnings while
computing the nmber of iterations. */
fold_defer_overflow_warnings ();
iv0.base = expand_simple_operations (iv0.base);
iv1.base = expand_simple_operations (iv1.base);
if (!number_of_iterations_cond (type, &iv0, code, &iv1, niter,
loop_only_exit_p (loop, exit)))
return false;
{
fold_undefer_and_ignore_overflow_warnings ();
return false;
}
if (optimize >= 3)
{
@ -1078,6 +1091,8 @@ number_of_iterations_exit (struct loop *loop, edge exit,
niter->may_be_zero,
&niter->additional_info);
fold_undefer_and_ignore_overflow_warnings ();
if (integer_onep (niter->assumptions))
return true;
@ -1376,6 +1391,9 @@ loop_niter_by_eval (struct loop *loop, edge exit)
}
}
/* Don't issue signed overflow warnings. */
fold_defer_overflow_warnings ();
for (i = 0; i < MAX_ITERATIONS_TO_TRACK; i++)
{
for (j = 0; j < 2; j++)
@ -1384,6 +1402,7 @@ loop_niter_by_eval (struct loop *loop, edge exit)
acnd = fold_binary (cmp, boolean_type_node, aval[0], aval[1]);
if (acnd && integer_zerop (acnd))
{
fold_undefer_and_ignore_overflow_warnings ();
if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file,
"Proved that loop %d iterates %d times using brute force.\n",
@ -1395,10 +1414,15 @@ loop_niter_by_eval (struct loop *loop, edge exit)
{
val[j] = get_val_for (next[j], val[j]);
if (!is_gimple_min_invariant (val[j]))
return chrec_dont_know;
{
fold_undefer_and_ignore_overflow_warnings ();
return chrec_dont_know;
}
}
}
fold_undefer_and_ignore_overflow_warnings ();
return chrec_dont_know;
}
@ -1994,10 +2018,16 @@ estimate_numbers_of_iterations (void)
loop_iterator li;
struct loop *loop;
/* We don't want to issue signed overflow warnings while getting
loop iteration estimates. */
fold_defer_overflow_warnings ();
FOR_EACH_LOOP (li, loop, 0)
{
estimate_numbers_of_iterations_loop (loop);
}
fold_undefer_and_ignore_overflow_warnings ();
}
/* Returns true if statement S1 dominates statement S2. */
@ -2153,6 +2183,9 @@ scev_probably_wraps_p (tree base, tree step,
if (use_overflow_semantics && nowrap_type_p (type))
return false;
/* Don't issue signed overflow warnings. */
fold_defer_overflow_warnings ();
/* Otherwise, compute the number of iterations before we reach the
bound of the type, and verify that the loop is exited before this
occurs. */
@ -2179,8 +2212,15 @@ scev_probably_wraps_p (tree base, tree step,
estimate_numbers_of_iterations_loop (loop);
for (bound = loop->bounds; bound; bound = bound->next)
if (n_of_executions_at_most (at_stmt, bound, valid_niter))
return false;
{
if (n_of_executions_at_most (at_stmt, bound, valid_niter))
{
fold_undefer_and_ignore_overflow_warnings ();
return false;
}
}
fold_undefer_and_ignore_overflow_warnings ();
/* At this point we still don't have a proof that the iv does not
overflow: give up. */

View File

@ -1,5 +1,5 @@
/* SSA Jump Threading
Copyright (C) 2005, 2006 Free Software Foundation, Inc.
Copyright (C) 2005, 2006, 2007 Free Software Foundation, Inc.
Contributed by Jeff Law <law@redhat.com>
This file is part of GCC.
@ -425,12 +425,17 @@ simplify_control_stmt_condition (edge e,
/* We absolutely do not care about any type conversions
we only care about a zero/nonzero value. */
fold_defer_overflow_warnings ();
cached_lhs = fold (COND_EXPR_COND (dummy_cond));
while (TREE_CODE (cached_lhs) == NOP_EXPR
|| TREE_CODE (cached_lhs) == CONVERT_EXPR
|| TREE_CODE (cached_lhs) == NON_LVALUE_EXPR)
cached_lhs = TREE_OPERAND (cached_lhs, 0);
fold_undefer_overflow_warnings (is_gimple_min_invariant (cached_lhs),
stmt, WARN_STRICT_OVERFLOW_CONDITIONAL);
/* If we have not simplified the condition down to an invariant,
then use the pass specific callback to simplify the condition. */
if (! is_gimple_min_invariant (cached_lhs))

View File

@ -414,7 +414,10 @@ symbolic_range_p (value_range_t *vr)
static bool
vrp_expr_computes_nonnegative (tree expr)
{
return tree_expr_nonnegative_p (expr);
bool ovf;
/* FIXME: May need to record overflow information here. */
return tree_expr_nonnegative_warnv_p (expr, &ovf);
}
/* Like tree_expr_nonzero_p, but this function uses value ranges
@ -423,7 +426,10 @@ vrp_expr_computes_nonnegative (tree expr)
static bool
vrp_expr_computes_nonzero (tree expr)
{
if (tree_expr_nonzero_p (expr))
bool ovf;
/* FIXME: May need to record overflow information here. */
if (tree_expr_nonzero_warnv_p (expr, &ovf))
return true;
/* If we have an expression of the form &X->a, then the expression
@ -1697,7 +1703,10 @@ extract_range_from_unary_expr (value_range_t *vr, tree expr)
determining if it evaluates to NULL [0, 0] or non-NULL (~[0, 0]). */
if (POINTER_TYPE_P (TREE_TYPE (expr)) || POINTER_TYPE_P (TREE_TYPE (op0)))
{
if (range_is_nonnull (&vr0) || tree_expr_nonzero_p (expr))
bool ovf;
/* FIXME: May need to record overflow information here. */
if (range_is_nonnull (&vr0) || tree_expr_nonzero_warnv_p (expr, &ovf))
set_value_range_to_nonnull (vr, TREE_TYPE (expr));
else if (range_is_null (&vr0))
set_value_range_to_null (vr, TREE_TYPE (expr));

View File

@ -3735,6 +3735,7 @@ extern int tree_int_cst_msb (tree);
extern int tree_int_cst_sgn (tree);
extern int tree_int_cst_sign_bit (tree);
extern bool tree_expr_nonnegative_p (tree);
extern bool tree_expr_nonnegative_warnv_p (tree, bool *);
extern bool may_negate_without_overflow_p (tree);
extern tree get_inner_array_type (tree);
@ -4333,6 +4334,10 @@ extern tree fold_single_bit_test (enum tree_code, tree, tree, tree);
extern tree fold_ignored_result (tree);
extern tree fold_abs_const (tree, tree);
extern tree fold_indirect_ref_1 (tree, tree);
extern void fold_defer_overflow_warnings (void);
extern void fold_undefer_overflow_warnings (bool, tree, int);
extern void fold_undefer_and_ignore_overflow_warnings (void);
extern bool fold_deferring_overflow_warnings_p (void);
extern tree force_fit_type_double (tree, unsigned HOST_WIDE_INT, HOST_WIDE_INT,
int, bool);
@ -4405,6 +4410,7 @@ extern bool ptr_difference_const (tree, tree, HOST_WIDE_INT *);
extern enum tree_code invert_tree_comparison (enum tree_code, bool);
extern bool tree_expr_nonzero_p (tree);
extern bool tree_expr_nonzero_warnv_p (tree, bool *);
/* In builtins.c */
extern tree fold_builtin (tree, tree, bool);