Index: gcc/doc/invoke.texi =================================================================== --- gcc/doc/invoke.texi (revision 120173) +++ gcc/doc/invoke.texi (working copy) @@ -230,7 +230,7 @@ Objective-C and Objective-C++ Dialects}. -Werror -Werror-* -Werror-implicit-function-declaration @gol -Wfatal-errors -Wfloat-equal -Wformat -Wformat=2 @gol -Wno-format-extra-args -Wformat-nonliteral @gol --Wformat-security -Wformat-y2k @gol +-Wformat-security -Wformat-y2k -Wfutile-unsigned-comparison @gol -Wimplicit -Wimplicit-function-declaration -Wimplicit-int @gol -Wimport -Wno-import -Winit-self -Winline @gol -Wno-int-to-pointer-cast @gol @@ -2883,7 +2883,9 @@ For example, an expression such as @samp but @samp{x[(void)i,j]} will not. @item -An unsigned value is compared against zero with @samp{<} or @samp{>=}. +An unsigned variable is compared against zero with @samp{<} or @samp{>=}. +This warning can be independently controlled by +@option{-Wfutile-unsigned-comparison}. @item Storage-class specifiers like @code{static} are not the first things in @@ -3177,6 +3179,11 @@ changed by the conversion like in @code{ An empty body occurs in an @samp{if} or @samp{else} statement. This warning is also enabled by @option{-Wextra}. +@item -Wfutile-unsigned-comparison +@opindex Wfutile-unsigned-comparison +An unsigned variable is compared against zero with @samp{<} or @samp{>=}. +This warning is also enabled by @option{-Wextra}. + @item -Wsign-compare @opindex Wsign-compare @cindex warning for comparison of signed and unsigned values Index: gcc/testsuite/gcc.dg/Wfutile-unsigned-comparison-no.c =================================================================== --- gcc/testsuite/gcc.dg/Wfutile-unsigned-comparison-no.c (revision 0) +++ gcc/testsuite/gcc.dg/Wfutile-unsigned-comparison-no.c (revision 0) @@ -0,0 +1,11 @@ +/* Test disabling -Wfutile-unsigned-comparison */ +/* { dg-do compile } */ +/* { dg-options "-Wextra -Wno-futile-unsigned-comparison" } */ + +void h(unsigned x) +{ + if (x < 0) return;/* { dg-bogus "comparison of unsigned expression < 0 is always false" } */ + if (x >= 0) return;/* { dg-bogus "comparison of unsigned expression >= 0 is always true" } */ + if (1U >= 0) return; + if (1U < 0) return; +} Index: gcc/testsuite/gcc.dg/Wfutile-unsigned-comparison-Wextra.c =================================================================== --- gcc/testsuite/gcc.dg/Wfutile-unsigned-comparison-Wextra.c (revision 0) +++ gcc/testsuite/gcc.dg/Wfutile-unsigned-comparison-Wextra.c (revision 0) @@ -0,0 +1,11 @@ +/* Test that -Wfutile-unsigned-comparison is enabled by -Wextra */ +/* { dg-do compile } */ +/* { dg-options "-Wextra" } */ + +void h(unsigned x) +{ + if (x < 0) return;/* { dg-warning "comparison of unsigned expression < 0 is always false" } */ + if (x >= 0) return;/* { dg-warning "comparison of unsigned expression >= 0 is always true" } */ + if (1U >= 0) return; + if (1U < 0) return; +} Index: gcc/testsuite/gcc.dg/Wfutile-unsigned-comparison.c =================================================================== --- gcc/testsuite/gcc.dg/Wfutile-unsigned-comparison.c (revision 0) +++ gcc/testsuite/gcc.dg/Wfutile-unsigned-comparison.c (revision 0) @@ -0,0 +1,10 @@ +/* { dg-do compile } */ +/* { dg-options "-Wfutile-unsigned-comparison" } */ + +void h(unsigned x) +{ + if (x < 0) return;/* { dg-warning "comparison of unsigned expression < 0 is always false" } */ + if (x >= 0) return;/* { dg-warning "comparison of unsigned expression >= 0 is always true" } */ + if (1U >= 0) return; + if (1U < 0) return; +} Index: gcc/testsuite/g++.dg/warn/Wfutile-unsigned-comparison.C =================================================================== --- gcc/testsuite/g++.dg/warn/Wfutile-unsigned-comparison.C (revision 0) +++ gcc/testsuite/g++.dg/warn/Wfutile-unsigned-comparison.C (revision 0) @@ -0,0 +1,10 @@ +/* { dg-do compile } */ +/* { dg-options "-Wfutile-unsigned-comparison" } */ + +void h(unsigned x) +{ + if (x < 0) return;/* { dg-warning "comparison of unsigned expression < 0 is always false" } */ + if (x >= 0) return;/* { dg-warning "comparison of unsigned expression >= 0 is always true" } */ + if (1U >= 0) return; + if (1U < 0) return; +} Index: gcc/testsuite/g++.dg/warn/Wfutile-unsigned-comparison-Wextra.C =================================================================== --- gcc/testsuite/g++.dg/warn/Wfutile-unsigned-comparison-Wextra.C (revision 0) +++ gcc/testsuite/g++.dg/warn/Wfutile-unsigned-comparison-Wextra.C (revision 0) @@ -0,0 +1,11 @@ +/* Test that -Wfutile-unsigned-comparison is enabled by -Wextra */ +/* { dg-do compile } */ +/* { dg-options "-Wextra" } */ + +void h(unsigned x) +{ + if (x < 0) return;/* { dg-warning "comparison of unsigned expression < 0 is always false" } */ + if (x >= 0) return;/* { dg-warning "comparison of unsigned expression >= 0 is always true" } */ + if (1U >= 0) return; + if (1U < 0) return; +} Index: gcc/testsuite/g++.dg/warn/Wfutile-unsigned-comparison-no.C =================================================================== --- gcc/testsuite/g++.dg/warn/Wfutile-unsigned-comparison-no.C (revision 0) +++ gcc/testsuite/g++.dg/warn/Wfutile-unsigned-comparison-no.C (revision 0) @@ -0,0 +1,11 @@ +/* Test disabling -Wfutile-unsigned-comparison */ +/* { dg-do compile } */ +/* { dg-options "-Wextra -Wno-futile-unsigned-comparison" } */ + +void h(unsigned x) +{ + if (x < 0) return;/* { dg-bogus "comparison of unsigned expression < 0 is always false" } */ + if (x >= 0) return;/* { dg-bogus "comparison of unsigned expression >= 0 is always true" } */ + if (1U >= 0) return; + if (1U < 0) return; +} Index: gcc/c.opt =================================================================== --- gcc/c.opt (revision 120173) +++ gcc/c.opt (working copy) @@ -224,6 +224,10 @@ Warn about zero-length formats Wformat= C ObjC C++ ObjC++ Joined +Wfutile-unsigned-comparison +C ObjC C++ ObjC++ Var(warn_futile_unsigned_comparison) Init(-1) +Warn about comparison of unsigned variables against zero with < or >= + Winit-self C ObjC C++ ObjC++ Var(warn_init_self) Warn about variables which are initialized to themselves Index: gcc/c-opts.c =================================================================== --- gcc/c-opts.c (revision 120173) +++ gcc/c-opts.c (working copy) @@ -1025,13 +1025,16 @@ c_common_post_options (const char **pfil if (flag_objc_exceptions && !flag_objc_sjlj_exceptions) flag_exceptions = 1; - /* -Wextra implies -Wclobbered, -Wempty-body, -Wsign-compare, + /* -Wextra implies -Wclobbered, -Wempty-body, + -Wfutile-unsigned-comparison, -Wsign-compare, -Wmissing-field-initializers, -Wmissing-parameter-type and -Woverride-init, but not if explicitly overridden. */ if (warn_clobbered == -1) warn_clobbered = extra_warnings; if (warn_empty_body == -1) warn_empty_body = extra_warnings; + if (warn_futile_unsigned_comparison == -1) + warn_futile_unsigned_comparison = extra_warnings; if (warn_sign_compare == -1) warn_sign_compare = extra_warnings; if (warn_missing_field_initializers == -1) Index: gcc/c-common.c =================================================================== --- gcc/c-common.c (revision 120173) +++ gcc/c-common.c (working copy) @@ -2463,24 +2463,27 @@ shorten_compare (tree *op0_ptr, tree *op switch (code) { case GE_EXPR: - /* All unsigned values are >= 0, so we warn if extra warnings - are requested. However, if OP0 is a constant that is - >= 0, the signedness of the comparison isn't an issue, - so suppress the warning. */ - if (extra_warnings && !in_system_header + /* All unsigned values are >= 0, so we warn if + Wfutile-unsigned-comparison is requested. However, + if OP0 is a constant that is >= 0, the signedness of + the comparison isn't an issue, so suppress the + warning. */ + if (warn_futile_unsigned_comparison && !in_system_header && !(TREE_CODE (primop0) == INTEGER_CST && !TREE_OVERFLOW (convert (c_common_signed_type (type), primop0)))) - warning (0, "comparison of unsigned expression >= 0 is always true"); + warning (OPT_Wfutile_unsigned_comparison, + "comparison of unsigned expression >= 0 is always true"); value = truthvalue_true_node; break; case LT_EXPR: - if (extra_warnings && !in_system_header + if (warn_futile_unsigned_comparison && !in_system_header && !(TREE_CODE (primop0) == INTEGER_CST && !TREE_OVERFLOW (convert (c_common_signed_type (type), primop0)))) - warning (0, "comparison of unsigned expression < 0 is always false"); + warning (OPT_Wfutile_unsigned_comparison, + "comparison of unsigned expression < 0 is always false"); value = truthvalue_false_node; break;