From owner-freebsd-current@FreeBSD.ORG Thu Jul 11 13:02:25 2013 Return-Path: Delivered-To: freebsd-current@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 X-Mailman-Approved-At: Thu, 11 Jul 2013 13:34:53 +0000 Cc: Garrett Wollman , FreeBSD CURRENT , freebsd-standards@freebsd.org, Bruce Evans , freebsd-toolchain@freebsd.org X-BeenThere: freebsd-current@freebsd.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: Discussions about the use of FreeBSD-current 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