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: >>> <<On Wed, 10 Jul 2013 22:12:59 +0200, Tijl Coosemans <tijl_at_freebsd.org> 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 <math.h> > > 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. BruceReceived on Thu Jul 11 2013 - 11:02:25 UTC
This archive was generated by hypermail 2.4.0 : Wed May 19 2021 - 11:40:39 UTC