From owner-freebsd-standards@FreeBSD.ORG Mon Jul 8 11:41:09 2013 Return-Path: Delivered-To: freebsd-standards@FreeBSD.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by hub.freebsd.org (Postfix) with ESMTP id B20FA569 for ; Mon, 8 Jul 2013 11:41:09 +0000 (UTC) (envelope-from owner-bugmaster@FreeBSD.org) Received: from freefall.freebsd.org (freefall.freebsd.org [IPv6:2001:1900:2254:206c::16:87]) by mx1.freebsd.org (Postfix) with ESMTP id A4B5F15BA for ; Mon, 8 Jul 2013 11:41:09 +0000 (UTC) Received: from freefall.freebsd.org (localhost [127.0.0.1]) by freefall.freebsd.org (8.14.7/8.14.7) with ESMTP id r68BeXg6053981 for ; Mon, 8 Jul 2013 11:41:09 GMT (envelope-from owner-bugmaster@FreeBSD.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.14.7/8.14.7/Submit) id r68B6gq9046221 for freebsd-standards@FreeBSD.org; Mon, 8 Jul 2013 11:06:42 GMT (envelope-from owner-bugmaster@FreeBSD.org) Date: Mon, 8 Jul 2013 11:06:42 GMT Message-Id: <201307081106.r68B6gq9046221@freefall.freebsd.org> X-Authentication-Warning: freefall.freebsd.org: gnats set sender to owner-bugmaster@FreeBSD.org using -f From: FreeBSD bugmaster To: freebsd-standards@FreeBSD.org Subject: Current problem reports assigned to freebsd-standards@FreeBSD.org X-BeenThere: freebsd-standards@freebsd.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: Standards compliance List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 08 Jul 2013 11:41:09 -0000 Note: to view an individual PR, use: http://www.freebsd.org/cgi/query-pr.cgi?pr=(number). The following is a listing of current problems submitted by FreeBSD users. These represent problem reports covering all versions including experimental development code and obsolete releases. S Tracker Resp. Description -------------------------------------------------------------------------------- o stand/179248 standards A return value of telldir(3) only seekable for once o stand/177742 standards conflict of dd's bs= option with use of conv=sparse o stand/176683 standards catman pages shall be stored in /var (/usr/local/var,/ o stand/176412 standards newfs writes by default, compare to bsdlabel/disklabel o stand/175711 standards When the server has more than 3 days, rising interrupt p stand/175453 standards Catching C++ std::bad_cast doesn't work in FreeBSD 9.1 o stand/174938 standards Problem statement: iSCSI target failure o stand/173421 standards [libc] [patch] strptime() accepts formats that should o stand/173087 standards pax(1) does not support the pax interchange format o stand/172805 standards Fix catopen(3)'s EINVAL usage and document EFTYPE o stand/172276 standards POSIX: {get,set}groups gidsetsize is u_int not int o stand/172215 standards localeconv() grouping appears not to match POSIX o stand/170403 standards wrong ntohs expression type tickling clang o stand/169697 standards syslogd(8) is not BOM aware o stand/166349 standards Support the assignment-allocation character for fscanf p stand/164787 standards dirfd() function not available when _POSIX_C_SOURCE is o kern/164674 standards [patch] [libc] vfprintf/vfwprintf return error (EOF) o o stand/162434 standards getaddrinfo: addrinfo.ai_family is an address family, o stand/150093 standards C++ std::locale support is broken o stand/130067 standards Wrong numeric limits in system headers? o stand/125751 standards man 3 pthread_getschedparam section ERRORS incomplete o stand/124860 standards flockfile(3) doesn't work when the memory has been exh o stand/121921 standards [patch] Add leap second support to at(1), atrun(8) o stand/116477 standards rm(1): rm behaves unexpectedly when using -r and relat o bin/116413 standards incorrect getconf(1) handling of unsigned constants gi o stand/116081 standards make does not work with the directive sinclude a stand/86484 standards [patch] mkfifo(1) uses wrong permissions o stand/81287 standards [patch] fingerd(8) might send a line not ending in CRL a stand/80293 standards sysconf() does not support well-defined unistd values o stand/79056 standards [feature request] [atch] regex(3) regression tests o stand/70813 standards [patch] ls(1) not Posix compliant o stand/66357 standards make POSIX conformance problem ('sh -e' & '+' command- s kern/64875 standards [libc] [patch] [request] add a system call: fdatasync( o stand/56476 standards [patch] cd9660 unicode support simple hack o stand/54410 standards one-true-awk not POSIX compliant (no extended REs) o stand/46119 standards Priority problems for SCHED_OTHER using pthreads o stand/44365 standards [headers] [patch] [request] introduce ulong and unchar a stand/41576 standards ln(1): replacing old dir-symlinks a docs/26003 standards getgroups(2) lists NGROUPS_MAX but not syslimits.h s stand/24590 standards timezone function not compatible witn Single Unix Spec o stand/21519 standards sys/dir.h should be deprecated some more s bin/14925 standards getsubopt isn't poisonous enough 42 problems total. From owner-freebsd-standards@FreeBSD.ORG Wed Jul 10 20:13:15 2013 Return-Path: Delivered-To: freebsd-standards@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [8.8.178.115]) by hub.freebsd.org (Postfix) with ESMTP id 55349B11; Wed, 10 Jul 2013 20:13:15 +0000 (UTC) (envelope-from tijl@freebsd.org) Received: from mailrelay007.isp.belgacom.be (mailrelay007.isp.belgacom.be [195.238.6.173]) by mx1.freebsd.org (Postfix) with ESMTP id 6C09E1960; Wed, 10 Jul 2013 20:13:14 +0000 (UTC) X-Belgacom-Dynamic: yes X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: AoUGADG/3VFR8aPm/2dsb2JhbABagwkywXGBExd0giMBAQVWIxALGAkWDwkDAgECASceBg0BBQIBAYgPuACPYwcJg2wDkA6BLYdIkCGBWIE7Og Received: from 230.163-241-81.adsl-dyn.isp.belgacom.be (HELO kalimero.tijl.coosemans.org) ([81.241.163.230]) by relay.skynet.be with ESMTP; 10 Jul 2013 22:13:06 +0200 Received: from kalimero.tijl.coosemans.org (kalimero.tijl.coosemans.org [127.0.0.1]) by kalimero.tijl.coosemans.org (8.14.7/8.14.7) with ESMTP id r6AKD53P023353; Wed, 10 Jul 2013 22:13:06 +0200 (CEST) (envelope-from tijl@FreeBSD.org) Message-ID: <51DDC04B.6040209@FreeBSD.org> Date: Wed, 10 Jul 2013 22:12:59 +0200 From: Tijl Coosemans User-Agent: Mozilla/5.0 (X11; FreeBSD i386; rv:17.0) Gecko/20130701 Thunderbird/17.0.7 MIME-Version: 1.0 To: "O. Hartmann" Subject: Re: CURRENT: CLANG 3.3 and -stad=c++11 and -stdlib=libc++: isnan()/isninf() oddity References: <20130710155809.0f589c22@thor.walstatt.dyndns.org> <20130710183315.725dfde0@thor.walstatt.dyndns.org> <20130710203200.5359fd18@thor.walstatt.dyndns.org> In-Reply-To: <20130710203200.5359fd18@thor.walstatt.dyndns.org> X-Enigmail-Version: 1.5.1 Content-Type: multipart/signed; micalg=pgp-sha256; protocol="application/pgp-signature"; boundary="----enig2EQINXAXUJPBVPTPMIQWW" Cc: freebsd-standards@FreeBSD.org, FreeBSD CURRENT , freebsd-toolchain@FreeBSD.org X-BeenThere: freebsd-standards@freebsd.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: Standards compliance List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 10 Jul 2013 20:13:15 -0000 This is an OpenPGP/MIME signed message (RFC 4880 and 3156) ------enig2EQINXAXUJPBVPTPMIQWW Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable On 2013-07-10 20:32, O. Hartmann wrote: > On Wed, 10 Jul 2013 18:04:16 +0100 > David Chisnall wrote: >=20 >> On 10 Jul 2013, at 17:33, "O. Hartmann" >> wrote: >> >>> Hi David, >>> >>> thanks for the fast response. >>> >>> The code I was told to check with is this: >>> >>> #include >>> #include >>> #include >>> >>> int >>> main(void) >>> { >>> >>> std::cout << typeid(isnan(1.0)).name() << "\n"; >>> >>> } >>> >>> >>> If I compile it with=20 >>> >>> c++ -o testme -std=3Dc++11 -stdlib=3Dlibc++ source.cc >>> >>> and run the binary, the result is "i" which I interpret as "INT". >> >> I believe there is a bug, which is that the math.h things are being >> exposed but shouldn't be, however it is not the bug that you think it >> is. Try this line instead: >> >> std::cout << typeid(std::isnan(1.0)).name() << "\n"; >> >> We have a libm function, isnan(), and a libc++ function, >> std::isnan(). The former is detected if you do not specify a >> namespace. I am not sure what will happen if you do: >> >> #include >> #include >> #include >> using namespace std; >> >> int >> main(void) >> { >> >> cout << typeid(isnan(1.0)).name() << "\n"; >> >> } >> >> This is considered bad form, but does happen in some code. I am not >> certain what the precedence rules are in this case and so I don't >> know what happens. >> >> To properly fix this, we'd need to namespace the libm functions when >> including math.h in C++. This would also include fixing tweaking the >> macros. =20 >> >> A fix for your code is to ensure isnan() and isinf() are explicitly >> namespaced. Potentially, this may also work: >> >> using std::isinf; >> using std::isnan; >> >> David >> >=20 > I tried in the test code I provided using=20 >=20 >=20 > #include > #include > #include >=20 > int > main(void) > { >=20 > std::cout << typeid(std::isnan(1.0)).name() << "\n"; >=20 > } >=20 > now std::isnan(). >=20 > The result is the same, it flags "INT". >=20 > Using=20 >=20 > #include > #include > #include >=20 > using namespace std; >=20 > int > main(void) > { >=20 > std::cout << typeid(std::isnan(1.0)).name() << "\n"; >=20 > } >=20 > which is considered "bad coding" also results in "INT" (it gives "i"). >=20 > So, is this woth a PR? isnan is overloaded. There's "int isnan(double)" in math.h and "bool isnan(arithmetic)" in cmath. When you call isnan(1.0), isnan(double) is selected. I think isnan(double) and isinf(double) in math.h should only be visible if (_BSD_VISIBLE || _XSI_VISIBLE) && __ISO_C_VISIBLE < 1999. For C99 and higher there should only be the isnan/isinf macros. CCed standards@. ------enig2EQINXAXUJPBVPTPMIQWW Content-Type: application/pgp-signature; name="signature.asc" Content-Description: OpenPGP digital signature Content-Disposition: attachment; filename="signature.asc" -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.20 (FreeBSD) iF4EAREIAAYFAlHdwFEACgkQfoCS2CCgtisMQwD9FoF5bcEWaWyVmEC5YXZKGLWd BYB0w68AI3sn0TyNdM0A/iFHD46Iybj5t3tc51SM9HPxom1uMg8HgBwj+shZgyt0 =n5uK -----END PGP SIGNATURE----- ------enig2EQINXAXUJPBVPTPMIQWW-- From owner-freebsd-standards@FreeBSD.ORG Wed Jul 10 20:25:31 2013 Return-Path: Delivered-To: freebsd-standards@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by hub.freebsd.org (Postfix) with ESMTP id F09D11C3; Wed, 10 Jul 2013 20:25:30 +0000 (UTC) (envelope-from wollman@khavrinen.csail.mit.edu) Received: from khavrinen.csail.mit.edu (khavrinen.csail.mit.edu [IPv6:2001:470:8b2d:1e1c:21b:21ff:feb8:d7b0]) by mx1.freebsd.org (Postfix) with ESMTP id C4B6F19FC; Wed, 10 Jul 2013 20:25:30 +0000 (UTC) Received: from khavrinen.csail.mit.edu (localhost [127.0.0.1]) by khavrinen.csail.mit.edu (8.14.5/8.14.5) with ESMTP id r6AKPUra014863 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=FAIL CN=khavrinen.csail.mit.edu issuer=Client+20CA); Wed, 10 Jul 2013 16:25:30 -0400 (EDT) (envelope-from wollman@khavrinen.csail.mit.edu) Received: (from wollman@localhost) by khavrinen.csail.mit.edu (8.14.5/8.14.5/Submit) id r6AKPUU6014860; Wed, 10 Jul 2013 16:25:30 -0400 (EDT) (envelope-from wollman) MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit Message-ID: <20957.49978.73666.392417@khavrinen.csail.mit.edu> Date: Wed, 10 Jul 2013 16:25:30 -0400 From: Garrett Wollman To: Tijl Coosemans Subject: Re: CURRENT: CLANG 3.3 and -stad=c++11 and -stdlib=libc++: isnan()/isninf() oddity In-Reply-To: <51DDC04B.6040209@FreeBSD.org> References: <20130710155809.0f589c22@thor.walstatt.dyndns.org> <20130710183315.725dfde0@thor.walstatt.dyndns.org> <20130710203200.5359fd18@thor.walstatt.dyndns.org> <51DDC04B.6040209@FreeBSD.org> X-Mailer: VM 7.17 under 21.4 (patch 22) "Instant Classic" XEmacs Lucid X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.4.3 (khavrinen.csail.mit.edu [127.0.0.1]); Wed, 10 Jul 2013 16:25:30 -0400 (EDT) Cc: FreeBSD CURRENT , freebsd-standards@freebsd.org, freebsd-toolchain@freebsd.org X-BeenThere: freebsd-standards@freebsd.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: Standards compliance List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 10 Jul 2013 20:25:31 -0000 < said: > I think isnan(double) and isinf(double) in math.h should only be > visible if (_BSD_VISIBLE || _XSI_VISIBLE) && __ISO_C_VISIBLE < 1999. > For C99 and higher there should only be the isnan/isinf macros. I believe you are correct. POSIX.1-2008 (which is aligned with C99) consistently calls isnan() a "macro", and gives a pseudo-prototype of int isnan(real-floating x); -GAWollman From owner-freebsd-standards@FreeBSD.ORG Thu Jul 11 04:21:43 2013 Return-Path: Delivered-To: freebsd-standards@FreeBSD.org Received: from mx1.freebsd.org (mx1.freebsd.org [8.8.178.115]) by hub.freebsd.org (Postfix) with ESMTP id C63413FF; Thu, 11 Jul 2013 04:21:43 +0000 (UTC) (envelope-from brde@optusnet.com.au) Received: from mail107.syd.optusnet.com.au (mail107.syd.optusnet.com.au [211.29.132.53]) by mx1.freebsd.org (Postfix) with ESMTP id 49F871F3E; Thu, 11 Jul 2013 04:21:42 +0000 (UTC) Received: from c122-106-156-23.carlnfd1.nsw.optusnet.com.au (c122-106-156-23.carlnfd1.nsw.optusnet.com.au [122.106.156.23]) by mail107.syd.optusnet.com.au (Postfix) with ESMTPS id A59C2D40A1A; Thu, 11 Jul 2013 14:21:22 +1000 (EST) Date: Thu, 11 Jul 2013 14:21:19 +1000 (EST) From: Bruce Evans X-X-Sender: bde@besplex.bde.org To: Garrett Wollman Subject: Re: CURRENT: CLANG 3.3 and -stad=c++11 and -stdlib=libc++: isnan()/isninf() oddity In-Reply-To: <20957.49978.73666.392417@khavrinen.csail.mit.edu> Message-ID: <20130711130043.R920@besplex.bde.org> References: <20130710155809.0f589c22@thor.walstatt.dyndns.org> <20130710183315.725dfde0@thor.walstatt.dyndns.org> <20130710203200.5359fd18@thor.walstatt.dyndns.org> <51DDC04B.6040209@FreeBSD.org> <20957.49978.73666.392417@khavrinen.csail.mit.edu> MIME-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII; format=flowed X-Optus-CM-Score: 0 X-Optus-CM-Analysis: v=2.0 cv=eqSHVfVX c=1 sm=1 a=GSpoo125mhwA:10 a=kj9zAlcOel0A:10 a=PO7r1zJSAAAA:8 a=JzwRw_2MAAAA:8 a=mlUDQFikY8EA:10 a=6I5d2MoRAAAA:8 a=dJdWW8WEajGmMdPzLgYA:9 a=CjuIK1q_8ugA:10 a=SV7veod9ZcQA:10 a=ebeQFi2P/qHVC0Yw9JDJ4g==:117 Cc: Tijl Coosemans , FreeBSD CURRENT , freebsd-standards@FreeBSD.org, freebsd-toolchain@FreeBSD.org X-BeenThere: freebsd-standards@freebsd.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: Standards compliance List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 11 Jul 2013 04:21:43 -0000 On Wed, 10 Jul 2013, Garrett Wollman wrote: > < said: > >> I think isnan(double) and isinf(double) in math.h should only be >> visible if (_BSD_VISIBLE || _XSI_VISIBLE) && __ISO_C_VISIBLE < 1999. >> For C99 and higher there should only be the isnan/isinf macros. > > I believe you are correct. POSIX.1-2008 (which is aligned with C99) > consistently calls isnan() a "macro", and gives a pseudo-prototype of > > int isnan(real-floating x); Almost any macro may be implemented as a function, if no conforming program can tell the difference. It is impossible for technical reasons to implement isnan() as a macro (except on weird implementations where all real-floating types are physically the same). In the FreeBSD implementation, isnan() is a macro, but it is also a function, and the macro expands to the function in double precision: % #define isnan(x) \ % ((sizeof (x) == sizeof (float)) ? __isnanf(x) \ % : (sizeof (x) == sizeof (double)) ? isnan(x) \ % : __isnanl(x)) 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 or libm.a and creates a bug for C++. The FreeBSD isnan() implementation would be broken by removing the isnan() function from libm.a or ifdefing it in . Changing the function to __isnan() would cause compatibility problems. The function is intentionally named isnan() to reduce compatibility problems. OTOH, the all of the extern sub-functions that are currently used should bever never be used, since using them gives a very low quality of implementation: - the functions are very slow - the functions have names that confuse compilers and thus prevent compilers from replacing them by builtins. Currently, only gcc automatically replaces isnan() by __builtin_isnan(). This only works in double precision. So the FreeBSD implementation only works right in double precision too, only with gcc, __because__ it replaces the macro isnan(x) by the function isnan(x). The result is inline expansion, the same as if the macro isnan() is replaced by __builtin_isnan(). clang never does this automatic replacement, so it generates calls to the slow library functions. Other things go wrong for gcc in other precisions: - if is not included, then isnan(x) gives __builtin_isnan((double)x). This sort of works on x86, but is low quality since it is broken for signaling NaNs (see below). One of the main reasons reason for the existence of the classification macros is that simply converting the arg to a common type and classifying the result doesn't always work. - if is not included, then spelling the API isnanf() or isnanl() gives correct results but a warning about these APIs not being declared. These APIs are nonstandard but are converted to __builtin_isnan[fl] by gcc. - if is included, then: - if the API is spelled isnan(), then the macro converts to __isnanf() or __isnanl(). gcc doesn't understand these, and the slow extern functions are used. - if the API is spelled isnanf() or isnanl(), then the result is correct and the warning magically goes away. declares isnanf(), but gcc apparently declares both iff is included. gcc also optimizes isnanl() on a float arg to __builtin_isnanf(). - no function version can work in some cases, because any function version may have unwanted side effects. This is another of the main reason for the existence of these and other macros. The main unwanted side effect is signaling for signaling NaNs. C99 doesn't really support signaling NaNs, even with the IEC 60559 extensions, so almost anything is allowed for them. But IEEE 854 is fairly clear that isnan() and classification macros shouldn't raise any exceptions. IEEE 854 is even clearer that copying values without changing their representation should (shall?) not cause exceptions. But on i387, just loading a float or double value changes its representation and generates an exception for signaling NaNs, while just loading a long double value conforms to IEEE 854 and doesn't change its representation or generate an exception. Passing of args to functions may or may not load the values. ABIs may require a change of representation. On i387, passing of double args should go through the FPU for efficiency reasons, and this changes the representation twice to not even get back to the original (for signaling NaNs, it generates an exception and sets the quiet bit in the result; thus a classification function can never see a signaling NaN in double precision). So a high quality inplementation must not use function versions, and it must also use builtins that don't even load the values into normal FP registers if this might cause an exception or change the values. Both gcc's and clang's builtins are broken on i387 (i386 or amd64 -m32) since the do load the value. In view of all these bugs, the best available implementation of isnan(x) is ((x) != (x)) (using an unportable statement-expression to avoid multiple evaluation). The known bugs in this implementation are: - it will load the value and thus give unwanted exceptions for signaling NaNs in some cases. But compiler builtins are no better. (IEEE 854 has a lot to say about exceptions for comparison operators, and the builtin comparison operators exist in C99 for related reasons. IIRC, the comparison operators are useless with IEEE 854 conformance, since ordinary comparison operators then do the right thing. The details are unclear, but I couldn't find any cases where gcc or clang on x86 do the wrong thing or do different things for the builtin comparison operators. For ((x) != (x)), they generate an "unordered" comparison and this is the right thing for isnan(). Their builtin isnan()s generate exactly the same code as for ((x) != (x)).) - it may be broken by flags like -ffast-math that turn off IEEE conformance. Bruce From owner-freebsd-standards@FreeBSD.ORG Thu Jul 11 08:47:49 2013 Return-Path: Delivered-To: freebsd-standards@FreeBSD.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by hub.freebsd.org (Postfix) with ESMTP id 2C180B31; Thu, 11 Jul 2013 08:47:49 +0000 (UTC) (envelope-from theraven@FreeBSD.org) Received: from theravensnest.org (theraven.freebsd.your.org [216.14.102.27]) by mx1.freebsd.org (Postfix) with ESMTP id F04E31B5A; Thu, 11 Jul 2013 08:47:48 +0000 (UTC) Received: from [192.168.0.2] (cpc27-cmbg15-2-0-cust235.5-4.cable.virginmedia.com [86.27.188.236]) (authenticated bits=0) by theravensnest.org (8.14.5/8.14.5) with ESMTP id r6B8kLGo001311 (version=TLSv1/SSLv3 cipher=AES128-SHA bits=128 verify=NO); Thu, 11 Jul 2013 08:46:23 GMT (envelope-from theraven@FreeBSD.org) Content-Type: multipart/signed; boundary="Apple-Mail=_B9A0D356-39FE-4BC5-B2BB-1563285CBA51"; protocol="application/pgp-signature"; micalg=pgp-sha1 Mime-Version: 1.0 (Mac OS X Mail 6.3 \(1503\)) Subject: Re: CURRENT: CLANG 3.3 and -stad=c++11 and -stdlib=libc++: isnan()/isninf() oddity From: David Chisnall In-Reply-To: <20130711130043.R920@besplex.bde.org> Date: Thu, 11 Jul 2013 09:46:17 +0100 Message-Id: References: <20130710155809.0f589c22@thor.walstatt.dyndns.org> <20130710183315.725dfde0@thor.walstatt.dyndns.org> <20130710203200.5359fd18@thor.walstatt.dyndns.org> <51DDC04B.6040209@FreeBSD.org> <20957.49978.73666.392417@khavrinen.csail.mit.edu> <20130711130043.R920@besplex.bde.org> To: Bruce Evans X-Mailer: Apple Mail (2.1503) Cc: Garrett Wollman , Tijl Coosemans , FreeBSD CURRENT , freebsd-standards@FreeBSD.org, freebsd-toolchain@FreeBSD.org X-BeenThere: freebsd-standards@freebsd.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: Standards compliance List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 11 Jul 2013 08:47:49 -0000 --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 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 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 . > The FreeBSD isnan() implementation would be broken by removing the > isnan() function from libm.a or ifdefing it in . 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-- From owner-freebsd-standards@FreeBSD.ORG Thu Jul 11 09:37:36 2013 Return-Path: Delivered-To: freebsd-standards@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [8.8.178.115]) by hub.freebsd.org (Postfix) with ESMTP id 45BAED9C; Thu, 11 Jul 2013 09:37:36 +0000 (UTC) (envelope-from tijl@freebsd.org) Received: from mailrelay011.isp.belgacom.be (mailrelay011.isp.belgacom.be [195.238.6.178]) by mx1.freebsd.org (Postfix) with ESMTP id 7B3411DF2; Thu, 11 Jul 2013 09:37:35 +0000 (UTC) X-Belgacom-Dynamic: yes X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: Al4GAGZ73lFR8aPm/2dsb2JhbABagwnCT4EGF3SCIwEBBAFWIwULCw4KCSUPAigeBg0BBQIBAYgFCrccj2EHg3UDkA6BLZdpgViBOzo Received: from 230.163-241-81.adsl-dyn.isp.belgacom.be (HELO kalimero.tijl.coosemans.org) ([81.241.163.230]) by relay.skynet.be with ESMTP; 11 Jul 2013 11:37:26 +0200 Received: from kalimero.tijl.coosemans.org (kalimero.tijl.coosemans.org [127.0.0.1]) by kalimero.tijl.coosemans.org (8.14.7/8.14.7) with ESMTP id r6B9bP9C007983; Thu, 11 Jul 2013 11:37:25 +0200 (CEST) (envelope-from tijl@FreeBSD.org) Message-ID: <51DE7CD0.60306@FreeBSD.org> Date: Thu, 11 Jul 2013 11:37:20 +0200 From: Tijl Coosemans User-Agent: Mozilla/5.0 (X11; FreeBSD i386; rv:17.0) Gecko/20130701 Thunderbird/17.0.7 MIME-Version: 1.0 To: Bruce Evans Subject: Re: CURRENT: CLANG 3.3 and -stad=c++11 and -stdlib=libc++: isnan()/isninf() oddity References: <20130710155809.0f589c22@thor.walstatt.dyndns.org> <20130710183315.725dfde0@thor.walstatt.dyndns.org> <20130710203200.5359fd18@thor.walstatt.dyndns.org> <51DDC04B.6040209@FreeBSD.org> <20957.49978.73666.392417@khavrinen.csail.mit.edu> <20130711130043.R920@besplex.bde.org> In-Reply-To: <20130711130043.R920@besplex.bde.org> X-Enigmail-Version: 1.5.1 Content-Type: multipart/signed; micalg=pgp-sha256; protocol="application/pgp-signature"; boundary="----enig2EUTOIBMOAOLMNPWCAKBE" Cc: Garrett Wollman , FreeBSD CURRENT , freebsd-standards@FreeBSD.org, freebsd-toolchain@FreeBSD.org X-BeenThere: freebsd-standards@freebsd.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: Standards compliance List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 11 Jul 2013 09:37:36 -0000 This is an OpenPGP/MIME signed message (RFC 4880 and 3156) ------enig2EUTOIBMOAOLMNPWCAKBE Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable On 2013-07-11 06:21, Bruce Evans wrote: > On Wed, 10 Jul 2013, Garrett Wollman wrote: >> < said: >>> I think isnan(double) and isinf(double) in math.h should only be >>> visible if (_BSD_VISIBLE || _XSI_VISIBLE) && __ISO_C_VISIBLE < 1999. >>> For C99 and higher there should only be the isnan/isinf macros. >> >> I believe you are correct. POSIX.1-2008 (which is aligned with C99) >> consistently calls isnan() a "macro", and gives a pseudo-prototype of >> >> int isnan(real-floating x); >=20 > Almost any macro may be implemented as a function, if no conforming > program can tell the difference. It is impossible for technical reason= s > to implement isnan() as a macro (except on weird implementations where > all real-floating types are physically the same). In the FreeBSD > implementation, isnan() is a macro, but it is also a function, and > the macro expands to the function in double precision: >=20 > % #define isnan(x) \ > % ((sizeof (x) =3D=3D sizeof (float)) ? __isnanf(x) \ > % : (sizeof (x) =3D=3D sizeof (double)) ? isnan(x) \ > % : __isnanl(x)) The C99 standard says isnan is a macro. I would say that only means defined(isnan) is true. Whether that macro then expands to function calls or not is not important. > 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. I don't think the standard allows a function to be declared with the same= name as a standard macro (it does allow the reverse: define a macro with the same name as a standard function). I believe the following code is C99 conforming but it currently does not compile with our math.h: ------ #include =20 int (isnan)(int a, int b, int c) { return (a + b + c); } ------ ------enig2EUTOIBMOAOLMNPWCAKBE Content-Type: application/pgp-signature; name="signature.asc" Content-Description: OpenPGP digital signature Content-Disposition: attachment; filename="signature.asc" -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.20 (FreeBSD) iF4EAREIAAYFAlHefNQACgkQfoCS2CCgtisTnwD7BfDDEcW43Z/knFNt/gk133gK oHU9NLmi8d4J9J5MIlQA/jpqMQEQHsree+HBmQmG+RWL1sBDXxit5pXk28CVamlC =faze -----END PGP SIGNATURE----- ------enig2EUTOIBMOAOLMNPWCAKBE-- From owner-freebsd-standards@FreeBSD.ORG Thu Jul 11 12:11:08 2013 Return-Path: Delivered-To: freebsd-standards@FreeBSD.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by hub.freebsd.org (Postfix) with ESMTP id EB7E34C5; Thu, 11 Jul 2013 12:11:08 +0000 (UTC) (envelope-from brde@optusnet.com.au) Received: from mail106.syd.optusnet.com.au (mail106.syd.optusnet.com.au [211.29.132.42]) by mx1.freebsd.org (Postfix) with ESMTP id 35E6718C5; Thu, 11 Jul 2013 12:11:07 +0000 (UTC) Received: from c122-106-156-23.carlnfd1.nsw.optusnet.com.au (c122-106-156-23.carlnfd1.nsw.optusnet.com.au [122.106.156.23]) by mail106.syd.optusnet.com.au (Postfix) with ESMTPS id 90CC93C2C4C; Thu, 11 Jul 2013 22:11:01 +1000 (EST) Date: Thu, 11 Jul 2013 22:11:00 +1000 (EST) From: Bruce Evans X-X-Sender: bde@besplex.bde.org To: David Chisnall Subject: Re: CURRENT: CLANG 3.3 and -stad=c++11 and -stdlib=libc++: isnan()/isninf() oddity In-Reply-To: Message-ID: <20130711202908.L84170@besplex.bde.org> References: <20130710155809.0f589c22@thor.walstatt.dyndns.org> <20130710183315.725dfde0@thor.walstatt.dyndns.org> <20130710203200.5359fd18@thor.walstatt.dyndns.org> <51DDC04B.6040209@FreeBSD.org> <20957.49978.73666.392417@khavrinen.csail.mit.edu> <20130711130043.R920@besplex.bde.org> MIME-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII; format=flowed X-Optus-CM-Score: 0 X-Optus-CM-Analysis: v=2.0 cv=K8x6hFqI c=1 sm=1 a=GSpoo125mhwA:10 a=kj9zAlcOel0A:10 a=PO7r1zJSAAAA:8 a=JzwRw_2MAAAA:8 a=mlUDQFikY8EA:10 a=AJ7DxV0eBxafINBosPIA:9 a=CjuIK1q_8ugA:10 a=ebeQFi2P/qHVC0Yw9JDJ4g==:117 Cc: freebsd-toolchain@FreeBSD.org, Garrett Wollman , FreeBSD CURRENT , Tijl Coosemans , freebsd-standards@FreeBSD.org X-BeenThere: freebsd-standards@freebsd.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: Standards compliance List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 11 Jul 2013 12:11:09 -0000 On Thu, 11 Jul 2013, David Chisnall wrote: > You're joining in this discussion starting in the middle, so you probably missed the earlier explanation. I was mainly addressing a C99 point. I know little about C++ or C11. > On 11 Jul 2013, at 05:21, Bruce Evans 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 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. > > 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 . is also not required to be conforming C code, let alone C++ code, so there is only a practical requirement that it works when included in the C++ implementation. >> The FreeBSD isnan() implementation would be broken by removing the >> isnan() function from libm.a or ifdefing it in . 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 != 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. The compatibility that I'm talking about is with old versions of FreeBSD. isnan() is still in libc as a function since that was part of the FreeBSD ABI and too many things depended on getting it from there. It was recently removed from libc.so, but is still in libm.a. This causes some implementation problems in libm that are still not completely solved. I keep having to edit msun/src/s_isnan.c the msun sources are more portable. Mostly I need to kill the isnan() there so that it doesn't get in the way of the one in libc. This mostly works even if there is none in libc, since the builtins result in neither being used. isnanf() is more of a problem, since it is mapped to __isnanf() and there is no builtin for __isnanf(). The old functions have actually been removed from libc.a too. They only in libc_pic.a. libc.a still has isnan.o, but that is bogus since isnan.o is now empty. > 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) This won't work for me, since I develop and test msun with old compilers that don't support __has_builtin(). Much the same set of compilers also don't have enough FP builtins. It also doesn't even work. clang has squillions of builtins that aren't really builtines so they reduce to libcalls. gcc has fewer builtins, but still many that reduce to libcalls. An example is fma(). __has_builtin(__builtin_fma) is true for clang on amd64 (freefall), but at least freefalls's CPU doesn't support fma in hardware, so the builtin can't really work, and in fact it doesn't -- it reduces to a libcall. This might change if the hardware supports fma, but then __has_builtin(__builtin_fma) would be even more useless for telling if fma is worth using. C99 has macros FP_FAST_FMA[FL] whose implementation makes them almost equally useless. For example, ia64 has fma in hardware and the implementation defines all of FP_FAST_FMA[FL] for ia64. But fma is implemented as an extern function, partly because there is no way to tell if __builtin_fma is any good (but IIRC, __builtin_fma is no good on ia64 either, since it reduces to the same extern function). The extern function is slow (something like 20 cycles instead of 1 for the fma operation). But if you ignore the existence of the C99 fma API and just write expressions of the form (a*x + b), then gcc on ia64 will automatically use the hardware fma, although this is technically wrong in some fenv environments. For gcc-4.2.1, __has_builtin(__builtin_fma) is a syntax error. I test with gcc-3.x. It is also missing __builtin_isnan(). The msun implementation knows that isnan() and other classification macros are too slow to actually use, and rarely uses them. Sometimes it is inherent that it can do better, because it already knows the bits in the macros and can test the bits directly. I have had limited tests with arranging access macros so that loads of the bits can be shared. > #define isnan(x) __builtin_isnan(x) > #else > static __inline int > __isnanf(float __x) > { > return (__x != __x); > } Here we can do better in most cases by hard-coding this without the ifdef. > static __inline int > __isnand(double __x) > { > return (__x != __x); > } __isnand() is a strange name, and doesn't match compiler conventions for builtins. Compilers use __builtin_isnan() and map this to the libcall __isnan(). > static __inline int > __isnanl(long double __x) > { > return (__x != __x); > } > #if __STDC_VERSION__ >= 201112L > #define isnan(x) _Generic((x), \ > float: __isnanf(x), \ > double: __isnand(x), \ > long double: __isnanl(x)) Does _Generic() have no side effects, like sizeof()? > #else > #define isnan(x) \ > ((sizeof (x) == sizeof (float)) ? __isnanf(x) \ > : (sizeof (x) == sizeof (double)) ? __isnand(x) \ > : __isnanl(x)) > #endif > #endif Both cases need to use __builtin_isnan[fl]() and depend on compiler magic to have any chance of avoiding side effects from loads and parameter passing. Generic stuff doesn't seem to work right for either isnan() or __builtin_isnan(), though it could for at least the latter. According to a quick grep of strings $(which clang), __builtin_classify() is generic but __builtin_isnan*() isn't (the former has no type suffixes but the latter does, and testing shows that the latter doesn't work without the suffices). It is the most useful FP builtins like __builtin_fabs*() that aren't generic. C99 probably prevents fabs*() being generic, but I think any builtin can be generic, and the isnan() macro is specified to be generic, so if compilers understood it directly their builtin for it needs to be and can be generic. > 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); > ^ The error message for the __builtin_isnan() version is slightly better up to where it says more. The less-unportable macro can do more classification and detect problems at compile time using __typeof(). isnan(integer) = 0 with no warnings is quite good though. Integers are never NaNs, and converting an integer to a floating point type should never give a NaN. Bruce From owner-freebsd-standards@FreeBSD.ORG Thu Jul 11 12:50:10 2013 Return-Path: Delivered-To: freebsd-standards@FreeBSD.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by hub.freebsd.org (Postfix) with ESMTP id 93F7050F; Thu, 11 Jul 2013 12:50:08 +0000 (UTC) (envelope-from theraven@FreeBSD.org) Received: from theravensnest.org (theraven.freebsd.your.org [216.14.102.27]) by mx1.freebsd.org (Postfix) with ESMTP id E41761B1C; Thu, 11 Jul 2013 12:50:07 +0000 (UTC) Received: from c120.sec.cl.cam.ac.uk (c120.sec.cl.cam.ac.uk [128.232.18.120]) (authenticated bits=0) by theravensnest.org (8.14.5/8.14.5) with ESMTP id r6BCo1km015361 (version=TLSv1/SSLv3 cipher=AES128-SHA bits=128 verify=NO); Thu, 11 Jul 2013 12:50:02 GMT (envelope-from theraven@FreeBSD.org) Content-Type: multipart/signed; boundary="Apple-Mail=_C84CB7FF-D855-40EC-9DD9-FD206EB11660"; protocol="application/pgp-signature"; micalg=pgp-sha1 Mime-Version: 1.0 (Mac OS X Mail 6.3 \(1503\)) Subject: Re: CURRENT: CLANG 3.3 and -stad=c++11 and -stdlib=libc++: isnan()/isninf() oddity From: David Chisnall In-Reply-To: <20130711202908.L84170@besplex.bde.org> Date: Thu, 11 Jul 2013 13:49:57 +0100 Message-Id: References: <20130710155809.0f589c22@thor.walstatt.dyndns.org> <20130710183315.725dfde0@thor.walstatt.dyndns.org> <20130710203200.5359fd18@thor.walstatt.dyndns.org> <51DDC04B.6040209@FreeBSD.org> <20957.49978.73666.392417@khavrinen.csail.mit.edu> <20130711130043.R920@besplex.bde.org> <20130711202908.L84170@besplex.bde.org> To: Bruce Evans X-Mailer: Apple Mail (2.1503) Cc: freebsd-toolchain@FreeBSD.org, Garrett Wollman , FreeBSD CURRENT , Tijl Coosemans , freebsd-standards@FreeBSD.org X-BeenThere: freebsd-standards@freebsd.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: Standards compliance List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 11 Jul 2013 12:50:10 -0000 --Apple-Mail=_C84CB7FF-D855-40EC-9DD9-FD206EB11660 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset=us-ascii On 11 Jul 2013, at 13:11, Bruce Evans wrote: > is also not required to be conforming C code, let alone C++ = code, > so there is only a practical requirement that it works when included > in the C++ implementation. Working with the C++ implementation is the problem that we are trying to = solve. > The compatibility that I'm talking about is with old versions of = FreeBSD. > isnan() is still in libc as a function since that was part of the = FreeBSD > ABI and too many things depended on getting it from there. It was = recently > removed from libc.so, but is still in libm.a. This causes some > implementation problems in libm that are still not completely solved. = I > keep having to edit msun/src/s_isnan.c the msun sources are more = portable. > Mostly I need to kill the isnan() there so that it doesn't get in the > way of the one in libc. This mostly works even if there is none in = libc, > since the builtins result in neither being used. isnanf() is more of = a > problem, since it is mapped to __isnanf() and there is no builtin for > __isnanf(). The old functions have actually been removed from libc.a > too. They only in libc_pic.a. libc.a still has isnan.o, but that is = bogus > since isnan.o is now empty. I don't see a problem with changing the name of the function in the = header and leaving the old symbol in libm for legacy code. =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: >=20 >> #if __has_builtin(__builtin_isnan) >=20 > This won't work for me, since I develop and test msun with old = compilers > that don't support __has_builtin(). Much the same set of compilers = also > don't have enough FP builtins. Please look in cdefs.h, which defines __has_builtin(x) to 0 if we the = compiler does not support it. It is therefore safe to use = __has_builtin() in any FreeBSD header. > It also doesn't even work. clang has squillions of builtins that > aren't really builtines so they reduce to libcalls. Which, again, is not a problem for code outside of libm. If libm needs = different definitions of these macros then that's fine, but they should = be private to libm, not installed as public headers. > The msun implementation knows that isnan() and other classification > macros are too slow to actually use, and rarely uses them. =20 Which makes any concerns that only apply to msun internals irrelevant = from the perspective of discussing what goes into this header. >> #define isnan(x) __builtin_isnan(x) >> #else >> static __inline int >> __isnanf(float __x) >> { >> return (__x !=3D __x); >> } >=20 > Here we can do better in most cases by hard-coding this without the = ifdef. They will generate the same code. Clang expands the builtin in the LLVM = IR to a fcmp uno, so will generate the correct code even when doing fast = math optimisations. >> static __inline int >> __isnand(double __x) >> { >> return (__x !=3D __x); >> } >=20 > __isnand() is a strange name, and doesn't match compiler conventions = for > builtins. Compilers use __builtin_isnan() and map this to the libcall > __isnan(). That's fine. >> 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)) >=20 > Does _Generic() have no side effects, like sizeof()? Yes. >> #else >> #define isnan(x) \ >> ((sizeof (x) =3D=3D sizeof (float)) ? __isnanf(x) \ >> : (sizeof (x) =3D=3D sizeof (double)) ? __isnand(x) \ >> : __isnanl(x)) >> #endif >> #endif >=20 > Both cases need to use __builtin_isnan[fl]() and depend on compiler > magic to have any chance of avoiding side effects from loads and > parameter passing. > Generic stuff doesn't seem to work right for either isnan() or > __builtin_isnan(), though it could for at least the latter. According > to a quick grep of strings $(which clang), __builtin_classify() is > generic but __builtin_isnan*() isn't (the former has no type suffixes > but the latter does, and testing shows that the latter doesn't work > without the suffices). =20 I'm not sure what you were testing: $ cat isnan2.c=20 int test(float f, double d, long double l) { return __builtin_isnan(f) | __builtin_isnan(d) | __builtin_isnan(l); } $ clang isnan2.c -S -emit-llvm -o - -O1 ... %cmp =3D fcmp uno float %f, 0.000000e+00 %cmp1 =3D fcmp uno double %d, 0.000000e+00 %or4 =3D or i1 %cmp, %cmp1 %cmp2 =3D fcmp uno x86_fp80 %l, 0xK00000000000000000000 ... As you can see, it parses them as generics and generates different IR = for each. I don't believe that there's a way that these would be = translated back into libcalls in the back end. >> For a trivial example of why this is an improvement in terms of error = reporting, consider this trivial piece of code: >>=20 >> int is(int x) >> { >> return isnan(x); >> } >>=20 >> 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: >>=20 >> 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) >>=20 >> With the C11 version, it reports this error: >>=20 >> isnan.c:35:15: error: controlling expression type 'int' not = compatible with any >> generic association type >> return isnan(x); >> ^ >=20 > The error message for the __builtin_isnan() version is slightly better = up > to where it says more. I agree. > The less-unportable macro can do more classification and detect = problems > at compile time using __typeof(). Yes, that would be an improvement, however all of our current = type-generic macros in math.h use sizeof(). > isnan(integer) =3D 0 with no warnings is quite good though. Integers = are > never NaNs, and converting an integer to a floating point type should > never give a NaN. I disagree. isnan(integer) is almost certainly a mistake and so should = be a compile-time error. If it is intentional, it relies on = non-standard behaviour and so should be discouraged. David --Apple-Mail=_C84CB7FF-D855-40EC-9DD9-FD206EB11660 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 iQIcBAEBAgAGBQJR3qn2AAoJEKx65DEEsqIdl20P/1LQgcJ0nXFNpCOq37dEkMlY hPc/5+f0g+2U27WGbaiEjwT1lD+Up598h3TmgZqlUsALGLVZ650tDlbHG6eF77US zCmMuCbnWJcTitLaSBaIpvT8HBF5NrfHssPr5AXMaaO66AssKedgnL72GbCHz0CK izxO+p4Wq+kQcG1WfXwhUJZrpCmCYZO1sdBztKN4e6EbI8RRUhM1ySce69yN3/nm BlQbSJQqHttn35+Va9E3t02uXfZivtYjdxPphROymTMgfe4d9MJu85BZqZsrPkxm AglIzrnIdFFkCz9bICrFX8/NNXhEHMHNlzGEhCOf9QUZWLrdiIyhI7FibOs/mtUi RUxeiNupnXso32o0B2gcokm/swUkwiszjDfIyT8K/I3taBHyyrVEmZu2wZ40AZRx TjI5a6pe/Phcq+5PmGFp90NXkONyQ7aCOPPRcWYVictw60BYy7AJDp/Iwa+X6rFI ij3LSPONv+FUOYuJyNct9VIfT2zBHE71Q6LRPzto6PO50gsfVVUsBBl6eXL0ULz/ nWOCckUYHkVciPvdZkP/dV9z5t043KAJMdhkclpsY/h1eVZ9eNPj3T403RzLiWSW hF7+t+dhOP5CkZ2wRe2ONDq6T/mLULaWhVWu5Rgp9VNFk62tWoqSdt2ZsybAjxjT u5vg2zAg+cYrujbX8AN9 =A/T6 -----END PGP SIGNATURE----- --Apple-Mail=_C84CB7FF-D855-40EC-9DD9-FD206EB11660-- From owner-freebsd-standards@FreeBSD.ORG Thu Jul 11 13:02:25 2013 Return-Path: Delivered-To: freebsd-standards@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by hub.freebsd.org (Postfix) with ESMTP id CA8C8B13; Thu, 11 Jul 2013 13:02:25 +0000 (UTC) (envelope-from brde@optusnet.com.au) Received: from mail110.syd.optusnet.com.au (mail110.syd.optusnet.com.au [211.29.132.97]) by mx1.freebsd.org (Postfix) with ESMTP id 482CF1BFD; Thu, 11 Jul 2013 13:02:24 +0000 (UTC) Received: from c122-106-156-23.carlnfd1.nsw.optusnet.com.au (c122-106-156-23.carlnfd1.nsw.optusnet.com.au [122.106.156.23]) by mail110.syd.optusnet.com.au (Postfix) with ESMTPS id CA90F780326; Thu, 11 Jul 2013 23:02:11 +1000 (EST) Date: Thu, 11 Jul 2013 23:02:10 +1000 (EST) From: Bruce Evans X-X-Sender: bde@besplex.bde.org To: Tijl Coosemans Subject: Re: CURRENT: CLANG 3.3 and -stad=c++11 and -stdlib=libc++: isnan()/isninf() oddity In-Reply-To: <51DE7CD0.60306@FreeBSD.org> Message-ID: <20130711221303.A84846@besplex.bde.org> References: <20130710155809.0f589c22@thor.walstatt.dyndns.org> <20130710183315.725dfde0@thor.walstatt.dyndns.org> <20130710203200.5359fd18@thor.walstatt.dyndns.org> <51DDC04B.6040209@FreeBSD.org> <20957.49978.73666.392417@khavrinen.csail.mit.edu> <20130711130043.R920@besplex.bde.org> <51DE7CD0.60306@FreeBSD.org> MIME-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII; format=flowed X-Optus-CM-Score: 0 X-Optus-CM-Analysis: v=2.0 cv=eqSHVfVX c=1 sm=1 a=GSpoo125mhwA:10 a=kj9zAlcOel0A:10 a=PO7r1zJSAAAA:8 a=JzwRw_2MAAAA:8 a=mlUDQFikY8EA:10 a=6I5d2MoRAAAA:8 a=0ey3mXvhcGIDxT-u3RAA:9 a=CjuIK1q_8ugA:10 a=SV7veod9ZcQA:10 a=ebeQFi2P/qHVC0Yw9JDJ4g==:117 Cc: Garrett Wollman , FreeBSD CURRENT , freebsd-standards@freebsd.org, freebsd-toolchain@freebsd.org X-BeenThere: freebsd-standards@freebsd.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: Standards compliance List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 11 Jul 2013 13:02:25 -0000 On Thu, 11 Jul 2013, Tijl Coosemans wrote: > On 2013-07-11 06:21, Bruce Evans wrote: >> On Wed, 10 Jul 2013, Garrett Wollman wrote: >>> < said: >>>> I think isnan(double) and isinf(double) in math.h should only be >>>> visible if (_BSD_VISIBLE || _XSI_VISIBLE) && __ISO_C_VISIBLE < 1999. >>>> For C99 and higher there should only be the isnan/isinf macros. >>> >>> I believe you are correct. POSIX.1-2008 (which is aligned with C99) >>> consistently calls isnan() a "macro", and gives a pseudo-prototype of >>> >>> int isnan(real-floating x); >> >> Almost any macro may be implemented as a function, if no conforming >> program can tell the difference. It is impossible for technical reasons >> to implement isnan() as a macro (except on weird implementations where >> all real-floating types are physically the same). In the FreeBSD >> implementation, isnan() is a macro, but it is also a function, and >> the macro expands to the function in double precision: >> >> % #define isnan(x) \ >> % ((sizeof (x) == sizeof (float)) ? __isnanf(x) \ >> % : (sizeof (x) == sizeof (double)) ? isnan(x) \ >> % : __isnanl(x)) > > The C99 standard says isnan is a macro. I would say that only means > defined(isnan) is true. Whether that macro then expands to function > calls or not is not important. I think it means only that defined(isnan) is true. isnan() can still be a function (declared or just in the compile-time namespace somewhere, or in a library object). It is reserved in the compile-time namespace, and the standard doesn't cover library objects, so conforming applications can't reference either except via the isnan() macro (if that has its strange historical implementation). >> 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. > > I don't think the standard allows a function to be declared with the same > name as a standard macro (it does allow the reverse: define a macro with > the same name as a standard function). I believe the following code is > C99 conforming but it currently does not compile with our math.h: > > ------ > #include > > int (isnan)(int a, int b, int c) { > return (a + b + c); > } > ------ I think isnan is just reserved, so you can't redefine it an any way. I think the reverse is even less allowed. Almost any standard function may be implemented as a macro, and then any macro definition of it would conflict with the previous macro even more than with a previous prototype. E.g.: /* Header. */ void exit(int); #define exit(x) __exit(x) /* Application. */ #undef exit /* non-conforming */ #define exit(x) my_exit(x) /* conflicts without the #undef */ Now suppose the header doesn't define exit(). #define exit(x) my_exit(x) This hides the protoype but doesn't automatically cause problems, especially if exit() is not used after this point. But this is still non-conforming, since exit() is reserved. Here are some relevant parts of C99 (n869.txt): %%% -- Each identifier with file scope listed in any of the following subclauses (including the future library directions) is reserved for use as macro and as an identifier with file scope in the same name space if any of its associated headers is included. [#2] No other identifiers are reserved. If the program declares or defines an identifier in a context in which it is reserved (other than as allowed by 7.1.4), or defines a reserved identifier as a macro name, the behavior is undefined. [#3] If the program removes (with #undef) any macro definition of an identifier in the first group listed above, the behavior is undefined. %%% Without any include of a header that is specified to declare exit(), file scope things are permitted for it, including defining it and making it a static function, but not making it an extern function. isnan is reserved for use as a macro and as an identifier with file scope by the first clause above. Thus (isnan) cannot even be defined as a static function. But (isnan) is not reserved in inner scopes. I thought that declarations like "int (isnan);" are impossible since they look like syntax errors, but this syntax seems to be allowed an actually work with gcc-3.3.3 and TenDRA-5.0.0. So you can have variables with silly names like (isnan) and (getchar) :-). However, (NULL) for a variable name doesn't work, and (isnan) is a syntax error for struct member names. The compilers may be correct in allowing (isnan) but not (NULL) for variables. isnan happens to be function-like, so the parentheses are special for (isnan), but the parentheses are not special for (NULL). cpp confirms this -- NULL inside of parentheses still gets expanded. The above quote of C99 can cover both since it just says that isnan is reserved for use as a macro. In (isnan), the parentheses prevent isnan being interpreted as a macro so the reservation doesn't apply. Bruce From owner-freebsd-standards@FreeBSD.ORG Thu Jul 11 14:33:44 2013 Return-Path: Delivered-To: freebsd-standards@FreeBSD.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by hub.freebsd.org (Postfix) with ESMTP id 8DEA042A; Thu, 11 Jul 2013 14:33:44 +0000 (UTC) (envelope-from theraven@FreeBSD.org) Received: from theravensnest.org (theraven.freebsd.your.org [216.14.102.27]) by mx1.freebsd.org (Postfix) with ESMTP id 4444F10AB; Thu, 11 Jul 2013 14:33:43 +0000 (UTC) Received: from c120.sec.cl.cam.ac.uk (c120.sec.cl.cam.ac.uk [128.232.18.120]) (authenticated bits=0) by theravensnest.org (8.14.5/8.14.5) with ESMTP id r6BEXZMt028134 (version=TLSv1/SSLv3 cipher=AES128-SHA bits=128 verify=NO); Thu, 11 Jul 2013 14:33:36 GMT (envelope-from theraven@FreeBSD.org) Content-Type: multipart/signed; boundary="Apple-Mail=_F8478B29-A983-4EC7-89DB-B3DA02262956"; protocol="application/pgp-signature"; micalg=pgp-sha1 Mime-Version: 1.0 (Mac OS X Mail 6.3 \(1503\)) Subject: Re: CURRENT: CLANG 3.3 and -stad=c++11 and -stdlib=libc++: isnan()/isninf() oddity From: David Chisnall In-Reply-To: <20130711202908.L84170@besplex.bde.org> Date: Thu, 11 Jul 2013 15:33:34 +0100 Message-Id: References: <20130710155809.0f589c22@thor.walstatt.dyndns.org> <20130710183315.725dfde0@thor.walstatt.dyndns.org> <20130710203200.5359fd18@thor.walstatt.dyndns.org> <51DDC04B.6040209@FreeBSD.org> <20957.49978.73666.392417@khavrinen.csail.mit.edu> <20130711130043.R920@besplex.bde.org> <20130711202908.L84170@besplex.bde.org> To: Bruce Evans X-Mailer: Apple Mail (2.1503) Cc: Garrett Wollman , Tijl Coosemans , "freebsd-toolchain@FreeBSD.org" , "freebsd-standards@FreeBSD.org" , FreeBSD CURRENT X-BeenThere: freebsd-standards@freebsd.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: Standards compliance List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 11 Jul 2013 14:33:44 -0000 --Apple-Mail=_F8478B29-A983-4EC7-89DB-B3DA02262956 Content-Type: multipart/mixed; boundary="Apple-Mail=_AEC87547-9126-4EA9-8106-07500F2E3C05" --Apple-Mail=_AEC87547-9126-4EA9-8106-07500F2E3C05 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset=us-ascii On 11 Jul 2013, at 13:11, Bruce Evans wrote: > The error message for the __builtin_isnan() version is slightly better = up > to where it says more. >=20 > The less-unportable macro can do more classification and detect = problems > at compile time using __typeof(). The attached patch fixes the related test cases in the libc++ test = suite. Please review. This does not use __builtin_isnan(), but it does: - Stop exposing isnan and isinf in the header. We already have __isinf = in libc, so this is used instead. - Call the static functions for isnan __inline__isnan*() so that they = don't conflict with the ones in libm. - Add an __fp_type_select() macro that uses either __Generic(), = __builtin_choose_expr() / __builtin_choose_expr(), or sizeof() = comparisons, depending on what the compiler supports. - Refactor all of the type-generic macros to use __fp_type_select(). =20 David --Apple-Mail=_AEC87547-9126-4EA9-8106-07500F2E3C05 Content-Disposition: attachment; filename=isnan.diff Content-Type: application/octet-stream; name="isnan.diff" Content-Transfer-Encoding: 7bit Index: src/math.h =================================================================== --- src/math.h (revision 253148) +++ src/math.h (working copy) @@ -80,28 +80,39 @@ #define FP_NORMAL 0x04 #define FP_SUBNORMAL 0x08 #define FP_ZERO 0x10 + +#if __STDC_VERSION__ >= 201112L +#define __fp_type_select(x, f, d, ld) _Generic((x), \ + float: f(x), \ + double: d(x), \ + long double: ld(x)) +#elif __GNUC_PREREQ__(5, 1) +#define __fp_type_select(x, f, d, ld) __builtin_choose_expr( \ + __builtin_types_compatible_p(__typeof (x), long double), ld(x), \ + __builtin_choose_expr( \ + __builtin_types_compatible_p(__typeof (x), double), d(x), \ + __builtin_choose_expr( \ + __builtin_types_compatible_p(__typeof (x), float), f(x), (void)0))) +#else +#define __fp_type_select(x, f, d, ld) \ + ((sizeof (x) == sizeof (float)) ? f(x) \ + : (sizeof (x) == sizeof (double)) ? d(x) \ + : ld(x)) +#endif + + + #define fpclassify(x) \ - ((sizeof (x) == sizeof (float)) ? __fpclassifyf(x) \ - : (sizeof (x) == sizeof (double)) ? __fpclassifyd(x) \ - : __fpclassifyl(x)) + __fp_type_select(x, __fpclassifyf, __fpclassifyd, __fpclassifyd) +#define isfinite(x) \ + __fp_type_select(x, __isfinitef, __isfinite, __isfinitel) +#define isinf(x) \ + __fp_type_select(x, __isinff, __isinf, __isinfl) +#define isnan(x) \ + __fp_type_select(x, __inline_isnanf, __inline_isnan, __inline_isnanl) +#define isnormal(x) \ + __fp_type_select(x, __isnormalf, __isnormal, __isnormall) -#define isfinite(x) \ - ((sizeof (x) == sizeof (float)) ? __isfinitef(x) \ - : (sizeof (x) == sizeof (double)) ? __isfinite(x) \ - : __isfinitel(x)) -#define isinf(x) \ - ((sizeof (x) == sizeof (float)) ? __isinff(x) \ - : (sizeof (x) == sizeof (double)) ? isinf(x) \ - : __isinfl(x)) -#define isnan(x) \ - ((sizeof (x) == sizeof (float)) ? __isnanf(x) \ - : (sizeof (x) == sizeof (double)) ? isnan(x) \ - : __isnanl(x)) -#define isnormal(x) \ - ((sizeof (x) == sizeof (float)) ? __isnormalf(x) \ - : (sizeof (x) == sizeof (double)) ? __isnormal(x) \ - : __isnormall(x)) - #ifdef __MATH_BUILTIN_RELOPS #define isgreater(x, y) __builtin_isgreater((x), (y)) #define isgreaterequal(x, y) __builtin_isgreaterequal((x), (y)) @@ -119,10 +130,8 @@ #define isunordered(x, y) (isnan(x) || isnan(y)) #endif /* __MATH_BUILTIN_RELOPS */ -#define signbit(x) \ - ((sizeof (x) == sizeof (float)) ? __signbitf(x) \ - : (sizeof (x) == sizeof (double)) ? __signbit(x) \ - : __signbitl(x)) +#define signbit(x) \ + __fp_type_select(x, __signbitf, __signbit, __signbitl) typedef __double_t double_t; typedef __float_t float_t; @@ -175,6 +184,7 @@ int __isfinite(double) __pure2; int __isfinitel(long double) __pure2; int __isinff(float) __pure2; +int __isinf(double) __pure2; int __isinfl(long double) __pure2; int __isnanf(float) __pure2; int __isnanl(long double) __pure2; @@ -185,6 +195,23 @@ int __signbitf(float) __pure2; int __signbitl(long double) __pure2; +static __inline int +__inline_isnanf(float __x) +{ + return (__x != __x); +} +static __inline int +__inline_isnan(double __x) +{ + return (__x != __x); +} +static __inline int +__inline_isnanl(long double __x) +{ + return (__x != __x); +} + + double acos(double); double asin(double); double atan(double); @@ -227,8 +254,6 @@ double fma(double, double, double); double hypot(double, double); int ilogb(double) __pure2; -int (isinf)(double) __pure2; -int (isnan)(double) __pure2; double lgamma(double); long long llrint(double); long long llround(double); --Apple-Mail=_AEC87547-9126-4EA9-8106-07500F2E3C05-- --Apple-Mail=_F8478B29-A983-4EC7-89DB-B3DA02262956 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 iQIcBAEBAgAGBQJR3sI+AAoJEKx65DEEsqId32IQAJZK9h5IrteHBj43ympoqEz4 XqfWOje7QIB1nMI10pOdT2oGMjF18ea7g/YMnYZ5PrHtMNlreuYqX/DkoeYvg7Lk WA2cROCI3CgIveTuODn0zfZGAd/vMlOKOm7Vw5s96vzHH/Ow8kVPbAOzd+bfmCSk xGKSi8pOHhFqBXufb269cy1Pjlh78cdY3/mEtxGFrpVxO3IZP6o844UiAicicQ+1 aqggtQH+BK7UfJN2uwGiuLjxjJmCfJR2MNqqA86q3XeACMOh52wd49w2CWt2cNrv AP5SMizT5G6gt+Qvvev5aN+1EZM7pTTSTfMtfCJyhP6iqmRPQ5yISj1A/qIzPaPd 5Qqj+xa0Y87OTf1E5xihIpZa3OileGA9nvJPLiUejLM67rjmCoA8Yea3yKoxR/58 EY6L+ZsLSJiXihO/mdTavVmHpc9u+DEO6BWo94dycciNE6KXOrFspQe6SyAgCPZ2 bqorYrrT+wWBKAox5cjGwBnkibSCdqXCZiPo/lPreZQRKgGHWgxuOSXj705fAumT 1Gg2rIbvfXWVoDlKUnXhHcmiAkRJL8hQsN/KOBTP5zOXA9xCd2LSnWSEBy5nJXha lnoBga9xG1cNlLaSMwRNd3WlSLtA5sW8ldz/wWJlaHh4zMijBwoip9VpFiLrVSi7 f4Mj5wRDY9oZclRi3PHa =v+Kg -----END PGP SIGNATURE----- --Apple-Mail=_F8478B29-A983-4EC7-89DB-B3DA02262956-- From owner-freebsd-standards@FreeBSD.ORG Thu Jul 11 15:28:35 2013 Return-Path: Delivered-To: freebsd-standards@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by hub.freebsd.org (Postfix) with ESMTP id CA0589B; Thu, 11 Jul 2013 15:28:35 +0000 (UTC) (envelope-from brde@optusnet.com.au) Received: from mail107.syd.optusnet.com.au (mail107.syd.optusnet.com.au [211.29.132.53]) by mx1.freebsd.org (Postfix) with ESMTP id 51C0B146B; Thu, 11 Jul 2013 15:28:34 +0000 (UTC) Received: from c122-106-156-23.carlnfd1.nsw.optusnet.com.au (c122-106-156-23.carlnfd1.nsw.optusnet.com.au [122.106.156.23]) by mail107.syd.optusnet.com.au (Postfix) with ESMTPS id C96DBD409AA; Fri, 12 Jul 2013 01:28:28 +1000 (EST) Date: Fri, 12 Jul 2013 01:28:26 +1000 (EST) From: Bruce Evans X-X-Sender: bde@besplex.bde.org To: David Chisnall Subject: Re: CURRENT: CLANG 3.3 and -stad=c++11 and -stdlib=libc++: isnan()/isninf() oddity In-Reply-To: Message-ID: <20130711232150.G85090@besplex.bde.org> References: <20130710155809.0f589c22@thor.walstatt.dyndns.org> <20130710183315.725dfde0@thor.walstatt.dyndns.org> <20130710203200.5359fd18@thor.walstatt.dyndns.org> <51DDC04B.6040209@FreeBSD.org> <20957.49978.73666.392417@khavrinen.csail.mit.edu> <20130711130043.R920@besplex.bde.org> <20130711202908.L84170@besplex.bde.org> MIME-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII; format=flowed X-Optus-CM-Score: 0 X-Optus-CM-Analysis: v=2.0 cv=Q6eKePKa c=1 sm=1 a=GSpoo125mhwA:10 a=kj9zAlcOel0A:10 a=PO7r1zJSAAAA:8 a=JzwRw_2MAAAA:8 a=mlUDQFikY8EA:10 a=muatdVjo9zT8fA-HE-QA:9 a=CjuIK1q_8ugA:10 a=ebeQFi2P/qHVC0Yw9JDJ4g==:117 Cc: freebsd-toolchain@freebsd.org, Garrett Wollman , FreeBSD CURRENT , Tijl Coosemans , freebsd-standards@freebsd.org X-BeenThere: freebsd-standards@freebsd.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: Standards compliance List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 11 Jul 2013 15:28:35 -0000 On Thu, 11 Jul 2013, David Chisnall wrote: > On 11 Jul 2013, at 13:11, Bruce Evans wrote: > >> is also not required to be conforming C code, let alone C++ code, >> so there is only a practical requirement that it works when included >> in the C++ implementation. > > Working with the C++ implementation is the problem that we are trying to solve. > >> The compatibility that I'm talking about is with old versions of FreeBSD. >> isnan() is still in libc as a function since that was part of the FreeBSD >> ABI and too many things depended on getting it from there. It was recently >> ... > > I don't see a problem with changing the name of the function in the header and leaving the old symbol in libm for legacy code. I don't even see why old code needs the symbol. Old code should link to old compat libraries that still have it. > >>> 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) >> >> This won't work for me, since I develop and test msun with old compilers >> that don't support __has_builtin(). Much the same set of compilers also >> don't have enough FP builtins. > > Please look in cdefs.h, which defines __has_builtin(x) to 0 if we the compiler does not support it. It is therefore safe to use __has_builtin() in any FreeBSD header. The old compilers run on old systems that don't have that in cdefs.h (though I sometimes edit it to add compatibility cruft like that). msun sources are otherwise portable to these systems. Well, not quite. They are not fully modular and also depend on stuff in libc/include and libc/${ARCH}. I have to update or edit headers there. This hack also doesn't work with gcc in -current. gcc has __builtin_isnan but not __has_builtin(), so __has_builtin(__builtin_isnan) gives the wrong result 0. >> It also doesn't even work. clang has squillions of builtins that >> aren't really builtines so they reduce to libcalls. > > Which, again, is not a problem for code outside of libm. If libm needs different definitions of these macros then that's fine, but they should be private to libm, not installed as public headers. Yes it is. It means that nothing should use isnan() or FP_FAST_FMA* outside of libm either, since isnan() is too slow and FP_FAST_FMA* can't be trusted. Even the implementation can't reliably tell if __builtin_isnan is usuable or better than alternatives. >> The msun implementation knows that isnan() and other classification >> macros are too slow to actually use, and rarely uses them. > > Which makes any concerns that only apply to msun internals irrelevant from the perspective of discussing what goes into this header. No, the efficiency of isnan() is more important for externals, because the internals already have work-arounds. >>> #define isnan(x) __builtin_isnan(x) >>> #else >>> static __inline int >>> __isnanf(float __x) >>> { >>> return (__x != __x); >>> } >> >> Here we can do better in most cases by hard-coding this without the ifdef. > > They will generate the same code. Clang expands the builtin in the LLVM IR to a fcmp uno, so will generate the correct code even when doing fast math optimisations. On some arches the same, and not affected by -ffast-math. But this is not necessarily the fastest code, so it is a performance bug if clang akways generates the same code for the builtin. Bit tests are faster in some cases, and may be required to prevent exceptions for signaling NaNs. -ffast-math could reasonably optimize x != x to "false". It already assumes that things like overflow and NaN results can't happen, so why not optimize further by assuming that NaN inputs can't happen? >> Generic stuff doesn't seem to work right for either isnan() or >> __builtin_isnan(), though it could for at least the latter. According >> to a quick grep of strings $(which clang), __builtin_classify() is >> generic but __builtin_isnan*() isn't (the former has no type suffixes >> but the latter does, and testing shows that the latter doesn't work >> without the suffices). > > I'm not sure what you were testing: Mostly isnan() without including , and gcc. I was confused by gcc converting floats to doubles. > $ cat isnan2.c > > int test(float f, double d, long double l) > { > return __builtin_isnan(f) | > __builtin_isnan(d) | > __builtin_isnan(l); > } > $ clang isnan2.c -S -emit-llvm -o - -O1 > ... > %cmp = fcmp uno float %f, 0.000000e+00 > %cmp1 = fcmp uno double %d, 0.000000e+00 > %or4 = or i1 %cmp, %cmp1 > %cmp2 = fcmp uno x86_fp80 %l, 0xK00000000000000000000 > ... > > As you can see, it parses them as generics and generates different IR for each. I don't believe that there's a way that these would be translated back into libcalls in the back end. Yes, most cases work right. gcc converts f to double and compares the result, but that mostly works. It would be just a pessimization except te conversion gives an exception for signaling NaNs. I hope I remember correctly that the comparision doesn't give this exception. When the above is changed to use __builtin_isnanf() on the float, gcc does the right thing (no conversion). The almost-correct handling of the float is apparently not completely accidental, since for the long double gcc doesn't convert to double before comparing. With gcc, you also don't have to use __builtin_isnan*() to get the builtins. gcc doesn't warn about the undeclared isnan(), and generates the same code as the above. You can also use isnanf() on the float to avoid the conversion. isnanf() is nonstandard, so gcc warns about it. If isnan() is declared as a function as in , then gcc forgets that it is standard and generates a conversion for the long double case too. This almost works, like the conversion for the float case, since changing the precision doesn't affect the classification With clang, you only get the builtins if you use them explicitly. clang generates verbose warnings for undeclared isnan() and always calls the named function. Conversions occur according to the prototype, if any. The above was tested only on amd64. isinf() is even more interesting and broken. Now gcc doesn't convert automatically to builtins. It does the reverse, in broken ways when __builtin_isinf() is used on floats and long doubles: - it converts the float to double to create the arg. Mostly works, as above. - it doesn't convert the long double to double, but copies it to the stack pessimally through integer registers. The pessimization can be fixed by compiling with -march=core2. isinf() is called twice with a double arg and once with a long double arg. This shows that gcc doesn't really understand its own builtin, but is just passing the values with the default promotions that occur when there is no prototype in scope. When __builtin_isinff() is used on the float arg and __builtin_isinfl() is used on the long double arg, gcc passes the args correctly except for pessimizing the long double. It converts __builtin_isinff() to isinff(), etc. This is very broken, since isinff() is in the application namespace. Apart from that, it causes the following problems: - isinff(), isinf() and isinfl() can't easily be removed from libraries - in general, there is no way to know the name of a libcall functions that might be generated for builtins that don't really exist. gcc also converts __builtin_fma() to fma(). That works and is not a namespace error since fma() is a standard API that must exist as a function. clang does different things wrong for __builtin_isinf(). It gets the type stuff right, as for __builtin_isnan(). It never generates libcalls, so it doesn't need a differently named set of extern functions. But it has the major pessimization of calling extern functions for fabs(), fabsf() and fabsl(). The latter is weird, since clang optimizes explicit fabs*() calls almost perfectly on amd64 using SSE bit operations for floats and doubles and i387 hardware fabs for long doubles (bit operations also work for long doubles, but are less convenient and much slower when done wrong). I probably knew some of the previous paragraph when I wrote a local isinf() for catrig*.c. catrig*.c is unlike most of msun. It uses classification macros a lot. Efficiency investigations showed that these work OK provided they always use efficient builtins and in particular, never use the standard macros (except isnan() = itself -> builtin for gcc). isinf(x) is just (fabs(x) == INFINITY), like clang generates for __builtin_isinf(), but much better since the fabs() is explicit so clang doesn't neglect to optimize it. This works well for gcc too (3.x and 4.2.1). Bruce From owner-freebsd-standards@FreeBSD.ORG Thu Jul 11 17:10:20 2013 Return-Path: Delivered-To: freebsd-standards@FreeBSD.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by hub.freebsd.org (Postfix) with ESMTP id DD671DEF; Thu, 11 Jul 2013 17:10:20 +0000 (UTC) (envelope-from brde@optusnet.com.au) Received: from mail108.syd.optusnet.com.au (mail108.syd.optusnet.com.au [211.29.132.59]) by mx1.freebsd.org (Postfix) with ESMTP id 71BFC1AB4; Thu, 11 Jul 2013 17:10:20 +0000 (UTC) Received: from c122-106-156-23.carlnfd1.nsw.optusnet.com.au (c122-106-156-23.carlnfd1.nsw.optusnet.com.au [122.106.156.23]) by mail108.syd.optusnet.com.au (Postfix) with ESMTPS id EA3171A060B; Fri, 12 Jul 2013 02:38:06 +1000 (EST) Date: Fri, 12 Jul 2013 02:38:05 +1000 (EST) From: Bruce Evans X-X-Sender: bde@besplex.bde.org To: David Chisnall Subject: Re: CURRENT: CLANG 3.3 and -stad=c++11 and -stdlib=libc++: isnan()/isninf() oddity In-Reply-To: Message-ID: <20130712013458.X85470@besplex.bde.org> References: <20130710155809.0f589c22@thor.walstatt.dyndns.org> <20130710183315.725dfde0@thor.walstatt.dyndns.org> <20130710203200.5359fd18@thor.walstatt.dyndns.org> <51DDC04B.6040209@FreeBSD.org> <20957.49978.73666.392417@khavrinen.csail.mit.edu> <20130711130043.R920@besplex.bde.org> <20130711202908.L84170@besplex.bde.org> MIME-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII; format=flowed X-Optus-CM-Score: 0 X-Optus-CM-Analysis: v=2.0 cv=eqSHVfVX c=1 sm=1 a=GSpoo125mhwA:10 a=kj9zAlcOel0A:10 a=PO7r1zJSAAAA:8 a=JzwRw_2MAAAA:8 a=mlUDQFikY8EA:10 a=5RSJzs5NDUsr1fZtrzAA:9 a=CjuIK1q_8ugA:10 a=ebeQFi2P/qHVC0Yw9JDJ4g==:117 Cc: FreeBSD CURRENT , Garrett Wollman , "freebsd-toolchain@FreeBSD.org" , Tijl Coosemans , "freebsd-standards@FreeBSD.org" X-BeenThere: freebsd-standards@freebsd.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: Standards compliance List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 11 Jul 2013 17:10:21 -0000 On Thu, 11 Jul 2013, David Chisnall wrote: > On 11 Jul 2013, at 13:11, Bruce Evans wrote: > >> The error message for the __builtin_isnan() version is slightly better up >> to where it says more. >> >> The less-unportable macro can do more classification and detect problems >> at compile time using __typeof(). > > The attached patch fixes the related test cases in the libc++ test suite. Please review. OK if the ifdefs work and the style bugs are fixed. > This does not use __builtin_isnan(), but it does: > > - Stop exposing isnan and isinf in the header. We already have __isinf in libc, so this is used instead. > > - Call the static functions for isnan __inline__isnan*() so that they don't conflict with the ones in libm. > > - Add an __fp_type_select() macro that uses either __Generic(), __builtin_choose_expr() / __builtin_choose_expr(), or sizeof() comparisons, depending on what the compiler supports. > > - Refactor all of the type-generic macros to use __fp_type_select(). % Index: src/math.h % =================================================================== % --- src/math.h (revision 253148) % +++ src/math.h (working copy) % @@ -80,28 +80,39 @@ % #define FP_NORMAL 0x04 % #define FP_SUBNORMAL 0x08 % #define FP_ZERO 0x10 % + % +#if __STDC_VERSION__ >= 201112L % +#define __fp_type_select(x, f, d, ld) _Generic((x), \ % + float: f(x), \ % + double: d(x), \ % + long double: ld(x)) The normal formatting of this is unclear. Except for the tab after #define. math.h has only 1 other instance of a space after #define. % +#elif __GNUC_PREREQ__(5, 1) % +#define __fp_type_select(x, f, d, ld) __builtin_choose_expr( \ % + __builtin_types_compatible_p(__typeof (x), long double), ld(x), \ % + __builtin_choose_expr( \ % + __builtin_types_compatible_p(__typeof (x), double), d(x), \ % + __builtin_choose_expr( \ % + __builtin_types_compatible_p(__typeof (x), float), f(x), (void)0))) Extra space after __typeof. Normal formatting doesn't march to the right like this... % +#else % +#define __fp_type_select(x, f, d, ld) \ % + ((sizeof (x) == sizeof (float)) ? f(x) \ % + : (sizeof (x) == sizeof (double)) ? d(x) \ % + : ld(x)) ... or like this. Extra space after sizeof (bug copied from old code). % +#endif % + % + % + Extra blank lines. % #define fpclassify(x) \ % - ((sizeof (x) == sizeof (float)) ? __fpclassifyf(x) \ % - : (sizeof (x) == sizeof (double)) ? __fpclassifyd(x) \ % - : __fpclassifyl(x)) Example of normal style in old code (except for the space after sizeof(), and the backslashes aren't line up like they are in some other places in this file). % ... % @@ -119,10 +130,8 @@ % #define isunordered(x, y) (isnan(x) || isnan(y)) % #endif /* __MATH_BUILTIN_RELOPS */ % % -#define signbit(x) \ % - ((sizeof (x) == sizeof (float)) ? __signbitf(x) \ % - : (sizeof (x) == sizeof (double)) ? __signbit(x) \ % - : __signbitl(x)) % +#define signbit(x) \ % + __fp_type_select(x, __signbitf, __signbit, __signbitl) The tab lossage is especially obvious here. This macro definition fits on 1 line now. Similarly for others except __inline_isnan*, which takes 2 lines. __inline_isnan* should be named less verbosely, without __inline. I think this doesn't cause any significant conflicts with libm. Might need __always_inline. __fp_type_select is also verbose. % % typedef __double_t double_t; % typedef __float_t float_t; % @@ -175,6 +184,7 @@ % int __isfinite(double) __pure2; % int __isfinitel(long double) __pure2; % int __isinff(float) __pure2; % +int __isinf(double) __pure2; % int __isinfl(long double) __pure2; % int __isnanf(float) __pure2; % int __isnanl(long double) __pure2; % @@ -185,6 +195,23 @@ % int __signbitf(float) __pure2; % int __signbitl(long double) __pure2; The declarations of old extern functions can probably be removed too when they are replaced by inlines (only __isnan*() for now) . I think the declarations of __isnan*() are now only used to prevent warnings (at higher warning levels than have ever been used) in the file that implement the functions. % % +static __inline int % +__inline_isnanf(float __x) % +{ % + return (__x != __x); % +} % +static __inline int % +__inline_isnan(double __x) % +{ % + return (__x != __x); % +} % +static __inline int % +__inline_isnanl(long double __x) % +{ % + return (__x != __x); % +} % + % + Extra blank lines. Some insertion sort errors. In this file, APIs are mostly sorted in the order double, float, long double. All the inline functions except __inline_isnan*() only evaluate their args once, so they can be simpler shorter and less namespace-polluting as macros. catrig*.c uses the following macros for them (just showing the double precision ones here): @ #define isinf(x) (fabs(x) == INFINITY) @ #define isnan(x) ((x) != (x)) @ #define signbit(x) (__builtin_signbit(x)) Note that that these are not quite independent of the precision, so they don't all need multiple inline functions or macros. fabs() is not type-generic, but __builtin_fabs() might be. fabsl() for all precisions would work but be slower. __builtin_signbit() is even more likely to be type-generic, like __builtin_isnan(). But catrig[fl].c spell out the type suffixes for safety. I hoped to copy these to math.h after fixing any technical problems. isnan() needs a statement-expression to be safe. signbit() is more of the problem than the others, since it is hard to do without a builtin and the builtin doesn't exist in gcc-3.x. The builtin works fine with -current gcc and clang, at least on x86 . So the committed version just uses the builtin, and my local version uses libm internals that are unsuitable for the public signbit() (mainly due to namespace problems). The builtin might not work right in -curent for non-x86. When the extern function is used, it uses similar libm internals, but they take much longer when not inlined. Bruce From owner-freebsd-standards@FreeBSD.ORG Fri Jul 12 16:16:47 2013 Return-Path: Delivered-To: freebsd-standards@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by hub.freebsd.org (Postfix) with ESMTP id C0DA321B; Fri, 12 Jul 2013 16:16:47 +0000 (UTC) (envelope-from swhetzel@gmail.com) Received: from mail-ie0-x22c.google.com (mail-ie0-x22c.google.com [IPv6:2607:f8b0:4001:c03::22c]) by mx1.freebsd.org (Postfix) with ESMTP id 6A0241E6F; Fri, 12 Jul 2013 16:16:47 +0000 (UTC) Received: by mail-ie0-f172.google.com with SMTP id 16so21260016iea.17 for ; Fri, 12 Jul 2013 09:16:47 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=mime-version:in-reply-to:references:date:message-id:subject:from:to :cc:content-type; bh=080gMjUYyiD0/PHb/kkcV71HbnZ9j2lWJ1l/2+iWDyM=; b=p0dQlnQBjlxO3/wrsnkArUdPVcRKw0V+NP1s/DtWDZJxC3SQkmlZMPMiptnwqP9Cuq NGl0n4Q3jme7BHxocXH8A0sf8Mq/BO/zulcHzka4d2FyGI9KwQ60Jci/HpxXfbiltGdP fBdbOhqA872YMuWvKuwpdEuaImMm86yLIA+QzKpVgnxckDHzTKbWPJS4LQQkCSWjyfJK 59/0DzsTo5xIAgutuhiJZV6DlD0hWM2GBwRI8NDzyA9M7tF+mXzd58j1UljRYPc9UPnM IrwusFOLdkQn7fLwaV5LXFIFYfpJ5Vyyxdpp3HdL8spphaP5QL4P3o0bYtIQL5JIrrQS hJAA== MIME-Version: 1.0 X-Received: by 10.50.57.51 with SMTP id f19mr1178741igq.26.1373645807137; Fri, 12 Jul 2013 09:16:47 -0700 (PDT) Received: by 10.50.221.179 with HTTP; Fri, 12 Jul 2013 09:16:46 -0700 (PDT) In-Reply-To: References: <20130710155809.0f589c22@thor.walstatt.dyndns.org> <20130710183315.725dfde0@thor.walstatt.dyndns.org> <20130710203200.5359fd18@thor.walstatt.dyndns.org> <51DDC04B.6040209@FreeBSD.org> <20957.49978.73666.392417@khavrinen.csail.mit.edu> <20130711130043.R920@besplex.bde.org> <20130711202908.L84170@besplex.bde.org> Date: Fri, 12 Jul 2013 11:16:46 -0500 Message-ID: Subject: Re: CURRENT: CLANG 3.3 and -stad=c++11 and -stdlib=libc++: isnan()/isninf() oddity From: Scot Hetzel To: David Chisnall Content-Type: text/plain; charset=ISO-8859-1 Cc: FreeBSD CURRENT , Garrett Wollman , "freebsd-toolchain@FreeBSD.org" , Tijl Coosemans , "freebsd-standards@FreeBSD.org" X-BeenThere: freebsd-standards@freebsd.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: Standards compliance List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 12 Jul 2013 16:16:47 -0000 On Thu, Jul 11, 2013 at 9:33 AM, David Chisnall wrote: > On 11 Jul 2013, at 13:11, Bruce Evans wrote: > >> The error message for the __builtin_isnan() version is slightly better up >> to where it says more. >> >> The less-unportable macro can do more classification and detect problems >> at compile time using __typeof(). > > The attached patch fixes the related test cases in the libc++ test suite. Please review. > #define fpclassify(x) \ - ((sizeof (x) == sizeof (float)) ? __fpclassifyf(x) \ - : (sizeof (x) == sizeof (double)) ? __fpclassifyd(x) \ - : __fpclassifyl(x)) + __fp_type_select(x, __fpclassifyf, __fpclassifyd, __fpclassifyd) The last __fpclassifyd should be __fpclassifyl. -- DISCLAIMER: No electrons were maimed while sending this message. Only slightly bruised. From owner-freebsd-standards@FreeBSD.ORG Fri Jul 12 17:13:59 2013 Return-Path: Delivered-To: freebsd-standards@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [8.8.178.115]) by hub.freebsd.org (Postfix) with ESMTP id 673E1AFA; Fri, 12 Jul 2013 17:13:59 +0000 (UTC) (envelope-from swhetzel@gmail.com) Received: from mail-ie0-x232.google.com (mail-ie0-x232.google.com [IPv6:2607:f8b0:4001:c03::232]) by mx1.freebsd.org (Postfix) with ESMTP id 10CBE1118; Fri, 12 Jul 2013 17:13:59 +0000 (UTC) Received: by mail-ie0-f178.google.com with SMTP id u16so21061158iet.37 for ; Fri, 12 Jul 2013 10:13:58 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=mime-version:in-reply-to:references:date:message-id:subject:from:to :cc:content-type; bh=QiisUPirFKoVMBGknphIrRZc1nDMAFRG3tSIkRd6f4A=; b=vxMm7x7CcKMfsBiyJzfiOWrjLS025G2jU91bPy+W96nfW9qdCgS9Xw2/DSv+X0SCDb goeFjw/mOmVXX3usiEu1nAVePgNC1I6223OMcOpKWPqRzWc5q7PVNFI0+QYFGlg3kUZC ggLyEeaIXiPbojCUchcVEYkwn7v5YnqwoP7UN+H/MgQgcHRkgt2m0J+I5DYPwVVHkVcN Ct6HMwonTcyBHk8P4lQYoYdW41t6zF9dc10dOCjRECmfC1YjXNVjM6BND8Jsioc5WHRz Qv1suFDojub+xZ9OagB/FmqcP18QB1oBMnyH3u2o2XKuXpKxm6YymlcvdN1sUjCXdNRd mSzA== MIME-Version: 1.0 X-Received: by 10.50.67.43 with SMTP id k11mr1242994igt.26.1373649238734; Fri, 12 Jul 2013 10:13:58 -0700 (PDT) Received: by 10.50.221.179 with HTTP; Fri, 12 Jul 2013 10:13:58 -0700 (PDT) In-Reply-To: References: <20130710155809.0f589c22@thor.walstatt.dyndns.org> <20130710183315.725dfde0@thor.walstatt.dyndns.org> <20130710203200.5359fd18@thor.walstatt.dyndns.org> <51DDC04B.6040209@FreeBSD.org> <20957.49978.73666.392417@khavrinen.csail.mit.edu> <20130711130043.R920@besplex.bde.org> <20130711202908.L84170@besplex.bde.org> Date: Fri, 12 Jul 2013 12:13:58 -0500 Message-ID: Subject: Re: CURRENT: CLANG 3.3 and -stad=c++11 and -stdlib=libc++: isnan()/isninf() oddity From: Scot Hetzel To: David Chisnall Content-Type: text/plain; charset=ISO-8859-1 Cc: FreeBSD CURRENT , Garrett Wollman , "freebsd-toolchain@FreeBSD.org" , Tijl Coosemans , "freebsd-standards@FreeBSD.org" X-BeenThere: freebsd-standards@freebsd.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: Standards compliance List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 12 Jul 2013 17:13:59 -0000 On Fri, Jul 12, 2013 at 11:16 AM, Scot Hetzel wrote: > On Thu, Jul 11, 2013 at 9:33 AM, David Chisnall wrote: >> On 11 Jul 2013, at 13:11, Bruce Evans wrote: >> >>> The error message for the __builtin_isnan() version is slightly better up >>> to where it says more. >>> >>> The less-unportable macro can do more classification and detect problems >>> at compile time using __typeof(). >> >> The attached patch fixes the related test cases in the libc++ test suite. Please review. >> > > #define fpclassify(x) \ > - ((sizeof (x) == sizeof (float)) ? __fpclassifyf(x) \ > - : (sizeof (x) == sizeof (double)) ? __fpclassifyd(x) \ > - : __fpclassifyl(x)) > + __fp_type_select(x, __fpclassifyf, __fpclassifyd, __fpclassifyd) > > The last __fpclassifyd should be __fpclassifyl. > I see it has already been fixed. -- DISCLAIMER: No electrons were maimed while sending this message. Only slightly bruised. From owner-freebsd-standards@FreeBSD.ORG Fri Jul 12 21:48:01 2013 Return-Path: Delivered-To: freebsd-standards@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [8.8.178.115]) by hub.freebsd.org (Postfix) with ESMTP id 92EA298C; Fri, 12 Jul 2013 21:48:01 +0000 (UTC) (envelope-from ohartman@zedat.fu-berlin.de) Received: from outpost1.zedat.fu-berlin.de (outpost1.zedat.fu-berlin.de [130.133.4.66]) by mx1.freebsd.org (Postfix) with ESMTP id 399A71114; Fri, 12 Jul 2013 21:48:00 +0000 (UTC) Received: from inpost2.zedat.fu-berlin.de ([130.133.4.69]) by outpost1.zedat.fu-berlin.de (Exim 4.80.1) with esmtp (envelope-from ) id <1UxlC2-002rxb-V6>; Fri, 12 Jul 2013 23:47:59 +0200 Received: from g231188215.adsl.alicedsl.de ([92.231.188.215] helo=thor.walstatt.dyndns.org) by inpost2.zedat.fu-berlin.de (Exim 4.80.1) with esmtpsa (envelope-from ) id <1UxlC2-003DTm-Px>; Fri, 12 Jul 2013 23:47:58 +0200 Date: Fri, 12 Jul 2013 23:47:49 +0200 From: "O. Hartmann" To: Scot Hetzel Subject: Re: CURRENT: CLANG 3.3 and -stad=c++11 and -stdlib=libc++: isnan()/isninf() oddity Message-ID: <20130712234749.5afa3c9b@thor.walstatt.dyndns.org> In-Reply-To: References: <20130710155809.0f589c22@thor.walstatt.dyndns.org> <20130710183315.725dfde0@thor.walstatt.dyndns.org> <20130710203200.5359fd18@thor.walstatt.dyndns.org> <51DDC04B.6040209@FreeBSD.org> <20957.49978.73666.392417@khavrinen.csail.mit.edu> <20130711130043.R920@besplex.bde.org> <20130711202908.L84170@besplex.bde.org> Organization: FU Berlin X-Mailer: Claws Mail 3.9.2 (GTK+ 2.24.19; amd64-portbld-freebsd10.0) Mime-Version: 1.0 Content-Type: multipart/signed; micalg=PGP-SHA1; boundary="Sig_/ZSAD9CXLaxRHx01iUtdTl3B"; protocol="application/pgp-signature" X-Originating-IP: 92.231.188.215 Cc: "freebsd-toolchain@FreeBSD.org" , Garrett Wollman , FreeBSD CURRENT , Tijl Coosemans , "freebsd-standards@FreeBSD.org" X-BeenThere: freebsd-standards@freebsd.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: Standards compliance List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 12 Jul 2013 21:48:01 -0000 --Sig_/ZSAD9CXLaxRHx01iUtdTl3B Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: quoted-printable On Fri, 12 Jul 2013 12:13:58 -0500 Scot Hetzel wrote: > On Fri, Jul 12, 2013 at 11:16 AM, Scot Hetzel > wrote: > > On Thu, Jul 11, 2013 at 9:33 AM, David Chisnall > > wrote: > >> On 11 Jul 2013, at 13:11, Bruce Evans wrote: > >> > >>> The error message for the __builtin_isnan() version is slightly > >>> better up to where it says more. > >>> > >>> The less-unportable macro can do more classification and detect > >>> problems at compile time using __typeof(). > >> > >> The attached patch fixes the related test cases in the libc++ test > >> suite. Please review. > >> > > > > #define fpclassify(x) \ > > - ((sizeof (x) =3D=3D sizeof (float)) ? __fpclassifyf(x) \ > > - : (sizeof (x) =3D=3D sizeof (double)) ? __fpclassifyd(x) \ > > - : __fpclassifyl(x)) > > + __fp_type_select(x, __fpclassifyf, __fpclassifyd, > > __fpclassifyd) > > > > The last __fpclassifyd should be __fpclassifyl. > > > I see it has already been fixed. >=20 >=20 Obviously not really fixed, but even worse: if I use in C code (C99, using clang 3.3 on FreeBSD 10.0-CURRENT/amd64 revision 253287) isnan(x) where x is a "const double", I receive now the following error (which doesn't appear on previous versions): [...] Making all in scaling /bin/sh ../../libtool --tag=3DCC --mode=3Dcompile cc -DHAVE_CONFIG_H -I. -I../.. -I. -I../ -I/usr/local/include -O0 -march=3Dnative -g -pipe -DHAVE_INLINE -g -O2 -MT libscaling_la-scalingTransientCroft.lo -MD -MP -MF .deps/libscaling_la-scalingTransientCroft.Tpo -c -o libscaling_la-scalingTransientCroft.lo `test -f 'scalingTransientCroft.c' || echo './'`scalingTransientCroft.c libtool: compile: cc -DHAVE_CONFIG_H -I. -I../.. -I. -I../ -I/usr/local/include -O0 -march=3Dnative -g -pipe -DHAVE_INLINE -g -O2 -MT libscaling_la-scalingTransientCroft.lo -MD -MP -MF .deps/libscaling_la-scalingTransientCroft.Tpo -c scalingTransientCroft.c -o libscaling_la-scalingTransientCroft.o scalingTransientCroft.c:48:12: error: controlling expression type 'const double' not compatible with any generic association type if (isnan(Dsg) || isnan(Dsc)) ^~~ /usr/include/math.h:109:19: note: expanded from macro 'isnan' __fp_type_select(x, __inline_isnanf, __inline_isnan, __inline_isnanl) ^ /usr/include/math.h:86:49: note: expanded from macro '__fp_type_select' #define __fp_type_select(x, f, d, ld) _Generic((x),=20 [...] The variables in question (Dsg and Dsc) are of type "const double". --Sig_/ZSAD9CXLaxRHx01iUtdTl3B Content-Type: application/pgp-signature; name=signature.asc Content-Disposition: attachment; filename=signature.asc -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.20 (FreeBSD) iQEcBAEBAgAGBQJR4HmNAAoJEOgBcD7A/5N8l/QH/35RmvVTNDC6a4uuInnSk27p eCprNuBQBFJvRVOAsNk22JmwNwH3MaKoSCbWQ8kaek0FMZiIL8CqZnujst+ONi5j 4rS5x1YTNlZrgl2vA/k0kdXbxXBb9gU7vbxGPGhwV+URo+zF5Fxbp/bq5+DIU+qQ 1sBGwv3gKFXsDqAUJ+Fhb/8u7V8NtyLwJLHlqVCpMFYMopeChw/936tATSeZZKkj iCU71toRC8ErBpVGQGHzhLde7GfI4RFhCJMPCFp/Iv/87Dia5DeGNz3xk35BzodG CF7sXwAowQJbv6ff4NLy/EfCxI6b0rZOrUQ7M8MvxKMh0MTt9bsomftaAwDGFB0= =/XUd -----END PGP SIGNATURE----- --Sig_/ZSAD9CXLaxRHx01iUtdTl3B-- From owner-freebsd-standards@FreeBSD.ORG Sat Jul 13 10:13:24 2013 Return-Path: Delivered-To: freebsd-standards@FreeBSD.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by hub.freebsd.org (Postfix) with ESMTP id 8A36E2BA; Sat, 13 Jul 2013 10:13:24 +0000 (UTC) (envelope-from theraven@FreeBSD.org) Received: from theravensnest.org (theraven.freebsd.your.org [216.14.102.27]) by mx1.freebsd.org (Postfix) with ESMTP id 4E65E1988; Sat, 13 Jul 2013 10:13:23 +0000 (UTC) Received: from [192.168.0.2] (cpc27-cmbg15-2-0-cust235.5-4.cable.virginmedia.com [86.27.188.236]) (authenticated bits=0) by theravensnest.org (8.14.5/8.14.5) with ESMTP id r6DAD3hL037645 (version=TLSv1/SSLv3 cipher=AES128-SHA bits=128 verify=NO); Sat, 13 Jul 2013 10:13:06 GMT (envelope-from theraven@FreeBSD.org) Content-Type: multipart/signed; boundary="Apple-Mail=_6B70CB09-FD89-4DA2-BEA2-1A534D35DC7A"; protocol="application/pgp-signature"; micalg=pgp-sha1 Mime-Version: 1.0 (Mac OS X Mail 6.3 \(1503\)) Subject: Re: CURRENT: CLANG 3.3 and -stad=c++11 and -stdlib=libc++: isnan()/isninf() oddity From: David Chisnall In-Reply-To: <20130712234749.5afa3c9b@thor.walstatt.dyndns.org> Date: Sat, 13 Jul 2013 11:12:59 +0100 Message-Id: <9B0A6D14-640E-4ADD-8E58-0B7867C7C674@FreeBSD.org> References: <20130710155809.0f589c22@thor.walstatt.dyndns.org> <20130710183315.725dfde0@thor.walstatt.dyndns.org> <20130710203200.5359fd18@thor.walstatt.dyndns.org> <51DDC04B.6040209@FreeBSD.org> <20957.49978.73666.392417@khavrinen.csail.mit.edu> <20130711130043.R920@besplex.bde.org> <20130711202908.L84170@besplex.bde.org> <20130712234749.5afa3c9b@thor.walstatt.dyndns.org> To: "O. Hartmann" X-Mailer: Apple Mail (2.1503) X-Mailman-Approved-At: Sat, 13 Jul 2013 12:05:54 +0000 Cc: Ed Schouten , Scot Hetzel , "freebsd-toolchain@FreeBSD.org" , Garrett Wollman , FreeBSD Current , Tijl Coosemans , "freebsd-standards@FreeBSD.org" X-BeenThere: freebsd-standards@freebsd.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: Standards compliance List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 13 Jul 2013 10:13:24 -0000 --Apple-Mail=_6B70CB09-FD89-4DA2-BEA2-1A534D35DC7A Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset=us-ascii On 12 Jul 2013, at 22:47, "O. Hartmann" = wrote: > Obviously not really fixed, but even worse: >=20 > if I use in C code (C99, using clang 3.3 on FreeBSD 10.0-CURRENT/amd64 > revision 253287) isnan(x) where x is a "const double", I receive now > the following error (which doesn't appear on previous versions): Thanks. This is now fixed, however the _Generic() usage that we had = there is also present in tgmath.h, and so this file will also need to be = fixed in the same way. I've now tested the macros with clang/c99, clang/c11, clang/c++98 and = clang/c++11, and gcc/c89 and they all seem to work for unqualified, = const, volatile, and const-volatile qualified types. I've added Ed to the cc: list, as he wrote this code in tgmath.h. David --Apple-Mail=_6B70CB09-FD89-4DA2-BEA2-1A534D35DC7A 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 iQIcBAEBAgAGBQJR4SgrAAoJEKx65DEEsqIdX+EQAMQpv3rkIYsk3U/45VwY9exf 4fjD7vuwWpsIeqtd9YL8Ru6bJ6dHsEk5P+6ffOHrzdzQfTyxDmU9jco9YcTPVkv8 OrMZ+Ld7ROuGQPX6QIPg63zGfRfREL+Lntabkbm0yGRZIr3Uf6EEham5DIMFp+OB MSqNq1AoMTc27zCACCimW3L6jbT3xrD6XLExR0hum4wAR2LAuflxodHESXmlo7n5 y+Oh+OuO/U60EkXoOoColAMEicLdvci+eoq35DbyReVO7DEf3o2eNd9PVmssVcZ+ 0RfC3KCzFqybbOyw3ZAbgoY+B9BDXgX3p75g4Qk9TKTTaAvwLHUFj0S+A0u8Rrb6 eNFw0ZGfLii/ao1RrWLnsHOiPKovf/uBRC3LDcpeOOJr8AyLOlpinBTaeGEnS4dS HnnJzHmKpOM0qJ6dSlwkQvA4AePRRzsTrm4viLuwsI8IionG+OPkNs7FuxORTW5I tKoFUwFKhzbU6p4XVuhEStowL4cqT4Ba9EbK07HWqMJ5xNBA0BPpTEKd4RVorXOm 54K0sIz3AB/TQk7I01iWmFOebaVMYorlBP6NMqvNWW9h35PRFyBrfxQVVYHmINrr F7hpH0oL5gJBCFVLUxhBlATJiM7FdbB0sHqXaFEqpdZjKUt9X8dysWJYHNXpoJOh GDnQq1VQEBMDqPjx9C53 =TyR3 -----END PGP SIGNATURE----- --Apple-Mail=_6B70CB09-FD89-4DA2-BEA2-1A534D35DC7A-- From owner-freebsd-standards@FreeBSD.ORG Sat Jul 13 12:26:10 2013 Return-Path: Delivered-To: freebsd-standards@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [8.8.178.115]) by hub.freebsd.org (Postfix) with ESMTP id 0909A388; Sat, 13 Jul 2013 12:26:10 +0000 (UTC) (envelope-from pasi.parviainen@iki.fi) Received: from sypressi.dnainternet.net (sypressi.dnainternet.net [83.102.40.135]) by mx1.freebsd.org (Postfix) with ESMTP id AC5C81DF2; Sat, 13 Jul 2013 12:26:09 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by sypressi.dnainternet.net (Postfix) with ESMTP id 5BFB72618E4; Sat, 13 Jul 2013 15:20:22 +0300 (EEST) X-Virus-Scanned: DNA Postiturva at dnainternet.net X-Spam-Flag: NO X-Spam-Score: -1 X-Spam-Level: X-Spam-Status: No, score=-1 tagged_above=-9999 required=6 tests=[ALL_TRUSTED=-1] autolearn=disabled Received: from sypressi.dnainternet.net ([83.102.40.135]) by localhost (sypressi.dnainternet.net [127.0.0.1]) (DNA Postiturva, port 10041) with ESMTP id vCYO0WFvf7n2; Sat, 13 Jul 2013 15:20:21 +0300 (EEST) Received: from luumupuu.dnainternet.net (luumupuu.dnainternet.net [83.102.40.213]) by sypressi.dnainternet.net (Postfix) with ESMTP id DC8C72618E9; Sat, 13 Jul 2013 15:20:21 +0300 (EEST) Received: from [192.168.0.2] (host-109-204-160-251.tp-fne.tampereenpuhelin.net [109.204.160.251]) (using TLSv1 with cipher ECDHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by luumupuu.dnainternet.net (Postfix) with ESMTPS id 79EDD5FA7F; Sat, 13 Jul 2013 15:20:12 +0300 (EEST) Message-ID: <51E145CC.8080900@iki.fi> Date: Sat, 13 Jul 2013 15:19:24 +0300 From: Pasi Parviainen User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:17.0) Gecko/20130620 Thunderbird/17.0.7 MIME-Version: 1.0 To: David Chisnall Subject: Re: CURRENT: CLANG 3.3 and -stad=c++11 and -stdlib=libc++: isnan()/isninf() oddity References: <20130710155809.0f589c22@thor.walstatt.dyndns.org> <20130710183315.725dfde0@thor.walstatt.dyndns.org> <20130710203200.5359fd18@thor.walstatt.dyndns.org> <51DDC04B.6040209@FreeBSD.org> <20957.49978.73666.392417@khavrinen.csail.mit.edu> <20130711130043.R920@besplex.bde.org> <20130711202908.L84170@besplex.bde.org> <20130712234749.5afa3c9b@thor.walstatt.dyndns.org> <9B0A6D14-640E-4ADD-8E58-0B7867C7C674@FreeBSD.org> In-Reply-To: <9B0A6D14-640E-4ADD-8E58-0B7867C7C674@FreeBSD.org> Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit Cc: Scot Hetzel , "freebsd-standards@FreeBSD.org" , "freebsd-toolchain@FreeBSD.org" , Garrett Wollman , FreeBSD Current , Tijl Coosemans , "O. Hartmann" X-BeenThere: freebsd-standards@freebsd.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: Standards compliance List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 13 Jul 2013 12:26:10 -0000 On 13.7.2013 13:12, David Chisnall wrote: > On 12 Jul 2013, at 22:47, "O. Hartmann" wrote: > >> Obviously not really fixed, but even worse: >> >> if I use in C code (C99, using clang 3.3 on FreeBSD 10.0-CURRENT/amd64 >> revision 253287) isnan(x) where x is a "const double", I receive now >> the following error (which doesn't appear on previous versions): > > Thanks. This is now fixed, however the _Generic() usage that we had there is also present in tgmath.h, and so this file will also need to be fixed in the same way. > > I've now tested the macros with clang/c99, clang/c11, clang/c++98 and clang/c++11, and gcc/c89 and they all seem to work for unqualified, const, volatile, and const-volatile qualified types. > > I've added Ed to the cc: list, as he wrote this code in tgmath.h. > > David > Instead of listing all possible type qualifier combinations (like in r253319), how about using a comma operator to strip away type qualifiers? Since only the result type of the expression matters and it isn't evaluated at all. like: #define __fp_type_select(x, f, d, ld) _Generic((0,(x)), Pasi