Walways-true:Warn if a comparison is always true or always false due to the limited range of the data type

Manuel López-Ibáñez lopezibanez@gmail.com
Sun Mar 4 13:28:00 GMT 2007


:ADDPATCH c/c++:

A new warning option Walways-true takes over from Wextra the function
of warning about comparison of unsigned variables against zero with <
or >=. To keep current behaviour, Walways-true is also enabled by
Wextra.

Walways-true also includes an unnamed warning for comparisons that are
always true because of type range limits. (This is the warning that
RMS was talking about sometime ago).

This patch affects a few PRs.

PR 29694 and 23587 are about the inconsistency of having some warnings
in Wextra and others issued unconditionally. Thus, this patch fixes
those.

PR 11856 is about warning for templates. This patch is not a
definitive fix, since Gabriel Dos Reis thinks that we should not warn
at all,  but it is a partial fix, since at least it gives to the user
the option of disabling the warning (and it allows the use #pragma
machinery), instead of using -w.


PR 12963 asks for a way to disable the unconditional warning without
using -w. This patch fixes that.


I took testcases from the PRs, bootstrapped and regression tested with
--enable-languages=all for i686-pc-linux-gnu.


Ok for mainline?

Manuel.


2007-03-04 Manuel Lopez-Ibanez <manu@gcc.gnu.org>

 PR middle-end/7651
 PR c++/11856
 PR c/12963
 PR c/23587
 PR other/29694
 * c.opt (Walways-true): New.
 * doc/invoke.texi (Walways-true): Document it.
 (Wextra): Enabled by -Wextra.
 * c-opts.c (c_common_post_options): Enabled by -Wextra.
 * c-common.c (shorten_compare): Warn with Walways-true.

testsuite/
2007-03-04  Manuel Lopez-Ibanez  <manu@gcc.gnu.org>

 PR middle-end/7651
 PR c++/11856
 PR c/12963
 PR c/23587
 PR other/29694
 * gcc.dg/compare6.c: Replace Wall with Walways-true.
 * gcc.dg/Walways-true.c: New.
 * gcc.dg/Walways-true-Wextra.c: New.
 * gcc.dg/Walways-true-no.c: New.
 * g++.dg/warn/Walways-true.C: New.
 * g++.dg/warn/Walways-true-Wextra.C: New.
 * g++.dg/warn/Walways-true-no.C: New.
-------------- next part --------------
Index: gcc/doc/invoke.texi
===================================================================
--- gcc/doc/invoke.texi	(revision 122472)
+++ gcc/doc/invoke.texi	(working copy)
@@ -223,7 +223,7 @@ Objective-C and Objective-C++ Dialects}.
 @item Warning Options
 @xref{Warning Options,,Options to Request or Suppress Warnings}.
 @gccoptlist{-fsyntax-only  -pedantic  -pedantic-errors @gol
--w  -Wextra  -Wall  -Waddress  -Waggregate-return -Warray-bounds @gol
+-w  -Wextra  -Wall  -Waddress  -Waggregate-return  -Walways-true  -Warray-bounds @gol
 -Wno-attributes -Wc++-compat -Wc++0x-compat -Wcast-align  -Wcast-qual  @gol
 -Wchar-subscripts -Wclobbered  -Wcomment @gol
 -Wconversion -Wcoverage-mismatch -Wno-deprecated-declarations @gol
@@ -3072,7 +3072,11 @@ foo (a)
 @end smallexample
 
 @item
-An unsigned value is compared against zero with @samp{<} or @samp{>=}.
+Warn if a comparison is always true or always false due to the limited
+range of the data type, but do not warn for constant expressions.  For
+example, warn if an unsigned variable is compared against zero with
+@samp{<} or @samp{>=}.  This warning can be independently controlled
+by @option{-Walways-true}.
 
 @item @r{(C only)}
 Storage-class specifiers like @code{static} are not the first things
@@ -3308,6 +3312,15 @@ convenience in calculations with @code{v
 to functions.  In C++, warn also when an arithmetic operation involves
 @code{NULL}.  This warning is also enabled by @option{-pedantic}.
 
+@item -Walways-true
+@opindex Walways-true
+@opindex Wno-always-true
+Warn if a comparison is always true or always false due to the limited
+range of the data type, but do not warn for constant expressions.  For
+example, warn if an unsigned variable is compared against zero with
+@samp{<} or @samp{>=}.  This warning is also enabled by
+@option{-Wextra}.
+
 @item -Wbad-function-cast @r{(C only)}
 @opindex Wbad-function-cast
 Warn whenever a function call is cast to a non-matching type.
Index: gcc/testsuite/gcc.dg/Walways-true.c
===================================================================
--- gcc/testsuite/gcc.dg/Walways-true.c	(revision 0)
+++ gcc/testsuite/gcc.dg/Walways-true.c	(revision 0)
@@ -0,0 +1,66 @@
+/* { dg-do compile } */
+/* { dg-options "-Walways-true" } */
+
+
+
+void a (unsigned char x)
+{
+  if (x < 0)  return;/* { dg-warning "comparison is always false due to limited range of data type" } */
+  if (x >= 0) return;/* { dg-warning "comparison is always true due to limited range of data type" } */
+  if (0 > x)  return;/* { dg-warning "comparison is always false due to limited range of data type" } */
+  if (0 <= x) return;/* { dg-warning "comparison is always true due to limited range of data type" } */
+  if (x <= 255) /* { dg-warning "comparison is always true due to limited range of data type" } */
+    return;
+  if (255 >= x) /* { dg-warning "comparison is always true due to limited range of data type" } */
+    return;
+  if ((int)x <= 255) /* { dg-bogus "comparison is always true due to limited range of data type" "" { xfail *-*-* } 16 } */
+    return;
+  if (255 >= (unsigned char) 1)
+    return;
+
+}
+
+void b (unsigned short x)
+{
+  if (x < 0)  return;/* { dg-warning "comparison is always false due to limited range of data type" } */
+  if (x >= 0) return;/* { dg-warning "comparison is always true due to limited range of data type" } */
+  if (0 > x)  return;/* { dg-warning "comparison is always false due to limited range of data type" } */
+  if (0 <= x) return;/* { dg-warning "comparison is always true due to limited range of data type" } */
+}
+
+void c (unsigned int 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 (0 > x)  return;/* { dg-warning "comparison of unsigned expression < 0 is always false" } */
+  if (0 <= x) return;/* { dg-warning "comparison of unsigned expression >= 0 is always true" } */
+  if (1U >= 0) return;
+  if (1U < 0) return;
+  if (0 <= 1U) return;
+  if (0 > 1U) return;
+}
+
+void d (unsigned long 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 (0 > x)  return;/* { dg-warning "comparison of unsigned expression < 0 is always false" } */
+  if (0 <= x) return;/* { dg-warning "comparison of unsigned expression >= 0 is always true" } */
+}
+
+void e (unsigned long long 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 (0 > x)  return;/* { dg-warning "comparison of unsigned expression < 0 is always false" } */
+  if (0 <= x) return;/* { dg-warning "comparison of unsigned expression >= 0 is always true" } */
+}
+
+int test (int x) 
+{
+  if ((long long)x <= 0x123456789ABCLL) /* { dg-bogus "comparison is always true due to limited range of data type" "" { xfail *-*-* } 61 } */
+    return 1;
+  else 
+    return 0;
+}
+
Index: gcc/testsuite/gcc.dg/compare6.c
===================================================================
--- gcc/testsuite/gcc.dg/compare6.c	(revision 122472)
+++ gcc/testsuite/gcc.dg/compare6.c	(working copy)
@@ -1,7 +1,7 @@
 /* PR c/2098 */
 /* Test for a warning on comparison on out-of-range data.  */
 /* { dg-do compile { xfail c4x-*-* } } */
-/* { dg-options "-Wall" } */
+/* { dg-options "-Walways-true" } */
 
 signed char sc;
 unsigned char uc;
Index: gcc/testsuite/gcc.dg/Walways-true-Wextra.c
===================================================================
--- gcc/testsuite/gcc.dg/Walways-true-Wextra.c	(revision 0)
+++ gcc/testsuite/gcc.dg/Walways-true-Wextra.c	(revision 0)
@@ -0,0 +1,66 @@
+/* Test that -Walways-true is enabled by -Wextra */
+/* { dg-do compile } */
+/* { dg-options "-Wextra" } */
+
+
+void a (unsigned char x)
+{
+  if (x < 0)  return;/* { dg-warning "comparison is always false due to limited range of data type" } */
+  if (x >= 0) return;/* { dg-warning "comparison is always true due to limited range of data type" } */
+  if (0 > x)  return;/* { dg-warning "comparison is always false due to limited range of data type" } */
+  if (0 <= x) return;/* { dg-warning "comparison is always true due to limited range of data type" } */
+  if (x <= 255) /* { dg-warning "comparison is always true due to limited range of data type" } */
+    return;
+  if (255 >= x) /* { dg-warning "comparison is always true due to limited range of data type" } */
+    return;
+  if ((int)x <= 255) /* { dg-bogus "comparison is always true due to limited range of data type" "" { xfail *-*-* } 16 } */
+    return;
+  if (255 >= (unsigned char) 1)
+    return;
+
+}
+
+void b (unsigned short x)
+{
+  if (x < 0)  return;/* { dg-warning "comparison is always false due to limited range of data type" } */
+  if (x >= 0) return;/* { dg-warning "comparison is always true due to limited range of data type" } */
+  if (0 > x)  return;/* { dg-warning "comparison is always false due to limited range of data type" } */
+  if (0 <= x) return;/* { dg-warning "comparison is always true due to limited range of data type" } */
+}
+
+void c (unsigned int 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 (0 > x)  return;/* { dg-warning "comparison of unsigned expression < 0 is always false" } */
+  if (0 <= x) return;/* { dg-warning "comparison of unsigned expression >= 0 is always true" } */
+  if (1U >= 0) return;
+  if (1U < 0) return;
+  if (0 <= 1U) return;
+  if (0 > 1U) return;
+}
+
+void d (unsigned long 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 (0 > x)  return;/* { dg-warning "comparison of unsigned expression < 0 is always false" } */
+  if (0 <= x) return;/* { dg-warning "comparison of unsigned expression >= 0 is always true" } */
+}
+
+void e (unsigned long long 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 (0 > x)  return;/* { dg-warning "comparison of unsigned expression < 0 is always false" } */
+  if (0 <= x) return;/* { dg-warning "comparison of unsigned expression >= 0 is always true" } */
+}
+
+int test (int x) 
+{
+  if ((long long)x <= 0x123456789ABCLL) /* { dg-bogus "comparison is always true due to limited range of data type" "" { xfail *-*-* } 61 } */
+    return 1;
+  else 
+    return 0;
+}
+
Index: gcc/testsuite/gcc.dg/Walways-true-no.c
===================================================================
--- gcc/testsuite/gcc.dg/Walways-true-no.c	(revision 0)
+++ gcc/testsuite/gcc.dg/Walways-true-no.c	(revision 0)
@@ -0,0 +1,66 @@
+/* Test disabling -Walways-true */
+/* { dg-do compile } */
+/* { dg-options "-Wextra -Wno-always-true" } */
+
+
+void a (unsigned char x)
+{
+  if (x < 0)  return;/* { dg-bogus "comparison is always false due to limited range of data type" } */
+  if (x >= 0) return;/* { dg-bogus "comparison is always true due to limited range of data type" } */
+  if (0 > x)  return;/* { dg-bogus "comparison is always false due to limited range of data type" } */
+  if (0 <= x) return;/* { dg-bogus "comparison is always true due to limited range of data type" } */
+  if (x <= 255) /* { dg-bogus "comparison is always true due to limited range of data type" } */
+    return;
+  if (255 >= x) /* { dg-bogus "comparison is always true due to limited range of data type" } */
+    return;
+  if ((int)x <= 255)
+    return;
+  if (255 >= (unsigned char) 1)
+    return;
+
+}
+
+void b (unsigned short x)
+{
+  if (x < 0)  return;/* { dg-bogus "comparison is always false due to limited range of data type" } */
+  if (x >= 0) return;/* { dg-bogus "comparison is always true due to limited range of data type" } */
+  if (0 > x)  return;/* { dg-bogus "comparison is always false due to limited range of data type" } */
+  if (0 <= x) return;/* { dg-bogus "comparison is always true due to limited range of data type" } */
+}
+
+void c (unsigned int 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 (0 > x)  return;/* { dg-bogus "comparison of unsigned expression < 0 is always false" } */
+  if (0 <= x) return;/* { dg-bogus "comparison of unsigned expression >= 0 is always true" } */
+  if (1U >= 0) return;
+  if (1U < 0) return;
+  if (0 <= 1U) return;
+  if (0 > 1U) return;
+}
+
+void d (unsigned long 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 (0 > x)  return;/* { dg-bogus "comparison of unsigned expression < 0 is always false" } */
+  if (0 <= x) return;/* { dg-bogus "comparison of unsigned expression >= 0 is always true" } */
+}
+
+void e (unsigned long long 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 (0 > x)  return;/* { dg-bogus "comparison of unsigned expression < 0 is always false" } */
+  if (0 <= x) return;/* { dg-bogus "comparison of unsigned expression >= 0 is always true" } */
+}
+
+int test (int x) 
+{
+  if ((long long)x <= 0x123456789ABCLL) 
+    return 1;
+  else 
+    return 0;
+}
+
Index: gcc/testsuite/g++.dg/warn/Walways-true-Wextra.C
===================================================================
--- gcc/testsuite/g++.dg/warn/Walways-true-Wextra.C	(revision 0)
+++ gcc/testsuite/g++.dg/warn/Walways-true-Wextra.C	(revision 0)
@@ -0,0 +1,84 @@
+/* Test that -Walways-true is enabled by -Wextra.  */
+/* { dg-do compile } */
+/* { dg-options "-Wextra" } */
+extern void assert (int);
+
+void a (unsigned char x)
+{
+  if (x < 0)  return;/* { dg-warning "comparison is always false due to limited range of data type" } */
+  if (x >= 0) return;/* { dg-warning "comparison is always true due to limited range of data type" } */
+  if (0 > x)  return;/* { dg-warning "comparison is always false due to limited range of data type" } */
+  if (0 <= x) return;/* { dg-warning "comparison is always true due to limited range of data type" } */
+  if (x <= 255) /* { dg-warning "comparison is always true due to limited range of data type" } */
+    return;
+  if (255 >= x) /* { dg-warning "comparison is always true due to limited range of data type" } */
+    return;
+  if ((int)x <= 255) /* { dg-bogus "comparison is always true due to limited range of data type" "" { xfail *-*-* } 16 } */
+    return;
+  if (255 >= (unsigned char) 1)
+    return;
+
+}
+
+void b (unsigned short x)
+{
+  if (x < 0)  return;/* { dg-warning "comparison is always false due to limited range of data type" } */
+  if (x >= 0) return;/* { dg-warning "comparison is always true due to limited range of data type" } */
+  if (0 > x)  return;/* { dg-warning "comparison is always false due to limited range of data type" } */
+  if (0 <= x) return;/* { dg-warning "comparison is always true due to limited range of data type" } */
+}
+
+void c (unsigned int 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 (0 > x)  return;/* { dg-warning "comparison of unsigned expression < 0 is always false" } */
+  if (0 <= x) return;/* { dg-warning "comparison of unsigned expression >= 0 is always true" } */
+  if (1U >= 0) return;
+  if (1U < 0) return;
+  if (0 <= 1U) return;
+  if (0 > 1U) return;
+}
+
+void d (unsigned long 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 (0 > x)  return;/* { dg-warning "comparison of unsigned expression < 0 is always false" } */
+  if (0 <= x) return;/* { dg-warning "comparison of unsigned expression >= 0 is always true" } */
+}
+
+void e (unsigned long long 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 (0 > x)  return;/* { dg-warning "comparison of unsigned expression < 0 is always false" } */
+  if (0 <= x) return;/* { dg-warning "comparison of unsigned expression >= 0 is always true" } */
+}
+
+int test (int x) 
+{
+  if ((long long)x <= 0x123456789ABCLL) /* { dg-bogus "comparison is always true due to limited range of data type" "" { xfail *-*-* } 61 } */
+    return 1;
+  else 
+    return 0;
+}
+
+template <typename Int, Int D>
+void f(Int x) {
+  assert(0 <= x and x <= D); // { dg-warning "comparison is always true due to limited range of data type" }
+}
+
+int ff(void) {
+  f<unsigned char, 2>(5);
+  f<signed char, 2>(5);
+}
+
+template <typename Int, Int D>
+void g(void) {
+  assert(0 <= D);
+}
+int gg(void) {
+  g<unsigned char, 2>();
+}
+
Index: gcc/testsuite/g++.dg/warn/Walways-true.C
===================================================================
--- gcc/testsuite/g++.dg/warn/Walways-true.C	(revision 0)
+++ gcc/testsuite/g++.dg/warn/Walways-true.C	(revision 0)
@@ -0,0 +1,84 @@
+/* { dg-do compile } */
+/* { dg-options "-Walways-true" } */
+
+extern void assert (int);
+
+void a (unsigned char x)
+{
+  if (x < 0)  return;/* { dg-warning "comparison is always false due to limited range of data type" } */
+  if (x >= 0) return;/* { dg-warning "comparison is always true due to limited range of data type" } */
+  if (0 > x)  return;/* { dg-warning "comparison is always false due to limited range of data type" } */
+  if (0 <= x) return;/* { dg-warning "comparison is always true due to limited range of data type" } */
+  if (x <= 255) /* { dg-warning "comparison is always true due to limited range of data type" } */
+    return;
+  if (255 >= x) /* { dg-warning "comparison is always true due to limited range of data type" } */
+    return;
+  if ((int)x <= 255) /* { dg-bogus "comparison is always true due to limited range of data type" "" { xfail *-*-* } 16 } */
+    return;
+  if (255 >= (unsigned char) 1)
+    return;
+
+}
+
+void b (unsigned short x)
+{
+  if (x < 0)  return;/* { dg-warning "comparison is always false due to limited range of data type" } */
+  if (x >= 0) return;/* { dg-warning "comparison is always true due to limited range of data type" } */
+  if (0 > x)  return;/* { dg-warning "comparison is always false due to limited range of data type" } */
+  if (0 <= x) return;/* { dg-warning "comparison is always true due to limited range of data type" } */
+}
+
+void c (unsigned int 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 (0 > x)  return;/* { dg-warning "comparison of unsigned expression < 0 is always false" } */
+  if (0 <= x) return;/* { dg-warning "comparison of unsigned expression >= 0 is always true" } */
+  if (1U >= 0) return;
+  if (1U < 0) return;
+  if (0 <= 1U) return;
+  if (0 > 1U) return;
+}
+
+void d (unsigned long 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 (0 > x)  return;/* { dg-warning "comparison of unsigned expression < 0 is always false" } */
+  if (0 <= x) return;/* { dg-warning "comparison of unsigned expression >= 0 is always true" } */
+}
+
+void e (unsigned long long 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 (0 > x)  return;/* { dg-warning "comparison of unsigned expression < 0 is always false" } */
+  if (0 <= x) return;/* { dg-warning "comparison of unsigned expression >= 0 is always true" } */
+}
+
+int test (int x) 
+{
+  if ((long long)x <= 0x123456789ABCLL) /* { dg-bogus "comparison is always true due to limited range of data type" "" { xfail *-*-* } 61 } */
+    return 1;
+  else 
+    return 0;
+}
+
+template <typename Int, Int D>
+void f(Int x) {
+  assert(0 <= x and x <= D); // { dg-warning "comparison is always true due to limited range of data type" }
+}
+
+int ff(void) {
+  f<unsigned char, 2>(5);
+  f<signed char, 2>(5);
+}
+
+template <typename Int, Int D>
+void g(void) {
+  assert(0 <= D);
+}
+int gg(void) {
+  g<unsigned char, 2>();
+}
+
Index: gcc/testsuite/g++.dg/warn/Walways-true-no.C
===================================================================
--- gcc/testsuite/g++.dg/warn/Walways-true-no.C	(revision 0)
+++ gcc/testsuite/g++.dg/warn/Walways-true-no.C	(revision 0)
@@ -0,0 +1,84 @@
+/* Test disabling -Walways-true.  */
+/* { dg-do compile } */
+/* { dg-options "-Wextra -Wno-always-true" } */
+extern void assert (int);
+
+void a (unsigned char x)
+{
+  if (x < 0)  return;/* { dg-bogus "comparison is always false due to limited range of data type" } */
+  if (x >= 0) return;/* { dg-bogus "comparison is always true due to limited range of data type" } */
+  if (0 > x)  return;/* { dg-bogus "comparison is always false due to limited range of data type" } */
+  if (0 <= x) return;/* { dg-bogus "comparison is always true due to limited range of data type" } */
+  if (x <= 255) /* { dg-bogus "comparison is always true due to limited range of data type" } */
+    return;
+  if (255 >= x) /* { dg-bogus "comparison is always true due to limited range of data type" } */
+    return;
+  if ((int)x <= 255) 
+    return;
+  if (255 >= (unsigned char) 1)
+    return;
+
+}
+
+void b (unsigned short x)
+{
+  if (x < 0)  return;/* { dg-bogus "comparison is always false due to limited range of data type" } */
+  if (x >= 0) return;/* { dg-bogus "comparison is always true due to limited range of data type" } */
+  if (0 > x)  return;/* { dg-bogus "comparison is always false due to limited range of data type" } */
+  if (0 <= x) return;/* { dg-bogus "comparison is always true due to limited range of data type" } */
+}
+
+void c (unsigned int 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 (0 > x)  return;/* { dg-bogus "comparison of unsigned expression < 0 is always false" } */
+  if (0 <= x) return;/* { dg-bogus "comparison of unsigned expression >= 0 is always true" } */
+  if (1U >= 0) return;
+  if (1U < 0) return;
+  if (0 <= 1U) return;
+  if (0 > 1U) return;
+}
+
+void d (unsigned long 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 (0 > x)  return;/* { dg-bogus "comparison of unsigned expression < 0 is always false" } */
+  if (0 <= x) return;/* { dg-bogus "comparison of unsigned expression >= 0 is always true" } */
+}
+
+void e (unsigned long long 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 (0 > x)  return;/* { dg-bogus "comparison of unsigned expression < 0 is always false" } */
+  if (0 <= x) return;/* { dg-bogus "comparison of unsigned expression >= 0 is always true" } */
+}
+
+int test (int x) 
+{
+  if ((long long)x <= 0x123456789ABCLL) /* { dg-bogus "comparison is always true due to limited range of data type" } */
+    return 1;
+  else 
+    return 0;
+}
+
+template <typename Int, Int D>
+void f(Int x) {
+  assert(0 <= x and x <= D); // { dg-bogus "comparison is always true due to limited range of data type" }
+}
+
+int ff(void) {
+  f<unsigned char, 2>(5);
+  f<signed char, 2>(5);
+}
+
+template <typename Int, Int D>
+void g(void) {
+  assert(0 <= D);
+}
+int gg(void) {
+  g<unsigned char, 2>();
+}
+
Index: gcc/c.opt
===================================================================
--- gcc/c.opt	(revision 122472)
+++ gcc/c.opt	(working copy)
@@ -124,6 +124,10 @@ Wall
 C ObjC C++ ObjC++ Warning
 Enable most warning messages
 
+Walways-true
+C ObjC C++ ObjC++ Var(warn_always_true) Init(-1) Warning
+Warn if a comparison is always true or always false due to the limited range of the data type
+
 Wassign-intercept
 ObjC ObjC++ Var(warn_assign_intercept) Warning
 Warn whenever an Objective-C assignment is being intercepted by the garbage collector
Index: gcc/c-opts.c
===================================================================
--- gcc/c-opts.c	(revision 122472)
+++ gcc/c-opts.c	(working copy)
@@ -1034,10 +1034,13 @@ 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 -Walways-true, -Wclobbered, 
+     -Wempty-body, -Wsign-compare, 
      -Wmissing-field-initializers, -Wmissing-parameter-type
      -Wold-style-declaration, and -Woverride-init, 
      but not if explicitly overridden.  */
+  if (warn_always_true == -1)
+    warn_always_true = extra_warnings;
   if (warn_clobbered == -1)
     warn_clobbered = extra_warnings;
   if (warn_empty_body == -1)
Index: gcc/c-common.c
===================================================================
--- gcc/c-common.c	(revision 122472)
+++ gcc/c-common.c	(working copy)
@@ -2433,9 +2433,9 @@ shorten_compare (tree *op0_ptr, tree *op
       if (TREE_CODE (primop0) != INTEGER_CST)
 	{
 	  if (val == truthvalue_false_node)
-	    warning (0, "comparison is always false due to limited range of data type");
+	    warning (OPT_Walways_true, "comparison is always false due to limited range of data type");
 	  if (val == truthvalue_true_node)
-	    warning (0, "comparison is always true due to limited range of data type");
+	    warning (OPT_Walways_true, "comparison is always true due to limited range of data type");
 	}
 
       if (val != 0)
@@ -2505,24 +2505,26 @@ 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.  However,
+		 if OP0 is a constant that is >= 0, the signedness of
+		 the comparison isn't an issue, so suppress the
+		 warning.  */
+	      if (warn_always_true && !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_Walways_true, 
+			 "comparison of unsigned expression >= 0 is always true");
 	      value = truthvalue_true_node;
 	      break;
 
 	    case LT_EXPR:
-	      if (extra_warnings && !in_system_header
+	      if (warn_always_true && !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_Walways_true, 
+			 "comparison of unsigned expression < 0 is always false");
 	      value = truthvalue_false_node;
 	      break;
 


More information about the Gcc-patches mailing list