Menu

#481 Invalid conversion warning with isnan()

v1.0 (example)
open
nobody
None
5
2025-04-15
2015-06-11
lolwat
No
#include <math.h>

int isnan_wrapper(double value)
{
  return isnan(value);
}

Compiling this snippet with:

g++ -Wconversion -c snippet.cpp

gives following error:

snippet.cpp: In function 'int isnan_wrapper(double)':
snippet.cpp:5:10: warning: conversion to 'float' from 'double' may alter its value [-Wfloat-conversion]
   return isnan(value);
          ^
snippet.cpp:5:10: warning: conversion to 'int' from 'double' may alter its value [-Wfloat-conversion]

I would expect this to compile without any warning or error.

Described behaviour can be reproduced with mingw-w64 from msys2. This error was originally discovered here.

g++ -v
Using built-in specs.
COLLECT_GCC=g++
COLLECT_LTO_WRAPPER=C:/Coding/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/4
.9.2/lto-wrapper.exe
Target: x86_64-w64-mingw32
Configured with: ../gcc-4.9.2/configure --prefix=/mingw64 --with-local-prefix=/mingw64/local --build=x86_64-w64-mingw32 --host=x86_64-w64-mingw32 --target=x86_64-w64-mingw32 --with-native-system-header-dir=/mingw64/x86_64-w64-mingw32/include --libexecdir=/mingw64/lib --with-gxx-include-dir=/mingw64/include/c++/4.9.2 --enable-bootstrap --with-arch=x86-64 --with-tune=generic --enable-languages=c,lto,c++,objc,obj-c++,fortran,ada --enable-shared --enable-static --enable-libatomic --enable-threads=posix --enable-graphite --enable-fully-dynamic-string --enable-libstdcxx-time=yes --disable-libstdcxx-pch --disable-libstdcxx-debug --enable-cloog-backend=isl --enable-version-specific-runtime-libs --disable-cloog-version-check --disable-isl-version-check --enable-lto --enable-libgomp --disable-multilib --enable-checking=release --disable-rpath --disable-win32-registry --disable-nls --disable-werror --disable-symvers --with-libiconv --with-system-zlib --with-gmp=/mingw64 --with-mpfr=/mingw64 --with-mpc=/mingw64 --with-isl=/mingw64 --with-cloog=/mingw64 --with-pkgversion='Rev5, Built by MSYS2 project' --with-bugurl=http://sourceforge.net/projects/msys2 --with-gnu-as --with-gnu-ld
Thread model: posix
gcc version 4.9.2 (Rev5, Built by MSYS2 project)

Discussion

  • Richard Lang

    Richard Lang - 2015-12-04

    Hit same issue trying to build code (in same source as origional reporter - CppUTest) that builds fine under cygwin 2.3.1 GCC

     
  • WinPORTS

    WinPORTS - 2016-05-26

    It compiles fine with GCC 6.1.0.

     
  • lolwat

    lolwat - 2016-07-24

    Can corfirm it’s working with GCC 6.1.0 from msys2.
    This bug can be closed.

     

    Last edit: lolwat 2016-07-24
  • Lukasz

    Lukasz - 2019-12-12

    Hello,
    I am experiencing this bug in mingw 7.3.0 64-bit too.

     
  • Ed Waugh

    Ed Waugh - 2024-09-05

    Hi I still see this issue today when using -Wconversion with mingw gcc v14.1
    It looks like mingw is not choosing the correct __isnan from math.h

     
  • Pali

    Pali - 2024-09-08

    Hello, I have looked at this problem and mingw-w64 math.h header file is choosing the correct __isnan function. The problem is in how gcc throws -Wconversion warnings for __builtin_choose_expr usage.

    isnan in math is defined as:

    #define isnan(x) \
    __mingw_choose_expr (                                         \
      __mingw_types_compatible_p (__typeof__ (x), double),            \
        __isnan(x),                                                 \
        __mingw_choose_expr (                                     \
          __mingw_types_compatible_p (__typeof__ (x), float),         \
            __isnanf(x),                                            \
        __mingw_choose_expr (                                     \
          __mingw_types_compatible_p (__typeof__ (x), long double),   \
            __isnanl(x),                                            \
        __dfp_expansion(__isnan,(__builtin_trap(),x),x))))
    

    and __mingw_choose_expr in C mode is __builtin_choose_expr.

    gcc -Wconversion during compilation see that there is some possible __isnanf(x) call for x of double value and it triggers warning. It is even for the case which is not evaluated. The final compiled version does not contain any __isnanf usage as double value does not match float type.

    So you can safely ignores this -Wconversion warning, it is false-positive here.

    One of the option how to change isnan macro to avoid this false-positive warning can be to postpone function call after evaluating the macro itself. To completely avoid parser to see __isnanf(x) call. For example as:

    #define isnan(x) \
    __mingw_choose_expr (                                         \
      __mingw_types_compatible_p (__typeof__ (x), double),            \
        __isnan,                                                 \
        __mingw_choose_expr (                                     \
          __mingw_types_compatible_p (__typeof__ (x), float),         \
            __isnanf,                                            \
        __mingw_choose_expr (                                     \
          __mingw_types_compatible_p (__typeof__ (x), long double),   \
            __isnanl,                                            \
        __dfp_expansion(__isnan,(__builtin_trap(),x),x))) \
    )(x)
    
     
    👍
    1
  • Pali

    Pali - 2024-09-08

    You can look into objdump to check that the correct function is called.

    $ objdump -dr isnan.o
    
    isnan.o:     file format pe-i386
    
    
    Disassembly of section .text:
    
    00000000 <_isnan_wrapper>:
       0:   55                      push   %ebp
       1:   89 e5                   mov    %esp,%ebp
       3:   83 ec 28                sub    $0x28,%esp
       6:   8b 45 08                mov    0x8(%ebp),%eax
       9:   89 45 f0                mov    %eax,-0x10(%ebp)
       c:   8b 45 0c                mov    0xc(%ebp),%eax
       f:   89 45 f4                mov    %eax,-0xc(%ebp)
      12:   dd 45 f0                fldl   -0x10(%ebp)
      15:   dd 1c 24                fstpl  (%esp)
      18:   e8 00 00 00 00          call   1d <_isnan_wrapper+0x1d>
                19: DISP32  ___isnan
      1d:   c9                      leave  
      1e:   c3                      ret    
      1f:   90                      nop
    
     
    👍
    1
  • Pali

    Pali - 2024-09-08

    The example how to avoid that false-positive warning in previous post does not work in C++ mode, because __mingw_choose_expr is C++ is ternary operator.

    Possible fix which can work in both C and C++ mode to avoid that false-positive warning can be:

    #define isnan(x) \
    __mingw_choose_expr (                                         \
      __mingw_types_compatible_p (__typeof__ (x), double),            \
        __isnan((double)(x)),                                     \
        __mingw_choose_expr (                                     \
          __mingw_types_compatible_p (__typeof__ (x), float),         \
            __isnanf((float)(x)),                                 \
        __mingw_choose_expr (                                     \
          __mingw_types_compatible_p (__typeof__ (x), long double),   \
            __isnanl((long double)(x)),                           \
        __dfp_expansion(__isnan,(__builtin_trap(),(int)0),x))))
    

    It explicitly cast x-argument to the called function type. And also it changes finalizer from (__builtin_trap(),x) to (__builtin_trap(),(int)0) which mute the second false-positive warning conversion from ‘double’ to ‘int’ may change value. It is caused by the fact that isnan's return value is int, but type of (__builtin_trap(),x) expression is double. (int)0 in this case is always of type int.

     
    👍
    1
  • Ed Waugh

    Ed Waugh - 2024-09-09

    Amazing work, thanks Pali. Will you add your fix in a future version?

     
  • Pali

    Pali - 2024-09-15

    Now the fix is in master branch in commit d60139

    Please check if it works for you.

     
  • Ed Waugh

    Ed Waugh - 2025-04-15

    Hi Pali, I am just working with released versions of the mingw so to try the change I just copied your fix into math.h in v12.0.0 installed by msys2.
    This worked for me just fine and resolved the problem. Thanks very much.
    Do you expect the change to be included in the next release?

     

Log in to post a comment.

MongoDB Logo MongoDB