Bug 88173 - constant folding of NaN comparison depends on order of operands
Summary: constant folding of NaN comparison depends on order of operands
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: middle-end (show other bugs)
Version: 7.3.0
: P3 normal
Target Milestone: 12.0
Assignee: Roger Sayle
URL:
Keywords: rejects-valid
: 88683 101795 (view as bug list)
Depends on:
Blocks:
 
Reported: 2018-11-23 18:01 UTC by Christoph Conrads
Modified: 2022-12-28 19:14 UTC (History)
6 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2020-12-08 00:00:00


Attachments
Code pre-processed with GCC 7.3.0 on Ubuntu 18.04 LTS (3.55 KB, text/plain)
2018-11-23 18:04 UTC, Christoph Conrads
Details
Code pre-processed with GCC 6.3.0 on Raspbian 9.4 (3.29 KB, text/plain)
2018-11-23 18:06 UTC, Christoph Conrads
Details
nan-lhs.ii created by GCC 7.3.0 on Ubuntu 18.04 LTS (3.57 KB, text/plain)
2018-11-24 10:36 UTC, Christoph Conrads
Details
nan-lhs.ii created by GCC 6.3.0 on Raspbian 9.4 (3.31 KB, text/plain)
2018-11-24 10:37 UTC, Christoph Conrads
Details
nan-lhs.cpp (174 bytes, text/x-csrc)
2018-11-24 10:38 UTC, Christoph Conrads
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Christoph Conrads 2018-11-23 18:01:36 UTC
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);
          ~~~^~~~~
Comment 1 Christoph Conrads 2018-11-23 18:04:25 UTC
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.
Comment 2 Christoph Conrads 2018-11-23 18:06:44 UTC
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).
Comment 3 Marc Glisse 2018-11-23 18:26:49 UTC
-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...).
Comment 4 jsm-csl@polyomino.org.uk 2018-11-23 20:52:57 UTC
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.
Comment 5 Christoph Conrads 2018-11-24 10:32:19 UTC
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);
          ~~~^~~~~
Comment 6 Christoph Conrads 2018-11-24 10:36:08 UTC
Created attachment 45080 [details]
nan-lhs.ii created by GCC 7.3.0 on Ubuntu 18.04 LTS
Comment 7 Christoph Conrads 2018-11-24 10:37:39 UTC
Created attachment 45081 [details]
nan-lhs.ii created by GCC 6.3.0 on Raspbian 9.4
Comment 8 Christoph Conrads 2018-11-24 10:38:22 UTC
Created attachment 45082 [details]
nan-lhs.cpp
Comment 9 Christoph Conrads 2018-11-24 10:42:33 UTC
nan-lhs.cpp with `float` instead of `double` triggers the same error messages with `QNaNf` in place of `QNaN`.
Comment 10 Jason Merrill 2020-12-08 18:52:39 UTC
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
Comment 11 Jason Merrill 2020-12-08 19:47:31 UTC
Middle-end issue; the patterns in match.pd handle these equivalent comparisons very differently.
Comment 12 Jakub Jelinek 2020-12-08 20:48:33 UTC
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
Comment 13 Roger Sayle 2021-09-18 08:58:46 UTC
Patch proposed.
https://gcc.gnu.org/pipermail/gcc-patches/2021-September/579747.html
Comment 14 GCC Commits 2021-09-19 08:08:36 UTC
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.
Comment 15 Roger Sayle 2021-09-19 21:42:35 UTC
This has been fixed on mainline.
Comment 16 Andrew Pinski 2021-11-08 10:01:46 UTC
*** Bug 88683 has been marked as a duplicate of this bug. ***
Comment 17 Andrew Pinski 2022-12-28 19:14:11 UTC
*** Bug 101795 has been marked as a duplicate of this bug. ***