Consider the following C++11 code: $ cat nan.cpp #include <limits> constexpr bool foo(double x) { return !(x <= 0); } int main() { static_assert(std::numeric_limits<double>::has_quiet_NaN, ""); static_assert(!(0 <= std::numeric_limits<double>::quiet_NaN()), ""); static_assert(foo(std::numeric_limits<double>::quiet_NaN()), ""); } I expect this code to compile because `foo()` is a constexpr function and because `std::numeric_limits<double>::quiet_NaN()` must be a constexpr function according to §18.3.2.4 of the C++ standard draft N3337 (and because there are quiet NaNs on my computer). Nevertheless, the code fails to compile with GCC: $ g++ -Wextra -Wall -std=c++11 -pedantic nan.cpp nan.cpp: In function ‘int main()’: nan.cpp:12:2: error: non-constant condition for static assertion static_assert(foo(std::numeric_limits<double>::quiet_NaN()), ""); ^~~~~~~~~~~~~ nan.cpp:12:19: in constexpr expansion of ‘foo(std::numeric_limits<double>::quiet_NaN())’ nan.cpp:5:13: error: ‘(+QNaN <= 0.0)’ is not a constant expression return !(x <= 0); ~~~^~~~~ The errors is the same with GCC 7.3.0 on Ubuntu 18.04 LTS (Bionic Beaver), GCC 7.3.0 on Gentoo (no output posted), and GCC 6.3.0 on Raspbian (output below). $ lsb_release --all No LSB modules are available. Distributor ID: Ubuntu Description: Ubuntu 18.04.1 LTS Release: 18.04 Codename: bionic $ g++ -Wextra -Wall -std=c++11 -pedantic -v nan.cpp Using built-in specs. COLLECT_GCC=g++ COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/7/lto-wrapper OFFLOAD_TARGET_NAMES=nvptx-none OFFLOAD_TARGET_DEFAULT=1 Target: x86_64-linux-gnu Configured with: ../src/configure -v --with-pkgversion='Ubuntu 7.3.0-27ubuntu1~18.04' --with-bugurl=file:///usr/share/doc/gcc-7/README.Bugs --enable-languages=c,ada,c++,go,brig,d,fortran,objc,obj-c++ --prefix=/usr --with-gcc-major-version-only --program-suffix=-7 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-libmpx --enable-plugin --enable-default-pie --with-system-zlib --with-target-system-zlib --enable-objc-gc=auto --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-offload-targets=nvptx-none --without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu Thread model: posix gcc version 7.3.0 (Ubuntu 7.3.0-27ubuntu1~18.04) COLLECT_GCC_OPTIONS='-Wextra' '-Wall' '-std=c++11' '-Wpedantic' '-v' '-shared-libgcc' '-mtune=generic' '-march=x86-64' /usr/lib/gcc/x86_64-linux-gnu/7/cc1plus -quiet -v -imultiarch x86_64-linux-gnu -D_GNU_SOURCE nan.cpp -quiet -dumpbase nan.cpp -mtune=generic -march=x86-64 -auxbase nan -Wextra -Wall -Wpedantic -std=c++11 -version -fstack-protector-strong -Wformat-security -o /tmp/ccSEEcsH.s GNU C++11 (Ubuntu 7.3.0-27ubuntu1~18.04) version 7.3.0 (x86_64-linux-gnu) compiled by GNU C version 7.3.0, GMP version 6.1.2, MPFR version 4.0.1, MPC version 1.1.0, isl version isl-0.19-GMP GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072 ignoring duplicate directory "/usr/include/x86_64-linux-gnu/c++/7" ignoring nonexistent directory "/usr/local/include/x86_64-linux-gnu" ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/7/../../../../x86_64-linux-gnu/include" #include "..." search starts here: #include <...> search starts here: /usr/include/c++/7 /usr/include/x86_64-linux-gnu/c++/7 /usr/include/c++/7/backward /usr/lib/gcc/x86_64-linux-gnu/7/include /usr/local/include /usr/lib/gcc/x86_64-linux-gnu/7/include-fixed /usr/include/x86_64-linux-gnu /usr/include End of search list. GNU C++11 (Ubuntu 7.3.0-27ubuntu1~18.04) version 7.3.0 (x86_64-linux-gnu) compiled by GNU C version 7.3.0, GMP version 6.1.2, MPFR version 4.0.1, MPC version 1.1.0, isl version isl-0.19-GMP GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072 Compiler executable checksum: 1bfae38ae5df64de6196cbd8c3b07d86 nan.cpp: In function ‘int main()’: nan.cpp:12:2: error: non-constant condition for static assertion static_assert(foo(std::numeric_limits<double>::quiet_NaN()), ""); ^~~~~~~~~~~~~ nan.cpp:12:19: in constexpr expansion of ‘foo(std::numeric_limits<double>::quiet_NaN())’ nan.cpp:5:13: error: ‘(+QNaN <= 0.0)’ is not a constant expression return !(x <= 0); ~~~^~~~~ $ lsb_release --all No LSB modules are available. Distributor ID: Raspbian Description: Raspbian GNU/Linux 9.4 (stretch) Release: 9.4 Codename: stretch $ g++ -Wextra -Wall -std=c++11 -pedantic -v nan.cpp Using built-in specs. COLLECT_GCC=g++ COLLECT_LTO_WRAPPER=/usr/lib/gcc/arm-linux-gnueabihf/6/lto-wrapper Target: arm-linux-gnueabihf Configured with: ../src/configure -v --with-pkgversion='Raspbian 6.3.0-18+rpi1+deb9u1' --with-bugurl=file:///usr/share/doc/gcc-6/README.Bugs --enable-languages=c,ada,c++,java,go,d,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-6 --program-prefix=arm-linux-gnueabihf- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-libitm --disable-libquadmath --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-6-armhf/jre --enable-java-home --with-jvm-root-dir=/usr/lib/jvm/java-1.5.0-gcj-6-armhf --with-jvm-jar-dir=/usr/lib/jvm-exports/java-1.5.0-gcj-6-armhf --with-arch-directory=arm --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --with-target-system-zlib --enable-objc-gc=auto --enable-multiarch --disable-sjlj-exceptions --with-arch=armv6 --with-fpu=vfp --with-float=hard --enable-checking=release --build=arm-linux-gnueabihf --host=arm-linux-gnueabihf --target=arm-linux-gnueabihf Thread model: posix gcc version 6.3.0 20170516 (Raspbian 6.3.0-18+rpi1+deb9u1) COLLECT_GCC_OPTIONS='-Wextra' '-Wall' '-std=c++11' '-Wpedantic' '-v' '-shared-libgcc' '-march=armv6' '-mfloat-abi=hard' '-mfpu=vfp' '-mtls-dialect=gnu' /usr/lib/gcc/arm-linux-gnueabihf/6/cc1plus -quiet -v -imultilib . -imultiarch arm-linux-gnueabihf -D_GNU_SOURCE nan.cpp -quiet -dumpbase nan.cpp -march=armv6 -mfloat-abi=hard -mfpu=vfp -mtls-dialect=gnu -auxbase nan -Wextra -Wall -Wpedantic -std=c++11 -version -o /tmp/ccfELtIA.s GNU C++11 (Raspbian 6.3.0-18+rpi1+deb9u1) version 6.3.0 20170516 (arm-linux-gnueabihf) compiled by GNU C version 6.3.0 20170516, GMP version 6.1.2, MPFR version 3.1.5, MPC version 1.0.3, isl version 0.15 GGC heuristics: --param ggc-min-expand=93 --param ggc-min-heapsize=118681 ignoring duplicate directory "/usr/include/arm-linux-gnueabihf/c++/6" ignoring nonexistent directory "/usr/local/include/arm-linux-gnueabihf" ignoring nonexistent directory "/usr/lib/gcc/arm-linux-gnueabihf/6/../../../../arm-linux-gnueabihf/include" #include "..." search starts here: #include <...> search starts here: /usr/include/c++/6 /usr/include/arm-linux-gnueabihf/c++/6 /usr/include/c++/6/backward /usr/lib/gcc/arm-linux-gnueabihf/6/include /usr/local/include /usr/lib/gcc/arm-linux-gnueabihf/6/include-fixed /usr/include/arm-linux-gnueabihf /usr/include End of search list. GNU C++11 (Raspbian 6.3.0-18+rpi1+deb9u1) version 6.3.0 20170516 (arm-linux-gnueabihf) compiled by GNU C version 6.3.0 20170516, GMP version 6.1.2, MPFR version 3.1.5, MPC version 1.0.3, isl version 0.15 GGC heuristics: --param ggc-min-expand=93 --param ggc-min-heapsize=118681 Compiler executable checksum: 79dca666fccaa96025c9107a8b3f60f3 nan.cpp: In function ‘int main()’: nan.cpp:12:2: error: non-constant condition for static assertion static_assert(foo(std::numeric_limits<double>::quiet_NaN()), ""); ^~~~~~~~~~~~~ nan.cpp:12:19: in constexpr expansion of ‘foo(std::numeric_limits<double>::quiet_NaN())’ nan.cpp:5:13: error: ‘(+QNaN <= 0.0)’ is not a constant expression return !(x <= 0); ~~~^~~~~
Created attachment 45075 [details] Code pre-processed with GCC 7.3.0 on Ubuntu 18.04 LTS This file was created with $ g++ -Wextra -Wall -std=c++11 -pedantic --save-temps nan.cpp on Ubuntu 18.04 LTS.
Created attachment 45076 [details] Code pre-processed with GCC 6.3.0 on Raspbian 9.4 The file was created with $ g++ -Wextra -Wall -std=c++11 -pedantic --save-temps nan.cpp on Raspbian 9.4 (codename stretch).
-fno-trapping-math is relevant. Gcc believes that comparing QNaN to something requires setting a flag in fenv, which can only be done at runtime. I expect that's wrong, or almost any operation on double would not be constexpr because of the inexact flag (that would have been a consistent choice, but most people don't care about fenv...).
An ordered comparison (< <= > >=) with qNaN raises the "invalid" exception. An equality comparison (== !=) does not, and nor do __builtin_isless etc. I don't know how C++ constexpr rules relate to floating-point exceptions.
Having read the comments, I began to modify code in the bug report. Apparently, the bug is only triggered if QNaN is on the wrong side of the comparison operator: christoph:~$ cat nan-lhs.cpp #include <limits> constexpr bool rhs(double f) { return !(0 <= f); } constexpr bool lhs(double f) { return !(f <= 0); } int main() { static_assert(std::numeric_limits<double>::has_quiet_NaN, ""); static_assert(!(std::numeric_limits<double>::quiet_NaN() <= 0), ""); static_assert(!(0 <= std::numeric_limits<double>::quiet_NaN()), ""); static_assert(lhs(std::numeric_limits<double>::quiet_NaN()), ""); static_assert(rhs(std::numeric_limits<double>::quiet_NaN()), ""); } christoph:~$ g++ -Wextra -Wall -std=c++11 -pedantic nan-lhs.cpp nan-lhs.cpp: In function ‘int main()’: nan-lhs.cpp:16:2: error: non-constant condition for static assertion static_assert(!(std::numeric_limits<double>::quiet_NaN() <= 0), ""); ^~~~~~~~~~~~~ nan-lhs.cpp:16:59: error: ‘(+QNaN <= 0.0)’ is not a constant expression static_assert(!(std::numeric_limits<double>::quiet_NaN() <= 0), ""); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~ nan-lhs.cpp:18:2: error: non-constant condition for static assertion static_assert(lhs(std::numeric_limits<double>::quiet_NaN()), ""); ^~~~~~~~~~~~~ nan-lhs.cpp:18:19: in constexpr expansion of ‘lhs(std::numeric_limits<double>::quiet_NaN())’ nan-lhs.cpp:10:13: error: ‘(+QNaN <= 0.0)’ is not a constant expression return !(f <= 0); ~~~^~~~~ nan-lhs.cpp:19:2: error: non-constant condition for static assertion static_assert(rhs(std::numeric_limits<double>::quiet_NaN()), ""); ^~~~~~~~~~~~~ nan-lhs.cpp:19:19: in constexpr expansion of ‘rhs(std::numeric_limits<double>::quiet_NaN())’ nan-lhs.cpp:5:13: error: ‘(+QNaN >= 0.0)’ is not a constant expression return !(0 <= f); ~~~^~~~~ Note that QNaN only appears on the left-hand side in the error messages, irrespective of the user input. christoph:~$ lsb_release --all No LSB modules are available. Distributor ID: Ubuntu Description: Ubuntu 18.04.1 LTS Release: 18.04 Codename: bionic christoph:~$ g++ -Wextra -Wall -std=c++11 -pedantic -v nan-lhs.cpp Using built-in specs. COLLECT_GCC=g++ COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/7/lto-wrapper OFFLOAD_TARGET_NAMES=nvptx-none OFFLOAD_TARGET_DEFAULT=1 Target: x86_64-linux-gnu Configured with: ../src/configure -v --with-pkgversion='Ubuntu 7.3.0-27ubuntu1~18.04' --with-bugurl=file:///usr/share/doc/gcc-7/README.Bugs --enable-languages=c,ada,c++,go,brig,d,fortran,objc,obj-c++ --prefix=/usr --with-gcc-major-version-only --program-suffix=-7 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-libmpx --enable-plugin --enable-default-pie --with-system-zlib --with-target-system-zlib --enable-objc-gc=auto --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-offload-targets=nvptx-none --without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu Thread model: posix gcc version 7.3.0 (Ubuntu 7.3.0-27ubuntu1~18.04) COLLECT_GCC_OPTIONS='-Wextra' '-Wall' '-std=c++11' '-Wpedantic' '-v' '-shared-libgcc' '-mtune=generic' '-march=x86-64' /usr/lib/gcc/x86_64-linux-gnu/7/cc1plus -quiet -v -imultiarch x86_64-linux-gnu -D_GNU_SOURCE nan-lhs.cpp -quiet -dumpbase nan-lhs.cpp -mtune=generic -march=x86-64 -auxbase nan-lhs -Wextra -Wall -Wpedantic -std=c++11 -version -fstack-protector-strong -Wformat-security -o /tmp/ccOYNOxa.s GNU C++11 (Ubuntu 7.3.0-27ubuntu1~18.04) version 7.3.0 (x86_64-linux-gnu) compiled by GNU C version 7.3.0, GMP version 6.1.2, MPFR version 4.0.1, MPC version 1.1.0, isl version isl-0.19-GMP GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072 ignoring duplicate directory "/usr/include/x86_64-linux-gnu/c++/7" ignoring nonexistent directory "/usr/local/include/x86_64-linux-gnu" ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/7/../../../../x86_64-linux-gnu/include" #include "..." search starts here: #include <...> search starts here: /usr/include/c++/7 /usr/include/x86_64-linux-gnu/c++/7 /usr/include/c++/7/backward /usr/lib/gcc/x86_64-linux-gnu/7/include /usr/local/include /usr/lib/gcc/x86_64-linux-gnu/7/include-fixed /usr/include/x86_64-linux-gnu /usr/include End of search list. GNU C++11 (Ubuntu 7.3.0-27ubuntu1~18.04) version 7.3.0 (x86_64-linux-gnu) compiled by GNU C version 7.3.0, GMP version 6.1.2, MPFR version 4.0.1, MPC version 1.1.0, isl version isl-0.19-GMP GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072 Compiler executable checksum: 1bfae38ae5df64de6196cbd8c3b07d86 nan-lhs.cpp: In function ‘int main()’: nan-lhs.cpp:16:2: error: non-constant condition for static assertion static_assert(!(std::numeric_limits<double>::quiet_NaN() <= 0), ""); ^~~~~~~~~~~~~ nan-lhs.cpp:16:59: error: ‘(+QNaN <= 0.0)’ is not a constant expression static_assert(!(std::numeric_limits<double>::quiet_NaN() <= 0), ""); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~ nan-lhs.cpp:18:2: error: non-constant condition for static assertion static_assert(lhs(std::numeric_limits<double>::quiet_NaN()), ""); ^~~~~~~~~~~~~ nan-lhs.cpp:18:19: in constexpr expansion of ‘lhs(std::numeric_limits<double>::quiet_NaN())’ nan-lhs.cpp:10:13: error: ‘(+QNaN <= 0.0)’ is not a constant expression return !(f <= 0); ~~~^~~~~ nan-lhs.cpp:19:2: error: non-constant condition for static assertion static_assert(rhs(std::numeric_limits<double>::quiet_NaN()), ""); ^~~~~~~~~~~~~ nan-lhs.cpp:19:19: in constexpr expansion of ‘rhs(std::numeric_limits<double>::quiet_NaN())’ nan-lhs.cpp:5:13: error: ‘(+QNaN >= 0.0)’ is not a constant expression return !(0 <= f); ~~~^~~~~ christoph:~ $ lsb_release --all No LSB modules are available. Distributor ID: Raspbian Description: Raspbian GNU/Linux 9.4 (stretch) Release: 9.4 Codename: stretch christoph:~ $ g++ -Wextra -Wall -std=c++11 -pedantic -v nan-lhs.cpp Using built-in specs. COLLECT_GCC=g++ COLLECT_LTO_WRAPPER=/usr/lib/gcc/arm-linux-gnueabihf/6/lto-wrapper Target: arm-linux-gnueabihf Configured with: ../src/configure -v --with-pkgversion='Raspbian 6.3.0-18+rpi1+deb9u1' --with-bugurl=file:///usr/share/doc/gcc-6/README.Bugs --enable-languages=c,ada,c++,java,go,d,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-6 --program-prefix=arm-linux-gnueabihf- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-libitm --disable-libquadmath --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-6-armhf/jre --enable-java-home --with-jvm-root-dir=/usr/lib/jvm/java-1.5.0-gcj-6-armhf --with-jvm-jar-dir=/usr/lib/jvm-exports/java-1.5.0-gcj-6-armhf --with-arch-directory=arm --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --with-target-system-zlib --enable-objc-gc=auto --enable-multiarch --disable-sjlj-exceptions --with-arch=armv6 --with-fpu=vfp --with-float=hard --enable-checking=release --build=arm-linux-gnueabihf --host=arm-linux-gnueabihf --target=arm-linux-gnueabihf Thread model: posix gcc version 6.3.0 20170516 (Raspbian 6.3.0-18+rpi1+deb9u1) COLLECT_GCC_OPTIONS='-Wextra' '-Wall' '-std=c++11' '-Wpedantic' '-v' '-shared-libgcc' '-march=armv6' '-mfloat-abi=hard' '-mfpu=vfp' '-mtls-dialect=gnu' /usr/lib/gcc/arm-linux-gnueabihf/6/cc1plus -quiet -v -imultilib . -imultiarch arm-linux-gnueabihf -D_GNU_SOURCE nan-lhs.cpp -quiet -dumpbase nan-lhs.cpp -march=armv6 -mfloat-abi=hard -mfpu=vfp -mtls-dialect=gnu -auxbase nan-lhs -Wextra -Wall -Wpedantic -std=c++11 -version -o /tmp/ccuRevtG.s GNU C++11 (Raspbian 6.3.0-18+rpi1+deb9u1) version 6.3.0 20170516 (arm-linux-gnueabihf) compiled by GNU C version 6.3.0 20170516, GMP version 6.1.2, MPFR version 3.1.5, MPC version 1.0.3, isl version 0.15 GGC heuristics: --param ggc-min-expand=93 --param ggc-min-heapsize=118681 ignoring duplicate directory "/usr/include/arm-linux-gnueabihf/c++/6" ignoring nonexistent directory "/usr/local/include/arm-linux-gnueabihf" ignoring nonexistent directory "/usr/lib/gcc/arm-linux-gnueabihf/6/../../../../arm-linux-gnueabihf/include" #include "..." search starts here: #include <...> search starts here: /usr/include/c++/6 /usr/include/arm-linux-gnueabihf/c++/6 /usr/include/c++/6/backward /usr/lib/gcc/arm-linux-gnueabihf/6/include /usr/local/include /usr/lib/gcc/arm-linux-gnueabihf/6/include-fixed /usr/include/arm-linux-gnueabihf /usr/include End of search list. GNU C++11 (Raspbian 6.3.0-18+rpi1+deb9u1) version 6.3.0 20170516 (arm-linux-gnueabihf) compiled by GNU C version 6.3.0 20170516, GMP version 6.1.2, MPFR version 3.1.5, MPC version 1.0.3, isl version 0.15 GGC heuristics: --param ggc-min-expand=93 --param ggc-min-heapsize=118681 Compiler executable checksum: 79dca666fccaa96025c9107a8b3f60f3 nan-lhs.cpp: In function ‘int main()’: nan-lhs.cpp:16:2: error: non-constant condition for static assertion static_assert(!(std::numeric_limits<double>::quiet_NaN() <= 0), ""); ^~~~~~~~~~~~~ nan-lhs.cpp:16:59: error: ‘(+QNaN <= 0.0)’ is not a constant expression static_assert(!(std::numeric_limits<double>::quiet_NaN() <= 0), ""); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~ nan-lhs.cpp:18:2: error: non-constant condition for static assertion static_assert(lhs(std::numeric_limits<double>::quiet_NaN()), ""); ^~~~~~~~~~~~~ nan-lhs.cpp:18:19: in constexpr expansion of ‘lhs(std::numeric_limits<double>::quiet_NaN())’ nan-lhs.cpp:10:13: error: ‘(+QNaN <= 0.0)’ is not a constant expression return !(f <= 0); ~~~^~~~~ nan-lhs.cpp:19:2: error: non-constant condition for static assertion static_assert(rhs(std::numeric_limits<double>::quiet_NaN()), ""); ^~~~~~~~~~~~~ nan-lhs.cpp:19:19: in constexpr expansion of ‘rhs(std::numeric_limits<double>::quiet_NaN())’ nan-lhs.cpp:5:13: error: ‘(+QNaN >= 0.0)’ is not a constant expression return !(0 <= f); ~~~^~~~~
Created attachment 45080 [details] nan-lhs.ii created by GCC 7.3.0 on Ubuntu 18.04 LTS
Created attachment 45081 [details] nan-lhs.ii created by GCC 6.3.0 on Raspbian 9.4
Created attachment 45082 [details] nan-lhs.cpp
nan-lhs.cpp with `float` instead of `double` triggers the same error messages with `QNaNf` in place of `QNaN`.
Shorter: #define inf __builtin_huge_val() #define nan __builtin_nan("") constexpr bool b1 = inf > nan; // OK constexpr bool b2 = nan < inf; // ‘(+QNaN <= 1.7976931348623157e+308)’ is not a constant expression
Middle-end issue; the patterns in match.pd handle these equivalent comparisons very differently.
What should be the exact rules for C++ floating point evaluation that trigger non-constant expressions? And shall that depend (like it partly does for GCC currently) on e.g. -ftrapping-math and other command line options? 1.0 / 0.0 - division by zero (for floating point results in Inf) 10000000000000.0 + 0.000000000000001 - inexact (hope this one not) inf - inf - invalid - non-NaN operands resulting in NaN result sqrt (-1) - likewise DBL_MAX * DBL_MAX - overflow DBL_MIN * DBL_MIN - underflow NaN + 1.0 - one or both operands NaN resulting in NaN sNaN + 1.0 - at least one operand sNaN
Patch proposed. https://gcc.gnu.org/pipermail/gcc-patches/2021-September/579747.html
The master branch has been updated by Roger Sayle <sayle@gcc.gnu.org>: https://gcc.gnu.org/g:e9e46864cd0695d2dcec5c513f249b1e1ab0056f commit r12-3660-ge9e46864cd0695d2dcec5c513f249b1e1ab0056f Author: Roger Sayle <roger@nextmovesoftware.com> Date: Sun Sep 19 09:07:01 2021 +0100 PR middle-end/88173: More constant folding of NaN comparisons. This patch tackles PR middle-end/88173 where the order of operands in a comparison affects constant folding. As diagnosed by Jason Merrill, "match.pd handles these comparisons very differently". The history is that the middle end, typically canonicalizes comparisons to place constants on the right, but when a comparison contains two constants we need to check/transform both constants, i.e. on both the left and the right. Hence the added lines below duplicate for @0 the same transform applied a few lines above for @1. Whilst preparing the testcase, I noticed that this transformation is incorrectly disabled with -fsignaling-nans even when both operands are known not be be signaling NaNs, so I've corrected that and added a second test case. Unfortunately, c-c++-common/pr57371-4.c then starts failing, as it doesn't distinguish QNaNs (which are quiet) from SNaNs (which signal), so this patch includes a minor tweak to the expected behaviour for QNaNs in that existing test. 2021-09-19 Roger Sayle <roger@nextmovesoftware.com> gcc/ChangeLog PR middle-end/88173 * match.pd (cmp @0 REAL_CST@1): When @0 is also REAL_CST, apply the same transformations as to @1. For comparisons against NaN, don't check HONOR_SNANS but confirm that neither operand is a signaling NaN. gcc/testsuite/ChangeLog PR middle-end/88173 * c-c++-common/pr57371-4.c: Tweak/correct test case for QNaNs. * g++.dg/pr88173-1.C: New test case. * g++.dg/pr88173-2.C: New test case.
This has been fixed on mainline.
*** Bug 88683 has been marked as a duplicate of this bug. ***
*** Bug 101795 has been marked as a duplicate of this bug. ***