Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 11 Jul 2013 09:46:17 +0100
From:      David Chisnall <theraven@FreeBSD.org>
To:        Bruce Evans <brde@optusnet.com.au>
Cc:        Garrett Wollman <wollman@csail.mit.edu>, Tijl Coosemans <tijl@FreeBSD.org>, FreeBSD CURRENT <freebsd-current@FreeBSD.org>, freebsd-standards@FreeBSD.org, freebsd-toolchain@FreeBSD.org
Subject:   Re: CURRENT: CLANG 3.3 and -stad=c++11 and -stdlib=libc++: isnan()/isninf() oddity
Message-ID:  <FD768A6B-8B72-44A1-BC1C-14FF44CB4643@FreeBSD.org>
In-Reply-To: <20130711130043.R920@besplex.bde.org>
References:  <20130710155809.0f589c22@thor.walstatt.dyndns.org> <CD51F125-AE9E-4461-916D-CF583002B47D@FreeBSD.org> <20130710183315.725dfde0@thor.walstatt.dyndns.org> <C8C94CF2-7D5A-471B-AD63-8E961AED6274@FreeBSD.org> <20130710203200.5359fd18@thor.walstatt.dyndns.org> <51DDC04B.6040209@FreeBSD.org> <20957.49978.73666.392417@khavrinen.csail.mit.edu> <20130711130043.R920@besplex.bde.org>

next in thread | previous in thread | raw e-mail | index | archive | help

--Apple-Mail=_B9A0D356-39FE-4BC5-B2BB-1563285CBA51
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain;
	charset=us-ascii

Hi Bruce,

You're joining in this discussion starting in the middle, so you =
probably missed the earlier explanation.

On 11 Jul 2013, at 05:21, Bruce Evans <brde@optusnet.com.au> wrote:

> I don't see how any conforming program can access the isnan() function
> directly.  It is just as protected as __isnan() would be.  (isnan)()
> gives the function (the function prototype uses this), but conforming
> programs can't do that since the function might not exist.  Maybe some
> non-conforming program like autoconfig reads <math.h> or libm.a and
> creates a bug for C++.

The cmath header defines a template function isnan that invokes the =
isnan macro, but then undefines the isnan macro.  This causes a problem =
because when someone does something along the lines of using namespace =
std then they end up with two functions called isnan and the compiler =
gets to pick the one to use.  Unfortunately, std::isnan() returns a =
bool, whereas isnan() returns an int. =20

The C++ headers are not required to be conforming C code, because they =
are not C, and our math.h causes namespace pollution in C++ when =
included from <cmath>.

> The FreeBSD isnan() implementation would be broken by removing the
> isnan() function from libm.a or ifdefing it in <math.h>.  Changing the
> function to __isnan() would cause compatibility problems.  The =
function
> is intentionally named isnan() to reduce compatibility problems.


On OS X this is avoided because their isnan() macro expands to call one =
of the __-prefixed inline functions (which adopt your suggestion of =
being implemented as x !=3D x, for all types).  I am not sure that this =
is required for standards conformance, but it is certainly cleaner.  =
Your statement that having the function not called isnan() causes =
compatibility problems is demonstrably false, as neither OS X nor glibc =
has a function called isnan() and, unlike us, they do not experience =
problems with this macro. =20

It would also be nice to implement these macros using _Generic when =
compiling in C11 mode, as it will allow the compiler to produce more =
helpful warning messages.  I would propose this implementation:


#if __has_builtin(__builtin_isnan)
#define isnan(x) __builtin_isnan(x)
#else
static __inline int
__isnanf(float __x)
{
        return (__x !=3D __x);
}
static __inline int
__isnand(double __x)
{
        return (__x !=3D __x);
}
static __inline int
__isnanl(long double __x)
{
        return (__x !=3D __x);
}
#if __STDC_VERSION__ >=3D 201112L
#define isnan(x) _Generic((x),     \
        float: __isnanf(x),        \
        double: __isnand(x),       \
        long double: __isnanl(x))
#else
#define isnan(x)                                                \
        ((sizeof (x) =3D=3D sizeof (float)) ? __isnanf(x)           \
             : (sizeof (x) =3D=3D sizeof (double)) ? __isnand(x)    \
             : __isnanl(x))
#endif
#endif

For a trivial example of why this is an improvement in terms of error =
reporting, consider this trivial piece of code:

int is(int x)
{
        return isnan(x);
}

With our current implementation, this compiles and links without any =
warnings, although it will have somewhat interesting results at run =
time.  With the __builtin_isnan() version, clang reports this error:

isnan.c:35:15: error: floating point classification requires argument of
      floating point type (passed in 'int')
        return isnan(x);
                     ^
(and then some more about the macro expansion)

With the C11 version, it reports this error:

isnan.c:35:15: error: controlling expression type 'int' not compatible =
with any
      generic association type
        return isnan(x);
                     ^



David


--Apple-Mail=_B9A0D356-39FE-4BC5-B2BB-1563285CBA51
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
	filename=signature.asc
Content-Type: application/pgp-signature;
	name=signature.asc
Content-Description: Message signed with OpenPGP using GPGMail

-----BEGIN PGP SIGNATURE-----
Version: GnuPG/MacGPG2 v2.0.18 (Darwin)
Comment: GPGTools - http://gpgtools.org

iQIcBAEBAgAGBQJR3nDZAAoJEKx65DEEsqIdT0UP/R3/DJeYYumScK0sTI0u0f/K
zr03X2Nn8rHa4xk8avxANTaYYK8QfutKvViv11G1JH/gTGMNh8LxxdoRhsVx4bOe
rAjYY+NDplfLqKTBva+zf25FiQNOn08NnOZDd9l0ApyAK1u2J2dp7Q9yqZbRU7Kj
bACBptR3dREJzSZgIbQcJ5WE3BDsBztW0Az3/WcyDtmILmZ8psVLs+R39qe4yjeV
NxNQRDJuJmccxi8Jx6sjQaUrXVLZ4VWc0Cbr7+0SasHY1avtqoHr6H5pt3ltUtfF
Ld0wQHG8MUuuqZd9j1tQDHSKWmjeDQdOwu8IjEbGP/IXjJI/lK93+K07qMgQPp5G
DJzPoSxJEKTVudNVBuv8sA6iToWMli9ZI/h4YL0Lc0G5vOwLbPHcX1ctEb+g118z
676x26Xdr/vawe0rddCUW2z+CVHj7q1eKY37Za9xVlmchUYWMMzqE8m9MdlQGvmi
y60IDPDcwCiIoZZQ2VbE+wqrgWevEi0nASFttrgqrS7HEBy/rszm8Cdy1wZqUKSe
xi2CwevaMWSfTc9MIwGId5y89UjQ5bSzAPBFWonFZkd/KDN6rRQ1LZvyVrMuZMlX
q/6/2ksNXFHzonOw66/913m+JjYYEaSjmndL0w30qN5HKdNw8C6d+Y9EMrQRMK1A
cjNdMjwrwk2pdBNsVo1d
=FIry
-----END PGP SIGNATURE-----

--Apple-Mail=_B9A0D356-39FE-4BC5-B2BB-1563285CBA51--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?FD768A6B-8B72-44A1-BC1C-14FF44CB4643>