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)
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; ^
I think this is confirmed.
Probable duplicate of Bug 38341
(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)
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 ***