Bug 59098 - Unwarranted warning: promoted ~unsigned is always non-zero [-Wsign-compare]
Summary: Unwarranted warning: promoted ~unsigned is always non-zero [-Wsign-compare]
Status: RESOLVED DUPLICATE of bug 107465
Alias: None
Product: gcc
Classification: Unclassified
Component: c (show other bugs)
Version: 4.8.2
: P3 minor
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: diagnostic
Depends on:
Blocks:
 
Reported: 2013-11-13 01:37 UTC by jmattsson
Modified: 2023-05-20 04:33 UTC (History)
1 user (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2014-08-20 00:00:00


Attachments
Tiny test case for this issue (241 bytes, text/plain)
2013-11-13 01:37 UTC, jmattsson
Details

Note You need to log in before you can comment on or make changes to this bug.
Description jmattsson 2013-11-13 01:37:15 UTC
Created attachment 31202 [details]
Tiny test case for this issue

We recently switched to compiling existing warning-free code from IAR to gcc, and are seeing "warning: promoted ~unsigned is always non-zero" for lines like this:

  return (val ^ (small_type_t)0xfffffffful) == 0;

where "val" is of type "small_type_t" and "small_type_t" is typedef'd elsewhere depending on the target platform/project to a uint8_t/uint16_t/uint32_t. The code produced is correct, with or without optimization enabled.

Rewriting the code into two lines removes the warning:

  small_type_t mask = (small_type_t)0xfffffffful;
  return (val ^ mask) == 0;


As far as we can tell, the warning in the above is unwarranted and incorrect, given that correct output is produced. It appears what the warning is really trying to catch is this:

  return ~val == 0;

which due to promotion before the tilde application, does in fact end up always non-zero and probably not what was intended/expected by the developer. Gcc however also warns about

  return (small_type_t)~val == 0;

despite this producing the expected correct behavior.


We see this both on gcc 4.7.3 and 4.8.2 (and presumably others, but we haven't tested).

$ gcc -v
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/4.8/lto-wrapper
Target: x86_64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Debian 4.8.2-1' --with-bugurl=file:///usr/share/doc/gcc-4.8/README.Bugs --enable-languages=c,c++,java,go,d,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-4.8 --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.8 --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --enable-gnu-unique-object --enable-plugin --with-system-zlib --disable-browser-plugin --enable-java-awt=gtk --enable-gtk-cairo --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-4.8-amd64/jre --enable-java-home --with-jvm-root-dir=/usr/lib/jvm/java-1.5.0-gcj-4.8-amd64 --with-jvm-jar-dir=/usr/lib/jvm-exports/java-1.5.0-gcj-4.8-amd64 --with-arch-directory=amd64 --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --enable-objc-gc --enable-multiarch --with-arch-32=i586 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu
Thread model: posix
gcc version 4.8.2 (Debian 4.8.2-1)

$ gcc -v
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/4.7/lto-wrapper
Target: x86_64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Ubuntu/Linaro 4.7.3-1ubuntu1' --with-bugurl=file:///usr/share/doc/gcc-4.7/README.Bugs --enable-languages=c,c++,go,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-4.7 --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.7 --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --enable-gnu-unique-object --enable-plugin --with-system-zlib --enable-objc-gc --with-cloog --enable-cloog-backend=ppl --disable-cloog-version-check --disable-ppl-version-check --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu
Thread model: posix
gcc version 4.7.3 (Ubuntu/Linaro 4.7.3-1ubuntu1)
Comment 1 Manuel López-Ibáñez 2013-11-13 03:09:42 UTC
Possibly related to bug 38341.

Note also that this simple change:

Index: c-common.c
===================================================================
--- c-common.c  (revision 204219)
+++ c-common.c  (working copy)
@@ -11236,11 +11236,11 @@ warn_for_sign_compare (location_t locati
             {
               mask = (~ (HOST_WIDE_INT) 0) << bits;
               if ((mask & constant) != mask)
                {
                  if (constant == 0)
-                   warning (OPT_Wsign_compare,
+                   warning_at (location, OPT_Wsign_compare,
                             "promoted ~unsigned is always non-zero");
                  else
                    warning_at (location, OPT_Wsign_compare,
                                "comparison of promoted ~unsigned with constant");
                }


improves the caret information from:

small.c:6:3: warning: promoted ~unsigned is always non-zero [-Wsign-compare]
   return (val ^ (small_type_t)0xfffffffful) == 0;
   ^

to:

small.c:6:45: warning: promoted ~unsigned is always non-zero [-Wsign-compare]
   return (val ^ (small_type_t)0xfffffffful) != 0;
                                             ^
Comment 2 Manuel López-Ibáñez 2014-08-20 23:46:02 UTC
I think this is confirmed.
Comment 3 fenugrec 2015-05-02 03:32:23 UTC
Probable duplicate of Bug 38341
Comment 4 Manuel López-Ibáñez 2015-05-02 07:44:17 UTC
(In reply to fenugrec from comment #3)
> Probable duplicate of Bug 38341

I don't think so. The problem here is not only whether the warning is correct or not. A major issue is that the original code does not contain ~unsigned, but GCC transforms (folds) the code too early. It is also unclear whether the code paths that lead to this are the same. Two things may cause exactly the same wrong warning but may be unrelated, or cause two different warnings, but have the same root cause. Hard to say without running GCC under the debugger and analyzing the execution (https://gcc.gnu.org/wiki/DebuggingGCC)
Comment 5 Andrew Pinski 2023-05-20 04:33:18 UTC
Marking as a dup of bug 107465 as that is what fixed the issue here.

*** This bug has been marked as a duplicate of bug 107465 ***