Status of __STDC_IEC_559__ with modern C compilers - c

C99 added a macro __STDC_IEC_559__ which can be used to test if a compiler and standard library conform to the ISO/IEC/IEEE 60559 (or IEEE 754) standard.
According to the answers for this question
how-to-check-that-ieee-754-single-precision-32-bit-floating-point-representation most C compilers don't set the preprocessor macro __STDC_IEC_559__.
According to GCC's documentation it does not define __STDC_IEC_559__.
I tested this with GCC 4.9.2 and Clang 3.6.0 both using with glibc 2.21 using the following code.
//test.c
//#include <features.h>
int main(void) {
#if defined ( __STDC_IEC_559__ )
//#if defined ( __GCC_IEC_559__ )
return 1;
#else
return 0;
#endif
}
and then
echo $?
This shows that with this code __STDC_IEC_559__ is defined with GCC but not with Clang. I then did gcc -E and it showed that the file stdc-predef.h is included. This file defines __STDC_IEC_559__.
/* glibc's intent is to support the IEC 559 math functionality, real
and complex. If the GCC (4.9 and later) predefined macros
specifying compiler intent are available, use them to determine
whether the overall intent is to support these features; otherwise,
presume an older compiler has intent to support these features and
define these macros by default. */
#ifdef __GCC_IEC_559
# if __GCC_IEC_559 > 0
# define __STDC_IEC_559__ 1
# endif
#else
# define __STDC_IEC_559__ 1
#endif
This confirms that it's glibc that defines this macro and not GCC.
However, when I include features.h (or stdio.h) this file is included by Clang as well and that __STDC_IEC_559__ is defined.
So __STDC_IEC_559__ is defined by both GCC and Clang (with a glibc header file) which seems to disagree with the answer to the first question I linked to.
I then tested musl (e.g. musl-gcc -test.c) which is a different standard library than glibc. This showed that __STDC_IEC_559__ is not defined with musl.
As I understand it the standard C library does not define the basic floating point algebra. For example the standard C library does not define the result of 1.0/-0.0. This is defined by the compiler.
My questions are (ranked in order of importance to me):
Why is __STDC_IEC_559__ defined by glibc and not by the compiler?
If I made my own standard library and I wanted to define __STDC_IEC_559__ I would need to know that the compiler already conforms to IEEE 754 for operations not defined in my standard library (e.g 1.0/-0.0). Is there documentations for this or a macro to test for this?
Wikipedia states that "users should be aware that this macro (__STDC_IEC_559__) is sometimes defined while it shouldn't be". Is this statement still accurate?

I believe __STDC_IEC_559__ relies on some library features and can't be defined solely by the compiler. See this post for some information. This is not uncommon for C -- the compiler and the C library must sometimes cooperate in order to implement the entire standard.
What you're asking depends on the compiler. I think you would have to have special knowledge of the compiler in order to decide this. In the specific case of GCC, it defines a macro to tell you. Search this node of the manual for __GCC_IEC_559.
Well... I don't know the answer to this one :-). The original post seems to indicate that, yes, GCC might define __GCC_IEC_559 if it intends to implement IEEE 754, even if it does not actually do so.

Related

Cygwin doesn't define __STDC_IEC_559__

I was curious if this is intentional. I found that traditionally __STDC_IEC_559__ is defined in glibc and then used by gcc. Cygwin doesn't use glibc however, and I was wondering if __STDC_IEC_559__ isn't defined by newlib for whatever reason or if it is merely a problem on my end.
I understand that all compilers/libraries do not define __STDC_IEC_559__ as they are not all compliant with the standard, I am just trying to figure out why the libraries used by cygwin specifically are not.

__STDC_LIB_EXT1__ availability in gcc and clang

Since a quick Google search did not find anything, I will try to ask here (since many people involved in gcc/clang hang around here) - What is the status of __STDC_LIB_EXT1__ in gcc/clang? We are developing a cross platform applicataion and I wanted to use some of the safe bounds checking functions from <stdio.h> (which by miracle are available on Visual Studio 2017), but could not compile the code with Xcode 9.2. I assumed maybe the clang version Xcode uses is outdated, but gcc 6.3.0 on Ubuntu behaves the same. I am trying to use tmpnam_s with the following sample:
#if defined(__STDC_LIB_EXT1__)
#define __STDC_WANT_LIB_EXT1__ 1
#include <stdio.h>
#else
#error "__STDC_LIB_EXT1__ not defined"
#endif
int main(int argc, char** argv)
{
char t[L_tmpnam_s];
tmpnam_s(t, L_tmpnam_s);
return 0;
}
But the compilation fails with the macro not being defined:
gcc -std=c11 test.c
test.c:5:2: error: #error "__STDC_LIB_EXT1__ not defined"
#error "__STDC_LIB_EXT1__ not defined"
^~~~~
Am I doing something wrong or this function set is simply poorly supported?
The whole set of 'safe' functions with the _s suffixes is poorly supported. Microsoft wrote a set of functions with the _s suffixes and submitted that to the C standard committee to be standardized. The committee made some changes (arguably out of necessity), and created a technical report, TR 24731-1. A mildly modified version of the TR was included as optional Annex K (normative) in the C11 standard, ISO/IEC 9899:2011.
You can find many sordid details in the answers to Do you use the TR-24731 "safer" functions?, especially in the notes in my answer to that question, and especially the link to the Standard C committee document N1967 Field Experience with Annex K — Bounds Checking Interfaces.
I don't know what the current status of the N1967 proposal is, but that it was suggested is telling. N1967 also contains links to libraries that support Annex K / TR-24731-1 — the list is limited.
Note that Microsoft does not implement the library specified by the C11 standard. It implements an approximation to the standard, but there are crucial differences. This would matter more if any other system had implemented the standard — but the functions have not been implemented in any widely accepted form (so, for example, the GNU C Library does not and will not support them).

getchar_unlocked() implicit declaration in C99

Using getchar_unlocked and compiling with --std=c99 flag gives warningas follows-
warning: implicit declaration of function ‘getchar_unlocked’ [-Wimplicit-function-declaration]
Does not give any warning if compiled without flag.Is there any way to work around with it ?
Starting from C99 you must have a visible function prototype before calling a function. While the earlier C standard would just stupidly assume that any function unknown to the compiler has the format int func (params), which in turn would cause severe bugs most of the time.
Properly declare a prototype for getchar_unlocked and the bug will go away.
Note that there is no such function present in any standard library. It seems you might have to include some non-standard library for the compiler to find the function.
_unlocked versions of get... functions are POSIX extensions. They are not part of the standard functions of C99. The full list of get... functions is given in 7.19.1.5: getwc, getwchar, getc, getchar, and gets (deprecated).
When the function is not on this list, C99-compliant compiler must warn you that your program may not compile with other C99-compliant compilers.
Dialect selection options like -ansi and -std=c99 cause the compiler to define certain macros (in addition to altering the accepted dialect).
Library header files react to those macros.
Precisely how they react is quite system-dependent (the compiler doesn't provide a C library), but a common behavior you can broadly expect is that if you use one of these flags alone (without any other "feature selection macro"), it has the effect of hiding the declarations of functions, macros and other global symbols which are not in the specified ISO C dialect.
ISO C knows nothing about getchar_unlocked. The presence of such a declaration in <stdio.h> (normally an ISO C header) is a POSIX extension, which is basically nonconforming, since getchar_unlocked is an identifier that strictly conforming C programs can use, even if they include <stdio.h>. When you use -ansi or -std=c99, the <stdio.h> header listens up and whips itself into ISO-C-conforming shape, hiding such extensions.
On well-behaved POSIX systems, you can request that you want an ISO C dialect and that you want certain rudimentary 1990-ish POSIX features to be visible in header files, for instance like this:
gcc -std=c99 -D_POSIX_SOURCE ...
^^^^^ "feature selection macro"
There is a whole science to these feature selection macros, too broad for this question and answer; some forms of them have values, like -D_XOPEN_SOURCE=500. _POSIX_SOURCE doesn't need an argument; it is just defined or not, but _POSIX_C_SOURCE is numeric.
I just checked glibc and Cygwin: on both, _POSIX_SOURCE is enough to reveal the getchar_unlocked declaration. It is quite old, dating back to POSIX.1 1996.
Beware: on some systems, multiple feature selection macros don't play along reasonably; they give you a set intersection rather than union, so that -D_POSIX_SOURCE and -D_BSD_SOURCE together end up meaning "Declare to me only those handful of functions that are specific to classic BSD that have been standardized in POSIX too", which means that next to nothing is declared.
getchar_unlocked is not a C standard function.
Compiling it forcing c99 standard does not support it natively.

GCC options for strict C90 code?

I am trying to find what is the combination of gcc flags to use when testing strict C90 conformance. According to previous post: GCC options for strictest C code?, I should only need a --std=c90.
However here is what I tried:
$ cat t.c
#include <stdint.h> /* added in C99 */
int main()
{
uint64_t t;
return 0;
}
$ gcc -std=c90 -ansi -pedantic t.c
The above does work well (no warnings/errors produced).
Does anyone knows of:
gcc flags to have strict ISO/IEC 9899:1990 conformance
A different compiler (tcc, clang...) with different set of flags ?
EDIT:
Sorry for my wording, yes I would really like to mimic a strictly conforming C90 compiler, in other word it should fail if the code tries to use any feature added later (C99 comes to mind). So pthread include header ought to emit a warning when compiled in what GNU/GCC calls C90 mode (just like stdint.h header should produce a warning without C99). -pedantic nicely warns me about usage of long long, I do not see why it should not warn me about uint64_t.
I used the terminology of ISO/IEC 9899:1990 as quoted from:
http://en.wikipedia.org/wiki/C_(programming_language)#ANSI_C_and_ISO_C
In 1990, the ANSI C standard (with formatting changes) was adopted by
the International Organization for Standardization (ISO) as ISO/IEC
9899:1990, which is sometimes called C90. Therefore, the terms "C89"
and "C90" refer to the same programming language.
EDIT2:
GCC documentation are actually quite clear:
Some features that are part of the C99 standard are accepted as
extensions in C90 mode, and some features that are part of the C11
standard are accepted as extensions in C90 and C99 modes.
So my question is rephrased into:
Is there a compiler + standard include header on a linux system which strictly conforms to C90 ?
C90 compliance doesn't mean that the compiler can't offer other headers that aren't mentioned in the C90 standard. (sys/socket.h, for instance.) If you want to disallow these for some strange reason, you can pass the -I option to add an extra include path, and in that path put versions of all the C99-only headers which are simply #error Don't include me.
Keep in mind here that GCC itself is a conforming freestanding implementation of the C standard specified; such an implementation only supplies a small subset of the standard header files, and practically none of the actual functionality of the C standard library, instead relying on another party -- glibc on Linux systems, for instance -- to supply the C standard library's functionality.
What you seek is something that not only warns you when you are using a C99/C11/GNU language feature that is not in C90, but when you use a library function that is not defined by C90 itself. Sadly, the compiler alone cannot do this for the reason stated above -- it is aloof to what libc it is used with. On glibc systems, the C standard library will pick up on the macros defined by -std=c90 or -ansi:
The macro __STRICT_ANSI__ is predefined when the -ansi option is used. Some header files may notice this macro and refrain from declaring certain functions or defining certain macros that the ISO standard doesn't call for; this is to avoid interfering with any programs that might use these names for other things.
and give you some help by turning off gratuitous extensions:
If you compile your programs using ‘gcc -ansi’, you get only the ISO C library features, unless you explicitly request additional features by defining one or more of the feature macros.
However, this only covers extensions and POSIX-but-not-ISO C functions; it will not save you if a function's behavior is specified differently in ISO C and POSIX.1!

__func__ or __FUNCTION__ or manual const char* id?

I'm wondering how widely are __func__ (part of C99, but I'm compiling as C89) and __FUNCTION__ supported.
I have an old code base that is mostly using manual const char* id; variables that are then passed to various (mostly logging) functions. I would like to get rid of this and move the function name into a macro.
The predefined identifier __func__ was added to the 1999 ISO C standard; the older 1990 C standard doesn't have it.
Support for __func__ in pre-C99 compilers will depend on which compiler you're using.
Modern versions of gcc support __func__ even in C90 mode (-ansi or -std=c89).
Before __func__ was added to the standard, gcc implemented its own equivalent extension, but with the name __FUNCTION__. (gcc also supports __PRETTY_FUNCTION__, which is identical to __func__ and __FUNCTION__ for C, but provides more information in C++.)
The gcc manual gives some advice:
__FUNCTION__ is another name for __func__. Older versions of GCC recognize only this name. However, it is not standardized. For maximum
portability, we recommend you use __func__, but provide a fallback
definition with the preprocessor:
#if __STDC_VERSION__ < 199901L
# if __GNUC__ >= 2
# define __func__ __FUNCTION__
# else
# define __func__ "<unknown>"
# endif
#endif
which implies that gcc added support for __FUNCTION__ in version 2. gcc 2.0 was released in 1992; you're very unlikely to be using a version of gcc that doesn't support at least __FUNCTION__, if not __func__.
Note that since __func__ and __FUNCTION__ are predefined identifiers, not macros, you only need the #define once, not in each function. On the other hand, you can't use #ifdef __func__ or #ifdef __FUNCTION__ to detect the level of support.
As for other compilers, a quick experiment indicates that Microsoft Visual C++ 2010 Express supports __FUNCTION__, but not __func__ or __PRETTY_FUNCTION__, when compiling C code. The above block of code from the gcc manual compiles under MSVC, but it results in __func__ being defined as "<unknown>". It shouldn't be too difficult to adjust it to recognize that MSVC supports __FUNCTION__. (I don't know whether older versions do so.) You can probably use the predefined macro _MSC_VER for this. Microsoft's documentation says that support for __FUNCTION__ goes back at least to the 2003 release, which sets _MSC_VER to 1300, so changing the second line to
# if __GNUC >= 2 || _MSC_VER >= 1300
is a good start. (It may well have been supported in earlier releases.)
For compilers other than gcc and MSVC, you'll have to consult their respective documentation -- but in any case, the block of code recommended in the gcc manual should work for any compiler, at worst falling back to "<unknown>".
The boost current_function.hpp header contains several #defines for the ways to get the current function on different platforms.
That's not to say that those platforms don't support other ways of getting the current function, but the choices made for boost are likely to represent nice (if not the nicest) ways of getting the information on those platforms.
An adaptation of this header for your code (and for C) could well be what you need.
I believe it is regardless what C standard is used (if C89 or C99). The more important factor is the compiler being used since it is the one that will implement __func__. The latest GCC compilers will add __func__ no matter the standard being used. I think. :)

Resources