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>
